Update to new pppd with new option parsing stuff
authorPaul Mackerras <paulus@samba.org>
Sat, 7 Nov 1998 06:59:32 +0000 (06:59 +0000)
committerPaul Mackerras <paulus@samba.org>
Sat, 7 Nov 1998 06:59:32 +0000 (06:59 +0000)
25 files changed:
pppd/auth.c
pppd/cbcp.c
pppd/ccp.c
pppd/ccp.h
pppd/chap.c
pppd/chap_ms.c
pppd/ipcp.c
pppd/ipcp.h
pppd/ipxcp.c
pppd/ipxcp.h
pppd/lcp.c
pppd/lcp.h
pppd/main.c
pppd/options.c
pppd/patchlevel.h
pppd/pppd.8
pppd/pppd.h
pppd/sys-NeXT.c
pppd/sys-bsd.c
pppd/sys-linux.c
pppd/sys-osf.c
pppd/sys-sunos4.c
pppd/sys-svr4.c
pppd/sys-ultrix.c
pppd/upap.c

index 7b1ba5ccdd9d4d40d7bb40e3ceb9cf3eac0018c7..c924d7be35bfaf72105a4d8ce288f19a4808a3ff 100644 (file)
@@ -33,7 +33,7 @@
  */
 
 #ifndef lint
-static char rcsid[] = "$Id: auth.c,v 1.38 1998/11/02 10:55:19 paulus Exp $";
+static char rcsid[] = "$Id: auth.c,v 1.39 1998/11/07 06:59:25 paulus Exp $";
 #endif
 
 #include <stdio.h>
@@ -104,6 +104,7 @@ static int logged_in;
 
 /* Set if we have run the /etc/ppp/auth-up script. */
 static int did_authup;
+static pid_t authup_pid;       /* process ID of auth-up/down script */
 
 /* List of addresses which the peer may use. */
 static struct wordlist *addresses[NUM_PPP];
@@ -117,6 +118,17 @@ static int num_np_up;
 /* Set if we got the contents of passwd[] from the pap-secrets file. */
 static int passwd_from_file;
 
+/*
+ * Option variables.
+ */
+bool uselogin = 0;             /* Use /etc/passwd for checking PAP */
+bool cryptpap = 0;             /* Passwords in pap-secrets are encrypted */
+bool refuse_pap = 0;           /* Don't wanna auth. ourselves with PAP */
+bool refuse_chap = 0;          /* Don't wanna auth. ourselves with CHAP */
+bool usehostname = 0;          /* Use hostname for our_name */
+bool auth_required = 0;                /* Always require authentication from peer */
+bool allow_any_ip = 0;         /* Allow peer to use any IP address */
+
 /* Bits in auth_pending[] */
 #define PAP_WITHPEER   1
 #define PAP_PEER       2
@@ -143,6 +155,99 @@ static void free_wordlist __P((struct wordlist *));
 static void auth_script __P((char *));
 static void set_allowed_addrs __P((int, struct wordlist *));
 
+#ifdef OLD_OPTIONS
+static int setupapfile __P((char **));
+#endif
+
+/*
+ * Authentication-related options.
+ */
+option_t auth_options[] = {
+    { "require-pap", o_bool, &lcp_wantoptions[0].neg_upap,
+      "Require PAP authentication from peer", 1, &auth_required },
+    { "+pap", o_bool, &lcp_wantoptions[0].neg_upap,
+      "Require PAP authentication from peer", 1, &auth_required },
+    { "refuse-pap", o_bool, &refuse_pap,
+      "Don't agree to auth to peer with PAP", 1 },
+    { "-pap", o_bool, &refuse_pap,
+      "Don't allow UPAP authentication with peer", 1 },
+    { "require-chap", o_bool, &lcp_wantoptions[0].neg_chap,
+      "Require CHAP authentication from peer", 1, &auth_required },
+    { "+chap", o_bool, &lcp_wantoptions[0].neg_chap,
+      "Require CHAP authentication from peer", 1, &auth_required },
+    { "refuse-chap", o_bool, &refuse_chap,
+      "Don't agree to auth to peer with CHAP", 1 },
+    { "-chap", o_bool, &refuse_chap,
+      "Don't allow CHAP authentication with peer", 1 },
+    { "name", o_string, our_name,
+      "Set local name for authentication",
+      OPT_PRIV|OPT_STATIC, NULL, MAXNAMELEN },
+    { "user", o_string, user,
+      "Set name for auth with peer", OPT_STATIC, NULL, MAXNAMELEN },
+    { "usehostname", o_bool, &usehostname,
+      "Must use hostname for authentication", 1 },
+    { "remotename", o_string, remote_name,
+      "Set remote name for authentication", OPT_STATIC, NULL, MAXNAMELEN },
+    { "auth", o_bool, &auth_required,
+      "Require authentication from peer", 1 },
+    { "noauth", o_bool, &auth_required,
+      "Don't require peer to authenticate", OPT_PRIV, &allow_any_ip },
+    {  "login", o_bool, &uselogin,
+      "Use system password database for PAP", 1 },
+    { "papcrypt", o_bool, &cryptpap,
+      "PAP passwords are encrypted", 1 },
+#if OLD_OPTIONS
+    { "+ua", o_special, setupapfile,
+      "Get PAP user and password from file" },
+#endif
+    { NULL }
+};
+
+#if OLD_OPTIONS
+/*
+ * setupapfile - specifies UPAP info for authenticating with peer.
+ */
+static int
+setupapfile(argv)
+    char **argv;
+{
+    FILE * ufile;
+    int l;
+
+    lcp_allowoptions[0].neg_upap = 1;
+
+    /* open user info file */
+    if ((ufile = fopen(*argv, "r")) == NULL) {
+       option_error("unable to open user login data file %s", *argv);
+       return 0;
+    }
+    if (!readable(fileno(ufile))) {
+       option_error("%s: access denied", *argv);
+       return 0;
+    }
+    check_access(ufile, *argv);
+
+    /* get username */
+    if (fgets(user, MAXNAMELEN - 1, ufile) == NULL
+       || fgets(passwd, MAXSECRETLEN - 1, ufile) == NULL){
+       option_error("unable to read user login data file %s", *argv);
+       return 0;
+    }
+    fclose(ufile);
+
+    /* get rid of newlines */
+    l = strlen(user);
+    if (l > 0 && user[l-1] == '\n')
+       user[l-1] = 0;
+    l = strlen(passwd);
+    if (l > 0 && passwd[l-1] == '\n')
+       passwd[l-1] = 0;
+
+    return (1);
+}
+#endif
+
+
 /*
  * An Open on LCP has requested a change from Dead to Establish phase.
  * Do what's necessary to bring the physical layer up.
@@ -437,7 +542,7 @@ np_up(unit, proto)
        /*
         * Detach now, if the updetach option was given.
         */
-       if (nodetach == -1)
+       if (updetach && !nodetach)
            detach();
     }
     ++num_np_up;
@@ -520,9 +625,14 @@ auth_check_options()
        strcpy(user, our_name);
 
     /* If authentication is required, ask peer for CHAP or PAP. */
-    if (auth_required && !wo->neg_chap && !wo->neg_upap) {
-       wo->neg_chap = 1;
-       wo->neg_upap = 1;
+    if (auth_required) {
+       if (!wo->neg_chap && !wo->neg_upap) {
+           wo->neg_chap = 1;
+           wo->neg_upap = 1;
+       }
+    } else {
+       wo->neg_chap = 0;
+       wo->neg_upap = 0;
     }
 
     /*
@@ -549,7 +659,7 @@ auth_check_options()
      * Check whether the user tried to override certain values
      * set by root.
      */
-    if (!auth_required && auth_req_info.priv > 0) {
+    if (allow_any_ip) {
        if (!default_device && devnam_info.priv == 0) {
            option_error("can't override device name when noauth option used");
            exit(1);
@@ -557,8 +667,8 @@ auth_check_options()
        if ((connector != NULL && connector_info.priv == 0)
            || (disconnector != NULL && disconnector_info.priv == 0)
            || (welcomer != NULL && welcomer_info.priv == 0)) {
-           option_error("can't override connect, disconnect or welcome");
-           option_error("option values when noauth option used");
+           option_error("connect, disconnect and welcome options");
+           option_error("are privileged when noauth option is used");
            exit(1);
        }
     }
@@ -1196,8 +1306,11 @@ ip_addr_check(addr, addrs)
     if (bad_ip_adrs(addr))
        return 0;
 
-    if (addrs == NULL)
-       return !auth_required;          /* no addresses authorized */
+    if (addrs == NULL) {
+       if (auth_required)
+           return 0;           /* no addresses authorized */
+       return allow_any_ip || !have_route_to(addr);
+    }
 
     for (; addrs != NULL; addrs = addrs->next) {
        /* "-" means no addresses authorized, "*" means any address allowed */
@@ -1498,5 +1611,5 @@ auth_script(script)
     argv[5] = strspeed;
     argv[6] = NULL;
 
-    run_program(script, argv, 0);
+    authup_pid = run_program(script, argv, 0, NULL, NULL);
 }
index c9ef0899ae9fb500fbfe692f0f1198cce44e1e91..9d56850606edb614138bb8089586779d17e67314 100644 (file)
@@ -19,7 +19,7 @@
  */
 
 #ifndef lint
-static char rcsid[] = "$Id: cbcp.c,v 1.2 1997/04/30 05:50:26 paulus Exp $";
+static char rcsid[] = "$Id: cbcp.c,v 1.3 1998/11/07 06:59:25 paulus Exp $";
 #endif
 
 #include <stdio.h>
@@ -34,6 +34,17 @@ static char rcsid[] = "$Id: cbcp.c,v 1.2 1997/04/30 05:50:26 paulus Exp $";
 #include "lcp.h"
 #include "ipcp.h"
 
+/*
+ * Options.
+ */
+static int setcbcp __P((char **));
+
+static option_t cbcp_option_list[] = {
+    { "callback", o_special, setcbcp,
+      "Ask for callback" },
+    { NULL }
+};
+
 /*
  * Protocol entry points.
  */
@@ -59,6 +70,8 @@ struct protent cbcp_protent = {
     NULL,
     0,
     "CBCP",
+    cbcp_option_list,
+    NULL,
     NULL,
     NULL,
     NULL
@@ -74,6 +87,21 @@ static void cbcp_up __P((cbcp_state *us));
 static void cbcp_recvack __P((cbcp_state *us, char *pckt, int len));
 static void cbcp_send __P((cbcp_state *us, u_char code, u_char *buf, int len));
 
+/* option processing */
+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);
+}
+
 /* init state */
 static void
 cbcp_init(iface)
index 6d328b762d3c985df5d8523cc3ee87dd00a47d07..0f0f4447b8e8600b1f1a85331c89d536f14ab209 100644 (file)
  */
 
 #ifndef lint
-static char rcsid[] = "$Id: ccp.c,v 1.22 1998/03/25 01:25:02 paulus Exp $";
+static char rcsid[] = "$Id: ccp.c,v 1.23 1998/11/07 06:59:26 paulus Exp $";
 #endif
 
+#include <stdlib.h>
 #include <string.h>
 #include <syslog.h>
 #include <sys/ioctl.h>
@@ -39,6 +40,48 @@ static char rcsid[] = "$Id: ccp.c,v 1.22 1998/03/25 01:25:02 paulus Exp $";
 #include "ccp.h"
 #include <net/ppp-comp.h>
 
+/*
+ * Command-line options.
+ */
+static int setbsdcomp __P((char **));
+static int setdeflate __P((char **));
+
+static option_t ccp_option_list[] = {
+    { "noccp", o_bool, &ccp_protent.enabled_flag,
+      "Disable CCP negotiation" },
+    { "-ccp", o_bool, &ccp_protent.enabled_flag,
+      "Disable CCP negotiation" },
+    { "bsdcomp", o_special, setbsdcomp,
+      "Request BSD-Compress packet compression" },
+    { "nobsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress,
+      "don't allow BSD-Compress", OPT_A2COPY,
+      &ccp_allowoptions[0].bsd_compress },
+    { "-bsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress,
+      "don't allow BSD-Compress", OPT_A2COPY,
+      &ccp_allowoptions[0].bsd_compress },
+    { "deflate", 1, setdeflate,
+      "request Deflate compression" },
+    { "nodeflate", o_bool, &ccp_wantoptions[0].deflate,
+      "don't allow Deflate compression", OPT_A2COPY,
+      &ccp_allowoptions[0].deflate },
+    { "-deflate", o_bool, &ccp_wantoptions[0].deflate,
+      "don't allow Deflate compression", OPT_A2COPY,
+      &ccp_allowoptions[0].deflate },
+    { "nodeflatedraft", o_bool, &ccp_wantoptions[0].deflate_draft,
+      "don't use draft deflate #", OPT_A2COPY,
+      &ccp_allowoptions[0].deflate_draft },
+    { "predictor1", o_bool, &ccp_wantoptions[0].predictor_1,
+      "request Predictor-1", 1, &ccp_allowoptions[0].predictor_1 },
+    { "nopredictor1", o_bool, &ccp_wantoptions[0].predictor_1,
+      "don't allow Predictor-1", OPT_A2COPY,
+      &ccp_allowoptions[0].predictor_1 },
+    { "-predictor1", o_bool, &ccp_wantoptions[0].predictor_1,
+      "don't allow Predictor-1", OPT_A2COPY,
+      &ccp_allowoptions[0].predictor_1 },
+
+    { NULL }
+};
+
 /*
  * Protocol entry points from main code.
  */
@@ -67,6 +110,7 @@ struct protent ccp_protent = {
     ccp_datainput,
     1,
     "CCP",
+    ccp_option_list,
     NULL,
     NULL,
     NULL
@@ -129,6 +173,83 @@ static int ccp_localstate[NUM_PPP];
 
 static int all_rejected[NUM_PPP];      /* we rejected all peer's options */
 
+/*
+ * Option parsing.
+ */
+static int
+setbsdcomp(argv)
+    char **argv;
+{
+    int rbits, abits;
+    char *str, *endp;
+
+    str = *argv;
+    abits = rbits = strtol(str, &endp, 0);
+    if (endp != str && *endp == ',') {
+       str = endp + 1;
+       abits = strtol(str, &endp, 0);
+    }
+    if (*endp != 0 || endp == str) {
+       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))) {
+       option_error("bsdcomp option values must be 0 or %d .. %d",
+                    BSD_MIN_BITS, BSD_MAX_BITS);
+       return 0;
+    }
+    if (rbits > 0) {
+       ccp_wantoptions[0].bsd_compress = 1;
+       ccp_wantoptions[0].bsd_bits = rbits;
+    } else
+       ccp_wantoptions[0].bsd_compress = 0;
+    if (abits > 0) {
+       ccp_allowoptions[0].bsd_compress = 1;
+       ccp_allowoptions[0].bsd_bits = abits;
+    } else
+       ccp_allowoptions[0].bsd_compress = 0;
+    return 1;
+}
+
+static int
+setdeflate(argv)
+    char **argv;
+{
+    int rbits, abits;
+    char *str, *endp;
+
+    str = *argv;
+    abits = rbits = strtol(str, &endp, 0);
+    if (endp != str && *endp == ',') {
+       str = endp + 1;
+       abits = strtol(str, &endp, 0);
+    }
+    if (*endp != 0 || endp == str) {
+       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))) {
+       option_error("deflate option values must be 0 or %d .. %d",
+                    DEFLATE_MIN_SIZE, DEFLATE_MAX_SIZE);
+       return 0;
+    }
+    if (rbits > 0) {
+       ccp_wantoptions[0].deflate = 1;
+       ccp_wantoptions[0].deflate_size = rbits;
+    } else
+       ccp_wantoptions[0].deflate = 0;
+    if (abits > 0) {
+       ccp_allowoptions[0].deflate = 1;
+       ccp_allowoptions[0].deflate_size = abits;
+    } else
+       ccp_allowoptions[0].deflate = 0;
+    return 1;
+}
+
+
 /*
  * ccp_init - initialize CCP.
  */
index 2fcba915758b9282ef22c17ff5ed7fea0eaf3f8d..c28a5b885a65c629e4249a477883e64e7b701675 100644 (file)
  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
  * OR MODIFICATIONS.
  *
