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