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