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