]> git.ozlabs.org Git - ppp.git/blobdiff - pppd/ccp.c
typo
[ppp.git] / pppd / ccp.c
index f4d00eb031e05bff8786ed600057e6902ef423ff..d6da2d56923fe8493eaa7aee6dabf90d3ceb3c3e 100644 (file)
  * OR MODIFICATIONS.
  */
 
-#ifndef lint
-static char rcsid[] = "$Id: ccp.c,v 1.18 1996/09/14 05:14:36 paulus Exp $";
-#endif
+#define RCSID  "$Id: ccp.c,v 1.29 1999/08/13 06:46:11 paulus Exp $"
 
+#include <stdlib.h>
 #include <string.h>
-#include <syslog.h>
-#include <sys/ioctl.h>
-#include <net/ppp-comp.h>
 
 #include "pppd.h"
 #include "fsm.h"
 #include "ccp.h"
+#include <net/ppp-comp.h>
+
+static const char rcsid[] = RCSID;
+
+/*
+ * 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.
@@ -66,6 +107,8 @@ struct protent ccp_protent = {
     ccp_datainput,
     1,
     "CCP",
+    "Compressed",
+    ccp_option_list,
     NULL,
     NULL,
     NULL
@@ -90,7 +133,7 @@ static int  ccp_reqci __P((fsm *, u_char *, int *, int));
 static void ccp_up __P((fsm *));
 static void ccp_down __P((fsm *));
 static int  ccp_extcode __P((fsm *, int, int, u_char *, int));
-static void ccp_rack_timeout __P(());
+static void ccp_rack_timeout __P((void *));
 static char *method_name __P((ccp_options *, ccp_options *));
 
 static fsm_callbacks ccp_callbacks = {
@@ -128,6 +171,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.
  */
@@ -149,8 +269,12 @@ ccp_init(unit)
 
     ccp_wantoptions[0].deflate = 1;
     ccp_wantoptions[0].deflate_size = DEFLATE_MAX_SIZE;
+    ccp_wantoptions[0].deflate_correct = 1;
+    ccp_wantoptions[0].deflate_draft = 1;
     ccp_allowoptions[0].deflate = 1;
     ccp_allowoptions[0].deflate_size = DEFLATE_MAX_SIZE;
+    ccp_allowoptions[0].deflate_correct = 1;
+    ccp_allowoptions[0].deflate_draft = 1;
 
     ccp_wantoptions[0].bsd_compress = 1;
     ccp_wantoptions[0].bsd_bits = BSD_MAX_BITS;
@@ -163,7 +287,7 @@ ccp_init(unit)
 /*
  * ccp_open - CCP is allowed to come up.
  */
