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