]> git.ozlabs.org Git - ppp.git/blobdiff - pppd/options.c
Describe environment variables set for scripts.
[ppp.git] / pppd / options.c
index 4e3ac8a2149be0d5bbaf3c6eaff257794848e4b6..5a194b59ea1054511f3ec402601753c529189d7b 100644 (file)
@@ -18,7 +18,7 @@
  */
 
 #ifndef lint
-static char rcsid[] = "$Id: options.c,v 1.31 1996/05/27 00:04:47 paulus Exp $";
+static char rcsid[] = "$Id: options.c,v 1.42 1998/03/26 04:46:06 paulus Exp $";
 #endif
 
 #include <ctype.h>
@@ -36,6 +36,10 @@ static char rcsid[] = "$Id: options.c,v 1.31 1996/05/27 00:04:47 paulus Exp $";
 #include <sys/stat.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#ifdef PPP_FILTER
+#include <pcap.h>
+#include <pcap-int.h>  /* XXX: To get struct pcap */
+#endif
 
 #include "pppd.h"
 #include "pathnames.h"
@@ -46,6 +50,9 @@ static char rcsid[] = "$Id: options.c,v 1.31 1996/05/27 00:04:47 paulus Exp $";
 #include "upap.h"
 #include "chap.h"
 #include "ccp.h"
+#ifdef CBCP_SUPPORT
+#include "cbcp.h"
+#endif
 
 #ifdef IPX_CHANGE
 #include "ipxcp.h"
@@ -67,6 +74,9 @@ char *strdup __P((char *));
 /*
  * Option variables and default values.
  */
+#ifdef PPP_FILTER
+int    dflag = 0;              /* Tell libpcap we want debugging */
+#endif
 int    debug = 0;              /* Debug flag */
 int    kdebugflag = 0;         /* Tell kernel to print debug messages */
 int    default_device = 1;     /* Using /dev/tty or equivalent */
@@ -92,6 +102,7 @@ int  lcp_echo_interval = 0;  /* Interval between LCP echo-requests */
 int    lcp_echo_fails = 0;     /* Tolerance to unanswered echo-requests */
 char   our_name[MAXNAMELEN];   /* Our name for authentication purposes */
 char   remote_name[MAXNAMELEN]; /* Peer's name for authentication */
+int    explicit_remote = 0;    /* User specified explicit remote name */
 int    usehostname = 0;        /* Use hostname for our_name */
 int    disable_defaultip = 0;  /* Don't use hostname for default IP adrs */
 int    demand = 0;             /* do dial-on-demand */
@@ -99,64 +110,89 @@ char       *ipparam = NULL;        /* Extra parameter for ip up/down scripts */
 int    cryptpap;               /* Passwords in pap-secrets are encrypted */
 int    idle_time_limit = 0;    /* Disconnect if idle for this many seconds */
 int    holdoff = 30;           /* # seconds to pause before reconnecting */
+int    refuse_pap = 0;         /* Set to say we won't do PAP */
+int    refuse_chap = 0;        /* Set to say we won't do CHAP */
+
+#ifdef MSLANMAN
+int    ms_lanman = 0;          /* Nonzero if use LanMan password instead of NT */
+                               /* Has meaning only with MS-CHAP challenges */
+#endif
+
+struct option_info auth_req_info;
+struct option_info connector_info;
+struct option_info disconnector_info;
+struct option_info welcomer_info;
+struct option_info devnam_info;
+#ifdef PPP_FILTER
+struct bpf_program pass_filter;/* Filter program for packets to pass */
+struct bpf_program active_filter; /* Filter program for link-active pkts */
+pcap_t  pc;                    /* Fake struct pcap so we can compile expr */
+#endif
 
 /*
  * Prototypes
  */
-static int setdevname __P((char *));
+static int setdevname __P((char *, int));
 static int setipaddr __P((char *));
-static int setdebug __P((void));
+static int setspeed __P((char *));
+static int setdebug __P((char **));
 static int setkdebug __P((char **));
-static int setpassive __P((void));
-static int setsilent __P((void));
-static int noopt __P((void));
-static int setnovj __P((void));
-static int setnovjccomp __P((void));
+static int setpassive __P((char **));
+static int setsilent __P((char **));
+static int noopt __P((char **));
+static int setnovj __P((char **));
+static int setnovjccomp __P((char **));
 static int setvjslots __P((char **));
-static int reqpap __P((void));
-static int nopap __P((void));
+static int reqpap __P((char **));
+static int nopap __P((char **));
 #ifdef OLD_OPTIONS
 static int setupapfile __P((char **));
 #endif
-static int nochap __P((void));
-static int reqchap __P((void));
-static int setspeed __P((char *));
-static int noaccomp __P((void));
-static int noasyncmap __P((void));
-static int noip __P((void));
-static int nomagicnumber __P((void));
+static int nochap __P((char **));
+static int reqchap __P((char **));
+static int noaccomp __P((char **));
+static int noasyncmap __P((char **));
+static int noip __P((char **));
+static int nomagicnumber __P((char **));
 static int setasyncmap __P((char **));
 static int setescape __P((char **));
 static int setmru __P((char **));
 static int setmtu __P((char **));
-static int nomru __P((void));
-static int nopcomp __P((void));
+#ifdef CBCP_SUPPORT
+static int setcbcp __P((char **));
+#endif
+static int nomru __P((char **));
+static int nopcomp __P((char **));
 static int setconnector __P((char **));
 static int setdisconnector __P((char **));
 static int setwelcomer __P((char **));
 static int setmaxconnect __P((char **));
 static int setdomain __P((char **));
 static int setnetmask __P((char **));
-static int setcrtscts __P((void));
-static int setnocrtscts __P((void));
-static int setxonxoff __P((void));
-static int setnodetach __P((void));
-static int setmodem __P((void));
-static int setlocal __P((void));
-static int setlock __P((void));
+static int setcrtscts __P((char **));
+static int setnocrtscts __P((char **));
+static int setxonxoff __P((char **));
+static int setnodetach __P((char **));
+static int setupdetach __P((char **));
+static int setmodem __P((char **));
+static int setlocal __P((char **));
+static int setlock __P((char **));
 static int setname __P((char **));
 static int setuser __P((char **));
 static int setremote __P((char **));
