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