X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=pppd%2Fccp.c;h=e6b1c1262c80370b08ad5c189199e10bd2f8e1c9;hp=50cb92ab6e18590453795bc765f23b941048312c;hb=875d9641d05b4fcb7e186f784c801962bb2670e5;hpb=2305ca29c0b59dae6edf23b1d69823013999883a diff --git a/pppd/ccp.c b/pppd/ccp.c index 50cb92a..e6b1c12 100644 --- a/pppd/ccp.c +++ b/pppd/ccp.c @@ -26,19 +26,58 @@ */ #ifndef lint -static char rcsid[] = "$Id: ccp.c,v 1.20 1997/04/30 05:50:40 paulus Exp $"; +static const char rcsid[] = "$Id: ccp.c,v 1.28 1999/08/12 04:25:19 paulus Exp $"; #endif +#include #include -#include -#include -#include -#include -#include #include "pppd.h" #include "fsm.h" #include "ccp.h" +#include + +/* + * 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. @@ -526,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 @@ -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; } @@ -672,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; } /* @@ -710,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; } /* @@ -808,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; } @@ -846,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)); } /* @@ -929,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) @@ -1007,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 { /*