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