-void
+static void
 ccp_open(unit)
     int unit;
 {
@@ -233,7 +357,7 @@ ccp_input(unit, p, len)
     oldstate = f->state;
     fsm_input(f, p, len);
     if (oldstate == OPENED && p[0] == TERMREQ && f->state != OPENED)
-       syslog(LOG_NOTICE, "Compression disabled by peer.");
+       notice("Compression disabled by peer.");
 
     /*
      * If we get a terminate-ack and we're not asking for compression,
@@ -266,7 +390,7 @@ ccp_extcode(f, code, id, p, len)
     case CCP_RESETACK:
        if (ccp_localstate[f->unit] & RACK_PENDING && id == f->reqid) {
            ccp_localstate[f->unit] &= ~(RACK_PENDING | RREQ_REPEAT);
-           UNTIMEOUT(ccp_rack_timeout, (caddr_t) f);
+           UNTIMEOUT(ccp_rack_timeout, f);
        }
        break;
 
@@ -313,11 +437,23 @@ ccp_resetci(f)
            go->bsd_compress = 0;
     }
     if (go->deflate) {
-       opt_buf[0] = CI_DEFLATE;
-       opt_buf[1] = CILEN_DEFLATE;
-       opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_SIZE);
-       opt_buf[3] = DEFLATE_CHK_SEQUENCE;
-       if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0)
+       if (go->deflate_correct) {
+           opt_buf[0] = CI_DEFLATE;
+           opt_buf[1] = CILEN_DEFLATE;
+           opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_SIZE);
+           opt_buf[3] = DEFLATE_CHK_SEQUENCE;
+           if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0)
+               go->deflate_correct = 0;
+       }
+       if (go->deflate_draft) {
+           opt_buf[0] = CI_DEFLATE_DRAFT;
+           opt_buf[1] = CILEN_DEFLATE;
+           opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_SIZE);
+           opt_buf[3] = DEFLATE_CHK_SEQUENCE;
+           if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0)
+               go->deflate_draft = 0;
+       }
+       if (!go->deflate_correct && !go->deflate_draft)
            go->deflate = 0;
     }
     if (go->predictor_1) {
@@ -368,7 +504,7 @@ ccp_addci(f, p, lenp)
      * in case it gets Acked.
      */
     if (go->deflate) {
-       p[0] = CI_DEFLATE;
+       p[0] = go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT;
        p[1] = CILEN_DEFLATE;
        p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
        p[3] = DEFLATE_CHK_SEQUENCE;
@@ -385,6 +521,13 @@ ccp_addci(f, p, lenp)
            --go->deflate_size;
            p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
        }
+       if (p != p0 && go->deflate_correct && go->deflate_draft) {
+           p[0] = CI_DEFLATE_DRAFT;
+           p[1] = CILEN_DEFLATE;
+           p[2] = p[2 - CILEN_DEFLATE];
+           p[3] = DEFLATE_CHK_SEQUENCE;
+           p += CILEN_DEFLATE;
+       }
     }
     if (go->bsd_compress) {
        p[0] = CI_BSD_COMPRESS;
@@ -448,7 +591,8 @@ ccp_ackci(f, p, len)
 
     if (go->deflate) {
        if (len < CILEN_DEFLATE
-           || p[0] != CI_DEFLATE || p[1] != CILEN_DEFLATE
+           || p[0] != (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
+           || p[1] != CILEN_DEFLATE
            || p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
            || p[3] != DEFLATE_CHK_SEQUENCE)
            return 0;
@@ -457,6 +601,16 @@ ccp_ackci(f, p, len)
        /* XXX Cope with first/fast ack */
        if (len == 0)
            return 1;
+       if (go->deflate_correct && go->deflate_draft) {
+           if (len < CILEN_DEFLATE
+               || p[0] != CI_DEFLATE_DRAFT
+               || p[1] != CILEN_DEFLATE
+               || p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
+               || p[3] != DEFLATE_CHK_SEQUENCE)
+               return 0;
+           p += CILEN_DEFLATE;
+           len -= CILEN_DEFLATE;
+       }
     }
     if (go->bsd_compress) {
        if (len < CILEN_BSD_COMPRESS
@@ -513,7 +667,8 @@ ccp_nakci(f, p, len)
     try = *go;
 
     if (go->deflate && len >= CILEN_DEFLATE
-       && p[0] == CI_DEFLATE && p[1] == CILEN_DEFLATE) {
+       && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
+       && p[1] == CILEN_DEFLATE) {
        no.deflate = 1;
        /*
         * Peer wants us to use a different code size or something.
@@ -524,9 +679,15 @@ ccp_nakci(f, p, len)
            || p[3] != DEFLATE_CHK_SEQUENCE)
            try.deflate = 0;
        else if (DEFLATE_SIZE(p[2]) < go->deflate_size)
-           go->deflate_size = DEFLATE_SIZE(p[2]);
+           try.deflate_size = DEFLATE_SIZE(p[2]);
        p += CILEN_DEFLATE;
        len -= CILEN_DEFLATE;
+       if (go->deflate_correct && go->deflate_draft
+           && len >= CILEN_DEFLATE && p[0] == CI_DEFLATE_DRAFT
+           && p[1] == CILEN_DEFLATE) {
+           p += CILEN_DEFLATE;
+           len -= CILEN_DEFLATE;
+       }
     }
 
     if (go->bsd_compress && len >= CILEN_BSD_COMPRESS
@@ -547,12 +708,9 @@ ccp_nakci(f, p, len)
     /*
      * Predictor-1 and 2 have no options, so they can't be Naked.
      *
-     * XXX What should we do with any remaining options?
+     * There may be remaining options but we ignore them.
      */
 
-    if (len != 0)
-       return 0;
-
     if (f->state != OPENED)
        *go = try;
     return 1;
@@ -580,13 +738,29 @@ ccp_rejci(f, p, len)
        return -1;
 
     if (go->deflate && len >= CILEN_DEFLATE
-       && p[0] == CI_DEFLATE && p[1] == CILEN_DEFLATE) {
+       && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
+       && p[1] == CILEN_DEFLATE) {
        if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
            || p[3] != DEFLATE_CHK_SEQUENCE)
            return 0;           /* Rej is bad */
-       try.deflate = 0;
+       if (go->deflate_correct)
+           try.deflate_correct = 0;
+       else
+           try.deflate_draft = 0;
        p += CILEN_DEFLATE;
        len -= CILEN_DEFLATE;
+       if (go->deflate_correct && go->deflate_draft
+           && len >= CILEN_DEFLATE && p[0] == CI_DEFLATE_DRAFT
+           && p[1] == CILEN_DEFLATE) {
+           if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
+               || p[3] != DEFLATE_CHK_SEQUENCE)
+               return 0;               /* Rej is bad */
+           try.deflate_draft = 0;
+           p += CILEN_DEFLATE;
+           len -= CILEN_DEFLATE;
+       }
+       if (!try.deflate_correct && !try.deflate_draft)
+           try.deflate = 0;
     }
     if (go->bsd_compress && len >= CILEN_BSD_COMPRESS
        && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) {
@@ -656,7 +830,10 @@ ccp_reqci(f, p, lenp, dont_nak)
 
            switch (type) {
            case CI_DEFLATE:
-               if (!ao->deflate || clen != CILEN_DEFLATE) {
+           case CI_DEFLATE_DRAFT:
+               if (!ao->deflate || clen != CILEN_DEFLATE
+                   || (!ao->deflate_correct && type == CI_DEFLATE)
+                   || (!ao->deflate_draft && type == CI_DEFLATE_DRAFT)) {
                    newret = CONFREJ;
                    break;
                }
@@ -670,8 +847,9 @@ ccp_reqci(f, p, lenp, dont_nak)
                    if (!dont_nak) {
                        p[2] = DEFLATE_MAKE_OPT(ao->deflate_size);
                        p[3] = DEFLATE_CHK_SEQUENCE;
-                   }
-                   break;
+                       /* fall through to test this #bits below */
+                   } else
+                       break;
                }
 
                /*
@@ -708,9 +886,11 @@ ccp_reqci(f, p, lenp, dont_nak)
                if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION
                    || nb > ao->bsd_bits || nb < BSD_MIN_BITS) {
                    newret = CONFNAK;
-                   if (!dont_nak)
+                   if (!dont_nak) {
                        p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, ao->bsd_bits);
-                   break;
+                       /* fall through to test this #bits below */
+                   } else
+                       break;
                }
 
                /*
@@ -770,7 +950,7 @@ ccp_reqci(f, p, lenp, dont_nak)
 
        if (newret == CONFNAK && dont_nak)
            newret = CONFREJ;
-       if (!(newret == CONFACK || newret == CONFNAK && ret == CONFREJ)) {
+       if (!(newret == CONFACK || (newret == CONFNAK && ret == CONFREJ))) {
            /* we're returning this option */
            if (newret == CONFREJ && ret == CONFNAK)
                retp = p0;
@@ -806,25 +986,30 @@ method_name(opt, opt2)
        return "(none)";
     switch (opt->method) {
     case CI_DEFLATE:
+    case CI_DEFLATE_DRAFT:
        if (opt2 != NULL && opt2->deflate_size != opt->deflate_size)
-           sprintf(result, "Deflate (%d/%d)", opt->deflate_size,
-                   opt2->deflate_size);
+           slprintf(result, sizeof(result), "Deflate%s (%d/%d)",
+                    (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""),
+                    opt->deflate_size, opt2->deflate_size);
        else
-           sprintf(result, "Deflate (%d)", opt->deflate_size);
+           slprintf(result, sizeof(result), "Deflate%s (%d)",
+                    (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""),
+                    opt->deflate_size);
        break;
     case CI_BSD_COMPRESS:
        if (opt2 != NULL && opt2->bsd_bits != opt->bsd_bits)
-           sprintf(result, "BSD-Compress (%d/%d)", opt->bsd_bits,
-                   opt2->bsd_bits);
+           slprintf(result, sizeof(result), "BSD-Compress (%d/%d)",
+                    opt->bsd_bits, opt2->bsd_bits);
        else
-           sprintf(result, "BSD-Compress (%d)", opt->bsd_bits);
+           slprintf(result, sizeof(result), "BSD-Compress (%d)",
+                    opt->bsd_bits);
        break;
     case CI_PREDICTOR_1:
        return "Predictor 1";
     case CI_PREDICTOR_2:
        return "Predictor 2";
     default:
-       sprintf(result, "Method %d", opt->method);
+       slprintf(result, sizeof(result), "Method %d", opt->method);
     }
     return result;
 }
@@ -844,19 +1029,16 @@ ccp_up(f)
     if (ANY_COMPRESS(*go)) {
        if (ANY_COMPRESS(*ho)) {
            if (go->method == ho->method) {
-               syslog(LOG_NOTICE, "%s compression enabled",
-                      method_name(go, ho));
+               notice("%s compression enabled", method_name(go, ho));
            } else {
-               strcpy(method1, method_name(go, NULL));
-               syslog(LOG_NOTICE, "%s / %s compression enabled",
+               strlcpy(method1, method_name(go, NULL), sizeof(method1));
+               notice("%s / %s compression enabled",
                       method1, method_name(ho, NULL));
            }
        } else
-           syslog(LOG_NOTICE, "%s receive compression enabled",
-                  method_name(go, NULL));
+           notice("%s receive compression enabled", method_name(go, NULL));
     } else if (ANY_COMPRESS(*ho))
-       syslog(LOG_NOTICE, "%s transmit compression enabled",
-              method_name(ho, NULL));
+       notice("%s transmit compression enabled", method_name(ho, NULL));
 }
 
 /*
@@ -867,7 +1049,7 @@ ccp_down(f)
     fsm *f;
 {
     if (ccp_localstate[f->unit] & RACK_PENDING)
-       UNTIMEOUT(ccp_rack_timeout, (caddr_t) f);
+       UNTIMEOUT(ccp_rack_timeout, f);
     ccp_localstate[f->unit] = 0;
     ccp_flags_set(f->unit, 1, 0);
 }
@@ -927,8 +1109,11 @@ ccp_printpkt(p, plen, printer, arg)
            optend = p + optlen;
            switch (code) {
            case CI_DEFLATE:
+           case CI_DEFLATE_DRAFT:
                if (optlen >= CILEN_DEFLATE) {
-                   printer(arg, "deflate %d", DEFLATE_SIZE(p[2]));
+                   printer(arg, "deflate%s %d",
+                           (code == CI_DEFLATE_DRAFT? "(old#)": ""),
+                           DEFLATE_SIZE(p[2]));
                    if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL)
                        printer(arg, " method %d", DEFLATE_METHOD(p[2]));
                    if (p[3] != DEFLATE_CHK_SEQUENCE)
@@ -991,7 +1176,7 @@ ccp_printpkt(p, plen, printer, arg)
  * decompression; if it was, we take CCP down, thus disabling
  * compression :-(, otherwise we issue the reset-request.
  */
-void
+static void
 ccp_datainput(unit, pkt, len)
     int unit;
     u_char *pkt;
@@ -1005,7 +1190,7 @@ ccp_datainput(unit, pkt, len)
            /*
             * Disable compression by taking CCP down.
             */
-           syslog(LOG_ERR, "Lost compression sync: disabling compression");
+           error("Lost compression sync: disabling compression");
            ccp_close(unit, "Lost compression sync");
        } else {
            /*
@@ -1015,7 +1200,7 @@ ccp_datainput(unit, pkt, len)
             */
            if (!(ccp_localstate[f->unit] & RACK_PENDING)) {
                fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0);
-               TIMEOUT(ccp_rack_timeout, (caddr_t) f, RACKTIMEOUT);
+               TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT);
                ccp_localstate[f->unit] |= RACK_PENDING;
            } else
                ccp_localstate[f->unit] |= RREQ_REPEAT;
@@ -1028,13 +1213,13 @@ ccp_datainput(unit, pkt, len)
  */
 static void
 ccp_rack_timeout(arg)
-    caddr_t arg;
+    void *arg;
 {
-    fsm *f = (fsm *) arg;
+    fsm *f = arg;
 
     if (f->state == OPENED && ccp_localstate[f->unit] & RREQ_REPEAT) {
        fsm_sdata(f, CCP_RESETREQ, f->reqid, NULL, 0);
-       TIMEOUT(ccp_rack_timeout, (caddr_t) f, RACKTIMEOUT);
+       TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT);
        ccp_localstate[f->unit] &= ~RREQ_REPEAT;
     } else
        ccp_localstate[f->unit] &= ~RACK_PENDING;