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