options.c
来自「经典的ppp程序」· C语言 代码 · 共 1,513 行 · 第 1/3 页
C
1,513 行
/* * options.c - handles option processing for PPP. * * Copyright (c) 1989 Carnegie Mellon University. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by Carnegie Mellon University. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */#define RCSID "$Id: options.c,v 1.80 2001/03/12 22:56:12 paulus Exp $"#include <ctype.h>#include <stdio.h>#include <errno.h>#include <unistd.h>#include <fcntl.h>#include <stdlib.h>#include <syslog.h>#include <string.h>#include <pwd.h>#ifdef PLUGIN#include <dlfcn.h>#endif#ifdef PPP_FILTER#include <pcap.h>#include <pcap-int.h> /* XXX: To get struct pcap */#endif#include "pppd.h"#include "pathnames.h"#if defined(ultrix) || defined(NeXT)char *strdup __P((char *));#endifstatic const char rcsid[] = RCSID;struct option_value { struct option_value *next; const char *source; char value[1];};/* * Option variables and default values. */#ifdef PPP_FILTERint dflag = 0; /* Tell libpcap we want debugging */#endifint debug = 0; /* Debug flag */int kdebugflag = 0; /* Tell kernel to print debug messages */int default_device = 1; /* Using /dev/tty or equivalent */char devnam[MAXPATHLEN]; /* Device name */bool nodetach = 0; /* Don't detach from controlling tty */bool updetach = 0; /* Detach once link is up */int maxconnect = 0; /* Maximum connect time */char user[MAXNAMELEN]; /* Username for PAP */char passwd[MAXSECRETLEN]; /* Password for PAP */bool persist = 0; /* Reopen link after it goes down */char our_name[MAXNAMELEN]; /* Our name for authentication purposes */bool demand = 0; /* do dial-on-demand */char *ipparam = NULL; /* Extra parameter for ip up/down scripts */int idle_time_limit = 0; /* Disconnect if idle for this many seconds */int holdoff = 30; /* # seconds to pause before reconnecting */bool holdoff_specified; /* true if a holdoff value has been given */int log_to_fd = 1; /* send log messages to this fd too */bool log_default = 1; /* log_to_fd is default (stdout) */int maxfail = 10; /* max # of unsuccessful connection attempts */char linkname[MAXPATHLEN]; /* logical name for link */bool tune_kernel; /* may alter kernel settings */int connect_delay = 1000; /* wait this many ms after connect script */int req_unit = -1; /* requested interface unit */bool multilink = 0; /* Enable multilink operation */char *bundle_name = NULL; /* bundle name for multilink */bool dump_options; /* print out option values */bool dryrun; /* print out option values and exit */char *domain; /* domain name set by domain option */extern option_t auth_options[];extern struct stat devstat;#ifdef PPP_FILTERstruct bpf_program pass_filter;/* Filter program for packets to pass */struct bpf_program active_filter; /* Filter program for link-active pkts */pcap_t pc; /* Fake struct pcap so we can compile expr */#endifchar *current_option; /* the name of the option being parsed */int privileged_option; /* set iff the current option came from root */char *option_source; /* string saying where the option came from */int option_priority = OPRIO_CFGFILE; /* priority of the current options */bool devnam_fixed; /* can no longer change device name */static int logfile_fd = -1; /* fd opened for log file */static char logfile_name[MAXPATHLEN]; /* name of log file *//* * Prototypes */static int setdomain __P((char **));static int readfile __P((char **));static int callfile __P((char **));static int showversion __P((char **));static int showhelp __P((char **));static void usage __P((void));static int setlogfile __P((char **));#ifdef PLUGINstatic int loadplugin __P((char **));#endif#ifdef PPP_FILTERstatic int setpassfilter __P((char **));static int setactivefilter __P((char **));#endifstatic option_t *find_option __P((const char *name));static int process_option __P((option_t *, char *, char **));static int n_arguments __P((option_t *));static int number_option __P((char *, u_int32_t *, int));/* * Structure to store extra lists of options. */struct option_list { option_t *options; struct option_list *next;};static struct option_list *extra_options = NULL;/* * Valid arguments. */option_t general_options[] = { { "debug", o_int, &debug, "Increase debugging level", OPT_INC | OPT_NOARG | 1 }, { "-d", o_int, &debug, "Increase debugging level", OPT_ALIAS | OPT_INC | OPT_NOARG | 1 }, { "kdebug", o_int, &kdebugflag, "Set kernel driver debug level", OPT_PRIO }, { "nodetach", o_bool, &nodetach, "Don't detach from controlling tty", OPT_PRIO | 1 }, { "-detach", o_bool, &nodetach, "Don't detach from controlling tty", OPT_ALIAS | OPT_PRIOSUB | 1 }, { "updetach", o_bool, &updetach, "Detach from controlling tty once link is up", OPT_PRIOSUB | OPT_A2CLR | 1, &nodetach }, { "holdoff", o_int, &holdoff, "Set time in seconds before retrying connection", OPT_PRIO }, { "idle", o_int, &idle_time_limit, "Set time in seconds before disconnecting idle link", OPT_PRIO }, { "maxconnect", o_int, &maxconnect, "Set connection time limit", OPT_PRIO | OPT_LLIMIT | OPT_NOINCR | OPT_ZEROINF }, { "domain", o_special, (void *)setdomain, "Add given domain name to hostname", OPT_PRIO | OPT_PRIV | OPT_A2STRVAL, &domain }, { "file", o_special, (void *)readfile, "Take options from a file", OPT_NOPRINT }, { "call", o_special, (void *)callfile, "Take options from a privileged file", OPT_NOPRINT }, { "persist", o_bool, &persist, "Keep on reopening connection after close", OPT_PRIO | 1 }, { "nopersist", o_bool, &persist, "Turn off persist option", OPT_PRIOSUB }, { "demand", o_bool, &demand, "Dial on demand", OPT_INITONLY | 1, &persist }, { "--version", o_special_noarg, (void *)showversion, "Show version number" }, { "--help", o_special_noarg, (void *)showhelp, "Show brief listing of options" }, { "-h", o_special_noarg, (void *)showhelp, "Show brief listing of options", OPT_ALIAS }, { "logfile", o_special, (void *)setlogfile, "Append log messages to this file", OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, &logfile_name }, { "logfd", o_int, &log_to_fd, "Send log messages to this file descriptor", OPT_PRIOSUB | OPT_A2CLR, &log_default }, { "nolog", o_int, &log_to_fd, "Don't send log messages to any file", OPT_PRIOSUB | OPT_NOARG | OPT_VAL(-1) }, { "nologfd", o_int, &log_to_fd, "Don't send log messages to any file descriptor", OPT_PRIOSUB | OPT_ALIAS | OPT_NOARG | OPT_VAL(-1) }, { "linkname", o_string, linkname, "Set logical name for link", OPT_PRIO | OPT_PRIV | OPT_STATIC, NULL, MAXPATHLEN }, { "maxfail", o_int, &maxfail, "Maximum number of unsuccessful connection attempts to allow", OPT_PRIO }, { "ktune", o_bool, &tune_kernel, "Alter kernel settings as necessary", OPT_PRIO | 1 }, { "noktune", o_bool, &tune_kernel, "Don't alter kernel settings", OPT_PRIOSUB }, { "connect-delay", o_int, &connect_delay, "Maximum time (in ms) to wait after connect script finishes", OPT_PRIO }, { "unit", o_int, &req_unit, "PPP interface unit number to use if possible", OPT_PRIO | OPT_LLIMIT, 0, 0 }, { "dump", o_bool, &dump_options, "Print out option values after parsing all options", 1 }, { "dryrun", o_bool, &dryrun, "Stop after parsing, printing, and checking options", 1 },#ifdef HAVE_MULTILINK { "multilink", o_bool, &multilink, "Enable multilink operation", OPT_PRIO | 1 }, { "mp", o_bool, &multilink, "Enable multilink operation", OPT_PRIOSUB | OPT_ALIAS | 1 }, { "nomultilink", o_bool, &multilink, "Disable multilink operation", OPT_PRIOSUB | 0 }, { "nomp", o_bool, &multilink, "Disable multilink operation", OPT_PRIOSUB | OPT_ALIAS | 0 }, { "bundle", o_string, &bundle_name, "Bundle name for multilink", OPT_PRIO },#endif /* HAVE_MULTILINK */#ifdef PLUGIN { "plugin", o_special, (void *)loadplugin, "Load a plug-in module into pppd", OPT_PRIV | OPT_A2LIST },#endif#ifdef PPP_FILTER { "pdebug", o_int, &dflag, "libpcap debugging", OPT_PRIO }, { "pass-filter", 1, setpassfilter, "set filter for packets to pass", OPT_PRIO }, { "active-filter", 1, setactivefilter, "set filter for active pkts", OPT_PRIO },#endif { NULL }};#ifndef IMPLEMENTATION#define IMPLEMENTATION ""#endifstatic char *usage_string = "\pppd version %s\n\Usage: %s [ options ], where options are:\n\ <device> Communicate over the named device\n\ <speed> Set the baud rate to <speed>\n\ <loc>:<rem> Set the local and/or remote interface IP\n\ addresses. Either one may be omitted.\n\ asyncmap <n> Set the desired async map to hex <n>\n\ auth Require authentication from peer\n\ connect <p> Invoke shell command <p> to set up the serial line\n\ crtscts Use hardware RTS/CTS flow control\n\ defaultroute Add default route through interface\n\ file <f> Take options from file <f>\n\ modem Use modem control lines\n\ mru <n> Set MRU value to <n> for negotiation\n\See pppd(8) for more options.\n\";/* * parse_args - parse a string of arguments from the command line. */intparse_args(argc, argv) int argc; char **argv;{ char *arg; option_t *opt; int n; privileged_option = privileged; option_source = "command line"; option_priority = OPRIO_CMDLINE; while (argc > 0) { arg = *argv++; --argc; opt = find_option(arg); if (opt == NULL) { option_error("unrecognized option '%s'", arg); usage(); return 0; } n = n_arguments(opt); if (argc < n) { option_error("too few parameters for option %s", arg); return 0; } if (!process_option(opt, arg, argv)) return 0; argc -= n; argv += n; } return 1;}/* * options_from_file - Read a string of options from a file, * and interpret them. */intoptions_from_file(filename, must_exist, check_prot, priv) char *filename; int must_exist; int check_prot; int priv;{ FILE *f; int i, newline, ret, err; option_t *opt; int oldpriv, n; char *oldsource; char *argv[MAXARGS]; char args[MAXARGS][MAXWORDLEN]; char cmd[MAXWORDLEN]; if (check_prot) seteuid(getuid()); f = fopen(filename, "r"); err = errno; if (check_prot) seteuid(0); if (f == NULL) { errno = err; if (!must_exist) { if (err != ENOENT && err != ENOTDIR) warn("Warning: can't open options file %s: %m", filename); return 1; } option_error("Can't open options file %s: %m", filename); return 0; } oldpriv = privileged_option; privileged_option = priv; oldsource = option_source; option_source = strdup(filename); if (option_source == NULL) option_source = "file"; ret = 0; while (getword(f, cmd, &newline, filename)) { opt = find_option(cmd); if (opt == NULL) { option_error("In file %s: unrecognized option '%s'", filename, cmd); goto err; } n = n_arguments(opt); for (i = 0; i < n; ++i) { if (!getword(f, args[i], &newline, filename)) { option_error( "In file %s: too few parameters for option '%s'", filename, cmd); goto err; } argv[i] = args[i]; } if (!process_option(opt, cmd, argv)) goto err; } ret = 1;err: fclose(f); privileged_option = oldpriv; option_source = oldsource; return ret;}/* * options_from_user - See if the use has a ~/.ppprc file, * and if so, interpret options from it. */intoptions_from_user(){ char *user, *path, *file; int ret; struct passwd *pw; size_t pl; pw = getpwuid(getuid()); if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == 0) return 1; file = _PATH_USEROPT; pl = strlen(user) + strlen(file) + 2; path = malloc(pl); if (path == NULL) novm("init file name"); slprintf(path, pl, "%s/%s", user, file); option_priority = OPRIO_CFGFILE; ret = options_from_file(path, 0, 1, privileged); free(path); return ret;}/* * options_for_tty - See if an options file exists for the serial * device, and if so, interpret options from it. * We only allow the per-tty options file to override anything from * the command line if it is something that the user can't override * once it has been set by root; this is done by giving configuration * files a lower priority than the command line. */intoptions_for_tty(){ char *dev, *path, *p; int ret; size_t pl; dev = devnam; if (strncmp(dev, "/dev/", 5) == 0) dev += 5; if (dev[0] == 0 || strcmp(dev, "tty") == 0) return 1; /* don't look for /etc/ppp/options.tty */ pl = strlen(_PATH_TTYOPT) + strlen(dev) + 1; path = malloc(pl); if (path == NULL) novm("tty init file name"); slprintf(path, pl, "%s%s", _PATH_TTYOPT, dev); /* Turn slashes into dots, for Solaris case (e.g. /dev/term/a) */ for (p = path + strlen(_PATH_TTYOPT); *p != 0; ++p) if (*p == '/') *p = '.'; option_priority = OPRIO_CFGFILE; ret = options_from_file(path, 0, 0, 1); free(path); return ret;}/* * options_from_list - process a string of options in a wordlist. */intoptions_from_list(w, priv) struct wordlist *w; int priv;{ char *argv[MAXARGS]; option_t *opt; int i, n, ret = 0; struct wordlist *w0; privileged_option = priv; option_source = "secrets file"; option_priority = OPRIO_SECFILE; while (w != NULL) { opt = find_option(w->word); if (opt == NULL) { option_error("In secrets file: unrecognized option '%s'", w->word); goto err; } n = n_arguments(opt); w0 = w; for (i = 0; i < n; ++i) { w = w->next; if (w == NULL) { option_error( "In secrets file: too few parameters for option '%s'", w0->word); goto err; } argv[i] = w->word; } if (!process_option(opt, w0->word, argv)) goto err; w = w->next; } ret = 1;err: return ret;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?