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