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