]> git.ozlabs.org Git - ppp.git/blobdiff - pppd/ccp.c
typo
[ppp.git] / pppd / ccp.c
index d4e3b3c4b093ae5b3faa7c7750fe02f9236969d7..d6da2d56923fe8493eaa7aee6dabf90d3ceb3c3e 100644 (file)
  * OR MODIFICATIONS.
  */
 
-#ifndef lint
-static char rcsid[] = "$Id: ccp.c,v 1.21 1997/05/22 06:45:59 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 <sys/types.h>
-#include <net/ppp_defs.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.
@@ -68,6 +107,8 @@ struct protent ccp_protent = {
     ccp_datainput,
     1,
     "CCP",
+    "Compressed",
+    ccp_option_list,
     NULL,
     NULL,
     NULL
@@ -130,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.
  */
@@ -151,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;
@@ -235,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,
@@ -315,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) {
@@ -370,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;
@@ -387,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;
@@ -450,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;
@@ -459,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
@@ -515,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.
@@ -529,6 +682,12 @@ ccp_nakci(f, p, len)
            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
@@ -549,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;
@@ -582,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) {
@@ -658,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;
                }
@@ -811,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;
 }
@@ -849,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));
 }
 
 /*
@@ -932,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)
@@ -1010,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 {
            /*