📄 options.c
字号:
/* * options.c - handles option processing for PPP. * * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The name "Carnegie Mellon University" must not be used to * endorse or promote products derived from this software without * prior written permission. For permission or any legal * details, please contact * Office of Technology Transfer * Carnegie Mellon University * 5000 Forbes Avenue * Pittsburgh, PA 15213-3890 * (412) 268-4387, fax: (412) 268-7395 * tech-transfer@andrew.cmu.edu * * 4. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by Computing Services * at Carnegie Mellon University (http://www.cmu.edu/computing/)." * * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */#define RCSID "$Id: options.c,v 1.100 2006/06/18 11:26:00 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>/* * There have been 3 or 4 different names for this in libpcap CVS, but * this seems to be what they have settled on... * For older versions of libpcap, use DLT_PPP - but that means * we lose the inbound and outbound qualifiers. */#ifndef DLT_PPP_PPPD#ifdef DLT_PPP_WITHDIRECTION#define DLT_PPP_PPPD DLT_PPP_WITHDIRECTION#else#define DLT_PPP_PPPD DLT_PPP#endif#endif#endif /* PPP_FILTER */#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. */int 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 */int child_wait = 5; /* # seconds to wait for children at exit */#ifdef MAXOCTETSunsigned int maxoctets = 0; /* default - no limit */int maxoctets_dir = 0; /* default - sum of traffic */int maxoctets_timeout = 1; /* default 1 second */ #endifextern 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 */#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 **));#endif#ifdef MAXOCTETSstatic int setmodir __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, &holdoff_specified }, { "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 }, { "child-timeout", o_int, &child_wait, "Number of seconds to wait for child processes at exit", OPT_PRIO },#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 { "pass-filter", o_special, setpassfilter, "set filter for packets to pass", OPT_PRIO }, { "active-filter", o_special, setactivefilter, "set filter for active pkts", OPT_PRIO },#endif#ifdef MAXOCTETS { "maxoctets", o_int, &maxoctets, "Set connection traffic limit", OPT_PRIO | OPT_LLIMIT | OPT_NOINCR | OPT_ZEROINF }, { "mo", o_int, &maxoctets, "Set connection traffic limit", OPT_ALIAS | OPT_PRIO | OPT_LLIMIT | OPT_NOINCR | OPT_ZEROINF }, { "mo-direction", o_special, setmodir, "Set direction for limit traffic (sum,in,out,max)" }, { "mo-timeout", o_int, &maxoctets_timeout, "Check for traffic limit every N seconds", OPT_PRIO | OPT_LLIMIT | 1 },#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; uid_t euid; char *argv[MAXARGS]; char args[MAXARGS][MAXWORDLEN]; char cmd[MAXWORDLEN]; euid = geteuid(); if (check_prot && seteuid(getuid()) == -1) { option_error("unable to drop privileges to open %s: %m", filename); return 0; } f = fopen(filename, "r"); err = errno; if (check_prot && seteuid(euid) == -1) fatal("unable to regain privileges"); 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 ((p = strstr(dev, "/dev/")) != NULL) dev = p + 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -