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