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