123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797 |
- /*
- * 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.102 2008/06/15 06:53:06 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 *));
- #endif
- static 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 */
- bool master_detach; /* Detach when we're (only) multilink master */
- 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 */
- struct userenv *userenv_list; /* user environment variables */
- #ifdef MAXOCTETS
- unsigned int maxoctets = 0; /* default - no limit */
- int maxoctets_dir = 0; /* default - sum of traffic */
- int maxoctets_timeout = 1; /* default 1 second */
- #endif
- extern option_t auth_options[];
- extern struct stat devstat;
- #ifdef PPP_FILTER
- struct bpf_program pass_filter;/* Filter program for packets to pass */
- struct bpf_program active_filter; /* Filter program for link-active pkts */
- #endif
- static option_t *curopt; /* pointer to option being processed */
- char *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 PLUGIN
- static int loadplugin __P((char **));
- #endif
- #ifdef PPP_FILTER
- static int setpassfilter __P((char **));
- static int setactivefilter __P((char **));
- #endif
- #ifdef MAXOCTETS
- static int setmodir __P((char **));
- #endif
- static int user_setenv __P((char **));
- static void user_setprint __P((option_t *, printer_func, void *));
- static int user_unsetenv __P((char **));
- static void user_unsetprint __P((option_t *, printer_func, void *));
- static 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 },
- { "master_detach", o_bool, &master_detach,
- "Detach when we're multilink master but have no link", 1 },
- { "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 },
- { "set", o_special, (void *)user_setenv,
- "Set user environment variable",
- OPT_A2PRINTER | OPT_NOPRINT, (void *)user_setprint },
- { "unset", o_special, (void *)user_unsetenv,
- "Unset user environment variable",
- OPT_A2PRINTER | OPT_NOPRINT, (void *)user_unsetprint },
- #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 ""
- #endif
- static 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.
- */
- int
- parse_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.
- */
- int
- options_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.
- */
- int
- options_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.
- */
- int
- options_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.
- */
- int
- options_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;
- }
- /*
- * match_option - see if this option matches an option_t structure.
- */
- static int
- match_option(name, opt, dowild)
- char *name;
- option_t *opt;
- int dowild;
- {
- int (*match) __P((char *, char **, int));
- if (dowild != (opt->type == o_wild))
- return 0;
- if (!dowild)
- return strcmp(name, opt->name) == 0;
- match = (int (*) __P((char *, char **, int))) opt->addr;
- return (*match)(name, NULL, 0);
- }
- /*
- * find_option - scan the option lists for the various protocols
- * looking for an entry with the given name.
- * This could be optimized by using a hash table.
- */
- static option_t *
- find_option(name)
- const char *name;
- {
- option_t *opt;
- struct option_list *list;
- int i, dowild;
- for (dowild = 0; dowild <= 1; ++dowild) {
- for (opt = general_options; opt->name != NULL; ++opt)
- if (match_option(name, opt, dowild))
- return opt;
- for (opt = auth_options; opt->name != NULL; ++opt)
- if (match_option(name, opt, dowild))
- return opt;
- for (list = extra_options; list != NULL; list = list->next)
- for (opt = list->options; opt->name != NULL; ++opt)
- if (match_option(name, opt, dowild))
- return opt;
- for (opt = the_channel->options; opt->name != NULL; ++opt)
- if (match_option(name, opt, dowild))
- return opt;
- for (i = 0; protocols[i] != NULL; ++i)
- if ((opt = protocols[i]->options) != NULL)
- for (; opt->name != NULL; ++opt)
- if (match_option(name, opt, dowild))
- return opt;
- }
- return NULL;
- }
- /*
- * process_option - process one new-style option.
- */
- static int
- process_option(opt, cmd, argv)
- option_t *opt;
- char *cmd;
- char **argv;
- {
- u_int32_t v;
- int iv, a;
- char *sv;
- int (*parser) __P((char **));
- int (*wildp) __P((char *, char **, int));
- char *optopt = (opt->type == o_wild)? "": " option";
- int prio = option_priority;
- option_t *mainopt = opt;
- current_option = opt->name;
- if ((opt->flags & OPT_PRIVFIX) && privileged_option)
- prio += OPRIO_ROOT;
- while (mainopt->flags & OPT_PRIOSUB)
- --mainopt;
- if (mainopt->flags & OPT_PRIO) {
- if (prio < mainopt->priority) {
- /* new value doesn't override old */
- if (prio == OPRIO_CMDLINE && mainopt->priority > OPRIO_ROOT) {
- option_error("%s%s set in %s cannot be overridden\n",
- opt->name, optopt, mainopt->source);
- return 0;
- }
- return 1;
- }
- if (prio > OPRIO_ROOT && mainopt->priority == OPRIO_CMDLINE)
- warn("%s%s from %s overrides command line",
- opt->name, optopt, option_source);
- }
- if ((opt->flags & OPT_INITONLY) && phase != PHASE_INITIALIZE) {
- option_error("%s%s cannot be changed after initialization",
- opt->name, optopt);
- return 0;
- }
- if ((opt->flags & OPT_PRIV) && !privileged_option) {
- option_error("using the %s%s requires root privilege",
- opt->name, optopt);
- return 0;
- }
- if ((opt->flags & OPT_ENABLE) && *(bool *)(opt->addr2) == 0) {
- option_error("%s%s is disabled", opt->name, optopt);
- return 0;
- }
- if ((opt->flags & OPT_DEVEQUIV) && devnam_fixed) {
- option_error("the %s%s may not be changed in %s",
- opt->name, optopt, option_source);
- return 0;
- }
- switch (opt->type) {
- case o_bool:
- v = opt->flags & OPT_VALUE;
- *(bool *)(opt->addr) = v;
- if (opt->addr2 && (opt->flags & OPT_A2COPY))
- *(bool *)(opt->addr2) = v;
- else if (opt->addr2 && (opt->flags & OPT_A2CLR))
- *(bool *)(opt->addr2) = 0;
- else if (opt->addr2 && (opt->flags & OPT_A2CLRB))
- *(u_char *)(opt->addr2) &= ~v;
- else if (opt->addr2 && (opt->flags & OPT_A2OR))
- *(u_char *)(opt->addr2) |= v;
- break;
- case o_int:
- iv = 0;
- if ((opt->flags & OPT_NOARG) == 0) {
- if (!int_option(*argv, &iv))
- return 0;
- if ((((opt->flags & OPT_LLIMIT) && iv < opt->lower_limit)
- || ((opt->flags & OPT_ULIMIT) && iv > opt->upper_limit))
- && !((opt->flags & OPT_ZEROOK && iv == 0))) {
- char *zok = (opt->flags & OPT_ZEROOK)? " zero or": "";
- switch (opt->flags & OPT_LIMITS) {
- case OPT_LLIMIT:
- option_error("%s value must be%s >= %d",
- opt->name, zok, opt->lower_limit);
- break;
- case OPT_ULIMIT:
- option_error("%s value must be%s <= %d",
- opt->name, zok, opt->upper_limit);
- break;
- case OPT_LIMITS:
- option_error("%s value must be%s between %d and %d",
- opt->name, zok, opt->lower_limit, opt->upper_limit);
- break;
- }
- return 0;
- }
- }
- a = opt->flags & OPT_VALUE;
- if (a >= 128)
- a -= 256; /* sign extend */
- iv += a;
- if (opt->flags & OPT_INC)
- iv += *(int *)(opt->addr);
- if ((opt->flags & OPT_NOINCR) && !privileged_option) {
- int oldv = *(int *)(opt->addr);
- if ((opt->flags & OPT_ZEROINF) ?
- (oldv != 0 && (iv == 0 || iv > oldv)) : (iv > oldv)) {
- option_error("%s value cannot be increased", opt->name);
- return 0;
- }
- }
- *(int *)(opt->addr) = iv;
- if (opt->addr2 && (opt->flags & OPT_A2COPY))
- *(int *)(opt->addr2) = iv;
- break;
- case o_uint32:
- if (opt->flags & OPT_NOARG) {
- v = opt->flags & OPT_VALUE;
- if (v & 0x80)
- v |= 0xffffff00U;
- } else if (!number_option(*argv, &v, 16))
- return 0;
- if (opt->flags & OPT_OR)
- v |= *(u_int32_t *)(opt->addr);
- *(u_int32_t *)(opt->addr) = v;
- if (opt->addr2 && (opt->flags & OPT_A2COPY))
- *(u_int32_t *)(opt->addr2) = v;
- break;
- case o_string:
- if (opt->flags & OPT_STATIC) {
- strlcpy((char *)(opt->addr), *argv, opt->upper_limit);
- } else {
- char **optptr = (char **)(opt->addr);
- sv = strdup(*argv);
- if (sv == NULL)
- novm("option argument");
- if (*optptr)
- free(*optptr);
- *optptr = sv;
- }
- break;
- case o_special_noarg:
- case o_special:
- parser = (int (*) __P((char **))) opt->addr;
- curopt = opt;
- if (!(*parser)(argv))
- return 0;
- if (opt->flags & OPT_A2LIST) {
- struct option_value *ovp, *pp;
- ovp = malloc(sizeof(*ovp) + strlen(*argv));
- if (ovp != 0) {
- strcpy(ovp->value, *argv);
- ovp->source = option_source;
- ovp->next = NULL;
- if (opt->addr2 == NULL) {
- opt->addr2 = ovp;
- } else {
- for (pp = opt->addr2; pp->next != NULL; pp = pp->next)
- ;
- pp->next = ovp;
- }
- }
- }
- break;
- case o_wild:
- wildp = (int (*) __P((char *, char **, int))) opt->addr;
- if (!(*wildp)(cmd, argv, 1))
- return 0;
- break;
- }
- /*
- * If addr2 wasn't used by any flag (OPT_A2COPY, etc.) but is set,
- * treat it as a bool and set/clear it based on the OPT_A2CLR bit.
- */
- if (opt->addr2 && (opt->flags & (OPT_A2COPY|OPT_ENABLE
- |OPT_A2PRINTER|OPT_A2STRVAL|OPT_A2LIST|OPT_A2OR)) == 0)
- *(bool *)(opt->addr2) = !(opt->flags & OPT_A2CLR);
- mainopt->source = option_source;
- mainopt->priority = prio;
- mainopt->winner = opt - mainopt;
- return 1;
- }
- /*
- * override_value - if the option priorities would permit us to
- * override the value of option, return 1 and update the priority
- * and source of the option value. Otherwise returns 0.
- */
- int
- override_value(option, priority, source)
- const char *option;
- int priority;
- const char *source;
- {
- option_t *opt;
- opt = find_option(option);
- if (opt == NULL)
- return 0;
- while (opt->flags & OPT_PRIOSUB)
- --opt;
- if ((opt->flags & OPT_PRIO) && priority < opt->priority)
- return 0;
- opt->priority = priority;
- opt->source = source;
- opt->winner = -1;
- return 1;
- }
- /*
- * n_arguments - tell how many arguments an option takes
- */
- static int
- n_arguments(opt)
- option_t *opt;
- {
- return (opt->type == o_bool || opt->type == o_special_noarg
- || (opt->flags & OPT_NOARG))? 0: 1;
- }
- /*
- * add_options - add a list of options to the set we grok.
- */
- void
- add_options(opt)
- option_t *opt;
- {
- struct option_list *list;
- list = malloc(sizeof(*list));
- if (list == 0)
- novm("option list entry");
- list->options = opt;
- list->next = extra_options;
- extra_options = list;
- }
- /*
- * check_options - check that options are valid and consistent.
- */
- void
- check_options()
- {
- if (logfile_fd >= 0 && logfile_fd != log_to_fd)
- close(logfile_fd);
- }
- /*
- * print_option - print out an option and its value
- */
- static void
- print_option(opt, mainopt, printer, arg)
- option_t *opt, *mainopt;
- printer_func printer;
- void *arg;
- {
- int i, v;
- char *p;
- if (opt->flags & OPT_NOPRINT)
- return;
- switch (opt->type) {
- case o_bool:
- v = opt->flags & OPT_VALUE;
- if (*(bool *)opt->addr != v)
- /* this can happen legitimately, e.g. lock
- option turned off for default device */
- break;
- printer(arg, "%s", opt->name);
- break;
- case o_int:
- v = opt->flags & OPT_VALUE;
- if (v >= 128)
- v -= 256;
- i = *(int *)opt->addr;
- if (opt->flags & OPT_NOARG) {
- printer(arg, "%s", opt->name);
- if (i != v) {
- if (opt->flags & OPT_INC) {
- for (; i > v; i -= v)
- printer(arg, " %s", opt->name);
- } else
- printer(arg, " # oops: %d not %d\n",
- i, v);
- }
- } else {
- printer(arg, "%s %d", opt->name, i);
- }
- break;
- case o_uint32:
- printer(arg, "%s", opt->name);
- if ((opt->flags & OPT_NOARG) == 0)
- printer(arg, " %x", *(u_int32_t *)opt->addr);
- break;
- case o_string:
- if (opt->flags & OPT_HIDE) {
- p = "??????";
- } else {
- p = (char *) opt->addr;
- if ((opt->flags & OPT_STATIC) == 0)
- p = *(char **)p;
- }
- printer(arg, "%s %q", opt->name, p);
- break;
- case o_special:
- case o_special_noarg:
- case o_wild:
- if (opt->type != o_wild) {
- printer(arg, "%s", opt->name);
- if (n_arguments(opt) == 0)
- break;
- printer(arg, " ");
- }
- if (opt->flags & OPT_A2PRINTER) {
- void (*oprt) __P((option_t *, printer_func, void *));
- oprt = (void (*) __P((option_t *, printer_func,
- void *)))opt->addr2;
- (*oprt)(opt, printer, arg);
- } else if (opt->flags & OPT_A2STRVAL) {
- p = (char *) opt->addr2;
- if ((opt->flags & OPT_STATIC) == 0)
- p = *(char **)p;
- printer("%q", p);
- } else if (opt->flags & OPT_A2LIST) {
- struct option_value *ovp;
- ovp = (struct option_value *) opt->addr2;
- for (;;) {
- printer(arg, "%q", ovp->value);
- if ((ovp = ovp->next) == NULL)
- break;
- printer(arg, "\t\t# (from %s)\n%s ",
- ovp->source, opt->name);
- }
- } else {
- printer(arg, "xxx # [don't know how to print value]");
- }
- break;
- default:
- printer(arg, "# %s value (type %d\?\?)", opt->name, opt->type);
- break;
- }
- printer(arg, "\t\t# (from %s)\n", mainopt->source);
- }
- /*
- * print_option_list - print out options in effect from an
- * array of options.
- */
- static void
- print_option_list(opt, printer, arg)
- option_t *opt;
- printer_func printer;
- void *arg;
- {
- while (opt->name != NULL) {
- if (opt->priority != OPRIO_DEFAULT
- && opt->winner != (short int) -1)
- print_option(opt + opt->winner, opt, printer, arg);
- do {
- ++opt;
- } while (opt->flags & OPT_PRIOSUB);
- }
- }
- /*
- * print_options - print out what options are in effect.
- */
- void
- print_options(printer, arg)
- printer_func printer;
- void *arg;
- {
- struct option_list *list;
- int i;
- printer(arg, "pppd options in effect:\n");
- print_option_list(general_options, printer, arg);
- print_option_list(auth_options, printer, arg);
- for (list = extra_options; list != NULL; list = list->next)
- print_option_list(list->options, printer, arg);
- print_option_list(the_channel->options, printer, arg);
- for (i = 0; protocols[i] != NULL; ++i)
- print_option_list(protocols[i]->options, printer, arg);
- }
- /*
- * usage - print out a message telling how to use the program.
- */
- static void
- usage()
- {
- if (phase == PHASE_INITIALIZE)
- fprintf(stderr, usage_string, VERSION, progname);
- }
- /*
- * showhelp - print out usage message and exit.
- */
- static int
- showhelp(argv)
- char **argv;
- {
- if (phase == PHASE_INITIALIZE) {
- usage();
- exit(0);
- }
- return 0;
- }
- /*
- * showversion - print out the version number and exit.
- */
- static int
- showversion(argv)
- char **argv;
- {
- if (phase == PHASE_INITIALIZE) {
- fprintf(stderr, "pppd version %s\n", VERSION);
- exit(0);
- }
- return 0;
- }
- /*
- * option_error - print a message about an error in an option.
- * The message is logged, and also sent to
- * stderr if phase == PHASE_INITIALIZE.
- */
- void
- option_error __V((char *fmt, ...))
- {
- va_list args;
- char buf[1024];
- #if defined(__STDC__)
- va_start(args, fmt);
- #else
- char *fmt;
- va_start(args);
- fmt = va_arg(args, char *);
- #endif
- vslprintf(buf, sizeof(buf), fmt, args);
- va_end(args);
- if (phase == PHASE_INITIALIZE)
- fprintf(stderr, "%s: %s\n", progname, buf);
- syslog(LOG_ERR, "%s", buf);
- }
- #if 0
- /*
- * readable - check if a file is readable by the real user.
- */
- int
- readable(fd)
- int fd;
- {
- uid_t uid;
- int i;
- struct stat sbuf;
- uid = getuid();
- if (uid == 0)
- return 1;
- if (fstat(fd, &sbuf) != 0)
- return 0;
- if (sbuf.st_uid == uid)
- return sbuf.st_mode & S_IRUSR;
- if (sbuf.st_gid == getgid())
- return sbuf.st_mode & S_IRGRP;
- for (i = 0; i < ngroups; ++i)
- if (sbuf.st_gid == groups[i])
- return sbuf.st_mode & S_IRGRP;
- return sbuf.st_mode & S_IROTH;
- }
- #endif
- /*
- * Read a word from a file.
- * Words are delimited by white-space or by quotes (" or ').
- * Quotes, white-space and \ may be escaped with \.
- * \<newline> is ignored.
- */
- int
- getword(f, word, newlinep, filename)
- FILE *f;
- char *word;
- int *newlinep;
- char *filename;
- {
- int c, len, escape;
- int quoted, comment;
- int value, digit, got, n;
- #define isoctal(c) ((c) >= '0' && (c) < '8')
- *newlinep = 0;
- len = 0;
- escape = 0;
- comment = 0;
- quoted = 0;
- /*
- * First skip white-space and comments.
- */
- for (;;) {
- c = getc(f);
- if (c == EOF)
- break;
- /*
- * A newline means the end of a comment; backslash-newline
- * is ignored. Note that we cannot have escape && comment.
- */
- if (c == '\n') {
- if (!escape) {
- *newlinep = 1;
- comment = 0;
- } else
- escape = 0;
- continue;
- }
- /*
- * Ignore characters other than newline in a comment.
- */
- if (comment)
- continue;
- /*
- * If this character is escaped, we have a word start.
- */
- if (escape)
- break;
- /*
- * If this is the escape character, look at the next character.
- */
- if (c == '\\') {
- escape = 1;
- continue;
- }
- /*
- * If this is the start of a comment, ignore the rest of the line.
- */
- if (c == '#') {
- comment = 1;
- continue;
- }
- /*
- * A non-whitespace character is the start of a word.
- */
- if (!isspace(c))
- break;
- }
- /*
- * Process characters until the end of the word.
- */
- while (c != EOF) {
- if (escape) {
- /*
- * This character is escaped: backslash-newline is ignored,
- * various other characters indicate particular values
- * as for C backslash-escapes.
- */
- escape = 0;
- if (c == '\n') {
- c = getc(f);
- continue;
- }
- got = 0;
- switch (c) {
- case 'a':
- value = '\a';
- break;
- case 'b':
- value = '\b';
- break;
- case 'f':
- value = '\f';
- break;
- case 'n':
- value = '\n';
- break;
- case 'r':
- value = '\r';
- break;
- case 's':
- value = ' ';
- break;
- case 't':
- value = '\t';
- break;
- default:
- if (isoctal(c)) {
- /*
- * \ddd octal sequence
- */
- value = 0;
- for (n = 0; n < 3 && isoctal(c); ++n) {
- value = (value << 3) + (c & 07);
- c = getc(f);
- }
- got = 1;
- break;
- }
- if (c == 'x') {
- /*
- * \x<hex_string> sequence
- */
- value = 0;
- c = getc(f);
- for (n = 0; n < 2 && isxdigit(c); ++n) {
- digit = toupper(c) - '0';
- if (digit > 10)
- digit += '0' + 10 - 'A';
- value = (value << 4) + digit;
- c = getc (f);
- }
- got = 1;
- break;
- }
- /*
- * Otherwise the character stands for itself.
- */
- value = c;
- break;
- }
- /*
- * Store the resulting character for the escape sequence.
- */
- if (len < MAXWORDLEN) {
- word[len] = value;
- ++len;
- }
- if (!got)
- c = getc(f);
- continue;
- }
- /*
- * Backslash starts a new escape sequence.
- */
- if (c == '\\') {
- escape = 1;
- c = getc(f);
- continue;
- }
- /*
- * Not escaped: check for the start or end of a quoted
- * section and see if we've reached the end of the word.
- */
- if (quoted) {
- if (c == quoted) {
- quoted = 0;
- c = getc(f);
- continue;
- }
- } else if (c == '"' || c == '\'') {
- quoted = c;
- c = getc(f);
- continue;
- } else if (isspace(c) || c == '#') {
- ungetc (c, f);
- break;
- }
- /*
- * An ordinary character: store it in the word and get another.
- */
- if (len < MAXWORDLEN) {
- word[len] = c;
- ++len;
- }
- c = getc(f);
- }
- /*
- * End of the word: check for errors.
- */
- if (c == EOF) {
- if (ferror(f)) {
- if (errno == 0)
- errno = EIO;
- option_error("Error reading %s: %m", filename);
- die(1);
- }
- /*
- * If len is zero, then we didn't find a word before the
- * end of the file.
- */
- if (len == 0)
- return 0;
- if (quoted)
- option_error("warning: quoted word runs to end of file (%.20s...)",
- filename, word);
- }
- /*
- * Warn if the word was too long, and append a terminating null.
- */
- if (len >= MAXWORDLEN) {
- option_error("warning: word in file %s too long (%.20s...)",
- filename, word);
- len = MAXWORDLEN - 1;
- }
- word[len] = 0;
- return 1;
- #undef isoctal
- }
- /*
- * number_option - parse an unsigned numeric parameter for an option.
- */
- static int
- number_option(str, valp, base)
- char *str;
- u_int32_t *valp;
- int base;
- {
- char *ptr;
- *valp = strtoul(str, &ptr, base);
- if (ptr == str) {
- option_error("invalid numeric parameter '%s' for %s option",
- str, current_option);
- return 0;
- }
- return 1;
- }
- /*
- * int_option - like number_option, but valp is int *,
- * the base is assumed to be 0, and *valp is not changed
- * if there is an error.
- */
- int
- int_option(str, valp)
- char *str;
- int *valp;
- {
- u_int32_t v;
- if (!number_option(str, &v, 0))
- return 0;
- *valp = (int) v;
- return 1;
- }
- /*
- * The following procedures parse options.
- */
- /*
- * readfile - take commands from a file.
- */
- static int
- readfile(argv)
- char **argv;
- {
- return options_from_file(*argv, 1, 1, privileged_option);
- }
- /*
- * callfile - take commands from /etc/ppp/peers/<name>.
- * Name may not contain /../, start with / or ../, or end in /..
- */
- static int
- callfile(argv)
- char **argv;
- {
- char *fname, *arg, *p;
- int l, ok;
- arg = *argv;
- ok = 1;
- if (arg[0] == '/' || arg[0] == 0)
- ok = 0;
- else {
- for (p = arg; *p != 0; ) {
- if (p[0] == '.' && p[1] == '.' && (p[2] == '/' || p[2] == 0)) {
- ok = 0;
- break;
- }
- while (*p != '/' && *p != 0)
- ++p;
- if (*p == '/')
- ++p;
- }
- }
- if (!ok) {
- option_error("call option value may not contain .. or start with /");
- return 0;
- }
- l = strlen(arg) + strlen(_PATH_PEERFILES) + 1;
- if ((fname = (char *) malloc(l)) == NULL)
- novm("call file name");
- slprintf(fname, l, "%s%s", _PATH_PEERFILES, arg);
- ok = options_from_file(fname, 1, 1, 1);
- free(fname);
- return ok;
- }
- #ifdef PPP_FILTER
- /*
- * setpassfilter - Set the pass filter for packets
- */
- static int
- setpassfilter(argv)
- char **argv;
- {
- pcap_t *pc;
- int ret = 1;
- pc = pcap_open_dead(DLT_PPP_PPPD, 65535);
- if (pcap_compile(pc, &pass_filter, *argv, 1, netmask) == -1) {
- option_error("error in pass-filter expression: %s\n",
- pcap_geterr(pc));
- ret = 0;
- }
- pcap_close(pc);
- return ret;
- }
- /*
- * setactivefilter - Set the active filter for packets
- */
- static int
- setactivefilter(argv)
- char **argv;
- {
- pcap_t *pc;
- int ret = 1;
- pc = pcap_open_dead(DLT_PPP_PPPD, 65535);
- if (pcap_compile(pc, &active_filter, *argv, 1, netmask) == -1) {
- option_error("error in active-filter expression: %s\n",
- pcap_geterr(pc));
- ret = 0;
- }
- pcap_close(pc);
- return ret;
- }
- #endif
- /*
- * setdomain - Set domain name to append to hostname
- */
- static int
- setdomain(argv)
- char **argv;
- {
- gethostname(hostname, MAXNAMELEN);
- if (**argv != 0) {
- if (**argv != '.')
- strncat(hostname, ".", MAXNAMELEN - strlen(hostname));
- domain = hostname + strlen(hostname);
- strncat(hostname, *argv, MAXNAMELEN - strlen(hostname));
- }
- hostname[MAXNAMELEN-1] = 0;
- return (1);
- }
- static int
- setlogfile(argv)
- char **argv;
- {
- int fd, err;
- uid_t euid;
- euid = geteuid();
- if (!privileged_option && seteuid(getuid()) == -1) {
- option_error("unable to drop permissions to open %s: %m", *argv);
- return 0;
- }
- fd = open(*argv, O_WRONLY | O_APPEND | O_CREAT | O_EXCL, 0644);
- if (fd < 0 && errno == EEXIST)
- fd = open(*argv, O_WRONLY | O_APPEND);
- err = errno;
- if (!privileged_option && seteuid(euid) == -1)
- fatal("unable to regain privileges: %m");
- if (fd < 0) {
- errno = err;
- option_error("Can't open log file %s: %m", *argv);
- return 0;
- }
- strlcpy(logfile_name, *argv, sizeof(logfile_name));
- if (logfile_fd >= 0)
- close(logfile_fd);
- logfile_fd = fd;
- log_to_fd = fd;
- log_default = 0;
- return 1;
- }
- #ifdef MAXOCTETS
- static int
- setmodir(argv)
- char **argv;
- {
- if(*argv == NULL)
- return 0;
- if(!strcmp(*argv,"in")) {
- maxoctets_dir = PPP_OCTETS_DIRECTION_IN;
- } else if (!strcmp(*argv,"out")) {
- maxoctets_dir = PPP_OCTETS_DIRECTION_OUT;
- } else if (!strcmp(*argv,"max")) {
- maxoctets_dir = PPP_OCTETS_DIRECTION_MAXOVERAL;
- } else {
- maxoctets_dir = PPP_OCTETS_DIRECTION_SUM;
- }
- return 1;
- }
- #endif
- #ifdef PLUGIN
- static int
- loadplugin(argv)
- char **argv;
- {
- char *arg = *argv;
- void *handle;
- const char *err;
- void (*init) __P((void));
- char *path = arg;
- const char *vers;
- if (strchr(arg, '/') == 0) {
- const char *base = _PATH_PLUGIN;
- int l = strlen(base) + strlen(arg) + 2;
- path = malloc(l);
- if (path == 0)
- novm("plugin file path");
- strlcpy(path, base, l);
- strlcat(path, "/", l);
- strlcat(path, arg, l);
- }
- handle = dlopen(path, RTLD_GLOBAL | RTLD_NOW);
- if (handle == 0) {
- err = dlerror();
- if (err != 0)
- option_error("%s", err);
- option_error("Couldn't load plugin %s", arg);
- goto err;
- }
- init = (void (*)(void))dlsym(handle, "plugin_init");
- if (init == 0) {
- option_error("%s has no initialization entry point", arg);
- goto errclose;
- }
- vers = (const char *) dlsym(handle, "pppd_version");
- if (vers == 0) {
- warn("Warning: plugin %s has no version information", arg);
- } else if (strcmp(vers, VERSION) != 0) {
- option_error("Plugin %s is for pppd version %s, this is %s",
- arg, vers, VERSION);
- goto errclose;
- }
- info("Plugin %s loaded.", arg);
- (*init)();
- return 1;
- errclose:
- dlclose(handle);
- err:
- if (path != arg)
- free(path);
- return 0;
- }
- #endif /* PLUGIN */
- /*
- * Set an environment variable specified by the user.
- */
- static int
- user_setenv(argv)
- char **argv;
- {
- char *arg = argv[0];
- char *eqp;
- struct userenv *uep, **insp;
- if ((eqp = strchr(arg, '=')) == NULL) {
- option_error("missing = in name=value: %s", arg);
- return 0;
- }
- if (eqp == arg) {
- option_error("missing variable name: %s", arg);
- return 0;
- }
- for (uep = userenv_list; uep != NULL; uep = uep->ue_next) {
- int nlen = strlen(uep->ue_name);
- if (nlen == (eqp - arg) &&
- strncmp(arg, uep->ue_name, nlen) == 0)
- break;
- }
- /* Ignore attempts by unprivileged users to override privileged sources */
- if (uep != NULL && !privileged_option && uep->ue_priv)
- return 1;
- /* The name never changes, so allocate it with the structure */
- if (uep == NULL) {
- uep = malloc(sizeof (*uep) + (eqp-arg));
- strncpy(uep->ue_name, arg, eqp-arg);
- uep->ue_name[eqp-arg] = '\0';
- uep->ue_next = NULL;
- insp = &userenv_list;
- while (*insp != NULL)
- insp = &(*insp)->ue_next;
- *insp = uep;
- } else {
- struct userenv *uep2;
- for (uep2 = userenv_list; uep2 != NULL; uep2 = uep2->ue_next) {
- if (uep2 != uep && !uep2->ue_isset)
- break;
- }
- if (uep2 == NULL && !uep->ue_isset)
- find_option("unset")->flags |= OPT_NOPRINT;
- free(uep->ue_value);
- }
- uep->ue_isset = 1;
- uep->ue_priv = privileged_option;
- uep->ue_source = option_source;
- uep->ue_value = strdup(eqp + 1);
- curopt->flags &= ~OPT_NOPRINT;
- return 1;
- }
- static void
- user_setprint(opt, printer, arg)
- option_t *opt;
- printer_func printer;
- void *arg;
- {
- struct userenv *uep, *uepnext;
- uepnext = userenv_list;
- while (uepnext != NULL && !uepnext->ue_isset)
- uepnext = uepnext->ue_next;
- while ((uep = uepnext) != NULL) {
- uepnext = uep->ue_next;
- while (uepnext != NULL && !uepnext->ue_isset)
- uepnext = uepnext->ue_next;
- (*printer)(arg, "%s=%s", uep->ue_name, uep->ue_value);
- if (uepnext != NULL)
- (*printer)(arg, "\t\t# (from %s)\n%s ", uep->ue_source, opt->name);
- else
- opt->source = uep->ue_source;
- }
- }
- static int
- user_unsetenv(argv)
- char **argv;
- {
- struct userenv *uep, **insp;
- char *arg = argv[0];
- if (strchr(arg, '=') != NULL) {
- option_error("unexpected = in name: %s", arg);
- return 0;
- }
- if (arg == '\0') {
- option_error("missing variable name for unset");
- return 0;
- }
- for (uep = userenv_list; uep != NULL; uep = uep->ue_next) {
- if (strcmp(arg, uep->ue_name) == 0)
- break;
- }
- /* Ignore attempts by unprivileged users to override privileged sources */
- if (uep != NULL && !privileged_option && uep->ue_priv)
- return 1;
- /* The name never changes, so allocate it with the structure */
- if (uep == NULL) {
- uep = malloc(sizeof (*uep) + strlen(arg));
- strcpy(uep->ue_name, arg);
- uep->ue_next = NULL;
- insp = &userenv_list;
- while (*insp != NULL)
- insp = &(*insp)->ue_next;
- *insp = uep;
- } else {
- struct userenv *uep2;
- for (uep2 = userenv_list; uep2 != NULL; uep2 = uep2->ue_next) {
- if (uep2 != uep && uep2->ue_isset)
- break;
- }
- if (uep2 == NULL && uep->ue_isset)
- find_option("set")->flags |= OPT_NOPRINT;
- free(uep->ue_value);
- }
- uep->ue_isset = 0;
- uep->ue_priv = privileged_option;
- uep->ue_source = option_source;
- uep->ue_value = NULL;
- curopt->flags &= ~OPT_NOPRINT;
- return 1;
- }
- static void
- user_unsetprint(opt, printer, arg)
- option_t *opt;
- printer_func printer;
- void *arg;
- {
- struct userenv *uep, *uepnext;
- uepnext = userenv_list;
- while (uepnext != NULL && uepnext->ue_isset)
- uepnext = uepnext->ue_next;
- while ((uep = uepnext) != NULL) {
- uepnext = uep->ue_next;
- while (uepnext != NULL && uepnext->ue_isset)
- uepnext = uepnext->ue_next;
- (*printer)(arg, "%s", uep->ue_name);
- if (uepnext != NULL)
- (*printer)(arg, "\t\t# (from %s)\n%s ", uep->ue_source, opt->name);
- else
- opt->source = uep->ue_source;
- }
- }
|