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