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)
64char *strdup __P((char *));
65#endif
66
67/*
68 * Option variables and default values.
69 */
70#ifdef PPP_FILTER
71int	dflag = 0;		/* Tell libpcap we want debugging */
72#endif /* PPP_FILTER */
73int	debug = 0;		/* Debug flag */
74int	kdebugflag = 0;		/* Tell kernel to print debug messages */
75int	default_device = 1;	/* Using /dev/tty or equivalent */
76char	devnam[MAXPATHLEN];	/* Device name */
77int	crtscts = 0;		/* Use hardware flow control */
78bool	modem = 1;		/* Use modem control lines */
79int	inspeed = 0;		/* Input/Output speed requested */
80u_int32_t netmask = 0;		/* IP netmask to set on interface */
81bool	lockflag = 0;		/* Create lock file to lock the serial dev */
82bool	nodetach = 0;		/* Don't detach from controlling tty */
83bool	updetach = 0;		/* Detach once link is up */
84char	*initializer = NULL;	/* Script to initialize physical link */
85char	*connect_script = NULL;	/* Script to establish physical link */
86char	*disconnect_script = NULL; /* Script to disestablish physical link */
87char	*welcomer = NULL;	/* Script to run after phys link estab. */
88char	*ptycommand = NULL;	/* Command to run on other side of pty */
89int	maxconnect = 0;		/* Maximum connect time */
90char	user[MAXNAMELEN];	/* Username for PAP */
91char	passwd[MAXSECRETLEN];	/* Password for PAP */
92bool	persist = 0;		/* Reopen link after it goes down */
93char	our_name[MAXNAMELEN];	/* Our name for authentication purposes */
94bool	demand = 0;		/* do dial-on-demand */
95char	*ipparam = NULL;	/* Extra parameter for ip up/down scripts */
96int	idle_time_limit = 0;	/* Disconnect if idle for this many seconds */
97int	holdoff = 30;		/* # seconds to pause before reconnecting */
98bool	holdoff_specified;	/* true if a holdoff value has been given */
99bool	notty = 0;		/* Stdin/out is not a tty */
100char	*pty_socket = NULL;	/* Socket to connect to pty */
101char	*record_file = NULL;	/* File to record chars sent/received */
102int	using_pty = 0;
103bool	sync_serial = 0;	/* Device is synchronous serial device */
104int	log_to_fd = 1;		/* send log messages to this fd too */
105int	maxfail = 10;		/* max # of unsuccessful connection attempts */
106char	linkname[MAXPATHLEN];	/* logical name for link */
107bool	tune_kernel;		/* may alter kernel settings */
108int	connect_delay = 1000;	/* wait this many ms after connect script */
109int	max_data_rate;		/* max bytes/sec through charshunt */
110int	req_unit = -1;		/* requested interface unit */
111bool	multilink = 0;		/* Enable multilink operation */
112char	*bundle_name = NULL;	/* bundle name for multilink */
113bool	direct_tty = 0;		/* use standard input directly; not a tty */
114
115/* Maximum depth of include files; prevents looping. */
116#define	MAXFILENESTING	10
117
118struct option_info initializer_info;
119struct option_info connect_script_info;
120struct option_info disconnect_script_info;
121struct option_info welcomer_info;
122struct option_info devnam_info;
123struct option_info ptycommand_info;
124struct option_info ipsrc_info;
125struct option_info ipdst_info;
126struct option_info speed_info;
127
128#ifdef PPP_FILTER
129struct	bpf_program pass_filter;/* Filter program for packets to pass */
130struct	bpf_program active_filter; /* Filter program for link-active pkts */
131pcap_t  pc;			/* Fake struct pcap so we can compile expr */
132#endif /* PPP_FILTER */
133
134char *current_option;		/* the name of the option being parsed */
135bool privileged_option;		/* set iff the current option came from root */
136char *option_source = NULL;	/* string saying where the option came from */
137int option_line = 0;		/* line number in file */
138bool log_to_file;		/* log_to_fd is a file opened by us */
139bool log_to_specific_fd;	/* log_to_fd was specified by user option */
140
141/*
142 * Prototypes.
143 */
144static int setdevname __P((char *));
145static int setipaddr __P((char *));
146static int setspeed __P((char *));
147static int noopt __P((char **, option_t *));
148static int setdomain __P((char **, option_t *));
149static int setnetmask __P((char **, option_t *));
150static int setxonxoff __P((char **, option_t *));
151static int readfile __P((char **, option_t *));
152static int callfile __P((char **, option_t *));
153static int showversion __P((char **, option_t *));
154static int showhelp __P((char **, option_t *));
155static int showalloptions __P((char **, option_t *));
156static void usage __P((void));
157static int setlogfile __P((char **, option_t *));
158#ifdef PLUGIN
159static int loadplugin __P((char **, option_t *));
160#endif
161#ifdef PPP_FILTER
162static int setpassfilter __P((char **, option_t *));
163static int setactivefilter __P((char **, option_t *));
164#endif /* PPP_FILTER */
165static option_t *find_option __P((char *name));
166static int process_option __P((option_t *opt, char **argv, int sline));
167static int n_arguments __P((option_t *opt));
168static int number_option __P((char *str, u_int32_t *valp, int base));
169static u_int32_t opt_hash __P((const void *key));
170static int opt_compare __P((const void *p1, const void *p2));
171
172typedef struct _opt_t {
173    option_t	*p;
174} opt_t;
175
176typedef 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 */
189static hashentry_t *hash_tbl[OPTHASH_TBLSIZE] = { NULL };
190
191/*
192 * Total number of entries in the hash table.
193 */
194int hash_tblcnt = 0;
195
196/*
197 * Valid arguments.
198 */
199option_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, &notty,
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 */
345static const char pre_allopt_string[] = "\
346pppd version %s.%d%s\n\
347Usage: %s [ options ], where options are:\n\n\
348";
349
350/* Do not call add_options() on this structure */
351static 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
361static const char post_allopt_string[] = "\
362\n\
363Notes:\
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\
373Please 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 */
381int
382parse_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 */
437int
438options_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
534err:
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 */
557int
558options_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 */
584int
585options_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 */
614int
615options_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
669err:
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 */
678static option_t *
679find_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 */
701static int
702process_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 */
849static int
850n_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 */
861static u_int32_t
862opt_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 */
888void
889add_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 */
938option_t *
939remove_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 */
956static int
957opt_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*/
968static int
969showalloptions(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 */
1041static void
1042usage()
1043{
1044	static const char usage_string[] = "\
1045pppd version %s.%d%s\n\
1046Usage: %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\
1054Use \"%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*/
1067static int
1068showhelp(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*/
1084static int
1085showversion(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 */
1101void
1102option_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 */
1146int
1147getword(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 */
1393static int
1394number_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 */
1414void
1415save_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 */
1427void
1428set_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 */
1440const char *
1441name_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 */
1459int
1460int_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*/
1481static int
1482readfile(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*/
1495static int
1496callfile(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 */
1540static int
1541setpdebug(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*/
1552static int
1553setpassfilter(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*/
1571static int
1572setactivefilter(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*/
1591static int
1592noopt(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*/
1609static int
1610setdomain(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 */
1633static int
1634setspeed(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 */
1656static int
1657setdevname(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 */
1714static int
1715setipaddr(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*/
1788static int
1789setnetmask(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 */
1822int
1823parse_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;
1835again:
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*/
1917static int
1918setxonxoff(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*/
1939static int
1940setlogfile(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*/
1973static int
1974loadplugin(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