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