]> git.ozlabs.org Git - ppp.git/blob - pppd/options.c
Merge branch 'master' of https://github.com/ncopa/ppp
[ppp.git] / pppd / options.c
1 /*
2  * options.c - handles option processing for PPP.
3  *
4  * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  *
18  * 3. The name "Carnegie Mellon University" must not be used to
19  *    endorse or promote products derived from this software without
20  *    prior written permission. For permission or any legal
21  *    details, please contact
22  *      Office of Technology Transfer
23  *      Carnegie Mellon University
24  *      5000 Forbes Avenue
25  *      Pittsburgh, PA  15213-3890
26  *      (412) 268-4387, fax: (412) 268-7395
27  *      tech-transfer@andrew.cmu.edu
28  *
29  * 4. Redistributions of any form whatsoever must retain the following
30  *    acknowledgment:
31  *    "This product includes software developed by Computing Services
32  *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
33  *
34  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
35  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
36  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
37  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
38  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
39  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
40  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
41  */
42
43 #define RCSID   "$Id: options.c,v 1.102 2008/06/15 06:53:06 paulus Exp $"
44
45 #include <ctype.h>
46 #include <stdio.h>
47 #include <errno.h>
48 #include <unistd.h>
49 #include <fcntl.h>
50 #include <stdlib.h>
51 #include <syslog.h>
52 #include <string.h>
53 #include <pwd.h>
54 #ifdef PLUGIN
55 #include <dlfcn.h>
56 #endif
57
58 #ifdef PPP_FILTER
59 #include <pcap.h>
60 /*
61  * There have been 3 or 4 different names for this in libpcap CVS, but
62  * this seems to be what they have settled on...
63  * For older versions of libpcap, use DLT_PPP - but that means
64  * we lose the inbound and outbound qualifiers.
65  */
66 #ifndef DLT_PPP_PPPD
67 #ifdef DLT_PPP_WITHDIRECTION
68 #define DLT_PPP_PPPD    DLT_PPP_WITHDIRECTION
69 #else
70 #define DLT_PPP_PPPD    DLT_PPP
71 #endif
72 #endif
73 #endif /* PPP_FILTER */
74
75 #include "pppd.h"
76 #include "pathnames.h"
77
78 #if defined(ultrix) || defined(NeXT)
79 char *strdup __P((char *));
80 #endif
81
82 static const char rcsid[] = RCSID;
83
84 struct option_value {
85     struct option_value *next;
86     const char *source;
87     char value[1];
88 };
89
90 /*
91  * Option variables and default values.
92  */
93 int     debug = 0;              /* Debug flag */
94 int     kdebugflag = 0;         /* Tell kernel to print debug messages */
95 int     default_device = 1;     /* Using /dev/tty or equivalent */
96 char    devnam[MAXPATHLEN];     /* Device name */
97 bool    nodetach = 0;           /* Don't detach from controlling tty */
98 bool    updetach = 0;           /* Detach once link is up */
99 bool    master_detach;          /* Detach when we're (only) multilink master */
100 int     maxconnect = 0;         /* Maximum connect time */
101 char    user[MAXNAMELEN];       /* Username for PAP */
102 char    passwd[MAXSECRETLEN];   /* Password for PAP */
103 bool    persist = 0;            /* Reopen link after it goes down */
104 char    our_name[MAXNAMELEN];   /* Our name for authentication purposes */
105 bool    demand = 0;             /* do dial-on-demand */
106 char    *ipparam = NULL;        /* Extra parameter for ip up/down scripts */
107 int     idle_time_limit = 0;    /* Disconnect if idle for this many seconds */
108 int     holdoff = 30;           /* # seconds to pause before reconnecting */
109 bool    holdoff_specified;      /* true if a holdoff value has been given */
110 int     log_to_fd = 1;          /* send log messages to this fd too */
111 bool    log_default = 1;        /* log_to_fd is default (stdout) */
112 int     maxfail = 10;           /* max # of unsuccessful connection attempts */
113 char    linkname[MAXPATHLEN];   /* logical name for link */
114 bool    tune_kernel;            /* may alter kernel settings */
115 int     connect_delay = 1000;   /* wait this many ms after connect script */
116 int     req_unit = -1;          /* requested interface unit */
117 bool    multilink = 0;          /* Enable multilink operation */
118 char    *bundle_name = NULL;    /* bundle name for multilink */
119 bool    dump_options;           /* print out option values */
120 bool    dryrun;                 /* print out option values and exit */
121 char    *domain;                /* domain name set by domain option */
122 int     child_wait = 5;         /* # seconds to wait for children at exit */
123 struct userenv *userenv_list;   /* user environment variables */
124 int     dfl_route_metric = -1;  /* metric of the default route to set over the PPP link */
125
126 #ifdef MAXOCTETS
127 unsigned int  maxoctets = 0;    /* default - no limit */
128 int maxoctets_dir = 0;       /* default - sum of traffic */
129 int maxoctets_timeout = 1;   /* default 1 second */ 
130 #endif
131
132
133 extern option_t auth_options[];
134 extern struct stat devstat;
135
136 #ifdef PPP_FILTER
137 struct  bpf_program pass_filter;/* Filter program for packets to pass */
138 struct  bpf_program active_filter; /* Filter program for link-active pkts */
139 #endif
140
141 static option_t *curopt;        /* pointer to option being processed */
142 char *current_option;           /* the name of the option being parsed */
143 int  privileged_option;         /* set iff the current option came from root */
144 char *option_source;            /* string saying where the option came from */
145 int  option_priority = OPRIO_CFGFILE; /* priority of the current options */
146 bool devnam_fixed;              /* can no longer change device name */
147
148 static int logfile_fd = -1;     /* fd opened for log file */
149 static char logfile_name[MAXPATHLEN];   /* name of log file */
150
151 /*
152  * Prototypes
153  */
154 static int setdomain __P((char **));
155 static int readfile __P((char **));
156 static int callfile __P((char **));
157 static int showversion __P((char **));
158 static int showhelp __P((char **));
159 static void usage __P((void));
160 static int setlogfile __P((char **));
161 #ifdef PLUGIN
162 static int loadplugin __P((char **));
163 #endif
164
165 #ifdef PPP_FILTER
166 static int setpassfilter __P((char **));
167 static int setactivefilter __P((char **));
168 #endif
169
170 #ifdef MAXOCTETS
171 static int setmodir __P((char **));
172 #endif
173
174 static int user_setenv __P((char **));
175 static void user_setprint __P((option_t *, printer_func, void *));
176 static int user_unsetenv __P((char **));
177 static void user_unsetprint __P((option_t *, printer_func, void *));
178
179 static option_t *find_option __P((const char *name));
180 static int process_option __P((option_t *, char *, char **));
181 static int n_arguments __P((option_t *));
182 static int number_option __P((char *, u_int32_t *, int));
183
184 /*
185  * Structure to store extra lists of options.
186  */
187 struct option_list {
188     option_t *options;
189     struct option_list *next;
190 };
191
192 static struct option_list *extra_options = NULL;
193
194 /*
195  * Valid arguments.
196  */
197 option_t general_options[] = {
198     { "debug", o_int, &debug,
199       "Increase debugging level", OPT_INC | OPT_NOARG | 1 },
200     { "-d", o_int, &debug,
201       "Increase debugging level",
202       OPT_ALIAS | OPT_INC | OPT_NOARG | 1 },
203
204     { "kdebug", o_int, &kdebugflag,
205       "Set kernel driver debug level", OPT_PRIO },
206
207     { "nodetach", o_bool, &nodetach,
208       "Don't detach from controlling tty", OPT_PRIO | 1 },
209     { "-detach", o_bool, &nodetach,
210       "Don't detach from controlling tty", OPT_ALIAS | OPT_PRIOSUB | 1 },
211     { "updetach", o_bool, &updetach,
212       "Detach from controlling tty once link is up",
213       OPT_PRIOSUB | OPT_A2CLR | 1, &nodetach },
214
215     { "master_detach", o_bool, &master_detach,
216       "Detach when we're multilink master but have no link", 1 },
217
218     { "holdoff", o_int, &holdoff,
219       "Set time in seconds before retrying connection",
220       OPT_PRIO, &holdoff_specified },
221
222     { "idle", o_int, &idle_time_limit,
223       "Set time in seconds before disconnecting idle link", OPT_PRIO },
224
225     { "maxconnect", o_int, &maxconnect,
226       "Set connection time limit",
227       OPT_PRIO | OPT_LLIMIT | OPT_NOINCR | OPT_ZEROINF },
228
229     { "domain", o_special, (void *)setdomain,
230       "Add given domain name to hostname",
231       OPT_PRIO | OPT_PRIV | OPT_A2STRVAL, &domain },
232
233     { "file", o_special, (void *)readfile,
234       "Take options from a file", OPT_NOPRINT },
235     { "call", o_special, (void *)callfile,
236       "Take options from a privileged file", OPT_NOPRINT },
237
238     { "persist", o_bool, &persist,
239       "Keep on reopening connection after close", OPT_PRIO | 1 },
240     { "nopersist", o_bool, &persist,
241       "Turn off persist option", OPT_PRIOSUB },
242
243     { "demand", o_bool, &demand,
244       "Dial on demand", OPT_INITONLY | 1, &persist },
245
246     { "--version", o_special_noarg, (void *)showversion,
247       "Show version number" },
248     { "--help", o_special_noarg, (void *)showhelp,
249       "Show brief listing of options" },
250     { "-h", o_special_noarg, (void *)showhelp,
251       "Show brief listing of options", OPT_ALIAS },
252
253     { "logfile", o_special, (void *)setlogfile,
254       "Append log messages to this file",
255       OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, &logfile_name },
256     { "logfd", o_int, &log_to_fd,
257       "Send log messages to this file descriptor",
258       OPT_PRIOSUB | OPT_A2CLR, &log_default },
259     { "nolog", o_int, &log_to_fd,
260       "Don't send log messages to any file",
261       OPT_PRIOSUB | OPT_NOARG | OPT_VAL(-1) },
262     { "nologfd", o_int, &log_to_fd,
263       "Don't send log messages to any file descriptor",
264       OPT_PRIOSUB | OPT_ALIAS | OPT_NOARG | OPT_VAL(-1) },
265
266     { "linkname", o_string, linkname,
267       "Set logical name for link",
268       OPT_PRIO | OPT_PRIV | OPT_STATIC, NULL, MAXPATHLEN },
269
270     { "maxfail", o_int, &maxfail,
271       "Maximum number of unsuccessful connection attempts to allow",
272       OPT_PRIO },
273
274     { "ktune", o_bool, &tune_kernel,
275       "Alter kernel settings as necessary", OPT_PRIO | 1 },
276     { "noktune", o_bool, &tune_kernel,
277       "Don't alter kernel settings", OPT_PRIOSUB },
278
279     { "connect-delay", o_int, &connect_delay,
280       "Maximum time (in ms) to wait after connect script finishes",
281       OPT_PRIO },
282
283     { "unit", o_int, &req_unit,
284       "PPP interface unit number to use if possible",
285       OPT_PRIO | OPT_LLIMIT, 0, 0 },
286
287     { "dump", o_bool, &dump_options,
288       "Print out option values after parsing all options", 1 },
289     { "dryrun", o_bool, &dryrun,
290       "Stop after parsing, printing, and checking options", 1 },
291
292     { "child-timeout", o_int, &child_wait,
293       "Number of seconds to wait for child processes at exit",
294       OPT_PRIO },
295
296     { "set", o_special, (void *)user_setenv,
297       "Set user environment variable",
298       OPT_A2PRINTER | OPT_NOPRINT, (void *)user_setprint },
299     { "unset", o_special, (void *)user_unsetenv,
300       "Unset user environment variable",
301       OPT_A2PRINTER | OPT_NOPRINT, (void *)user_unsetprint },
302
303     { "defaultroute-metric", o_int, &dfl_route_metric,
304       "Metric to use for the default route (Linux only; -1 for default behavior)",
305       OPT_PRIV|OPT_LLIMIT|OPT_INITONLY, NULL, 0, -1 },
306
307 #ifdef HAVE_MULTILINK
308     { "multilink", o_bool, &multilink,
309       "Enable multilink operation", OPT_PRIO | 1 },
310     { "mp", o_bool, &multilink,
311       "Enable multilink operation", OPT_PRIOSUB | OPT_ALIAS | 1 },
312     { "nomultilink", o_bool, &multilink,
313       "Disable multilink operation", OPT_PRIOSUB | 0 },
314     { "nomp", o_bool, &multilink,
315       "Disable multilink operation", OPT_PRIOSUB | OPT_ALIAS | 0 },
316
317     { "bundle", o_string, &bundle_name,
318       "Bundle name for multilink", OPT_PRIO },
319 #endif /* HAVE_MULTILINK */
320
321 #ifdef PLUGIN
322     { "plugin", o_special, (void *)loadplugin,
323       "Load a plug-in module into pppd", OPT_PRIV | OPT_A2LIST },
324 #endif
325
326 #ifdef PPP_FILTER
327     { "pass-filter", o_special, setpassfilter,
328       "set filter for packets to pass", OPT_PRIO },
329
330     { "active-filter", o_special, setactivefilter,
331       "set filter for active pkts", OPT_PRIO },
332 #endif
333
334 #ifdef MAXOCTETS
335     { "maxoctets", o_int, &maxoctets,
336       "Set connection traffic limit",
337       OPT_PRIO | OPT_LLIMIT | OPT_NOINCR | OPT_ZEROINF },
338     { "mo", o_int, &maxoctets,
339       "Set connection traffic limit",
340       OPT_ALIAS | OPT_PRIO | OPT_LLIMIT | OPT_NOINCR | OPT_ZEROINF },
341     { "mo-direction", o_special, setmodir,
342       "Set direction for limit traffic (sum,in,out,max)" },
343     { "mo-timeout", o_int, &maxoctets_timeout,
344       "Check for traffic limit every N seconds", OPT_PRIO | OPT_LLIMIT | 1 },
345 #endif
346
347     { NULL }
348 };
349
350 #ifndef IMPLEMENTATION
351 #define IMPLEMENTATION ""
352 #endif
353
354 static char *usage_string = "\
355 pppd version %s\n\
356 Usage: %s [ options ], where options are:\n\
357         <device>        Communicate over the named device\n\
358         <speed>         Set the baud rate to <speed>\n\
359         <loc>:<rem>     Set the local and/or remote interface IP\n\
360                         addresses.  Either one may be omitted.\n\
361         asyncmap <n>    Set the desired async map to hex <n>\n\
362         auth            Require authentication from peer\n\
363         connect <p>     Invoke shell command <p> to set up the serial line\n\
364         crtscts         Use hardware RTS/CTS flow control\n\
365         defaultroute    Add default route through interface\n\
366         file <f>        Take options from file <f>\n\
367         modem           Use modem control lines\n\
368         mru <n>         Set MRU value to <n> for negotiation\n\
369 See pppd(8) for more options.\n\
370 ";
371
372 /*
373  * parse_args - parse a string of arguments from the command line.
374  */
375 int
376 parse_args(argc, argv)
377     int argc;
378     char **argv;
379 {
380     char *arg;
381     option_t *opt;
382     int n;
383
384     privileged_option = privileged;
385     option_source = "command line";
386     option_priority = OPRIO_CMDLINE;
387     while (argc > 0) {
388         arg = *argv++;
389         --argc;
390         opt = find_option(arg);
391         if (opt == NULL) {
392             option_error("unrecognized option '%s'", arg);
393             usage();
394             return 0;
395         }
396         n = n_arguments(opt);
397         if (argc < n) {
398             option_error("too few parameters for option %s", arg);
399             return 0;
400         }
401         if (!process_option(opt, arg, argv))
402             return 0;
403         argc -= n;
404         argv += n;
405     }
406     return 1;
407 }
408
409 /*
410  * options_from_file - Read a string of options from a file,
411  * and interpret them.
412  */
413 int
414 options_from_file(filename, must_exist, check_prot, priv)
415     char *filename;
416     int must_exist;
417     int check_prot;
418     int priv;
419 {
420     FILE *f;
421     int i, newline, ret, err;
422     option_t *opt;
423     int oldpriv, n;
424     char *oldsource;
425     uid_t euid;
426     char *argv[MAXARGS];
427     char args[MAXARGS][MAXWORDLEN];
428     char cmd[MAXWORDLEN];
429
430     euid = geteuid();
431     if (check_prot && seteuid(getuid()) == -1) {
432         option_error("unable to drop privileges to open %s: %m", filename);
433         return 0;
434     }
435     f = fopen(filename, "r");
436     err = errno;
437     if (check_prot && seteuid(euid) == -1)
438         fatal("unable to regain privileges");
439     if (f == NULL) {
440         errno = err;
441         if (!must_exist) {
442             if (err != ENOENT && err != ENOTDIR)
443                 warn("Warning: can't open options file %s: %m", filename);
444             return 1;
445         }
446         option_error("Can't open options file %s: %m", filename);
447         return 0;
448     }
449
450     oldpriv = privileged_option;
451     privileged_option = priv;
452     oldsource = option_source;
453     option_source = strdup(filename);
454     if (option_source == NULL)
455         option_source = "file";
456     ret = 0;
457     while (getword(f, cmd, &newline, filename)) {
458         opt = find_option(cmd);
459         if (opt == NULL) {
460             option_error("In file %s: unrecognized option '%s'",
461                          filename, cmd);
462             goto err;
463         }
464         n = n_arguments(opt);
465         for (i = 0; i < n; ++i) {
466             if (!getword(f, args[i], &newline, filename)) {
467                 option_error(
468                         "In file %s: too few parameters for option '%s'",
469                         filename, cmd);
470                 goto err;
471             }
472             argv[i] = args[i];
473         }
474         if (!process_option(opt, cmd, argv))
475             goto err;
476     }
477     ret = 1;
478
479 err:
480     fclose(f);
481     privileged_option = oldpriv;
482     option_source = oldsource;
483     return ret;
484 }
485
486 /*
487  * options_from_user - See if the use has a ~/.ppprc file,
488  * and if so, interpret options from it.
489  */
490 int
491 options_from_user()
492 {
493     char *user, *path, *file;
494     int ret;
495     struct passwd *pw;
496     size_t pl;
497
498     pw = getpwuid(getuid());
499     if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == 0)
500         return 1;
501     file = _PATH_USEROPT;
502     pl = strlen(user) + strlen(file) + 2;
503     path = malloc(pl);
504     if (path == NULL)
505         novm("init file name");
506     slprintf(path, pl, "%s/%s", user, file);
507     option_priority = OPRIO_CFGFILE;
508     ret = options_from_file(path, 0, 1, privileged);
509     free(path);
510     return ret;
511 }
512
513 /*
514  * options_for_tty - See if an options file exists for the serial
515  * device, and if so, interpret options from it.
516  * We only allow the per-tty options file to override anything from
517  * the command line if it is something that the user can't override
518  * once it has been set by root; this is done by giving configuration
519  * files a lower priority than the command line.
520  */
521 int
522 options_for_tty()
523 {
524     char *dev, *path, *p;
525     int ret;
526     size_t pl;
527
528     dev = devnam;
529     if ((p = strstr(dev, "/dev/")) != NULL)
530         dev = p + 5;
531     if (dev[0] == 0 || strcmp(dev, "tty") == 0)
532         return 1;               /* don't look for /etc/ppp/options.tty */
533     pl = strlen(_PATH_TTYOPT) + strlen(dev) + 1;
534     path = malloc(pl);
535     if (path == NULL)
536         novm("tty init file name");
537     slprintf(path, pl, "%s%s", _PATH_TTYOPT, dev);
538     /* Turn slashes into dots, for Solaris case (e.g. /dev/term/a) */
539     for (p = path + strlen(_PATH_TTYOPT); *p != 0; ++p)
540         if (*p == '/')
541             *p = '.';
542     option_priority = OPRIO_CFGFILE;
543     ret = options_from_file(path, 0, 0, 1);
544     free(path);
545     return ret;
546 }
547
548 /*
549  * options_from_list - process a string of options in a wordlist.
550  */
551 int
552 options_from_list(w, priv)
553     struct wordlist *w;
554     int priv;
555 {
556     char *argv[MAXARGS];
557     option_t *opt;
558     int i, n, ret = 0;
559     struct wordlist *w0;
560
561     privileged_option = priv;
562     option_source = "secrets file";
563     option_priority = OPRIO_SECFILE;
564
565     while (w != NULL) {
566         opt = find_option(w->word);
567         if (opt == NULL) {
568             option_error("In secrets file: unrecognized option '%s'",
569                          w->word);
570             goto err;
571         }
572         n = n_arguments(opt);
573         w0 = w;
574         for (i = 0; i < n; ++i) {
575             w = w->next;
576             if (w == NULL) {
577                 option_error(
578                         "In secrets file: too few parameters for option '%s'",
579                         w0->word);
580                 goto err;
581             }
582             argv[i] = w->word;
583         }
584         if (!process_option(opt, w0->word, argv))
585             goto err;
586         w = w->next;
587     }
588     ret = 1;
589
590 err:
591     return ret;
592 }
593
594 /*
595  * match_option - see if this option matches an option_t structure.
596  */
597 static int
598 match_option(name, opt, dowild)
599     char *name;
600     option_t *opt;
601     int dowild;
602 {
603         int (*match) __P((char *, char **, int));
604
605         if (dowild != (opt->type == o_wild))
606                 return 0;
607         if (!dowild)
608                 return strcmp(name, opt->name) == 0;
609         match = (int (*) __P((char *, char **, int))) opt->addr;
610         return (*match)(name, NULL, 0);
611 }
612
613 /*
614  * find_option - scan the option lists for the various protocols
615  * looking for an entry with the given name.
616  * This could be optimized by using a hash table.
617  */
618 static option_t *
619 find_option(name)
620     const char *name;
621 {
622         option_t *opt;
623         struct option_list *list;
624         int i, dowild;
625
626         for (dowild = 0; dowild <= 1; ++dowild) {
627                 for (opt = general_options; opt->name != NULL; ++opt)
628                         if (match_option(name, opt, dowild))
629                                 return opt;
630                 for (opt = auth_options; opt->name != NULL; ++opt)
631                         if (match_option(name, opt, dowild))
632                                 return opt;
633                 for (list = extra_options; list != NULL; list = list->next)
634                         for (opt = list->options; opt->name != NULL; ++opt)
635                                 if (match_option(name, opt, dowild))
636                                         return opt;
637                 for (opt = the_channel->options; opt->name != NULL; ++opt)
638                         if (match_option(name, opt, dowild))
639                                 return opt;
640                 for (i = 0; protocols[i] != NULL; ++i)
641                         if ((opt = protocols[i]->options) != NULL)
642                                 for (; opt->name != NULL; ++opt)
643                                         if (match_option(name, opt, dowild))
644                                                 return opt;
645         }
646         return NULL;
647 }
648
649 /*
650  * process_option - process one new-style option.
651  */
652 static int
653 process_option(opt, cmd, argv)
654     option_t *opt;
655     char *cmd;
656     char **argv;
657 {
658     u_int32_t v;
659     int iv, a;
660     char *sv;
661     int (*parser) __P((char **));
662     int (*wildp) __P((char *, char **, int));
663     char *optopt = (opt->type == o_wild)? "": " option";
664     int prio = option_priority;
665     option_t *mainopt = opt;
666
667     current_option = opt->name;
668     if ((opt->flags & OPT_PRIVFIX) && privileged_option)
669         prio += OPRIO_ROOT;
670     while (mainopt->flags & OPT_PRIOSUB)
671         --mainopt;
672     if (mainopt->flags & OPT_PRIO) {
673         if (prio < mainopt->priority) {
674             /* new value doesn't override old */
675             if (prio == OPRIO_CMDLINE && mainopt->priority > OPRIO_ROOT) {
676                 option_error("%s%s set in %s cannot be overridden\n",
677                              opt->name, optopt, mainopt->source);
678                 return 0;
679             }
680             return 1;
681         }
682         if (prio > OPRIO_ROOT && mainopt->priority == OPRIO_CMDLINE)
683             warn("%s%s from %s overrides command line",
684                  opt->name, optopt, option_source);
685     }
686
687     if ((opt->flags & OPT_INITONLY) && phase != PHASE_INITIALIZE) {
688         option_error("%s%s cannot be changed after initialization",
689                      opt->name, optopt);
690         return 0;
691     }
692     if ((opt->flags & OPT_PRIV) && !privileged_option) {
693         option_error("using the %s%s requires root privilege",
694                      opt->name, optopt);
695         return 0;
696     }
697     if ((opt->flags & OPT_ENABLE) && *(bool *)(opt->addr2) == 0) {
698         option_error("%s%s is disabled", opt->name, optopt);
699         return 0;
700     }
701     if ((opt->flags & OPT_DEVEQUIV) && devnam_fixed) {
702         option_error("the %s%s may not be changed in %s",
703                      opt->name, optopt, option_source);
704         return 0;
705     }
706
707     switch (opt->type) {
708     case o_bool:
709         v = opt->flags & OPT_VALUE;
710         *(bool *)(opt->addr) = v;
711         if (opt->addr2 && (opt->flags & OPT_A2COPY))
712             *(bool *)(opt->addr2) = v;
713         else if (opt->addr2 && (opt->flags & OPT_A2CLR))
714             *(bool *)(opt->addr2) = 0;
715         else if (opt->addr2 && (opt->flags & OPT_A2CLRB))
716             *(u_char *)(opt->addr2) &= ~v;
717         else if (opt->addr2 && (opt->flags & OPT_A2OR))
718             *(u_char *)(opt->addr2) |= v;
719         break;
720
721     case o_int:
722         iv = 0;
723         if ((opt->flags & OPT_NOARG) == 0) {
724             if (!int_option(*argv, &iv))
725                 return 0;
726             if ((((opt->flags & OPT_LLIMIT) && iv < opt->lower_limit)
727                  || ((opt->flags & OPT_ULIMIT) && iv > opt->upper_limit))
728                 && !((opt->flags & OPT_ZEROOK && iv == 0))) {
729                 char *zok = (opt->flags & OPT_ZEROOK)? " zero or": "";
730                 switch (opt->flags & OPT_LIMITS) {
731                 case OPT_LLIMIT:
732                     option_error("%s value must be%s >= %d",
733                                  opt->name, zok, opt->lower_limit);
734                     break;
735                 case OPT_ULIMIT:
736                     option_error("%s value must be%s <= %d",
737                                  opt->name, zok, opt->upper_limit);
738                     break;
739                 case OPT_LIMITS:
740                     option_error("%s value must be%s between %d and %d",
741                                 opt->name, zok, opt->lower_limit, opt->upper_limit);
742                     break;
743                 }
744                 return 0;
745             }
746         }
747         a = opt->flags & OPT_VALUE;
748         if (a >= 128)
749             a -= 256;           /* sign extend */
750         iv += a;
751         if (opt->flags & OPT_INC)
752             iv += *(int *)(opt->addr);
753         if ((opt->flags & OPT_NOINCR) && !privileged_option) {
754             int oldv = *(int *)(opt->addr);
755             if ((opt->flags & OPT_ZEROINF) ?
756                 (oldv != 0 && (iv == 0 || iv > oldv)) : (iv > oldv)) {
757                 option_error("%s value cannot be increased", opt->name);
758                 return 0;
759             }
760         }
761         *(int *)(opt->addr) = iv;
762         if (opt->addr2 && (opt->flags & OPT_A2COPY))
763             *(int *)(opt->addr2) = iv;
764         break;
765
766     case o_uint32:
767         if (opt->flags & OPT_NOARG) {
768             v = opt->flags & OPT_VALUE;
769             if (v & 0x80)
770                     v |= 0xffffff00U;
771         } else if (!number_option(*argv, &v, 16))
772             return 0;
773         if (opt->flags & OPT_OR)
774             v |= *(u_int32_t *)(opt->addr);
775         *(u_int32_t *)(opt->addr) = v;
776         if (opt->addr2 && (opt->flags & OPT_A2COPY))
777             *(u_int32_t *)(opt->addr2) = v;
778         break;
779
780     case o_string:
781         if (opt->flags & OPT_STATIC) {
782             strlcpy((char *)(opt->addr), *argv, opt->upper_limit);
783         } else {
784             char **optptr = (char **)(opt->addr);
785             sv = strdup(*argv);
786             if (sv == NULL)
787                 novm("option argument");
788             if (*optptr)
789                 free(*optptr);
790             *optptr = sv;
791         }
792         break;
793
794     case o_special_noarg:
795     case o_special:
796         parser = (int (*) __P((char **))) opt->addr;
797         curopt = opt;
798         if (!(*parser)(argv))
799             return 0;
800         if (opt->flags & OPT_A2LIST) {
801             struct option_value *ovp, *pp;
802
803             ovp = malloc(sizeof(*ovp) + strlen(*argv));
804             if (ovp != 0) {
805                 strcpy(ovp->value, *argv);
806                 ovp->source = option_source;
807                 ovp->next = NULL;
808                 if (opt->addr2 == NULL) {
809                     opt->addr2 = ovp;
810                 } else {
811                     for (pp = opt->addr2; pp->next != NULL; pp = pp->next)
812                         ;
813                     pp->next = ovp;
814                 }
815             }
816         }
817         break;
818
819     case o_wild:
820         wildp = (int (*) __P((char *, char **, int))) opt->addr;
821         if (!(*wildp)(cmd, argv, 1))
822             return 0;
823         break;
824     }
825
826     /*
827      * If addr2 wasn't used by any flag (OPT_A2COPY, etc.) but is set,
828      * treat it as a bool and set/clear it based on the OPT_A2CLR bit.
829      */
830     if (opt->addr2 && (opt->flags & (OPT_A2COPY|OPT_ENABLE
831                 |OPT_A2PRINTER|OPT_A2STRVAL|OPT_A2LIST|OPT_A2OR)) == 0)
832         *(bool *)(opt->addr2) = !(opt->flags & OPT_A2CLR);
833
834     mainopt->source = option_source;
835     mainopt->priority = prio;
836     mainopt->winner = opt - mainopt;
837
838     return 1;
839 }
840
841 /*
842  * override_value - if the option priorities would permit us to
843  * override the value of option, return 1 and update the priority
844  * and source of the option value.  Otherwise returns 0.
845  */
846 int
847 override_value(option, priority, source)
848     const char *option;
849     int priority;
850     const char *source;
851 {
852         option_t *opt;
853
854         opt = find_option(option);
855         if (opt == NULL)
856                 return 0;
857         while (opt->flags & OPT_PRIOSUB)
858                 --opt;
859         if ((opt->flags & OPT_PRIO) && priority < opt->priority)
860                 return 0;
861         opt->priority = priority;
862         opt->source = source;
863         opt->winner = -1;
864         return 1;
865 }
866
867 /*
868  * n_arguments - tell how many arguments an option takes
869  */
870 static int
871 n_arguments(opt)
872     option_t *opt;
873 {
874         return (opt->type == o_bool || opt->type == o_special_noarg
875                 || (opt->flags & OPT_NOARG))? 0: 1;
876 }
877
878 /*
879  * add_options - add a list of options to the set we grok.
880  */
881 void
882 add_options(opt)
883     option_t *opt;
884 {
885     struct option_list *list;
886
887     list = malloc(sizeof(*list));
888     if (list == 0)
889         novm("option list entry");
890     list->options = opt;
891     list->next = extra_options;
892     extra_options = list;
893 }
894
895 /*
896  * check_options - check that options are valid and consistent.
897  */
898 void
899 check_options()
900 {
901         if (logfile_fd >= 0 && logfile_fd != log_to_fd)
902                 close(logfile_fd);
903 }
904
905 /*
906  * print_option - print out an option and its value
907  */
908 static void
909 print_option(opt, mainopt, printer, arg)
910     option_t *opt, *mainopt;
911     printer_func printer;
912     void *arg;
913 {
914         int i, v;
915         char *p;
916
917         if (opt->flags & OPT_NOPRINT)
918                 return;
919         switch (opt->type) {
920         case o_bool:
921                 v = opt->flags & OPT_VALUE;
922                 if (*(bool *)opt->addr != v)
923                         /* this can happen legitimately, e.g. lock
924                            option turned off for default device */
925                         break;
926                 printer(arg, "%s", opt->name);
927                 break;
928         case o_int:
929                 v = opt->flags & OPT_VALUE;
930                 if (v >= 128)
931                         v -= 256;
932                 i = *(int *)opt->addr;
933                 if (opt->flags & OPT_NOARG) {
934                         printer(arg, "%s", opt->name);
935                         if (i != v) {
936                                 if (opt->flags & OPT_INC) {
937                                         for (; i > v; i -= v)
938                                                 printer(arg, " %s", opt->name);
939                                 } else
940                                         printer(arg, " # oops: %d not %d\n",
941                                                 i, v);
942                         }
943                 } else {
944                         printer(arg, "%s %d", opt->name, i);
945                 }
946                 break;
947         case o_uint32:
948                 printer(arg, "%s", opt->name);
949                 if ((opt->flags & OPT_NOARG) == 0)
950                         printer(arg, " %x", *(u_int32_t *)opt->addr);
951                 break;
952
953         case o_string:
954                 if (opt->flags & OPT_HIDE) {
955                         p = "??????";
956                 } else {
957                         p = (char *) opt->addr;
958                         if ((opt->flags & OPT_STATIC) == 0)
959                                 p = *(char **)p;
960                 }
961                 printer(arg, "%s %q", opt->name, p);
962                 break;
963
964         case o_special:
965         case o_special_noarg:
966         case o_wild:
967                 if (opt->type != o_wild) {
968                         printer(arg, "%s", opt->name);
969                         if (n_arguments(opt) == 0)
970                                 break;
971                         printer(arg, " ");
972                 }
973                 if (opt->flags & OPT_A2PRINTER) {
974                         void (*oprt) __P((option_t *, printer_func, void *));
975                         oprt = (void (*) __P((option_t *, printer_func,
976                                          void *)))opt->addr2;
977                         (*oprt)(opt, printer, arg);
978                 } else if (opt->flags & OPT_A2STRVAL) {
979                         p = (char *) opt->addr2;
980                         if ((opt->flags & OPT_STATIC) == 0)
981                                 p = *(char **)p;
982                         printer("%q", p);
983                 } else if (opt->flags & OPT_A2LIST) {
984                         struct option_value *ovp;
985
986                         ovp = (struct option_value *) opt->addr2;
987                         for (;;) {
988                                 printer(arg, "%q", ovp->value);
989                                 if ((ovp = ovp->next) == NULL)
990                                         break;
991                                 printer(arg, "\t\t# (from %s)\n%s ",
992                                         ovp->source, opt->name);
993                         }
994                 } else {
995                         printer(arg, "xxx # [don't know how to print value]");
996                 }
997                 break;
998
999         default:
1000                 printer(arg, "# %s value (type %d\?\?)", opt->name, opt->type);
1001                 break;
1002         }
1003         printer(arg, "\t\t# (from %s)\n", mainopt->source);
1004 }
1005
1006 /*
1007  * print_option_list - print out options in effect from an
1008  * array of options.
1009  */
1010 static void
1011 print_option_list(opt, printer, arg)
1012     option_t *opt;
1013     printer_func printer;
1014     void *arg;
1015 {
1016         while (opt->name != NULL) {
1017                 if (opt->priority != OPRIO_DEFAULT
1018                     && opt->winner != (short int) -1)
1019                         print_option(opt + opt->winner, opt, printer, arg);
1020                 do {
1021                         ++opt;
1022                 } while (opt->flags & OPT_PRIOSUB);
1023         }
1024 }
1025
1026 /*
1027  * print_options - print out what options are in effect.
1028  */
1029 void
1030 print_options(printer, arg)
1031     printer_func printer;
1032     void *arg;
1033 {
1034         struct option_list *list;
1035         int i;
1036
1037         printer(arg, "pppd options in effect:\n");
1038         print_option_list(general_options, printer, arg);
1039         print_option_list(auth_options, printer, arg);
1040         for (list = extra_options; list != NULL; list = list->next)
1041                 print_option_list(list->options, printer, arg);
1042         print_option_list(the_channel->options, printer, arg);
1043         for (i = 0; protocols[i] != NULL; ++i)
1044                 print_option_list(protocols[i]->options, printer, arg);
1045 }
1046
1047 /*
1048  * usage - print out a message telling how to use the program.
1049  */
1050 static void
1051 usage()
1052 {
1053     if (phase == PHASE_INITIALIZE)
1054         fprintf(stderr, usage_string, VERSION, progname);
1055 }
1056
1057 /*
1058  * showhelp - print out usage message and exit.
1059  */
1060 static int
1061 showhelp(argv)
1062     char **argv;
1063 {
1064     if (phase == PHASE_INITIALIZE) {
1065         usage();
1066         exit(0);
1067     }
1068     return 0;
1069 }
1070
1071 /*
1072  * showversion - print out the version number and exit.
1073  */
1074 static int
1075 showversion(argv)
1076     char **argv;
1077 {
1078     if (phase == PHASE_INITIALIZE) {
1079         fprintf(stderr, "pppd version %s\n", VERSION);
1080         exit(0);
1081     }
1082     return 0;
1083 }
1084
1085 /*
1086  * option_error - print a message about an error in an option.
1087  * The message is logged, and also sent to
1088  * stderr if phase == PHASE_INITIALIZE.
1089  */
1090 void
1091 option_error __V((char *fmt, ...))
1092 {
1093     va_list args;
1094     char buf[1024];
1095
1096 #if defined(__STDC__)
1097     va_start(args, fmt);
1098 #else
1099     char *fmt;
1100     va_start(args);
1101     fmt = va_arg(args, char *);
1102 #endif
1103     vslprintf(buf, sizeof(buf), fmt, args);
1104     va_end(args);
1105     if (phase == PHASE_INITIALIZE)
1106         fprintf(stderr, "%s: %s\n", progname, buf);
1107     syslog(LOG_ERR, "%s", buf);
1108 }
1109
1110 #if 0
1111 /*
1112  * readable - check if a file is readable by the real user.
1113  */
1114 int
1115 readable(fd)
1116     int fd;
1117 {
1118     uid_t uid;
1119     int i;
1120     struct stat sbuf;
1121
1122     uid = getuid();
1123     if (uid == 0)
1124         return 1;
1125     if (fstat(fd, &sbuf) != 0)
1126         return 0;
1127     if (sbuf.st_uid == uid)
1128         return sbuf.st_mode & S_IRUSR;
1129     if (sbuf.st_gid == getgid())
1130         return sbuf.st_mode & S_IRGRP;
1131     for (i = 0; i < ngroups; ++i)
1132         if (sbuf.st_gid == groups[i])
1133             return sbuf.st_mode & S_IRGRP;
1134     return sbuf.st_mode & S_IROTH;
1135 }
1136 #endif
1137
1138 /*
1139  * Read a word from a file.
1140  * Words are delimited by white-space or by quotes (" or ').
1141  * Quotes, white-space and \ may be escaped with \.
1142  * \<newline> is ignored.
1143  */
1144 int
1145 getword(f, word, newlinep, filename)
1146     FILE *f;
1147     char *word;
1148     int *newlinep;
1149     char *filename;
1150 {
1151     int c, len, escape;
1152     int quoted, comment;
1153     int value, digit, got, n;
1154
1155 #define isoctal(c) ((c) >= '0' && (c) < '8')
1156
1157     *newlinep = 0;
1158     len = 0;
1159     escape = 0;
1160     comment = 0;
1161     quoted = 0;
1162
1163     /*
1164      * First skip white-space and comments.
1165      */
1166     for (;;) {
1167         c = getc(f);
1168         if (c == EOF)
1169             break;
1170
1171         /*
1172          * A newline means the end of a comment; backslash-newline
1173          * is ignored.  Note that we cannot have escape && comment.
1174          */
1175         if (c == '\n') {
1176             if (!escape) {
1177                 *newlinep = 1;
1178                 comment = 0;
1179             } else
1180                 escape = 0;
1181             continue;
1182         }
1183
1184         /*
1185          * Ignore characters other than newline in a comment.
1186          */
1187         if (comment)
1188             continue;
1189
1190         /*
1191          * If this character is escaped, we have a word start.
1192          */
1193         if (escape)
1194             break;
1195
1196         /*
1197          * If this is the escape character, look at the next character.
1198          */
1199         if (c == '\\') {
1200             escape = 1;
1201             continue;
1202         }
1203
1204         /*
1205          * If this is the start of a comment, ignore the rest of the line.
1206          */
1207         if (c == '#') {
1208             comment = 1;
1209             continue;
1210         }
1211
1212         /*
1213          * A non-whitespace character is the start of a word.
1214          */
1215         if (!isspace(c))
1216             break;
1217     }
1218
1219     /*
1220      * Process characters until the end of the word.
1221      */
1222     while (c != EOF) {
1223         if (escape) {
1224             /*
1225              * This character is escaped: backslash-newline is ignored,
1226              * various other characters indicate particular values
1227              * as for C backslash-escapes.
1228              */
1229             escape = 0;
1230             if (c == '\n') {
1231                 c = getc(f);
1232                 continue;
1233             }
1234
1235             got = 0;
1236             switch (c) {
1237             case 'a':
1238                 value = '\a';
1239                 break;
1240             case 'b':
1241                 value = '\b';
1242                 break;
1243             case 'f':
1244                 value = '\f';
1245                 break;
1246             case 'n':
1247                 value = '\n';
1248                 break;
1249             case 'r':
1250                 value = '\r';
1251                 break;
1252             case 's':
1253                 value = ' ';
1254                 break;
1255             case 't':
1256                 value = '\t';
1257                 break;
1258
1259             default:
1260                 if (isoctal(c)) {
1261                     /*
1262                      * \ddd octal sequence
1263                      */
1264                     value = 0;
1265                     for (n = 0; n < 3 && isoctal(c); ++n) {
1266                         value = (value << 3) + (c & 07);
1267                         c = getc(f);
1268                     }
1269                     got = 1;
1270                     break;
1271                 }
1272
1273                 if (c == 'x') {
1274                     /*
1275                      * \x<hex_string> sequence
1276                      */
1277                     value = 0;
1278                     c = getc(f);
1279                     for (n = 0; n < 2 && isxdigit(c); ++n) {
1280                         digit = toupper(c) - '0';
1281                         if (digit > 10)
1282                             digit += '0' + 10 - 'A';
1283                         value = (value << 4) + digit;
1284                         c = getc (f);
1285                     }
1286                     got = 1;
1287                     break;
1288                 }
1289
1290                 /*
1291                  * Otherwise the character stands for itself.
1292                  */
1293                 value = c;
1294                 break;
1295             }
1296
1297             /*
1298              * Store the resulting character for the escape sequence.
1299              */
1300             if (len < MAXWORDLEN) {
1301                 word[len] = value;
1302                 ++len;
1303             }
1304
1305             if (!got)
1306                 c = getc(f);
1307             continue;
1308         }
1309
1310         /*
1311          * Backslash starts a new escape sequence.
1312          */
1313         if (c == '\\') {
1314             escape = 1;
1315             c = getc(f);
1316             continue;
1317         }
1318
1319         /*
1320          * Not escaped: check for the start or end of a quoted
1321          * section and see if we've reached the end of the word.
1322          */
1323         if (quoted) {
1324             if (c == quoted) {
1325                 quoted = 0;
1326                 c = getc(f);
1327                 continue;
1328             }
1329         } else if (c == '"' || c == '\'') {
1330             quoted = c;
1331             c = getc(f);
1332             continue;
1333         } else if (isspace(c) || c == '#') {
1334             ungetc (c, f);
1335             break;
1336         }
1337
1338         /*
1339          * An ordinary character: store it in the word and get another.
1340          */
1341         if (len < MAXWORDLEN) {
1342             word[len] = c;
1343             ++len;
1344         }
1345
1346         c = getc(f);
1347     }
1348
1349     /*
1350      * End of the word: check for errors.
1351      */
1352     if (c == EOF) {
1353         if (ferror(f)) {
1354             if (errno == 0)
1355                 errno = EIO;
1356             option_error("Error reading %s: %m", filename);
1357             die(1);
1358         }
1359         /*
1360          * If len is zero, then we didn't find a word before the
1361          * end of the file.
1362          */
1363         if (len == 0)
1364             return 0;
1365         if (quoted)
1366             option_error("warning: quoted word runs to end of file (%.20s...)",
1367                          filename, word);
1368     }
1369
1370     /*
1371      * Warn if the word was too long, and append a terminating null.
1372      */
1373     if (len >= MAXWORDLEN) {
1374         option_error("warning: word in file %s too long (%.20s...)",
1375                      filename, word);
1376         len = MAXWORDLEN - 1;
1377     }
1378     word[len] = 0;
1379
1380     return 1;
1381
1382 #undef isoctal
1383
1384 }
1385
1386 /*
1387  * number_option - parse an unsigned numeric parameter for an option.
1388  */
1389 static int
1390 number_option(str, valp, base)
1391     char *str;
1392     u_int32_t *valp;
1393     int base;
1394 {
1395     char *ptr;
1396
1397     *valp = strtoul(str, &ptr, base);
1398     if (ptr == str) {
1399         option_error("invalid numeric parameter '%s' for %s option",
1400                      str, current_option);
1401         return 0;
1402     }
1403     return 1;
1404 }
1405
1406
1407 /*
1408  * int_option - like number_option, but valp is int *,
1409  * the base is assumed to be 0, and *valp is not changed
1410  * if there is an error.
1411  */
1412 int
1413 int_option(str, valp)
1414     char *str;
1415     int *valp;
1416 {
1417     u_int32_t v;
1418
1419     if (!number_option(str, &v, 0))
1420         return 0;
1421     *valp = (int) v;
1422     return 1;
1423 }
1424
1425
1426 /*
1427  * The following procedures parse options.
1428  */
1429
1430 /*
1431  * readfile - take commands from a file.
1432  */
1433 static int
1434 readfile(argv)
1435     char **argv;
1436 {
1437     return options_from_file(*argv, 1, 1, privileged_option);
1438 }
1439
1440 /*
1441  * callfile - take commands from /etc/ppp/peers/<name>.
1442  * Name may not contain /../, start with / or ../, or end in /..
1443  */
1444 static int
1445 callfile(argv)
1446     char **argv;
1447 {
1448     char *fname, *arg, *p;
1449     int l, ok;
1450
1451     arg = *argv;
1452     ok = 1;
1453     if (arg[0] == '/' || arg[0] == 0)
1454         ok = 0;
1455     else {
1456         for (p = arg; *p != 0; ) {
1457             if (p[0] == '.' && p[1] == '.' && (p[2] == '/' || p[2] == 0)) {
1458                 ok = 0;
1459                 break;
1460             }
1461             while (*p != '/' && *p != 0)
1462                 ++p;
1463             if (*p == '/')
1464                 ++p;
1465         }
1466     }
1467     if (!ok) {
1468         option_error("call option value may not contain .. or start with /");
1469         return 0;
1470     }
1471
1472     l = strlen(arg) + strlen(_PATH_PEERFILES) + 1;
1473     if ((fname = (char *) malloc(l)) == NULL)
1474         novm("call file name");
1475     slprintf(fname, l, "%s%s", _PATH_PEERFILES, arg);
1476
1477     ok = options_from_file(fname, 1, 1, 1);
1478
1479     free(fname);
1480     return ok;
1481 }
1482
1483 #ifdef PPP_FILTER
1484 /*
1485  * setpassfilter - Set the pass filter for packets
1486  */
1487 static int
1488 setpassfilter(argv)
1489     char **argv;
1490 {
1491     pcap_t *pc;
1492     int ret = 1;
1493
1494     pc = pcap_open_dead(DLT_PPP_PPPD, 65535);
1495     if (pcap_compile(pc, &pass_filter, *argv, 1, netmask) == -1) {
1496         option_error("error in pass-filter expression: %s\n",
1497                      pcap_geterr(pc));
1498         ret = 0;
1499     }
1500     pcap_close(pc);
1501
1502     return ret;
1503 }
1504
1505 /*
1506  * setactivefilter - Set the active filter for packets
1507  */
1508 static int
1509 setactivefilter(argv)
1510     char **argv;
1511 {
1512     pcap_t *pc;
1513     int ret = 1;
1514
1515     pc = pcap_open_dead(DLT_PPP_PPPD, 65535);
1516     if (pcap_compile(pc, &active_filter, *argv, 1, netmask) == -1) {
1517         option_error("error in active-filter expression: %s\n",
1518                      pcap_geterr(pc));
1519         ret = 0;
1520     }
1521     pcap_close(pc);
1522
1523     return ret;
1524 }
1525 #endif
1526
1527 /*
1528  * setdomain - Set domain name to append to hostname 
1529  */
1530 static int
1531 setdomain(argv)
1532     char **argv;
1533 {
1534     gethostname(hostname, MAXNAMELEN);
1535     if (**argv != 0) {
1536         if (**argv != '.')
1537             strncat(hostname, ".", MAXNAMELEN - strlen(hostname));
1538         domain = hostname + strlen(hostname);
1539         strncat(hostname, *argv, MAXNAMELEN - strlen(hostname));
1540     }
1541     hostname[MAXNAMELEN-1] = 0;
1542     return (1);
1543 }
1544
1545 static int
1546 setlogfile(argv)
1547     char **argv;
1548 {
1549     int fd, err;
1550     uid_t euid;
1551
1552     euid = geteuid();
1553     if (!privileged_option && seteuid(getuid()) == -1) {
1554         option_error("unable to drop permissions to open %s: %m", *argv);
1555         return 0;
1556     }
1557     fd = open(*argv, O_WRONLY | O_APPEND | O_CREAT | O_EXCL, 0644);
1558     if (fd < 0 && errno == EEXIST)
1559         fd = open(*argv, O_WRONLY | O_APPEND);
1560     err = errno;
1561     if (!privileged_option && seteuid(euid) == -1)
1562         fatal("unable to regain privileges: %m");
1563     if (fd < 0) {
1564         errno = err;
1565         option_error("Can't open log file %s: %m", *argv);
1566         return 0;
1567     }
1568     strlcpy(logfile_name, *argv, sizeof(logfile_name));
1569     if (logfile_fd >= 0)
1570         close(logfile_fd);
1571     logfile_fd = fd;
1572     log_to_fd = fd;
1573     log_default = 0;
1574     return 1;
1575 }
1576
1577 #ifdef MAXOCTETS
1578 static int
1579 setmodir(argv)
1580     char **argv;
1581 {
1582     if(*argv == NULL)
1583         return 0;
1584     if(!strcmp(*argv,"in")) {
1585         maxoctets_dir = PPP_OCTETS_DIRECTION_IN;
1586     } else if (!strcmp(*argv,"out")) {
1587         maxoctets_dir = PPP_OCTETS_DIRECTION_OUT;
1588     } else if (!strcmp(*argv,"max")) {
1589         maxoctets_dir = PPP_OCTETS_DIRECTION_MAXOVERAL;
1590     } else {
1591         maxoctets_dir = PPP_OCTETS_DIRECTION_SUM;
1592     }
1593     return 1;
1594 }
1595 #endif
1596
1597 #ifdef PLUGIN
1598 static int
1599 loadplugin(argv)
1600     char **argv;
1601 {
1602     char *arg = *argv;
1603     void *handle;
1604     const char *err;
1605     void (*init) __P((void));
1606     char *path = arg;
1607     const char *vers;
1608
1609     if (strchr(arg, '/') == 0) {
1610         const char *base = _PATH_PLUGIN;
1611         int l = strlen(base) + strlen(arg) + 2;
1612         path = malloc(l);
1613         if (path == 0)
1614             novm("plugin file path");
1615         strlcpy(path, base, l);
1616         strlcat(path, "/", l);
1617         strlcat(path, arg, l);
1618     }
1619     handle = dlopen(path, RTLD_GLOBAL | RTLD_NOW);
1620     if (handle == 0) {
1621         err = dlerror();
1622         if (err != 0)
1623             option_error("%s", err);
1624         option_error("Couldn't load plugin %s", arg);
1625         goto err;
1626     }
1627     init = (void (*)(void))dlsym(handle, "plugin_init");
1628     if (init == 0) {
1629         option_error("%s has no initialization entry point", arg);
1630         goto errclose;
1631     }
1632     vers = (const char *) dlsym(handle, "pppd_version");
1633     if (vers == 0) {
1634         warn("Warning: plugin %s has no version information", arg);
1635     } else if (strcmp(vers, VERSION) != 0) {
1636         option_error("Plugin %s is for pppd version %s, this is %s",
1637                      arg, vers, VERSION);
1638         goto errclose;
1639     }
1640     info("Plugin %s loaded.", arg);
1641     (*init)();
1642     return 1;
1643
1644  errclose:
1645     dlclose(handle);
1646  err:
1647     if (path != arg)
1648         free(path);
1649     return 0;
1650 }
1651 #endif /* PLUGIN */
1652
1653 /*
1654  * Set an environment variable specified by the user.
1655  */
1656 static int
1657 user_setenv(argv)
1658     char **argv;
1659 {
1660     char *arg = argv[0];
1661     char *eqp;
1662     struct userenv *uep, **insp;
1663
1664     if ((eqp = strchr(arg, '=')) == NULL) {
1665         option_error("missing = in name=value: %s", arg);
1666         return 0;
1667     }
1668     if (eqp == arg) {
1669         option_error("missing variable name: %s", arg);
1670         return 0;
1671     }
1672     for (uep = userenv_list; uep != NULL; uep = uep->ue_next) {
1673         int nlen = strlen(uep->ue_name);
1674         if (nlen == (eqp - arg) &&
1675             strncmp(arg, uep->ue_name, nlen) == 0)
1676             break;
1677     }
1678     /* Ignore attempts by unprivileged users to override privileged sources */
1679     if (uep != NULL && !privileged_option && uep->ue_priv)
1680         return 1;
1681     /* The name never changes, so allocate it with the structure */
1682     if (uep == NULL) {
1683         uep = malloc(sizeof (*uep) + (eqp-arg));
1684         strncpy(uep->ue_name, arg, eqp-arg);
1685         uep->ue_name[eqp-arg] = '\0';
1686         uep->ue_next = NULL;
1687         insp = &userenv_list;
1688         while (*insp != NULL)
1689             insp = &(*insp)->ue_next;
1690         *insp = uep;
1691     } else {
1692         struct userenv *uep2;
1693         for (uep2 = userenv_list; uep2 != NULL; uep2 = uep2->ue_next) {
1694             if (uep2 != uep && !uep2->ue_isset)
1695                 break;
1696         }
1697         if (uep2 == NULL && !uep->ue_isset)
1698             find_option("unset")->flags |= OPT_NOPRINT;
1699         free(uep->ue_value);
1700     }
1701     uep->ue_isset = 1;
1702     uep->ue_priv = privileged_option;
1703     uep->ue_source = option_source;
1704     uep->ue_value = strdup(eqp + 1);
1705     curopt->flags &= ~OPT_NOPRINT;
1706     return 1;
1707 }
1708
1709 static void
1710 user_setprint(opt, printer, arg)
1711     option_t *opt;
1712     printer_func printer;
1713     void *arg;
1714 {
1715     struct userenv *uep, *uepnext;
1716
1717     uepnext = userenv_list;
1718     while (uepnext != NULL && !uepnext->ue_isset)
1719         uepnext = uepnext->ue_next;
1720     while ((uep = uepnext) != NULL) {
1721         uepnext = uep->ue_next;
1722         while (uepnext != NULL && !uepnext->ue_isset)
1723             uepnext = uepnext->ue_next;
1724         (*printer)(arg, "%s=%s", uep->ue_name, uep->ue_value);
1725         if (uepnext != NULL)
1726             (*printer)(arg, "\t\t# (from %s)\n%s ", uep->ue_source, opt->name);
1727         else
1728             opt->source = uep->ue_source;
1729     }
1730 }
1731
1732 static int
1733 user_unsetenv(argv)
1734     char **argv;
1735 {
1736     struct userenv *uep, **insp;
1737     char *arg = argv[0];
1738
1739     if (strchr(arg, '=') != NULL) {
1740         option_error("unexpected = in name: %s", arg);
1741         return 0;
1742     }
1743     if (arg == '\0') {
1744         option_error("missing variable name for unset");
1745         return 0;
1746     }
1747     for (uep = userenv_list; uep != NULL; uep = uep->ue_next) {
1748         if (strcmp(arg, uep->ue_name) == 0)
1749             break;
1750     }
1751     /* Ignore attempts by unprivileged users to override privileged sources */
1752     if (uep != NULL && !privileged_option && uep->ue_priv)
1753         return 1;
1754     /* The name never changes, so allocate it with the structure */
1755     if (uep == NULL) {
1756         uep = malloc(sizeof (*uep) + strlen(arg));
1757         strcpy(uep->ue_name, arg);
1758         uep->ue_next = NULL;
1759         insp = &userenv_list;
1760         while (*insp != NULL)
1761             insp = &(*insp)->ue_next;
1762         *insp = uep;
1763     } else {
1764         struct userenv *uep2;
1765         for (uep2 = userenv_list; uep2 != NULL; uep2 = uep2->ue_next) {
1766             if (uep2 != uep && uep2->ue_isset)
1767                 break;
1768         }
1769         if (uep2 == NULL && uep->ue_isset)
1770             find_option("set")->flags |= OPT_NOPRINT;
1771         free(uep->ue_value);
1772     }
1773     uep->ue_isset = 0;
1774     uep->ue_priv = privileged_option;
1775     uep->ue_source = option_source;
1776     uep->ue_value = NULL;
1777     curopt->flags &= ~OPT_NOPRINT;
1778     return 1;
1779 }
1780
1781 static void
1782 user_unsetprint(opt, printer, arg)
1783     option_t *opt;
1784     printer_func printer;
1785     void *arg;
1786 {
1787     struct userenv *uep, *uepnext;
1788
1789     uepnext = userenv_list;
1790     while (uepnext != NULL && uepnext->ue_isset)
1791         uepnext = uepnext->ue_next;
1792     while ((uep = uepnext) != NULL) {
1793         uepnext = uep->ue_next;
1794         while (uepnext != NULL && uepnext->ue_isset)
1795             uepnext = uepnext->ue_next;
1796         (*printer)(arg, "%s", uep->ue_name);
1797         if (uepnext != NULL)
1798             (*printer)(arg, "\t\t# (from %s)\n%s ", uep->ue_source, opt->name);
1799         else
1800             opt->source = uep->ue_source;
1801     }
1802 }