1/* 2 * options.c - handles option processing for PPP. 3 * 4 * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 18 * 3. The name "Carnegie Mellon University" must not be used to 19 * endorse or promote products derived from this software without 20 * prior written permission. For permission or any legal 21 * details, please contact 22 * Office of Technology Transfer 23 * Carnegie Mellon University 24 * 5000 Forbes Avenue 25 * Pittsburgh, PA 15213-3890 26 * (412) 268-4387, fax: (412) 268-7395 27 * tech-transfer@andrew.cmu.edu 28 * 29 * 4. Redistributions of any form whatsoever must retain the following 30 * acknowledgment: 31 * "This product includes software developed by Computing Services 32 * at Carnegie Mellon University (http://www.cmu.edu/computing/)." 33 * 34 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO 35 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 36 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE 37 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 38 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 39 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 40 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 41 */ 42 43#define RCSID "$Id: options.c,v 1.102 2008/06/15 06:53:06 paulus Exp $" 44 45#include <ctype.h> 46#include <stdio.h> 47#include <errno.h> 48#include <unistd.h> 49#include <fcntl.h> 50#include <stdlib.h> 51#include <syslog.h> 52#include <string.h> 53#include <pwd.h> 54#ifdef PLUGIN 55#include <dlfcn.h> 56#endif 57 58#ifdef PPP_FILTER 59#include <pcap.h> 60/* 61 * There have been 3 or 4 different names for this in libpcap CVS, but 62 * this seems to be what they have settled on... 63 * For older versions of libpcap, use DLT_PPP - but that means 64 * we lose the inbound and outbound qualifiers. 65 */ 66#ifndef DLT_PPP_PPPD 67#ifdef DLT_PPP_WITHDIRECTION 68#define DLT_PPP_PPPD DLT_PPP_WITHDIRECTION 69#else 70#define DLT_PPP_PPPD DLT_PPP 71#endif 72#endif 73#endif /* PPP_FILTER */ 74 75#include "pppd.h" 76#include "pathnames.h" 77 78#if defined(ultrix) || defined(NeXT) 79char *strdup __P((char *)); 80#endif 81bool tx_only; /* JYWeng 20031216: idle time counting on tx traffic */ 82 83static const char rcsid[] = RCSID; 84 85struct option_value { 86 struct option_value *next; 87 const char *source; 88 char value[1]; 89}; 90 91/* 92 * Option variables and default values. 93 */ 94bool nochecktime = 0; /* Don't check time */ 95int debug = 0; /* Debug flag */ 96int kdebugflag = 0; /* Tell kernel to print debug messages */ 97int default_device = 1; /* Using /dev/tty or equivalent */ 98char devnam[MAXPATHLEN]; /* Device name */ 99bool nodetach = 0; /* Don't detach from controlling tty */ 100bool updetach = 0; /* Detach once link is up */ 101bool master_detach; /* Detach when we're (only) multilink master */ 102int maxconnect = 0; /* Maximum connect time */ 103char user[MAXNAMELEN]; /* Username for PAP */ 104char passwd[MAXSECRETLEN]; /* Password for PAP */ 105bool persist = 0; /* Reopen link after it goes down */ 106char our_name[MAXNAMELEN]; /* Our name for authentication purposes */ 107bool demand = 0; /* do dial-on-demand */ 108char *ipparam = NULL; /* Extra parameter for ip up/down scripts */ 109 110int idle_time_limit = 0; /* Disconnect if idle for this many seconds */ 111int holdoff = 30; /* # seconds to pause before reconnecting */ 112bool holdoff_specified; /* true if a holdoff value has been given */ 113int log_to_fd = 1; /* send log messages to this fd too */ 114bool log_default = 1; /* log_to_fd is default (stdout) */ 115int maxfail = 10; /* max # of unsuccessful connection attempts */ 116char linkname[MAXPATHLEN]; /* logical name for link */ 117bool tune_kernel; /* may alter kernel settings */ 118int connect_delay = 1000; /* wait this many ms after connect script */ 119int req_unit = -1; /* requested interface unit */ 120int req_minunit = -1; /* requested minimal interface unit */ 121char req_ifname[32]; /* requested interface name */ 122bool multilink = 0; /* Enable multilink operation */ 123char *bundle_name = NULL; /* bundle name for multilink */ 124bool dump_options; /* print out option values */ 125bool dryrun; /* print out option values and exit */ 126char *domain; /* domain name set by domain option */ 127int child_wait = 5; /* # seconds to wait for children at exit */ 128struct userenv *userenv_list; /* user environment variables */ 129 130#ifdef MAXOCTETS 131unsigned int maxoctets = 0; /* default - no limit */ 132int maxoctets_dir = 0; /* default - sum of traffic */ 133int maxoctets_timeout = 1; /* default 1 second */ 134#endif 135 136 137extern option_t auth_options[]; 138extern struct stat devstat; 139 140#ifdef PPP_FILTER 141struct bpf_program pass_filter;/* Filter program for packets to pass */ 142struct bpf_program active_filter; /* Filter program for link-active pkts */ 143#endif 144 145static option_t *curopt; /* pointer to option being processed */ 146char *current_option; /* the name of the option being parsed */ 147int privileged_option; /* set iff the current option came from root */ 148char *option_source; /* string saying where the option came from */ 149int option_priority = OPRIO_CFGFILE; /* priority of the current options */ 150bool devnam_fixed; /* can no longer change device name */ 151 152static int logfile_fd = -1; /* fd opened for log file */ 153static char logfile_name[MAXPATHLEN]; /* name of log file */ 154 155/* 156 * Prototypes 157 */ 158static int setdomain __P((char **)); 159static int readfile __P((char **)); 160static int callfile __P((char **)); 161static int showversion __P((char **)); 162static int showhelp __P((char **)); 163static void usage __P((void)); 164static int setlogfile __P((char **)); 165#ifdef PLUGIN 166static int loadplugin __P((char **)); 167#endif 168 169#ifdef PPP_FILTER 170static int setpassfilter __P((char **)); 171static int setactivefilter __P((char **)); 172#endif 173 174#ifdef MAXOCTETS 175static int setmodir __P((char **)); 176#endif 177 178static int user_setenv __P((char **)); 179static void user_setprint __P((option_t *, printer_func, void *)); 180static int user_unsetenv __P((char **)); 181static void user_unsetprint __P((option_t *, printer_func, void *)); 182 183static option_t *find_option __P((const char *name)); 184static int process_option __P((option_t *, char *, char **)); 185static int n_arguments __P((option_t *)); 186static int number_option __P((char *, u_int32_t *, int)); 187 188/* 189 * Structure to store extra lists of options. 190 */ 191struct option_list { 192 option_t *options; 193 struct option_list *next; 194}; 195 196static struct option_list *extra_options = NULL; 197 198/* 199 * Valid arguments. 200 */ 201option_t general_options[] = { 202 { "nochecktime", o_bool, &nochecktime, 203 "Don't check time", OPT_PRIO | 1 }, 204 { "debug", o_int, &debug, 205 "Increase debugging level", OPT_INC | OPT_NOARG | 1 }, 206 { "-d", o_int, &debug, 207 "Increase debugging level", 208 OPT_ALIAS | OPT_INC | OPT_NOARG | 1 }, 209 210 { "kdebug", o_int, &kdebugflag, 211 "Set kernel driver debug level", OPT_PRIO }, 212 213 { "nodetach", o_bool, &nodetach, 214 "Don't detach from controlling tty", OPT_PRIO | 1 }, 215 { "-detach", o_bool, &nodetach, 216 "Don't detach from controlling tty", OPT_ALIAS | OPT_PRIOSUB | 1 }, 217 { "updetach", o_bool, &updetach, 218 "Detach from controlling tty once link is up", 219 OPT_PRIOSUB | OPT_A2CLR | 1, &nodetach }, 220 221 { "master_detach", o_bool, &master_detach, 222 "Detach when we're multilink master but have no link", 1 }, 223 224 { "holdoff", o_int, &holdoff, 225 "Set time in seconds before retrying connection", 226 OPT_PRIO, &holdoff_specified }, 227 228 { "idle", o_int, &idle_time_limit, 229 "Set time in seconds before disconnecting idle link", OPT_PRIO }, 230 231 { "maxconnect", o_int, &maxconnect, 232 "Set connection time limit", 233 OPT_PRIO | OPT_LLIMIT | OPT_NOINCR | OPT_ZEROINF }, 234 235 { "domain", o_special, (void *)setdomain, 236 "Add given domain name to hostname", 237 OPT_PRIO | OPT_PRIV | OPT_A2STRVAL, &domain }, 238 239 { "file", o_special, (void *)readfile, 240 "Take options from a file", OPT_NOPRINT }, 241 { "call", o_special, (void *)callfile, 242 "Take options from a privileged file", OPT_NOPRINT }, 243 244 { "persist", o_bool, &persist, 245 "Keep on reopening connection after close", OPT_PRIO | 1 }, 246 { "nopersist", o_bool, &persist, 247 "Turn off persist option", OPT_PRIOSUB }, 248 249 { "demand", o_bool, &demand, 250 "Dial on demand", OPT_INITONLY | 1, &persist }, 251 252 { "--version", o_special_noarg, (void *)showversion, 253 "Show version number" }, 254 { "--help", o_special_noarg, (void *)showhelp, 255 "Show brief listing of options" }, 256 { "-h", o_special_noarg, (void *)showhelp, 257 "Show brief listing of options", OPT_ALIAS }, 258 259 { "logfile", o_special, (void *)setlogfile, 260 "Append log messages to this file", 261 OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, &logfile_name }, 262 { "logfd", o_int, &log_to_fd, 263 "Send log messages to this file descriptor", 264 OPT_PRIOSUB | OPT_A2CLR, &log_default }, 265 { "nolog", o_int, &log_to_fd, 266 "Don't send log messages to any file", 267 OPT_PRIOSUB | OPT_NOARG | OPT_VAL(-1) }, 268 { "nologfd", o_int, &log_to_fd, 269 "Don't send log messages to any file descriptor", 270 OPT_PRIOSUB | OPT_ALIAS | OPT_NOARG | OPT_VAL(-1) }, 271 272 { "linkname", o_string, linkname, 273 "Set logical name for link", 274 OPT_PRIO | OPT_PRIV | OPT_STATIC, NULL, MAXPATHLEN }, 275 276 { "maxfail", o_int, &maxfail, 277 "Maximum number of unsuccessful connection attempts to allow", 278 OPT_PRIO }, 279 280 { "ktune", o_bool, &tune_kernel, 281 "Alter kernel settings as necessary", OPT_PRIO | 1 }, 282 { "noktune", o_bool, &tune_kernel, 283 "Don't alter kernel settings", OPT_PRIOSUB }, 284 285 { "connect-delay", o_int, &connect_delay, 286 "Maximum time (in ms) to wait after connect script finishes", 287 OPT_PRIO }, 288 289 { "unit", o_int, &req_unit, 290 "PPP interface unit number to use if possible", 291 OPT_PRIO | OPT_LLIMIT, 0, 0 }, 292 { "minunit", o_int, &req_minunit, 293 "PPP interface minimal unit number", 294 OPT_PRIO | OPT_LLIMIT, 0, 0 }, 295 296 { "ifname", o_string, req_ifname, 297 "PPP interface name to use if possible", 298 OPT_PRIO | OPT_PRIV | OPT_STATIC, NULL, sizeof(req_ifname) }, 299 300 { "dump", o_bool, &dump_options, 301 "Print out option values after parsing all options", 1 }, 302 { "dryrun", o_bool, &dryrun, 303 "Stop after parsing, printing, and checking options", 1 }, 304 305 { "child-timeout", o_int, &child_wait, 306 "Number of seconds to wait for child processes at exit", 307 OPT_PRIO }, 308 309 { "set", o_special, (void *)user_setenv, 310 "Set user environment variable", 311 OPT_A2PRINTER | OPT_NOPRINT, (void *)user_setprint }, 312 { "unset", o_special, (void *)user_unsetenv, 313 "Unset user environment variable", 314 OPT_A2PRINTER | OPT_NOPRINT, (void *)user_unsetprint }, 315 316#ifdef HAVE_MULTILINK 317 { "multilink", o_bool, &multilink, 318 "Enable multilink operation", OPT_PRIO | 1 }, 319 { "mp", o_bool, &multilink, 320 "Enable multilink operation", OPT_PRIOSUB | OPT_ALIAS | 1 }, 321 { "nomultilink", o_bool, &multilink, 322 "Disable multilink operation", OPT_PRIOSUB | 0 }, 323 { "nomp", o_bool, &multilink, 324 "Disable multilink operation", OPT_PRIOSUB | OPT_ALIAS | 0 }, 325 326 { "bundle", o_string, &bundle_name, 327 "Bundle name for multilink", OPT_PRIO }, 328#endif /* HAVE_MULTILINK */ 329 330#ifdef PLUGIN 331 { "plugin", o_special, (void *)loadplugin, 332 "Load a plug-in module into pppd", OPT_PRIV | OPT_A2LIST }, 333#endif 334 335#ifdef PPP_FILTER 336 { "pass-filter", o_special, setpassfilter, 337 "set filter for packets to pass", OPT_PRIO }, 338 339 { "active-filter", o_special, setactivefilter, 340 "set filter for active pkts", OPT_PRIO }, 341#endif 342 343#ifdef MAXOCTETS 344 { "maxoctets", o_int, &maxoctets, 345 "Set connection traffic limit", 346 OPT_PRIO | OPT_LLIMIT | OPT_NOINCR | OPT_ZEROINF }, 347 { "mo", o_int, &maxoctets, 348 "Set connection traffic limit", 349 OPT_ALIAS | OPT_PRIO | OPT_LLIMIT | OPT_NOINCR | OPT_ZEROINF }, 350 { "mo-direction", o_special, setmodir, 351 "Set direction for limit traffic (sum,in,out,max)" }, 352 { "mo-timeout", o_int, &maxoctets_timeout, 353 "Check for traffic limit every N seconds", OPT_PRIO | OPT_LLIMIT | 1 }, 354#endif 355 356/* JYWeng 20031216: add for tx_only option*/ 357 { "tx_only", o_bool, &tx_only, 358 "set idle time counting on tx_only or not", 1 }, 359 360 { NULL } 361}; 362 363#ifndef IMPLEMENTATION 364#define IMPLEMENTATION "" 365#endif 366 367static char *usage_string = "\ 368pppd version %s\n\ 369Usage: %s [ options ], where options are:\n\ 370 <device> Communicate over the named device\n\ 371 <speed> Set the baud rate to <speed>\n\ 372 <loc>:<rem> Set the local and/or remote interface IP\n\ 373 addresses. Either one may be omitted.\n\ 374 asyncmap <n> Set the desired async map to hex <n>\n\ 375 auth Require authentication from peer\n\ 376 connect <p> Invoke shell command <p> to set up the serial line\n\ 377 crtscts Use hardware RTS/CTS flow control\n\ 378 defaultroute Add default route through interface\n\ 379 file <f> Take options from file <f>\n\ 380 modem Use modem control lines\n\ 381 mru <n> Set MRU value to <n> for negotiation\n\ 382See pppd(8) for more options.\n\ 383"; 384 385/* 386 * parse_args - parse a string of arguments from the command line. 387 */ 388int 389parse_args(argc, argv) 390 int argc; 391 char **argv; 392{ 393 char *arg; 394 option_t *opt; 395 int n; 396 397 privileged_option = privileged; 398 option_source = "command line"; 399 option_priority = OPRIO_CMDLINE; 400 while (argc > 0) { 401 arg = *argv++; 402 --argc; 403 opt = find_option(arg); 404 if (opt == NULL) { 405 option_error("unrecognized option '%s'", arg); 406 usage(); 407 return 0; 408 } 409 410 n = n_arguments(opt); 411 if (argc < n) { 412 option_error("too few parameters for option %s", arg); 413 return 0; 414 } 415 if (!process_option(opt, arg, argv)) 416 return 0; 417 argc -= n; 418 argv += n; 419 } 420 return 1; 421} 422 423/* 424 * options_from_file - Read a string of options from a file, 425 * and interpret them. 426 */ 427int 428options_from_file(filename, must_exist, check_prot, priv) 429 char *filename; 430 int must_exist; 431 int check_prot; 432 int priv; 433{ 434 FILE *f; 435 int i, newline, ret, err; 436 option_t *opt; 437 int oldpriv, n; 438 char *oldsource; 439 uid_t euid; 440 char *argv[MAXARGS]; 441 char args[MAXARGS][MAXWORDLEN]; 442 char cmd[MAXWORDLEN]; 443 444 euid = geteuid(); 445 if (check_prot && seteuid(getuid()) == -1) { 446 option_error("unable to drop privileges to open %s: %m", filename); 447 return 0; 448 } 449 f = fopen(filename, "r"); 450 err = errno; 451 if (check_prot && seteuid(euid) == -1) 452 fatal("unable to regain privileges"); 453 if (f == NULL) { 454 errno = err; 455 if (!must_exist) { 456 if (err != ENOENT && err != ENOTDIR) 457 warn("Warning: can't open options file %s: %m", filename); 458 return 1; 459 } 460 option_error("Can't open options file %s: %m", filename); 461 return 0; 462 } 463 464 oldpriv = privileged_option; 465 privileged_option = priv; 466 oldsource = option_source; 467 option_source = strdup(filename); 468 if (option_source == NULL) 469 option_source = "file"; 470 ret = 0; 471 while (getword(f, cmd, &newline, filename)) { 472 opt = find_option(cmd); 473 if (opt == NULL) { 474 option_error("In file %s: unrecognized option '%s'", 475 filename, cmd); 476 goto err; 477 } 478 n = n_arguments(opt); 479 for (i = 0; i < n; ++i) { 480 if (!getword(f, args[i], &newline, filename)) { 481 option_error( 482 "In file %s: too few parameters for option '%s'", 483 filename, cmd); 484 goto err; 485 } 486 argv[i] = args[i]; 487 } 488 if (!process_option(opt, cmd, argv)) 489 goto err; 490 } 491 ret = 1; 492 493err: 494 fclose(f); 495 privileged_option = oldpriv; 496 option_source = oldsource; 497 return ret; 498} 499 500/* 501 * options_from_user - See if the use has a ~/.ppprc file, 502 * and if so, interpret options from it. 503 */ 504int 505options_from_user() 506{ 507 char *user, *path, *file; 508 int ret; 509 struct passwd *pw; 510 size_t pl; 511 512 pw = getpwuid(getuid()); 513 if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == 0) 514 return 1; 515 file = _PATH_USEROPT; 516 pl = strlen(user) + strlen(file) + 2; 517 path = malloc(pl); 518 if (path == NULL) 519 novm("init file name"); 520 slprintf(path, pl, "%s/%s", user, file); 521 option_priority = OPRIO_CFGFILE; 522 ret = options_from_file(path, 0, 1, privileged); 523 free(path); 524 return ret; 525} 526 527/* 528 * options_for_tty - See if an options file exists for the serial 529 * device, and if so, interpret options from it. 530 * We only allow the per-tty options file to override anything from 531 * the command line if it is something that the user can't override 532 * once it has been set by root; this is done by giving configuration 533 * files a lower priority than the command line. 534 */ 535int 536options_for_tty() 537{ 538 char *dev, *path, *p; 539 int ret; 540 size_t pl; 541 542 dev = devnam; 543 if ((p = strstr(dev, "/dev/")) != NULL) 544 dev = p + 5; 545 if (dev[0] == 0 || strcmp(dev, "tty") == 0) 546 return 1; /* don't look for /etc/ppp/options.tty */ 547 pl = strlen(_PATH_TTYOPT) + strlen(dev) + 1; 548 path = malloc(pl); 549 if (path == NULL) 550 novm("tty init file name"); 551 slprintf(path, pl, "%s%s", _PATH_TTYOPT, dev); 552 /* Turn slashes into dots, for Solaris case (e.g. /dev/term/a) */ 553 for (p = path + strlen(_PATH_TTYOPT); *p != 0; ++p) 554 if (*p == '/') 555 *p = '.'; 556 option_priority = OPRIO_CFGFILE; 557 ret = options_from_file(path, 0, 0, 1); 558 free(path); 559 return ret; 560} 561 562/* 563 * options_from_list - process a string of options in a wordlist. 564 */ 565int 566options_from_list(w, priv) 567 struct wordlist *w; 568 int priv; 569{ 570 char *argv[MAXARGS]; 571 option_t *opt; 572 int i, n, ret = 0; 573 struct wordlist *w0; 574 575 privileged_option = priv; 576 option_source = "secrets file"; 577 option_priority = OPRIO_SECFILE; 578 579 while (w != NULL) { 580 opt = find_option(w->word); 581 if (opt == NULL) { 582 option_error("In secrets file: unrecognized option '%s'", 583 w->word); 584 goto err; 585 } 586 n = n_arguments(opt); 587 w0 = w; 588 for (i = 0; i < n; ++i) { 589 w = w->next; 590 if (w == NULL) { 591 option_error( 592 "In secrets file: too few parameters for option '%s'", 593 w0->word); 594 goto err; 595 } 596 argv[i] = w->word; 597 } 598 if (!process_option(opt, w0->word, argv)) 599 goto err; 600 w = w->next; 601 } 602 ret = 1; 603 604err: 605 return ret; 606} 607 608/* 609 * match_option - see if this option matches an option_t structure. 610 */ 611static int 612match_option(name, opt, dowild) 613 char *name; 614 option_t *opt; 615 int dowild; 616{ 617 int (*match) __P((char *, char **, int)); 618 619 if (dowild != (opt->type == o_wild)) 620 return 0; 621 if (!dowild) 622 return strcmp(name, opt->name) == 0; 623 match = (int (*) __P((char *, char **, int))) opt->addr; 624 return (*match)(name, NULL, 0); 625} 626 627/* 628 * find_option - scan the option lists for the various protocols 629 * looking for an entry with the given name. 630 * This could be optimized by using a hash table. 631 */ 632static option_t * 633find_option(name) 634 const char *name; 635{ 636 option_t *opt; 637 struct option_list *list; 638 int i, dowild; 639 640 for (dowild = 0; dowild <= 1; ++dowild) { 641 for (opt = general_options; opt->name != NULL; ++opt) 642 if (match_option(name, opt, dowild)) 643 return opt; 644 for (opt = auth_options; opt->name != NULL; ++opt) 645 if (match_option(name, opt, dowild)) 646 return opt; 647 for (list = extra_options; list != NULL; list = list->next) 648 for (opt = list->options; opt->name != NULL; ++opt) 649 if (match_option(name, opt, dowild)) 650 return opt; 651 for (opt = the_channel->options; opt->name != NULL; ++opt) 652 if (match_option(name, opt, dowild)) 653 return opt; 654 for (i = 0; protocols[i] != NULL; ++i) 655 if ((opt = protocols[i]->options) != NULL) 656 for (; opt->name != NULL; ++opt) 657 if (match_option(name, opt, dowild)) 658 return opt; 659 } 660 return NULL; 661} 662 663/* 664 * process_option - process one new-style option. 665 */ 666static int 667process_option(opt, cmd, argv) 668 option_t *opt; 669 char *cmd; 670 char **argv; 671{ 672 u_int32_t v; 673 int iv, a; 674 char *sv; 675 int (*parser) __P((char **)); 676 int (*wildp) __P((char *, char **, int)); 677 char *optopt = (opt->type == o_wild)? "": " option"; 678 int prio = option_priority; 679 option_t *mainopt = opt; 680 681 current_option = opt->name; 682 if ((opt->flags & OPT_PRIVFIX) && privileged_option) 683 prio += OPRIO_ROOT; 684 while (mainopt->flags & OPT_PRIOSUB) 685 --mainopt; 686 if (mainopt->flags & OPT_PRIO) { 687 if (prio < mainopt->priority) { 688 /* new value doesn't override old */ 689 if (prio == OPRIO_CMDLINE && mainopt->priority > OPRIO_ROOT) { 690 option_error("%s%s set in %s cannot be overridden\n", 691 opt->name, optopt, mainopt->source); 692 return 0; 693 } 694 return 1; 695 } 696 if (prio > OPRIO_ROOT && mainopt->priority == OPRIO_CMDLINE) 697 warn("%s%s from %s overrides command line", 698 opt->name, optopt, option_source); 699 } 700 701 if ((opt->flags & OPT_INITONLY) && phase != PHASE_INITIALIZE) { 702 option_error("%s%s cannot be changed after initialization", 703 opt->name, optopt); 704 return 0; 705 } 706 if ((opt->flags & OPT_PRIV) && !privileged_option) { 707 option_error("using the %s%s requires root privilege", 708 opt->name, optopt); 709 return 0; 710 } 711 if ((opt->flags & OPT_ENABLE) && *(bool *)(opt->addr2) == 0) { 712 option_error("%s%s is disabled", opt->name, optopt); 713 return 0; 714 } 715 if ((opt->flags & OPT_DEVEQUIV) && devnam_fixed) { 716 option_error("the %s%s may not be changed in %s", 717 opt->name, optopt, option_source); 718 return 0; 719 } 720 721 switch (opt->type) { 722 case o_bool: 723 v = opt->flags & OPT_VALUE; 724 *(bool *)(opt->addr) = v; 725 if (opt->addr2 && (opt->flags & OPT_A2COPY)) 726 *(bool *)(opt->addr2) = v; 727 else if (opt->addr2 && (opt->flags & OPT_A2CLR)) 728 *(bool *)(opt->addr2) = 0; 729 else if (opt->addr2 && (opt->flags & OPT_A2CLRB)) 730 *(u_char *)(opt->addr2) &= ~v; 731 else if (opt->addr2 && (opt->flags & OPT_A2OR)) 732 *(u_char *)(opt->addr2) |= v; 733 break; 734 735 case o_int: 736 iv = 0; 737 if ((opt->flags & OPT_NOARG) == 0) { 738 if (!int_option(*argv, &iv)) 739 return 0; 740 if ((((opt->flags & OPT_LLIMIT) && iv < opt->lower_limit) 741 || ((opt->flags & OPT_ULIMIT) && iv > opt->upper_limit)) 742 && !((opt->flags & OPT_ZEROOK && iv == 0))) { 743 char *zok = (opt->flags & OPT_ZEROOK)? " zero or": ""; 744 switch (opt->flags & OPT_LIMITS) { 745 case OPT_LLIMIT: 746 option_error("%s value must be%s >= %d", 747 opt->name, zok, opt->lower_limit); 748 break; 749 case OPT_ULIMIT: 750 option_error("%s value must be%s <= %d", 751 opt->name, zok, opt->upper_limit); 752 break; 753 case OPT_LIMITS: 754 option_error("%s value must be%s between %d and %d", 755 opt->name, zok, opt->lower_limit, opt->upper_limit); 756 break; 757 } 758 return 0; 759 } 760 } 761 a = opt->flags & OPT_VALUE; 762 if (a >= 128) 763 a -= 256; /* sign extend */ 764 iv += a; 765 if (opt->flags & OPT_INC) 766 iv += *(int *)(opt->addr); 767 if ((opt->flags & OPT_NOINCR) && !privileged_option) { 768 int oldv = *(int *)(opt->addr); 769 if ((opt->flags & OPT_ZEROINF) ? 770 (oldv != 0 && (iv == 0 || iv > oldv)) : (iv > oldv)) { 771 option_error("%s value cannot be increased", opt->name); 772 return 0; 773 } 774 } 775 *(int *)(opt->addr) = iv; 776 if (opt->addr2 && (opt->flags & OPT_A2COPY)) 777 *(int *)(opt->addr2) = iv; 778 break; 779 780 case o_uint32: 781 if (opt->flags & OPT_NOARG) { 782 v = opt->flags & OPT_VALUE; 783 if (v & 0x80) 784 v |= 0xffffff00U; 785 } else if (!number_option(*argv, &v, 16)) 786 return 0; 787 if (opt->flags & OPT_OR) 788 v |= *(u_int32_t *)(opt->addr); 789 *(u_int32_t *)(opt->addr) = v; 790 if (opt->addr2 && (opt->flags & OPT_A2COPY)) 791 *(u_int32_t *)(opt->addr2) = v; 792 break; 793 794 case o_string: 795 if (opt->flags & OPT_STATIC) { 796 strlcpy((char *)(opt->addr), *argv, opt->upper_limit); 797 } else { 798 char **optptr = (char **)(opt->addr); 799 sv = strdup(*argv); 800 if (sv == NULL) 801 novm("option argument"); 802 if (*optptr && opt->source) 803 free(*optptr); 804 *optptr = sv; 805 } 806 break; 807 808 case o_special_noarg: 809 case o_special: 810 parser = (int (*) __P((char **))) opt->addr; 811 curopt = opt; 812 if (!(*parser)(argv)) 813 return 0; 814 if (opt->flags & OPT_A2LIST) { 815 struct option_value *ovp, *pp; 816 817 ovp = malloc(sizeof(*ovp) + strlen(*argv)); 818 if (ovp != 0) { 819 strcpy(ovp->value, *argv); 820 ovp->source = option_source; 821 ovp->next = NULL; 822 if (opt->addr2 == NULL) { 823 opt->addr2 = ovp; 824 } else { 825 for (pp = opt->addr2; pp->next != NULL; pp = pp->next) 826 ; 827 pp->next = ovp; 828 } 829 } 830 } 831 break; 832 833 case o_wild: 834 wildp = (int (*) __P((char *, char **, int))) opt->addr; 835 if (!(*wildp)(cmd, argv, 1)) 836 return 0; 837 break; 838 } 839 840 /* 841 * If addr2 wasn't used by any flag (OPT_A2COPY, etc.) but is set, 842 * treat it as a bool and set/clear it based on the OPT_A2CLR bit. 843 */ 844 if (opt->addr2 && (opt->flags & (OPT_A2COPY|OPT_ENABLE 845 |OPT_A2PRINTER|OPT_A2STRVAL|OPT_A2LIST|OPT_A2OR)) == 0) 846 *(bool *)(opt->addr2) = !(opt->flags & OPT_A2CLR); 847 848 mainopt->source = option_source; 849 mainopt->priority = prio; 850 mainopt->winner = opt - mainopt; 851 852 return 1; 853} 854 855/* 856 * override_value - if the option priorities would permit us to 857 * override the value of option, return 1 and update the priority 858 * and source of the option value. Otherwise returns 0. 859 */ 860int 861override_value(option, priority, source) 862 const char *option; 863 int priority; 864 const char *source; 865{ 866 option_t *opt; 867 868 opt = find_option(option); 869 if (opt == NULL) 870 return 0; 871 while (opt->flags & OPT_PRIOSUB) 872 --opt; 873 if ((opt->flags & OPT_PRIO) && priority < opt->priority) 874 return 0; 875 opt->priority = priority; 876 opt->source = source; 877 opt->winner = -1; 878 return 1; 879} 880 881/* 882 * n_arguments - tell how many arguments an option takes 883 */ 884static int 885n_arguments(opt) 886 option_t *opt; 887{ 888 return (opt->type == o_bool || opt->type == o_special_noarg 889 || (opt->flags & OPT_NOARG))? 0: 1; 890} 891 892/* 893 * add_options - add a list of options to the set we grok. 894 */ 895void 896add_options(opt) 897 option_t *opt; 898{ 899 struct option_list *list; 900 901 list = malloc(sizeof(*list)); 902 if (list == 0) 903 novm("option list entry"); 904 list->options = opt; 905 list->next = extra_options; 906 extra_options = list; 907} 908 909/* 910 * check_options - check that options are valid and consistent. 911 */ 912void 913check_options() 914{ 915 if (logfile_fd >= 0 && logfile_fd != log_to_fd) 916 close(logfile_fd); 917} 918 919/* 920 * print_option - print out an option and its value 921 */ 922static void 923print_option(opt, mainopt, printer, arg) 924 option_t *opt, *mainopt; 925 printer_func printer; 926 void *arg; 927{ 928 int i, v; 929 char *p; 930 931 if (opt->flags & OPT_NOPRINT) 932 return; 933 switch (opt->type) { 934 case o_bool: 935 v = opt->flags & OPT_VALUE; 936 if (*(bool *)opt->addr != v) 937 /* this can happen legitimately, e.g. lock 938 option turned off for default device */ 939 break; 940 printer(arg, "%s", opt->name); 941 break; 942 case o_int: 943 v = opt->flags & OPT_VALUE; 944 if (v >= 128) 945 v -= 256; 946 i = *(int *)opt->addr; 947 if (opt->flags & OPT_NOARG) { 948 printer(arg, "%s", opt->name); 949 if (i != v) { 950 if (opt->flags & OPT_INC) { 951 for (; i > v; i -= v) 952 printer(arg, " %s", opt->name); 953 } else 954 printer(arg, " # oops: %d not %d\n", 955 i, v); 956 } 957 } else { 958 printer(arg, "%s %d", opt->name, i); 959 } 960 break; 961 case o_uint32: 962 printer(arg, "%s", opt->name); 963 if ((opt->flags & OPT_NOARG) == 0) 964 printer(arg, " %x", *(u_int32_t *)opt->addr); 965 break; 966 967 case o_string: 968 if (opt->flags & OPT_HIDE) { 969 p = "??????"; 970 } else { 971 p = (char *) opt->addr; 972 if ((opt->flags & OPT_STATIC) == 0) 973 p = *(char **)p; 974 } 975 printer(arg, "%s %q", opt->name, p); 976 break; 977 978 case o_special: 979 case o_special_noarg: 980 case o_wild: 981 if (opt->type != o_wild) { 982 printer(arg, "%s", opt->name); 983 if (n_arguments(opt) == 0) 984 break; 985 printer(arg, " "); 986 } 987 if (opt->flags & OPT_A2PRINTER) { 988 void (*oprt) __P((option_t *, printer_func, void *)); 989 oprt = (void (*) __P((option_t *, printer_func, 990 void *)))opt->addr2; 991 (*oprt)(opt, printer, arg); 992 } else if (opt->flags & OPT_A2STRVAL) { 993 p = (char *) opt->addr2; 994 if ((opt->flags & OPT_STATIC) == 0) 995 p = *(char **)p; 996 printer("%q", p); 997 } else if (opt->flags & OPT_A2LIST) { 998 struct option_value *ovp; 999 1000 ovp = (struct option_value *) opt->addr2; 1001 for (;;) { 1002 printer(arg, "%q", ovp->value); 1003 if ((ovp = ovp->next) == NULL) 1004 break; 1005 printer(arg, "\t\t# (from %s)\n%s ", 1006 ovp->source, opt->name); 1007 } 1008 } else { 1009 printer(arg, "xxx # [don't know how to print value]"); 1010 } 1011 break; 1012 1013 default: 1014 printer(arg, "# %s value (type %d\?\?)", opt->name, opt->type); 1015 break; 1016 } 1017 printer(arg, "\t\t# (from %s)\n", mainopt->source); 1018} 1019 1020/* 1021 * print_option_list - print out options in effect from an 1022 * array of options. 1023 */ 1024static void 1025print_option_list(opt, printer, arg) 1026 option_t *opt; 1027 printer_func printer; 1028 void *arg; 1029{ 1030 while (opt->name != NULL) { 1031 if (opt->priority != OPRIO_DEFAULT 1032 && opt->winner != (short int) -1) 1033 print_option(opt + opt->winner, opt, printer, arg); 1034 do { 1035 ++opt; 1036 } while (opt->flags & OPT_PRIOSUB); 1037 } 1038} 1039 1040/* 1041 * print_options - print out what options are in effect. 1042 */ 1043void 1044print_options(printer, arg) 1045 printer_func printer; 1046 void *arg; 1047{ 1048 struct option_list *list; 1049 int i; 1050 1051 printer(arg, "pppd options in effect:\n"); 1052 print_option_list(general_options, printer, arg); 1053 print_option_list(auth_options, printer, arg); 1054 for (list = extra_options; list != NULL; list = list->next) 1055 print_option_list(list->options, printer, arg); 1056 print_option_list(the_channel->options, printer, arg); 1057 for (i = 0; protocols[i] != NULL; ++i) 1058 print_option_list(protocols[i]->options, printer, arg); 1059} 1060 1061/* 1062 * usage - print out a message telling how to use the program. 1063 */ 1064static void 1065usage() 1066{ 1067 if (phase == PHASE_INITIALIZE) 1068 fprintf(stderr, usage_string, VERSION, progname); 1069} 1070 1071/* 1072 * showhelp - print out usage message and exit. 1073 */ 1074static int 1075showhelp(argv) 1076 char **argv; 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. 1087 */ 1088static int 1089showversion(argv) 1090 char **argv; 1091{ 1092 if (phase == PHASE_INITIALIZE) { 1093 fprintf(stderr, "pppd version %s\n", VERSION); 1094 exit(0); 1095 } 1096 return 0; 1097} 1098 1099/* 1100 * option_error - print a message about an error in an option. 1101 * The message is logged, and also sent to 1102 * stderr if phase == PHASE_INITIALIZE. 1103 */ 1104void 1105option_error __V((char *fmt, ...)) 1106{ 1107 va_list args; 1108 char buf[1024]; 1109 1110#if defined(__STDC__) 1111 va_start(args, fmt); 1112#else 1113 char *fmt; 1114 va_start(args); 1115 fmt = va_arg(args, char *); 1116#endif 1117 vslprintf(buf, sizeof(buf), fmt, args); 1118 va_end(args); 1119 if (phase == PHASE_INITIALIZE) 1120 fprintf(stderr, "%s: %s\n", progname, buf); 1121 syslog(LOG_ERR, "%s", buf); 1122} 1123 1124#if 0 1125/* 1126 * readable - check if a file is readable by the real user. 1127 */ 1128int 1129readable(fd) 1130 int fd; 1131{ 1132 uid_t uid; 1133 int i; 1134 struct stat sbuf; 1135 1136 uid = getuid(); 1137 if (uid == 0) 1138 return 1; 1139 if (fstat(fd, &sbuf) != 0) 1140 return 0; 1141 if (sbuf.st_uid == uid) 1142 return sbuf.st_mode & S_IRUSR; 1143 if (sbuf.st_gid == getgid()) 1144 return sbuf.st_mode & S_IRGRP; 1145 for (i = 0; i < ngroups; ++i) 1146 if (sbuf.st_gid == groups[i]) 1147 return sbuf.st_mode & S_IRGRP; 1148 return sbuf.st_mode & S_IROTH; 1149} 1150#endif 1151 1152/* 1153 * Read a word from a file. 1154 * Words are delimited by white-space or by quotes (" or '). 1155 * Quotes, white-space and \ may be escaped with \. 1156 * \<newline> is ignored. 1157 */ 1158int 1159getword(f, word, newlinep, filename) 1160 FILE *f; 1161 char *word; 1162 int *newlinep; 1163 char *filename; 1164{ 1165 int c, len, escape; 1166 int quoted, comment; 1167 int value, digit, got, n; 1168 1169#define isoctal(c) ((c) >= '0' && (c) < '8') 1170 1171 *newlinep = 0; 1172 len = 0; 1173 escape = 0; 1174 comment = 0; 1175 quoted = 0; 1176 1177 /* 1178 * First skip white-space and comments. 1179 */ 1180 for (;;) { 1181 c = getc(f); 1182 if (c == EOF) 1183 break; 1184 1185 /* 1186 * A newline means the end of a comment; backslash-newline 1187 * is ignored. Note that we cannot have escape && comment. 1188 */ 1189 if (c == '\n') { 1190 if (!escape) { 1191 *newlinep = 1; 1192 comment = 0; 1193 } else 1194 escape = 0; 1195 continue; 1196 } 1197 1198 /* 1199 * Ignore characters other than newline in a comment. 1200 */ 1201 if (comment) 1202 continue; 1203 1204 /* 1205 * If this character is escaped, we have a word start. 1206 */ 1207 if (escape) 1208 break; 1209 1210 /* 1211 * If this is the escape character, look at the next character. 1212 */ 1213 if (c == '\\') { 1214 escape = 1; 1215 continue; 1216 } 1217 1218 /* 1219 * If this is the start of a comment, ignore the rest of the line. 1220 */ 1221 if (c == '#') { 1222 comment = 1; 1223 continue; 1224 } 1225 1226 /* 1227 * A non-whitespace character is the start of a word. 1228 */ 1229 if (!isspace(c)) 1230 break; 1231 } 1232 1233 /* 1234 * Process characters until the end of the word. 1235 */ 1236 while (c != EOF) { 1237 if (escape) { 1238 /* 1239 * This character is escaped: backslash-newline is ignored, 1240 * various other characters indicate particular values 1241 * as for C backslash-escapes. 1242 */ 1243 escape = 0; 1244 if (c == '\n') { 1245 c = getc(f); 1246 continue; 1247 } 1248 1249 got = 0; 1250 switch (c) { 1251 case 'a': 1252 value = '\a'; 1253 break; 1254 case 'b': 1255 value = '\b'; 1256 break; 1257 case 'f': 1258 value = '\f'; 1259 break; 1260 case 'n': 1261 value = '\n'; 1262 break; 1263 case 'r': 1264 value = '\r'; 1265 break; 1266 case 's': 1267 value = ' '; 1268 break; 1269 case 't': 1270 value = '\t'; 1271 break; 1272 1273 default: 1274 if (isoctal(c)) { 1275 /* 1276 * \ddd octal sequence 1277 */ 1278 value = 0; 1279 for (n = 0; n < 3 && isoctal(c); ++n) { 1280 value = (value << 3) + (c & 07); 1281 c = getc(f); 1282 } 1283 got = 1; 1284 break; 1285 } 1286 1287 if (c == 'x') { 1288 /* 1289 * \x<hex_string> sequence 1290 */ 1291 value = 0; 1292 c = getc(f); 1293 for (n = 0; n < 2 && isxdigit(c); ++n) { 1294 digit = toupper(c) - '0'; 1295 if (digit > 10) 1296 digit += '0' + 10 - 'A'; 1297 value = (value << 4) + digit; 1298 c = getc (f); 1299 } 1300 got = 1; 1301 break; 1302 } 1303 1304 /* 1305 * Otherwise the character stands for itself. 1306 */ 1307 value = c; 1308 break; 1309 } 1310 1311 /* 1312 * Store the resulting character for the escape sequence. 1313 */ 1314 if (len < MAXWORDLEN) { 1315 word[len] = value; 1316 ++len; 1317 } 1318 1319 if (!got) 1320 c = getc(f); 1321 continue; 1322 } 1323 1324 /* 1325 * Backslash starts a new escape sequence. 1326 */ 1327 if (c == '\\') { 1328 escape = 1; 1329 c = getc(f); 1330 continue; 1331 } 1332 1333 /* 1334 * Not escaped: check for the start or end of a quoted 1335 * section and see if we've reached the end of the word. 1336 */ 1337 if (quoted) { 1338 if (c == quoted) { 1339 quoted = 0; 1340 c = getc(f); 1341 continue; 1342 } 1343 } else if (c == '"' || c == '\'') { 1344 quoted = c; 1345 c = getc(f); 1346 continue; 1347 } else if (isspace(c) || c == '#') { 1348 ungetc (c, f); 1349 break; 1350 } 1351 1352 /* 1353 * An ordinary character: store it in the word and get another. 1354 */ 1355 if (len < MAXWORDLEN) { 1356 word[len] = c; 1357 ++len; 1358 } 1359 1360 c = getc(f); 1361 } 1362 1363 /* 1364 * End of the word: check for errors. 1365 */ 1366 if (c == EOF) { 1367 if (ferror(f)) { 1368 if (errno == 0) 1369 errno = EIO; 1370 option_error("Error reading %s: %m", filename); 1371 die(1); 1372 } 1373 /* 1374 * If len is zero, then we didn't find a word before the 1375 * end of the file. 1376 */ 1377 if (len == 0) 1378 return 0; 1379 if (quoted) 1380 option_error("warning: quoted word runs to end of file (%.20s...)", 1381 filename, word); 1382 } 1383 1384 /* 1385 * Warn if the word was too long, and append a terminating null. 1386 */ 1387 if (len >= MAXWORDLEN) { 1388 option_error("warning: word in file %s too long (%.20s...)", 1389 filename, word); 1390 len = MAXWORDLEN - 1; 1391 } 1392 word[len] = 0; 1393 1394 return 1; 1395 1396#undef isoctal 1397 1398} 1399 1400/* 1401 * number_option - parse an unsigned numeric parameter for an option. 1402 */ 1403static int 1404number_option(str, valp, base) 1405 char *str; 1406 u_int32_t *valp; 1407 int base; 1408{ 1409 char *ptr; 1410 1411 *valp = strtoul(str, &ptr, base); 1412 if (ptr == str) { 1413 option_error("invalid numeric parameter '%s' for %s option", 1414 str, current_option); 1415 return 0; 1416 } 1417 return 1; 1418} 1419 1420 1421/* 1422 * int_option - like number_option, but valp is int *, 1423 * the base is assumed to be 0, and *valp is not changed 1424 * if there is an error. 1425 */ 1426int 1427int_option(str, valp) 1428 char *str; 1429 int *valp; 1430{ 1431 u_int32_t v; 1432 1433 if (!number_option(str, &v, 0)) 1434 return 0; 1435 *valp = (int) v; 1436 return 1; 1437} 1438 1439 1440/* 1441 * The following procedures parse options. 1442 */ 1443 1444/* 1445 * readfile - take commands from a file. 1446 */ 1447static int 1448readfile(argv) 1449 char **argv; 1450{ 1451 return options_from_file(*argv, 1, 1, privileged_option); 1452} 1453 1454/* 1455 * callfile - take commands from /etc/ppp/peers/<name>. 1456 * Name may not contain /../, start with / or ../, or end in /.. 1457 */ 1458static int 1459callfile(argv) 1460 char **argv; 1461{ 1462 char *fname, *arg, *p; 1463 int l, ok; 1464 1465 arg = *argv; 1466 ok = 1; 1467 if (arg[0] == '/' || arg[0] == 0) 1468 ok = 0; 1469 else { 1470 for (p = arg; *p != 0; ) { 1471 if (p[0] == '.' && p[1] == '.' && (p[2] == '/' || p[2] == 0)) { 1472 ok = 0; 1473 break; 1474 } 1475 while (*p != '/' && *p != 0) 1476 ++p; 1477 if (*p == '/') 1478 ++p; 1479 } 1480 } 1481 if (!ok) { 1482 option_error("call option value may not contain .. or start with /"); 1483 return 0; 1484 } 1485 1486 l = strlen(arg) + strlen(_PATH_PEERFILES) + 1; 1487 if ((fname = (char *) malloc(l)) == NULL) 1488 novm("call file name"); 1489 slprintf(fname, l, "%s%s", _PATH_PEERFILES, arg); 1490 1491 ok = options_from_file(fname, 1, 1, 1); 1492 1493 free(fname); 1494 return ok; 1495} 1496 1497#ifdef PPP_FILTER 1498/* 1499 * setpassfilter - Set the pass filter for packets 1500 */ 1501static int 1502setpassfilter(argv) 1503 char **argv; 1504{ 1505 pcap_t *pc; 1506 int ret = 1; 1507 1508 pc = pcap_open_dead(DLT_PPP_PPPD, 65535); 1509 if (pcap_compile(pc, &pass_filter, *argv, 1, netmask) == -1) { 1510 option_error("error in pass-filter expression: %s\n", 1511 pcap_geterr(pc)); 1512 ret = 0; 1513 } 1514 pcap_close(pc); 1515 1516 return ret; 1517} 1518 1519/* 1520 * setactivefilter - Set the active filter for packets 1521 */ 1522static int 1523setactivefilter(argv) 1524 char **argv; 1525{ 1526 pcap_t *pc; 1527 int ret = 1; 1528 1529 pc = pcap_open_dead(DLT_PPP_PPPD, 65535); 1530 if (pcap_compile(pc, &active_filter, *argv, 1, netmask) == -1) { 1531 option_error("error in active-filter expression: %s\n", 1532 pcap_geterr(pc)); 1533 ret = 0; 1534 } 1535 pcap_close(pc); 1536 1537 return ret; 1538} 1539#endif 1540 1541/* 1542 * setdomain - Set domain name to append to hostname 1543 */ 1544static int 1545setdomain(argv) 1546 char **argv; 1547{ 1548 gethostname(hostname, MAXNAMELEN); 1549 if (**argv != 0) { 1550 if (**argv != '.') 1551 strncat(hostname, ".", MAXNAMELEN - strlen(hostname)); 1552 domain = hostname + strlen(hostname); 1553 strncat(hostname, *argv, MAXNAMELEN - strlen(hostname)); 1554 } 1555 hostname[MAXNAMELEN-1] = 0; 1556 return (1); 1557} 1558 1559static int 1560setlogfile(argv) 1561 char **argv; 1562{ 1563 int fd, err; 1564 uid_t euid; 1565 1566 euid = geteuid(); 1567 if (!privileged_option && seteuid(getuid()) == -1) { 1568 option_error("unable to drop permissions to open %s: %m", *argv); 1569 return 0; 1570 } 1571 fd = open(*argv, O_WRONLY | O_APPEND | O_CREAT | O_EXCL, 0644); 1572 if (fd < 0 && errno == EEXIST) 1573 fd = open(*argv, O_WRONLY | O_APPEND); 1574 err = errno; 1575 if (!privileged_option && seteuid(euid) == -1) 1576 fatal("unable to regain privileges: %m"); 1577 if (fd < 0) { 1578 errno = err; 1579 option_error("Can't open log file %s: %m", *argv); 1580 return 0; 1581 } 1582 strlcpy(logfile_name, *argv, sizeof(logfile_name)); 1583 if (logfile_fd >= 0) 1584 close(logfile_fd); 1585 logfile_fd = fd; 1586 log_to_fd = fd; 1587 log_default = 0; 1588 return 1; 1589} 1590 1591#ifdef MAXOCTETS 1592static int 1593setmodir(argv) 1594 char **argv; 1595{ 1596 if(*argv == NULL) 1597 return 0; 1598 if(!strcmp(*argv,"in")) { 1599 maxoctets_dir = PPP_OCTETS_DIRECTION_IN; 1600 } else if (!strcmp(*argv,"out")) { 1601 maxoctets_dir = PPP_OCTETS_DIRECTION_OUT; 1602 } else if (!strcmp(*argv,"max")) { 1603 maxoctets_dir = PPP_OCTETS_DIRECTION_MAXOVERAL; 1604 } else { 1605 maxoctets_dir = PPP_OCTETS_DIRECTION_SUM; 1606 } 1607 return 1; 1608} 1609#endif 1610 1611#ifdef PLUGIN 1612static int 1613loadplugin(argv) 1614 char **argv; 1615{ 1616 char *arg = *argv; 1617 void *handle; 1618 const char *err; 1619 void (*init) __P((void)); 1620 char *path = arg; 1621 const char *vers; 1622 1623 if (strchr(arg, '/') == 0) { 1624 const char *base = _PATH_PLUGIN; 1625 int l = strlen(base) + strlen(arg) + 2; 1626 path = malloc(l); 1627 if (path == 0) 1628 novm("plugin file path"); 1629 strlcpy(path, base, l); 1630 strlcat(path, "/", l); 1631 strlcat(path, arg, l); 1632 } 1633 handle = dlopen(path, RTLD_GLOBAL | RTLD_NOW); 1634 if (handle == 0) { 1635 err = dlerror(); 1636 if (err != 0) 1637 option_error("%s", err); 1638 option_error("Couldn't load plugin %s", arg); 1639 goto err; 1640 } 1641 init = (void (*)(void))dlsym(handle, "plugin_init"); 1642 if (init == 0) { 1643 option_error("%s has no initialization entry point", arg); 1644 goto errclose; 1645 } 1646 vers = (const char *) dlsym(handle, "pppd_version"); 1647 if (vers == 0) { 1648 warn("Warning: plugin %s has no version information", arg); 1649 } else if (strcmp(vers, VERSION) != 0) { 1650 option_error("Plugin %s is for pppd version %s, this is %s", 1651 arg, vers, VERSION); 1652 goto errclose; 1653 } 1654 info("Plugin %s loaded.", arg); 1655 (*init)(); 1656 return 1; 1657 1658 errclose: 1659 dlclose(handle); 1660 err: 1661 if (path != arg) 1662 free(path); 1663 return 0; 1664} 1665#endif /* PLUGIN */ 1666 1667/* 1668 * Set an environment variable specified by the user. 1669 */ 1670static int 1671user_setenv(argv) 1672 char **argv; 1673{ 1674 char *arg = argv[0]; 1675 char *eqp; 1676 struct userenv *uep, **insp; 1677 1678 if ((eqp = strchr(arg, '=')) == NULL) { 1679 option_error("missing = in name=value: %s", arg); 1680 return 0; 1681 } 1682 if (eqp == arg) { 1683 option_error("missing variable name: %s", arg); 1684 return 0; 1685 } 1686 for (uep = userenv_list; uep != NULL; uep = uep->ue_next) { 1687 int nlen = strlen(uep->ue_name); 1688 if (nlen == (eqp - arg) && 1689 strncmp(arg, uep->ue_name, nlen) == 0) 1690 break; 1691 } 1692 /* Ignore attempts by unprivileged users to override privileged sources */ 1693 if (uep != NULL && !privileged_option && uep->ue_priv) 1694 return 1; 1695 /* The name never changes, so allocate it with the structure */ 1696 if (uep == NULL) { 1697 uep = malloc(sizeof (*uep) + (eqp-arg)); 1698 strncpy(uep->ue_name, arg, eqp-arg); 1699 uep->ue_name[eqp-arg] = '\0'; 1700 uep->ue_next = NULL; 1701 insp = &userenv_list; 1702 while (*insp != NULL) 1703 insp = &(*insp)->ue_next; 1704 *insp = uep; 1705 } else { 1706 struct userenv *uep2; 1707 for (uep2 = userenv_list; uep2 != NULL; uep2 = uep2->ue_next) { 1708 if (uep2 != uep && !uep2->ue_isset) 1709 break; 1710 } 1711 if (uep2 == NULL && !uep->ue_isset) 1712 find_option("unset")->flags |= OPT_NOPRINT; 1713 free(uep->ue_value); 1714 } 1715 uep->ue_isset = 1; 1716 uep->ue_priv = privileged_option; 1717 uep->ue_source = option_source; 1718 uep->ue_value = strdup(eqp + 1); 1719 curopt->flags &= ~OPT_NOPRINT; 1720 return 1; 1721} 1722 1723static void 1724user_setprint(opt, printer, arg) 1725 option_t *opt; 1726 printer_func printer; 1727 void *arg; 1728{ 1729 struct userenv *uep, *uepnext; 1730 1731 uepnext = userenv_list; 1732 while (uepnext != NULL && !uepnext->ue_isset) 1733 uepnext = uepnext->ue_next; 1734 while ((uep = uepnext) != NULL) { 1735 uepnext = uep->ue_next; 1736 while (uepnext != NULL && !uepnext->ue_isset) 1737 uepnext = uepnext->ue_next; 1738 (*printer)(arg, "%s=%s", uep->ue_name, uep->ue_value); 1739 if (uepnext != NULL) 1740 (*printer)(arg, "\t\t# (from %s)\n%s ", uep->ue_source, opt->name); 1741 else 1742 opt->source = uep->ue_source; 1743 } 1744} 1745 1746static int 1747user_unsetenv(argv) 1748 char **argv; 1749{ 1750 struct userenv *uep, **insp; 1751 char *arg = argv[0]; 1752 1753 if (strchr(arg, '=') != NULL) { 1754 option_error("unexpected = in name: %s", arg); 1755 return 0; 1756 } 1757 if (arg == '\0') { 1758 option_error("missing variable name for unset"); 1759 return 0; 1760 } 1761 for (uep = userenv_list; uep != NULL; uep = uep->ue_next) { 1762 if (strcmp(arg, uep->ue_name) == 0) 1763 break; 1764 } 1765 /* Ignore attempts by unprivileged users to override privileged sources */ 1766 if (uep != NULL && !privileged_option && uep->ue_priv) 1767 return 1; 1768 /* The name never changes, so allocate it with the structure */ 1769 if (uep == NULL) { 1770 uep = malloc(sizeof (*uep) + strlen(arg)); 1771 strcpy(uep->ue_name, arg); 1772 uep->ue_next = NULL; 1773 insp = &userenv_list; 1774 while (*insp != NULL) 1775 insp = &(*insp)->ue_next; 1776 *insp = uep; 1777 } else { 1778 struct userenv *uep2; 1779 for (uep2 = userenv_list; uep2 != NULL; uep2 = uep2->ue_next) { 1780 if (uep2 != uep && uep2->ue_isset) 1781 break; 1782 } 1783 if (uep2 == NULL && uep->ue_isset) 1784 find_option("set")->flags |= OPT_NOPRINT; 1785 free(uep->ue_value); 1786 } 1787 uep->ue_isset = 0; 1788 uep->ue_priv = privileged_option; 1789 uep->ue_source = option_source; 1790 uep->ue_value = NULL; 1791 curopt->flags &= ~OPT_NOPRINT; 1792 return 1; 1793} 1794 1795static void 1796user_unsetprint(opt, printer, arg) 1797 option_t *opt; 1798 printer_func printer; 1799 void *arg; 1800{ 1801 struct userenv *uep, *uepnext; 1802 1803 uepnext = userenv_list; 1804 while (uepnext != NULL && uepnext->ue_isset) 1805 uepnext = uepnext->ue_next; 1806 while ((uep = uepnext) != NULL) { 1807 uepnext = uep->ue_next; 1808 while (uepnext != NULL && uepnext->ue_isset) 1809 uepnext = uepnext->ue_next; 1810 (*printer)(arg, "%s", uep->ue_name); 1811 if (uepnext != NULL) 1812 (*printer)(arg, "\t\t# (from %s)\n%s ", uep->ue_source, opt->name); 1813 else 1814 opt->source = uep->ue_source; 1815 } 1816} 1817