2 * options.c - handles option processing for PPP.
4 * Copyright (c) 2000-2001 by Sun Microsystems, Inc.
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.
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
18 * Copyright (c) 1989 Carnegie Mellon University.
19 * All rights reserved.
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.
44 #include <sys/types.h>
46 #include <netinet/in.h>
47 #include <arpa/inet.h>
53 #include <pcap-int.h> /* XXX: To get struct pcap */
54 #endif /* PPP_FILTER */
57 #include "pathnames.h"
58 #include "patchlevel.h"
63 #if defined(ultrix) || defined(NeXT)
64 char *strdup
__P((char *));
68 * Option variables and default values.
71 int dflag
= 0; /* Tell libpcap we want debugging */
72 #endif /* PPP_FILTER */
73 int debug
= 0; /* Debug flag */
74 int kdebugflag
= 0; /* Tell kernel to print debug messages */
75 int default_device
= 1; /* Using /dev/tty or equivalent */
76 char devnam
[MAXPATHLEN
]; /* Device name */
77 int crtscts
= 0; /* Use hardware flow control */
78 bool modem
= 1; /* Use modem control lines */
79 int inspeed
= 0; /* Input/Output speed requested */
80 u_int32_t netmask
= 0; /* IP netmask to set on interface */
81 bool lockflag
= 0; /* Create lock file to lock the serial dev */
82 bool nodetach
= 0; /* Don't detach from controlling tty */
83 bool updetach
= 0; /* Detach once link is up */
84 char *initializer
= NULL
; /* Script to initialize physical link */
85 char *connect_script
= NULL
; /* Script to establish physical link */
86 char *disconnect_script
= NULL
; /* Script to disestablish physical link */
87 char *welcomer
= NULL
; /* Script to run after phys link estab. */
88 char *ptycommand
= NULL
; /* Command to run on other side of pty */
89 int maxconnect
= 0; /* Maximum connect time */
90 char user
[MAXNAMELEN
]; /* Username for PAP */
91 char passwd
[MAXSECRETLEN
]; /* Password for PAP */
92 bool persist
= 0; /* Reopen link after it goes down */
93 char our_name
[MAXNAMELEN
]; /* Our name for authentication purposes */
94 bool demand
= 0; /* do dial-on-demand */
95 char *ipparam
= NULL
; /* Extra parameter for ip up/down scripts */
96 int idle_time_limit
= 0; /* Disconnect if idle for this many seconds */
97 int holdoff
= 30; /* # seconds to pause before reconnecting */
98 bool holdoff_specified
; /* true if a holdoff value has been given */
99 bool notty
= 0; /* Stdin/out is not a tty */
100 char *pty_socket
= NULL
; /* Socket to connect to pty */
101 char *record_file
= NULL
; /* File to record chars sent/received */
103 bool sync_serial
= 0; /* Device is synchronous serial device */
104 int log_to_fd
= 1; /* send log messages to this fd too */
105 int maxfail
= 10; /* max # of unsuccessful connection attempts */
106 char linkname
[MAXPATHLEN
]; /* logical name for link */
107 bool tune_kernel
; /* may alter kernel settings */
108 int connect_delay
= 1000; /* wait this many ms after connect script */
109 int max_data_rate
; /* max bytes/sec through charshunt */
110 int req_unit
= -1; /* requested interface unit */
111 bool multilink
= 0; /* Enable multilink operation */
112 char *bundle_name
= NULL
; /* bundle name for multilink */
113 bool direct_tty
= 0; /* use standard input directly; not a tty */
115 /* Maximum depth of include files; prevents looping. */
116 #define MAXFILENESTING 10
118 struct option_info initializer_info
;
119 struct option_info connect_script_info
;
120 struct option_info disconnect_script_info
;
121 struct option_info welcomer_info
;
122 struct option_info devnam_info
;
123 struct option_info ptycommand_info
;
124 struct option_info ipsrc_info
;
125 struct option_info ipdst_info
;
126 struct option_info speed_info
;
129 struct bpf_program pass_filter
;/* Filter program for packets to pass */
130 struct bpf_program active_filter
; /* Filter program for link-active pkts */
131 pcap_t pc
; /* Fake struct pcap so we can compile expr */
132 #endif /* PPP_FILTER */
134 char *current_option
; /* the name of the option being parsed */
135 bool privileged_option
; /* set iff the current option came from root */
136 char *option_source
= NULL
; /* string saying where the option came from */
137 int option_line
= 0; /* line number in file */
138 bool log_to_file
; /* log_to_fd is a file opened by us */
139 bool log_to_specific_fd
; /* log_to_fd was specified by user option */
144 static int setdevname
__P((char *));
145 static int setipaddr
__P((char *));
146 static int setspeed
__P((char *));
147 static int noopt
__P((char **, option_t
*));
148 static int setdomain
__P((char **, option_t
*));
149 static int setnetmask
__P((char **, option_t
*));
150 static int setxonxoff
__P((char **, option_t
*));
151 static int readfile
__P((char **, option_t
*));
152 static int callfile
__P((char **, option_t
*));
153 static int showversion
__P((char **, option_t
*));
154 static int showhelp
__P((char **, option_t
*));
155 static int showalloptions
__P((char **, option_t
*));
156 static void usage
__P((void));
157 static int setlogfile
__P((char **, option_t
*));
159 static int loadplugin
__P((char **, option_t
*));
162 static int setpassfilter
__P((char **, option_t
*));
163 static int setactivefilter
__P((char **, option_t
*));
164 #endif /* PPP_FILTER */
165 static option_t
*find_option
__P((char *name
));
166 static int process_option
__P((option_t
*opt
, char **argv
, int sline
));
167 static int n_arguments
__P((option_t
*opt
));
168 static int number_option
__P((char *str
, u_int32_t
*valp
, int base
));
169 static u_int32_t opt_hash
__P((const void *key
));
170 static int opt_compare
__P((const void *p1
, const void *p2
));
172 typedef struct _opt_t
{
176 typedef struct _hashentry_t
{
177 struct _hashentry_t
*next
;
182 * A prime number describing the size of hash table.
184 #define OPTHASH_TBLSIZE 101
187 * Chained hash table containing pointers to available options.
189 static hashentry_t
*hash_tbl
[OPTHASH_TBLSIZE
] = { NULL
};
192 * Total number of entries in the hash table.
199 option_t general_options
[] = {
200 { "debug", o_int
, &debug
,
201 "Increase debugging level", OPT_INC
|OPT_NOARG
|1 },
202 { "-d", o_int
, &debug
,
203 "Increase debugging level", OPT_INC
|OPT_NOARG
|1 },
204 { "kdebug", o_int
, &kdebugflag
,
205 "Set kernel driver debug level" },
206 { "nodetach", o_bool
, &nodetach
,
207 "Don't detach from controlling tty", 1 },
208 { "-detach", o_bool
, &nodetach
,
209 "Don't detach from controlling tty", 1 },
210 { "updetach", o_bool
, &updetach
,
211 "Detach from controlling tty once link is up", 1 },
212 { "holdoff", o_int
, &holdoff
,
213 "Set time in seconds before retrying connection" },
214 { "idle", o_int
, &idle_time_limit
,
215 "Set time in seconds before disconnecting idle link" },
216 { "lock", o_bool
, &lockflag
,
217 "Lock serial device with UUCP-style lock file", 1 },
218 { "-all", o_special_noarg
, (void *)noopt
,
219 "Don't request/allow any LCP or IPCP options (useless)" },
220 { "init", o_string
, &initializer
,
221 "A program to initialize the device",
222 OPT_A2INFO
| OPT_PRIVFIX
, &initializer_info
},
223 { "connect", o_string
, &connect_script
,
224 "A program to set up a connection",
225 OPT_A2INFO
| OPT_PRIVFIX
, &connect_script_info
},
226 { "disconnect", o_string
, &disconnect_script
,
227 "Program to disconnect serial device",
228 OPT_A2INFO
| OPT_PRIVFIX
, &disconnect_script_info
},
229 { "welcome", o_string
, &welcomer
,
230 "Script to welcome client",
231 OPT_A2INFO
| OPT_PRIVFIX
, &welcomer_info
},
232 { "pty", o_string
, &ptycommand
,
233 "Script to run on pseudo-tty master side",
234 OPT_A2INFO
| OPT_PRIVFIX
| OPT_DEVNAM
, &ptycommand_info
},
235 { "notty", o_bool
, ¬ty
,
236 "Input/output is not a tty", OPT_DEVNAM
| 1 },
237 { "directtty", o_bool
, &direct_tty
,
238 "Use standard input as tty without checking", OPT_DEVNAM
| 1 },
239 { "socket", o_string
, &pty_socket
,
240 "Send and receive over socket, arg is host:port", OPT_DEVNAM
},
241 { "record", o_string
, &record_file
,
242 "Record characters sent/received to file" },
243 { "maxconnect", o_int
, &maxconnect
,
244 "Set connection time limit", OPT_LLIMIT
|OPT_NOINCR
|OPT_ZEROINF
},
245 { "crtscts", o_int
, &crtscts
,
246 "Set hardware (RTS/CTS) flow control", OPT_NOARG
|OPT_VAL(1) },
247 { "nocrtscts", o_int
, &crtscts
,
248 "Disable hardware flow control", OPT_NOARG
|OPT_VAL(-1) },
249 { "-crtscts", o_int
, &crtscts
,
250 "Disable hardware flow control", OPT_NOARG
|OPT_VAL(-1) },
251 { "cdtrcts", o_int
, &crtscts
,
252 "Set alternate hardware (DTR/CTS) flow control", OPT_NOARG
|OPT_VAL(2) },
253 { "nocdtrcts", o_int
, &crtscts
,
254 "Disable hardware flow control", OPT_NOARG
|OPT_VAL(-1) },
255 { "xonxoff", o_special_noarg
, (void *)setxonxoff
,
256 "Set software (XON/XOFF) flow control" },
257 { "domain", o_special
, (void *)setdomain
,
258 "Add given domain name to hostname" },
259 { "netmask", o_special
, (void *)setnetmask
,
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 */
324 { "plugin", o_special
, (void *)loadplugin
,
325 "Load a plug-in module into pppd", OPT_PRIV
},
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 */
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.
345 static const char pre_allopt_string
[] = "\
346 pppd version %s.%d%s\n\
347 Usage: %s [ options ], where options are:\n\n\
350 /* Do not call add_options() on this structure */
351 static option_t dummy_options
[] = {
352 { "<device>", o_special_noarg
, NULL
,
353 "Communicate over the named device" },
354 { "<speed>", o_special_noarg
, NULL
,
355 "Set the baud rate to <speed>" },
356 { "[<loc>]:[<rem>]", o_special_noarg
, NULL
,
357 "Set the local and/or remote interface IP addresses" },
361 static const char post_allopt_string
[] = "\
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\
373 Please see the pppd man page for details.\n";
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.
382 parse_args(argc
, argv
)
390 privileged_option
= privileged
;
391 option_source
= "command line";
398 * First check to see if it's a known option name. If so, parse the
399 * argument(s) and set the option.
401 opt
= find_option(arg
);
403 int n
= n_arguments(opt
);
405 option_error("too few parameters for option '%s'", arg
);
408 current_option
= arg
;
409 if (!process_option(opt
, argv
, 0))
417 * Maybe a tty name, speed or IP address ?
419 if (((ret
= setdevname(arg
)) == 0) &&
420 ((ret
= setspeed(arg
)) == 0) &&
421 ((ret
= setipaddr(arg
)) == 0) && !prepass
) {
422 option_error("unrecognized option '%s'", arg
);
426 if (ret
< 0) /* error */
433 * options_from_file - read a string of options from a file, and
434 * interpret them. Returns 1 upon successful processing of options,
440 (char *filename
, bool must_exist
, bool check_prot
, bool priv
)
442 (filename
, must_exist
, check_prot
, priv
)
450 int i
, newline
, ret
, err
;
456 char args
[MAXARGS
][MAXWORDLEN
];
457 char cmd
[MAXWORDLEN
];
458 static bool firsterr
= 1;
459 static int nestlevel
= 0;
461 if (nestlevel
>= MAXFILENESTING
) {
462 option_error("file nesting too deep");
466 (void) seteuid(getuid());
468 f
= fopen(filename
, "r");
473 if (!must_exist
&& err
== ENOENT
)
476 option_error("Can't open options file %s: %m", filename
);
481 oldpriv
= privileged_option
;
482 privileged_option
= priv
;
483 oldsource
= option_source
;
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.
489 option_source
= strdup(filename
);
490 oldline
= option_line
;
492 if (option_source
== NULL
)
493 option_source
= "file";
495 while (getword(f
, cmd
, &newline
, filename
)) {
498 * First see if it's a command.
500 opt
= find_option(cmd
);
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
);
510 current_option
= cmd
;
511 if ((opt
->flags
& OPT_DEVEQUIV
) && devnam_fixed
) {
512 option_error("the '%s' option may not be used here", cmd
);
515 if (!process_option(opt
, argv
, sline
))
521 * Maybe a tty name, speed or IP address ?
523 if (((i
= setdevname(cmd
)) == 0) &&
524 ((i
= setspeed(cmd
)) == 0) &&
525 ((i
= setipaddr(cmd
)) == 0)) {
526 option_error("unrecognized option '%s'", cmd
);
529 if (i
< 0) /* error */
536 /* We assume here that we abort all processing on the first error. */
539 else if (!prepass
&& !ret
)
540 option_error("error in included file");
542 * Cannot free option_source because it might be referenced in one
543 * or more option_info structures now.
545 privileged_option
= oldpriv
;
546 option_source
= oldsource
;
547 option_line
= oldline
;
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.
560 char *user
, *path
, *file
;
565 pw
= getpwuid(getuid());
566 if (pw
== NULL
|| (user
= pw
->pw_dir
) == NULL
|| user
[0] == '\0')
568 file
= _PATH_USEROPT
;
569 pl
= strlen(user
) + strlen(file
) + 2;
572 novm("init file name");
573 (void) slprintf(path
, pl
, "%s/%s", user
, file
);
574 ret
= options_from_file(path
, 0, 1, privileged
);
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.
587 char *dev
, *path
, *p
;
592 if (strncmp(dev
, "/dev/", 5) == 0)
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;
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
)
605 ret
= options_from_file(path
, 0, 0, 1);
611 * options_from_list - process a string of options in a wordlist. Returns 1
612 * upon successful processing of options, and 0 otherwise.
617 (struct wordlist
*w
, bool priv
)
628 privileged_option
= priv
;
630 /* Caller is expected to set option_source and option_line. */
634 * First see if it's a command.
636 opt
= find_option(w
->word
);
638 int n
= n_arguments(opt
);
639 struct wordlist
*w0
= w
;
640 for (i
= 0; i
< n
; ++i
) {
643 option_error("too few parameters for option '%s'",
649 current_option
= w0
->word
;
650 if (!process_option(opt
, argv
, option_line
))
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.
660 if ((i
= setipaddr(w
->word
)) == 0) {
661 option_error("unrecognized option '%s'", w
->word
);
664 if (i
< 0) /* error */
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.
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
);
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.
702 process_option(opt
, argv
, sline
)
710 int (*parser
) __P((char **, option_t
*));
712 if ((opt
->flags
& OPT_PREPASS
) == 0 && prepass
)
714 if ((opt
->flags
& OPT_INITONLY
) && phase
!= PHASE_INITIALIZE
) {
715 option_error("it's too late to use the '%s' option", opt
->name
);
718 if ((opt
->flags
& OPT_PRIV
) && !privileged_option
) {
719 option_error("using the '%s' option requires root privilege",
723 if ((opt
->flags
& OPT_ENABLE
) && !privileged_option
&&
724 *(bool *)(opt
->addr2
) == 0) {
725 option_error("'%s' option is disabled", opt
->name
);
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
);
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);
746 if ((opt
->flags
& OPT_NOARG
) == 0) {
747 if (!int_option(*argv
, &iv
))
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
) {
755 option_error("%s value must be%s >= %d",
756 opt
->name
, zok
, opt
->lower_limit
);
759 option_error("%s value must be%s <= %d",
760 opt
->name
, zok
, opt
->upper_limit
);
763 option_error("%s value must be%s between %d and %d",
764 opt
->name
, zok
, opt
->lower_limit
, opt
->upper_limit
);
770 a
= opt
->flags
& OPT_VALUE
;
772 a
-= 256; /* sign extend */
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
);
779 if ((opt
->flags
& OPT_ZEROINF
) && (iv
== 0)) {
781 option_error("%s value cannot be set to infinity; limited to %d",
785 } else if (iv
> oldv
) {
786 option_error("%s value cannot be increased beyond %d",
791 *(int *)(opt
->addr
) = iv
;
792 if ((opt
->addr2
!= NULL
) && (opt
->flags
& OPT_A2COPY
))
793 *(int *)(opt
->addr2
) = iv
;
797 if (opt
->flags
& OPT_NOARG
) {
798 v
= opt
->flags
& OPT_VALUE
;
799 } else if (!number_option(*argv
, &v
, 16))
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
;
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
);
817 novm("option argument");
818 *(char **)(opt
->addr
) = sv
;
819 if (opt
->addr2
!= NULL
&& (opt
->flags
& OPT_A2COPY
))
820 *(char **)(opt
->addr2
) = sv
;
824 case o_special_noarg
:
826 parser
= (int (*) __P((char **, option_t
*))) opt
->addr
;
827 if (!(*parser
)(argv
, opt
))
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
;
838 } else if ((opt
->flags
& (OPT_A2COPY
|OPT_ENABLE
)) == 0)
839 *(bool *)(opt
->addr2
) = 1;
846 * n_arguments - tell how many arguments an option takes. Returns 1 upon
847 * successful processing of options, and 0 otherwise.
853 return ((opt
->type
== o_bool
|| opt
->type
== o_special_noarg
||
854 (opt
->flags
& OPT_NOARG
)) ? 0 : 1);
858 * opt_hash - a hash function that works quite well for strings. Returns
859 * the hash key of the supplied string.
865 register const char *ptr
;
866 register u_int32_t val
;
870 while (*ptr
!= '\0') {
872 val
= (val
<< 4) + (*ptr
);
873 tmp
= val
& 0xf0000000;
880 return (val
% OPTHASH_TBLSIZE
);
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.
892 register option_t
*sopt
;
893 register hashentry_t
*bucket
;
894 register u_int32_t loc
;
897 /* fill hash-table */
898 for (sopt
= opt
; sopt
->name
!= NULL
; ++sopt
, hash_tblcnt
++) {
900 /* first, allocate a hash entry */
901 he
= (hashentry_t
*)malloc(sizeof(*he
));
903 novm("option hash table entry");
909 * fill the chained hash table and take care of any collisions or
912 loc
= opt_hash(sopt
->name
);
913 bucket
= hash_tbl
[loc
];
914 if (bucket
!= NULL
) {
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",
920 bucket
->opt
.p
->flags
|= OPT_DISABLE
;
922 if (bucket
->next
== NULL
)
924 bucket
= bucket
->next
;
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.
944 if ((opt
= find_option(name
)) != NULL
) {
945 opt
->flags
|= OPT_DISABLE
;
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.
961 opt_t
*o1
= (opt_t
*)p1
;
962 opt_t
*o2
= (opt_t
*)p2
;
964 return (strcmp(o1
->p
->name
, o2
->p
->name
));
969 showalloptions(argv
, topt
)
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)); \
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)); \
989 (void) printf("%-26s%s\n", opt_str, opt->description); \
992 char opt_str
[MAXOPTSTRLEN
];
998 if (phase
!= PHASE_INITIALIZE
) {
1001 (void) printf(pre_allopt_string
, VERSION
, PATCHLEVEL
, IMPLEMENTATION
,
1003 for (opt
= dummy_options
; opt
->name
!= NULL
; ++opt
) {
1007 sopt
= malloc(sizeof(*sopt
) * hash_tblcnt
);
1009 novm("sorted option table");
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");
1018 sopt
[sofar
++].p
= bucket
->opt
.p
;
1022 qsort((void *)sopt
, sofar
, sizeof(sopt
[0]), opt_compare
);
1023 for (i
= 0; i
< sofar
; i
++) {
1028 (void) printf(post_allopt_string
);
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
1044 static const char usage_string
[] = "\
1045 pppd version %s.%d%s\n\
1046 Usage: %s [ options ], where options are:\n\
1047 \t<device>\tCommunicate over the named device\n\
1048 \t<speed>\t\tSet the baud rate to <speed>\n\
1049 \t<loc>:<rem>\tSet the local and/or remote interface IP\n\
1050 \t\t\taddresses. Either one may be omitted.\n\
1051 \tnoauth\t\tDon't require authentication from peer\n\
1052 \tconnect <p>\tInvoke shell command <p> to set up the serial line\n\
1053 \tdefaultroute\tAdd default route through interface\n\
1054 Use \"%s options\" or \"man pppd\" for more options.\n\
1057 if (phase
== PHASE_INITIALIZE
)
1058 (void) fprintf(stderr
, usage_string
, VERSION
, PATCHLEVEL
,
1059 IMPLEMENTATION
, progname
, progname
);
1063 * showhelp - print out usage message and exit program upon success, or
1064 * return 0 otherwise.
1072 if (phase
== PHASE_INITIALIZE
) {
1080 * showversion - print out the version number and exit program upon success,
1081 * or return 0 otherwise.
1085 showversion(argv
, opt
)
1089 if (phase
== PHASE_INITIALIZE
) {
1090 (void) fprintf(stderr
, "pppd version %s.%d%s\n", VERSION
, PATCHLEVEL
,
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.
1102 option_error
__V((char *fmt
, ...))
1108 #if defined(__STDC__)
1109 va_start(args
, fmt
);
1113 fmt
= va_arg(args
, char *);
1120 if (option_source
== NULL
) {
1122 } else if (option_line
<= 0) {
1123 (void) strlcpy(buf
, option_source
, sizeof (buf
));
1126 i
= slprintf(buf
, sizeof(buf
), "%s:%d", option_source
, option_line
);
1129 (void) strlcat(buf
, ": ", sizeof (buf
));
1133 (void) vslprintf(buf
+ i
, sizeof (buf
) - i
, fmt
, args
);
1135 if ((phase
== PHASE_INITIALIZE
) && !detached
)
1136 (void) fprintf(stderr
, "%s: %s\n", progname
, buf
);
1137 syslog(LOG_ERR
, "%s", buf
);
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,
1147 getword(f
, word
, newlinep
, filename
)
1154 int quoted
, comment
;
1155 int value
, digit
, got
, n
;
1157 #define isoctal(c) ((c) >= '0' && (c) < '8')
1165 * First skip white-space and comments.
1173 * A newline means the end of a comment; backslash-newline
1174 * is ignored. Note that we cannot have escape && comment.
1187 * Ignore characters other than newline in a comment.
1193 * If this character is escaped, we have a word start.
1199 * If this is the escape character, look at the next character.
1207 * If this is the start of a comment, ignore the rest of the line.
1215 * A non-whitespace character is the start of a word.
1222 * Save the delimiter for quoted strings.
1224 if (!escape
&& (c
== '"' || c
== '\'')) {
1231 * Process characters until the end of the word.
1236 * This character is escaped: backslash-newline is ignored,
1237 * various other characters indicate particular values
1238 * as for C backslash-escapes.
1273 * \ddd octal sequence
1276 for (n
= 0; n
< 3 && isoctal(c
); ++n
) {
1277 value
= (value
<< 3) + (c
& 07);
1286 * \x<hex_string> sequence
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
;
1302 * Otherwise the character stands for itself.
1309 * Store the resulting character for the escape sequence.
1311 if (len
< MAXWORDLEN
) {
1323 * Not escaped: see if we've reached the end of the word.
1329 if (isspace(c
) || c
== '#') {
1330 (void) ungetc (c
, f
);
1336 * Backslash starts an escape sequence.
1345 * An ordinary character: store it in the word and get another.
1347 if (len
< MAXWORDLEN
) {
1356 * End of the word: check for errors.
1362 option_error("Error reading %s: %m", filename
);
1366 * If len is zero, then we didn't find a word before the
1374 * Warn if the word was too long, and append a terminating null.
1376 if (len
>= MAXWORDLEN
) {
1377 option_error("warning: word in file %s too long (%.20s...)",
1379 len
= MAXWORDLEN
- 1;
1390 * number_option - parse an unsigned numeric parameter for an option.
1391 * Returns 1 upon successful processing of options, and 0 otherwise.
1394 number_option(str
, valp
, base
)
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
);
1411 * save_source - store option source, line, and privilege into an
1412 * option_info structure.
1416 struct option_info
*info
;
1418 info
->priv
= privileged_option
;
1419 info
->source
= option_source
;
1420 info
->line
= option_line
;
1424 * set_source - set option source, line, and privilege from an
1425 * option_info structure.
1429 struct option_info
*info
;
1431 privileged_option
= info
->priv
;
1432 option_source
= info
->source
;
1433 option_line
= info
->line
;
1437 * name_source - return string containing option source and line. Can
1438 * be used as part of an option_error call.
1442 struct option_info
*info
;
1444 static char buf
[MAXPATHLEN
];
1446 if (info
->source
== NULL
)
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
;
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.
1460 int_option(str
, valp
)
1466 if (!number_option(str
, &v
, 0))
1474 * The following procedures parse options.
1478 * readfile - take commands from a file.
1486 return (options_from_file(*argv
, 1, 1, privileged_option
));
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.
1500 char *fname
, *arg
, *p
;
1505 if (arg
[0] == '/' || arg
[0] == '\0')
1508 for (p
= arg
; *p
!= '\0'; ) {
1509 if (p
[0] == '.' && p
[1] == '.' && (p
[2] == '/' || p
[2] == '\0')) {
1513 while (*p
!= '/' && *p
!= '\0')
1520 option_error("call option value may not contain .. or start with /");
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
);
1529 ok
= options_from_file(fname
, 1, 1, 1);
1537 * setpdebug - set libpcap debugging level. Returns 1 upon successful
1538 * processing of options, and 0 otherwise.
1544 return (int_option(*argv
, &dflag
));
1548 * setpassfilter - set the pass filter for packets. Returns 1 upon successful
1549 * processing of options, and 0 otherwise.
1553 setpassfilter(argv
, opt
)
1557 pc
.linktype
= DLT_PPP
;
1558 pc
.snapshot
= PPP_HDRLEN
;
1560 if (pcap_compile(&pc
, &pass_filter
, *argv
, 1, netmask
) == 0)
1562 option_error("error in pass-filter expression: %s\n", pcap_geterr(&pc
));
1567 * setactivefilter - set the active filter for packets. Returns 1 upon
1568 * successful processing of options, and 0 otherwise.
1572 setactivefilter(argv
, opt
)
1576 pc
.linktype
= DLT_PPP
;
1577 pc
.snapshot
= PPP_HDRLEN
;
1579 if (pcap_compile(&pc
, &active_filter
, *argv
, 1, netmask
) == 0)
1581 option_error("error in active-filter expression: %s\n", pcap_geterr(&pc
));
1584 #endif /* PPP_FILTER */
1587 * noopt - disable all options. Returns 1 upon successful processing of
1588 * options, and 0 otherwise.
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
));
1605 * setdomain - set domain name to append to hostname. Returns 1 upon
1606 * successful processing of options, and 0 otherwise.
1610 setdomain(argv
, opt
)
1614 if (!privileged_option
) {
1615 option_error("using the domain option requires root privilege");
1618 (void) gethostname(hostname
, MAXHOSTNAMELEN
+1);
1619 if (**argv
!= '\0') {
1621 (void) strncat(hostname
, ".", MAXHOSTNAMELEN
- strlen(hostname
));
1622 (void) strncat(hostname
, *argv
, MAXHOSTNAMELEN
- strlen(hostname
));
1624 hostname
[MAXHOSTNAMELEN
] = '\0';
1630 * setspeed - set the speed. Returns 1 upon successful processing of options,
1642 spd
= strtol(arg
, &ptr
, 0);
1643 if (ptr
== arg
|| *ptr
!= '\0' || spd
<= 0)
1646 save_source(&speed_info
);
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
1660 struct stat statbuf
;
1661 char dev
[MAXPATHLEN
];
1666 if (strncmp("/dev/", cp
, 5) != 0) {
1667 (void) strlcpy(dev
, "/dev/", sizeof(dev
));
1668 (void) strlcat(dev
, cp
, sizeof(dev
));
1673 * Check if there is a character device by this name.
1675 if (stat(cp
, &statbuf
) < 0) {
1676 if (errno
== ENOENT
) {
1679 option_error("Couldn't stat '%s': %m", cp
);
1682 if (!S_ISCHR(statbuf
.st_mode
)) {
1683 option_error("'%s' is not a character device", cp
);
1687 if (phase
!= PHASE_INITIALIZE
) {
1688 option_error("device name cannot be changed after initialization");
1690 } else if (devnam_fixed
) {
1691 option_error("per-tty options file may not specify device name");
1695 if (devnam_info
.priv
&& !privileged_option
) {
1696 option_error("device name %s from %s cannot be overridden",
1697 devnam
, name_source(&devnam_info
));
1701 (void) strlcpy(devnam
, cp
, sizeof(devnam
));
1704 save_source(&devnam_info
);
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.
1720 u_int32_t local
, remote
;
1721 ipcp_options
*wo
= &ipcp_wantoptions
[0];
1724 * IP address pair separated by ":".
1726 if ((colon
= strchr(arg
, ':')) == NULL
)
1732 * If colon first character, then no local addr.
1736 if ((local
= inet_addr(arg
)) == (u_int32_t
) -1) {
1737 if ((hp
= gethostbyname(arg
)) == NULL
) {
1738 option_error("unknown host: %s", arg
);
1741 BCOPY(hp
->h_addr
, &local
, sizeof(local
));
1744 if (bad_ip_adrs(local
)) {
1745 option_error("bad local IP address %I", local
);
1749 save_source(&ipsrc_info
);
1750 wo
->ouraddr
= local
;
1756 * If colon last character, then no remote addr.
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
);
1764 BCOPY(hp
->h_addr
, &remote
, sizeof(remote
));
1765 if (remote_name
[0] == '\0')
1766 (void) strlcpy(remote_name
, colon
, sizeof(remote_name
));
1769 if (bad_ip_adrs(remote
)) {
1770 option_error("bad remote IP address %I", remote
);
1774 save_source(&ipdst_info
);
1775 wo
->hisaddr
= remote
;
1784 * setnetmask - set the netmask to be used on the interface. Returns 1 upon
1785 * successful processing of options, and 0 otherwise.
1789 setnetmask(argv
, opt
)
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.
1802 n
= parse_dotted_ip(p
, &mask
);
1806 if (n
== 0 || p
[n
] != 0 || (netmask
& ~mask
) != 0) {
1807 option_error("invalid netmask value '%s'", *argv
);
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
1823 parse_dotted_ip(cp
, vp
)
1827 register u_int32_t val
, base
, n
;
1830 u_char parts
[3], *pp
= parts
;
1832 if ((*cp
== '\0') || (vp
== NULL
))
1833 return (0); /* disallow null string in cp */
1837 * Collect number up to ``.''. Values are specified as for C:
1838 * 0x=hex, 0=octal, other=decimal.
1842 if (*++cp
== 'x' || *cp
== 'X')
1847 while ((c
= *cp
) != '\0') {
1849 if ((c
- '0') >= base
)
1851 val
= (val
* base
) + (c
- '0');
1855 if (base
== 16 && isxdigit(c
)) {
1856 val
= (val
<< 4) + (c
+ 10 - (islower(c
) ? 'a' : 'A'));
1866 * a.b.c (with c treated as 16-bits)
1867 * a.b (with b treated as 24 bits)
1869 if ((pp
>= parts
+ 3) || (val
> 0xff)) {
1872 *pp
++ = (u_char
)val
;
1877 * Check for trailing characters.
1879 if (*cp
!= '\0' && !isspace(*cp
)) {
1883 * Concoct the address according to the number of parts specified.
1887 case 0: /* a -- 32 bits */
1889 case 1: /* a.b -- 8.24 bits */
1892 val
|= parts
[0] << 24;
1894 case 2: /* a.b.c -- 8.8.16 bits */
1897 val
|= (parts
[0] << 24) | (parts
[1] << 16);
1899 case 3: /* a.b.c.d -- 8.8.8.8 bits */
1902 val
|= (parts
[0] << 24) | (parts
[1] << 16) | (parts
[2] << 8);
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.
1918 setxonxoff(argv
, opt
)
1922 int xonxoff
= 0x000A0000;
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 */
1935 * setlogfile - open (or create) a file used for logging purposes. Returns 1
1936 * upon success, and 0 otherwise.
1940 setlogfile(argv
, opt
)
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
);
1952 if (!privileged_option
)
1956 option_error("Can't open log file %s: %m", *argv
);
1959 if (log_to_file
&& log_to_fd
>= 0)
1960 (void) close(log_to_fd
);
1969 * loadplugin - load and initialize the plugin. Returns 1 upon successful
1970 * processing of the plugin, and 0 otherwise.
1974 loadplugin(argv
, opt
)
1981 void (*init
) __P((void));
1983 handle
= dlopen(arg
, RTLD_GLOBAL
| RTLD_NOW
);
1984 if (handle
== NULL
) {
1987 option_error("%s", err
);
1988 option_error("Couldn't load plugin %s", arg
);
1991 init
= (void (*)(void))dlsym(handle
, "plugin_init");
1993 option_error("%s has no initialization entry point", arg
);
1994 (void) dlclose(handle
);
1997 info("Plugin %s loaded.", arg
);