1 /*
2 * options.c - handles option processing for PPP.
3 *
4 * Copyright (c) 2000-2001 by Sun Microsystems, Inc.
5 * All rights reserved.
6 *
7 * Permission to use, copy, modify, and distribute this software and its
8 * documentation is hereby granted, provided that the above copyright
9 * notice appears in all copies.
10 *
11 * SUN MAKES NO REPRESENTATION OR WARRANTIES ABOUT THE SUITABILITY OF
12 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
13 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
14 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
15 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
16 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES
17 *
18 * Copyright (c) 1989 Carnegie Mellon University.
19 * All rights reserved.
20 *
21 * Redistribution and use in source and binary forms are permitted
22 * provided that the above copyright notice and this paragraph are
23 * duplicated in all such forms and that any documentation,
24 * advertising materials, and other materials related to such
25 * distribution and use acknowledge that the software was developed
26 * by Carnegie Mellon University. The name of the
27 * University may not be used to endorse or promote products derived
28 * from this software without specific prior written permission.
29 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
30 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
31 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32 */
33
34 #include <ctype.h>
35 #include <stdio.h>
36 #include <errno.h>
37 #include <unistd.h>
38 #include <fcntl.h>
39 #include <stdlib.h>
40 #include <syslog.h>
41 #include <string.h>
42 #include <netdb.h>
43 #include <pwd.h>
44 #include <sys/types.h>
45 #include <sys/stat.h>
46 #include <netinet/in.h>
47 #include <arpa/inet.h>
48 #ifdef PLUGIN
49 #include <dlfcn.h>
50 #endif /* PLUGIN */
51 #ifdef PPP_FILTER
52 #include <pcap.h>
53 #include <pcap-int.h> /* XXX: To get struct pcap */
54 #endif /* PPP_FILTER */
55
56 #include "pppd.h"
57 #include "pathnames.h"
58 #include "patchlevel.h"
59 #include "fsm.h"
60 #include "lcp.h"
61 #include "ipcp.h"
62
63 #if defined(ultrix) || defined(NeXT)
64 char *strdup __P((char *));
65 #endif
66
67 /*
68 * Option variables and default values.
69 */
70 #ifdef PPP_FILTER
71 int dflag = 0; /* Tell libpcap we want debugging */
72 #endif /* PPP_FILTER */
73 int debug = 0; /* Debug flag */
74 int kdebugflag = 0; /* Tell kernel to print debug messages */
75 int default_device = 1; /* Using /dev/tty or equivalent */
76 char devnam[MAXPATHLEN]; /* Device name */
77 int crtscts = 0; /* Use hardware flow control */
78 bool modem = 1; /* Use modem control lines */
79 int inspeed = 0; /* Input/Output speed requested */
80 u_int32_t netmask = 0; /* IP netmask to set on interface */
81 bool lockflag = 0; /* Create lock file to lock the serial dev */
82 bool nodetach = 0; /* Don't detach from controlling tty */
83 bool updetach = 0; /* Detach once link is up */
84 char *initializer = NULL; /* Script to initialize physical link */
85 char *connect_script = NULL; /* Script to establish physical link */
86 char *disconnect_script = NULL; /* Script to disestablish physical link */
87 char *welcomer = NULL; /* Script to run after phys link estab. */
88 char *ptycommand = NULL; /* Command to run on other side of pty */
89 int maxconnect = 0; /* Maximum connect time */
90 char user[MAXNAMELEN]; /* Username for PAP */
91 char passwd[MAXSECRETLEN]; /* Password for PAP */
92 bool persist = 0; /* Reopen link after it goes down */
93 char our_name[MAXNAMELEN]; /* Our name for authentication purposes */
94 bool demand = 0; /* do dial-on-demand */
95 char *ipparam = NULL; /* Extra parameter for ip up/down scripts */
96 int idle_time_limit = 0; /* Disconnect if idle for this many seconds */
97 int holdoff = 30; /* # seconds to pause before reconnecting */
98 bool holdoff_specified; /* true if a holdoff value has been given */
99 bool notty = 0; /* Stdin/out is not a tty */
100 char *pty_socket = NULL; /* Socket to connect to pty */
101 char *record_file = NULL; /* File to record chars sent/received */
102 int using_pty = 0;
103 bool sync_serial = 0; /* Device is synchronous serial device */
104 int log_to_fd = 1; /* send log messages to this fd too */
105 int maxfail = 10; /* max # of unsuccessful connection attempts */
106 char linkname[MAXPATHLEN]; /* logical name for link */
107 bool tune_kernel; /* may alter kernel settings */
108 int connect_delay = 1000; /* wait this many ms after connect script */
109 int max_data_rate; /* max bytes/sec through charshunt */
110 int req_unit = -1; /* requested interface unit */
111 bool multilink = 0; /* Enable multilink operation */
112 char *bundle_name = NULL; /* bundle name for multilink */
113 bool direct_tty = 0; /* use standard input directly; not a tty */
114
115 /* Maximum depth of include files; prevents looping. */
116 #define MAXFILENESTING 10
117
118 struct option_info initializer_info;
119 struct option_info connect_script_info;
120 struct option_info disconnect_script_info;
121 struct option_info welcomer_info;
122 struct option_info devnam_info;
123 struct option_info ptycommand_info;
124 struct option_info ipsrc_info;
125 struct option_info ipdst_info;
126 struct option_info speed_info;
127
128 #ifdef PPP_FILTER
129 struct bpf_program pass_filter;/* Filter program for packets to pass */
130 struct bpf_program active_filter; /* Filter program for link-active pkts */
131 pcap_t pc; /* Fake struct pcap so we can compile expr */
132 #endif /* PPP_FILTER */
133
134 char *current_option; /* the name of the option being parsed */
135 bool privileged_option; /* set iff the current option came from root */
136 char *option_source = NULL; /* string saying where the option came from */
137 int option_line = 0; /* line number in file */
138 bool log_to_file; /* log_to_fd is a file opened by us */
139 bool log_to_specific_fd; /* log_to_fd was specified by user option */
140
141 /*
142 * Prototypes.
143 */
144 static int setdevname __P((char *));
145 static int setipaddr __P((char *));
146 static int setspeed __P((char *));
147 static int noopt __P((char **, option_t *));
148 static int setdomain __P((char **, option_t *));
149 static int setnetmask __P((char **, option_t *));
150 static int setxonxoff __P((char **, option_t *));
151 static int readfile __P((char **, option_t *));
152 static int callfile __P((char **, option_t *));
153 static int showversion __P((char **, option_t *));
154 static int showhelp __P((char **, option_t *));
155 static int showalloptions __P((char **, option_t *));
156 static void usage __P((void));
157 static int setlogfile __P((char **, option_t *));
158 #ifdef PLUGIN
159 static int loadplugin __P((char **, option_t *));
160 #endif
161 #ifdef PPP_FILTER
162 static int setpassfilter __P((char **, option_t *));
163 static int setactivefilter __P((char **, option_t *));
164 #endif /* PPP_FILTER */
165 static option_t *find_option __P((char *name));
166 static int process_option __P((option_t *opt, char **argv, int sline));
167 static int n_arguments __P((option_t *opt));
168 static int number_option __P((char *str, u_int32_t *valp, int base));
169 static u_int32_t opt_hash __P((const void *key));
170 static int opt_compare __P((const void *p1, const void *p2));
171
172 typedef struct _opt_t {
173 option_t *p;
174 } opt_t;
175
176 typedef struct _hashentry_t {
177 struct _hashentry_t *next;
178 opt_t opt;
179 } hashentry_t;
180
181 /*
182 * A prime number describing the size of hash table.
183 */
184 #define OPTHASH_TBLSIZE 101
185
186 /*
187 * Chained hash table containing pointers to available options.
188 */
189 static hashentry_t *hash_tbl[OPTHASH_TBLSIZE] = { NULL };
190
191 /*
192 * Total number of entries in the hash table.
193 */
194 int hash_tblcnt = 0;
195
196 /*
197 * Valid arguments.
198 */
199 option_t general_options[] = {
200 { "debug", o_int, &debug,
201 "Increase debugging level", OPT_INC|OPT_NOARG|1 },
202 { "-d", o_int, &debug,
203 "Increase debugging level", OPT_INC|OPT_NOARG|1 },
204 { "kdebug", o_int, &kdebugflag,
205 "Set kernel driver debug level" },
206 { "nodetach", o_bool, &nodetach,
207 "Don't detach from controlling tty", 1 },
208 { "-detach", o_bool, &nodetach,
209 "Don't detach from controlling tty", 1 },
210 { "updetach", o_bool, &updetach,
211 "Detach from controlling tty once link is up", 1 },
212 { "holdoff", o_int, &holdoff,
213 "Set time in seconds before retrying connection" },
214 { "idle", o_int, &idle_time_limit,
215 "Set time in seconds before disconnecting idle link" },
216 { "lock", o_bool, &lockflag,
217 "Lock serial device with UUCP-style lock file", 1 },
218 { "-all", o_special_noarg, (void *)noopt,
219 "Don't request/allow any LCP or IPCP options (useless)" },
220 { "init", o_string, &initializer,
221 "A program to initialize the device",
222 OPT_A2INFO | OPT_PRIVFIX, &initializer_info },
223 { "connect", o_string, &connect_script,
224 "A program to set up a connection",
225 OPT_A2INFO | OPT_PRIVFIX, &connect_script_info },
226 { "disconnect", o_string, &disconnect_script,
227 "Program to disconnect serial device",
228 OPT_A2INFO | OPT_PRIVFIX, &disconnect_script_info },
229 { "welcome", o_string, &welcomer,
230 "Script to welcome client",
231 OPT_A2INFO | OPT_PRIVFIX, &welcomer_info },
232 { "pty", o_string, &ptycommand,
233 "Script to run on pseudo-tty master side",
234 OPT_A2INFO | OPT_PRIVFIX | OPT_DEVNAM, &ptycommand_info },
235 { "notty", o_bool, ¬ty,
236 "Input/output is not a tty", OPT_DEVNAM | 1 },
237 { "directtty", o_bool, &direct_tty,
238 "Use standard input as tty without checking", OPT_DEVNAM | 1 },
239 { "socket", o_string, &pty_socket,
240 "Send and receive over socket, arg is host:port", OPT_DEVNAM },
241 { "record", o_string, &record_file,
242 "Record characters sent/received to file" },
243 { "maxconnect", o_int, &maxconnect,
244 "Set connection time limit", OPT_LLIMIT|OPT_NOINCR|OPT_ZEROINF },
245 { "crtscts", o_int, &crtscts,
246 "Set hardware (RTS/CTS) flow control", OPT_NOARG|OPT_VAL(1) },
247 { "nocrtscts", o_int, &crtscts,
248 "Disable hardware flow control", OPT_NOARG|OPT_VAL(-1) },
249 { "-crtscts", o_int, &crtscts,
250 "Disable hardware flow control", OPT_NOARG|OPT_VAL(-1) },
251 { "cdtrcts", o_int, &crtscts,
252 "Set alternate hardware (DTR/CTS) flow control", OPT_NOARG|OPT_VAL(2) },
253 { "nocdtrcts", o_int, &crtscts,
254 "Disable hardware flow control", OPT_NOARG|OPT_VAL(-1) },
255 { "xonxoff", o_special_noarg, (void *)setxonxoff,
256 "Set software (XON/XOFF) flow control" },
257 { "domain", o_special, (void *)setdomain,
258 "Add given domain name to hostname" },
259 { "netmask", o_special, (void *)setnetmask,
260 "set netmask" },
261 { "modem", o_bool, &modem,
262 "Use modem control lines", 1 },
263 { "local", o_bool, &modem,
264 "Don't use modem control lines" },
265 { "file", o_special, (void *)readfile,
266 "Take options from a file", OPT_PREPASS },
267 { "call", o_special, (void *)callfile,
268 "Take options from a privileged file", OPT_PREPASS },
269 { "persist", o_bool, &persist,
270 "Keep on reopening connection after close", 1 },
271 { "nopersist", o_bool, &persist,
272 "Turn off persist option" },
273 { "demand", o_bool, &demand,
274 "Dial on demand", OPT_INITONLY | 1, &persist },
275 { "--version", o_special_noarg, (void *)showversion,
276 "Show version number" },
277 { "--help", o_special_noarg, (void *)showhelp,
278 "Show brief listing of options" },
279 { "-h", o_special_noarg, (void *)showhelp,
280 "Show brief listing of options" },
281 { "options", o_special_noarg, (void *)showalloptions,
282 "Show full listing of options" },
283 { "sync", o_bool, &sync_serial,
284 "Use synchronous HDLC serial encoding", 1 },
285 { "logfd", o_int, &log_to_fd,
286 "Send log messages to this file descriptor",
287 0, &log_to_specific_fd },
288 { "logfile", o_special, (void *)setlogfile,
289 "Append log messages to this file" },
290 { "nolog", o_int, &log_to_fd,
291 "Don't send log messages to any file",
292 OPT_NOARG | OPT_VAL(-1) },
293 { "nologfd", o_int, &log_to_fd,
294 "Don't send log messages to any file descriptor",
295 OPT_NOARG | OPT_VAL(-1) },
296 { "linkname", o_string, linkname,
297 "Set logical name for link",
298 OPT_PRIV|OPT_STATIC, NULL, MAXPATHLEN },
299 { "maxfail", o_int, &maxfail,
300 "Number of unsuccessful connection attempts to allow" },
301 { "ktune", o_bool, &tune_kernel,
302 "Alter kernel settings as necessary", 1 },
303 { "noktune", o_bool, &tune_kernel,
304 "Don't alter kernel settings", 0 },
305 { "connect-delay", o_int, &connect_delay,
306 "Maximum wait time (msec) after connect script finishes" },
307 { "datarate", o_int, &max_data_rate,
308 "Max data rate in bytes/sec for pty, notty, or record" },
309 { "unit", o_int, &req_unit,
310 "PPP interface unit number to use if possible", OPT_LLIMIT, 0, 0 },
311 #ifdef HAVE_MULTILINK
312 { "multilink", o_bool, &multilink,
313 "Enable multilink operation", 1 },
314 { "nomultilink", o_bool, &multilink,
315 "Disable multilink operation", 0 },
316 { "mp", o_bool, &multilink,
317 "Enable multilink operation", 1 },
318 { "nomp", o_bool, &multilink,
319 "Disable multilink operation", 0 },
320 { "bundle", o_string, &bundle_name,
321 "Bundle name for multilink" },
322 #endif /* HAVE_MULTILINK */
323 #ifdef PLUGIN
324 { "plugin", o_special, (void *)loadplugin,
325 "Load a plug-in module into pppd", OPT_PRIV },
326 #endif /* PLUGIN */
327 #ifdef PPP_FILTER
328 { "pdebug", o_int, &dflag,
329 "libpcap debugging" },
330 { "pass-filter", o_special, setpassfilter,
331 "set filter for packets to pass" },
332 { "active-filter", o_special, setactivefilter,
333 "set filter for active pkts" },
334 #endif /* PPP_FILTER */
335 { NULL }
336 };
337
338 /*
339 * This string gets printed out when "options" is given on the command
340 * line. Following this string, all of the available options and
341 * their descriptions are printed out as well. Certain options which
342 * are not available as part of the option_t structure are placed in
343 * the "dummy" option structure.
344 */
345 static const char pre_allopt_string[] = "\
346 pppd version %s.%d%s\n\
347 Usage: %s [ options ], where options are:\n\n\
348 ";
349
350 /* Do not call add_options() on this structure */
351 static option_t dummy_options[] = {
352 { "<device>", o_special_noarg, NULL,
353 "Communicate over the named device" },
354 { "<speed>", o_special_noarg, NULL,
355 "Set the baud rate to <speed>" },
356 { "[<loc>]:[<rem>]", o_special_noarg, NULL,
357 "Set the local and/or remote interface IP addresses" },
358 { NULL }
359 };
360
361 static const char post_allopt_string[] = "\
362 \n\
363 Notes:\
364 \t<n>\tinteger type argument\n\
365 \t<s>\tstring type argument\n\
366 \t<r>\tspecial type argument\n\
367 \t(!)\tprivileged option available only when pppd is executed by root\n\
368 \t\tor when found in the privileged option files (/etc/ppp/options,\n\
369 \t\t/etc/ppp/options.ttyname, /etc/ppp/peers/name, or following\n\
370 \t\t\"--\" in /etc/ppp/pap-secrets or /etc/ppp/chap-secrets).\n\
371 \t(#)\tdisabled option\n\
372 \n\
373 Please see the pppd man page for details.\n";
374
375 /*
376 * parse_args - parse a string of arguments from the command line. If prepass
377 * is true, we are scanning for the device name and only processing a few
378 * options, so error messages are suppressed. Returns 1 upon successful
379 * processing of options, and 0 otherwise.
380 */
381 int
parse_args(argc,argv)382 parse_args(argc, argv)
383 int argc;
384 char **argv;
385 {
386 char *arg;
387 option_t *opt;
388 int ret;
389
390 privileged_option = privileged;
391 option_source = "command line";
392 option_line = 0;
393 while (argc > 0) {
394 arg = *argv++;
395 --argc;
396
397 /*
398 * First check to see if it's a known option name. If so, parse the
399 * argument(s) and set the option.
400 */
401 opt = find_option(arg);
402 if (opt != NULL) {
403 int n = n_arguments(opt);
404 if (argc < n) {
405 option_error("too few parameters for option '%s'", arg);
406 return (0);
407 }
408 current_option = arg;
409 if (!process_option(opt, argv, 0))
410 return (0);
411 argc -= n;
412 argv += n;
413 continue;
414 }
415
416 /*
417 * Maybe a tty name, speed or IP address ?
418 */
419 if (((ret = setdevname(arg)) == 0) &&
420 ((ret = setspeed(arg)) == 0) &&
421 ((ret = setipaddr(arg)) == 0) && !prepass) {
422 option_error("unrecognized option '%s'", arg);
423 usage();
424 return (0);
425 }
426 if (ret < 0) /* error */
427 return (0);
428 }
429 return (1);
430 }
431
432 /*
433 * options_from_file - read a string of options from a file, and
434 * interpret them. Returns 1 upon successful processing of options,
435 * and 0 otherwise.
436 */
437 int
options_from_file(char * filename,bool must_exist,bool check_prot,bool priv)438 options_from_file
439 #ifdef __STDC__
440 (char *filename, bool must_exist, bool check_prot, bool priv)
441 #else
442 (filename, must_exist, check_prot, priv)
443 char *filename;
444 bool must_exist;
445 bool check_prot;
446 bool priv;
447 #endif
448 {
449 FILE *f;
450 int i, newline, ret, err;
451 option_t *opt;
452 bool oldpriv;
453 int oldline, sline;
454 char *oldsource;
455 char *argv[MAXARGS];
456 char args[MAXARGS][MAXWORDLEN];
457 char cmd[MAXWORDLEN];
458 static bool firsterr = 1;
459 static int nestlevel = 0;
460
461 if (nestlevel >= MAXFILENESTING) {
462 option_error("file nesting too deep");
463 return (0);
464 }
465 if (check_prot)
466 (void) seteuid(getuid());
467 errno = 0;
468 f = fopen(filename, "r");
469 err = errno;
470 if (check_prot)
471 (void) seteuid(0);
472 if (f == NULL) {
473 if (!must_exist && err == ENOENT)
474 return (1);
475 errno = err;
476 option_error("Can't open options file %s: %m", filename);
477 return (0);
478 }
479
480 nestlevel++;
481 oldpriv = privileged_option;
482 privileged_option = priv;
483 oldsource = option_source;
484 /*
485 * strdup() is used here because the pointer might refer to the
486 * caller's automatic (stack) storage, and the option_info array
487 * records the source file name.
488 */
489 option_source = strdup(filename);
490 oldline = option_line;
491 option_line = 1;
492 if (option_source == NULL)
493 option_source = "file";
494 ret = 0;
495 while (getword(f, cmd, &newline, filename)) {
496 sline = option_line;
497 /*
498 * First see if it's a command.
499 */
500 opt = find_option(cmd);
501 if (opt != NULL) {
502 int n = n_arguments(opt);
503 for (i = 0; i < n; ++i) {
504 if (!getword(f, args[i], &newline, filename)) {
505 option_error("too few parameters for option '%s'", cmd);
506 goto err;
507 }
508 argv[i] = args[i];
509 }
510 current_option = cmd;
511 if ((opt->flags & OPT_DEVEQUIV) && devnam_fixed) {
512 option_error("the '%s' option may not be used here", cmd);
513 goto err;
514 }
515 if (!process_option(opt, argv, sline))
516 goto err;
517 continue;
518 }
519
520 /*
521 * Maybe a tty name, speed or IP address ?
522 */
523 if (((i = setdevname(cmd)) == 0) &&
524 ((i = setspeed(cmd)) == 0) &&
525 ((i = setipaddr(cmd)) == 0)) {
526 option_error("unrecognized option '%s'", cmd);
527 goto err;
528 }
529 if (i < 0) /* error */
530 goto err;
531 }
532 ret = 1;
533
534 err:
535 (void) fclose(f);
536 /* We assume here that we abort all processing on the first error. */
537 if (firsterr)
538 firsterr = 0;
539 else if (!prepass && !ret)
540 option_error("error in included file");
541 /*
542 * Cannot free option_source because it might be referenced in one
543 * or more option_info structures now.
544 */
545 privileged_option = oldpriv;
546 option_source = oldsource;
547 option_line = oldline;
548 nestlevel--;
549 return (ret);
550 }
551
552 /*
553 * options_from_user - see if the user has a ~/.ppprc file, and if so,
554 * interpret options from it. Returns 1 upon successful processing of
555 * options, and 0 otherwise.
556 */
557 int
options_from_user()558 options_from_user()
559 {
560 char *user, *path, *file;
561 int ret;
562 struct passwd *pw;
563 size_t pl;
564
565 pw = getpwuid(getuid());
566 if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == '\0')
567 return (1);
568 file = _PATH_USEROPT;
569 pl = strlen(user) + strlen(file) + 2;
570 path = malloc(pl);
571 if (path == NULL)
572 novm("init file name");
573 (void) slprintf(path, pl, "%s/%s", user, file);
574 ret = options_from_file(path, 0, 1, privileged);
575 free(path);
576 return (ret);
577 }
578
579 /*
580 * options_for_tty - see if an options file exists for the serial device, and
581 * if so, interpret options from it. Returns 1 upon successful processing of
582 * options, and 0 otherwise.
583 */
584 int
options_for_tty()585 options_for_tty()
586 {
587 char *dev, *path, *p;
588 int ret;
589 size_t pl;
590
591 dev = devnam;
592 if (strncmp(dev, "/dev/", 5) == 0)
593 dev += 5;
594 if (dev[0] == '\0' || strcmp(dev, "tty") == 0)
595 return (1); /* don't look for /etc/ppp/options.tty */
596 pl = strlen(_PATH_TTYOPT) + strlen(dev) + 1;
597 path = malloc(pl);
598 if (path == NULL)
599 novm("tty init file name");
600 (void) slprintf(path, pl, "%s%s", _PATH_TTYOPT, dev);
601 /* Turn slashes into dots, for Solaris case (e.g. /dev/term/a) */
602 for (p = path + strlen(_PATH_TTYOPT); *p != '\0'; ++p)
603 if (*p == '/')
604 *p = '.';
605 ret = options_from_file(path, 0, 0, 1);
606 free(path);
607 return (ret);
608 }
609
610 /*
611 * options_from_list - process a string of options in a wordlist. Returns 1
612 * upon successful processing of options, and 0 otherwise.
613 */
614 int
options_from_list(struct wordlist * w,bool priv)615 options_from_list
616 #ifdef __STDC__
617 (struct wordlist *w, bool priv)
618 #else
619 (w, priv)
620 struct wordlist *w;
621 bool priv;
622 #endif
623 {
624 char *argv[MAXARGS];
625 option_t *opt;
626 int i, ret = 0;
627
628 privileged_option = priv;
629
630 /* Caller is expected to set option_source and option_line. */
631
632 while (w != NULL) {
633 /*
634 * First see if it's a command.
635 */
636 opt = find_option(w->word);
637 if (opt != NULL) {
638 int n = n_arguments(opt);
639 struct wordlist *w0 = w;
640 for (i = 0; i < n; ++i) {
641 w = w->next;
642 if (w == NULL) {
643 option_error("too few parameters for option '%s'",
644 w0->word);
645 goto err;
646 }
647 argv[i] = w->word;
648 }
649 current_option = w0->word;
650 if (!process_option(opt, argv, option_line))
651 goto err;
652 continue;
653 }
654
655 /*
656 * Options from the {p,ch}ap-secrets files can't change the device
657 * name nor the speed. Therefore, calls to setdevname() and
658 * setspeed() were removed.
659 */
660 if ((i = setipaddr(w->word)) == 0) {
661 option_error("unrecognized option '%s'", w->word);
662 goto err;
663 }
664 if (i < 0) /* error */
665 goto err;
666 }
667 ret = 1;
668
669 err:
670 return (ret);
671 }
672
673 /*
674 * find_option - scan the option lists for the various protocols looking for an
675 * entry with the given name. Returns a pointer to the matching option_t
676 * structure upon successful processing of options, and NULL otherwise.
677 */
678 static option_t *
find_option(name)679 find_option(name)
680 char *name;
681 {
682 hashentry_t *bucket;
683
684 bucket = hash_tbl[opt_hash(name)];
685 for (; bucket != NULL; bucket = bucket->next) {
686 if (bucket->opt.p->name != NULL) {
687 if ((strcmp(bucket->opt.p->name, name) == 0) &&
688 !(bucket->opt.p->flags & OPT_DISABLE)) {
689 return (bucket->opt.p);
690 }
691 }
692 }
693 return (NULL);
694 }
695
696 /*
697 * process_option - process one new-style option (something other than a
698 * port name, bit rate, or IP address). Returns 1 upon successful
699 * processing of options, and 0 otherwise.
700 */
701 static int
process_option(opt,argv,sline)702 process_option(opt, argv, sline)
703 option_t *opt;
704 char **argv;
705 int sline;
706 {
707 u_int32_t v;
708 int iv, a;
709 char *sv;
710 int (*parser) __P((char **, option_t *));
711
712 if ((opt->flags & OPT_PREPASS) == 0 && prepass)
713 return (1);
714 if ((opt->flags & OPT_INITONLY) && phase != PHASE_INITIALIZE) {
715 option_error("it's too late to use the '%s' option", opt->name);
716 return (0);
717 }
718 if ((opt->flags & OPT_PRIV) && !privileged_option) {
719 option_error("using the '%s' option requires root privilege",
720 opt->name);
721 return (0);
722 }
723 if ((opt->flags & OPT_ENABLE) && !privileged_option &&
724 *(bool *)(opt->addr2) == 0) {
725 option_error("'%s' option is disabled", opt->name);
726 return (0);
727 }
728 if ((opt->flags & OPT_PRIVFIX) && !privileged_option) {
729 struct option_info *ip = (struct option_info *) opt->addr2;
730 if ((ip != NULL) && ip->priv) {
731 option_error("'%s' option cannot be overridden", opt->name);
732 return (0);
733 }
734 }
735
736 switch (opt->type) {
737 case o_bool:
738 v = opt->flags & OPT_VALUE;
739 *(bool *)(opt->addr) = (v != 0);
740 if ((opt->addr2 != NULL) && (opt->flags & OPT_A2COPY))
741 *(bool *)(opt->addr2) = (v != 0);
742 break;
743
744 case o_int:
745 iv = 0;
746 if ((opt->flags & OPT_NOARG) == 0) {
747 if (!int_option(*argv, &iv))
748 return (0);
749 if ((((opt->flags & OPT_LLIMIT) && (iv < opt->lower_limit)) ||
750 ((opt->flags & OPT_ULIMIT) && (iv > opt->upper_limit))) &&
751 !((opt->flags & OPT_ZEROOK) && (iv == 0))) {
752 char *zok = (opt->flags & OPT_ZEROOK) ? " zero or" : "";
753 switch (opt->flags & OPT_LIMITS) {
754 case OPT_LLIMIT:
755 option_error("%s value must be%s >= %d",
756 opt->name, zok, opt->lower_limit);
757 break;
758 case OPT_ULIMIT:
759 option_error("%s value must be%s <= %d",
760 opt->name, zok, opt->upper_limit);
761 break;
762 case OPT_LIMITS:
763 option_error("%s value must be%s between %d and %d",
764 opt->name, zok, opt->lower_limit, opt->upper_limit);
765 break;
766 }
767 return (0);
768 }
769 }
770 a = opt->flags & OPT_VALUE;
771 if (a >= 128)
772 a -= 256; /* sign extend */
773 iv += a;
774 if (opt->flags & OPT_INC)
775 iv += *(int *)(opt->addr);
776 if ((opt->flags & OPT_NOINCR) && !privileged_option) {
777 int oldv = *(int *)(opt->addr);
778
779 if ((opt->flags & OPT_ZEROINF) && (iv == 0)) {
780 if (oldv > 0) {
781 option_error("%s value cannot be set to infinity; limited to %d",
782 opt->name, oldv);
783 return (0);
784 }
785 } else if (iv > oldv) {
786 option_error("%s value cannot be increased beyond %d",
787 opt->name, oldv);
788 return (0);
789 }
790 }
791 *(int *)(opt->addr) = iv;
792 if ((opt->addr2 != NULL) && (opt->flags & OPT_A2COPY))
793 *(int *)(opt->addr2) = iv;
794 break;
795
796 case o_uint32:
797 if (opt->flags & OPT_NOARG) {
798 v = opt->flags & OPT_VALUE;
799 } else if (!number_option(*argv, &v, 16))
800 return (0);
801 if (opt->flags & OPT_OR)
802 v |= *(u_int32_t *)(opt->addr);
803 *(u_int32_t *)(opt->addr) = v;
804 if ((opt->addr2 != NULL) && (opt->flags & OPT_A2COPY))
805 *(u_int32_t *)(opt->addr2) = v;
806 break;
807
808 case o_string:
809 if (opt->flags & OPT_STATIC) {
810 (void) strlcpy((char *)(opt->addr), *argv, opt->upper_limit);
811 if ((opt->addr2 != NULL) && (opt->flags & OPT_A2COPY)) {
812 (void) strlcpy((char *)(opt->addr2), *argv, opt->upper_limit);
813 }
814 } else {
815 sv = strdup(*argv);
816 if (sv == NULL)
817 novm("option argument");
818 *(char **)(opt->addr) = sv;
819 if (opt->addr2 != NULL && (opt->flags & OPT_A2COPY))
820 *(char **)(opt->addr2) = sv;
821 }
822 break;
823
824 case o_special_noarg:
825 case o_special:
826 parser = (int (*) __P((char **, option_t *))) opt->addr;
827 if (!(*parser)(argv, opt))
828 return (0);
829 break;
830 }
831
832 if (opt->addr2 != NULL) {
833 if (opt->flags & OPT_A2INFO) {
834 struct option_info *ip = (struct option_info *) opt->addr2;
835 ip->priv = privileged_option;
836 ip->source = option_source;
837 ip->line = sline;
838 } else if ((opt->flags & (OPT_A2COPY|OPT_ENABLE)) == 0)
839 *(bool *)(opt->addr2) = 1;
840 }
841
842 return (1);
843 }
844
845 /*
846 * n_arguments - tell how many arguments an option takes. Returns 1 upon
847 * successful processing of options, and 0 otherwise.
848 */
849 static int
n_arguments(opt)850 n_arguments(opt)
851 option_t *opt;
852 {
853 return ((opt->type == o_bool || opt->type == o_special_noarg ||
854 (opt->flags & OPT_NOARG)) ? 0 : 1);
855 }
856
857 /*
858 * opt_hash - a hash function that works quite well for strings. Returns
859 * the hash key of the supplied string.
860 */
861 static u_int32_t
opt_hash(key)862 opt_hash(key)
863 const void *key;
864 {
865 register const char *ptr;
866 register u_int32_t val;
867
868 val = 0;
869 ptr = key;
870 while (*ptr != '\0') {
871 int tmp;
872 val = (val << 4) + (*ptr);
873 tmp = val & 0xf0000000;
874 if (tmp) {
875 val ^= (tmp >> 24);
876 val ^= tmp;
877 }
878 ptr++;
879 }
880 return (val % OPTHASH_TBLSIZE);
881 }
882
883 /*
884 * add_options - add a list of options to the chained hash table.
885 * Also detect duplicate options, and if found, disable the older
886 * definition and log it as an error.
887 */
888 void
add_options(opt)889 add_options(opt)
890 option_t *opt;
891 {
892 register option_t *sopt;
893 register hashentry_t *bucket;
894 register u_int32_t loc;
895 hashentry_t *he;
896
897 /* fill hash-table */
898 for (sopt = opt; sopt->name != NULL; ++sopt, hash_tblcnt++) {
899
900 /* first, allocate a hash entry */
901 he = (hashentry_t *)malloc(sizeof(*he));
902 if (he == NULL) {
903 novm("option hash table entry");
904 }
905 he->opt.p = sopt;
906 he->next = NULL;
907
908 /*
909 * fill the chained hash table and take care of any collisions or
910 * duplicate items.
911 */
912 loc = opt_hash(sopt->name);
913 bucket = hash_tbl[loc];
914 if (bucket != NULL) {
915 for (;;) {
916 if (!(bucket->opt.p->flags & OPT_DISABLE) &&
917 strcmp(sopt->name, bucket->opt.p->name) == 0) {
918 info("option '%s' redefined; old definition disabled",
919 sopt->name);
920 bucket->opt.p->flags |= OPT_DISABLE;
921 }
922 if (bucket->next == NULL)
923 break;
924 bucket = bucket->next;
925 }
926 bucket->next = he;
927 } else {
928 hash_tbl[loc] = he;
929 }
930 }
931 }
932
933 /*
934 * remove_option - disable an option. Returns the option_t structure
935 * of the disabled option, or NULL if the option name is invalid or if
936 * the option has already been disabled.
937 */
938 option_t *
remove_option(name)939 remove_option(name)
940 char *name;
941 {
942 option_t *opt;
943
944 if ((opt = find_option(name)) != NULL) {
945 opt->flags |= OPT_DISABLE;
946 }
947 return (opt);
948 }
949
950 /*
951 * opt_compare - a compare function supplied to the quicksort routine.
952 * Returns an integer less than, equal to, or greater than zero to indicate
953 * if the first argument is considered less than, equal to, or greater
954 * than the second argument.
955 */
956 static int
opt_compare(p1,p2)957 opt_compare(p1, p2)
958 const void *p1;
959 const void *p2;
960 {
961 opt_t *o1 = (opt_t *)p1;
962 opt_t *o2 = (opt_t *)p2;
963
964 return (strcmp(o1->p->name, o2->p->name));
965 }
966
967 /*ARGSUSED*/
968 static int
showalloptions(argv,topt)969 showalloptions(argv, topt)
970 char **argv;
971 option_t *topt;
972 {
973 #define MAXOPTSTRLEN 257
974 #define PRINTOPTIONS() { \
975 (void) slprintf(opt_str, sizeof(opt_str), "%s", opt->name); \
976 if ((opt->type == o_int || opt->type == o_uint32) && \
977 !(opt->flags & OPT_NOARG)) { \
978 (void) strlcat(opt_str, " <n>", sizeof(opt_str)); \
979 } else if (opt->type == o_string) { \
980 (void) strlcat(opt_str, " <s>", sizeof(opt_str)); \
981 } else if (opt->type == o_special) { \
982 (void) strlcat(opt_str, " <r>", sizeof(opt_str)); \
983 } \
984 if (opt->flags & OPT_PRIV) { \
985 (void) strlcat(opt_str, " (!)", sizeof(opt_str)); \
986 } else if (opt->flags & OPT_DISABLE) { \
987 (void) strlcat(opt_str, " (#)", sizeof(opt_str)); \
988 } \
989 (void) printf("%-26s%s\n", opt_str, opt->description); \
990 }
991
992 char opt_str[MAXOPTSTRLEN];
993 option_t *opt;
994 hashentry_t *bucket;
995 int i, sofar;
996 opt_t *sopt;
997
998 if (phase != PHASE_INITIALIZE) {
999 return (0);
1000 }
1001 (void) printf(pre_allopt_string, VERSION, PATCHLEVEL, IMPLEMENTATION,
1002 progname);
1003 for (opt = dummy_options; opt->name != NULL; ++opt) {
1004 PRINTOPTIONS();
1005 }
1006
1007 sopt = malloc(sizeof(*sopt) * hash_tblcnt);
1008 if (sopt == NULL) {
1009 novm("sorted option table");
1010 }
1011
1012 sofar = 0;
1013 for (i = 0; i < OPTHASH_TBLSIZE; i++) {
1014 for (bucket = hash_tbl[i]; bucket != NULL; bucket = bucket->next) {
1015 if (sofar >= hash_tblcnt) {
1016 fatal("options hash table corrupted; size mismatch");
1017 }
1018 sopt[sofar++].p = bucket->opt.p;
1019 }
1020 }
1021
1022 qsort((void *)sopt, sofar, sizeof(sopt[0]), opt_compare);
1023 for (i = 0; i < sofar; i++) {
1024 opt = sopt[i].p;
1025 PRINTOPTIONS();
1026 }
1027
1028 (void) printf(post_allopt_string);
1029 (void) free(sopt);
1030
1031 #undef MAXOPTSTRLEN
1032 #undef PRINTOPTIONS
1033 return (0);
1034 }
1035
1036 /*
1037 * usage - print out a message telling how to use the program.
1038 * This string gets printed out when either "--help" or an invalid option
1039 * is specified.
1040 */
1041 static void
usage()1042 usage()
1043 {
1044 static const char usage_string[] = "\
1045 pppd version %s.%d%s\n\
1046 Usage: %s [ options ], where options are:\n\
1047 \t<device>\tCommunicate over the named device\n\
1048 \t<speed>\t\tSet the baud rate to <speed>\n\
1049 \t<loc>:<rem>\tSet the local and/or remote interface IP\n\
1050 \t\t\taddresses. Either one may be omitted.\n\
1051 \tnoauth\t\tDon't require authentication from peer\n\
1052 \tconnect <p>\tInvoke shell command <p> to set up the serial line\n\
1053 \tdefaultroute\tAdd default route through interface\n\
1054 Use \"%s options\" or \"man pppd\" for more options.\n\
1055 ";
1056
1057 if (phase == PHASE_INITIALIZE)
1058 (void) fprintf(stderr, usage_string, VERSION, PATCHLEVEL,
1059 IMPLEMENTATION, progname, progname);
1060 }
1061
1062 /*
1063 * showhelp - print out usage message and exit program upon success, or
1064 * return 0 otherwise.
1065 */
1066 /*ARGSUSED*/
1067 static int
showhelp(argv,opt)1068 showhelp(argv, opt)
1069 char **argv;
1070 option_t *opt;
1071 {
1072 if (phase == PHASE_INITIALIZE) {
1073 usage();
1074 exit(0);
1075 }
1076 return (0);
1077 }
1078
1079 /*
1080 * showversion - print out the version number and exit program upon success,
1081 * or return 0 otherwise.
1082 */
1083 /*ARGSUSED*/
1084 static int
showversion(argv,opt)1085 showversion(argv, opt)
1086 char **argv;
1087 option_t *opt;
1088 {
1089 if (phase == PHASE_INITIALIZE) {
1090 (void) fprintf(stderr, "pppd version %s.%d%s\n", VERSION, PATCHLEVEL,
1091 IMPLEMENTATION);
1092 exit(0);
1093 }
1094 return (0);
1095 }
1096
1097 /*
1098 * option_error - print a message about an error in an option. The message is
1099 * logged, and also sent to stderr if phase == PHASE_INITIALIZE.
1100 */
1101 void
option_error(char * fmt,...)1102 option_error __V((char *fmt, ...))
1103 {
1104 va_list args;
1105 char buf[256];
1106 int i, err;
1107
1108 #if defined(__STDC__)
1109 va_start(args, fmt);
1110 #else
1111 char *fmt;
1112 va_start(args);
1113 fmt = va_arg(args, char *);
1114 #endif
1115 if (prepass) {
1116 va_end(args);
1117 return;
1118 }
1119 err = errno;
1120 if (option_source == NULL) {
1121 i = 0;
1122 } else if (option_line <= 0) {
1123 (void) strlcpy(buf, option_source, sizeof (buf));
1124 i = strlen(buf);
1125 } else {
1126 i = slprintf(buf, sizeof(buf), "%s:%d", option_source, option_line);
1127 }
1128 if (i != 0) {
1129 (void) strlcat(buf, ": ", sizeof (buf));
1130 i += 2;
1131 }
1132 errno = err;
1133 (void) vslprintf(buf + i, sizeof (buf) - i, fmt, args);
1134 va_end(args);
1135 if ((phase == PHASE_INITIALIZE) && !detached)
1136 (void) fprintf(stderr, "%s: %s\n", progname, buf);
1137 syslog(LOG_ERR, "%s", buf);
1138 }
1139
1140 /*
1141 * getword - read a word from a file. Words are delimited by white-space or by
1142 * quotes (" or '). Quotes, white-space and \ may be escaped with \.
1143 * \<newline> is ignored. Returns 1 upon successful processing of options,
1144 * and 0 otherwise.
1145 */
1146 int
getword(f,word,newlinep,filename)1147 getword(f, word, newlinep, filename)
1148 FILE *f;
1149 char *word;
1150 int *newlinep;
1151 char *filename;
1152 {
1153 int c, len, escape;
1154 int quoted, comment;
1155 int value, digit, got, n;
1156
1157 #define isoctal(c) ((c) >= '0' && (c) < '8')
1158
1159 *newlinep = 0;
1160 len = 0;
1161 escape = 0;
1162 comment = 0;
1163
1164 /*
1165 * First skip white-space and comments.
1166 */
1167 for (;;) {
1168 c = getc(f);
1169 if (c == EOF)
1170 break;
1171
1172 /*
1173 * A newline means the end of a comment; backslash-newline
1174 * is ignored. Note that we cannot have escape && comment.
1175 */
1176 if (c == '\n') {
1177 option_line++;
1178 if (!escape) {
1179 *newlinep = 1;
1180 comment = 0;
1181 } else
1182 escape = 0;
1183 continue;
1184 }
1185
1186 /*
1187 * Ignore characters other than newline in a comment.
1188 */
1189 if (comment)
1190 continue;
1191
1192 /*
1193 * If this character is escaped, we have a word start.
1194 */
1195 if (escape)
1196 break;
1197
1198 /*
1199 * If this is the escape character, look at the next character.
1200 */
1201 if (c == '\\') {
1202 escape = 1;
1203 continue;
1204 }
1205
1206 /*
1207 * If this is the start of a comment, ignore the rest of the line.
1208 */
1209 if (c == '#') {
1210 comment = 1;
1211 continue;
1212 }
1213
1214 /*
1215 * A non-whitespace character is the start of a word.
1216 */
1217 if (!isspace(c))
1218 break;
1219 }
1220
1221 /*
1222 * Save the delimiter for quoted strings.
1223 */
1224 if (!escape && (c == '"' || c == '\'')) {
1225 quoted = c;
1226 c = getc(f);
1227 } else
1228 quoted = 0;
1229
1230 /*
1231 * Process characters until the end of the word.
1232 */
1233 while (c != EOF) {
1234 if (escape) {
1235 /*
1236 * This character is escaped: backslash-newline is ignored,
1237 * various other characters indicate particular values
1238 * as for C backslash-escapes.
1239 */
1240 escape = 0;
1241 if (c == '\n') {
1242 c = getc(f);
1243 continue;
1244 }
1245
1246 got = 0;
1247 switch (c) {
1248 case 'a':
1249 value = '\a';
1250 break;
1251 case 'b':
1252 value = '\b';
1253 break;
1254 case 'f':
1255 value = '\f';
1256 break;
1257 case 'n':
1258 value = '\n';
1259 break;
1260 case 'r':
1261 value = '\r';
1262 break;
1263 case 's':
1264 value = ' ';
1265 break;
1266 case 't':
1267 value = '\t';
1268 break;
1269
1270 default:
1271 if (isoctal(c)) {
1272 /*
1273 * \ddd octal sequence
1274 */
1275 value = 0;
1276 for (n = 0; n < 3 && isoctal(c); ++n) {
1277 value = (value << 3) + (c & 07);
1278 c = getc(f);
1279 }
1280 got = 1;
1281 break;
1282 }
1283
1284 if (c == 'x') {
1285 /*
1286 * \x<hex_string> sequence
1287 */
1288 value = 0;
1289 c = getc(f);
1290 for (n = 0; n < 2 && isxdigit(c); ++n) {
1291 digit = (islower(c) ? toupper(c) : c) - '0';
1292 if (digit > 10 || digit < 0) /* allow non-ASCII */
1293 digit += '0' + 10 - 'A';
1294 value = (value << 4) + digit;
1295 c = getc (f);
1296 }
1297 got = 1;
1298 break;
1299 }
1300
1301 /*
1302 * Otherwise the character stands for itself.
1303 */
1304 value = c;
1305 break;
1306 }
1307
1308 /*
1309 * Store the resulting character for the escape sequence.
1310 */
1311 if (len < MAXWORDLEN) {
1312 word[len] = value;
1313 ++len;
1314 }
1315
1316 if (!got)
1317 c = getc(f);
1318 continue;
1319
1320 }
1321
1322 /*
1323 * Not escaped: see if we've reached the end of the word.
1324 */
1325 if (quoted) {
1326 if (c == quoted)
1327 break;
1328 } else {
1329 if (isspace(c) || c == '#') {
1330 (void) ungetc (c, f);
1331 break;
1332 }
1333 }
1334
1335 /*
1336 * Backslash starts an escape sequence.
1337 */
1338 if (c == '\\') {
1339 escape = 1;
1340 c = getc(f);
1341 continue;
1342 }
1343
1344 /*
1345 * An ordinary character: store it in the word and get another.
1346 */
1347 if (len < MAXWORDLEN) {
1348 word[len] = c;
1349 ++len;
1350 }
1351
1352 c = getc(f);
1353 }
1354
1355 /*
1356 * End of the word: check for errors.
1357 */
1358 if (c == EOF) {
1359 if (ferror(f)) {
1360 if (errno == 0)
1361 errno = EIO;
1362 option_error("Error reading %s: %m", filename);
1363 die(1);
1364 }
1365 /*
1366 * If len is zero, then we didn't find a word before the
1367 * end of the file.
1368 */
1369 if (len == 0)
1370 return (0);
1371 }
1372
1373 /*
1374 * Warn if the word was too long, and append a terminating null.
1375 */
1376 if (len >= MAXWORDLEN) {
1377 option_error("warning: word in file %s too long (%.20s...)",
1378 filename, word);
1379 len = MAXWORDLEN - 1;
1380 }
1381 word[len] = '\0';
1382
1383 return (1);
1384
1385 #undef isoctal
1386
1387 }
1388
1389 /*
1390 * number_option - parse an unsigned numeric parameter for an option.
1391 * Returns 1 upon successful processing of options, and 0 otherwise.
1392 */
1393 static int
number_option(str,valp,base)1394 number_option(str, valp, base)
1395 char *str;
1396 u_int32_t *valp;
1397 int base;
1398 {
1399 char *ptr;
1400
1401 *valp = strtoul(str, &ptr, base);
1402 if (ptr == str || *ptr != '\0') {
1403 option_error("invalid numeric parameter '%s' for '%s' option",
1404 str, current_option);
1405 return (0);
1406 }
1407 return (1);
1408 }
1409
1410 /*
1411 * save_source - store option source, line, and privilege into an
1412 * option_info structure.
1413 */
1414 void
save_source(info)1415 save_source(info)
1416 struct option_info *info;
1417 {
1418 info->priv = privileged_option;
1419 info->source = option_source;
1420 info->line = option_line;
1421 }
1422
1423 /*
1424 * set_source - set option source, line, and privilege from an
1425 * option_info structure.
1426 */
1427 void
set_source(info)1428 set_source(info)
1429 struct option_info *info;
1430 {
1431 privileged_option = info->priv;
1432 option_source = info->source;
1433 option_line = info->line;
1434 }
1435
1436 /*
1437 * name_source - return string containing option source and line. Can
1438 * be used as part of an option_error call.
1439 */
1440 const char *
name_source(info)1441 name_source(info)
1442 struct option_info *info;
1443 {
1444 static char buf[MAXPATHLEN];
1445
1446 if (info->source == NULL)
1447 return "none";
1448 if (info->line <= 0)
1449 return info->source;
1450 (void) slprintf(buf, sizeof (buf), "%s:%d", info->source, info->line);
1451 return (const char *)buf;
1452 }
1453
1454 /*
1455 * int_option - like number_option, but valp is int *, the base is assumed to
1456 * be 0, and *valp is not changed if there is an error. Returns 1 upon
1457 * successful processing of options, and 0 otherwise.
1458 */
1459 int
int_option(str,valp)1460 int_option(str, valp)
1461 char *str;
1462 int *valp;
1463 {
1464 u_int32_t v;
1465
1466 if (!number_option(str, &v, 0))
1467 return (0);
1468 *valp = (int) v;
1469 return (1);
1470 }
1471
1472
1473 /*
1474 * The following procedures parse options.
1475 */
1476
1477 /*
1478 * readfile - take commands from a file.
1479 */
1480 /*ARGSUSED*/
1481 static int
readfile(argv,opt)1482 readfile(argv, opt)
1483 char **argv;
1484 option_t *opt;
1485 {
1486 return (options_from_file(*argv, 1, 1, privileged_option));
1487 }
1488
1489 /*
1490 * callfile - take commands from /etc/ppp/peers/<name>. Name may not contain
1491 * /../, start with / or ../, or end in /. Returns 1 upon successful
1492 * processing of options, and 0 otherwise.
1493 */
1494 /*ARGSUSED*/
1495 static int
callfile(argv,opt)1496 callfile(argv, opt)
1497 char **argv;
1498 option_t *opt;
1499 {
1500 char *fname, *arg, *p;
1501 int l, ok;
1502
1503 arg = *argv;
1504 ok = 1;
1505 if (arg[0] == '/' || arg[0] == '\0')
1506 ok = 0;
1507 else {
1508 for (p = arg; *p != '\0'; ) {
1509 if (p[0] == '.' && p[1] == '.' && (p[2] == '/' || p[2] == '\0')) {
1510 ok = 0;
1511 break;
1512 }
1513 while (*p != '/' && *p != '\0')
1514 ++p;
1515 if (*p == '/')
1516 ++p;
1517 }
1518 }
1519 if (!ok) {
1520 option_error("call option value may not contain .. or start with /");
1521 return (0);
1522 }
1523
1524 l = strlen(arg) + strlen(_PATH_PEERFILES) + 1;
1525 if ((fname = (char *) malloc(l)) == NULL)
1526 novm("call file name");
1527 (void) slprintf(fname, l, "%s%s", _PATH_PEERFILES, arg);
1528
1529 ok = options_from_file(fname, 1, 1, 1);
1530
1531 free(fname);
1532 return (ok);
1533 }
1534
1535 #ifdef PPP_FILTER
1536 /*
1537 * setpdebug - set libpcap debugging level. Returns 1 upon successful
1538 * processing of options, and 0 otherwise.
1539 */
1540 static int
setpdebug(argv)1541 setpdebug(argv)
1542 char **argv;
1543 {
1544 return (int_option(*argv, &dflag));
1545 }
1546
1547 /*
1548 * setpassfilter - set the pass filter for packets. Returns 1 upon successful
1549 * processing of options, and 0 otherwise.
1550 */
1551 /*ARGSUSED*/
1552 static int
setpassfilter(argv,opt)1553 setpassfilter(argv, opt)
1554 char **argv;
1555 option_t *opt;
1556 {
1557 pc.linktype = DLT_PPP;
1558 pc.snapshot = PPP_HDRLEN;
1559
1560 if (pcap_compile(&pc, &pass_filter, *argv, 1, netmask) == 0)
1561 return (1);
1562 option_error("error in pass-filter expression: %s\n", pcap_geterr(&pc));
1563 return (0);
1564 }
1565
1566 /*
1567 * setactivefilter - set the active filter for packets. Returns 1 upon
1568 * successful processing of options, and 0 otherwise.
1569 */
1570 /*ARGSUSED*/
1571 static int
setactivefilter(argv,opt)1572 setactivefilter(argv, opt)
1573 char **argv;
1574 option_t *opt;
1575 {
1576 pc.linktype = DLT_PPP;
1577 pc.snapshot = PPP_HDRLEN;
1578
1579 if (pcap_compile(&pc, &active_filter, *argv, 1, netmask) == 0)
1580 return (1);
1581 option_error("error in active-filter expression: %s\n", pcap_geterr(&pc));
1582 return (0);
1583 }
1584 #endif /* PPP_FILTER */
1585
1586 /*
1587 * noopt - disable all options. Returns 1 upon successful processing of
1588 * options, and 0 otherwise.
1589 */
1590 /*ARGSUSED*/
1591 static int
noopt(argv,opt)1592 noopt(argv, opt)
1593 char **argv;
1594 option_t *opt;
1595 {
1596 BZERO((char *) &lcp_wantoptions[0], sizeof (struct lcp_options));
1597 BZERO((char *) &lcp_allowoptions[0], sizeof (struct lcp_options));
1598 BZERO((char *) &ipcp_wantoptions[0], sizeof (struct ipcp_options));
1599 BZERO((char *) &ipcp_allowoptions[0], sizeof (struct ipcp_options));
1600
1601 return (1);
1602 }
1603
1604 /*
1605 * setdomain - set domain name to append to hostname. Returns 1 upon
1606 * successful processing of options, and 0 otherwise.
1607 */
1608 /*ARGSUSED*/
1609 static int
setdomain(argv,opt)1610 setdomain(argv, opt)
1611 char **argv;
1612 option_t *opt;
1613 {
1614 if (!privileged_option) {
1615 option_error("using the domain option requires root privilege");
1616 return (0);
1617 }
1618 (void) gethostname(hostname, MAXHOSTNAMELEN+1);
1619 if (**argv != '\0') {
1620 if (**argv != '.')
1621 (void) strncat(hostname, ".", MAXHOSTNAMELEN - strlen(hostname));
1622 (void) strncat(hostname, *argv, MAXHOSTNAMELEN - strlen(hostname));
1623 }
1624 hostname[MAXHOSTNAMELEN] = '\0';
1625 return (1);
1626 }
1627
1628
1629 /*
1630 * setspeed - set the speed. Returns 1 upon successful processing of options,
1631 * and 0 otherwise.
1632 */
1633 static int
setspeed(arg)1634 setspeed(arg)
1635 char *arg;
1636 {
1637 char *ptr;
1638 int spd;
1639
1640 if (prepass)
1641 return (1);
1642 spd = strtol(arg, &ptr, 0);
1643 if (ptr == arg || *ptr != '\0' || spd <= 0)
1644 return (0);
1645 inspeed = spd;
1646 save_source(&speed_info);
1647 return (1);
1648 }
1649
1650
1651 /*
1652 * setdevname - set the device name. Returns 1 upon successful processing of
1653 * options, 0 when the device does not exist, and -1 when an error is
1654 * encountered.
1655 */
1656 static int
setdevname(cp)1657 setdevname(cp)
1658 char *cp;
1659 {
1660 struct stat statbuf;
1661 char dev[MAXPATHLEN];
1662
1663 if (*cp == '\0')
1664 return (0);
1665
1666 if (strncmp("/dev/", cp, 5) != 0) {
1667 (void) strlcpy(dev, "/dev/", sizeof(dev));
1668 (void) strlcat(dev, cp, sizeof(dev));
1669 cp = dev;
1670 }
1671
1672 /*
1673 * Check if there is a character device by this name.
1674 */
1675 if (stat(cp, &statbuf) < 0) {
1676 if (errno == ENOENT) {
1677 return (0);
1678 }
1679 option_error("Couldn't stat '%s': %m", cp);
1680 return (-1);
1681 }
1682 if (!S_ISCHR(statbuf.st_mode)) {
1683 option_error("'%s' is not a character device", cp);
1684 return (-1);
1685 }
1686
1687 if (phase != PHASE_INITIALIZE) {
1688 option_error("device name cannot be changed after initialization");
1689 return (-1);
1690 } else if (devnam_fixed) {
1691 option_error("per-tty options file may not specify device name");
1692 return (-1);
1693 }
1694
1695 if (devnam_info.priv && !privileged_option) {
1696 option_error("device name %s from %s cannot be overridden",
1697 devnam, name_source(&devnam_info));
1698 return (-1);
1699 }
1700
1701 (void) strlcpy(devnam, cp, sizeof(devnam));
1702 devstat = statbuf;
1703 default_device = 0;
1704 save_source(&devnam_info);
1705
1706 return (1);
1707 }
1708
1709
1710 /*
1711 * setipaddr - set the IP address. Returns 1 upon successful processing of
1712 * options, 0 when the argument does not contain a `:', and -1 for error.
1713 */
1714 static int
setipaddr(arg)1715 setipaddr(arg)
1716 char *arg;
1717 {
1718 struct hostent *hp;
1719 char *colon;
1720 u_int32_t local, remote;
1721 ipcp_options *wo = &ipcp_wantoptions[0];
1722
1723 /*
1724 * IP address pair separated by ":".
1725 */
1726 if ((colon = strchr(arg, ':')) == NULL)
1727 return (0);
1728 if (prepass)
1729 return (1);
1730
1731 /*
1732 * If colon first character, then no local addr.
1733 */
1734 if (colon != arg) {
1735 *colon = '\0';
1736 if ((local = inet_addr(arg)) == (u_int32_t) -1) {
1737 if ((hp = gethostbyname(arg)) == NULL) {
1738 option_error("unknown host: %s", arg);
1739 return (-1);
1740 } else {
1741 BCOPY(hp->h_addr, &local, sizeof(local));
1742 }
1743 }
1744 if (bad_ip_adrs(local)) {
1745 option_error("bad local IP address %I", local);
1746 return (-1);
1747 }
1748 if (local != 0) {
1749 save_source(&ipsrc_info);
1750 wo->ouraddr = local;
1751 }
1752 *colon = ':';
1753 }
1754
1755 /*
1756 * If colon last character, then no remote addr.
1757 */
1758 if (*++colon != '\0') {
1759 if ((remote = inet_addr(colon)) == (u_int32_t) -1) {
1760 if ((hp = gethostbyname(colon)) == NULL) {
1761 option_error("unknown host: %s", colon);
1762 return (-1);
1763 } else {
1764 BCOPY(hp->h_addr, &remote, sizeof(remote));
1765 if (remote_name[0] == '\0')
1766 (void) strlcpy(remote_name, colon, sizeof(remote_name));
1767 }
1768 }
1769 if (bad_ip_adrs(remote)) {
1770 option_error("bad remote IP address %I", remote);
1771 return (-1);
1772 }
1773 if (remote != 0) {
1774 save_source(&ipdst_info);
1775 wo->hisaddr = remote;
1776 }
1777 }
1778
1779 return (1);
1780 }
1781
1782
1783 /*
1784 * setnetmask - set the netmask to be used on the interface. Returns 1 upon
1785 * successful processing of options, and 0 otherwise.
1786 */
1787 /*ARGSUSED*/
1788 static int
setnetmask(argv,opt)1789 setnetmask(argv, opt)
1790 char **argv;
1791 option_t *opt;
1792 {
1793 u_int32_t mask;
1794 int n;
1795 char *p;
1796
1797 /*
1798 * Unfortunately, if we use inet_addr, we can't tell whether
1799 * a result of all 1s is an error or a valid 255.255.255.255.
1800 */
1801 p = *argv;
1802 n = parse_dotted_ip(p, &mask);
1803
1804 mask = htonl(mask);
1805
1806 if (n == 0 || p[n] != 0 || (netmask & ~mask) != 0) {
1807 option_error("invalid netmask value '%s'", *argv);
1808 return (0);
1809 }
1810
1811 netmask = mask;
1812 return (1);
1813 }
1814
1815 /*
1816 * parse_dotted_ip - parse and convert the IP address string to make
1817 * sure it conforms to the dotted notation. Returns the length of
1818 * processed characters upon success, and 0 otherwise. If successful,
1819 * the converted IP address number is stored in vp, in the host byte
1820 * order.
1821 */
1822 int
parse_dotted_ip(cp,vp)1823 parse_dotted_ip(cp, vp)
1824 register char *cp;
1825 u_int32_t *vp;
1826 {
1827 register u_int32_t val, base, n;
1828 register char c;
1829 char *cp0 = cp;
1830 u_char parts[3], *pp = parts;
1831
1832 if ((*cp == '\0') || (vp == NULL))
1833 return (0); /* disallow null string in cp */
1834 *vp = 0;
1835 again:
1836 /*
1837 * Collect number up to ``.''. Values are specified as for C:
1838 * 0x=hex, 0=octal, other=decimal.
1839 */
1840 val = 0; base = 10;
1841 if (*cp == '0') {
1842 if (*++cp == 'x' || *cp == 'X')
1843 base = 16, cp++;
1844 else
1845 base = 8;
1846 }
1847 while ((c = *cp) != '\0') {
1848 if (isdigit(c)) {
1849 if ((c - '0') >= base)
1850 break;
1851 val = (val * base) + (c - '0');
1852 cp++;
1853 continue;
1854 }
1855 if (base == 16 && isxdigit(c)) {
1856 val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A'));
1857 cp++;
1858 continue;
1859 }
1860 break;
1861 }
1862 if (*cp == '.') {
1863 /*
1864 * Internet format:
1865 * a.b.c.d
1866 * a.b.c (with c treated as 16-bits)
1867 * a.b (with b treated as 24 bits)
1868 */
1869 if ((pp >= parts + 3) || (val > 0xff)) {
1870 return (0);
1871 }
1872 *pp++ = (u_char)val;
1873 cp++;
1874 goto again;
1875 }
1876 /*
1877 * Check for trailing characters.
1878 */
1879 if (*cp != '\0' && !isspace(*cp)) {
1880 return (0);
1881 }
1882 /*
1883 * Concoct the address according to the number of parts specified.
1884 */
1885 n = pp - parts;
1886 switch (n) {
1887 case 0: /* a -- 32 bits */
1888 break;
1889 case 1: /* a.b -- 8.24 bits */
1890 if (val > 0xffffff)
1891 return (0);
1892 val |= parts[0] << 24;
1893 break;
1894 case 2: /* a.b.c -- 8.8.16 bits */
1895 if (val > 0xffff)
1896 return (0);
1897 val |= (parts[0] << 24) | (parts[1] << 16);
1898 break;
1899 case 3: /* a.b.c.d -- 8.8.8.8 bits */
1900 if (val > 0xff)
1901 return (0);
1902 val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
1903 break;
1904 default:
1905 return (0);
1906 }
1907 *vp = val;
1908 return (cp - cp0);
1909 }
1910
1911 /*
1912 * setxonxoff - modify the asyncmap to include escaping XON and XOFF
1913 * characters used for software flow control. Returns 1 upon successful
1914 * processing of options, and 0 otherwise.
1915 */
1916 /*ARGSUSED*/
1917 static int
setxonxoff(argv,opt)1918 setxonxoff(argv, opt)
1919 char **argv;
1920 option_t *opt;
1921 {
1922 int xonxoff = 0x000A0000;
1923
1924 lcp_wantoptions[0].neg_asyncmap = 1;
1925 lcp_wantoptions[0].asyncmap |= xonxoff; /* escape ^S and ^Q */
1926 lcp_allowoptions[0].asyncmap |= xonxoff;
1927 xmit_accm[0][0] |= xonxoff;
1928 xmit_accm[0][4] |= xonxoff; /* escape 0x91 and 0x93 as well */
1929
1930 crtscts = -2;
1931 return (1);
1932 }
1933
1934 /*
1935 * setlogfile - open (or create) a file used for logging purposes. Returns 1
1936 * upon success, and 0 otherwise.
1937 */
1938 /*ARGSUSED*/
1939 static int
setlogfile(argv,opt)1940 setlogfile(argv, opt)
1941 char **argv;
1942 option_t *opt;
1943 {
1944 int fd, err;
1945
1946 if (!privileged_option)
1947 (void) seteuid(getuid());
1948 fd = open(*argv, O_WRONLY | O_APPEND | O_CREAT | O_EXCL, 0644);
1949 if (fd < 0 && errno == EEXIST)
1950 fd = open(*argv, O_WRONLY | O_APPEND);
1951 err = errno;
1952 if (!privileged_option)
1953 (void) seteuid(0);
1954 if (fd < 0) {
1955 errno = err;
1956 option_error("Can't open log file %s: %m", *argv);
1957 return (0);
1958 }
1959 if (log_to_file && log_to_fd >= 0)
1960 (void) close(log_to_fd);
1961 log_to_fd = fd;
1962 log_to_file = 1;
1963 early_log = 0;
1964 return (1);
1965 }
1966
1967 #ifdef PLUGIN
1968 /*
1969 * loadplugin - load and initialize the plugin. Returns 1 upon successful
1970 * processing of the plugin, and 0 otherwise.
1971 */
1972 /*ARGSUSED*/
1973 static int
loadplugin(argv,opt)1974 loadplugin(argv, opt)
1975 char **argv;
1976 option_t *opt;
1977 {
1978 char *arg = *argv;
1979 void *handle;
1980 const char *err;
1981 void (*init) __P((void));
1982
1983 handle = dlopen(arg, RTLD_GLOBAL | RTLD_NOW);
1984 if (handle == NULL) {
1985 err = dlerror();
1986 if (err != NULL)
1987 option_error("%s", err);
1988 option_error("Couldn't load plugin %s", arg);
1989 return (0);
1990 }
1991 init = (void (*)(void))dlsym(handle, "plugin_init");
1992 if (init == NULL) {
1993 option_error("%s has no initialization entry point", arg);
1994 (void) dlclose(handle);
1995 return (0);
1996 }
1997 info("Plugin %s loaded.", arg);
1998 (*init)();
1999 return (1);
2000 }
2001 #endif /* PLUGIN */
2002