]> git.ozlabs.org Git - ppp.git/blob - pppd/options.c
use strlcpy, strlcat, slprintf everywhere
[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.51 1999/03/12 06:07:19 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 /*
64  * Option variables and default values.
65  */
66 #ifdef PPP_FILTER
67 int     dflag = 0;              /* Tell libpcap we want debugging */
68 #endif
69 int     debug = 0;              /* Debug flag */
70 int     kdebugflag = 0;         /* Tell kernel to print debug messages */
71 int     default_device = 1;     /* Using /dev/tty or equivalent */
72 char    devnam[MAXPATHLEN] = "/dev/tty";        /* Device name */
73 int     crtscts = 0;            /* Use hardware flow control */
74 bool    modem = 1;              /* Use modem control lines */
75 int     inspeed = 0;            /* Input/Output speed requested */
76 u_int32_t netmask = 0;          /* IP netmask to set on interface */
77 bool    lockflag = 0;           /* Create lock file to lock the serial dev */
78 bool    nodetach = 0;           /* Don't detach from controlling tty */
79 bool    updetach = 0;           /* Detach once link is up */
80 char    *connector = NULL;      /* Script to establish physical link */
81 char    *disconnector = NULL;   /* Script to disestablish physical link */
82 char    *welcomer = NULL;       /* Script to run after phys link estab. */
83 int     maxconnect = 0;         /* Maximum connect time */
84 char    user[MAXNAMELEN];       /* Username for PAP */
85 char    passwd[MAXSECRETLEN];   /* Password for PAP */
86 bool    persist = 0;            /* Reopen link after it goes down */
87 char    our_name[MAXNAMELEN];   /* Our name for authentication purposes */
88 char    remote_name[MAXNAMELEN]; /* Peer's name for authentication */
89 int     explicit_remote = 0;    /* User specified explicit remote name */
90 bool    demand = 0;             /* do dial-on-demand */
91 char    *ipparam = NULL;        /* Extra parameter for ip up/down scripts */
92 int     idle_time_limit = 0;    /* Disconnect if idle for this many seconds */
93 int     holdoff = 30;           /* # seconds to pause before reconnecting */
94
95 extern option_t auth_options[];
96
97 struct option_info connector_info;
98 struct option_info disconnector_info;
99 struct option_info welcomer_info;
100 struct option_info devnam_info;
101
102 #ifdef PPP_FILTER
103 struct  bpf_program pass_filter;/* Filter program for packets to pass */
104 struct  bpf_program active_filter; /* Filter program for link-active pkts */
105 pcap_t  pc;                     /* Fake struct pcap so we can compile expr */
106 #endif
107
108 /*
109  * Prototypes
110  */
111 static int setdevname __P((char *, int));
112 static int setipaddr __P((char *));
113 static int setspeed __P((char *));
114 static int noopt __P((char **));
115 static int setdomain __P((char **));
116 static int setnetmask __P((char **));
117 static int setxonxoff __P((char **));
118 static int readfile __P((char **));
119 static int callfile __P((char **));
120 static int showversion __P((char **));
121 static int showhelp __P((char **));
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
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     { "maxconnect", o_int, &maxconnect,
167       "Set connection time limit", OPT_LLIMIT|OPT_NOINCR|OPT_ZEROINF },
168     { "crtscts", o_int, &crtscts,
169       "Set hardware (RTS/CTS) flow control", OPT_NOARG|OPT_VAL(1) },
170     { "nocrtscts", o_int, &crtscts,
171       "Disable hardware flow control", OPT_NOARG|OPT_VAL(-1) },
172     { "-crtscts", o_int, &crtscts,
173       "Disable hardware flow control", OPT_NOARG|OPT_VAL(-1) },
174     { "cdtrcts", o_int, &crtscts,
175       "Set alternate hardware (DTR/CTS) flow control", OPT_NOARG|OPT_VAL(2) },
176     { "nocdtrcts", o_int, &crtscts,
177       "Disable hardware flow control", OPT_NOARG|OPT_VAL(-1) },
178     { "xonxoff", o_special_noarg, setxonxoff,
179       "Set software (XON/XOFF) flow control" },
180     { "domain", o_special, setdomain,
181       "Add given domain name to hostname" },
182     { "mtu", o_int, &lcp_allowoptions[0].mru,
183       "Set our MTU", OPT_LIMITS, NULL, MAXMRU, MINMRU },
184     { "netmask", o_special, setnetmask,
185       "set netmask" },
186     { "modem", o_bool, &modem,
187       "Use modem control lines", 1 },
188     { "local", o_bool, &modem,
189       "Don't use modem control lines" },
190     { "file", o_special, readfile,
191       "Take options from a file" },
192     { "call", o_special, callfile,
193       "Take options from a privileged file" },
194     { "persist", o_bool, &persist,
195       "Keep on reopening connection after close", 1 },
196     { "nopersist", o_bool, &persist,
197       "Turn off persist option" },
198     { "demand", o_bool, &demand,
199       "Dial on demand", 1, &persist },
200     { "--version", o_special_noarg, showversion,
201       "Show version number" },
202     { "--help", o_special_noarg, showhelp,
203       "Show brief listing of options" },
204     { "-h", o_special_noarg, showhelp,
205       "Show brief listing of options" },
206
207 #ifdef PPP_FILTER
208     { "pdebug", o_int, &dflag,
209       "libpcap debugging" },
210     { "pass-filter", 1, setpassfilter,
211       "set filter for packets to pass" },
212     { "active-filter", 1, setactivefilter,
213       "set filter for active pkts" },
214 #endif
215
216     { NULL }
217 };
218
219 #ifndef IMPLEMENTATION
220 #define IMPLEMENTATION ""
221 #endif
222
223 static char *usage_string = "\
224 pppd version %s.%d%s\n\
225 Usage: %s [ options ], where options are:\n\
226         <device>        Communicate over the named device\n\
227         <speed>         Set the baud rate to <speed>\n\
228         <loc>:<rem>     Set the local and/or remote interface IP\n\
229                         addresses.  Either one may be omitted.\n\
230         asyncmap <n>    Set the desired async map to hex <n>\n\
231         auth            Require authentication from peer\n\
232         connect <p>     Invoke shell command <p> to set up the serial line\n\
233         crtscts         Use hardware RTS/CTS flow control\n\
234         defaultroute    Add default route through interface\n\
235         file <f>        Take options from file <f>\n\
236         modem           Use modem control lines\n\
237         mru <n>         Set MRU value to <n> for negotiation\n\
238 See pppd(8) for more options.\n\
239 ";
240
241 /*
242  * parse_args - parse a string of arguments from the command line.
243  */
244 int
245 parse_args(argc, argv)
246     int argc;
247     char **argv;
248 {
249     char *arg;
250     option_t *opt;
251     int ret;
252
253     privileged_option = privileged;
254     option_source = "command line";
255     while (argc > 0) {
256         arg = *argv++;
257         --argc;
258
259         /*
260          * First see if it's an option in the new option list.
261          */
262         opt = find_option(arg);
263         if (opt != NULL) {
264             int n = n_arguments(opt);
265             if (argc < n) {
266                 option_error("too few parameters for option %s", arg);
267                 return 0;
268             }
269             current_option = arg;
270             if (!process_option(opt, argv))
271                 return 0;
272             argc -= n;
273             argv += n;
274             continue;
275         }
276
277         /*
278          * Maybe a tty name, speed or IP address?
279          */
280         if ((ret = setdevname(arg, 0)) == 0
281             && (ret = setspeed(arg)) == 0
282             && (ret = setipaddr(arg)) == 0) {
283             option_error("unrecognized option '%s'", arg);
284             usage();
285             return 0;
286         }
287         if (ret < 0)    /* error */
288             return 0;
289     }
290     return 1;
291 }
292
293 /*
294  * scan_args - scan the command line arguments to get the tty name,
295  * if specified.
296  */
297 void
298 scan_args(argc, argv)
299     int argc;
300     char **argv;
301 {
302     char *arg;
303     option_t *opt;
304
305     privileged_option = privileged;
306     while (argc > 0) {
307         arg = *argv++;
308         --argc;
309
310         /* Skip options and their arguments */
311         opt = find_option(arg);
312         if (opt != NULL) {
313             int n = n_arguments(opt);
314             argc -= n;
315             argv += n;
316             continue;
317         }
318
319         /* Check if it's a tty name and copy it if so */
320         (void) setdevname(arg, 1);
321     }
322 }
323
324 /*
325  * options_from_file - Read a string of options from a file,
326  * and interpret them.
327  */
328 int
329 options_from_file(filename, must_exist, check_prot, priv)
330     char *filename;
331     int must_exist;
332     int check_prot;
333     int priv;
334 {
335     FILE *f;
336     int i, newline, ret;
337     option_t *opt;
338     int oldpriv;
339     char *oldsource;
340     char *argv[MAXARGS];
341     char args[MAXARGS][MAXWORDLEN];
342     char cmd[MAXWORDLEN];
343
344     if (check_prot)
345         seteuid(getuid());
346     f = fopen(filename, "r");
347     if (check_prot)
348         seteuid(0);
349     if (f == NULL) {
350         if (!must_exist && errno == ENOENT)
351             return 1;
352         option_error("Can't open options file %s: %m", filename);
353         return 0;
354     }
355 #if 0   /* check done by setting effective UID above */
356     if (check_prot && !readable(fileno(f))) {
357         option_error("Can't open options file %s: access denied", filename);
358         fclose(f);
359         return 0;
360     }
361 #endif
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 (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), opt->upper_limit, *argv);
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 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 /*
698  * readable - check if a file is readable by the real user.
699  */
700 int
701 readable(fd)
702     int fd;
703 {
704     uid_t uid;
705     int i;
706     struct stat sbuf;
707
708     uid = getuid();
709     if (uid == 0)
710         return 1;
711     if (fstat(fd, &sbuf) != 0)
712         return 0;
713     if (sbuf.st_uid == uid)
714         return sbuf.st_mode & S_IRUSR;
715     if (sbuf.st_gid == getgid())
716         return sbuf.st_mode & S_IRGRP;
717     for (i = 0; i < ngroups; ++i)
718         if (sbuf.st_gid == groups[i])
719             return sbuf.st_mode & S_IRGRP;
720     return sbuf.st_mode & S_IROTH;
721 }
722
723 /*
724  * Read a word from a file.
725  * Words are delimited by white-space or by quotes (" or ').
726  * Quotes, white-space and \ may be escaped with \.
727  * \<newline> is ignored.
728  */
729 int
730 getword(f, word, newlinep, filename)
731     FILE *f;
732     char *word;
733     int *newlinep;
734     char *filename;
735 {
736     int c, len, escape;
737     int quoted, comment;
738     int value, digit, got, n;
739
740 #define isoctal(c) ((c) >= '0' && (c) < '8')
741
742     *newlinep = 0;
743     len = 0;
744     escape = 0;
745     comment = 0;
746
747     /*
748      * First skip white-space and comments.
749      */
750     for (;;) {
751         c = getc(f);
752         if (c == EOF)
753             break;
754
755         /*
756          * A newline means the end of a comment; backslash-newline
757          * is ignored.  Note that we cannot have escape && comment.
758          */
759         if (c == '\n') {
760             if (!escape) {
761                 *newlinep = 1;
762                 comment = 0;
763             } else
764                 escape = 0;
765             continue;
766         }
767
768         /*
769          * Ignore characters other than newline in a comment.
770          */
771         if (comment)
772             continue;
773
774         /*
775          * If this character is escaped, we have a word start.
776          */
777         if (escape)
778             break;
779
780         /*
781          * If this is the escape character, look at the next character.
782          */
783         if (c == '\\') {
784             escape = 1;
785             continue;
786         }
787
788         /*
789          * If this is the start of a comment, ignore the rest of the line.
790          */
791         if (c == '#') {
792             comment = 1;
793             continue;
794         }
795
796         /*
797          * A non-whitespace character is the start of a word.
798          */
799         if (!isspace(c))
800             break;
801     }
802
803     /*
804      * Save the delimiter for quoted strings.
805      */
806     if (!escape && (c == '"' || c == '\'')) {
807         quoted = c;
808         c = getc(f);
809     } else
810         quoted = 0;
811
812     /*
813      * Process characters until the end of the word.
814      */
815     while (c != EOF) {
816         if (escape) {
817             /*
818              * This character is escaped: backslash-newline is ignored,
819              * various other characters indicate particular values
820              * as for C backslash-escapes.
821              */
822             escape = 0;
823             if (c == '\n') {
824                 c = getc(f);
825                 continue;
826             }
827
828             got = 0;
829             switch (c) {
830             case 'a':
831                 value = '\a';
832                 break;
833             case 'b':
834                 value = '\b';
835                 break;
836             case 'f':
837                 value = '\f';
838                 break;
839             case 'n':
840                 value = '\n';
841                 break;
842             case 'r':
843                 value = '\r';
844                 break;
845             case 's':
846                 value = ' ';
847                 break;
848             case 't':
849                 value = '\t';
850                 break;
851
852             default:
853                 if (isoctal(c)) {
854                     /*
855                      * \ddd octal sequence
856                      */
857                     value = 0;
858                     for (n = 0; n < 3 && isoctal(c); ++n) {
859                         value = (value << 3) + (c & 07);
860                         c = getc(f);
861                     }
862                     got = 1;
863                     break;
864                 }
865
866                 if (c == 'x') {
867                     /*
868                      * \x<hex_string> sequence
869                      */
870                     value = 0;
871                     c = getc(f);
872                     for (n = 0; n < 2 && isxdigit(c); ++n) {
873                         digit = toupper(c) - '0';
874                         if (digit > 10)
875                             digit += '0' + 10 - 'A';
876                         value = (value << 4) + digit;
877                         c = getc (f);
878                     }
879                     got = 1;
880                     break;
881                 }
882
883                 /*
884                  * Otherwise the character stands for itself.
885                  */
886                 value = c;
887                 break;
888             }
889
890             /*
891              * Store the resulting character for the escape sequence.
892              */
893             if (len < MAXWORDLEN-1)
894                 word[len] = value;
895             ++len;
896
897             if (!got)
898                 c = getc(f);
899             continue;
900
901         }
902
903         /*
904          * Not escaped: see if we've reached the end of the word.
905          */
906         if (quoted) {
907             if (c == quoted)
908                 break;
909         } else {
910             if (isspace(c) || c == '#') {
911                 ungetc (c, f);
912                 break;
913             }
914         }
915
916         /*
917          * Backslash starts an escape sequence.
918          */
919         if (c == '\\') {
920             escape = 1;
921             c = getc(f);
922             continue;
923         }
924
925         /*
926          * An ordinary character: store it in the word and get another.
927          */
928         if (len < MAXWORDLEN-1)
929             word[len] = c;
930         ++len;
931
932         c = getc(f);
933     }
934
935     /*
936      * End of the word: check for errors.
937      */
938     if (c == EOF) {
939         if (ferror(f)) {
940             if (errno == 0)
941                 errno = EIO;
942             option_error("Error reading %s: %m", filename);
943             die(1);
944         }
945         /*
946          * If len is zero, then we didn't find a word before the
947          * end of the file.
948          */
949         if (len == 0)
950             return 0;
951     }
952
953     /*
954      * Warn if the word was too long, and append a terminating null.
955      */
956     if (len >= MAXWORDLEN) {
957         option_error("warning: word in file %s too long (%.20s...)",
958                      filename, word);
959         len = MAXWORDLEN - 1;
960     }
961     word[len] = 0;
962
963     return 1;
964
965 #undef isoctal
966
967 }
968
969 /*
970  * number_option - parse an unsigned numeric parameter for an option.
971  */
972 int
973 number_option(str, valp, base)
974     char *str;
975     u_int32_t *valp;
976     int base;
977 {
978     char *ptr;
979
980     *valp = strtoul(str, &ptr, base);
981     if (ptr == str) {
982         option_error("invalid numeric parameter '%s' for %s option",
983                      str, current_option);
984         return 0;
985     }
986     return 1;
987 }
988
989
990 /*
991  * int_option - like number_option, but valp is int *,
992  * the base is assumed to be 0, and *valp is not changed
993  * if there is an error.
994  */
995 int
996 int_option(str, valp)
997     char *str;
998     int *valp;
999 {
1000     u_int32_t v;
1001
1002     if (!number_option(str, &v, 0))
1003         return 0;
1004     *valp = (int) v;
1005     return 1;
1006 }
1007
1008
1009 /*
1010  * The following procedures parse options.
1011  */
1012
1013 /*
1014  * readfile - take commands from a file.
1015  */
1016 static int
1017 readfile(argv)
1018     char **argv;
1019 {
1020     return options_from_file(*argv, 1, 1, privileged_option);
1021 }
1022
1023 /*
1024  * callfile - take commands from /etc/ppp/peers/<name>.
1025  * Name may not contain /../, start with / or ../, or end in /..
1026  */
1027 static int
1028 callfile(argv)
1029     char **argv;
1030 {
1031     char *fname, *arg, *p;
1032     int l, ok;
1033
1034     arg = *argv;
1035     ok = 1;
1036     if (arg[0] == '/' || arg[0] == 0)
1037         ok = 0;
1038     else {
1039         for (p = arg; *p != 0; ) {
1040             if (p[0] == '.' && p[1] == '.' && (p[2] == '/' || p[2] == 0)) {
1041                 ok = 0;
1042                 break;
1043             }
1044             while (*p != '/' && *p != 0)
1045                 ++p;
1046             if (*p == '/')
1047                 ++p;
1048         }
1049     }
1050     if (!ok) {
1051         option_error("call option value may not contain .. or start with /");
1052         return 0;
1053     }
1054
1055     l = strlen(arg) + strlen(_PATH_PEERFILES) + 1;
1056     if ((fname = (char *) malloc(l)) == NULL)
1057         novm("call file name");
1058     slprintf(fname, l, "%s%s", _PATH_PEERFILES, arg);
1059
1060     ok = options_from_file(fname, 1, 1, 1);
1061
1062     free(fname);
1063     return ok;
1064 }
1065
1066 #ifdef PPP_FILTER
1067 /*
1068  * setpdebug - Set libpcap debugging level.
1069  */
1070 static int
1071 setpdebug(argv)
1072     char **argv;
1073 {
1074     return int_option(*argv, &dflag);
1075 }
1076
1077 /*
1078  * setpassfilter - Set the pass filter for packets
1079  */
1080 static int
1081 setpassfilter(argv)
1082     char **argv;
1083 {
1084     pc.linktype = DLT_PPP;
1085     pc.snapshot = PPP_HDRLEN;
1086  
1087     if (pcap_compile(&pc, &pass_filter, *argv, 1, netmask) == 0)
1088         return 1;
1089     option_error("error in pass-filter expression: %s\n", pcap_geterr(&pc));
1090     return 0;
1091 }
1092
1093 /*
1094  * setactivefilter - Set the active filter for packets
1095  */
1096 static int
1097 setactivefilter(argv)
1098     char **argv;
1099 {
1100     pc.linktype = DLT_PPP;
1101     pc.snapshot = PPP_HDRLEN;
1102  
1103     if (pcap_compile(&pc, &active_filter, *argv, 1, netmask) == 0)
1104         return 1;
1105     option_error("error in active-filter expression: %s\n", pcap_geterr(&pc));
1106     return 0;
1107 }
1108 #endif
1109
1110 /*
1111  * noopt - Disable all options.
1112  */
1113 static int
1114 noopt(argv)
1115     char **argv;
1116 {
1117     BZERO((char *) &lcp_wantoptions[0], sizeof (struct lcp_options));
1118     BZERO((char *) &lcp_allowoptions[0], sizeof (struct lcp_options));
1119     BZERO((char *) &ipcp_wantoptions[0], sizeof (struct ipcp_options));
1120     BZERO((char *) &ipcp_allowoptions[0], sizeof (struct ipcp_options));
1121
1122     return (1);
1123 }
1124
1125 /*
1126  * setdomain - Set domain name to append to hostname 
1127  */
1128 static int
1129 setdomain(argv)
1130     char **argv;
1131 {
1132     if (!privileged_option) {
1133         option_error("using the domain option requires root privilege");
1134         return 0;
1135     }
1136     gethostname(hostname, MAXNAMELEN);
1137     if (**argv != 0) {
1138         if (**argv != '.')
1139             strncat(hostname, ".", MAXNAMELEN - strlen(hostname));
1140         strncat(hostname, *argv, MAXNAMELEN - strlen(hostname));
1141     }
1142     hostname[MAXNAMELEN-1] = 0;
1143     return (1);
1144 }
1145
1146
1147 /*
1148  * setspeed - Set the speed.
1149  */
1150 static int
1151 setspeed(arg)
1152     char *arg;
1153 {
1154     char *ptr;
1155     int spd;
1156
1157     spd = strtol(arg, &ptr, 0);
1158     if (ptr == arg || *ptr != 0 || spd == 0)
1159         return 0;
1160     inspeed = spd;
1161     return 1;
1162 }
1163
1164
1165 /*
1166  * setdevname - Set the device name.
1167  */
1168 static int
1169 setdevname(cp, quiet)
1170     char *cp;
1171     int quiet;
1172 {
1173     struct stat statbuf;
1174     char dev[MAXPATHLEN];
1175
1176     if (*cp == 0)
1177         return 0;
1178
1179     if (strncmp("/dev/", cp, 5) != 0) {
1180         strlcpy(dev, sizeof(dev), "/dev/");
1181         strlcat(dev, sizeof(dev), cp);
1182         cp = dev;
1183     }
1184
1185     /*
1186      * Check if there is a device by this name.
1187      */
1188     if (stat(cp, &statbuf) < 0) {
1189         if (errno == ENOENT || quiet)
1190             return 0;
1191         option_error("Couldn't stat %s: %m", cp);
1192         return -1;
1193     }
1194
1195     if (devnam_info.priv && !privileged_option) {
1196         if (!quiet)
1197             option_error("device name cannot be overridden");
1198         return -1;
1199     }
1200
1201     strlcpy(devnam, sizeof(devnam), cp);
1202     default_device = FALSE;
1203     devnam_info.priv = privileged_option;
1204     devnam_info.source = option_source;
1205   
1206     return 1;
1207 }
1208
1209
1210 /*
1211  * setipaddr - Set the IP address
1212  */
1213 static int
1214 setipaddr(arg)
1215     char *arg;
1216 {
1217     struct hostent *hp;
1218     char *colon;
1219     u_int32_t local, remote;
1220     ipcp_options *wo = &ipcp_wantoptions[0];
1221   
1222     /*
1223      * IP address pair separated by ":".
1224      */
1225     if ((colon = strchr(arg, ':')) == NULL)
1226         return 0;
1227   
1228     /*
1229      * If colon first character, then no local addr.
1230      */
1231     if (colon != arg) {
1232         *colon = '\0';
1233         if ((local = inet_addr(arg)) == -1) {
1234             if ((hp = gethostbyname(arg)) == NULL) {
1235                 option_error("unknown host: %s", arg);
1236                 return -1;
1237             } else {
1238                 local = *(u_int32_t *)hp->h_addr;
1239             }
1240         }
1241         if (bad_ip_adrs(local)) {
1242             option_error("bad local IP address %s", ip_ntoa(local));
1243             return -1;
1244         }
1245         if (local != 0)
1246             wo->ouraddr = local;
1247         *colon = ':';
1248     }
1249   
1250     /*
1251      * If colon last character, then no remote addr.
1252      */
1253     if (*++colon != '\0') {
1254         if ((remote = inet_addr(colon)) == -1) {
1255             if ((hp = gethostbyname(colon)) == NULL) {
1256                 option_error("unknown host: %s", colon);
1257                 return -1;
1258             } else {
1259                 remote = *(u_int32_t *)hp->h_addr;
1260                 if (remote_name[0] == 0)
1261                     strlcpy(remote_name, sizeof(remote_name), colon);
1262             }
1263         }
1264         if (bad_ip_adrs(remote)) {
1265             option_error("bad remote IP address %s", ip_ntoa(remote));
1266             return -1;
1267         }
1268         if (remote != 0)
1269             wo->hisaddr = remote;
1270     }
1271
1272     return 1;
1273 }
1274
1275
1276 /*
1277  * setnetmask - set the netmask to be used on the interface.
1278  */
1279 static int
1280 setnetmask(argv)
1281     char **argv;
1282 {
1283     u_int32_t mask, b;
1284     int n, ok;
1285     char *p, *endp;
1286
1287     /*
1288      * Unfortunately, if we use inet_addr, we can't tell whether
1289      * a result of all 1s is an error or a valid 255.255.255.255.
1290      */
1291     p = *argv;
1292     ok = 0;
1293     mask = 0;
1294     for (n = 3;; --n) {
1295         b = strtoul(p, &endp, 0);
1296         if (endp == p)
1297             break;
1298         if (b < 0 || b > 255) {
1299             if (n == 3) {
1300                 /* accept e.g. 0xffffff00 */
1301                 p = endp;
1302                 mask = b;
1303             }
1304             break;
1305         }
1306         mask |= b << (n * 8);
1307         p = endp;
1308         if (*p != '.' || n == 0)
1309             break;
1310         ++p;
1311     }
1312
1313     mask = htonl(mask);
1314
1315     if (*p != 0 || (netmask & ~mask) != 0) {
1316         option_error("invalid netmask value '%s'", *argv);
1317         return 0;
1318     }
1319
1320     netmask = mask;
1321     return (1);
1322 }
1323
1324 static int
1325 setxonxoff(argv)
1326     char **argv;
1327 {
1328     lcp_wantoptions[0].asyncmap |= 0x000A0000;  /* escape ^S and ^Q */
1329     lcp_wantoptions[0].neg_asyncmap = 1;
1330
1331     crtscts = -2;
1332     return (1);
1333 }