- * $Id: ccp.h,v 1.8 1998/03/25 01:25:03 paulus Exp $
+ * $Id: ccp.h,v 1.9 1998/11/07 06:59:26 paulus Exp $
  */
 
 typedef struct ccp_options {
-    u_int bsd_compress: 1;     /* do BSD Compress? */
-    u_int deflate: 1;          /* do Deflate? */
-    u_int predictor_1: 1;      /* do Predictor-1? */
-    u_int predictor_2: 1;      /* do Predictor-2? */
-    u_int deflate_correct: 1;  /* use correct code for deflate? */
-    u_int deflate_draft: 1;    /* use draft RFC code for deflate? */
+    bool bsd_compress;         /* do BSD Compress? */
+    bool deflate;              /* do Deflate? */
+    bool predictor_1;          /* do Predictor-1? */
+    bool predictor_2;          /* do Predictor-2? */
+    bool deflate_correct;      /* use correct code for deflate? */
+    bool deflate_draft;                /* use draft RFC code for deflate? */
     u_short bsd_bits;          /* # bits/code for BSD Compress */
     u_short deflate_size;      /* lg(window size) for Deflate */
     short method;              /* code for chosen compression method */
index 189eb20ecc2de6ebbf5a22359c39fd3365e037fe..06c17e8bfdf71daeb31fef91e1f3bdc39a618cfa 100644 (file)
@@ -34,7 +34,7 @@
  */
 
 #ifndef lint
-static char rcsid[] = "$Id: chap.c,v 1.15 1997/11/27 06:07:48 paulus Exp $";
+static char rcsid[] = "$Id: chap.c,v 1.16 1998/11/07 06:59:26 paulus Exp $";
 #endif
 
 /*
@@ -54,6 +54,23 @@ static char rcsid[] = "$Id: chap.c,v 1.15 1997/11/27 06:07:48 paulus Exp $";
 #include "chap_ms.h"
 #endif
 
+/*
+ * Command-line options.
+ */
+static option_t chap_option_list[] = {
+    { "chap-restart", o_int, &chap[0].timeouttime,
+      "Set timeout for CHAP" },
+    { "chap-max-challenge", o_int, &chap[0].max_transmits,
+      "Set max #xmits for challenge" },
+    { "chap-interval", o_int, &chap[0].chal_interval,
+      "Set interval for rechallenge" },
+#ifdef MSLANMAN
+    { "ms-lanman", o_bool, &ms_lanman,
+      "Use LanMan psswd when using MS-CHAP", 1 },
+#endif
+    { NULL }
+};
+
 /*
  * Protocol entry points.
  */
@@ -78,6 +95,7 @@ struct protent chap_protent = {
     NULL,
     1,
     "CHAP",
+    chap_option_list,
     NULL,
     NULL,
     NULL
index 763693753e3a1d00a358088c7f86779e082534f4..f58bafc15ff5117fc36bc6f58ceac0dd901c4fd3 100644 (file)
@@ -32,7 +32,7 @@
  */
 
 #ifndef lint
-static char rcsid[] = "$Id: chap_ms.c,v 1.9 1998/09/04 18:48:12 christos Exp $";
+static char rcsid[] = "$Id: chap_ms.c,v 1.10 1998/11/07 06:59:26 paulus Exp $";
 #endif
 
 #ifdef CHAPMS
@@ -81,6 +81,11 @@ static void  Expand __P((u_char *, u_char *));
 static void    Collapse __P((u_char *, u_char *));
 #endif
 
+#ifdef MSLANMAN
+bool   ms_lanman = 0;          /* Use LanMan password instead of NT */
+                               /* Has meaning only with MS-CHAP challenges */
+#endif
+
 static void
 ChallengeResponse(challenge, pwHash, response)
     u_char *challenge; /* IN   8 octets */
@@ -308,9 +313,6 @@ ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len)
     int secret_len;
 {
     MS_ChapResponse    response;
-#ifdef MSLANMAN
-    extern int ms_lanman;
-#endif
 
 #if 0
     CHAPDEBUG((LOG_INFO, "ChapMS: secret is '%.*s'", secret_len, secret));
index 6250c7e6921bd9813b1da35d6a51bbb12c991343..0d1c128b89754d3daf3fb2ac67d8bd88f2011f50 100644 (file)
@@ -18,7 +18,7 @@
  */
 
 #ifndef lint
-static char rcsid[] = "$Id: ipcp.c,v 1.34 1998/04/28 23:38:09 paulus Exp $";
+static char rcsid[] = "$Id: ipcp.c,v 1.35 1998/11/07 06:59:26 paulus Exp $";
 #endif
 
 /*
@@ -33,6 +33,7 @@ static char rcsid[] = "$Id: ipcp.c,v 1.34 1998/04/28 23:38:09 paulus Exp $";
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
+#include <arpa/inet.h>
 
 #include "pppd.h"
 #include "fsm.h"
@@ -45,6 +46,8 @@ ipcp_options ipcp_gotoptions[NUM_PPP];        /* Options that peer ack'd */
 ipcp_options ipcp_allowoptions[NUM_PPP];       /* Options we allow peer to request */
 ipcp_options ipcp_hisoptions[NUM_PPP]; /* Options that we ack'd */
 
+bool   disable_defaultip = 0;  /* Don't use hostname for default IP adrs */
+
 /* local vars */
 static int cis_received[NUM_PPP];      /* # Conf-Reqs received */
 static int default_route_set[NUM_PPP]; /* Have set up a default route */
@@ -62,7 +65,6 @@ static int  ipcp_rejci __P((fsm *, u_char *, int));   /* Peer rej'd our CI */
 static int  ipcp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv CI */
 static void ipcp_up __P((fsm *));              /* We're UP */
 static void ipcp_down __P((fsm *));            /* We're DOWN */
-static void ipcp_script __P((fsm *, char *)); /* Run an up/down script */
 static void ipcp_finished __P((fsm *));        /* Don't need lower layer */
 
 fsm ipcp_fsm[NUM_PPP];         /* IPCP fsm structure */
@@ -85,6 +87,69 @@ static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */
     "IPCP"                     /* String name of protocol */
 };
 
+/*
+ * Command-line options.
+ */
+static int setvjslots __P((char **));
+static int setdnsaddr __P((char **));
+static int setwinsaddr __P((char **));
+
+static option_t ipcp_option_list[] = {
+    { "noip", o_bool, &ipcp_protent.enabled_flag,
+      "Disable IP and IPCP" },
+    { "-ip", o_bool, &ipcp_protent.enabled_flag,
+      "Disable IP and IPCP" },
+    { "novj", o_bool, &ipcp_wantoptions[0].neg_vj,
+      "Disable VJ compression", OPT_A2COPY, &ipcp_allowoptions[0].neg_vj },
+    { "-vj", o_bool, &ipcp_wantoptions[0].neg_vj,
+      "Disable VJ compression", OPT_A2COPY, &ipcp_allowoptions[0].neg_vj },
+    { "novjccomp", o_bool, &ipcp_wantoptions[0].cflag,
+      "Disable VJ connection-ID compression", OPT_A2COPY,
+      &ipcp_allowoptions[0].cflag },
+    { "-vjccomp", o_bool, &ipcp_wantoptions[0].cflag,
+      "Disable VJ connection-ID compression", OPT_A2COPY,
+      &ipcp_allowoptions[0].cflag },
+    { "vj-max-slots", 1, setvjslots,
+      "Set maximum VJ header slots" },
+    { "ipcp-accept-local", o_bool, &ipcp_wantoptions[0].accept_local,
+      "Accept peer's address for us", 1 },
+    { "ipcp-accept-remote", o_bool, &ipcp_wantoptions[0].accept_remote,
+      "Accept peer's address for it", 1 },
+    { "ipparam", o_string, &ipparam,
+      "Set ip script parameter" },
+    { "noipdefault", o_bool, &disable_defaultip,
+      "Don't use name for default IP adrs", 1 },
+    { "ms-dns", 1, setdnsaddr,
+      "DNS address for the peer's use" },
+    { "ms-wins", 1, setwinsaddr,
+      "Nameserver for SMB over TCP/IP for peer" },
+    { "ipcp-restart", o_int, &ipcp_fsm[0].timeouttime,
+      "Set timeout for IPCP" },
+    { "ipcp-max-terminate", o_int, &ipcp_fsm[0].maxtermtransmits,
+      "Set max #xmits for term-reqs" },
+    { "ipcp-max-configure", o_int, &ipcp_fsm[0].maxconfreqtransmits,
+      "Set max #xmits for conf-reqs" },
+    { "ipcp-max-failure", o_int, &ipcp_fsm[0].maxnakloops,
+      "Set max #conf-naks for IPCP" },
+    { "defaultroute", o_bool, &ipcp_wantoptions[0].default_route,
+      "Add default route", OPT_ENABLE|1, &ipcp_allowoptions[0].default_route },
+    { "nodefaultroute", o_bool, &ipcp_allowoptions[0].default_route,
+      "disable defaultroute option", OPT_A2COPY,
+      &ipcp_wantoptions[0].default_route },
+    { "-defaultroute", o_bool, &ipcp_allowoptions[0].default_route,
+      "disable defaultroute option", OPT_A2COPY,
+      &ipcp_wantoptions[0].default_route },
+    { "proxyarp", o_bool, &ipcp_wantoptions[0].proxy_arp,
+      "Add proxy ARP entry", OPT_ENABLE|1, &ipcp_allowoptions[0].proxy_arp },
+    { "noproxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp,
+      "disable proxyarp option", OPT_A2COPY,
+      &ipcp_wantoptions[0].proxy_arp },
+    { "-proxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp,
+      "disable proxyarp option", OPT_A2COPY,
+      &ipcp_wantoptions[0].proxy_arp },
+    { NULL }
+};
+
 /*
  * Protocol entry points from main code.
  */
@@ -114,12 +179,15 @@ struct protent ipcp_protent = {
     NULL,
     1,
     "IPCP",
+    ipcp_option_list,
     ip_check_options,
     ip_demand_conf,
     ip_active_pkt
 };
 
 static void ipcp_clear_addrs __P((int));
+static void ipcp_script __P((char *));         /* Run an up/down script */
+static void ipcp_script_done __P((void *));
 
 /*
  * Lengths of configuration options.
@@ -134,6 +202,15 @@ static void ipcp_clear_addrs __P((int));
 #define CODENAME(x)    ((x) == CONFACK ? "ACK" : \
                         (x) == CONFNAK ? "NAK" : "REJ")
 
+/*
+ * This state variable is used to ensure that we don't
+ * run an ipcp-up/down script while one is already running.
+ */
+static enum script_state {
+    s_down,
+    s_up,
+} ipcp_script_state;
+static pid_t ipcp_script_pid;
 
 /*
  * Make a string representation of a network IP address.
@@ -154,6 +231,92 @@ u_int32_t ipaddr;
     return b;
 }
 
+/*
+ * Option parsing.
+ */
+
+/*
+ * setvjslots - set maximum number of connection slots for VJ compression
+ */
+static int
+setvjslots(argv)
+    char **argv;
+{
+    int value;
+
+    if (!int_option(*argv, &value))
+       return 0;
+    if (value < 2 || value > 16) {
+       option_error("vj-max-slots value must be between 2 and 16");
+       return 0;
+    }
+    ipcp_wantoptions [0].maxslotindex =
+        ipcp_allowoptions[0].maxslotindex = value - 1;
+    return 1;
+}
+
+/*
+ * 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);
+}
+
 
 /*
  * ipcp_init - Initialize IPCP.
@@ -1180,12 +1343,20 @@ ipcp_up(f)
      */
     if (demand) {
        if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) {
-           if (go->ouraddr != wo->ouraddr)
+           if (go->ouraddr != wo->ouraddr) {
                syslog(LOG_WARNING, "Local IP address changed to %s",
                       ip_ntoa(go->ouraddr));
-           if (ho->hisaddr != wo->hisaddr)
+               script_setenv("OLDIPLOCAL", ip_ntoa(wo->ouraddr));
+               wo->ouraddr = go->ouraddr;
+           } else
+               script_unsetenv("OLDIPLOCAL");
+           if (ho->hisaddr != wo->hisaddr) {
                syslog(LOG_WARNING, "Remote IP address changed to %s",
                       ip_ntoa(ho->hisaddr));
+               script_setenv("OLDIPREMOTE", ip_ntoa(wo->hisaddr));
+               wo->hisaddr = ho->hisaddr;
+           } else
+               script_unsetenv("OLDIPREMOTE");
            ipcp_clear_addrs(f->unit);
 
            /* Set the interface to the new addresses */
@@ -1258,8 +1429,10 @@ ipcp_up(f)
      * Execute the ip-up script, like this:
      * /etc/ppp/ip-up interface tty speed local-IP remote-IP
      */
-    ipcp_script(f, _PATH_IPUP);
-
+    if (ipcp_script_state == s_down && ipcp_script_pid == 0) {
+       ipcp_script_state = s_up;
+       ipcp_script(_PATH_IPUP);
+    }
 }
 
 
@@ -1289,7 +1462,10 @@ ipcp_down(f)
     }
 
     /* Execute the ip-down script */
-    ipcp_script(f, _PATH_IPDOWN);
+    if (ipcp_script_state == s_up && ipcp_script_pid == 0) {
+       ipcp_script_state = s_down;
+       ipcp_script(_PATH_IPDOWN);
+    }
 }
 
 
@@ -1328,21 +1504,45 @@ ipcp_finished(f)
 }
 
 
+/*
+ * ipcp_script_done - called when the ip-up or ip-down script
+ * has finished.
+ */
+static void
+ipcp_script_done(void *arg)
+{
+    ipcp_script_pid = 0;
+    switch (ipcp_script_state) {
+    case s_up:
+       if (ipcp_fsm[0].state != OPENED) {
+           ipcp_script_state = s_down;
+           ipcp_script(_PATH_IPDOWN);
+       }
+       break;
+    case s_down:
+       if (ipcp_fsm[0].state == OPENED) {
+           ipcp_script_state = s_up;
+           ipcp_script(_PATH_IPUP);
+       }
+       break;
+    }
+}
+
+
 /*
  * ipcp_script - Execute a script with arguments
  * interface-name tty-name speed local-IP remote-IP.
  */
 static void
-ipcp_script(f, script)
-    fsm *f;
+ipcp_script(script)
     char *script;
 {
     char strspeed[32], strlocal[32], strremote[32];
     char *argv[8];
 
     sprintf(strspeed, "%d", baud_rate);
-    strcpy(strlocal, ip_ntoa(ipcp_gotoptions[f->unit].ouraddr));
-    strcpy(strremote, ip_ntoa(ipcp_hisoptions[f->unit].hisaddr));
+    strcpy(strlocal, ip_ntoa(ipcp_gotoptions[0].ouraddr));
+    strcpy(strremote, ip_ntoa(ipcp_hisoptions[0].hisaddr));
 
     argv[0] = script;
     argv[1] = ifname;
@@ -1352,7 +1552,7 @@ ipcp_script(f, script)
     argv[5] = strremote;
     argv[6] = ipparam;
     argv[7] = NULL;
-    run_program(script, argv, 0);
+    ipcp_script_pid = run_program(script, argv, 0, ipcp_script_done, NULL);
 }
 
 /*
index 01eb422a8a827004f5e3474f14a3a4a29311a911..0924321da48944d89ace4d3dca708ed419dc7f53 100644 (file)
@@ -16,7 +16,7 @@
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- * $Id: ipcp.h,v 1.11 1998/04/28 23:38:11 paulus Exp $
+ * $Id: ipcp.h,v 1.12 1998/11/07 06:59:27 paulus Exp $
  */
 
 /*
                                /* compression option*/ 
 
 typedef struct ipcp_options {
-    int neg_addr : 1;          /* Negotiate IP Address? */
-    int old_addrs : 1;         /* Use old (IP-Addresses) option? */
-    int req_addr : 1;          /* Ask peer to send IP address? */
-    int default_route : 1;     /* Assign default route through interface? */
-    int proxy_arp : 1;         /* Make proxy ARP entry for peer? */
-    int neg_vj : 1;            /* Van Jacobson Compression? */
-    int old_vj : 1;            /* use old (short) form of VJ option? */
-    int accept_local : 1;      /* accept peer's value for ouraddr */
-    int accept_remote : 1;     /* accept peer's value for hisaddr */
-    u_short vj_protocol;       /* protocol value to use in VJ option */
-    u_char maxslotindex, cflag;        /* values for RFC1332 VJ compression neg. */
+    bool neg_addr;             /* Negotiate IP Address? */
+    bool old_addrs;            /* Use old (IP-Addresses) option? */
+    bool req_addr;             /* Ask peer to send IP address? */
+    bool default_route;                /* Assign default route through interface? */
+    bool proxy_arp;            /* Make proxy ARP entry for peer? */
+    bool neg_vj;               /* Van Jacobson Compression? */
+    bool old_vj;               /* use old (short) form of VJ option? */
+    bool accept_local;         /* accept peer's value for ouraddr */
+    bool accept_remote;                /* accept peer's value for hisaddr */
+    int  vj_protocol;          /* protocol value to use in VJ option */
+    int  maxslotindex;         /* values for RFC1332 VJ compression neg. */
+    bool cflag;
     u_int32_t ouraddr, hisaddr;        /* Addresses in NETWORK BYTE ORDER */
     u_int32_t dnsaddr[2];      /* Primary and secondary MS DNS entries */
     u_int32_t winsaddr[2];     /* Primary and secondary MS WINS entries */
index dc64551d873a9044b3ec07b01175d51b39c2cfe9..34ce4c99f9e9b187a7c3b78fd9f016afd4747862 100644 (file)
@@ -19,7 +19,7 @@
 
 #ifdef IPX_CHANGE
 #ifndef lint
-static char rcsid[] = "$Id: ipxcp.c,v 1.7 1998/05/13 05:49:18 paulus Exp $";
+static char rcsid[] = "$Id: ipxcp.c,v 1.8 1998/11/07 06:59:27 paulus Exp $";
 #endif
 
 /*
@@ -30,6 +30,7 @@ static char rcsid[] = "$Id: ipxcp.c,v 1.7 1998/05/13 05:49:18 paulus Exp $";
 #include <string.h>
 #include <syslog.h>
 #include <unistd.h>
+#include <ctype.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -85,6 +86,50 @@ static fsm_callbacks ipxcp_callbacks = { /* IPXCP callback routines */
     "IPXCP"                    /* String name of protocol */
 };
 
+/*
+ * Command-line options.
+ */
+static int setipxnode __P((char **));
+static int setipxname __P((char **));
+
+static option_t ipxcp_option_list[] = {
+    { "ipx", o_bool, &ipxcp_protent.enabled_flag,
+      "Enable IPXCP (and IPX)", 1 },
+    { "+ipx", o_bool, &ipxcp_protent.enabled_flag,
+      "Enable IPXCP (and IPX)", 1 },
+    { "noipx", o_bool, &ipxcp_protent.enabled_flag,
+      "Disable IPXCP (and IPX)" },
+    { "-ipx", o_bool, &ipxcp_protent.enabled_flag,
+      "Disable IPXCP (and IPX)" } ,
+    { "ipx-network", o_int, &ipxcp_wantoptions[0].our_network,
+      "Set our IPX network number", 0, &ipxcp_wantoptions[0].neg_nn },
+    { "ipxcp-accept-network", o_bool, &ipxcp_wantoptions[0].accept_network,
+      "Accept peer IPX network number", 1,
+      &ipxcp_allowoptions[0].accept_network },
+    { "ipx-node", o_special, setipxnode,
+      "Set IPX node number" },
+    { "ipxcp-accept-local", o_bool, &ipxcp_wantoptions[0].accept_local,
+      "Accept our IPX address", 1,
+      &ipxcp_allowoptions[0].accept_local },
+    { "ipxcp-accept-remote", o_bool, &ipxcp_wantoptions[0].accept_remote,
+      "Accept peer's IPX address", 1,
+      &ipxcp_allowoptions[0].accept_remote },
+    { "ipx-routing", o_int, &ipxcp_wantoptions[0].router,
+      "Set IPX routing proto number", 0,
+      &ipxcp_wantoptions[0].neg_router },
+    { "ipx-router-name", o_special, setipxname,
+      "Set IPX router name" },
+    { "ipxcp-restart", o_int, &ipxcp_fsm[0].timeouttime,
+      "Set timeout for IPXCP" },
+    { "ipxcp-max-terminate", o_int, &ipxcp_fsm[0].maxtermtransmits,
+      "Set max #xmits for IPXCP term-reqs" },
+    { "ipxcp-max-configure", o_int, &ipxcp_fsm[0].maxconfreqtransmits,
+      "Set max #xmits for IPXCP conf-reqs" },
+    { "ipxcp-max-failure", o_int, &ipxcp_fsm[0].maxnakloops,
+      "Set max #conf-naks for IPXCP" },
+    { NULL }
+};
+
 /*
  * Protocol entry points.
  */
@@ -112,6 +157,7 @@ struct protent ipxcp_protent = {
     NULL,
     0,
     "IPXCP",
+    ipxcp_option_list,
     NULL,
     NULL,
     NULL
@@ -170,6 +216,87 @@ u_int32_t ipxaddr;
 }
 
 
+static u_char *
+setipxnodevalue(src,dst)
+u_char *src, *dst;
+{
+    int indx;
+    int item;
+
+    for (;;) {
+        if (!isxdigit (*src))
+           break;
+       
+       for (indx = 0; indx < 5; ++indx) {
+           dst[indx] <<= 4;
+           dst[indx] |= (dst[indx + 1] >> 4) & 0x0F;
+       }
+
+       item = toupper (*src) - '0';
+       if (item > 9)
+           item -= 7;
+
+       dst[5] = (dst[5] << 4) | item;
+       ++src;
+    }
+    return src;
+}
+
+static int
+setipxnode(argv)
+    char **argv;
+{
+    char *end;
+
+    memset (&ipxcp_wantoptions[0].our_node[0], 0, 6);
+    memset (&ipxcp_wantoptions[0].his_node[0], 0, 6);
+
+    end = setipxnodevalue (*argv, &ipxcp_wantoptions[0].our_node[0]);
+    if (*end == ':')
+       end = setipxnodevalue (++end, &ipxcp_wantoptions[0].his_node[0]);
+
+    if (*end == '\0') {
+        ipxcp_wantoptions[0].neg_node = 1;
+        return 1;
+    }
+
+    option_error("invalid parameter '%s' for ipx-node option", *argv);
+    return 0;
+}
+
+static int
+setipxname (argv)
+    char **argv;
+{
+    char *dest = ipxcp_wantoptions[0].name;
+    char *src  = *argv;
+    int  count;
+    char ch;
+
+    ipxcp_wantoptions[0].neg_name  = 1;
+    ipxcp_allowoptions[0].neg_name = 1;
+    memset (dest, '\0', sizeof (ipxcp_wantoptions[0].name));
+
+    count = 0;
+    while (*src) {
+        ch = *src++;
+       if (! isalnum (ch) && ch != '_') {
+           option_error("IPX router name must be alphanumeric or _");
+           return 0;
+       }
+
+       if (count >= sizeof (ipxcp_wantoptions[0].name)) {
+           option_error("IPX router name is limited to %d characters",
+                        sizeof (ipxcp_wantoptions[0].name) - 1);
+           return 0;
+       }
+
+       dest[count++] = toupper (ch);
+    }
+
+    return 1;
+}
+
 /*
  * ipxcp_init - Initialize IPXCP.
  */
