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