-static int setauth __P((void));
+static int setauth __P((char **));
+static int setnoauth __P((char **));
 static int readfile __P((char **));
-static int setdefaultroute __P((void));
-static int setnodefaultroute __P((void));
-static int setproxyarp __P((void));
-static int setnoproxyarp __P((void));
-static int setpersist __P((void));
-static int setdologin __P((void));
-static int setusehostname __P((void));
-static int setnoipdflt __P((void));
+static int callfile __P((char **));
+static int setdefaultroute __P((char **));
+static int setnodefaultroute __P((char **));
+static int setproxyarp __P((char **));
+static int setnoproxyarp __P((char **));
+static int setpersist __P((char **));
+static int setnopersist __P((char **));
+static int setdologin __P((char **));
+static int setusehostname __P((char **));
+static int setnoipdflt __P((char **));
 static int setlcptimeout __P((char **));
 static int setlcpterm __P((char **));
 static int setlcpconf __P((char **));
@@ -171,33 +207,40 @@ static int setpapreqtime __P((char **));
 static int setchaptimeout __P((char **));
 static int setchapchal __P((char **));
 static int setchapintv __P((char **));
-static int setipcpaccl __P((void));
-static int setipcpaccr __P((void));
+static int setipcpaccl __P((char **));
+static int setipcpaccr __P((char **));
 static int setlcpechointv __P((char **));
 static int setlcpechofails __P((char **));
-static int noccp __P((void));
+static int noccp __P((char **));
 static int setbsdcomp __P((char **));
-static int setnobsdcomp __P((void));
+static int setnobsdcomp __P((char **));
 static int setdeflate __P((char **));
-static int setnodeflate __P((void));
-static int setdemand __P((void));
-static int setpred1comp __P((void));
-static int setnopred1comp __P((void));
+static int setnodeflate __P((char **));
+static int setnodeflatedraft __P((char **));
+static int setdemand __P((char **));
+static int setpred1comp __P((char **));
+static int setnopred1comp __P((char **));
 static int setipparam __P((char **));
-static int setpapcrypt __P((void));
+static int setpapcrypt __P((char **));
 static int setidle __P((char **));
 static int setholdoff __P((char **));
-#if 0
+static int setdnsaddr __P((char **));
+static int resetipxproto __P((char **));
+static int setwinsaddr __P((char **));
+static int showversion __P((char **));
+static int showhelp __P((char **));
+
+#ifdef PPP_FILTER
+static int setpdebug __P((char **));
 static int setpassfilter __P((char **));
 static int setactivefilter __P((char **));
 #endif
 
 #ifdef IPX_CHANGE
-static int setipxproto __P((void));
-static int resetipxproto __P((void));
-static int setipxanet __P((void));
-static int setipxalcl __P((void));
-static int setipxarmt __P((void));
+static int setipxproto __P((char **));
+static int setipxanet __P((char **));
+static int setipxalcl __P((char **));
+static int setipxarmt __P((char **));
 static int setipxnetwork __P((char **));
 static int setipxnode __P((char **));
 static int setipxrouter __P((char **));
@@ -208,14 +251,13 @@ static int setipxcpconf __P((char **));
 static int setipxcpfails __P((char **));
 #endif /* IPX_CHANGE */
 
-#ifdef USE_MS_DNS
-static int setdnsaddr __P((char **));
+#ifdef MSLANMAN
+static int setmslanman __P((char **));
 #endif
 
 static int number_option __P((char *, u_int32_t *, int));
 static int int_option __P((char *, int *));
 static int readable __P((int fd));
-static void option_error __P((char *fmt, ...));
 
 /*
  * Valid arguments.
@@ -223,7 +265,7 @@ static void option_error __P((char *fmt, ...));
 static struct cmd {
     char *cmd_name;
     int num_args;
-    int (*cmd_func)();
+    int (*cmd_func) __P((char **));
 } cmds[] = {
     {"-all", 0, noopt},                /* Don't request/allow any options (useless) */
     {"noaccomp", 0, noaccomp}, /* Disable Address/Control compression */
