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