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