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