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