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