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