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