2 * ccp.c - PPP Compression Control Protocol.
4 * Copyright (c) 1994 The Australian National University.
7 * Permission to use, copy, modify, and distribute this software and its
8 * documentation is hereby granted, provided that the above copyright
9 * notice appears in all copies. This software is provided without any
10 * warranty, express or implied. The Australian National University
11 * makes no representations about the suitability of this software for
14 * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
15 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
16 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
17 * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
20 * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
21 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
22 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
23 * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
24 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
29 static char rcsid[] = "$Id: ccp.c,v 1.16 1996/04/04 03:35:37 paulus Exp $";
34 #include <sys/ioctl.h>
35 #include <net/ppp-comp.h>
41 struct protent ccp_protent = {
42 PPP_CCP, ccp_init, ccp_input, ccp_protrej,
43 ccp_lowerup, ccp_lowerdown, ccp_open, ccp_close,
44 ccp_printpkt, ccp_datainput, 1, "CCP", NULL, NULL
48 ccp_options ccp_wantoptions[NUM_PPP]; /* what to request the peer to use */
49 ccp_options ccp_gotoptions[NUM_PPP]; /* what the peer agreed to do */
50 ccp_options ccp_allowoptions[NUM_PPP]; /* what we'll agree to do */
51 ccp_options ccp_hisoptions[NUM_PPP]; /* what we agreed to do */
54 * Callbacks for fsm code.
56 static void ccp_resetci __P((fsm *));
57 static int ccp_cilen __P((fsm *));
58 static void ccp_addci __P((fsm *, u_char *, int *));
59 static int ccp_ackci __P((fsm *, u_char *, int));
60 static int ccp_nakci __P((fsm *, u_char *, int));
61 static int ccp_rejci __P((fsm *, u_char *, int));
62 static int ccp_reqci __P((fsm *, u_char *, int *, int));
63 static void ccp_up __P((fsm *));
64 static void ccp_down __P((fsm *));
65 static int ccp_extcode __P((fsm *, int, int, u_char *, int));
66 static void ccp_rack_timeout __P(());
68 static fsm_callbacks ccp_callbacks = {
87 * Do we want / did we get any compression?
89 #define ANY_COMPRESS(opt) ((opt).deflate || (opt).bsd_compress \
90 || (opt).predictor_1 || (opt).predictor_2)
93 * Local state (mainly for handling reset-reqs and reset-acks).
95 static int ccp_localstate[NUM_PPP];
96 #define RACK_PENDING 1 /* waiting for reset-ack */
97 #define RREQ_REPEAT 2 /* send another reset-req if no reset-ack */
99 #define RACKTIMEOUT 1 /* second */
101 static int all_rejected[NUM_PPP]; /* we rejected all peer's options */
104 * ccp_init - initialize CCP.
110 fsm *f = &ccp_fsm[unit];
113 f->protocol = PPP_CCP;
114 f->callbacks = &ccp_callbacks;
117 memset(&ccp_wantoptions[unit], 0, sizeof(ccp_options));
118 memset(&ccp_gotoptions[unit], 0, sizeof(ccp_options));
119 memset(&ccp_allowoptions[unit], 0, sizeof(ccp_options));
120 memset(&ccp_hisoptions[unit], 0, sizeof(ccp_options));
122 ccp_wantoptions[0].deflate = 1;
123 ccp_wantoptions[0].deflate_size = DEFLATE_MAX_SIZE;
124 ccp_allowoptions[0].deflate = 1;
125 ccp_allowoptions[0].deflate_size = DEFLATE_MAX_SIZE;
127 ccp_wantoptions[0].bsd_compress = 1;
128 ccp_wantoptions[0].bsd_bits = BSD_MAX_BITS;
129 ccp_allowoptions[0].bsd_compress = 1;
130 ccp_allowoptions[0].bsd_bits = BSD_MAX_BITS;
132 ccp_allowoptions[0].predictor_1 = 1;
136 * ccp_open - CCP is allowed to come up.
142 fsm *f = &ccp_fsm[unit];
144 if (f->state != OPENED)
145 ccp_flags_set(unit, 1, 0);
148 * Find out which compressors the kernel supports before
149 * deciding whether to open in silent mode.
152 if (!ANY_COMPRESS(ccp_gotoptions[unit]))
153 f->flags |= OPT_SILENT;
159 * ccp_close - Terminate CCP.
162 ccp_close(unit, reason)
166 ccp_flags_set(unit, 0, 0);
167 fsm_close(&ccp_fsm[unit], reason);
171 * ccp_lowerup - we may now transmit CCP packets.
177 fsm_lowerup(&ccp_fsm[unit]);
181 * ccp_lowerdown - we may not transmit CCP packets.
187 fsm_lowerdown(&ccp_fsm[unit]);
191 * ccp_input - process a received CCP packet.
194 ccp_input(unit, p, len)
199 fsm *f = &ccp_fsm[unit];
203 * Check for a terminate-request so we can print a message.
206 fsm_input(f, p, len);
207 if (oldstate == OPENED && p[0] == TERMREQ && f->state != OPENED)
208 syslog(LOG_NOTICE, "Compression disabled by peer.");
211 * If we get a terminate-ack and we're not asking for compression,
214 if (oldstate == REQSENT && p[0] == TERMACK
215 && !ANY_COMPRESS(ccp_gotoptions[unit]))
216 ccp_close(unit, "No compression negotiated");
220 * Handle a CCP-specific code.
223 ccp_extcode(f, code, id, p, len)
231 if (f->state != OPENED)
233 /* send a reset-ack, which the transmitter will see and
234 reset its compression state. */
235 fsm_sdata(f, CCP_RESETACK, id, NULL, 0);
239 if (ccp_localstate[f->unit] & RACK_PENDING && id == f->reqid) {
240 ccp_localstate[f->unit] &= ~(RACK_PENDING | RREQ_REPEAT);
241 UNTIMEOUT(ccp_rack_timeout, (caddr_t) f);
253 * ccp_protrej - peer doesn't talk CCP.
259 ccp_flags_set(unit, 0, 0);
260 fsm_lowerdown(&ccp_fsm[unit]);
264 * ccp_resetci - initialize at start of negotiation.
270 ccp_options *go = &ccp_gotoptions[f->unit];
273 *go = ccp_wantoptions[f->unit];
274 all_rejected[f->unit] = 0;
277 * Check whether the kernel knows about the various
278 * compression methods we might request.
280 if (go->bsd_compress) {
281 opt_buf[0] = CI_BSD_COMPRESS;
282 opt_buf[1] = CILEN_BSD_COMPRESS;
283 opt_buf[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, BSD_MIN_BITS);
284 if (ccp_test(f->unit, opt_buf, CILEN_BSD_COMPRESS, 0) <= 0)
285 go->bsd_compress = 0;
288 opt_buf[0] = CI_DEFLATE;
289 opt_buf[1] = CILEN_DEFLATE;
290 opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_SIZE);
291 opt_buf[3] = DEFLATE_CHK_SEQUENCE;
292 if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0)
295 if (go->predictor_1) {
296 opt_buf[0] = CI_PREDICTOR_1;
297 opt_buf[1] = CILEN_PREDICTOR_1;
298 if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_1, 0) <= 0)
301 if (go->predictor_2) {
302 opt_buf[0] = CI_PREDICTOR_2;
303 opt_buf[1] = CILEN_PREDICTOR_2;
304 if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_2, 0) <= 0)
310 * ccp_cilen - Return total length of our configuration info.
316 ccp_options *go = &ccp_gotoptions[f->unit];
318 return (go->bsd_compress? CILEN_BSD_COMPRESS: 0)
319 + (go->deflate? CILEN_DEFLATE: 0)
320 + (go->predictor_1? CILEN_PREDICTOR_1: 0)
321 + (go->predictor_2? CILEN_PREDICTOR_2: 0);
325 * ccp_addci - put our requests in a packet.
328 ccp_addci(f, p, lenp)
334 ccp_options *go = &ccp_gotoptions[f->unit];
338 * Add the compression types that we can receive, in decreasing
339 * preference order. Get the kernel to allocate the first one
340 * in case it gets Acked.
344 p[1] = CILEN_DEFLATE;
345 p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
346 p[3] = DEFLATE_CHK_SEQUENCE;
348 res = ccp_test(f->unit, p, CILEN_DEFLATE, 0);
353 if (res < 0 || go->deflate_size <= DEFLATE_MIN_SIZE) {
358 p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
361 if (go->bsd_compress) {
362 p[0] = CI_BSD_COMPRESS;
363 p[1] = CILEN_BSD_COMPRESS;
364 p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
366 p += CILEN_BSD_COMPRESS; /* not the first option */
369 res = ccp_test(f->unit, p, CILEN_BSD_COMPRESS, 0);
371 p += CILEN_BSD_COMPRESS;
374 if (res < 0 || go->bsd_bits <= BSD_MIN_BITS) {
375 go->bsd_compress = 0;
379 p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
383 /* XXX Should Predictor 2 be preferable to Predictor 1? */
384 if (go->predictor_1) {
385 p[0] = CI_PREDICTOR_1;
386 p[1] = CILEN_PREDICTOR_1;
387 if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_1, 0) <= 0) {
390 p += CILEN_PREDICTOR_1;
393 if (go->predictor_2) {
394 p[0] = CI_PREDICTOR_2;
395 p[1] = CILEN_PREDICTOR_2;
396 if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_2, 0) <= 0) {
399 p += CILEN_PREDICTOR_2;
407 * ccp_ackci - process a received configure-ack, and return
408 * 1 iff the packet was OK.
416 ccp_options *go = &ccp_gotoptions[f->unit];
420 if (len < CILEN_DEFLATE
421 || p[0] != CI_DEFLATE || p[1] != CILEN_DEFLATE
422 || p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
423 || p[3] != DEFLATE_CHK_SEQUENCE)
426 len -= CILEN_DEFLATE;
427 /* XXX Cope with first/fast ack */
431 if (go->bsd_compress) {
432 if (len < CILEN_BSD_COMPRESS
433 || p[0] != CI_BSD_COMPRESS || p[1] != CILEN_BSD_COMPRESS
434 || p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits))
436 p += CILEN_BSD_COMPRESS;
437 len -= CILEN_BSD_COMPRESS;
438 /* XXX Cope with first/fast ack */
439 if (p == p0 && len == 0)
442 if (go->predictor_1) {
443 if (len < CILEN_PREDICTOR_1
444 || p[0] != CI_PREDICTOR_1 || p[1] != CILEN_PREDICTOR_1)
446 p += CILEN_PREDICTOR_1;
447 len -= CILEN_PREDICTOR_1;
448 /* XXX Cope with first/fast ack */
449 if (p == p0 && len == 0)
452 if (go->predictor_2) {
453 if (len < CILEN_PREDICTOR_2
454 || p[0] != CI_PREDICTOR_2 || p[1] != CILEN_PREDICTOR_2)
456 p += CILEN_PREDICTOR_2;
457 len -= CILEN_PREDICTOR_2;
458 /* XXX Cope with first/fast ack */
459 if (p == p0 && len == 0)
469 * ccp_nakci - process received configure-nak.
470 * Returns 1 iff the nak was OK.
478 ccp_options *go = &ccp_gotoptions[f->unit];
479 ccp_options no; /* options we've seen already */
480 ccp_options try; /* options to ask for next time */
482 memset(&no, 0, sizeof(no));
485 if (go->deflate && len >= CILEN_DEFLATE
486 && p[0] == CI_DEFLATE && p[1] == CILEN_DEFLATE) {
489 * Peer wants us to use a different code size or something.
490 * Stop asking for Deflate if we don't understand his suggestion.
492 if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL
493 || DEFLATE_SIZE(p[2]) < DEFLATE_MIN_SIZE
494 || p[3] != DEFLATE_CHK_SEQUENCE)
496 else if (DEFLATE_SIZE(p[2]) < go->deflate_size)
497 go->deflate_size = DEFLATE_SIZE(p[2]);
499 len -= CILEN_DEFLATE;
502 if (go->bsd_compress && len >= CILEN_BSD_COMPRESS
503 && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) {
506 * Peer wants us to use a different number of bits
507 * or a different version.
509 if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION)
510 try.bsd_compress = 0;
511 else if (BSD_NBITS(p[2]) < go->bsd_bits)
512 try.bsd_bits = BSD_NBITS(p[2]);
513 p += CILEN_BSD_COMPRESS;
514 len -= CILEN_BSD_COMPRESS;
518 * Predictor-1 and 2 have no options, so they can't be Naked.
520 * XXX What should we do with any remaining options?
526 if (f->state != OPENED)
532 * ccp_rejci - reject some of our suggested compression methods.
540 ccp_options *go = &ccp_gotoptions[f->unit];
541 ccp_options try; /* options to request next time */
546 * Cope with empty configure-rejects by ceasing to send
547 * configure-requests.
549 if (len == 0 && all_rejected[f->unit])
552 if (go->deflate && len >= CILEN_DEFLATE
553 && p[0] == CI_DEFLATE && p[1] == CILEN_DEFLATE) {
554 if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
555 || p[3] != DEFLATE_CHK_SEQUENCE)
556 return 0; /* Rej is bad */
559 len -= CILEN_DEFLATE;
561 if (go->bsd_compress && len >= CILEN_BSD_COMPRESS
562 && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) {
563 if (p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits))
565 try.bsd_compress = 0;
566 p += CILEN_BSD_COMPRESS;
567 len -= CILEN_BSD_COMPRESS;
569 if (go->predictor_1 && len >= CILEN_PREDICTOR_1
570 && p[0] == CI_PREDICTOR_1 && p[1] == CILEN_PREDICTOR_1) {
572 p += CILEN_PREDICTOR_1;
573 len -= CILEN_PREDICTOR_1;
575 if (go->predictor_2 && len >= CILEN_PREDICTOR_2
576 && p[0] == CI_PREDICTOR_2 && p[1] == CILEN_PREDICTOR_2) {
578 p += CILEN_PREDICTOR_2;
579 len -= CILEN_PREDICTOR_2;
585 if (f->state != OPENED)
592 * ccp_reqci - processed a received configure-request.
593 * Returns CONFACK, CONFNAK or CONFREJ and the packet modified
597 ccp_reqci(f, p, lenp, dont_nak)
603 int ret, newret, res;
605 int len, clen, type, nb;
606 ccp_options *ho = &ccp_hisoptions[f->unit];
607 ccp_options *ao = &ccp_allowoptions[f->unit];
613 memset(ho, 0, sizeof(ccp_options));
617 if (len < 2 || p[1] < 2 || p[1] > len) {
628 if (!ao->deflate || clen != CILEN_DEFLATE) {
634 ho->deflate_size = nb = DEFLATE_SIZE(p[2]);
635 if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL
636 || p[3] != DEFLATE_CHK_SEQUENCE
637 || nb > ao->deflate_size || nb < DEFLATE_MIN_SIZE) {
640 p[2] = DEFLATE_MAKE_OPT(ao->deflate_size);
641 p[3] = DEFLATE_CHK_SEQUENCE;
647 * Check whether we can do Deflate with the window
648 * size they want. If the window is too big, reduce
649 * it until the kernel can cope and nak with that.
650 * We only check this for the first option.
654 res = ccp_test(f->unit, p, CILEN_DEFLATE, 1);
656 break; /* it's OK now */
657 if (res < 0 || nb == DEFLATE_MIN_SIZE || dont_nak) {
659 p[2] = DEFLATE_MAKE_OPT(ho->deflate_size);
664 p[2] = DEFLATE_MAKE_OPT(nb);
669 case CI_BSD_COMPRESS:
670 if (!ao->bsd_compress || clen != CILEN_BSD_COMPRESS) {
675 ho->bsd_compress = 1;
676 ho->bsd_bits = nb = BSD_NBITS(p[2]);
677 if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION
678 || nb > ao->bsd_bits || nb < BSD_MIN_BITS) {
681 p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, ao->bsd_bits);
686 * Check whether we can do BSD-Compress with the code
687 * size they want. If the code size is too big, reduce
688 * it until the kernel can cope and nak with that.
689 * We only check this for the first option.
693 res = ccp_test(f->unit, p, CILEN_BSD_COMPRESS, 1);
696 if (res < 0 || nb == BSD_MIN_BITS || dont_nak) {
698 p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION,
704 p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, nb);
710 if (!ao->predictor_1 || clen != CILEN_PREDICTOR_1) {
717 && ccp_test(f->unit, p, CILEN_PREDICTOR_1, 1) <= 0) {
723 if (!ao->predictor_2 || clen != CILEN_PREDICTOR_2) {
730 && ccp_test(f->unit, p, CILEN_PREDICTOR_2, 1) <= 0) {
740 if (newret == CONFNAK && dont_nak)
742 if (!(newret == CONFACK || newret == CONFNAK && ret == CONFREJ)) {
743 /* we're returning this option */
744 if (newret == CONFREJ && ret == CONFNAK)
748 BCOPY(p, retp, clen);
756 if (ret != CONFACK) {
757 if (ret == CONFREJ && *lenp == retp - p0)
758 all_rejected[f->unit] = 1;
766 * CCP has come up - inform the kernel driver.
772 ccp_options *go = &ccp_gotoptions[f->unit];
773 ccp_options *ho = &ccp_hisoptions[f->unit];
775 ccp_flags_set(f->unit, 1, 1);
776 if (ANY_COMPRESS(*go) || ANY_COMPRESS(*ho))
777 syslog(LOG_NOTICE, "%s enabled",
778 ANY_COMPRESS(*go)? ANY_COMPRESS(*ho)? "Compression":
779 "Receive compression": "Transmit compression");
783 * CCP has gone down - inform the kernel driver.
789 if (ccp_localstate[f->unit] & RACK_PENDING)
790 UNTIMEOUT(ccp_rack_timeout, (caddr_t) f);
791 ccp_localstate[f->unit] = 0;
792 ccp_flags_set(f->unit, 1, 0);
796 * Print the contents of a CCP packet.
798 char *ccp_codenames[] = {
799 "ConfReq", "ConfAck", "ConfNak", "ConfRej",
800 "TermReq", "TermAck", "CodeRej",
801 NULL, NULL, NULL, NULL, NULL, NULL,
802 "ResetReq", "ResetAck",
806 ccp_printpkt(p, plen, printer, arg)
809 void (*printer) __P((void *, char *, ...));
817 if (plen < HEADERLEN)
821 len = (p[2] << 8) + p[3];
822 if (len < HEADERLEN || len > plen)
825 if (code >= 1 && code <= sizeof(ccp_codenames) / sizeof(char *)
826 && ccp_codenames[code-1] != NULL)
827 printer(arg, " %s", ccp_codenames[code-1]);
829 printer(arg, " code=0x%x", code);
830 printer(arg, " id=0x%x", id);
839 /* print list of possible compression methods */
843 if (optlen < 2 || optlen > len)
850 if (optlen >= CILEN_DEFLATE) {
851 printer(arg, "deflate %d", DEFLATE_SIZE(p[2]));
852 if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL)
853 printer(arg, " method %d", DEFLATE_METHOD(p[2]));
854 if (p[3] != DEFLATE_CHK_SEQUENCE)
855 printer(arg, " check %d", p[3]);
859 case CI_BSD_COMPRESS:
860 if (optlen >= CILEN_BSD_COMPRESS) {
861 printer(arg, "bsd v%d %d", BSD_VERSION(p[2]),
863 p += CILEN_BSD_COMPRESS;
867 if (optlen >= CILEN_PREDICTOR_1) {
868 printer(arg, "predictor 1");
869 p += CILEN_PREDICTOR_1;
873 if (optlen >= CILEN_PREDICTOR_2) {
874 printer(arg, "predictor 2");
875 p += CILEN_PREDICTOR_2;
880 printer(arg, " %.2x", *p++);
886 /* dump out the rest of the packet in hex */
888 printer(arg, " %.2x", *p++);
894 * We have received a packet that the decompressor failed to
895 * decompress. Here we would expect to issue a reset-request, but
896 * Motorola has a patent on resetting the compressor as a result of
897 * detecting an error in the decompressed data after decompression.
898 * (See US patent 5,130,993; international patent publication number
899 * WO 91/10289; Australian patent 73296/91.)
901 * So we ask the kernel whether the error was detected after
902 * decompression; if it was, we take CCP down, thus disabling
903 * compression :-(, otherwise we issue the reset-request.
906 ccp_datainput(unit, pkt, len)
914 if (f->state == OPENED) {
915 if (ccp_fatal_error(unit)) {
917 * Disable compression by taking CCP down.
919 syslog(LOG_ERR, "Lost compression sync: disabling compression");
920 ccp_close(unit, "Lost compression sync");
923 * Send a reset-request to reset the peer's compressor.
924 * We don't do that if we are still waiting for an
925 * acknowledgement to a previous reset-request.
927 if (!(ccp_localstate[f->unit] & RACK_PENDING)) {
928 fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0);
929 TIMEOUT(ccp_rack_timeout, (caddr_t) f, RACKTIMEOUT);
930 ccp_localstate[f->unit] |= RACK_PENDING;
932 ccp_localstate[f->unit] |= RREQ_REPEAT;
938 * Timeout waiting for reset-ack.
941 ccp_rack_timeout(arg)
944 fsm *f = (fsm *) arg;
946 if (f->state == OPENED && ccp_localstate[f->unit] & RREQ_REPEAT) {
947 fsm_sdata(f, CCP_RESETREQ, f->reqid, NULL, 0);
948 TIMEOUT(ccp_rack_timeout, (caddr_t) f, RACKTIMEOUT);
949 ccp_localstate[f->unit] &= ~RREQ_REPEAT;
951 ccp_localstate[f->unit] &= ~RACK_PENDING;