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