@@ -1261,7 +1388,7 @@ ipxcp_script(f, script)
     argv[11] = ipparam;
     argv[12] = strpid;
     argv[13] = NULL;
-    run_program(script, argv, 0);
+    run_program(script, argv, 0, NULL, NULL);
 }
 
 /*
index 62385b0a499bb3498b396325b7b214f7d2066cac..52bd14adebaa5cfe00fdbd8258424a81764aa92c 100644 (file)
@@ -16,7 +16,7 @@
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- * $Id: ipxcp.h,v 1.3 1997/03/04 03:39:33 paulus Exp $
+ * $Id: ipxcp.h,v 1.4 1998/11/07 06:59:27 paulus Exp $
  */
 
 /*
 #define NLSP                     4
 
 typedef struct ipxcp_options {
-    int neg_node       : 1;    /* Negotiate IPX node number? */
-    int req_node       : 1;    /* Ask peer to send IPX node number? */
+    bool neg_node;             /* Negotiate IPX node number? */
+    bool req_node;             /* Ask peer to send IPX node number? */
 
-    int neg_nn         : 1;    /* Negotiate IPX network number? */
-    int req_nn         : 1;     /* Ask peer to send IPX network number */
+    bool neg_nn;               /* Negotiate IPX network number? */
+    bool req_nn;               /* Ask peer to send IPX network number */
 
-    int neg_name       : 1;    /* Negotiate IPX router name */
-    int neg_complete   : 1;     /* Negotiate completion */
-    int neg_router     : 1;    /* Negotiate IPX router number */
+    bool neg_name;             /* Negotiate IPX router name */
+    bool neg_complete;         /* Negotiate completion */
+    bool neg_router;           /* Negotiate IPX router number */
 
-    int accept_local   : 1;    /* accept peer's value for ournode */
-    int accept_remote  : 1;    /* accept peer's value for hisnode */
-    int accept_network : 1;    /* accept network number */
+    bool accept_local;         /* accept peer's value for ournode */
+    bool accept_remote;                /* accept peer's value for hisnode */
+    bool accept_network;       /* accept network number */
 
-    int tried_nlsp     : 1;     /* I have suggested NLSP already */
-    int tried_rip      : 1;     /* I have suggested RIP/SAP already */
+    bool tried_nlsp;           /* I have suggested NLSP already */
+    bool tried_rip;            /* I have suggested RIP/SAP already */
 
     u_int32_t his_network;     /* base network number */
     u_int32_t our_network;     /* our value for network number */
index fef4da6b05047dec2eec081d3aedd2d610f5167c..5f7cbfb3031a97676d4d3c26884bb8c40afc07b6 100644 (file)
@@ -18,7 +18,7 @@
  */
 
 #ifndef lint
-static char rcsid[] = "$Id: lcp.c,v 1.32 1998/05/13 05:49:19 paulus Exp $";
+static char rcsid[] = "$Id: lcp.c,v 1.33 1998/11/07 06:59:27 paulus Exp $";
 #endif
 
 /*
@@ -27,6 +27,7 @@ static char rcsid[] = "$Id: lcp.c,v 1.32 1998/05/13 05:49:19 paulus Exp $";
 
 #include <stdio.h>
 #include <string.h>
+#include <stdlib.h>
 #include <syslog.h>
 #include <assert.h>
 #include <sys/ioctl.h>
@@ -41,6 +42,78 @@ static char rcsid[] = "$Id: lcp.c,v 1.32 1998/05/13 05:49:19 paulus Exp $";
 #include "chap.h"
 #include "magic.h"
 
+/*
+ * LCP-related command-line options.
+ */
+int    lcp_echo_interval = 0;  /* Interval between LCP echo-requests */
+int    lcp_echo_fails = 0;     /* Tolerance to unanswered echo-requests */
+
+static int setescape __P((char **));
+
+static option_t lcp_option_list[] = {
+    /* LCP options */
+    { "noaccomp", o_bool, &lcp_wantoptions[0].neg_accompression,
+      "Disable address/control compression",
+      OPT_A2COPY, &lcp_allowoptions[0].neg_accompression },
+    { "-ac", o_bool, &lcp_wantoptions[0].neg_accompression,
+      "Disable address/control compression",
+      OPT_A2COPY, &lcp_allowoptions[0].neg_accompression },
+    { "default-asyncmap", o_bool, &lcp_wantoptions[0].neg_asyncmap,
+      "Disable asyncmap negotiation",
+      OPT_A2COPY, &lcp_allowoptions[0].neg_asyncmap },
+    { "-am", o_bool, &lcp_wantoptions[0].neg_asyncmap,
+      "Disable asyncmap negotiation",
+      OPT_A2COPY, &lcp_allowoptions[0].neg_asyncmap },
+    { "asyncmap", o_uint32, &lcp_wantoptions[0].asyncmap,
+      "Set asyncmap (for received packets)",
+      OPT_OR, &lcp_wantoptions[0].neg_asyncmap },
+    { "-as", o_uint32, &lcp_wantoptions[0].asyncmap,
+      "Set asyncmap (for received packets)",
+      OPT_OR, &lcp_wantoptions[0].neg_asyncmap },
+    { "nomagicnumber", o_bool, &lcp_wantoptions[0].neg_magicnumber,
+      "Disable magic number negotiation (looped-back line detection)",
+      OPT_A2COPY, &lcp_allowoptions[0].neg_magicnumber },
+    { "-mn", o_bool, &lcp_wantoptions[0].neg_magicnumber,
+      "Disable magic number negotiation (looped-back line detection)",
+      OPT_A2COPY, &lcp_allowoptions[0].neg_magicnumber },
+    { "default-mru", o_bool, &lcp_wantoptions[0].neg_mru,
+      "Disable MRU negotiation (use default 1500)",
+      OPT_A2COPY, &lcp_allowoptions[0].neg_mru },
+    { "-mru", o_bool, &lcp_wantoptions[0].neg_mru,
+      "Disable MRU negotiation (use default 1500)",
+      OPT_A2COPY, &lcp_allowoptions[0].neg_mru },
+    { "mru", o_int, &lcp_wantoptions[0].mru,
+      "Set MRU (maximum received packet size) for negotiation",
+      0, &lcp_wantoptions[0].neg_mru },
+    { "nopcomp", o_bool, &lcp_wantoptions[0].neg_pcompression,
+      "Disable protocol field compression",
+      OPT_A2COPY, &lcp_allowoptions[0].neg_pcompression },
+    { "-pc", o_bool, &lcp_wantoptions[0].neg_pcompression,
+      "Disable protocol field compression",
+      OPT_A2COPY, &lcp_allowoptions[0].neg_pcompression },
+    { "-p", o_bool, &lcp_wantoptions[0].passive,
+      "Set passive mode", 1 },
+    { "passive", o_bool, &lcp_wantoptions[0].passive,
+      "Set passive mode", 1 },
+    { "silent", o_bool, &lcp_wantoptions[0].silent,
+      "Set silent mode", 1 },
+    { "escape", o_special, setescape,
+      "List of character codes to escape on transmission" },
+    { "lcp-echo-failure", o_int, &lcp_echo_fails,
+      "Set number of consecutive echo failures to indicate link failure" },
+    { "lcp-echo-interval", o_int, &lcp_echo_interval,
+      "Set time in seconds between LCP echo requests" },
+    { "lcp-restart", o_int, &lcp_fsm[0].timeouttime,
+      "Set time in seconds between LCP retransmissions" },
+    { "lcp-max-terminate", o_int, &lcp_fsm[0].maxtermtransmits,
+      "Set maximum number of LCP terminate-request transmissions" },
+    { "lcp-max-configure", o_int, &lcp_fsm[0].maxconfreqtransmits,
+      "Set maximum number of LCP configure-request transmissions" },
+    { "lcp-max-failure", o_int, &lcp_fsm[0].maxnakloops,
+      "Set limit on number of LCP configure-naks" },
+    {NULL}
+};
+
 /* global vars */
 fsm lcp_fsm[NUM_PPP];                  /* LCP fsm structure (global)*/
 lcp_options lcp_wantoptions[NUM_PPP];  /* Options that we want to request */
@@ -126,6 +199,7 @@ struct protent lcp_protent = {
     NULL,
     1,
     "LCP",
+    lcp_option_list,
     NULL,
     NULL,
     NULL
@@ -148,6 +222,37 @@ int lcp_loopbackfail = DEFLOOPBACKFAIL;
                         (x) == CONFNAK ? "NAK" : "REJ")
 
 
+/*
+ * setescape - add chars to the set we escape on transmission.
+ */
+static int
+setescape(argv)
+    char **argv;
+{
+    int n, ret;
+    char *p, *endp;
+
+    p = *argv;
+    ret = 1;
+    while (*p) {
+       n = strtol(p, &endp, 16);
+       if (p == endp) {
+           option_error("escape parameter contains invalid hex number '%s'",
+                        p);
+           return 0;
+       }
+       p = endp;
+       if (n < 0 || (0x20 <= n && n <= 0x3F) || n == 0x5E || n > 0xFF) {
+           option_error("can't escape character 0x%x", n);
+           ret = 0;
+       } else
+           xmit_accm[0][n >> 5] |= 1 << (n & 0x1F);
+       while (*p == ',' || *p == ' ')
+           ++p;
+    }
+    return ret;
+}
+
 /*
  * lcp_init - Initialize LCP.
  */
index ddb5c6bdd4a6ac90a891949cbaa364c93cda888f..a7851f671c10f15374024f15942abcade0526acb 100644 (file)
@@ -16,7 +16,7 @@
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- * $Id: lcp.h,v 1.12 1996/10/08 04:35:02 paulus Exp $
+ * $Id: lcp.h,v 1.13 1998/11/07 06:59:27 paulus Exp $
  */
 
 /*
  * The state of options is described by an lcp_options structure.
  */
 typedef struct lcp_options {
-    int passive : 1;           /* Don't die if we don't get a response */
-    int silent : 1;            /* Wait for the other end to start first */
-    int restart : 1;           /* Restart vs. exit after close */
-    int neg_mru : 1;           /* Negotiate the MRU? */
-    int neg_asyncmap : 1;      /* Negotiate the async map? */
-    int neg_upap : 1;          /* Ask for UPAP authentication? */
-    int neg_chap : 1;          /* Ask for CHAP authentication? */
-    int neg_magicnumber : 1;   /* Ask for magic number? */
-    int neg_pcompression : 1;  /* HDLC Protocol Field Compression? */
-    int neg_accompression : 1; /* HDLC Address/Control Field Compression? */
-    int neg_lqr : 1;           /* Negotiate use of Link Quality Reports */
-    int neg_cbcp : 1;          /* Negotiate use of CBCP */
-    u_short mru;               /* Value of MRU */
+    bool passive;              /* Don't die if we don't get a response */
+    bool silent;               /* Wait for the other end to start first */
+    bool restart;              /* Restart vs. exit after close */
+    bool neg_mru;              /* Negotiate the MRU? */
+    bool neg_asyncmap;         /* Negotiate the async map? */
+    bool neg_upap;             /* Ask for UPAP authentication? */
+    bool neg_chap;             /* Ask for CHAP authentication? */
+    bool neg_magicnumber;      /* Ask for magic number? */
+    bool neg_pcompression;     /* HDLC Protocol Field Compression? */
+    bool neg_accompression;    /* HDLC Address/Control Field Compression? */
+    bool neg_lqr;              /* Negotiate use of Link Quality Reports */
+    bool neg_cbcp;             /* Negotiate use of CBCP */
+    int  mru;                  /* Value of MRU */
     u_char chap_mdtype;                /* which MD type (hashing algorithm) */
     u_int32_t asyncmap;                /* Value of async map */
     u_int32_t magicnumber;
index 7072d0a871fabcf9b615e3df1b179ff41ae2aa1d..dbeaeac0ce400338301c9e9cd968541be41fc00b 100644 (file)
@@ -18,7 +18,7 @@
  */
 
 #ifndef lint
-static char rcsid[] = "$Id: main.c,v 1.50 1998/09/13 23:38:49 paulus Exp $";
+static char rcsid[] = "$Id: main.c,v 1.51 1998/11/07 06:59:28 paulus Exp $";
 #endif
 
 #include <stdio.h>
@@ -33,6 +33,7 @@ static char rcsid[] = "$Id: main.c,v 1.50 1998/09/13 23:38:49 paulus Exp $";
 #include <netdb.h>
 #include <utmp.h>
 #include <pwd.h>
+#include <setjmp.h>
 #include <sys/param.h>
 #include <sys/types.h>
 #include <sys/wait.h>
@@ -91,6 +92,9 @@ int phase;                    /* where the link is at */
 int kill_link;
 int open_ccp_flag;
 
+static int waiting;
+static jmp_buf sigjmp;
+
 char **script_env;             /* Env. variable values for scripts */
 int s_env_nalloc;              /* # words avail at script_env */
 
@@ -192,7 +196,7 @@ main(argc, argv)
 
     if (gethostname(hostname, MAXNAMELEN) < 0 ) {
        option_error("Couldn't get hostname: %m");
-       die(1);
+       exit(1);
     }
     hostname[MAXNAMELEN-1] = 0;
 
@@ -225,7 +229,7 @@ main(argc, argv)
     if (geteuid() != 0) {
        option_error("must be root to run %s, since it is not setuid-root",
                     argv[0]);
-       die(1);
+       exit(1);
     }
 
     if (!ppp_available()) {
@@ -236,13 +240,14 @@ main(argc, argv)
     /*
      * Check that the options given are valid and consistent.
      */
-    sys_check_options();
+    if (!sys_check_options())
+       exit(1);
     auth_check_options();
     for (i = 0; (protp = protocols[i]) != NULL; ++i)
        if (protp->check_options != NULL)
            (*protp->check_options)();
     if (demand && connector == 0) {
-       option_error("connect script required for demand-dialling\n");
+       option_error("connect script is required for demand-dialling\n");
        exit(1);
     }
 
@@ -271,7 +276,7 @@ main(argc, argv)
      * Detach ourselves from the terminal, if required,
      * and identify who is running us.
      */
-    if (nodetach == 0)
+    if (!nodetach && !updetach)
        detach();
     pid = getpid();
     p = getlogin();
@@ -295,12 +300,13 @@ main(argc, argv)
     sigaddset(&mask, SIGINT);
     sigaddset(&mask, SIGTERM);
     sigaddset(&mask, SIGCHLD);
+    sigaddset(&mask, SIGUSR2);
 
 #define SIGNAL(s, handler)     { \
        sa.sa_handler = handler; \
        if (sigaction(s, &sa, NULL) < 0) { \
            syslog(LOG_ERR, "Couldn't establish signal handler (%d): %m", s); \
-           die(1); \
+           exit(1); \
        } \
     }
 
@@ -360,6 +366,9 @@ main(argc, argv)
      */
     signal(SIGPIPE, SIG_IGN);
 
+    waiting = 0;
+    sigprocmask(SIG_BLOCK, &mask, NULL);
+
     /*
      * If we're doing dial-on-demand, set up the interface now.
      */
@@ -393,17 +402,25 @@ main(argc, argv)
            kill_link = 0;
            demand_unblock();
            for (;;) {
-               wait_loop_output(timeleft(&timo));
+               if (setjmp(sigjmp) == 0) {
+                   waiting = 1;
+                   sigprocmask(SIG_UNBLOCK, &mask, NULL);
+                   wait_loop_output(timeleft(&timo));
+               }
+               sigprocmask(SIG_BLOCK, &mask, NULL);
+               waiting = 0;
                calltimeout();
                if (kill_link) {
                    if (!persist)
-                       die(0);
+                       break;
                    kill_link = 0;
                }
                if (get_loop_output())
                    break;
                reap_kids();
            }
+           if (kill_link)
+               break;
 
            /*
             * Now we want to bring up the link.
@@ -428,20 +445,21 @@ main(argc, argv)
         * out and we want to use the modem lines, we reopen it later
         * in order to wait for the carrier detect signal from the modem.
         */
+       hungup = 0;
+       kill_link = 0;
+       sigprocmask(SIG_UNBLOCK, &mask, NULL);
        while ((ttyfd = open(devnam, O_NONBLOCK | O_RDWR, 0)) < 0) {
            if (errno != EINTR)
                syslog(LOG_ERR, "Failed to open %s: %m", devnam);
            if (!persist || errno != EINTR)
                goto fail;
        }
+       sigprocmask(SIG_BLOCK, &mask, NULL);
        if ((fdflags = fcntl(ttyfd, F_GETFL)) == -1
            || fcntl(ttyfd, F_SETFL, fdflags & ~O_NONBLOCK) < 0)
            syslog(LOG_WARNING,
                   "Couldn't reset non-blocking mode on device: %m");
 
-       hungup = 0;
-       kill_link = 0;
-
        /*
         * Do the equivalent of `mesg n' to stop broadcast messages.
         */
@@ -456,6 +474,11 @@ main(argc, argv)
        if (connector && connector[0]) {
            MAINDEBUG((LOG_INFO, "Connecting with <%s>", connector));
 
+           if (!default_device && modem) {
+               hangup_modem(ttyfd);    /* in case modem is off hook */
+               sleep(1);
+           }
+
            /*
             * Set line speed, flow control, etc.
             * On most systems we set CLOCAL for now so that we can talk
@@ -463,24 +486,15 @@ main(argc, argv)
             * side effect that we might miss it if CD drops before we
             * get to clear CLOCAL below.  On systems where we can talk
             * successfully to the modem with CLOCAL clear and CD down,
-            * we can clear CLOCAL at this point.
+            * we could clear CLOCAL at this point.
             */
            set_up_tty(ttyfd, 1);
 
-           /* drop dtr to hang up in case modem is off hook */
-           if (!default_device && modem) {
-               setdtr(ttyfd, FALSE);
-               sleep(1);
-               setdtr(ttyfd, TRUE);
-           }
-
            if (device_script(connector, ttyfd, ttyfd) < 0) {
                syslog(LOG_ERR, "Connect script failed");
-               setdtr(ttyfd, FALSE);
                goto fail;
            }
 
-
            syslog(LOG_INFO, "Serial connection established.");
            sleep(1);           /* give it time to set up its terminal */
        }
@@ -524,14 +538,21 @@ main(argc, argv)
        syslog(LOG_NOTICE, "Connect: %s <--> %s", ifname, devnam);
        lcp_lowerup(0);
        lcp_open(0);            /* Start protocol */
+       open_ccp_flag = 0;
        for (phase = PHASE_ESTABLISH; phase != PHASE_DEAD; ) {
-           wait_input(timeleft(&timo));
+           if (setjmp(sigjmp) == 0) {
+               waiting = 1;
+               sigprocmask(SIG_UNBLOCK, &mask, NULL);
+               wait_input(timeleft(&timo));
+           }
+           sigprocmask(SIG_BLOCK, &mask, NULL);
+           waiting = 0;
            calltimeout();
-           get_input();
            if (kill_link) {
                lcp_close(0, "User request");
                kill_link = 0;
            }
+           get_input();
            if (open_ccp_flag) {
                if (phase == PHASE_NETWORK) {
                    ccp_fsm[0].flags = OPT_RESTART; /* clears OPT_SILENT */
@@ -581,7 +602,7 @@ main(argc, argv)
        }
 
        if (!persist)
-           die(1);
+           break;
 
        if (demand)
            demand_discard();
@@ -589,19 +610,29 @@ main(argc, argv)
            phase = PHASE_HOLDOFF;
            TIMEOUT(holdoff_end, NULL, holdoff);
            do {
-               wait_time(timeleft(&timo));
+               if (setjmp(sigjmp) == 0) {
+                   waiting = 1;
+                   sigprocmask(SIG_UNBLOCK, &mask, NULL);
+                   wait_time(timeleft(&timo));
+               }
+               sigprocmask(SIG_BLOCK, &mask, NULL);
+               waiting = 0;
                calltimeout();
                if (kill_link) {
-                   if (!persist)
-                       die(0);
                    kill_link = 0;
                    phase = PHASE_DORMANT; /* allow signal to end holdoff */
                }
                reap_kids();
            } while (phase == PHASE_HOLDOFF);
+           if (!persist)
+               break;
        }
     }
 
+    /* Wait for scripts to finish */
+    while (n_children > 0)
+       reap_kids();
+
     die(0);
     return 0;
 }