@@ -234,6 +276,7 @@ static struct cmd {
     {"-d", 0, setdebug},       /* Increase debugging level */
     {"nodetach", 0, setnodetach}, /* Don't detach from controlling tty */
     {"-detach", 0, setnodetach}, /* don't fork */
+    {"updetach", 0, setupdetach}, /* Detach once an NP has come up */
     {"noip", 0, noip},         /* Disable IP and IPCP */
     {"-ip", 0, noip},          /* Disable IP and IPCP */
     {"nomagic", 0, nomagicnumber}, /* Disable magic number negotiation */
@@ -274,6 +317,9 @@ static struct cmd {
     {"domain", 1, setdomain},  /* Add given domain name to hostname*/
     {"mru", 1, setmru},                /* Set MRU value for negotiation */
     {"mtu", 1, setmtu},                /* Set our MTU */
+#ifdef CBCP_SUPPORT
+    {"callback", 1, setcbcp},  /* Ask for callback */
+#endif
     {"netmask", 1, setnetmask},        /* set netmask */
     {"passive", 0, setpassive},        /* Set passive mode */
     {"silent", 0, setsilent},  /* Set silent mode */
@@ -281,11 +327,13 @@ static struct cmd {
     {"local", 0, setlocal},    /* Don't use modem control lines */
     {"lock", 0, setlock},      /* Lock serial device (with lock file) */
     {"name", 1, setname},      /* Set local name for authentication */
-    {"user", 1, setuser},      /* Set username for PAP auth with peer */
+    {"user", 1, setuser},      /* Set name for auth with peer */
     {"usehostname", 0, setusehostname},        /* Must use hostname for auth. */
     {"remotename", 1, setremote}, /* Set remote name for authentication */
     {"auth", 0, setauth},      /* Require authentication from peer */
+    {"noauth", 0, setnoauth},  /* Don't require peer to authenticate */
     {"file", 1, readfile},     /* Take options from a file */
+    {"call", 1, callfile},     /* Take options from a privileged file */
     {"defaultroute", 0, setdefaultroute}, /* Add default route */
     {"nodefaultroute", 0, setnodefaultroute}, /* disable defaultroute option */
     {"-defaultroute", 0, setnodefaultroute}, /* disable defaultroute option */
@@ -293,6 +341,7 @@ static struct cmd {
     {"noproxyarp", 0, setnoproxyarp}, /* disable proxyarp option */
     {"-proxyarp", 0, setnoproxyarp}, /* disable proxyarp option */
     {"persist", 0, setpersist},        /* Keep on reopening connection after close */
+    {"nopersist", 0, setnopersist},  /* Turn off persist option */
     {"demand", 0, setdemand},  /* Dial on demand */
     {"login", 0, setdologin},  /* Use system password database for UPAP */
     {"noipdefault", 0, setnoipdflt}, /* Don't use name for default IP adrs */
@@ -322,6 +371,7 @@ static struct cmd {
     {"deflate", 1, setdeflate},                /* request Deflate compression */
     {"nodeflate", 0, setnodeflate},    /* don't allow Deflate compression */
     {"-deflate", 0, setnodeflate},     /* don't allow Deflate compression */
+    {"nodeflatedraft", 0, setnodeflatedraft}, /* don't use draft deflate # */
     {"predictor1", 0, setpred1comp},   /* request Predictor-1 */
     {"nopredictor1", 0, setnopred1comp},/* don't allow Predictor-1 */
     {"-predictor1", 0, setnopred1comp},        /* don't allow Predictor-1 */
@@ -329,7 +379,16 @@ static struct cmd {
     {"papcrypt", 0, setpapcrypt},      /* PAP passwords encrypted */
     {"idle", 1, setidle},              /* idle time limit (seconds) */
     {"holdoff", 1, setholdoff},                /* set holdoff time (seconds) */
-#if 0
+    {"ms-dns", 1, setdnsaddr},         /* DNS address for the peer's use */
+    {"ms-wins", 1, setwinsaddr},       /* Nameserver for SMB over TCP/IP for peer */
+    {"noipx",  0, resetipxproto},      /* Disable IPXCP (and IPX) */
+    {"-ipx",   0, resetipxproto},      /* Disable IPXCP (and IPX) */
+    {"--version", 0, showversion},     /* Show version number */
+    {"--help", 0, showhelp},           /* Show brief listing of options */
+    {"-h", 0, showhelp},               /* ditto */
+
+#ifdef PPP_FILTER
+    {"pdebug", 1, setpdebug},          /* libpcap debugging */
     {"pass-filter", 1, setpassfilter}, /* set filter for packets to pass */
     {"active-filter", 1, setactivefilter}, /* set filter for active pkts */
 #endif
@@ -350,13 +409,11 @@ static struct cmd {
     {"ipx-compression", 1, setipxcompression}, /* IPX compression number */
 #endif
     {"ipx",                 0, setipxproto},   /* Enable IPXCP (and IPX) */
-    {"noipx",               0, resetipxproto}, /* Disable IPXCP (and IPX) */
     {"+ipx",                0, setipxproto},   /* Enable IPXCP (and IPX) */
-    {"-ipx",                0, resetipxproto}, /* Disable IPXCP (and IPX) */
 #endif /* IPX_CHANGE */
 
-#ifdef USE_MS_DNS
-    {"ms-dns", 1, setdnsaddr}, /* DNS address(es) for the peer's use */
+#ifdef MSLANMAN
+    {"ms-lanman", 0, setmslanman},     /* Use LanMan psswd when using MS-CHAP */
 #endif
 
     {NULL, 0, NULL}
@@ -382,16 +439,15 @@ Usage: %s [ options ], where options are:\n\
        file <f>        Take options from file <f>\n\
        modem           Use modem control lines\n\
        mru <n>         Set MRU value to <n> for negotiation\n\
-       netmask <n>     Set interface netmask to <n>\n\
 See pppd(8) for more options.\n\
 ";
 
 static char *current_option;   /* the name of the option being parsed */
-
+static int privileged_option;  /* set iff the current option came from root */
+static char *option_source;    /* string saying where the option came from */
 
 /*
- * parse_args - parse a string of arguments, from the command
- * line or from a file.
+ * parse_args - parse a string of arguments from the command line.
  */
 int
 parse_args(argc, argv)
@@ -402,6 +458,8 @@ parse_args(argc, argv)
     struct cmd *cmdp;
     int ret;
 
+    privileged_option = privileged;
+    option_source = "command line";
     while (argc > 0) {
        arg = *argv++;
        --argc;
@@ -428,7 +486,7 @@ parse_args(argc, argv)
            /*
             * Maybe a tty name, speed or IP address?
             */
-           if ((ret = setdevname(arg)) == 0
+           if ((ret = setdevname(arg, 0)) == 0
                && (ret = setspeed(arg)) == 0
                && (ret = setipaddr(arg)) == 0) {
                option_error("unrecognized option '%s'", arg);
@@ -442,6 +500,38 @@ parse_args(argc, argv)
     return 1;
 }
 
+/*
+ * scan_args - scan the command line arguments to get the tty name,
+ * if specified.
+ */
+void
+scan_args(argc, argv)
+    int argc;
+    char **argv;
+{
+    char *arg;
+    struct cmd *cmdp;
+
+    while (argc > 0) {
+       arg = *argv++;
+       --argc;
+
+       /* Skip options and their arguments */
+       for (cmdp = cmds; cmdp->cmd_name; cmdp++)
+           if (!strcmp(arg, cmdp->cmd_name))
+               break;
+
+       if (cmdp->cmd_name != NULL) {
+           argc -= cmdp->num_args;
+           argv += cmdp->num_args;
+           continue;
+       }
+
+       /* Check if it's a tty name and copy it if so */
+       (void) setdevname(arg, 1);
+    }
+}
+
 /*
  * usage - print out a message telling how to use the program.
  */
@@ -453,19 +543,50 @@ usage()
                progname);
 }
 
+/*
+ * showhelp - print out usage message and exit.
+ */
+static int
+showhelp(argv)
+    char **argv;
+{
+    if (phase == PHASE_INITIALIZE) {
+       usage();
+       exit(0);
+    }
+    return 0;
+}
+
+/*
+ * showversion - print out the version number and exit.
+ */
+static int
+showversion(argv)
+    char **argv;
+{
+    if (phase == PHASE_INITIALIZE) {
+       fprintf(stderr, "pppd version %s patch level %d%s\n",
+               VERSION, PATCHLEVEL, IMPLEMENTATION);
+       exit(0);
+    }
+    return 0;
+}
+
 /*
  * options_from_file - Read a string of options from a file,
  * and interpret them.
  */
 int
-options_from_file(filename, must_exist, check_prot)
+options_from_file(filename, must_exist, check_prot, priv)
     char *filename;
     int must_exist;
     int check_prot;
+    int priv;
 {
     FILE *f;
     int i, newline, ret;
     struct cmd *cmdp;
+    int oldpriv;
     char *argv[MAXARGS];
     char args[MAXARGS][MAXWORDLEN];
     char cmd[MAXWORDLEN];
@@ -482,6 +603,9 @@ options_from_file(filename, must_exist, check_prot)
        return 0;
     }
 
+    oldpriv = privileged_option;
+    privileged_option = priv;
+    ret = 0;
     while (getword(f, cmd, &newline, filename)) {
        /*
         * First see if it's a command.
@@ -496,34 +620,35 @@ options_from_file(filename, must_exist, check_prot)
                    option_error(
                        "In file %s: too few parameters for option '%s'",
                        filename, cmd);
-                   fclose(f);
-                   return 0;
+                   goto err;
                }
                argv[i] = args[i];
            }
            current_option = cmd;
-           if (!(*cmdp->cmd_func)(argv)) {
-               fclose(f);
-               return 0;
-           }
+           if (!(*cmdp->cmd_func)(argv))
+               goto err;
 
        } else {
            /*
             * Maybe a tty name, speed or IP address?
             */
-           if ((ret = setdevname(cmd)) == 0
-               && (ret = setspeed(cmd)) == 0
-               && (ret = setipaddr(cmd)) == 0) {
+           if ((i = setdevname(cmd, 0)) == 0
+               && (i = setspeed(cmd)) == 0
+               && (i = setipaddr(cmd)) == 0) {
                option_error("In file %s: unrecognized option '%s'",
                             filename, cmd);
-               fclose(f);
-               return 0;
+               goto err;
            }
-           if (ret < 0)        /* error */
-               return 0;
+           if (i < 0)          /* error */
+               goto err;
        }
     }
-    return 1;
+    ret = 1;
+
+err:
+    fclose(f);
+    privileged_option = oldpriv;
+    return ret;
 }
 
 /*
@@ -547,7 +672,7 @@ options_from_user()
     strcpy(path, user);
     strcat(path, "/");
     strcat(path, file);
-    ret = options_from_file(path, 0, 1);
+    ret = options_from_file(path, 0, 1, privileged);
     free(path);
     return ret;
 }
@@ -575,7 +700,7 @@ options_for_tty()
     for (p = path + strlen(path); *dev != 0; ++dev)
        *p++ = (*dev == '/'? '.': *dev);
     *p = 0;
-    ret = options_from_file(path, 0, 0);
+    ret = options_from_file(path, 0, 0, 1);
     free(path);
     return ret;
 }
@@ -589,7 +714,6 @@ void
 option_error __V((char *fmt, ...))
 {
     va_list args;
-    int n;
     char buf[256];
 
 #if __STDC__
@@ -931,14 +1055,60 @@ static int
 readfile(argv)
     char **argv;
 {
-    return options_from_file(*argv, 1, 1);
+    return options_from_file(*argv, 1, 1, privileged_option);
+}
+
+/*
+ * callfile - take commands from /etc/ppp/peers/<name>.
+ * Name may not contain /../, start with / or ../, or end in /..
+ */
+static int
+callfile(argv)
+    char **argv;
+{
+    char *fname, *arg, *p;
+    int l, ok;
+
+    arg = *argv;
+    ok = 1;
+    if (arg[0] == '/' || arg[0] == 0)
+       ok = 0;
+    else {
+       for (p = arg; *p != 0; ) {
+           if (p[0] == '.' && p[1] == '.' && (p[2] == '/' || p[2] == 0)) {
+               ok = 0;
+               break;
+           }
+           while (*p != '/' && *p != 0)
+               ++p;
+           if (*p == '/')
+               ++p;
+       }
+    }
+    if (!ok) {
+       option_error("call option value may not contain .. or start with /");
+       return 0;
+    }
+
+    l = strlen(arg) + strlen(_PATH_PEERFILES) + 1;
+    if ((fname = (char *) malloc(l)) == NULL)
+       novm("call file name");
+    strcpy(fname, _PATH_PEERFILES);
+    strcat(fname, arg);
+
+    ok = options_from_file(fname, 1, 1, 1);
+
+    free(fname);
+    return ok;
 }
 
+
 /*
  * setdebug - Set debug (command line argument).
  */
 static int
-setdebug()
+setdebug(argv)
+    char **argv;
 {
     debug++;
     return (1);
@@ -954,11 +1124,56 @@ setkdebug(argv)
     return int_option(*argv, &kdebugflag);
 }
 
+#ifdef PPP_FILTER
+/*
+ * setpdebug - Set libpcap debugging level.
+ */
+static int
+setpdebug(argv)
+    char **argv;
+{
+    return int_option(*argv, &dflag);
+}
+
+/*
+ * setpassfilter - Set the pass filter for packets
+ */
+static int
+setpassfilter(argv)
+    char **argv;
+{
+    pc.linktype = DLT_PPP;
+    pc.snapshot = PPP_HDRLEN;
+    if (pcap_compile(&pc, &pass_filter, *argv, 1, netmask) == 0)
+       return 1;
+    option_error("error in pass-filter expression: %s\n", pcap_geterr(&pc));
+    return 0;
+}
+
+/*
+ * setactivefilter - Set the active filter for packets
+ */
+static int
+setactivefilter(argv)
+    char **argv;
+{
+    pc.linktype = DLT_PPP;
+    pc.snapshot = PPP_HDRLEN;
+    if (pcap_compile(&pc, &active_filter, *argv, 1, netmask) == 0)
+       return 1;
+    option_error("error in active-filter expression: %s\n", pcap_geterr(&pc));
+    return 0;
+}
+#endif
+
 /*
  * noopt - Disable all options.
  */
 static int
-noopt()
+noopt(argv)
+    char **argv;
 {
     BZERO((char *) &lcp_wantoptions[0], sizeof (struct lcp_options));
     BZERO((char *) &lcp_allowoptions[0], sizeof (struct lcp_options));
@@ -977,7 +1192,8 @@ noopt()
  * noaccomp - Disable Address/Control field compression negotiation.
  */
 static int
-noaccomp()
+noaccomp(argv)
+    char **argv;
 {
     lcp_wantoptions[0].neg_accompression = 0;
     lcp_allowoptions[0].neg_accompression = 0;
@@ -989,7 +1205,8 @@ noaccomp()
  * noasyncmap - Disable async map negotiation.
  */
 static int
-noasyncmap()
+noasyncmap(argv)
+    char **argv;
 {
     lcp_wantoptions[0].neg_asyncmap = 0;
     lcp_allowoptions[0].neg_asyncmap = 0;
@@ -1001,7 +1218,8 @@ noasyncmap()
  * noip - Disable IP and IPCP.
  */
 static int
-noip()
+noip(argv)
+    char **argv;
 {
     ipcp_protent.enabled_flag = 0;
     return (1);
@@ -1012,7 +1230,8 @@ noip()
  * nomagicnumber - Disable magic number negotiation.
  */
 static int
-nomagicnumber()
+nomagicnumber(argv)
+    char **argv;
 {
     lcp_wantoptions[0].neg_magicnumber = 0;
     lcp_allowoptions[0].neg_magicnumber = 0;
@@ -1024,7 +1243,8 @@ nomagicnumber()
  * nomru - Disable mru negotiation.
  */
 static int
-nomru()
+nomru(argv)
+    char **argv;
 {
     lcp_wantoptions[0].neg_mru = 0;
     lcp_allowoptions[0].neg_mru = 0;
@@ -1069,12 +1289,28 @@ setmtu(argv)
     return (1);
 }
 
+#ifdef CBCP_SUPPORT
+static int
+setcbcp(argv)
+    char **argv;
+{
+    lcp_wantoptions[0].neg_cbcp = 1;
+    cbcp_protent.enabled_flag = 1;
+    cbcp[0].us_number = strdup(*argv);
+    if (cbcp[0].us_number == 0)
+       novm("callback number");
+    cbcp[0].us_type |= (1 << CB_CONF_USER);
+    cbcp[0].us_type |= (1 << CB_CONF_ADMIN);
+    return (1);
+}
+#endif
 
 /*
  * nopcomp - Disable Protocol field compression negotiation.
  */
 static int
-nopcomp()
+nopcomp(argv)
+    char **argv;
 {
     lcp_wantoptions[0].neg_pcompression = 0;
     lcp_allowoptions[0].neg_pcompression = 0;
@@ -1087,7 +1323,8 @@ nopcomp()
  * LCP configure-requests).
  */
 static int
-setpassive()
+setpassive(argv)
+    char **argv;
 {
     lcp_wantoptions[0].passive = 1;
     return (1);
@@ -1099,7 +1336,8 @@ setpassive()
  * until we get one from the peer).
  */
 static int
-setsilent()
+setsilent(argv)
+    char **argv;
 {
     lcp_wantoptions[0].silent = 1;
     return 1;
@@ -1110,9 +1348,10 @@ setsilent()
  * nopap - Disable PAP authentication with peer.
  */
 static int
-nopap()
+nopap(argv)
+    char **argv;
 {
-    lcp_allowoptions[0].neg_upap = 0;
+    refuse_pap = 1;
     return (1);
 }
 
@@ -1121,10 +1360,11 @@ nopap()
  * reqpap - Require PAP authentication from peer.
  */
 static int
-reqpap()
+reqpap(argv)
+    char **argv;
 {
     lcp_wantoptions[0].neg_upap = 1;
-    auth_required = 1;
+    setauth(NULL);
     return 1;
 }
 
@@ -1176,9 +1416,10 @@ setupapfile(argv)
  * nochap - Disable CHAP authentication with peer.
  */
 static int
-nochap()
+nochap(argv)
+    char **argv;
 {
-    lcp_allowoptions[0].neg_chap = 0;
+    refuse_chap = 1;
     return (1);
 }
 
@@ -1187,10 +1428,11 @@ nochap()
  * reqchap - Require CHAP authentication from peer.
  */
 static int
-reqchap()
+reqchap(argv)
+    char **argv;
 {
     lcp_wantoptions[0].neg_chap = 1;
-    auth_required = 1;
+    setauth(NULL);
     return (1);
 }
 
@@ -1199,7 +1441,8 @@ reqchap()
  * setnovj - disable vj compression
  */
 static int
-setnovj()
+setnovj(argv)
+    char **argv;
 {
     ipcp_wantoptions[0].neg_vj = 0;
     ipcp_allowoptions[0].neg_vj = 0;
@@ -1211,7 +1454,8 @@ setnovj()
  * setnovjccomp - disable VJ connection-ID compression
  */
 static int
-setnovjccomp()
+setnovjccomp(argv)
+    char **argv;
 {
     ipcp_wantoptions[0].cflag = 0;
     ipcp_allowoptions[0].cflag = 0;
@@ -1250,7 +1494,9 @@ setconnector(argv)
     connector = strdup(*argv);
     if (connector == NULL)
        novm("connect script");
-  
+    connector_info.priv = privileged_option;
+    connector_info.source = option_source;
+
     return (1);
 }
 
@@ -1264,6 +1510,8 @@ setdisconnector(argv)
     disconnector = strdup(*argv);
     if (disconnector == NULL)
        novm("disconnect script");
+    disconnector_info.priv = privileged_option;
+    disconnector_info.source = option_source;
   
     return (1);
 }
@@ -1278,7 +1526,9 @@ setwelcomer(argv)
     welcomer = strdup(*argv);
     if (welcomer == NULL)
        novm("welcome script");
-  
+    welcomer_info.priv = privileged_option;
+    welcomer_info.source = option_source;
+
     return (1);
 }
 
@@ -1292,10 +1542,14 @@ setmaxconnect(argv)
     int value;
 
     if (!int_option(*argv, &value))
-      return 0;
+       return 0;
     if (value < 0) {
-      option_error("maxconnect time must be positive");
-      return 0;
+       option_error("maxconnect time must be positive");
+       return 0;
+    }
+    if (maxconnect > 0 && (value == 0 || value > maxconnect)) {
+       option_error("maxconnect time cannot be increased");
+       return 0;
     }
     maxconnect = value;
     return 1;
@@ -1308,6 +1562,10 @@ static int
 setdomain(argv)
     char **argv;
 {
+    if (!privileged_option) {
+       option_error("using the domain option requires root privilege");
+       return 0;
+    }
     gethostname(hostname, MAXNAMELEN);
     if (**argv != 0) {
        if (**argv != '.')
@@ -1356,7 +1614,7 @@ setescape(argv)
            return 0;
        }
        p = endp;
-       if (n < 0 || 0x20 <= n && n <= 0x3F || n == 0x5E || n > 0xFF) {
+       if (n < 0 || (0x20 <= n && n <= 0x3F) || n == 0x5E || n > 0xFF) {
            option_error("can't escape character 0x%x", n);
            ret = 0;
        } else
@@ -1390,8 +1648,9 @@ setspeed(arg)
  * setdevname - Set the device name.
  */
 static int
-setdevname(cp)
+setdevname(cp, quiet)
     char *cp;
+    int quiet;
 {
     struct stat statbuf;
     char dev[MAXPATHLEN];
@@ -1410,15 +1669,17 @@ setdevname(cp)
      * Check if there is a device by this name.
      */
     if (stat(cp, &statbuf) < 0) {
-       if (errno == ENOENT)
+       if (errno == ENOENT || quiet)
            return 0;
        option_error("Couldn't stat %s: %m", cp);
        return -1;
     }
-  
+
     (void) strncpy(devnam, cp, MAXPATHLEN);
     devnam[MAXPATHLEN-1] = 0;
     default_device = FALSE;
+    devnam_info.priv = privileged_option;
+    devnam_info.source = option_source;
   
     return 1;
 }
@@ -1453,10 +1714,6 @@ setipaddr(arg)
                return -1;
            } else {
                local = *(u_int32_t *)hp->h_addr;
-               if (our_name[0] == 0) {
-                   strncpy(our_name, arg, MAXNAMELEN);
-                   our_name[MAXNAMELEN-1] = 0;
-               }
            }
        }
        if (bad_ip_adrs(local)) {
@@ -1500,7 +1757,8 @@ setipaddr(arg)
  * setnoipdflt - disable setipdefault()
  */
 static int
-setnoipdflt()
+setnoipdflt(argv)
+    char **argv;
 {
     disable_defaultip = 1;
     return 1;
@@ -1511,7 +1769,8 @@ setnoipdflt()
  * setipcpaccl - accept peer's idea of our address
  */
 static int
-setipcpaccl()
+setipcpaccl(argv)
+    char **argv;
 {
     ipcp_wantoptions[0].accept_local = 1;
     return 1;
@@ -1522,7 +1781,8 @@ setipcpaccl()
  * setipcpaccr - accept peer's idea of its address
  */
 static int
-setipcpaccr()
+setipcpaccr(argv)
+    char **argv;
 {
     ipcp_wantoptions[0].accept_remote = 1;
     return 1;
@@ -1536,9 +1796,39 @@ static int
 setnetmask(argv)
     char **argv;
 {
-    u_int32_t mask;
+    u_int32_t mask, b;
+    int n, ok;
+    char *p, *endp;
 
-    if ((mask = inet_addr(*argv)) == -1 || (netmask & ~mask) != 0) {
+    /*
+     * Unfortunately, if we use inet_addr, we can't tell whether
+     * a result of all 1s is an error or a valid 255.255.255.255.
+     */
+    p = *argv;
+    ok = 0;
+    mask = 0;
+    for (n = 3;; --n) {
+       b = strtoul(p, &endp, 0);
+       if (endp == p)
+           break;
+       if (b < 0 || b > 255) {
+           if (n == 3) {
+               /* accept e.g. 0xffffff00 */
+               p = endp;
+               mask = b;
+           }
+           break;
+       }
+       mask |= b << (n * 8);
+       p = endp;
+       if (*p != '.' || n == 0)
+           break;
+       ++p;
+    }
+
+    mask = htonl(mask);
+
+    if (*p != 0 || (netmask & ~mask) != 0) {
        option_error("invalid netmask value '%s'", *argv);
        return 0;
     }
@@ -1548,21 +1838,24 @@ setnetmask(argv)
 }
 
 static int
-setcrtscts()
+setcrtscts(argv)
+    char **argv;
 {
     crtscts = 1;
     return (1);
 }
 
 static int
-setnocrtscts()
+setnocrtscts(argv)
+    char **argv;
 {
     crtscts = -1;
     return (1);
 }
 
 static int
-setxonxoff()
+setxonxoff(argv)
+    char **argv;
 {
     lcp_wantoptions[0].asyncmap |= 0x000A0000; /* escape ^S and ^Q */
     lcp_wantoptions[0].neg_asyncmap = 1;
@@ -1572,42 +1865,57 @@ setxonxoff()
 }
 
 static int
-setnodetach()
+setnodetach(argv)
+    char **argv;
 {
     nodetach = 1;
     return (1);
 }
 
 static int
-setdemand()
+setupdetach(argv)
+    char **argv;
+{
+    nodetach = -1;
+    return (1);
+}
+
+static int
+setdemand(argv)
+    char **argv;
 {
     demand = 1;
+    persist = 1;
     return 1;
 }
 
 static int
-setmodem()
+setmodem(argv)
+    char **argv;
 {
     modem = 1;
     return 1;
 }
 
 static int
-setlocal()
+setlocal(argv)
+    char **argv;
 {
     modem = 0;
     return 1;
 }
 
 static int
-setlock()
+setlock(argv)
+    char **argv;
 {
     lockflag = 1;
     return 1;
 }
 
 static int
-setusehostname()
+setusehostname(argv)
+    char **argv;
 {
     usehostname = 1;
     return 1;
@@ -1617,10 +1925,12 @@ static int
 setname(argv)
     char **argv;
 {
-    if (our_name[0] == 0) {
-       strncpy(our_name, argv[0], MAXNAMELEN);
-       our_name[MAXNAMELEN-1] = 0;
+    if (!privileged_option) {
+       option_error("using the name option requires root privilege");
+       return 0;
     }
+    strncpy(our_name, argv[0], MAXNAMELEN);
+    our_name[MAXNAMELEN-1] = 0;
     return 1;
 }
 
@@ -1643,14 +1953,33 @@ setremote(argv)
 }
 
 static int
-setauth()
+setauth(argv)
+    char **argv;
 {
     auth_required = 1;
+    if (privileged_option > auth_req_info.priv) {
+       auth_req_info.priv = privileged_option;
+       auth_req_info.source = option_source;
+    }
+    return 1;
+}
+
+static int
+setnoauth(argv)
+    char **argv;
+{
+    if (auth_required && privileged_option < auth_req_info.priv) {
+       option_error("cannot override auth option set by %s",
+                    auth_req_info.source);
+       return 0;
+    }
+    auth_required = 0;
     return 1;
 }
 
 static int
-setdefaultroute()
+setdefaultroute(argv)
+    char **argv;
 {
     if (!ipcp_allowoptions[0].default_route) {
        option_error("defaultroute option is disabled");
@@ -1661,7 +1990,8 @@ setdefaultroute()
 }
 
 static int
-setnodefaultroute()
+setnodefaultroute(argv)
+    char **argv;
 {
     ipcp_allowoptions[0].default_route = 0;
     ipcp_wantoptions[0].default_route = 0;
@@ -1669,7 +1999,8 @@ setnodefaultroute()
 }
 
 static int
-setproxyarp()
+setproxyarp(argv)
+    char **argv;
 {
     if (!ipcp_allowoptions[0].proxy_arp) {
        option_error("proxyarp option is disabled");
@@ -1680,7 +2011,8 @@ setproxyarp()
 }
 
 static int
-setnoproxyarp()
+setnoproxyarp(argv)
+    char **argv;
 {
     ipcp_wantoptions[0].proxy_arp = 0;
     ipcp_allowoptions[0].proxy_arp = 0;
@@ -1688,14 +2020,24 @@ setnoproxyarp()
 }
 
 static int
-setpersist()
+setpersist(argv)
+    char **argv;
 {
     persist = 1;
     return 1;
 }
 
 static int
-setdologin()
+setnopersist(argv)
+    char **argv;
+{
+    persist = 0;
+    return 1;
+}
+
+static int
+setdologin(argv)
+    char **argv;
 {
     uselogin = 1;
     return 1;
@@ -1821,7 +2163,8 @@ setchapintv(argv)
 }
 
 static int
-noccp()
+noccp(argv)
+    char **argv;
 {
     ccp_protent.enabled_flag = 0;
     return 1;
@@ -1844,8 +2187,8 @@ setbsdcomp(argv)
        option_error("invalid parameter '%s' for bsdcomp option", *argv);
        return 0;
     }
-    if (rbits != 0 && (rbits < BSD_MIN_BITS || rbits > BSD_MAX_BITS)
-       || abits != 0 && (abits < BSD_MIN_BITS || abits > BSD_MAX_BITS)) {
+    if ((rbits != 0 && (rbits < BSD_MIN_BITS || rbits > BSD_MAX_BITS))
+       || (abits != 0 && (abits < BSD_MIN_BITS || abits > BSD_MAX_BITS))) {
        option_error("bsdcomp option values must be 0 or %d .. %d",
                     BSD_MIN_BITS, BSD_MAX_BITS);
        return 0;
@@ -1864,7 +2207,8 @@ setbsdcomp(argv)
 }
 
 static int
-setnobsdcomp()
+setnobsdcomp(argv)
+    char **argv;
 {
     ccp_wantoptions[0].bsd_compress = 0;
     ccp_allowoptions[0].bsd_compress = 0;
@@ -1888,9 +2232,9 @@ setdeflate(argv)
        option_error("invalid parameter '%s' for deflate option", *argv);
        return 0;
     }
-    if (rbits != 0 && (rbits < DEFLATE_MIN_SIZE || rbits > DEFLATE_MAX_SIZE)
-       || abits != 0 && (abits < DEFLATE_MIN_SIZE
-                         || abits > DEFLATE_MAX_SIZE)) {
+    if ((rbits != 0 && (rbits < DEFLATE_MIN_SIZE || rbits > DEFLATE_MAX_SIZE))
+       || (abits != 0 && (abits < DEFLATE_MIN_SIZE
+                         || abits > DEFLATE_MAX_SIZE))) {
        option_error("deflate option values must be 0 or %d .. %d",
                     DEFLATE_MIN_SIZE, DEFLATE_MAX_SIZE);
        return 0;
@@ -1909,7 +2253,8 @@ setdeflate(argv)
 }
 
 static int
-setnodeflate()
+setnodeflate(argv)
+    char **argv;
 {
     ccp_wantoptions[0].deflate = 0;
     ccp_allowoptions[0].deflate = 0;
@@ -1917,7 +2262,17 @@ setnodeflate()
 }
 
 static int
-setpred1comp()
+setnodeflatedraft(argv)
+    char **argv;
+{
+    ccp_wantoptions[0].deflate_draft = 0;
+    ccp_allowoptions[0].deflate_draft = 0;
+    return 1;
+}
+
+static int
+setpred1comp(argv)
+    char **argv;
 {
     ccp_wantoptions[0].predictor_1 = 1;
     ccp_allowoptions[0].predictor_1 = 1;
@@ -1925,7 +2280,8 @@ setpred1comp()
 }
 
 static int
-setnopred1comp()
+setnopred1comp(argv)
+    char **argv;
 {
     ccp_wantoptions[0].predictor_1 = 0;
     ccp_allowoptions[0].predictor_1 = 0;
@@ -1944,7 +2300,8 @@ setipparam(argv)
 }
 
 static int
-setpapcrypt()
+setpapcrypt(argv)
+    char **argv;
 {
     cryptpap = 1;
     return 1;
@@ -1964,6 +2321,68 @@ setholdoff(argv)
     return int_option(*argv, &holdoff);
 }
 
+/*
+ * setdnsaddr - set the dns address(es)
+ */
+static int
+setdnsaddr(argv)
+    char **argv;
+{
+    u_int32_t dns;
+    struct hostent *hp;
+
+    dns = inet_addr(*argv);
+    if (dns == -1) {
+       if ((hp = gethostbyname(*argv)) == NULL) {
+           option_error("invalid address parameter '%s' for ms-dns option",
+                        *argv);
+           return 0;
+       }
+       dns = *(u_int32_t *)hp->h_addr;
+    }
+
+    /* if there is no primary then update it. */
+    if (ipcp_allowoptions[0].dnsaddr[0] == 0)
+       ipcp_allowoptions[0].dnsaddr[0] = dns;
+
+    /* always set the secondary address value to the same value. */
+    ipcp_allowoptions[0].dnsaddr[1] = dns;
+
+    return (1);
+}
+
+/*
+ * setwinsaddr - set the wins address(es)
+ * This is primrarly used with the Samba package under UNIX or for pointing
+ * the caller to the existing WINS server on a Windows NT platform.
+ */
+static int
+setwinsaddr(argv)
+    char **argv;
+{
+    u_int32_t wins;
+    struct hostent *hp;
+
+    wins = inet_addr(*argv);
+    if (wins == -1) {
+       if ((hp = gethostbyname(*argv)) == NULL) {
+           option_error("invalid address parameter '%s' for ms-wins option",
+                        *argv);
+           return 0;
+       }
+       wins = *(u_int32_t *)hp->h_addr;
+    }
+
+    /* if there is no primary then update it. */
+    if (ipcp_allowoptions[0].winsaddr[0] == 0)
+       ipcp_allowoptions[0].winsaddr[0] = wins;
+
+    /* always set the secondary address value to the same value. */
+    ipcp_allowoptions[0].winsaddr[1] = wins;
+
+    return (1);
+}
+
 #ifdef IPX_CHANGE
 static int
 setipxrouter (argv)
@@ -2039,29 +2458,41 @@ static int
 setipxnetwork(argv)
     char **argv;
 {
-    ipxcp_wantoptions[0].neg_nn = 1;
-    return int_option(*argv, &ipxcp_wantoptions[0].our_network); 
+    u_int32_t v;
+
+    if (!number_option(*argv, &v, 16))
+       return 0;
+
+    ipxcp_wantoptions[0].our_network = (int) v;
+    ipxcp_wantoptions[0].neg_nn      = 1;
+    return 1;
 }
 
 static int
-setipxanet()
+setipxanet(argv)
+    char **argv;
 {
     ipxcp_wantoptions[0].accept_network = 1;
     ipxcp_allowoptions[0].accept_network = 1;
+    return 1;
 }
 
 static int
-setipxalcl()
+setipxalcl(argv)
+    char **argv;
 {
     ipxcp_wantoptions[0].accept_local = 1;
     ipxcp_allowoptions[0].accept_local = 1;
+    return 1;
 }
 
 static int
-setipxarmt()
+setipxarmt(argv)
+    char **argv;
 {
     ipxcp_wantoptions[0].accept_remote = 1;
     ipxcp_allowoptions[0].accept_remote = 1;
+    return 1;
 }
 
 static u_char *
@@ -2113,48 +2544,36 @@ setipxnode(argv)
 }
 
 static int
-setipxproto()
+setipxproto(argv)
+    char **argv;
 {
-    ipx_enabled = 1;           /* Enable IPXCP and IPX protocol */
+    ipxcp_protent.enabled_flag = 1;
     return 1;
 }
 
 static int
-resetipxproto()
+resetipxproto(argv)
+    char **argv;
 {
-    ipx_enabled = 0;           /* Disable IPXCP and IPX protocol */
+    ipxcp_protent.enabled_flag = 0;
     return 1;
 }
-#endif /* IPX_CHANGE */
-
-#ifdef USE_MS_DNS
-/*
- * setdnsaddr - set the dns address(es)
- */
+#else
 
 static int
-setdnsaddr(argv)
+resetipxproto(argv)
     char **argv;
 {
-    u_int32_t dns;
-    struct hostent *hp;
-
-    dns = inet_addr(*argv);
-    if (dns == -1) {
-       if ((hp = gethostbyname(*argv)) == NULL) {
-           option_error("invalid address parameter '%s' for ms-dns option",
-                        *argv);
-           return 0;
-       }
-       dns = *(u_int32_t *)hp->h_addr;
-    }
-
-    if (ipcp_allowoptions[0].dnsaddr[0] == 0) {
-       ipcp_allowoptions[0].dnsaddr[0] = dns;
-    } else {
-       ipcp_allowoptions[0].dnsaddr[1] = dns;
-    }
+    return 1;
+}
+#endif /* IPX_CHANGE */
 
+#ifdef MSLANMAN
+static int
+setmslanman(argv)
+    char **argv;
+{
+    ms_lanman = 1;
     return (1);
 }
-#endif /* USE_MS_DNS */
+#endif