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