@@ -632,6 +663,7 @@ static void
 create_pidfile()
 {
     FILE *pidfile;
+    char numbuf[16];
 
     (void) sprintf(pidfilename, "%s%s.pid", _PATH_VARRUN, ifname);
     if ((pidfile = fopen(pidfilename, "w")) != NULL) {
@@ -641,6 +673,8 @@ create_pidfile()
        syslog(LOG_ERR, "Failed to create pid file %s: %m", pidfilename);
        pidfilename[0] = 0;
     }
+    sprintf(numbuf, "%d", pid);
+    script_setenv("PPPD_PID", numbuf);
 }
 
 /*
@@ -782,8 +816,8 @@ close_tty()
     disestablish_ppp(ttyfd);
 
     /* drop dtr to hang up */
-    if (modem) {
-       setdtr(ttyfd, FALSE);
+    if (!default_device && modem) {
+       hangup_modem(ttyfd);
        /*
         * This sleep is in case the serial port has CLOCAL set by default,
         * and consequently will reassert DTR when we close the device.
@@ -847,7 +881,7 @@ timeout(func, arg, time)
     for (pp = &callout; (p = *pp); pp = &p->c_next)
        if (newp->c_time.tv_sec < p->c_time.tv_sec
            || (newp->c_time.tv_sec == p->c_time.tv_sec
-               && newp->c_time.tv_usec < p->c_time.tv_sec))
+               && newp->c_time.tv_usec < p->c_time.tv_usec))
            break;
     newp->c_next = p;
     *pp = newp;
@@ -963,6 +997,8 @@ hup(sig)
     if (conn_running)
        /* Send the signal to the [dis]connector process(es) also */
        kill_my_pg(sig);
+    if (waiting)
+       longjmp(sigjmp, 1);
 }
 
 
@@ -982,6 +1018,8 @@ term(sig)
     if (conn_running)
        /* Send the signal to the [dis]connector process(es) also */
        kill_my_pg(sig);
+    if (waiting)
+       longjmp(sigjmp, 1);
 }
 
 
@@ -993,7 +1031,8 @@ static void
 chld(sig)
     int sig;
 {
-    reap_kids();
+    if (waiting)
+       longjmp(sigjmp, 1);
 }
 
 
@@ -1027,6 +1066,8 @@ open_ccp(sig)
     int sig;
 {
     open_ccp_flag = 1;
+    if (waiting)
+       longjmp(sigjmp, 1);
 }
 
 
@@ -1092,7 +1133,7 @@ device_script(program, in, out)
                close(out);
            }
        }
-       if (nodetach == 0) {
+       if (!nodetach && !updetach) {
            close(2);
            errfd = open(_PATH_CONNERRS, O_WRONLY | O_APPEND | O_CREAT, 0600);
            if (errfd >= 0 && errfd != 2) {
@@ -1120,24 +1161,60 @@ device_script(program, in, out)
 }
 
 
+/*
+ * We maintain a list of child process pids and
+ * functions to call when they exit.
+ */
+struct subprocess {
+    pid_t      pid;
+    char       *prog;
+    void       (*done) __P((void *));
+    void       *arg;
+    struct subprocess *next;
+};
+
+struct subprocess *children;
+
 /*
  * run-program - execute a program with given arguments,
  * but don't wait for it.
  * If the program can't be executed, logs an error unless
  * must_exist is 0 and the program file doesn't exist.
+ * Returns -1 if it couldn't fork, 0 if the file doesn't exist
+ * or isn't an executable plain file, or the process ID of the child.
+ * If done != NULL, (*done)(arg) will be called later (within
+ * reap_kids) iff the return value is > 0.
  */
-int
-run_program(prog, args, must_exist)
+pid_t
+run_program(prog, args, must_exist, done, arg)
     char *prog;
     char **args;
     int must_exist;
+    void (*done) __P((void *));
+    void *arg;
 {
     int pid;
+    struct subprocess *chp;
+    struct stat sbuf;
+
+    /*
+     * First check if the file exists and is executable.
+     * We don't use access() because that would use the
+     * real user-id, which might not be root, and the script
+     * might be accessible only to root.
+     */
+    errno = EINVAL;
+    if (stat(prog, &sbuf) < 0 || !S_ISREG(sbuf.st_mode)
+       || (sbuf.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0) {
+       if (must_exist || errno != ENOENT)
+           syslog(LOG_WARNING, "Can't execute %s: %m", prog);
+       return 0;
+    }
 
     pid = fork();
     if (pid == -1) {
        syslog(LOG_ERR, "Failed to create child process for %s: %m", prog);
-       return -1;
+       die(1);
     }
     if (pid == 0) {
        int new_fd;
@@ -1176,15 +1253,36 @@ run_program(prog, args, must_exist)
 
        /* SysV recommends a second fork at this point. */
 
-       /* run the program; give it a null environment */
+       /* run the program */
        execve(prog, args, script_env);
-       if (must_exist || errno != ENOENT)
+       if (must_exist || errno != ENOENT) {
+           int i;
            syslog(LOG_WARNING, "Can't execute %s: %m", prog);
+           for (i = 0; args[i]; ++i)
+               syslog(LOG_DEBUG, "args[%d] = '%s'", i, args[i]);
+           for (i = 0; script_env[i]; ++i)
+               syslog(LOG_DEBUG, "env[%d] = '%s'", i, script_env[i]);
+       }
        _exit(-1);
     }
-    MAINDEBUG((LOG_DEBUG, "Script %s started; pid = %d", prog, pid));
+
+    if (debug)
+       syslog(LOG_DEBUG, "Script %s started; pid = %d", prog, pid);
     ++n_children;
-    return 0;
+
+    chp = (struct subprocess *) malloc(sizeof(struct subprocess));
+    if (chp == NULL) {
+       syslog(LOG_WARNING, "losing track of %s process", prog);
+    } else {
+       chp->pid = pid;
+       chp->prog = prog;
+       chp->done = done;
+       chp->arg = arg;
+       chp->next = children;
+       children = chp;
+    }
+
+    return pid;
 }
 
 
@@ -1196,21 +1294,28 @@ static void
 reap_kids()
 {
     int pid, status;
+    struct subprocess *chp, **prevp;
 
     if (n_children == 0)
        return;
-    if ((pid = waitpid(-1, &status, WNOHANG)) == -1) {
-       if (errno != ECHILD)
-           syslog(LOG_ERR, "Error waiting for child process: %m");
-       return;
-    }
-    if (pid > 0) {
+    while ((pid = waitpid(-1, &status, WNOHANG)) != -1 && pid != 0) {
        --n_children;
+       for (prevp = &children; (chp = *prevp) != NULL; prevp = &chp->next)
+           if (chp->pid == pid)
+               break;
+       if (debug)
+           syslog(LOG_DEBUG, "process %d (%s) finished, status = 0x%x",
+                  pid, (chp? chp->prog: "??"), status);
        if (WIFSIGNALED(status)) {
-           syslog(LOG_WARNING, "Child process %d terminated with signal %d",
-                  pid, WTERMSIG(status));
+           syslog(LOG_WARNING,
+                  "Child process %s (pid %d) terminated with signal %d",
+                  (chp? chp->prog: "??"), pid, WTERMSIG(status));
        }
+       if (chp && chp->done)
+           (*chp->done)(chp->arg);
     }
+    if (pid == -1 && errno != ECHILD)
+       syslog(LOG_ERR, "Error waiting for child process: %m");
 }
 
 
index 54810965f7a069c032cca0dafe0bf1684d1f7628..4407cefa16adbdc272b09206ce490c6bbbf5663d 100644 (file)
@@ -18,7 +18,7 @@
  */
 
 #ifndef lint
-static char rcsid[] = "$Id: options.c,v 1.43 1998/09/04 18:49:15 christos Exp $";
+static char rcsid[] = "$Id: options.c,v 1.44 1998/11/07 06:59:28 paulus Exp $";
 #endif
 
 #include <ctype.h>
@@ -50,13 +50,6 @@ static char rcsid[] = "$Id: options.c,v 1.43 1998/09/04 18:49:15 christos Exp $"
 #include "upap.h"
 #include "chap.h"
 #include "ccp.h"
-#ifdef CBCP_SUPPORT
-#include "cbcp.h"
-#endif
-
-#ifdef IPX_CHANGE
-#include "ipxcp.h"
-#endif /* IPX_CHANGE */
 
 #include <net/ppp-comp.h>
 
@@ -82,47 +75,34 @@ int kdebugflag = 0;         /* Tell kernel to print debug messages */
 int    default_device = 1;     /* Using /dev/tty or equivalent */
 char   devnam[MAXPATHLEN] = "/dev/tty";        /* Device name */
 int    crtscts = 0;            /* Use hardware flow control */
-int    modem = 1;              /* Use modem control lines */
+bool   modem = 1;              /* Use modem control lines */
 int    inspeed = 0;            /* Input/Output speed requested */
 u_int32_t netmask = 0;         /* IP netmask to set on interface */
-int    lockflag = 0;           /* Create lock file to lock the serial dev */
-int    nodetach = 0;           /* Don't detach from controlling tty */
+bool   lockflag = 0;           /* Create lock file to lock the serial dev */
+bool   nodetach = 0;           /* Don't detach from controlling tty */
+bool   updetach = 0;           /* Detach once link is up */
 char   *connector = NULL;      /* Script to establish physical link */
 char   *disconnector = NULL;   /* Script to disestablish physical link */
 char   *welcomer = NULL;       /* Script to run after phys link estab. */
 int    maxconnect = 0;         /* Maximum connect time */
 char   user[MAXNAMELEN];       /* Username for PAP */
 char   passwd[MAXSECRETLEN];   /* Password for PAP */
-int    auth_required = 0;      /* Peer is required to authenticate */
-int    defaultroute = 0;       /* assign default route through interface */
-int    proxyarp = 0;           /* Set up proxy ARP entry for peer */
-int    persist = 0;            /* Reopen link after it goes down */
-int    uselogin = 0;           /* Use /etc/passwd for checking PAP */
-int    lcp_echo_interval = 0;  /* Interval between LCP echo-requests */
-int    lcp_echo_fails = 0;     /* Tolerance to unanswered echo-requests */
+bool   persist = 0;            /* Reopen link after it goes down */
 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 */
+bool   demand = 0;             /* do dial-on-demand */
 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
+extern option_t auth_options[];
 
-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 */
@@ -135,295 +115,109 @@ pcap_t  pc;                     /* Fake struct pcap so we can compile expr */
 static int setdevname __P((char *, int));
 static int setipaddr __P((char *));
 static int setspeed __P((char *));
-static int setdebug __P((char **));
-static int setkdebug __P((char **));
-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((char **));
-static int nopap __P((char **));
-#ifdef OLD_OPTIONS
-static int setupapfile __P((char **));
-#endif
-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 **));
-#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((char **));
-static int setnocrtscts __P((char **));
-static int setcdtrcts __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((char **));
-static int setnoauth __P((char **));
 static int readfile __P((char **));
 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 **));
-static int setlcpfails __P((char **));
-static int setipcptimeout __P((char **));
-static int setipcpterm __P((char **));
-static int setipcpconf __P((char **));
-static int setipcpfails __P((char **));
-static int setpaptimeout __P((char **));
-static int setpapreqs __P((char **));
-static int setpapreqtime __P((char **));
-static int setchaptimeout __P((char **));
-static int setchapchal __P((char **));
-static int setchapintv __P((char **));
-static int setipcpaccl __P((char **));
-static int setipcpaccr __P((char **));
-static int setlcpechointv __P((char **));
-static int setlcpechofails __P((char **));
-static int noccp __P((char **));
-static int setbsdcomp __P((char **));
-static int setnobsdcomp __P((char **));
-static int setdeflate __P((char **));
-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((char **));
-static int setidle __P((char **));
-static int setholdoff __P((char **));
-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((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 **));
-static int setipxname __P((char **));
-static int setipxcptimeout __P((char **));
-static int setipxcpterm __P((char **));
-static int setipxcpconf __P((char **));
-static int setipxcpfails __P((char **));
-#endif /* IPX_CHANGE */
-
-#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 option_t *find_option __P((char *name));
+static int process_option __P((option_t *, char **));
+static int n_arguments __P((option_t *));
 static int readable __P((int fd));
 
 /*
  * Valid arguments.
  */
-static struct cmd {
-    char *cmd_name;
-    int num_args;
-    int (*cmd_func) __P((char **));
-} cmds[] = {
-    {"-all", 0, noopt},                /* Don't request/allow any options (useless) */
-    {"noaccomp", 0, noaccomp}, /* Disable Address/Control compression */
-    {"-ac", 0, noaccomp},      /* Disable Address/Control compress */
-    {"default-asyncmap", 0, noasyncmap}, /* Disable asyncmap negoatiation */
-    {"-am", 0, noasyncmap},    /* Disable asyncmap negotiation */
-    {"-as", 1, setasyncmap},   /* set the desired async map */
-    {"-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 */
-    {"-mn", 0, nomagicnumber}, /* Disable magic number negotiation */
-    {"default-mru", 0, nomru}, /* Disable MRU negotiation */
-    {"-mru", 0, nomru},                /* Disable mru negotiation */
-    {"-p", 0, setpassive},     /* Set passive mode */
-    {"nopcomp", 0, nopcomp},   /* Disable protocol field compression */
-    {"-pc", 0, nopcomp},       /* Disable protocol field compress */
-#if OLD_OPTIONS
-    {"+ua", 1, setupapfile},   /* Get PAP user and password from file */
-#endif
-    {"require-pap", 0, reqpap},        /* Require PAP authentication from peer */
-    {"+pap", 0, reqpap},       /* Require PAP auth from peer */
-    {"refuse-pap", 0, nopap},  /* Don't agree to auth to peer with PAP */
-    {"-pap", 0, nopap},                /* Don't allow UPAP authentication with peer */
-    {"require-chap", 0, reqchap}, /* Require CHAP authentication from peer */
-    {"+chap", 0, reqchap},     /* Require CHAP authentication from peer */
-    {"refuse-chap", 0, nochap},        /* Don't agree to auth to peer with CHAP */
-    {"-chap", 0, nochap},      /* Don't allow CHAP authentication with peer */
-    {"novj", 0, setnovj},      /* Disable VJ compression */
-    {"-vj", 0, setnovj},       /* disable VJ compression */
-    {"novjccomp", 0, setnovjccomp}, /* disable VJ connection-ID compression */
-    {"-vjccomp", 0, setnovjccomp}, /* disable VJ connection-ID compression */
-    {"vj-max-slots", 1, setvjslots}, /* Set maximum VJ header slots */
-    {"asyncmap", 1, setasyncmap}, /* set the desired async map */
-    {"escape", 1, setescape},  /* set chars to escape on transmission */
-    {"connect", 1, setconnector}, /* A program to set up a connection */
-    {"disconnect", 1, setdisconnector},        /* program to disconnect serial dev. */
-    {"welcome", 1, setwelcomer},/* Script to welcome client */
-    {"maxconnect", 1, setmaxconnect},  /* specify a maximum connect time */
-    {"crtscts", 0, setcrtscts},        /* set h/w flow control */
-    {"nocrtscts", 0, setnocrtscts}, /* clear h/w flow control */
-    {"-crtscts", 0, setnocrtscts}, /* clear h/w flow control */
-    {"cdtrcts", 0, setcdtrcts},  /* set alternate h/w flow control */
-    {"nocdtrcts", 0, setnocrtscts}, /* clear h/w flow control */
-    {"-cdtrcts", 0, setnocrtscts}, /* clear h/w flow control */
-    {"xonxoff", 0, setxonxoff},        /* set s/w flow control */
-    {"debug", 0, setdebug},    /* Increase debugging level */
-    {"kdebug", 1, setkdebug},  /* Enable kernel-level debugging */
-    {"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 */
-    {"modem", 0, setmodem},    /* Use modem control lines */
-    {"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 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 */
-    {"proxyarp", 0, setproxyarp}, /* Add proxy ARP entry */
-    {"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 */
-    {"lcp-echo-failure", 1, setlcpechofails}, /* consecutive echo failures */
-    {"lcp-echo-interval", 1, setlcpechointv}, /* time for lcp echo events */
-    {"lcp-restart", 1, setlcptimeout}, /* Set timeout for LCP */
-    {"lcp-max-terminate", 1, setlcpterm}, /* Set max #xmits for term-reqs */
-    {"lcp-max-configure", 1, setlcpconf}, /* Set max #xmits for conf-reqs */
-    {"lcp-max-failure", 1, setlcpfails}, /* Set max #conf-naks for LCP */
-    {"ipcp-restart", 1, setipcptimeout}, /* Set timeout for IPCP */
-    {"ipcp-max-terminate", 1, setipcpterm}, /* Set max #xmits for term-reqs */
-    {"ipcp-max-configure", 1, setipcpconf}, /* Set max #xmits for conf-reqs */
-    {"ipcp-max-failure", 1, setipcpfails}, /* Set max #conf-naks for IPCP */
-    {"pap-restart", 1, setpaptimeout}, /* Set retransmit timeout for PAP */
-    {"pap-max-authreq", 1, setpapreqs}, /* Set max #xmits for auth-reqs */
-    {"pap-timeout", 1, setpapreqtime}, /* Set time limit for peer PAP auth. */
-    {"chap-restart", 1, setchaptimeout}, /* Set timeout for CHAP */
-    {"chap-max-challenge", 1, setchapchal}, /* Set max #xmits for challenge */
-    {"chap-interval", 1, setchapintv}, /* Set interval for rechallenge */
-    {"ipcp-accept-local", 0, setipcpaccl}, /* Accept peer's address for us */
-    {"ipcp-accept-remote", 0, setipcpaccr}, /* Accept peer's address for it */
-    {"noccp", 0, noccp},               /* Disable CCP negotiation */
-    {"-ccp", 0, noccp},                        /* Disable CCP negotiation */
-    {"bsdcomp", 1, setbsdcomp},                /* request BSD-Compress */
-    {"nobsdcomp", 0, setnobsdcomp},    /* don't allow BSD-Compress */
-    {"-bsdcomp", 0, setnobsdcomp},     /* don't allow BSD-Compress */
-    {"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 */
-    {"ipparam", 1, setipparam},                /* set ip script parameter */
-    {"papcrypt", 0, setpapcrypt},      /* PAP passwords encrypted */
-    {"idle", 1, setidle},              /* idle time limit (seconds) */
-    {"holdoff", 1, setholdoff},                /* set holdoff time (seconds) */
-    {"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 */
+option_t general_options[] = {
+    { "debug", o_int, &debug,
+      "Increase debugging level", OPT_INC|OPT_NOARG|1 },
+    { "-d", o_int, &debug,
+      "Increase debugging level", OPT_INC|OPT_NOARG|1 },
+    { "kdebug", o_int, &kdebugflag,
+      "Set kernel driver debug level" },
+    { "nodetach", o_bool, &nodetach,
+      "Don't detach from controlling tty", 1 },
+    { "-detach", o_bool, &nodetach,
+      "Don't detach from controlling tty", 1 },
+    { "updetach", o_bool, &updetach,
+      "Detach from controlling tty once link is up", 1 },
+    { "holdoff", o_int, &holdoff,
+      "Set time in seconds before retrying connection" },
+    { "idle", o_int, &idle_time_limit,
+      "Set time in seconds before disconnecting idle link" },
+    { "lock", o_bool, &lockflag,
+      "Lock serial device with UUCP-style lock file", 1 },
+    { "-all", o_special_noarg, noopt,
+      "Don't request/allow any LCP or IPCP options (useless)" },
+    { "connect", o_string, &connector,
+      "A program to set up a connection", OPT_A2INFO, &connector_info },
+    { "disconnect", o_string, &disconnector,
+      "Program to disconnect serial device", OPT_A2INFO, &disconnector_info },
+    { "welcome", o_string, &welcomer,
+      "Script to welcome client", OPT_A2INFO, &welcomer_info },
+    { "maxconnect", o_int, &maxconnect,
+      "Set connection time limit", OPT_LLIMIT|OPT_NOINCR|OPT_ZEROINF },
+    { "crtscts", o_int, &crtscts,
+      "Set hardware (RTS/CTS) flow control", OPT_NOARG|OPT_VAL(1) },
+    { "nocrtscts", o_int, &crtscts,
+      "Disable hardware flow control", OPT_NOARG|OPT_VAL(-1) },
+    { "-crtscts", o_int, &crtscts,
+      "Disable hardware flow control", OPT_NOARG|OPT_VAL(-1) },
+    { "cdtrcts", o_int, &crtscts,
+      "Set alternate hardware (DTR/CTS) flow control", OPT_NOARG|OPT_VAL(2) },
+    { "nocdtrcts", o_int, &crtscts,
+      "Disable hardware flow control", OPT_NOARG|OPT_VAL(-1) },
+    { "xonxoff", o_special_noarg, setxonxoff,
+      "Set software (XON/XOFF) flow control" },
+    { "domain", o_special, setdomain,
+      "Add given domain name to hostname" },
+    { "mtu", o_int, &lcp_allowoptions[0].mru,
+      "Set our MTU", OPT_LIMITS, NULL, MAXMRU, MINMRU },
+    { "netmask", o_special, setnetmask,
+      "set netmask" },
+    { "modem", o_bool, &modem,
+      "Use modem control lines", 1 },
+    { "local", o_bool, &modem,
+      "Don't use modem control lines" },
+    { "file", o_special, readfile,
+      "Take options from a file" },
+    { "call", o_special, callfile,
+      "Take options from a privileged file" },
+    { "persist", o_bool, &persist,
+      "Keep on reopening connection after close", 1 },
+    { "nopersist", o_bool, &persist,
+      "Turn off persist option" },
+    { "demand", o_bool, &demand,
+      "Dial on demand", 1, &persist },
+    { "--version", o_special_noarg, showversion,
+      "Show version number" },
+    { "--help", o_special_noarg, showhelp,
+      "Show brief listing of options" },
+    { "-h", o_special_noarg, showhelp,
+      "Show brief listing of options" },
 
 #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
-
-#ifdef IPX_CHANGE
-    {"ipx-network",          1, setipxnetwork}, /* IPX network number */
-    {"ipxcp-accept-network", 0, setipxanet},    /* Accept peer netowrk */
-    {"ipx-node",             1, setipxnode},    /* IPX node number */
-    {"ipxcp-accept-local",   0, setipxalcl},    /* Accept our address */
-    {"ipxcp-accept-remote",  0, setipxarmt},    /* Accept peer's address */
-    {"ipx-routing",          1, setipxrouter},  /* IPX routing proto number */
-    {"ipx-router-name",      1, setipxname},    /* IPX router name */
-    {"ipxcp-restart",        1, setipxcptimeout}, /* Set timeout for IPXCP */
-    {"ipxcp-max-terminate",  1, setipxcpterm},  /* max #xmits for term-reqs */
-    {"ipxcp-max-configure",  1, setipxcpconf},  /* max #xmits for conf-reqs */
-    {"ipxcp-max-failure",    1, setipxcpfails}, /* max #conf-naks for IPXCP */
-#if 0
-    {"ipx-compression", 1, setipxcompression}, /* IPX compression number */
-#endif
-    {"ipx",                 0, setipxproto},   /* Enable IPXCP (and IPX) */
-    {"+ipx",                0, setipxproto},   /* Enable IPXCP (and IPX) */
-#endif /* IPX_CHANGE */
-
-#ifdef MSLANMAN
-    {"ms-lanman", 0, setmslanman},     /* Use LanMan psswd when using MS-CHAP */
+    { "pdebug", o_int, &dflag,
+      "libpcap debugging" },
+    { "pass-filter", 1, setpassfilter,
+      "set filter for packets to pass" },
+    { "active-filter", 1, setactivefilter,
+      "set filter for active pkts" },
 #endif
 
-    {NULL, 0, NULL}
+    { NULL }
 };
 
-
 #ifndef IMPLEMENTATION
 #define IMPLEMENTATION ""
 #endif
@@ -439,7 +233,6 @@ Usage: %s [ options ], where options are:\n\
        auth            Require authentication from peer\n\
         connect <p>     Invoke shell command <p> to set up the serial line\n\
        crtscts         Use hardware RTS/CTS flow control\n\
-       cdtrcts         Use hardware DTR/CTS flow control (if supported)\n\
        defaultroute    Add default route through interface\n\
        file <f>        Take options from file <f>\n\
        modem           Use modem control lines\n\
@@ -447,10 +240,6 @@ Usage: %s [ options ], where options are:\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.
  */
@@ -460,7 +249,7 @@ parse_args(argc, argv)
     char **argv;
 {
     char *arg;
-    struct cmd *cmdp;
+    option_t *opt;
     int ret;
 
     privileged_option = privileged;
@@ -470,37 +259,35 @@ parse_args(argc, argv)
        --argc;
 
        /*
-        * First see if it's a command.
+        * First see if it's an option in the new option list.
         */
-       for (cmdp = cmds; cmdp->cmd_name; cmdp++)
-           if (!strcmp(arg, cmdp->cmd_name))
-               break;
-
-       if (cmdp->cmd_name != NULL) {
-           if (argc < cmdp->num_args) {
+       opt = find_option(arg);
+       if (opt != NULL) {
+           int n = n_arguments(opt);
+           if (argc < n) {
                option_error("too few parameters for option %s", arg);
                return 0;
            }
            current_option = arg;
-           if (!(*cmdp->cmd_func)(argv))
+           if (!process_option(opt, argv))
                return 0;
-           argc -= cmdp->num_args;
-           argv += cmdp->num_args;
+           argc -= n;
+           argv += n;
+           continue;
+       }
 
-       } else {
-           /*
-            * Maybe a tty name, speed or IP address?
-            */
-           if ((ret = setdevname(arg, 0)) == 0
-               && (ret = setspeed(arg)) == 0
-               && (ret = setipaddr(arg)) == 0) {
-               option_error("unrecognized option '%s'", arg);
-               usage();
-               return 0;
-           }
-           if (ret < 0)        /* error */
-               return 0;
+       /*
+        * Maybe a tty name, speed or IP address?
+        */
+       if ((ret = setdevname(arg, 0)) == 0
+           && (ret = setspeed(arg)) == 0
+           && (ret = setipaddr(arg)) == 0) {
+           option_error("unrecognized option '%s'", arg);
+           usage();
+           return 0;
        }
+       if (ret < 0)    /* error */
+           return 0;
     }
     return 1;
 }
@@ -515,20 +302,18 @@ scan_args(argc, argv)
     char **argv;
 {
     char *arg;
-    struct cmd *cmdp;
+    option_t *opt;
 
     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;
+       opt = find_option(arg);
+       if (opt != NULL) {
+           int n = n_arguments(opt);
+           argc -= n;
+           argv += n;
            continue;
        }
 
@@ -537,46 +322,6 @@ scan_args(argc, argv)
     }
 }
 
-/*
- * usage - print out a message telling how to use the program.
- */
-void
-usage()
-{
-    if (phase == PHASE_INITIALIZE)
-       fprintf(stderr, usage_string, VERSION, PATCHLEVEL, IMPLEMENTATION,
-               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.
@@ -590,8 +335,9 @@ options_from_file(filename, must_exist, check_prot, priv)
 {
     FILE *f;
     int i, newline, ret;
-    struct cmd *cmdp;
+    option_t *opt;
     int oldpriv;
+    char *oldsource;
     char *argv[MAXARGS];
     char args[MAXARGS][MAXWORDLEN];
     char cmd[MAXWORDLEN];
@@ -610,17 +356,19 @@ options_from_file(filename, must_exist, check_prot, priv)
 
     oldpriv = privileged_option;
     privileged_option = priv;
+    oldsource = option_source;
+    option_source = strdup(filename);
+    if (option_source == NULL)
+       option_source = "file";
     ret = 0;
     while (getword(f, cmd, &newline, filename)) {
        /*
         * First see if it's a command.
         */
-       for (cmdp = cmds; cmdp->cmd_name; cmdp++)
-           if (!strcmp(cmd, cmdp->cmd_name))
-               break;
-
-       if (cmdp->cmd_name != NULL) {
-           for (i = 0; i < cmdp->num_args; ++i) {
+       opt = find_option(cmd);
+       if (opt != NULL) {
+           int n = n_arguments(opt);
+           for (i = 0; i < n; ++i) {
                if (!getword(f, args[i], &newline, filename)) {
                    option_error(
                        "In file %s: too few parameters for option '%s'",
@@ -630,29 +378,30 @@ options_from_file(filename, must_exist, check_prot, priv)
                argv[i] = args[i];
            }
            current_option = cmd;
-           if (!(*cmdp->cmd_func)(argv))
+           if (!process_option(opt, argv))
                goto err;
+           continue;
+       }
 
-       } else {
-           /*
-            * Maybe a tty name, speed or IP address?
-            */
-           if ((i = setdevname(cmd, 0)) == 0
-               && (i = setspeed(cmd)) == 0
-               && (i = setipaddr(cmd)) == 0) {
-               option_error("In file %s: unrecognized option '%s'",
-                            filename, cmd);
-               goto err;
-           }
-           if (i < 0)          /* error */
-               goto err;
+       /*
+        * Maybe a tty name, speed or IP address?
+        */
+       if ((i = setdevname(cmd, 0)) == 0
+           && (i = setspeed(cmd)) == 0
+           && (i = setipaddr(cmd)) == 0) {
+           option_error("In file %s: unrecognized option '%s'",
+                        filename, cmd);
+           goto err;
        }
+       if (i < 0)              /* error */
+           goto err;
     }
     ret = 1;
 
 err:
     fclose(f);
     privileged_option = oldpriv;
+    option_source = oldsource;
     return ret;
 }
 
@@ -710,6 +459,203 @@ options_for_tty()
     return ret;
 }
 
+/*
+ * find_option - scan the option lists for the various protocols
+ * looking for an entry with the given name.
+ * This could be optimized by using a hash table.
+ */
+static option_t *
+find_option(char *name)
+{
+    option_t *opt;
+    int i;
+
+    for (opt = general_options; opt->name != NULL; ++opt)
+       if (strcmp(name, opt->name) == 0)
+           return opt;
+    for (opt = auth_options; opt->name != NULL; ++opt)
+       if (strcmp(name, opt->name) == 0)
+           return opt;
+    for (i = 0; protocols[i] != NULL; ++i)
+       if ((opt = protocols[i]->options) != NULL)
+           for (; opt->name != NULL; ++opt)
+               if (strcmp(name, opt->name) == 0)
+                   return opt;
+    return NULL;
+}
+
+/*
+ * process_option - process one new-style option.
+ */
+static int
+process_option(opt, argv)
+    option_t *opt;
+    char **argv;
+{
+    u_int32_t v;
+    int iv, a;
+    char *sv;
+    int (*parser) __P((char **));
+
+    if ((opt->flags & OPT_PRIV) && !privileged_option) {
+       option_error("using the %s option requires root privilege", opt->name);
+       return 0;
+    }
+    if ((opt->flags & OPT_ENABLE) && *(bool *)(opt->addr2) == 0) {
+       option_error("%s option is disabled", opt->name);
+       return 0;
+    }
+
+    switch (opt->type) {
+    case o_bool:
+       v = opt->flags & OPT_VALUE;
+       *(bool *)(opt->addr) = v;
+       if (opt->addr2 && (opt->flags & OPT_A2COPY))
+           *(bool *)(opt->addr2) = v;
+       break;
+
+    case o_int:
+       iv = 0;
+       if ((opt->flags & OPT_NOARG) == 0) {
+           if (!int_option(*argv, &iv))
+               return 0;
+           if ((((opt->flags & OPT_LLIMIT) && iv < opt->lower_limit)
+                || ((opt->flags & OPT_ULIMIT) && iv > opt->upper_limit))
+               && !((opt->flags & OPT_ZEROOK && iv == 0))) {
+               char *zok = (opt->flags & OPT_ZEROOK)? " zero or": "";
+               switch (opt->flags & OPT_LIMITS) {
+               case OPT_LLIMIT:
+                   option_error("%s value must be%s >= %d",
+                                opt->name, zok, opt->lower_limit);
+                   break;
+               case OPT_ULIMIT:
+                   option_error("%s value must be%s <= %d",
+                                opt->name, zok, opt->upper_limit);
+                   break;
+               case OPT_LIMITS:
+                   option_error("%s value must be%s between %d and %d",
+                               opt->name, opt->lower_limit, opt->upper_limit);
+                   break;
+               }
+               return 0;
+           }
+       }
+       a = opt->flags & OPT_VALUE;
+       if (a >= 128)
+           a -= 256;           /* sign extend */
+       iv += a;
+       if (opt->flags & OPT_INC)
+           iv += *(int *)(opt->addr);
+       if ((opt->flags & OPT_NOINCR) && !privileged_option) {
+           int oldv = *(int *)(opt->addr);
+           if ((opt->flags & OPT_ZEROINF) ?
+               (oldv != 0 && (iv == 0 || iv > oldv)) : (iv > oldv)) {
+               option_error("%s value cannot be increased", opt->name);
+               return 0;
+           }
+       }
+       *(int *)(opt->addr) = iv;
+       if (opt->addr2 && (opt->flags & OPT_A2COPY))
+           *(int *)(opt->addr2) = iv;
+       break;
+
+    case o_uint32:
+       if (opt->flags & OPT_NOARG) {
+           v = opt->flags & OPT_VALUE;
+       } else if (!number_option(*argv, &v, 16))
+           return 0;
+       if (opt->flags & OPT_OR)
+           v |= *(u_int32_t *)(opt->addr);
+       *(u_int32_t *)(opt->addr) = v;
+       if (opt->addr2 && (opt->flags & OPT_A2COPY))
+           *(u_int32_t *)(opt->addr2) = v;
+       break;
+
+    case o_string:
+       if (opt->flags & OPT_STATIC) {
+           if (opt->upper_limit) {
+               strncpy((char *)(opt->addr), *argv, opt->upper_limit);
+               ((char *)(opt->addr))[opt->upper_limit-1] = 0;
+           } else
+               strcpy((char *)(opt->addr), *argv);
+       } else {
+           sv = strdup(*argv);
+           if (sv == NULL)
+               novm("option argument");
+           *(char **)(opt->addr) = sv;
+       }
+       break;
+
+    case o_special_noarg:
+    case o_special:
+       parser = (int (*) __P((char **))) opt->addr;
+       if (!(*parser)(argv))
+           return 0;
+       break;
+    }
+
+    if (opt->addr2) {
+       if (opt->flags & OPT_A2INFO) {
+           struct option_info *ip = (struct option_info *) opt->addr2;
+           ip->priv = privileged_option;
+           ip->source = option_source;
+       } else if ((opt->flags & (OPT_A2COPY|OPT_ENABLE)) == 0)
+           *(bool *)(opt->addr2) = 1;
+    }
+
+    return 1;
+}
+
+/*
+ * n_arguments - tell how many arguments an option takes
+ */
+static int
+n_arguments(option_t *opt)
+{
+    return (opt->type == o_bool || opt->type == o_special_noarg
+           || (opt->flags & OPT_NOARG))? 0: 1;
+}
+
+/*
+ * usage - print out a message telling how to use the program.
+ */
+void
+usage()
+{
+    if (phase == PHASE_INITIALIZE)
+       fprintf(stderr, usage_string, VERSION, PATCHLEVEL, IMPLEMENTATION,
+               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;
+}
+
 /*
  * option_error - print a message about an error in an option.
  * The message is logged, and also sent to
@@ -1012,7 +958,7 @@ getword(f, word, newlinep, filename)
 /*
  * number_option - parse an unsigned numeric parameter for an option.
  */
-static int
+int
 number_option(str, valp, base)
     char *str;
     u_int32_t *valp;
@@ -1035,7 +981,7 @@ number_option(str, valp, base)
  * the base is assumed to be 0, and *valp is not changed
  * if there is an error.
  */
-static int
+int
 int_option(str, valp)
     char *str;
     int *valp;
@@ -1107,28 +1053,6 @@ callfile(argv)
     return ok;
 }
 
-
-/*
- * setdebug - Set debug (command line argument).
- */
-static int
-setdebug(argv)
-    char **argv;
-{
-    debug++;
-    return (1);
-}
-
-/*
- * setkdebug - Set kernel debugging level.
- */
-static int
-setkdebug(argv)
-    char **argv;
-{
-    return int_option(*argv, &kdebugflag);
-}
-
 #ifdef PPP_FILTER
 /*
  * setpdebug - Set libpcap debugging level.
@@ -1185,1408 +1109,213 @@ noopt(argv)
     BZERO((char *) &ipcp_wantoptions[0], sizeof (struct ipcp_options));
     BZERO((char *) &ipcp_allowoptions[0], sizeof (struct ipcp_options));
 
-#ifdef IPX_CHANGE
-    BZERO((char *) &ipxcp_wantoptions[0], sizeof (struct ipxcp_options));
-    BZERO((char *) &ipxcp_allowoptions[0], sizeof (struct ipxcp_options));
-#endif /* IPX_CHANGE */
-
     return (1);
 }
 
 /*
- * noaccomp - Disable Address/Control field compression negotiation.
+ * setdomain - Set domain name to append to hostname 
  */
 static int
-noaccomp(argv)
+setdomain(argv)
     char **argv;
 {
-    lcp_wantoptions[0].neg_accompression = 0;
-    lcp_allowoptions[0].neg_accompression = 0;
+    if (!privileged_option) {
+       option_error("using the domain option requires root privilege");
+       return 0;
+    }
+    gethostname(hostname, MAXNAMELEN);
+    if (**argv != 0) {
+       if (**argv != '.')
+           strncat(hostname, ".", MAXNAMELEN - strlen(hostname));
+       strncat(hostname, *argv, MAXNAMELEN - strlen(hostname));
+    }
+    hostname[MAXNAMELEN-1] = 0;
     return (1);
 }
 
 
 /*
- * noasyncmap - Disable async map negotiation.
+ * setspeed - Set the speed.
  */
 static int
-noasyncmap(argv)
-    char **argv;
+setspeed(arg)
+    char *arg;
 {
-    lcp_wantoptions[0].neg_asyncmap = 0;
-    lcp_allowoptions[0].neg_asyncmap = 0;
-    return (1);
+    char *ptr;
+    int spd;
+
+    spd = strtol(arg, &ptr, 0);
+    if (ptr == arg || *ptr != 0 || spd == 0)
+       return 0;
+    inspeed = spd;
+    return 1;
 }
 
 
 /*
- * noip - Disable IP and IPCP.
+ * setdevname - Set the device name.
  */
 static int
-noip(argv)
-    char **argv;
+setdevname(cp, quiet)
+    char *cp;
+    int quiet;
 {
-    ipcp_protent.enabled_flag = 0;
-    return (1);
+    struct stat statbuf;
+    char dev[MAXPATHLEN];
+
+    if (*cp == 0)
+       return 0;
+
+    if (strncmp("/dev/", cp, 5) != 0) {
+       strcpy(dev, "/dev/");
+       strncat(dev, cp, MAXPATHLEN - 5);
+       dev[MAXPATHLEN-1] = 0;
+       cp = dev;
+    }
+
+    /*
+     * Check if there is a device by this name.
+     */
+    if (stat(cp, &statbuf) < 0) {
+       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;
 }
 
 
 /*
- * nomagicnumber - Disable magic number negotiation.
+ * setipaddr - Set the IP address
  */
 static int
-nomagicnumber(argv)
-    char **argv;
-{
-    lcp_wantoptions[0].neg_magicnumber = 0;
-    lcp_allowoptions[0].neg_magicnumber = 0;
-    return (1);
-}
-
-
-/*
- * nomru - Disable mru negotiation.
- */
-static int
-nomru(argv)
-    char **argv;
-{
-    lcp_wantoptions[0].neg_mru = 0;
-    lcp_allowoptions[0].neg_mru = 0;
-    return (1);
-}
-
-
-/*
- * setmru - Set MRU for negotiation.
- */
-static int
-setmru(argv)
-    char **argv;
-{
-    u_int32_t mru;
-
-    if (!number_option(*argv, &mru, 0))
-       return 0;
-    lcp_wantoptions[0].mru = mru;
-    lcp_wantoptions[0].neg_mru = 1;
-    return (1);
-}
-
-
-/*
- * setmru - Set the largest MTU we'll use.
- */
-static int
-setmtu(argv)
-    char **argv;
-{
-    u_int32_t mtu;
-
-    if (!number_option(*argv, &mtu, 0))
-       return 0;
-    if (mtu < MINMRU || mtu > MAXMRU) {
-       option_error("mtu option value of %u is too %s", mtu,
-                    (mtu < MINMRU? "small": "large"));
-       return 0;
-    }
-    lcp_allowoptions[0].mru = mtu;
-    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(argv)
-    char **argv;
-{
-    lcp_wantoptions[0].neg_pcompression = 0;
-    lcp_allowoptions[0].neg_pcompression = 0;
-    return (1);
-}
-
-
-/*
- * setpassive - Set passive mode (don't give up if we time out sending
- * LCP configure-requests).
- */
-static int
-setpassive(argv)
-    char **argv;
-{
-    lcp_wantoptions[0].passive = 1;
-    return (1);
-}
-
-
-/*
- * setsilent - Set silent mode (don't start sending LCP configure-requests
- * until we get one from the peer).
- */
-static int
-setsilent(argv)
-    char **argv;
-{
-    lcp_wantoptions[0].silent = 1;
-    return 1;
-}
-
-
-/*
- * nopap - Disable PAP authentication with peer.
- */
-static int
-nopap(argv)
-    char **argv;
-{
-    refuse_pap = 1;
-    return (1);
-}
-
-
-/*
- * reqpap - Require PAP authentication from peer.
- */
-static int
-reqpap(argv)
-    char **argv;
-{
-    lcp_wantoptions[0].neg_upap = 1;
-    setauth(NULL);
-    return 1;
-}
-
-#if OLD_OPTIONS
-/*
- * setupapfile - specifies UPAP info for authenticating with peer.
- */
-static int
-setupapfile(argv)
-    char **argv;
-{
-    FILE * ufile;
-    int l;
-
-    lcp_allowoptions[0].neg_upap = 1;
-
-    /* open user info file */
-    if ((ufile = fopen(*argv, "r")) == NULL) {
-       option_error("unable to open user login data file %s", *argv);
-       return 0;
-    }
-    if (!readable(fileno(ufile))) {
-       option_error("%s: access denied", *argv);
-       return 0;
-    }
-    check_access(ufile, *argv);
-
-    /* get username */
-    if (fgets(user, MAXNAMELEN - 1, ufile) == NULL
-       || fgets(passwd, MAXSECRETLEN - 1, ufile) == NULL){
-       option_error("unable to read user login data file %s", *argv);
-       return 0;
-    }
-    fclose(ufile);
-
-    /* get rid of newlines */
-    l = strlen(user);
-    if (l > 0 && user[l-1] == '\n')
-       user[l-1] = 0;
-    l = strlen(passwd);
-    if (l > 0 && passwd[l-1] == '\n')
-       passwd[l-1] = 0;
-
-    return (1);
-}
-#endif
-
-/*
- * nochap - Disable CHAP authentication with peer.
- */
-static int
-nochap(argv)
-    char **argv;
-{
-    refuse_chap = 1;
-    return (1);
-}
-
-
-/*
- * reqchap - Require CHAP authentication from peer.
- */
-static int
-reqchap(argv)
-    char **argv;
-{
-    lcp_wantoptions[0].neg_chap = 1;
-    setauth(NULL);
-    return (1);
-}
-
-
-/*
- * setnovj - disable vj compression
- */
-static int
-setnovj(argv)
-    char **argv;
-{
-    ipcp_wantoptions[0].neg_vj = 0;
-    ipcp_allowoptions[0].neg_vj = 0;
-    return (1);
-}
-
-
-/*
- * setnovjccomp - disable VJ connection-ID compression
- */
-static int
-setnovjccomp(argv)
-    char **argv;
-{
-    ipcp_wantoptions[0].cflag = 0;
-    ipcp_allowoptions[0].cflag = 0;
-    return 1;
-}
-
-
-/*
- * setvjslots - set maximum number of connection slots for VJ compression
- */
-static int
-setvjslots(argv)
-    char **argv;
-{
-    int value;
-
-    if (!int_option(*argv, &value))
-       return 0;
-    if (value < 2 || value > 16) {
-       option_error("vj-max-slots value must be between 2 and 16");
-       return 0;
-    }
-    ipcp_wantoptions [0].maxslotindex =
-        ipcp_allowoptions[0].maxslotindex = value - 1;
-    return 1;
-}
-
-
-/*
- * setconnector - Set a program to connect to a serial line
- */
-static int
-setconnector(argv)
-    char **argv;
-{
-    connector = strdup(*argv);
-    if (connector == NULL)
-       novm("connect script");
-    connector_info.priv = privileged_option;
-    connector_info.source = option_source;
-
-    return (1);
-}
-
-/*
- * setdisconnector - Set a program to disconnect from the serial line
- */
-static int
-setdisconnector(argv)
-    char **argv;
-{
-    disconnector = strdup(*argv);
-    if (disconnector == NULL)
-       novm("disconnect script");
-    disconnector_info.priv = privileged_option;
-    disconnector_info.source = option_source;
-  
-    return (1);
-}
-
-/*
- * setwelcomer - Set a program to welcome a client after connection
- */
-static int
-setwelcomer(argv)
-    char **argv;
-{
-    welcomer = strdup(*argv);
-    if (welcomer == NULL)
-       novm("welcome script");
-    welcomer_info.priv = privileged_option;
-    welcomer_info.source = option_source;
-
-    return (1);
-}
-
-/*
- * setmaxconnect - Set the maximum connect time
- */
-static int
-setmaxconnect(argv)
-    char **argv;
-{
-    int value;
-
-    if (!int_option(*argv, &value))
-       return 0;
-    if (value < 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;
-}
-
-/*
- * setdomain - Set domain name to append to hostname 
- */
-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 != '.')
-           strncat(hostname, ".", MAXNAMELEN - strlen(hostname));
-       strncat(hostname, *argv, MAXNAMELEN - strlen(hostname));
-    }
-    hostname[MAXNAMELEN-1] = 0;
-    return (1);
-}
-
-
-/*
- * setasyncmap - add bits to asyncmap (what we request peer to escape).
- */
-static int
-setasyncmap(argv)
-    char **argv;
-{
-    u_int32_t asyncmap;
-
-    if (!number_option(*argv, &asyncmap, 16))
-       return 0;
-    lcp_wantoptions[0].asyncmap |= asyncmap;
-    lcp_wantoptions[0].neg_asyncmap = 1;
-    return(1);
-}
-
-
-/*
- * setescape - add chars to the set we escape on transmission.
- */
-static int
-setescape(argv)
-    char **argv;
-{
-    int n, ret;
-    char *p, *endp;
-
-    p = *argv;
-    ret = 1;
-    while (*p) {
-       n = strtol(p, &endp, 16);
-       if (p == endp) {
-           option_error("escape parameter contains invalid hex number '%s'",
-                        p);
-           return 0;
-       }
-       p = endp;
-       if (n < 0 || (0x20 <= n && n <= 0x3F) || n == 0x5E || n > 0xFF) {
-           option_error("can't escape character 0x%x", n);
-           ret = 0;
-       } else
-           xmit_accm[0][n >> 5] |= 1 << (n & 0x1F);
-       while (*p == ',' || *p == ' ')
-           ++p;
-    }
-    return ret;
-}
-
-
-/*
- * setspeed - Set the speed.
- */
-static int
-setspeed(arg)
-    char *arg;
-{
-    char *ptr;
-    int spd;
-
-    spd = strtol(arg, &ptr, 0);
-    if (ptr == arg || *ptr != 0 || spd == 0)
-       return 0;
-    inspeed = spd;
-    return 1;
-}
-
-
-/*
- * setdevname - Set the device name.
- */
-static int
-setdevname(cp, quiet)
-    char *cp;
-    int quiet;
-{
-    struct stat statbuf;
-    char dev[MAXPATHLEN];
-
-    if (*cp == 0)
-       return 0;
-
-    if (strncmp("/dev/", cp, 5) != 0) {
-       strcpy(dev, "/dev/");
-       strncat(dev, cp, MAXPATHLEN - 5);
-       dev[MAXPATHLEN-1] = 0;
-       cp = dev;
-    }
-
-    /*
-     * Check if there is a device by this name.
-     */
-    if (stat(cp, &statbuf) < 0) {
-       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;
-}
-
-
-/*
- * setipaddr - Set the IP address
- */
-static int
-setipaddr(arg)
-    char *arg;
-{
-    struct hostent *hp;
-    char *colon;
-    u_int32_t local, remote;
-    ipcp_options *wo = &ipcp_wantoptions[0];
-  
-    /*
-     * IP address pair separated by ":".
-     */
-    if ((colon = strchr(arg, ':')) == NULL)
-       return 0;
-  
-    /*
-     * If colon first character, then no local addr.
-     */
-    if (colon != arg) {
-       *colon = '\0';
-       if ((local = inet_addr(arg)) == -1) {
-           if ((hp = gethostbyname(arg)) == NULL) {
-               option_error("unknown host: %s", arg);
-               return -1;
-           } else {
-               local = *(u_int32_t *)hp->h_addr;
-           }
-       }
-       if (bad_ip_adrs(local)) {
-           option_error("bad local IP address %s", ip_ntoa(local));
-           return -1;
-       }
-       if (local != 0)
-           wo->ouraddr = local;
-       *colon = ':';
-    }
-  
-    /*
-     * If colon last character, then no remote addr.
-     */
-    if (*++colon != '\0') {
-       if ((remote = inet_addr(colon)) == -1) {
-           if ((hp = gethostbyname(colon)) == NULL) {
-               option_error("unknown host: %s", colon);
-               return -1;
-           } else {
-               remote = *(u_int32_t *)hp->h_addr;
-               if (remote_name[0] == 0) {
-                   strncpy(remote_name, colon, MAXNAMELEN);
-                   remote_name[MAXNAMELEN-1] = 0;
-               }
-           }
-       }
-       if (bad_ip_adrs(remote)) {
-           option_error("bad remote IP address %s", ip_ntoa(remote));
-           return -1;
-       }
-       if (remote != 0)
-           wo->hisaddr = remote;
-    }
-
-    return 1;
-}
-
-
-/*
- * setnoipdflt - disable setipdefault()
- */
-static int
-setnoipdflt(argv)
-    char **argv;
-{
-    disable_defaultip = 1;
-    return 1;
-}
-
-
-/*
- * setipcpaccl - accept peer's idea of our address
- */
-static int
-setipcpaccl(argv)
-    char **argv;
-{
-    ipcp_wantoptions[0].accept_local = 1;
-    return 1;
-}
-
-
-/*
- * setipcpaccr - accept peer's idea of its address
- */
-static int
-setipcpaccr(argv)
-    char **argv;
-{
-    ipcp_wantoptions[0].accept_remote = 1;
-    return 1;
-}
-
-
-/*
- * setnetmask - set the netmask to be used on the interface.
- */
-static int
-setnetmask(argv)
-    char **argv;
-{
-    u_int32_t mask, b;
-    int n, ok;
-    char *p, *endp;
-
-    /*
-     * 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;
-    }
-
-    netmask = mask;
-    return (1);
-}
-
-static int
-setcrtscts(argv)
-    char **argv;
-{
-    crtscts = 1;
-    return (1);
-}
-
-static int
-setnocrtscts(argv)
-    char **argv;
-{
-    crtscts = -1;
-    return (1);
-}
-
-static int
-setcdtrcts(argv)
-    char **argv;
-{
-    crtscts = 2;
-    return (1);
-}
-
-static int
-setxonxoff(argv)
-    char **argv;
-{
-    lcp_wantoptions[0].asyncmap |= 0x000A0000; /* escape ^S and ^Q */
-    lcp_wantoptions[0].neg_asyncmap = 1;
-
-    crtscts = -2;
-    return (1);
-}
-
-static int
-setnodetach(argv)
-    char **argv;
-{
-    nodetach = 1;
-    return (1);
-}
-
-static int
-setupdetach(argv)
-    char **argv;
-{
-    nodetach = -1;
-    return (1);
-}
-
-static int
-setdemand(argv)
-    char **argv;
-{
-    demand = 1;
-    persist = 1;
-    return 1;
-}
-
-static int
-setmodem(argv)
-    char **argv;
-{
-    modem = 1;
-    return 1;
-}
-
-static int
-setlocal(argv)
-    char **argv;
-{
-    modem = 0;
-    return 1;
-}
-
-static int
-setlock(argv)
-    char **argv;
-{
-    lockflag = 1;
-    return 1;
-}
-
-static int
-setusehostname(argv)
-    char **argv;
-{
-    usehostname = 1;
-    return 1;
-}
-
-static int
-setname(argv)
-    char **argv;
-{
-    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;
-}
-
-static int
-setuser(argv)
-    char **argv;
-{
-    strncpy(user, argv[0], MAXNAMELEN);
-    user[MAXNAMELEN-1] = 0;
-    return 1;
-}
-
-static int
-setremote(argv)
-    char **argv;
-{
-    strncpy(remote_name, argv[0], MAXNAMELEN);
-    remote_name[MAXNAMELEN-1] = 0;
-    return 1;
-}
-
-static int
-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(argv)
-    char **argv;
-{
-    if (!ipcp_allowoptions[0].default_route) {
-       option_error("defaultroute option is disabled");
-       return 0;
-    }
-    ipcp_wantoptions[0].default_route = 1;
-    return 1;
-}
-
-static int
-setnodefaultroute(argv)
-    char **argv;
-{
-    ipcp_allowoptions[0].default_route = 0;
-    ipcp_wantoptions[0].default_route = 0;
-    return 1;
-}
-
-static int
-setproxyarp(argv)
-    char **argv;
-{
-    if (!ipcp_allowoptions[0].proxy_arp) {
-       option_error("proxyarp option is disabled");
-       return 0;
-    }
-    ipcp_wantoptions[0].proxy_arp = 1;
-    return 1;
-}
-
-static int
-setnoproxyarp(argv)
-    char **argv;
-{
-    ipcp_wantoptions[0].proxy_arp = 0;
-    ipcp_allowoptions[0].proxy_arp = 0;
-    return 1;
-}
-
-static int
-setpersist(argv)
-    char **argv;
-{
-    persist = 1;
-    return 1;
-}
-
-static int
-setnopersist(argv)
-    char **argv;
-{
-    persist = 0;
-    return 1;
-}
-
-static int
-setdologin(argv)
-    char **argv;
-{
-    uselogin = 1;
-    return 1;
-}
-
-/*
- * Functions to set the echo interval for modem-less monitors
- */
-
-static int
-setlcpechointv(argv)
-    char **argv;
-{
-    return int_option(*argv, &lcp_echo_interval);
-}
-
-static int
-setlcpechofails(argv)
-    char **argv;
-{
-    return int_option(*argv, &lcp_echo_fails);
-}
-
-/*
- * Functions to set timeouts, max transmits, etc.
- */
-static int
-setlcptimeout(argv)
-    char **argv;
-{
-    return int_option(*argv, &lcp_fsm[0].timeouttime);
-}
-
-static int
-setlcpterm(argv)
-    char **argv;
-{
-    return int_option(*argv, &lcp_fsm[0].maxtermtransmits);
-}
-
-static int
-setlcpconf(argv)
-    char **argv;
-{
-    return int_option(*argv, &lcp_fsm[0].maxconfreqtransmits);
-}
-
-static int
-setlcpfails(argv)
-    char **argv;
-{
-    return int_option(*argv, &lcp_fsm[0].maxnakloops);
-}
-
-static int
-setipcptimeout(argv)
-    char **argv;
-{
-    return int_option(*argv, &ipcp_fsm[0].timeouttime);
-}
-
-static int
-setipcpterm(argv)
-    char **argv;
-{
-    return int_option(*argv, &ipcp_fsm[0].maxtermtransmits);
-}
-
-static int
-setipcpconf(argv)
-    char **argv;
-{
-    return int_option(*argv, &ipcp_fsm[0].maxconfreqtransmits);
-}
-
-static int
-setipcpfails(argv)
-    char **argv;
-{
-    return int_option(*argv, &lcp_fsm[0].maxnakloops);
-}
-
-static int
-setpaptimeout(argv)
-    char **argv;
-{
-    return int_option(*argv, &upap[0].us_timeouttime);
-}
-
-static int
-setpapreqtime(argv)
-    char **argv;
-{
-    return int_option(*argv, &upap[0].us_reqtimeout);
-}
-
-static int
-setpapreqs(argv)
-    char **argv;
-{
-    return int_option(*argv, &upap[0].us_maxtransmits);
-}
-
-static int
-setchaptimeout(argv)
-    char **argv;
-{
-    return int_option(*argv, &chap[0].timeouttime);
-}
-
-static int
-setchapchal(argv)
-    char **argv;
-{
-    return int_option(*argv, &chap[0].max_transmits);
-}
-
-static int
-setchapintv(argv)
-    char **argv;
-{
-    return int_option(*argv, &chap[0].chal_interval);
-}
-
-static int
-noccp(argv)
-    char **argv;
-{
-    ccp_protent.enabled_flag = 0;
-    return 1;
-}
-
-static int
-setbsdcomp(argv)
-    char **argv;
-{
-    int rbits, abits;
-    char *str, *endp;
-
-    str = *argv;
-    abits = rbits = strtol(str, &endp, 0);
-    if (endp != str && *endp == ',') {
-       str = endp + 1;
-       abits = strtol(str, &endp, 0);
-    }
-    if (*endp != 0 || endp == str) {
-       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))) {
-       option_error("bsdcomp option values must be 0 or %d .. %d",
-                    BSD_MIN_BITS, BSD_MAX_BITS);
-       return 0;
-    }
-    if (rbits > 0) {
-       ccp_wantoptions[0].bsd_compress = 1;
-       ccp_wantoptions[0].bsd_bits = rbits;
-    } else
-       ccp_wantoptions[0].bsd_compress = 0;
-    if (abits > 0) {
-       ccp_allowoptions[0].bsd_compress = 1;
-       ccp_allowoptions[0].bsd_bits = abits;
-    } else
-       ccp_allowoptions[0].bsd_compress = 0;
-    return 1;
-}
-
-static int
-setnobsdcomp(argv)
-    char **argv;
-{
-    ccp_wantoptions[0].bsd_compress = 0;
-    ccp_allowoptions[0].bsd_compress = 0;
-    return 1;
-}
-
-static int
-setdeflate(argv)
-    char **argv;
-{
-    int rbits, abits;
-    char *str, *endp;
-
-    str = *argv;
-    abits = rbits = strtol(str, &endp, 0);
-    if (endp != str && *endp == ',') {
-       str = endp + 1;
-       abits = strtol(str, &endp, 0);
-    }
-    if (*endp != 0 || endp == str) {
-       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))) {
-       option_error("deflate option values must be 0 or %d .. %d",
-                    DEFLATE_MIN_SIZE, DEFLATE_MAX_SIZE);
-       return 0;
-    }
-    if (rbits > 0) {
-       ccp_wantoptions[0].deflate = 1;
-       ccp_wantoptions[0].deflate_size = rbits;
-    } else
-       ccp_wantoptions[0].deflate = 0;
-    if (abits > 0) {
-       ccp_allowoptions[0].deflate = 1;
-       ccp_allowoptions[0].deflate_size = abits;
-    } else
-       ccp_allowoptions[0].deflate = 0;
-    return 1;
-}
-
-static int
-setnodeflate(argv)
-    char **argv;
-{
-    ccp_wantoptions[0].deflate = 0;
-    ccp_allowoptions[0].deflate = 0;
-    return 1;
-}
-
-static int
-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;
-    return 1;
-}
-
-static int
-setnopred1comp(argv)
-    char **argv;
-{
-    ccp_wantoptions[0].predictor_1 = 0;
-    ccp_allowoptions[0].predictor_1 = 0;
-    return 1;
-}
-
-static int
-setipparam(argv)
-    char **argv;
-{
-    ipparam = strdup(*argv);
-    if (ipparam == NULL)
-       novm("ipparam string");
-
-    return 1;
-}
-
-static int
-setpapcrypt(argv)
-    char **argv;
-{
-    cryptpap = 1;
-    return 1;
-}
-
-static int
-setidle(argv)
-    char **argv;
-{
-    return int_option(*argv, &idle_time_limit);
-}
-
-static int
-setholdoff(argv)
-    char **argv;
-{
-    return int_option(*argv, &holdoff);
-}
-
-/*
- * setdnsaddr - set the dns address(es)
- */
-static int
-setdnsaddr(argv)
-    char **argv;
+setipaddr(arg)
+    char *arg;
 {
-    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;
+    char *colon;
+    u_int32_t local, remote;
+    ipcp_options *wo = &ipcp_wantoptions[0];
+  
+    /*
+     * IP address pair separated by ":".
+     */
+    if ((colon = strchr(arg, ':')) == NULL)
+       return 0;
+  
+    /*
+     * If colon first character, then no local addr.
+     */
+    if (colon != arg) {
+       *colon = '\0';
+       if ((local = inet_addr(arg)) == -1) {
+           if ((hp = gethostbyname(arg)) == NULL) {
+               option_error("unknown host: %s", arg);
+               return -1;
+           } else {
+               local = *(u_int32_t *)hp->h_addr;
+           }
        }
-       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;
+       if (bad_ip_adrs(local)) {
+           option_error("bad local IP address %s", ip_ntoa(local));
+           return -1;
        }
-       wins = *(u_int32_t *)hp->h_addr;
+       if (local != 0)
+           wo->ouraddr = local;
+       *colon = ':';
     }
-
-    /* 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)
-    char **argv;
-{
-    ipxcp_wantoptions[0].neg_router  = 1;
-    ipxcp_allowoptions[0].neg_router = 1;
-    return int_option(*argv, &ipxcp_wantoptions[0].router); 
-}
-
-static int
-setipxname (argv)
-    char **argv;
-{
-    char *dest = ipxcp_wantoptions[0].name;
-    char *src  = *argv;
-    int  count;
-    char ch;
-
-    ipxcp_wantoptions[0].neg_name  = 1;
-    ipxcp_allowoptions[0].neg_name = 1;
-    memset (dest, '\0', sizeof (ipxcp_wantoptions[0].name));
-
-    count = 0;
-    while (*src) {
-        ch = *src++;
-       if (! isalnum (ch) && ch != '_') {
-           option_error("IPX router name must be alphanumeric or _");
-           return 0;
+  
+    /*
+     * If colon last character, then no remote addr.
+     */
+    if (*++colon != '\0') {
+       if ((remote = inet_addr(colon)) == -1) {
+           if ((hp = gethostbyname(colon)) == NULL) {
+               option_error("unknown host: %s", colon);
+               return -1;
+           } else {
+               remote = *(u_int32_t *)hp->h_addr;
+               if (remote_name[0] == 0) {
+                   strncpy(remote_name, colon, MAXNAMELEN);
+                   remote_name[MAXNAMELEN-1] = 0;
+               }
+           }
        }
-
-       if (count >= sizeof (ipxcp_wantoptions[0].name)) {
-           option_error("IPX router name is limited to %d characters",
-                        sizeof (ipxcp_wantoptions[0].name) - 1);
-           return 0;
+       if (bad_ip_adrs(remote)) {
+           option_error("bad remote IP address %s", ip_ntoa(remote));
+           return -1;
        }
-
-       dest[count++] = toupper (ch);
+       if (remote != 0)
+           wo->hisaddr = remote;
     }
 
     return 1;
 }
 
-static int
-setipxcptimeout (argv)
-    char **argv;
-{
-    return int_option(*argv, &ipxcp_fsm[0].timeouttime);
-}
-
-static int
-setipxcpterm (argv)
-    char **argv;
-{
-    return int_option(*argv, &ipxcp_fsm[0].maxtermtransmits);
-}
-
-static int
-setipxcpconf (argv)
-    char **argv;
-{
-    return int_option(*argv, &ipxcp_fsm[0].maxconfreqtransmits);
-}
-
-static int
-setipxcpfails (argv)
-    char **argv;
-{
-    return int_option(*argv, &ipxcp_fsm[0].maxnakloops);
-}
-
-static int
-setipxnetwork(argv)
-    char **argv;
-{
-    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(argv)
-    char **argv;
-{
-    ipxcp_wantoptions[0].accept_network = 1;
-    ipxcp_allowoptions[0].accept_network = 1;
-    return 1;
-}
-
-static int
-setipxalcl(argv)
-    char **argv;
-{
-    ipxcp_wantoptions[0].accept_local = 1;
-    ipxcp_allowoptions[0].accept_local = 1;
-    return 1;
-}
 
+/*
+ * setnetmask - set the netmask to be used on the interface.
+ */
 static int
-setipxarmt(argv)
+setnetmask(argv)
     char **argv;
 {
-    ipxcp_wantoptions[0].accept_remote = 1;
-    ipxcp_allowoptions[0].accept_remote = 1;
-    return 1;
-}
-
-static u_char *
-setipxnodevalue(src,dst)
-u_char *src, *dst;
-{
-    int indx;
-    int item;
+    u_int32_t mask, b;
+    int n, ok;
+    char *p, *endp;
 
-    for (;;) {
-        if (!isxdigit (*src))
+    /*
+     * 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;
-       
-       for (indx = 0; indx < 5; ++indx) {
-           dst[indx] <<= 4;
-           dst[indx] |= (dst[indx + 1] >> 4) & 0x0F;
        }
-
-       item = toupper (*src) - '0';
-       if (item > 9)
-           item -= 7;
-
-       dst[5] = (dst[5] << 4) | item;
-       ++src;
+       mask |= b << (n * 8);
+       p = endp;
+       if (*p != '.' || n == 0)
+           break;
+       ++p;
     }
-    return src;
-}
-
-static int
-setipxnode(argv)
-    char **argv;
-{
-    char *end;
-
-    memset (&ipxcp_wantoptions[0].our_node[0], 0, 6);
-    memset (&ipxcp_wantoptions[0].his_node[0], 0, 6);
 
-    end = setipxnodevalue (*argv, &ipxcp_wantoptions[0].our_node[0]);
-    if (*end == ':')
-       end = setipxnodevalue (++end, &ipxcp_wantoptions[0].his_node[0]);
+    mask = htonl(mask);
 
-    if (*end == '\0') {
-        ipxcp_wantoptions[0].neg_node = 1;
-        return 1;
+    if (*p != 0 || (netmask & ~mask) != 0) {
+       option_error("invalid netmask value '%s'", *argv);
+       return 0;
     }
 
-    option_error("invalid parameter '%s' for ipx-node option", *argv);
-    return 0;
-}
-
-static int
-setipxproto(argv)
-    char **argv;
-{
-    ipxcp_protent.enabled_flag = 1;
-    return 1;
-}
-
-static int
-resetipxproto(argv)
-    char **argv;
-{
-    ipxcp_protent.enabled_flag = 0;
-    return 1;
+    netmask = mask;
+    return (1);
 }
-#else
 
 static int
-resetipxproto(argv)
+setxonxoff(argv)
     char **argv;
 {
-    return 1;
-}
-#endif /* IPX_CHANGE */
+    lcp_wantoptions[0].asyncmap |= 0x000A0000; /* escape ^S and ^Q */
+    lcp_wantoptions[0].neg_asyncmap = 1;
 
-#ifdef MSLANMAN
-static int
-setmslanman(argv)
-    char **argv;
-{
-    ms_lanman = 1;
+    crtscts = -2;
     return (1);
 }
-#endif
index 3a0a634cf3ce54e950e63e125e85201541ab4a08..8be0a2ee477a5cf9b3ea8d1e51eb4cb2da26d9f0 100644 (file)
@@ -1,6 +1,6 @@
-/* $Id: patchlevel.h,v 1.33 1998/05/04 06:10:31 paulus Exp $ */
-#define        PATCHLEVEL      5
+/* $Id: patchlevel.h,v 1.34 1998/11/07 06:59:29 paulus Exp $ */
+#define        PATCHLEVEL      0
 
-#define VERSION                "2.3"
-#define IMPLEMENTATION ""
-#define DATE           "4 May 1998"
+#define VERSION                "2.4"
+#define IMPLEMENTATION "alpha"
+#define DATE           "7 June 1998"
index f69380e2fb2f0b180c2b67eba9502738b63cdc93..6e039f954d7ef4733a48cd23750f1e9e50eaefbb 100644 (file)
@@ -1,5 +1,5 @@
 .\" manual page [] for pppd 2.3
-.\" $Id: pppd.8,v 1.29 1998/09/13 23:38:49 paulus Exp $
+.\" $Id: pppd.8,v 1.30 1998/11/07 06:59:29 paulus Exp $
 .\" SH section heading
 .\" SS subsection heading
 .\" LP paragraph
@@ -98,7 +98,7 @@ data on the serial port.  If neither the \fIcrtscts\fR, the
 is given, the hardware flow control setting for the serial port is
 left unchanged.
 Some serial ports (such as Macintosh serial ports) lack a true
-RTS output. Such serial ports use this mode to impliment
+RTS output. Such serial ports use this mode to implement
 unidirectional flow control. The serial port will
 suspend transmission when requested by the modem (via CTS)
 but will be unable to request the modem stop sending to the
@@ -112,8 +112,8 @@ the \fInocrtscts\fR, the \fIcdtrcts\fR nor the \fInocdtrcts\fR
 option is given, the hardware flow control setting for the serial
 port is left unchanged.
 Some serial ports (such as Macintosh serial ports) lack a true
-RTS output. Such serial ports use this mode to impliment true
-bi-directional flow control. The sacrafice is that this flow
+RTS output. Such serial ports use this mode to implement true
+bi-directional flow control. The sacrifice is that this flow
 control mode does not permit using DTR as a modem control line.
 .TP
 .B defaultroute
index b021a9a0849d98faf14d2802adcfb54bf3025e95..6924cb7d71f8ad72504281714fdf9afc33702d06 100644 (file)
@@ -16,7 +16,7 @@
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- * $Id: pppd.h,v 1.22 1998/05/13 05:49:21 paulus Exp $
+ * $Id: pppd.h,v 1.23 1998/11/07 06:59:29 paulus Exp $
  */
 
 /*
 #define MAXNAMELEN     256     /* max length of hostname or name for auth */
 #define MAXSECRETLEN   256     /* max length of password or secret */
 
+/*
+ * Option descriptor structure.
+ */
+
+typedef unsigned char  bool;
+
+enum opt_type {
+       o_special_noarg = 0,
+       o_special = 1,
+       o_bool,
+       o_int,
+       o_uint32,
+       o_string,
+};
+
+typedef struct {
+       char    *name;          /* name of the option */
+       enum opt_type type;
+       void    *addr;
+       char    *description;
+       int     flags;
+       void    *addr2;
+       int     upper_limit;
+       int     lower_limit;
+} option_t;
+
+/* Values for flags */
+#define OPT_VALUE      0xff    /* mask for presupplied value */
+#define OPT_HEX                0x100   /* int option is in hex */
+#define OPT_NOARG      0x200   /* option doesn't take argument */
+#define OPT_OR         0x400   /* OR in argument to value */
+#define OPT_INC                0x800   /* increment value */
+#define OPT_PRIV       0x1000  /* privileged option */
+#define OPT_STATIC     0x2000  /* string option goes into static array */
+#define OPT_LLIMIT     0x4000  /* check value against lower limit */
+#define OPT_ULIMIT     0x8000  /* check value against upper limit */
+#define OPT_LIMITS     (OPT_LLIMIT|OPT_ULIMIT)
+#define OPT_ZEROOK     0x10000 /* 0 value is OK even if not within limits */
+#define OPT_NOINCR     0x20000 /* value mustn't be increased */
+#define OPT_ZEROINF    0x40000 /* with OPT_NOINCR, 0 == infinity */
+#define OPT_A2INFO     0x100000 /* addr2 -> option_info to update */
+#define OPT_A2COPY     0x200000 /* addr2 -> second location to rcv value */
+#define OPT_ENABLE     0x400000 /* use *addr2 as enable for option */
+
+#define OPT_VAL(x)     ((x) & OPT_VALUE)
+
 /*
  * Global variables.
  */
@@ -80,43 +126,40 @@ extern int kdebugflag;     /* Tell kernel to print debug messages */
 extern int     default_device; /* Using /dev/tty or equivalent */
 extern char    devnam[];       /* Device name */
 extern int     crtscts;        /* Use hardware flow control */
-extern int     modem;          /* Use modem control lines */
+extern bool    modem;          /* Use modem control lines */
 extern int     inspeed;        /* Input/Output speed requested */
 extern u_int32_t netmask;      /* IP netmask to set on interface */
-extern int     lockflag;       /* Create lock file to lock the serial dev */
-extern int     nodetach;       /* Don't detach from controlling tty */
+extern bool    lockflag;       /* Create lock file to lock the serial dev */
+extern bool    nodetach;       /* Don't detach from controlling tty */
+extern bool    updetach;       /* Detach from controlling tty when link up */
 extern char    *connector;     /* Script to establish physical link */
 extern char    *disconnector;  /* Script to disestablish physical link */
 extern char    *welcomer;      /* Script to welcome client after connection */
 extern int     maxconnect;     /* Maximum connect time (seconds) */
 extern char    user[];         /* Our name for authenticating ourselves */
 extern char    passwd[];       /* Password for PAP */
-extern int     auth_required;  /* Peer is required to authenticate */
-extern int     proxyarp;       /* Set up proxy ARP entry for peer */
-extern int     persist;        /* Reopen link after it goes down */
-extern int     uselogin;       /* Use /etc/passwd for checking PAP */
-extern int     lcp_echo_interval; /* Interval between LCP echo-requests */
-extern int     lcp_echo_fails; /* Tolerance to unanswered echo-requests */
+extern bool    auth_required;  /* Peer is required to authenticate */
+extern bool    persist;        /* Reopen link after it goes down */
+extern bool    uselogin;       /* Use /etc/passwd for checking PAP */
 extern char    our_name[];     /* Our name for authentication purposes */
 extern char    remote_name[];  /* Peer's name for authentication */
 extern int     explicit_remote;/* remote_name specified with remotename opt */
-extern int     usehostname;    /* Use hostname for our_name */
-extern int     disable_defaultip; /* Don't use hostname for default IP adrs */
-extern int     demand;         /* Do dial-on-demand */
+extern bool    demand;         /* Do dial-on-demand */
 extern char    *ipparam;       /* Extra parameter for ip up/down scripts */
-extern int     cryptpap;       /* Others' PAP passwords are encrypted */
+extern bool    cryptpap;       /* Others' PAP passwords are encrypted */
 extern int     idle_time_limit;/* Shut down link if idle for this long */
 extern int     holdoff;        /* Dead time before restarting */
-extern int     refuse_pap;     /* Don't wanna auth. ourselves with PAP */
-extern int     refuse_chap;    /* Don't wanna auth. ourselves with CHAP */
 #ifdef PPP_FILTER
 extern struct  bpf_program pass_filter;   /* Filter for pkts to pass */
 extern struct  bpf_program active_filter; /* Filter for link-active pkts */
 #endif
 
+char *current_option;          /* the name of the option being parsed */
+int  privileged_option;                /* set iff the current option came from root */
+char *option_source;           /* string saying where the option came from */
 
 #ifdef MSLANMAN
-extern int     ms_lanman;      /* Nonzero if use LanMan password instead of NT */
+extern bool    ms_lanman;      /* Use LanMan password instead of NT */
                                /* Has meaning only with MS-CHAP challenges */
 #endif
 
@@ -159,8 +202,9 @@ struct protent {
                          void *arg));
     /* Process a received data packet */
     void (*datainput) __P((int unit, u_char *pkt, int len));
-    int  enabled_flag;         /* 0 iff protocol is disabled */
+    bool enabled_flag;         /* 0 iff protocol is disabled */
     char *name;                        /* Text name of protocol */
+    option_t *options;         /* List of command-line options */
     /* Check requested options, assign defaults */
     void (*check_options) __P((void));
     /* Configure interface for demand-dial */
@@ -185,7 +229,8 @@ void timeout __P((void (*func)(void *), void *arg, int t));
                                /* Call func(arg) after t seconds */
 void untimeout __P((void (*func)(void *), void *arg));
                                /* Cancel call to func(arg) */
-int run_program __P((char *prog, char **args, int must_exist));
+pid_t run_program __P((char *prog, char **args, int must_exist,
+                      void (*done)(void *), void *arg));
                                /* Run program prog with args in child */
 void demuxprotrej __P((int, int));
                                /* Demultiplex a Protocol-Reject */
@@ -242,7 +287,7 @@ int  loop_frame __P((unsigned char *, int)); /* process frame from loopback */
 /* Procedures exported from sys-*.c */
 void sys_init __P((void));     /* Do system-dependent initialization */
 void sys_cleanup __P((void));  /* Restore system state before exiting */
-void sys_check_options __P((void)); /* Check options specified */
+int  sys_check_options __P((void)); /* Check options specified */
 void sys_close __P((void));    /* Clean up in a child before execing */
 int  ppp_available __P((void));        /* Test whether ppp kernel support exists */
 void open_ppp_loopback __P((void)); /* Open loopback for demand-dialling */
@@ -299,6 +344,8 @@ int  daemon __P((int, int));        /* Detach us from terminal session */
 void logwtmp __P((const char *, const char *, const char *));
                                /* Write entry to wtmp file */
 int  get_host_seed __P((void));        /* Get host-dependent random number seed */
+int  have_route_to __P((u_int32_t)); /* Check if route to addr exists */
+void hangup_modem __P((int));  /* Make modem hang up */
 #ifdef PPP_FILTER
 int  set_filters __P((struct bpf_program *pass, struct bpf_program *active));
                                /* Set filter programs in kernel */
@@ -323,6 +370,10 @@ int  getword __P((FILE *f, char *word, int *newlinep, char *filename));
                                /* Read a word from a file */
 void option_error __P((char *fmt, ...));
                                /* Print an error message about an option */
+int number_option __P((char *, u_int32_t *, int));
+                               /* Parse a numerical option */
+int int_option __P((char *, int *));
+                               /* Simplified number_option for decimal ints */
 
 /*
  * This structure is used to store information about certain
index 8ab5a12d5ec29d5acb976bb66c033bcd03735d5e..e0c790e298d66b10f98e32656f91ce6eaa6b8ee4 100644 (file)
@@ -20,7 +20,7 @@
  */
 
 #ifndef lint
-static char rcsid[] = "$Id: sys-NeXT.c,v 1.9 1998/03/25 02:17:23 paulus Exp $";
+static char rcsid[] = "$Id: sys-NeXT.c,v 1.10 1998/11/07 06:59:30 paulus Exp $";
 #endif
 
 #include <stdio.h>
@@ -1636,17 +1636,18 @@ get_host_seed()
 /*
  * sys_check_options - check the options that the user specified
  */
-void
+int
 sys_check_options()
 {
   /*
    * We don't support demand dialing yet.
    */
-  if(demand)
+  if (demand)
     {
       syslog(LOG_WARNING, "PPP-2.3 for NeXTSTEP does not yet support demand dialing\n");
-      demand = 0;
+      return 0;
     }
+  return 1;
 }
 
 
index 88d22848272ab7461254e38348e16b513ad64f44..4239d0fc8dc2628f0dfda3b2cfd85e585eb77a19 100644 (file)
@@ -21,7 +21,7 @@
  */
 
 #ifndef lint
-static char rcsid[] = "$Id: sys-bsd.c,v 1.33 1998/09/04 18:49:16 christos Exp $";
+static char rcsid[] = "$Id: sys-bsd.c,v 1.34 1998/11/07 06:59:30 paulus Exp $";
 /*     $NetBSD: sys-bsd.c,v 1.1.1.3 1997/09/26 18:53:04 christos Exp $ */
 #endif
 
@@ -159,9 +159,16 @@ sys_close()
 /*
  * sys_check_options - check the options that the user specified
  */
-void
+int
 sys_check_options()
 {
+#ifndef CDTRCTS
+    if (crtscts == 2) {
+       syslog(LOG_WARNING, "DTR/CTS flow control is not supported on this system");
+       return 0;
+    }
+#endif
+    return 1;
 }
 
 /*
@@ -389,9 +396,6 @@ set_up_tty(fd, local)
         if (crtscts == 2) {
 #ifdef CDTRCTS
             tios.c_cflag |= CDTRCTS;
-#else
-           syslog(LOG_ERR, "System does not support DTR/CTS flow control");
-           die(1);
 #endif
        } else
            tios.c_cflag |= CRTSCTS;
index 29aa77fef300b9d3ef69334848723bb359825452..280ce890b1db45d2a422db65f0f77f067b61c15f 100644 (file)
@@ -165,8 +165,8 @@ extern int hungup;
 #endif
 
 static void set_ppp_fd (int new_fd)
-{    
-       SYSDEBUG ((LOG_DEBUG, "setting ppp_fd to %d\n", ppp_fd));
+{
+       SYSDEBUG ((LOG_DEBUG, "setting ppp_fd to %d\n", new_fd));
        ppp_fd = new_fd;
 }
 
@@ -659,11 +659,12 @@ static int baud_rate_of (int speed)
  * regardless of whether the modem option was specified.
  */
 
-void set_up_tty (int tty_fd, int local)
+void set_up_tty(int tty_fd, int local)
   {
     int speed;
     struct termios tios;
-    
+
+    setdtr(tty_fd, 1);
     if (tcgetattr(tty_fd, &tios) < 0)
       {
        syslog(LOG_ERR, "tcgetattr: %m(%d)", errno);
@@ -740,6 +741,14 @@ void set_up_tty (int tty_fd, int local)
     restore_term = TRUE;
   }
 
+/*
+ * hangup_modem - hang up the modem by clearing DTR.
+ */
+void hangup_modem(int ttyfd)
+{
+    setdtr(ttyfd, 0);
+}
+
 /********************************************************************
  *
  * setdtr - control the DTR line on the serial port.
@@ -1096,18 +1105,21 @@ get_idle_time(u, ip)
  */
 
 int ccp_fatal_error (int unit)
-  {
+{
     int x = get_flags();
 
     return x & SC_DC_FERROR;
-  }
+}
 
 /*
  * path_to_route - determine the path to the proc file system data
  */
-
+#define ROUTE_MAX_COLS 12
 FILE *route_fd = (FILE *) 0;
 static char route_buffer [512];
+static int route_dev_col, route_dest_col, route_gw_col;
+static int route_flags_col, route_mask_col;
+static int route_num_cols;
 
 static char *path_to_route (void);
 static int open_route_table (void);
@@ -1120,36 +1132,31 @@ static int read_route_table (struct rtentry *rt);
  */
 
 static int path_to_procfs (void)
-  {
+{
     struct mntent *mntent;
     FILE *fp;
 
-    fp = fopen (MOUNTED, "r");
-    if (fp != 0)
-      {
-       mntent = getmntent (fp);
-        while (mntent != (struct mntent *) 0)
-         {
-           if (strcmp (mntent->mnt_type, MNTTYPE_IGNORE) != 0)
-             {
-               if (strcmp (mntent->mnt_type, "proc") == 0)
-                 {
-                   strncpy (route_buffer, mntent->mnt_dir,
-                            sizeof (route_buffer)-10);
-                   route_buffer [sizeof (route_buffer)-10] = '\0';
-                   fclose (fp);
-                   return 1;
-                 }
-             }
-           mntent = getmntent (fp);
-         }
-       fclose (fp);
-      }
+    fp = fopen(MOUNTED, "r");
+    if (fp == NULL) {
+       /* Default the mount location of /proc */
+       strncpy (route_buffer, "/proc", sizeof (route_buffer)-10);
+       return 1;
+    }
+
+    while ((mntent = getmntent(fp)) != NULL) {
+       if (strcmp(mntent->mnt_type, MNTTYPE_IGNORE) == 0)
+           continue;
+       if (strcmp(mntent->mnt_type, "proc") == 0)
+           break;
+    }
+    fclose (fp);
+    if (mntent == 0)
+       return 0;
 
-    /* Default the mount location of /proc */
-    strncpy (route_buffer, "/proc", sizeof (route_buffer)-10);
+    strncpy(route_buffer, mntent->mnt_dir, sizeof (route_buffer)-10);
+    route_buffer [sizeof (route_buffer)-10] = '\0';
     return 1;
-  }
+}
 
 /********************************************************************
  *
@@ -1157,15 +1164,14 @@ static int path_to_procfs (void)
  */
 
 static char *path_to_route (void)
-  {
-    if (! path_to_procfs())
-      {
+{
+    if (!path_to_procfs()) {
        syslog (LOG_ERR, "proc file system not mounted");
        return 0;
-      }
+    }
     strcat (route_buffer, "/net/route");
     return (route_buffer);
-  }
+}
 
 /********************************************************************
  *
@@ -1173,89 +1179,107 @@ static char *path_to_route (void)
  */
 
 static void close_route_table (void)
-  {
-    if (route_fd != (FILE *) 0)
-      {
+{
+    if (route_fd != (FILE *) 0) {
         fclose (route_fd);
         route_fd = (FILE *) 0;
-      }
-  }
+    }
+}
 
 /********************************************************************
  *
  * open_route_table - open the interface to the route table
  */
+static char route_delims[] = " \t\n";
 
 static int open_route_table (void)
-  {
+{
     char *path;
 
     close_route_table();
 
     path = path_to_route();
     if (path == NULL)
-      {
         return 0;
-      }
 
     route_fd = fopen (path, "r");
-    if (route_fd == (FILE *) 0)
-      {
-        syslog (LOG_ERR, "can not open %s: %m(%d)", path, errno);
+    if (route_fd == NULL) {
+        syslog (LOG_ERR, "can't open %s: %m (%d)", path, errno);
         return 0;
-      }
+    }
+
+    route_dev_col = 0;         /* default to usual columns */
+    route_dest_col = 1;
+    route_gw_col = 2;
+    route_flags_col = 3;
+    route_mask_col = 7;
+    route_num_cols = 8;
+
+    /* parse header line */
+    if (fgets(route_buffer, sizeof(route_buffer), route_fd) != 0) {
+       char *p = route_buffer, *q;
+       int col;
+       for (col = 0; col < ROUTE_MAX_COLS; ++col) {
+           int used = 1;
+           if ((q = strtok(p, route_delims)) == 0)
+               break;
+           if (strcasecmp(q, "iface") == 0)
+               route_dev_col = col;
+           else if (strcasecmp(q, "destination") == 0)
+               route_dest_col = col;
+           else if (strcasecmp(q, "gateway") == 0)
+               route_gw_col = col;
+           else if (strcasecmp(q, "flags") == 0)
+               route_flags_col = col;
+           else if (strcasecmp(q, "mask") == 0)
+               route_mask_col = col;
+           else
+               used = 0;
+           if (used && col >= route_num_cols)
+               route_num_cols = col + 1;
+           p = NULL;
+       }
+    }
+
     return 1;
-  }
+}
 
 /********************************************************************
  *
  * read_route_table - read the next entry from the route table
  */
 
-static int read_route_table (struct rtentry *rt)
-  {
-    static char delims[] = " \t\n";
-    char *dev_ptr, *dst_ptr, *gw_ptr, *flag_ptr;
+static int read_route_table(struct rtentry *rt)
+{
+    char *cols[ROUTE_MAX_COLS], *p;
+    int col;
        
     memset (rt, '\0', sizeof (struct rtentry));
 
-    for (;;)
-      {
-       if (fgets (route_buffer, sizeof (route_buffer), route_fd) ==
-           (char *) 0)
-         {
-           return 0;
-         }
+    if (fgets (route_buffer, sizeof (route_buffer), route_fd) == (char *) 0)
+       return 0;
 
-       dev_ptr  = strtok (route_buffer, delims); /* interface name */
-       dst_ptr  = strtok (NULL,         delims); /* destination address */
-       gw_ptr   = strtok (NULL,         delims); /* gateway */
-       flag_ptr = strtok (NULL,         delims); /* flags */
-    
-       if (flag_ptr == (char *) 0) /* assume that we failed, somewhere. */
-         {
-           return 0;
-         }
-       
-       /* Discard that stupid header line which should never
-        * have been there in the first place !! */
-       if (isxdigit (*dst_ptr) && isxdigit (*gw_ptr) && isxdigit (*flag_ptr))
-         {
-           break;
-         }
-      }
+    p = route_buffer;
+    for (col = 0; col < route_num_cols; ++col) {
+       cols[col] = strtok(p, route_delims);
+       if (cols[col] == NULL)
+           return 0;           /* didn't get enough columns */
+    }
 
     ((struct sockaddr_in *) &rt->rt_dst)->sin_addr.s_addr =
-      strtoul (dst_ptr, NULL, 16);
+       strtoul(cols[route_dest_col], NULL, 16);
 
     ((struct sockaddr_in *) &rt->rt_gateway)->sin_addr.s_addr =
-      strtoul (gw_ptr, NULL, 16);
+       strtoul(cols[route_gw_col], NULL, 16);
+
+    ((struct sockaddr_in *) &rt->rt_genmask)->sin_addr.s_addr =
+       strtoul(cols[route_mask_col], NULL, 16);
 
-    rt->rt_flags = (short) strtoul (flag_ptr, NULL, 16);
-    rt->rt_dev   = dev_ptr;
+    rt->rt_flags = (short) strtoul(cols[route_flags_col], NULL, 16);
+    rt->rt_dev   = cols[route_dev_col];
 
     return 1;
-  }
+}
 
 /********************************************************************
  *
@@ -1263,31 +1287,51 @@ static int read_route_table (struct rtentry *rt)
  */
 
 static int defaultroute_exists (struct rtentry *rt)
-  {
-    int    result = 0;
+{
+    int result = 0;
 
     if (!open_route_table())
-      {
         return 0;
-      }
 
-    while (read_route_table(rt) != 0)
-      {
+    while (read_route_table(rt) != 0) {
         if ((rt->rt_flags & RTF_UP) == 0)
-         {
            continue;
-         }
 
-        if (((struct sockaddr_in *) (&rt->rt_dst))->sin_addr.s_addr == 0L)
-         {
+        if (((struct sockaddr_in *) (&rt->rt_dst))->sin_addr.s_addr == 0L) {
            result = 1;
            break;
-         }
-      }
+       }
+    }
 
     close_route_table();
     return result;
-  }
+}
+
+/*
+ * have_route_to - determine if the system has any route to
+ * a given IP address.
+ */
+int have_route_to(u_int32_t addr)
+{
+    struct rtentry rt;
+    int result = 0;
+
+    if (!open_route_table())
+       return -1;              /* don't know */
+
+    while (read_route_table(&rt)) {
+       if ((rt.rt_flags & RTF_UP) == 0)
+           continue;
+       if ((addr & ((struct sockaddr_in *)&rt.rt_genmask)->sin_addr.s_addr)
+           == ((struct sockaddr_in *)&rt.rt_genmask)->sin_addr.s_addr) {
+           result = 1;
+           break;
+       }
+    }
+
+    close_route_table();
+    return result;
+}
 
 /********************************************************************
  *
@@ -1298,7 +1342,7 @@ int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway)
   {
     struct rtentry rt;
 
-    if (defaultroute_exists(&rt))
+    if (defaultroute_exists(&rt) && strcmp(rt.rt_dev, ifname) != 0)
       {
        struct in_addr old_gateway =
          ((struct sockaddr_in *) (&rt.rt_gateway))-> sin_addr;
@@ -1307,8 +1351,7 @@ int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway)
          {
            syslog (LOG_ERR,
                    "not replacing existing default route to %s [%s]",
-                   rt.rt_dev,
-                   inet_ntoa (old_gateway));
+                   rt.rt_dev, inet_ntoa (old_gateway));
          }
        return 0;
       }
@@ -1830,7 +1873,7 @@ int ppp_available(void)
            }
       
            /* The modification levels must be legal */
-           if (driver_modification < my_modification)
+           if (driver_modification < 3)
            {
                if (driver_modification >= 2) {
                    /* we can cope with 2.2.0 and above */
@@ -2615,7 +2658,7 @@ get_host_seed()
  * sys_check_options - check the options that the user specified
  */
 
-void
+int
 sys_check_options(void)
   {
 #ifdef IPX_CHANGE
@@ -2644,6 +2687,7 @@ sys_check_options(void)
       option_error("demand dialling is not supported by kernel driver version "
                   "%d.%d.%d", driver_version, driver_modification,
                   driver_patch);
-      demand = 0;
+      return 0;
     }
+    return 1;
   }
index d1b82200e467fbab78bf64bc75c1b6738497172d..93070e558ccb2c02c843781af1a6ca6b6d61b98b 100644 (file)
@@ -26,7 +26,7 @@
  */
 
 #ifndef lint
-static char rcsid[] = "$Id: sys-osf.c,v 1.13 1998/03/25 02:19:27 paulus Exp $";
+static char rcsid[] = "$Id: sys-osf.c,v 1.14 1998/11/07 06:59:31 paulus Exp $";
 #endif
 
 #include <stdio.h>
@@ -202,9 +202,10 @@ sys_close()
 /*
  * sys_check_options - check the options that the user specified
  */
-void
+int
 sys_check_options()
 {
+    return 1;
 }
 
 
index a9d970ec91c44e1daef2d3b8083156ed29c8e3e9..ac24eb184364cf2c73b13123b08e44dcd103f5e1 100644 (file)
@@ -26,7 +26,7 @@
  */
 
 #ifndef lint
-static char rcsid[] = "$Id: sys-sunos4.c,v 1.9 1998/03/25 02:19:29 paulus Exp $";
+static char rcsid[] = "$Id: sys-sunos4.c,v 1.10 1998/11/07 06:59:31 paulus Exp $";
 #endif
 
 #include <stdio.h>
@@ -206,9 +206,10 @@ sys_close()
 /*
  * sys_check_options - check the options that the user specified
  */
-void
+int
 sys_check_options()
 {
+    return 1;
 }
 
 
index 01a377723cbc69d752681f8ff5b5815b3ffc065f..246712d7c8740d55cc18984b13fde67f5c4a97ba 100644 (file)
@@ -26,7 +26,7 @@
  */
 
 #ifndef lint
-static char rcsid[] = "$Id: sys-svr4.c,v 1.17 1998/03/25 02:19:31 paulus Exp $";
+static char rcsid[] = "$Id: sys-svr4.c,v 1.18 1998/11/07 06:59:31 paulus Exp $";
 #endif
 
 #include <limits.h>
@@ -219,9 +219,10 @@ sys_close()
 /*
  * sys_check_options - check the options that the user specified
  */
-void
+int
 sys_check_options()
 {
+    return 1;
 }
 
 
index d956be4ba4339d542fdefe69606a5e41f2151fa6..691b38695e8dcee8a52ba9ccce153cbf911cf527 100644 (file)
@@ -21,7 +21,7 @@
  */
 
 #ifndef lint
-static char rcsid[] = "$Id: sys-ultrix.c,v 1.22 1998/03/25 03:09:12 paulus Exp $";
+static char rcsid[] = "$Id: sys-ultrix.c,v 1.23 1998/11/07 06:59:32 paulus Exp $";
 #endif
 
 /*
@@ -137,13 +137,14 @@ sys_close()
 /*
  * sys_check_options - check the options that the user specified
  */
-void
+int
 sys_check_options()
 {
     if (demand) {
        option_error("Sorry - demand-dialling is not supported under Ultrix\n");
-       exit(1);
+       return 0;
     }
+    return 1;
 }
 
 
index c4ffb401cedc8154cd44ec0e0c767bdb5b75ae6e..3b025e06c91407555821a1da245ef906325b2eb5 100644 (file)
@@ -18,7 +18,7 @@
  */
 
 #ifndef lint
-static char rcsid[] = "$Id: upap.c,v 1.11 1997/04/30 05:59:56 paulus Exp $";
+static char rcsid[] = "$Id: upap.c,v 1.12 1998/11/07 06:59:32 paulus Exp $";
 #endif
 
 /*
@@ -34,6 +34,19 @@ static char rcsid[] = "$Id: upap.c,v 1.11 1997/04/30 05:59:56 paulus Exp $";
 #include "pppd.h"
 #include "upap.h"
 
+/*
+ * Command-line options.
+ */
+static option_t pap_option_list[] = {
+    { "pap-restart", o_int, &upap[0].us_timeouttime,
+      "Set retransmit timeout for PAP" },
+    { "pap-max-authreq", o_int, &upap[0].us_maxtransmits,
+      "Set max #xmits for auth-reqs" },
+    { "pap-timeout", o_int, &upap[0].us_reqtimeout,
+      "Set time limit for peer PAP auth." },
+    { NULL }
+};
+
 /*
  * Protocol entry points.
  */
@@ -58,6 +71,7 @@ struct protent pap_protent = {
     NULL,
     1,
     "PAP",
+    pap_option_list,
     NULL,
     NULL,
     NULL