dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / cmd-inet / usr.bin / pppd / ccp.c
blob1af52d9a4a62519f9b90a303e5af0dd48f5a41e7
1 /*
2 * ccp.c - PPP Compression Control Protocol.
4 * Copyright (c) 2000 by Sun Microsystems, Inc.
5 * All rights reserved.
7 * Copyright (c) 1994 The Australian National University.
8 * All rights reserved.
10 * Permission to use, copy, modify, and distribute this software and its
11 * documentation is hereby granted, provided that the above copyright
12 * notice appears in all copies. This software is provided without any
13 * warranty, express or implied. The Australian National University
14 * makes no representations about the suitability of this software for
15 * any purpose.
17 * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
18 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
19 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
20 * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
21 * OF SUCH DAMAGE.
23 * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
25 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
26 * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
27 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
28 * OR MODIFICATIONS.
31 * Copyright (c) 2016 by Delphix. All rights reserved.
34 #pragma ident "%Z%%M% %I% %E% SMI"
35 #define RCSID "$Id: ccp.c,v 1.30 2000/04/15 01:27:11 masputra Exp $"
37 #include <stdlib.h>
38 #include <string.h>
40 #include "pppd.h"
41 #include "fsm.h"
42 #include "ccp.h"
43 #include <net/ppp-comp.h>
45 static const char rcsid[] = RCSID;
48 * Command-line options.
50 static int setbsdcomp __P((char **, option_t *));
51 static int setdeflate __P((char **, option_t *));
53 static option_t ccp_option_list[] = {
54 { "noccp", o_bool, &ccp_protent.enabled_flag,
55 "Disable CCP negotiation" },
56 { "-ccp", o_bool, &ccp_protent.enabled_flag,
57 "Disable CCP negotiation" },
58 { "bsdcomp", o_special, (void *)setbsdcomp,
59 "Request BSD-Compress packet compression" },
60 { "nobsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress,
61 "don't allow BSD-Compress", OPT_A2COPY,
62 &ccp_allowoptions[0].bsd_compress },
63 { "-bsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress,
64 "don't allow BSD-Compress", OPT_A2COPY,
65 &ccp_allowoptions[0].bsd_compress },
66 { "deflate", o_special, (void *)setdeflate,
67 "request Deflate compression" },
68 { "nodeflate", o_bool, &ccp_wantoptions[0].deflate,
69 "don't allow Deflate compression", OPT_A2COPY,
70 &ccp_allowoptions[0].deflate },
71 { "-deflate", o_bool, &ccp_wantoptions[0].deflate,
72 "don't allow Deflate compression", OPT_A2COPY,
73 &ccp_allowoptions[0].deflate },
74 { "nodeflatedraft", o_bool, &ccp_wantoptions[0].deflate_draft,
75 "don't use draft deflate #", OPT_A2COPY,
76 &ccp_allowoptions[0].deflate_draft },
77 { "predictor1", o_bool, &ccp_wantoptions[0].predictor_1,
78 "request Predictor-1", 1, &ccp_allowoptions[0].predictor_1 },
79 { "nopredictor1", o_bool, &ccp_wantoptions[0].predictor_1,
80 "don't allow Predictor-1", OPT_A2COPY,
81 &ccp_allowoptions[0].predictor_1 },
82 { "-predictor1", o_bool, &ccp_wantoptions[0].predictor_1,
83 "don't allow Predictor-1", OPT_A2COPY,
84 &ccp_allowoptions[0].predictor_1 },
86 { NULL }
90 * Protocol entry points from main code.
92 static void ccp_init __P((int unit));
93 static void ccp_open __P((int unit));
94 static void ccp_close __P((int unit, char *));
95 static void ccp_lowerup __P((int unit));
96 static void ccp_lowerdown __P((int));
97 static void ccp_input __P((int unit, u_char *pkt, int len));
98 static void ccp_protrej __P((int unit));
99 static int ccp_printpkt __P((u_char *pkt, int len,
100 void (*printer) __P((void *, const char *, ...)),
101 void *arg));
102 static void ccp_datainput __P((int unit, u_char *pkt, int len));
104 struct protent ccp_protent = {
105 PPP_CCP,
106 ccp_init,
107 ccp_input,
108 ccp_protrej,
109 ccp_lowerup,
110 ccp_lowerdown,
111 ccp_open,
112 ccp_close,
113 ccp_printpkt,
114 ccp_datainput,
116 "CCP",
117 "Compressed",
118 ccp_option_list,
119 NULL,
120 NULL,
121 NULL
124 fsm ccp_fsm[NUM_PPP];
125 ccp_options ccp_wantoptions[NUM_PPP]; /* what to request the peer to use */
126 ccp_options ccp_gotoptions[NUM_PPP]; /* what the peer agreed to do */
127 ccp_options ccp_allowoptions[NUM_PPP]; /* what we'll agree to do */
128 ccp_options ccp_hisoptions[NUM_PPP]; /* what we agreed to do */
131 * Callbacks for fsm code.
133 static void ccp_resetci __P((fsm *));
134 static int ccp_cilen __P((fsm *));
135 static void ccp_addci __P((fsm *, u_char *, int *));
136 static int ccp_ackci __P((fsm *, u_char *, int));
137 static int ccp_nakci __P((fsm *, u_char *, int));
138 static int ccp_rejci __P((fsm *, u_char *, int));
139 static int ccp_reqci __P((fsm *, u_char *, int *, int));
140 static void ccp_up __P((fsm *));
141 static void ccp_down __P((fsm *));
142 static int ccp_extcode __P((fsm *, int, int, u_char *, int));
143 static int ccp_codereject __P((fsm *p, int code, int id, u_char *inp,
144 int len));
146 static fsm_callbacks ccp_callbacks = {
147 ccp_resetci, /* Reset our Configuration Information */
148 ccp_cilen, /* Length of our Configuration Information */
149 ccp_addci, /* Add our Configuration Information */
150 ccp_ackci, /* ACK our Configuration Information */
151 ccp_nakci, /* NAK our Configuration Information */
152 ccp_rejci, /* Reject our Configuration Information */
153 ccp_reqci, /* Request peer's Configuration Information */
154 ccp_up, /* Called when fsm reaches OPENED state */
155 ccp_down, /* Called when fsm leaves OPENED state */
156 NULL, /* Called when we want the lower layer up */
157 NULL, /* Called when we want the lower layer down */
158 NULL, /* Retransmission is necessary */
159 ccp_extcode, /* Called to handle LCP-specific codes */
160 "CCP", /* String name of protocol */
161 ccp_codereject, /* Peer rejected a code number */
165 * Local statics.
167 static void ccp_rack_timeout __P((void *));
168 static char * method_name __P((ccp_options *, ccp_options *));
171 * Do we want / did we get any compression?
173 #define ANY_COMPRESS(opt) ((opt).deflate || (opt).bsd_compress \
174 || (opt).predictor_1 || (opt).predictor_2)
177 * Local state (mainly for handling reset-reqs and reset-acks).
179 static int ccp_localstate[NUM_PPP];
180 #define RACK_PENDING 0x0001 /* waiting for reset-ack */
181 #define RREQ_REPEAT 0x0002 /* send another reset-req if no reset-ack */
182 #define RREQ_REJECTED 0x0004 /* peer code-rejected reset-request */
183 #define RACK_REJECTED 0x0008 /* peer code-rejected reset-ack */
184 #define RREQ_IGNORED 0x0010 /* peer just ignored reset-request */
186 #define RACKTIMEOUT 1 /* time in seconds between Reset-Requests */
188 static int all_rejected[NUM_PPP]; /* we rejected all peer's options */
190 #ifdef COMP_TUNE
191 static int deflate_tune = -1; /* compression effort level for deflate */
192 #endif
193 static int deflate_rmax = DEFLATE_MAX_SIZE; /* max rbits */
194 static int deflate_amax = DEFLATE_MAX_SIZE; /* max abits */
197 * Option parsing.
199 /*ARGSUSED*/
200 static int
201 setbsdcomp(argv, opt)
202 char **argv;
203 option_t *opt;
205 int rbits, abits;
206 char *str, *endp;
208 str = *argv;
209 abits = rbits = strtol(str, &endp, 0);
210 if (endp != str && *endp == ',') {
211 str = endp + 1;
212 abits = strtol(str, &endp, 0);
214 if (*endp != '\0' || endp == str) {
215 option_error("invalid parameter '%s' for bsdcomp option", *argv);
216 return 0;
218 if ((rbits != 0 && (rbits < BSD_MIN_BITS || rbits > BSD_MAX_BITS))
219 || (abits != 0 && (abits < BSD_MIN_BITS || abits > BSD_MAX_BITS))) {
220 option_error("bsdcomp option values must be 0 or %d .. %d",
221 BSD_MIN_BITS, BSD_MAX_BITS);
222 return 0;
224 if (rbits > 0) {
225 ccp_wantoptions[0].bsd_compress = 1;
226 ccp_wantoptions[0].bsd_bits = rbits;
227 } else
228 ccp_wantoptions[0].bsd_compress = 0;
229 if (abits > 0) {
230 ccp_allowoptions[0].bsd_compress = 1;
231 ccp_allowoptions[0].bsd_bits = abits;
232 } else
233 ccp_allowoptions[0].bsd_compress = 0;
234 return 1;
237 /*ARGSUSED*/
238 static int
239 setdeflate(argv, opt)
240 char **argv;
241 option_t *opt;
243 int rbits, abits, def_rmax, def_amax;
244 char *str, *endp;
246 str = endp = *argv;
247 if (*str == ',')
248 abits = rbits = -1;
249 else
250 abits = rbits = strtol(str, &endp, 0);
251 if (*endp == ',') {
252 str = ++endp;
253 if (*str == ',')
254 abits = rbits;
255 else
256 abits = strtol(str, &endp, 0);
258 #ifdef COMP_TUNE
259 if (*endp == ',' && privileged_option) {
260 str = ++endp;
261 deflate_tune = strtol(str, &endp, 0);
263 #endif
264 if (*endp != '\0' || endp == str) {
265 option_error("invalid parameter '%s' for deflate option", *argv);
266 return 0;
268 if (privileged_option) {
269 def_rmax = def_amax = DEFLATE_MAX_SIZE;
270 } else {
271 def_rmax = deflate_rmax;
272 def_amax = deflate_amax;
274 if (rbits < 0)
275 rbits = def_rmax;
276 if (abits < 0)
277 abits = def_amax;
278 if ((rbits != 0 && (rbits <= DEFLATE_MIN_SIZE || rbits > def_rmax))
279 || (abits != 0 && (abits <= DEFLATE_MIN_SIZE || abits > def_amax))) {
280 option_error("deflate option values must be 0 or {%d,%d} .. {%d,%d}",
281 DEFLATE_MIN_SIZE+1, DEFLATE_MIN_SIZE+1,
282 def_rmax, def_amax);
283 return 0;
285 if (privileged_option) {
286 deflate_rmax = rbits;
287 deflate_amax = abits;
289 if (rbits > 0) {
290 ccp_wantoptions[0].deflate = 1;
291 ccp_wantoptions[0].deflate_size = rbits;
292 } else
293 ccp_wantoptions[0].deflate = 0;
294 if (abits > 0) {
295 ccp_allowoptions[0].deflate = 1;
296 ccp_allowoptions[0].deflate_size = abits;
297 } else
298 ccp_allowoptions[0].deflate = 0;
299 return 1;
304 * ccp_init - initialize CCP.
306 static void
307 ccp_init(unit)
308 int unit;
310 fsm *f = &ccp_fsm[unit];
312 f->unit = unit;
313 f->protocol = PPP_CCP;
314 f->callbacks = &ccp_callbacks;
315 fsm_init(f);
316 f->flags |= OPT_RESTART;
318 BZERO(&ccp_wantoptions[unit], sizeof(ccp_options));
319 BZERO(&ccp_gotoptions[unit], sizeof(ccp_options));
320 BZERO(&ccp_allowoptions[unit], sizeof(ccp_options));
321 BZERO(&ccp_hisoptions[unit], sizeof(ccp_options));
323 ccp_wantoptions[0].deflate = 1;
324 ccp_wantoptions[0].deflate_size = DEFLATE_MAX_SIZE;
325 ccp_wantoptions[0].deflate_correct = 1;
326 ccp_wantoptions[0].deflate_draft = 1;
327 ccp_allowoptions[0].deflate = 1;
328 ccp_allowoptions[0].deflate_size = DEFLATE_MAX_SIZE;
329 ccp_allowoptions[0].deflate_correct = 1;
330 ccp_allowoptions[0].deflate_draft = 1;
332 ccp_wantoptions[0].bsd_compress = 1;
333 ccp_wantoptions[0].bsd_bits = BSD_MAX_BITS;
334 ccp_allowoptions[0].bsd_compress = 1;
335 ccp_allowoptions[0].bsd_bits = BSD_MAX_BITS;
337 ccp_allowoptions[0].predictor_1 = 1;
341 * ccp_open - CCP is allowed to come up.
343 static void
344 ccp_open(unit)
345 int unit;
347 fsm *f = &ccp_fsm[unit];
350 * If we haven't gone open yet (first time through), then go open
351 * but not up. Otherwise, skip this to allow reopen to reset the
352 * compressor.
354 if (f->state != OPENED)
355 ccp_flags_set(unit, 1, 0);
358 * Find out which compressors the kernel supports before
359 * deciding whether to open in silent mode.
361 ccp_resetci(f);
362 if (!ANY_COMPRESS(ccp_gotoptions[unit]))
363 f->flags |= OPT_SILENT;
365 fsm_open(f);
369 * ccp_close - Terminate CCP.
371 static void
372 ccp_close(unit, reason)
373 int unit;
374 char *reason;
376 ccp_flags_set(unit, 0, 0);
377 fsm_close(&ccp_fsm[unit], reason);
381 * ccp_lowerup - we may now transmit CCP packets.
383 static void
384 ccp_lowerup(unit)
385 int unit;
387 fsm_lowerup(&ccp_fsm[unit]);
391 * ccp_lowerdown - we may not transmit CCP packets.
393 static void
394 ccp_lowerdown(unit)
395 int unit;
397 fsm_lowerdown(&ccp_fsm[unit]);
401 * ccp_input - process a received CCP packet.
403 static void
404 ccp_input(unit, p, len)
405 int unit;
406 u_char *p;
407 int len;
409 fsm *f = &ccp_fsm[unit];
410 int oldstate;
413 * Check for a terminate-request so we can print a message.
415 oldstate = f->state;
416 fsm_input(f, p, len);
417 if (oldstate == OPENED && p[0] == CODE_TERMREQ && f->state != OPENED)
418 notice("Compression disabled by peer.");
421 * If we get a terminate-ack and we're not asking for compression,
422 * close CCP. (Terminate-Request is handled by fsm_input() above.)
424 if (oldstate == REQSENT && p[0] == CODE_TERMACK
425 && !ANY_COMPRESS(ccp_gotoptions[unit]))
426 ccp_close(unit, "No compression negotiated");
430 * Handle a CCP-specific code.
432 static int
433 ccp_extcode(f, code, id, p, len)
434 fsm *f;
435 int code, id;
436 u_char *p;
437 int len;
439 switch (code) {
440 case CCP_RESETREQ:
441 /* If not open, then silently ignore. */
442 if (f->state != OPENED)
443 break;
444 /* send a reset-ack, which our transmitter module will see and
445 reset its compression state. */
446 fsm_sdata(f, CCP_RESETACK, id, p, len);
447 break;
449 case CCP_RESETACK:
451 * Note that the compression module isn't picky about ID
452 * numbers and such.
454 ccp_localstate[f->unit] &= ~RREQ_IGNORED & ~RREQ_REJECTED;
455 if ((ccp_localstate[f->unit] & RACK_PENDING) && id == f->reqid) {
456 ccp_localstate[f->unit] &= ~RACK_PENDING & ~RREQ_REPEAT;
457 UNTIMEOUT(ccp_rack_timeout, f);
459 break;
461 default:
462 /* Tell fsm to send code reject */
463 return (0);
466 return (1);
470 * Handle Code-Reject for one of our extended codes by dropping back to
471 * reopen as mechanism to restart compression.
473 /*ARGSUSED*/
474 static int
475 ccp_codereject(f, code, id, inp, len)
476 fsm *f;
477 int code, id;
478 u_char *inp;
479 int len;
481 switch (code) {
482 case CCP_RESETREQ:
483 if (!(ccp_localstate[f->unit] & RREQ_REJECTED)) {
484 info("peer has rejected CCP Reset-Request; falling back on Open");
485 if (f->state == OPENED)
486 ccp_open(f->unit);
488 ccp_localstate[f->unit] |= RREQ_REJECTED;
489 return (0);
491 case CCP_RESETACK:
493 * Peer must have sent us CCP Reset-Request but then code-rejected when
494 * we sent CCP Reset-Ack. It seems to have changed its mind, and we
495 * have to obey its wishes.
497 ccp_localstate[f->unit] |= RACK_REJECTED;
498 notice("peer has erroneously rejected CCP Reset-Ack");
499 f->term_reason = "peer sent Code-Reject for CCP Reset-Ack";
500 f->term_reason_len = strlen(f->term_reason);
501 break;
503 default:
504 f->term_reason = "peer sent invalid Code-Reject";
505 break;
508 f->term_reason_len = strlen(f->term_reason);
509 return (1);
513 * ccp_protrej - peer doesn't talk CCP.
515 static void
516 ccp_protrej(unit)
517 int unit;
519 /* Neither open nor up. */
520 ccp_flags_set(unit, 0, 0);
521 fsm_lowerdown(&ccp_fsm[unit]);
525 * ccp_resetci - initialize at start of negotiation.
527 static void
528 ccp_resetci(f)
529 fsm *f;
531 ccp_options *go = &ccp_gotoptions[f->unit];
532 u_char opt_buf[16];
534 *go = ccp_wantoptions[f->unit];
535 all_rejected[f->unit] = 0;
538 * Check whether the kernel knows about the various
539 * decompression methods we might request.
541 if (go->bsd_compress) {
542 opt_buf[0] = CI_BSD_COMPRESS;
543 opt_buf[1] = CILEN_BSD_COMPRESS;
544 opt_buf[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, BSD_MIN_BITS);
545 if (ccp_test(f->unit, opt_buf, CILEN_BSD_COMPRESS, 0) <= 0)
546 go->bsd_compress = 0;
548 if (go->deflate) {
549 if (go->deflate_correct) {
550 opt_buf[0] = CI_DEFLATE;
551 opt_buf[1] = CILEN_DEFLATE;
552 opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_SIZE+1);
553 opt_buf[3] = DEFLATE_CHK_SEQUENCE;
554 if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0)
555 go->deflate_correct = 0;
557 if (go->deflate_draft) {
558 opt_buf[0] = CI_DEFLATE_DRAFT;
559 opt_buf[1] = CILEN_DEFLATE;
560 opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_SIZE+1);
561 opt_buf[3] = DEFLATE_CHK_SEQUENCE;
562 if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0)
563 go->deflate_draft = 0;
565 if (!go->deflate_correct && !go->deflate_draft)
566 go->deflate = 0;
568 if (go->predictor_1) {
569 opt_buf[0] = CI_PREDICTOR_1;
570 opt_buf[1] = CILEN_PREDICTOR_1;
571 if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_1, 0) <= 0)
572 go->predictor_1 = 0;
574 if (go->predictor_2) {
575 opt_buf[0] = CI_PREDICTOR_2;
576 opt_buf[1] = CILEN_PREDICTOR_2;
577 if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_2, 0) <= 0)
578 go->predictor_2 = 0;
583 * ccp_cilen - Return total length of our configuration info.
585 static int
586 ccp_cilen(f)
587 fsm *f;
589 ccp_options *go = &ccp_gotoptions[f->unit];
591 return (go->bsd_compress? CILEN_BSD_COMPRESS: 0)
592 + (go->deflate && go->deflate_correct ? CILEN_DEFLATE : 0)
593 + (go->deflate && go->deflate_draft ? CILEN_DEFLATE : 0)
594 + (go->predictor_1? CILEN_PREDICTOR_1: 0)
595 + (go->predictor_2? CILEN_PREDICTOR_2: 0);
599 * ccp_addci - put our requests in a packet.
601 static void
602 ccp_addci(f, p, lenp)
603 fsm *f;
604 u_char *p;
605 int *lenp;
607 int res;
608 ccp_options *go = &ccp_gotoptions[f->unit];
609 u_char *p0 = p;
612 * Add the compression types that we can receive, in decreasing
613 * preference order. Get the kernel to allocate the first one
614 * in case it gets Acked.
616 if (go->deflate) {
617 p[0] = go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT;
618 p[1] = CILEN_DEFLATE;
619 p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
620 p[3] = DEFLATE_CHK_SEQUENCE;
621 for (;;) {
622 res = ccp_test(f->unit, p, CILEN_DEFLATE, 0);
623 if (res > 0) {
624 p += CILEN_DEFLATE;
625 break;
627 if (res < 0 || go->deflate_size <= DEFLATE_MIN_SIZE+1) {
628 go->deflate = 0;
629 break;
631 --go->deflate_size;
632 p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
634 /* If we're offering both, then this is second. */
635 if (p != p0 && go->deflate_correct && go->deflate_draft) {
636 p[0] = CI_DEFLATE_DRAFT;
637 p[1] = CILEN_DEFLATE;
638 p[2] = p[2 - CILEN_DEFLATE];
639 p[3] = DEFLATE_CHK_SEQUENCE;
640 p += CILEN_DEFLATE;
643 if (go->bsd_compress) {
644 p[0] = CI_BSD_COMPRESS;
645 p[1] = CILEN_BSD_COMPRESS;
646 p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
647 if (p != p0) {
648 p += CILEN_BSD_COMPRESS; /* not the first option */
649 } else {
650 for (;;) {
651 res = ccp_test(f->unit, p, CILEN_BSD_COMPRESS, 0);
652 if (res > 0) {
653 p += CILEN_BSD_COMPRESS;
654 break;
656 if (res < 0 || go->bsd_bits <= BSD_MIN_BITS) {
657 go->bsd_compress = 0;
658 break;
660 --go->bsd_bits;
661 p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
666 * Prefer Predictor-1 over Predictor-2. (The latter requires the use
667 * of LAP-B and has no known implementations.)
669 if (go->predictor_1) {
670 p[0] = CI_PREDICTOR_1;
671 p[1] = CILEN_PREDICTOR_1;
672 if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_1, 0) <= 0) {
673 go->predictor_1 = 0;
674 } else {
675 p += CILEN_PREDICTOR_1;
678 if (go->predictor_2) {
679 p[0] = CI_PREDICTOR_2;
680 p[1] = CILEN_PREDICTOR_2;
681 if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_2, 0) <= 0) {
682 go->predictor_2 = 0;
683 } else {
684 p += CILEN_PREDICTOR_2;
688 go->method = (p > p0)? p0[0]: -1;
690 *lenp = p - p0;
694 * ccp_ackci - process a received configure-ack, and return
695 * 1 iff the packet was OK.
697 static int
698 ccp_ackci(f, p, len)
699 fsm *f;
700 u_char *p;
701 int len;
703 ccp_options *go = &ccp_gotoptions[f->unit];
704 u_char *p0 = p;
706 if (go->deflate && go->deflate_correct) {
707 if (len < CILEN_DEFLATE
708 || p[0] != CI_DEFLATE || p[1] != CILEN_DEFLATE
709 || p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
710 || p[3] != DEFLATE_CHK_SEQUENCE)
711 return 0;
712 /* Cope with non-standard first/fast ack */
713 if (p == p0 && len == 0)
714 return 1;
715 p += CILEN_DEFLATE;
716 len -= CILEN_DEFLATE;
718 if (go->deflate && go->deflate_draft) {
719 if (len < CILEN_DEFLATE
720 || p[0] != CI_DEFLATE_DRAFT || p[1] != CILEN_DEFLATE
721 || p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
722 || p[3] != DEFLATE_CHK_SEQUENCE)
723 return 0;
724 /* Cope with non-standard first/fast ack */
725 if (p == p0 && len == 0)
726 return 1;
727 p += CILEN_DEFLATE;
728 len -= CILEN_DEFLATE;
730 if (go->bsd_compress) {
731 if (len < CILEN_BSD_COMPRESS
732 || p[0] != CI_BSD_COMPRESS || p[1] != CILEN_BSD_COMPRESS
733 || p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits))
734 return 0;
735 /* Cope with non-standard first/fast ack */
736 if (p == p0 && len == 0)
737 return 1;
738 p += CILEN_BSD_COMPRESS;
739 len -= CILEN_BSD_COMPRESS;
741 if (go->predictor_1) {
742 if (len < CILEN_PREDICTOR_1
743 || p[0] != CI_PREDICTOR_1 || p[1] != CILEN_PREDICTOR_1)
744 return 0;
745 /* Cope with non-standard first/fast ack */
746 if (p == p0 && len == 0)
747 return 1;
748 p += CILEN_PREDICTOR_1;
749 len -= CILEN_PREDICTOR_1;
751 if (go->predictor_2) {
752 if (len < CILEN_PREDICTOR_2
753 || p[0] != CI_PREDICTOR_2 || p[1] != CILEN_PREDICTOR_2)
754 return 0;
755 /* Cope with non-standard first/fast ack */
756 if (p == p0 && len == 0)
757 return 1;
758 p += CILEN_PREDICTOR_2;
759 len -= CILEN_PREDICTOR_2;
762 /* Peer cannot ack something that wasn't sent. */
763 if (len != 0)
764 return 0;
765 return 1;
769 * ccp_nakci - process received configure-nak.
770 * Returns 1 iff the nak was OK.
772 static int
773 ccp_nakci(f, p, len)
774 fsm *f;
775 u_char *p;
776 int len;
778 ccp_options *go = &ccp_gotoptions[f->unit];
779 ccp_options no; /* options we've seen already */
780 ccp_options try; /* options to ask for next time */
782 BZERO(&no, sizeof(no));
783 try = *go;
785 if (go->deflate && go->deflate_correct && len >= CILEN_DEFLATE &&
786 p[0] == CI_DEFLATE) {
787 no.deflate = 1;
789 * Peer wants us to use a different code size or something.
790 * Stop asking for Deflate if we don't understand its suggestion.
792 if (p[1] != CILEN_DEFLATE
793 || DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL
794 || DEFLATE_SIZE(p[2]) <= DEFLATE_MIN_SIZE
795 || p[3] != DEFLATE_CHK_SEQUENCE)
796 try.deflate_correct = 0;
797 else if (DEFLATE_SIZE(p[2]) < go->deflate_size)
798 try.deflate_size = DEFLATE_SIZE(p[2]);
799 len -= p[1];
800 p += p[1];
803 if (go->deflate && go->deflate_draft && len >= CILEN_DEFLATE &&
804 p[0] == CI_DEFLATE_DRAFT) {
805 no.deflate = 1;
807 * Peer wants us to use a different code size or something.
808 * Stop asking for Deflate using the old algorithm number if
809 * we don't understand its suggestion. (Note that this will
810 * happen if the peer is running Magnalink instead of
811 * old-style Deflate.)
813 if (p[1] != CILEN_DEFLATE
814 || DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL
815 || DEFLATE_SIZE(p[2]) <= DEFLATE_MIN_SIZE
816 || p[3] != DEFLATE_CHK_SEQUENCE)
817 try.deflate_draft = 0;
818 else if (DEFLATE_SIZE(p[2]) < go->deflate_size)
819 try.deflate_size = DEFLATE_SIZE(p[2]);
820 len -= p[1];
821 p += p[1];
824 if (!try.deflate_correct && !try.deflate_draft)
825 try.deflate = 0;
827 if (go->bsd_compress && len >= CILEN_BSD_COMPRESS &&
828 p[0] == CI_BSD_COMPRESS) {
829 no.bsd_compress = 1;
831 * Peer wants us to use a different number of bits
832 * or a different version.
834 if (p[1] != CILEN_BSD_COMPRESS ||
835 BSD_VERSION(p[2]) != BSD_CURRENT_VERSION)
836 try.bsd_compress = 0;
837 else if (BSD_NBITS(p[2]) < go->bsd_bits)
838 try.bsd_bits = BSD_NBITS(p[2]);
839 len -= p[1];
840 p += p[1];
844 * Predictor-1 and 2 have no options, so they can't be Naked.
846 * There may be remaining options but we ignore them.
849 if (f->state != OPENED)
850 *go = try;
851 return 1;
855 * ccp_rejci - peer rejects some of our suggested compression methods.
857 static int
858 ccp_rejci(f, p, len)
859 fsm *f;
860 u_char *p;
861 int len;
863 ccp_options *go = &ccp_gotoptions[f->unit];
864 ccp_options try; /* options to request next time */
866 try = *go;
869 * Cope with empty configure-rejects by ceasing to send
870 * configure-requests.
872 if (len == 0 && all_rejected[f->unit])
873 return -1;
875 if (go->deflate && go->deflate_correct && len >= CILEN_DEFLATE &&
876 p[0] == CI_DEFLATE && p[1] == CILEN_DEFLATE) {
877 if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
878 || p[3] != DEFLATE_CHK_SEQUENCE)
879 return 0; /* Rej is bad */
880 try.deflate_correct = 0;
881 p += CILEN_DEFLATE;
882 len -= CILEN_DEFLATE;
884 if (go->deflate && go->deflate_draft && len >= CILEN_DEFLATE &&
885 p[0] == CI_DEFLATE_DRAFT && p[1] == CILEN_DEFLATE) {
886 if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
887 || p[3] != DEFLATE_CHK_SEQUENCE)
888 return 0; /* Rej is bad */
889 try.deflate_draft = 0;
890 p += CILEN_DEFLATE;
891 len -= CILEN_DEFLATE;
893 if (!try.deflate_correct && !try.deflate_draft)
894 try.deflate = 0;
895 if (go->bsd_compress && len >= CILEN_BSD_COMPRESS
896 && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) {
897 if (p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits))
898 return 0;
899 try.bsd_compress = 0;
900 p += CILEN_BSD_COMPRESS;
901 len -= CILEN_BSD_COMPRESS;
903 if (go->predictor_1 && len >= CILEN_PREDICTOR_1
904 && p[0] == CI_PREDICTOR_1 && p[1] == CILEN_PREDICTOR_1) {
905 try.predictor_1 = 0;
906 p += CILEN_PREDICTOR_1;
907 len -= CILEN_PREDICTOR_1;
909 if (go->predictor_2 && len >= CILEN_PREDICTOR_2
910 && p[0] == CI_PREDICTOR_2 && p[1] == CILEN_PREDICTOR_2) {
911 try.predictor_2 = 0;
912 p += CILEN_PREDICTOR_2;
913 len -= CILEN_PREDICTOR_2;
916 if (len != 0)
917 return 0;
919 if (f->state != OPENED)
920 *go = try;
922 return 1;
926 * ccp_reqci - process a received configure-request.
928 * Returns CODE_CONFACK, CODE_CONFNAK or CODE_CONFREJ and the packet
929 * is modified appropriately.
931 static int
932 ccp_reqci(f, p, lenp, dont_nak)
933 fsm *f;
934 u_char *p;
935 int *lenp;
936 int dont_nak;
938 int ret, newret, res;
939 u_char *p0, *nakp, *rejp, *pv;
940 int len, clen, type, nb;
941 ccp_options *ho = &ccp_hisoptions[f->unit];
942 ccp_options *ao = &ccp_allowoptions[f->unit];
944 ret = CODE_CONFACK;
945 rejp = p0 = p;
946 nakp = nak_buffer;
947 len = *lenp;
949 BZERO(ho, sizeof(ccp_options));
950 ho->method = (len > 0)? p[0]: -1;
952 for (; len > 0; len -= clen, p += clen) {
953 newret = CODE_CONFACK;
954 if (len < 2 || p[1] > len) {
956 * RFC 1661 page 40 -- if the option extends beyond the
957 * packet, then discard the entire packet.
959 return (0);
962 type = p[0];
963 clen = p[1];
965 pv = p;
966 switch (type) {
967 case CI_DEFLATE:
968 case CI_DEFLATE_DRAFT:
969 if (!ao->deflate ||
970 (!ao->deflate_correct && type == CI_DEFLATE) ||
971 (!ao->deflate_draft && type == CI_DEFLATE_DRAFT)) {
972 newret = CODE_CONFREJ;
973 break;
976 ho->deflate = 1;
977 nb = clen < CILEN_DEFLATE ? ao->deflate_size : DEFLATE_SIZE(p[2]);
978 ho->deflate_size = nb;
979 if (clen != CILEN_DEFLATE ||
980 DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL ||
981 p[3] != DEFLATE_CHK_SEQUENCE || nb > ao->deflate_size ||
982 nb <= DEFLATE_MIN_SIZE) {
983 newret = CODE_CONFNAK;
984 if (dont_nak)
985 break;
986 if (nb > ao->deflate_size)
987 nb = ao->deflate_size;
988 else if (nb <= DEFLATE_MIN_SIZE)
989 nb = DEFLATE_MIN_SIZE+1;
990 pv = nakp;
991 PUTCHAR(type, nakp);
992 PUTCHAR(CILEN_DEFLATE, nakp);
993 PUTCHAR(DEFLATE_MAKE_OPT(nb), nakp);
994 PUTCHAR(DEFLATE_CHK_SEQUENCE, nakp);
998 * Check whether we can do Deflate with the window
999 * size they want. If the window is too big, reduce
1000 * it until the kernel can cope and nak with that.
1001 * We only check this for the first option.
1003 if (p == p0) {
1004 for (;;) {
1005 res = ccp_test(f->unit, pv, CILEN_DEFLATE, 1);
1006 if (res > 0)
1007 break; /* it's OK now */
1008 if (res < 0 || nb <= DEFLATE_MIN_SIZE+1 || dont_nak) {
1009 newret = CODE_CONFREJ;
1010 break;
1012 if (newret == CODE_CONFACK) {
1013 BCOPY(pv, nakp, CILEN_DEFLATE);
1014 pv = nakp;
1015 nakp += CILEN_DEFLATE;
1016 newret = CODE_CONFNAK;
1018 --nb;
1019 pv[2] = DEFLATE_MAKE_OPT(nb);
1021 #ifdef COMP_TUNE
1022 /* Tune Deflate compression effort. */
1023 if (newret == CODE_CONFACK)
1024 ccp_tune(f->unit, deflate_tune);
1025 #endif
1027 break;
1029 case CI_BSD_COMPRESS:
1030 if (!ao->bsd_compress) {
1031 newret = CODE_CONFREJ;
1032 break;
1035 ho->bsd_compress = 1;
1036 nb = clen < CILEN_BSD_COMPRESS ? ao->bsd_bits : BSD_NBITS(p[2]);
1037 ho->bsd_bits = nb;
1038 if (clen != CILEN_BSD_COMPRESS ||
1039 BSD_VERSION(p[2]) != BSD_CURRENT_VERSION ||
1040 nb > ao->bsd_bits || nb < BSD_MIN_BITS) {
1041 newret = CODE_CONFNAK;
1042 if (dont_nak)
1043 break;
1044 if (nb > ao->bsd_bits)
1045 nb = ao->bsd_bits;
1046 else if (nb < BSD_MIN_BITS)
1047 nb = BSD_MIN_BITS;
1048 pv = nakp;
1049 PUTCHAR(type, nakp);
1050 PUTCHAR(CILEN_BSD_COMPRESS, nakp);
1051 PUTCHAR(BSD_MAKE_OPT(BSD_CURRENT_VERSION, nb), nakp);
1055 * Check whether we can do BSD-Compress with the code
1056 * size they want. If the code size is too big, reduce
1057 * it until the kernel can cope and nak with that.
1058 * We only check this for the first option.
1060 if (p == p0) {
1061 for (;;) {
1062 res = ccp_test(f->unit, pv, CILEN_BSD_COMPRESS, 1);
1063 if (res > 0)
1064 break;
1065 if (res < 0 || nb == BSD_MIN_BITS || dont_nak) {
1066 newret = CODE_CONFREJ;
1067 break;
1069 if (newret == CODE_CONFACK) {
1070 BCOPY(pv, nakp, CILEN_BSD_COMPRESS);
1071 pv = nakp;
1072 nakp += CILEN_BSD_COMPRESS;
1073 newret = CODE_CONFNAK;
1075 --nb;
1076 pv[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, nb);
1079 break;
1081 case CI_PREDICTOR_1:
1082 if (!ao->predictor_1) {
1083 newret = CODE_CONFREJ;
1084 break;
1087 ho->predictor_1 = 1;
1088 if (clen != CILEN_PREDICTOR_1) {
1089 newret = CODE_CONFNAK;
1090 if (dont_nak)
1091 break;
1092 pv = nakp;
1093 PUTCHAR(type, nakp);
1094 PUTCHAR(CILEN_PREDICTOR_1, nakp);
1096 if (p == p0 &&
1097 ccp_test(f->unit, pv, CILEN_PREDICTOR_1, 1) <= 0) {
1098 newret = CODE_CONFREJ;
1100 break;
1102 case CI_PREDICTOR_2:
1103 if (!ao->predictor_2) {
1104 newret = CODE_CONFREJ;
1105 break;
1108 ho->predictor_2 = 1;
1109 if (clen != CILEN_PREDICTOR_2) {
1110 newret = CODE_CONFNAK;
1111 if (dont_nak)
1112 break;
1113 pv = nakp;
1114 PUTCHAR(type, nakp);
1115 PUTCHAR(CILEN_PREDICTOR_2, nakp);
1117 if (p == p0 &&
1118 ccp_test(f->unit, p, CILEN_PREDICTOR_2, 1) <= 0) {
1119 newret = CODE_CONFREJ;
1121 break;
1123 default:
1124 newret = CODE_CONFREJ;
1125 break;
1128 /* Cope with confused peers. */
1129 if (clen < 2)
1130 clen = 2;
1132 if (newret == CODE_CONFACK && ret != CODE_CONFACK)
1133 continue;
1134 if (newret == CODE_CONFNAK) {
1135 if (dont_nak) {
1136 newret = CODE_CONFREJ;
1137 } else {
1138 /* Ignore subsequent nakable things if rejecting. */
1139 if (ret == CODE_CONFREJ)
1140 continue;
1141 ret = CODE_CONFNAK;
1144 if (newret == CODE_CONFREJ) {
1145 ret = CODE_CONFREJ;
1146 if (p != rejp)
1147 BCOPY(p, rejp, clen);
1148 rejp += clen;
1152 switch (ret) {
1153 case CODE_CONFACK:
1154 *lenp = p - p0;
1155 break;
1156 case CODE_CONFNAK:
1157 *lenp = nakp - nak_buffer;
1158 BCOPY(nak_buffer, p0, *lenp);
1159 break;
1160 case CODE_CONFREJ:
1161 *lenp = rejp - p0;
1162 break;
1164 return ret;
1168 * Make a string name for a compression method (or 2).
1170 static char *
1171 method_name(opt, opt2)
1172 ccp_options *opt, *opt2;
1174 static char result[64];
1176 if (!ANY_COMPRESS(*opt))
1177 return "(none)";
1178 switch (opt->method) {
1179 case CI_DEFLATE:
1180 case CI_DEFLATE_DRAFT:
1181 if (opt2 != NULL && opt2->deflate_size != opt->deflate_size)
1182 (void) slprintf(result, sizeof(result), "Deflate%s (%d/%d)",
1183 (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""),
1184 opt->deflate_size, opt2->deflate_size);
1185 else
1186 (void) slprintf(result, sizeof(result), "Deflate%s (%d)",
1187 (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""),
1188 opt->deflate_size);
1189 break;
1190 case CI_BSD_COMPRESS:
1191 if (opt2 != NULL && opt2->bsd_bits != opt->bsd_bits)
1192 (void) slprintf(result, sizeof(result), "BSD-Compress (%d/%d)",
1193 opt->bsd_bits, opt2->bsd_bits);
1194 else
1195 (void) slprintf(result, sizeof(result), "BSD-Compress (%d)",
1196 opt->bsd_bits);
1197 break;
1198 case CI_PREDICTOR_1:
1199 return "Predictor 1";
1200 case CI_PREDICTOR_2:
1201 return "Predictor 2";
1202 #ifdef CI_STAC
1203 case CI_STAC:
1204 return "Stac";
1205 #endif
1206 #ifdef CI_MPPC
1207 case CI_MPPC:
1208 return "MS-PPC";
1209 #endif
1210 default:
1211 (void) slprintf(result, sizeof(result), "Method %d", opt->method);
1213 return result;
1217 * CCP has come up - inform the kernel driver and log a message.
1219 static void
1220 ccp_up(f)
1221 fsm *f;
1223 ccp_options *go = &ccp_gotoptions[f->unit];
1224 ccp_options *ho = &ccp_hisoptions[f->unit];
1225 char method1[64];
1228 * We're now open and up (running).
1230 ccp_flags_set(f->unit, 1, 1);
1231 if (ANY_COMPRESS(*go)) {
1232 if (ANY_COMPRESS(*ho)) {
1233 if (go->method == ho->method) {
1234 notice("%s compression enabled", method_name(go, ho));
1235 } else {
1236 (void) strlcpy(method1, method_name(go, NULL), sizeof(method1));
1237 notice("%s / %s compression enabled",
1238 method1, method_name(ho, NULL));
1240 } else
1241 notice("%s receive decompression enabled", method_name(go, NULL));
1242 } else if (ANY_COMPRESS(*ho))
1243 notice("%s transmit compression enabled", method_name(ho, NULL));
1247 * CCP has gone down - inform the kernel driver.
1249 static void
1250 ccp_down(f)
1251 fsm *f;
1253 if (ccp_localstate[f->unit] & RACK_PENDING)
1254 UNTIMEOUT(ccp_rack_timeout, f);
1255 /* Don't forget about peer's code rejects or ignoring of requests. */
1256 ccp_localstate[f->unit] &= ~RACK_PENDING & ~RREQ_REPEAT;
1257 /* We're still open, but no longer up. */
1258 ccp_flags_set(f->unit, 1, 0);
1261 static int
1262 ccp_printpkt(p, plen, printer, arg)
1263 u_char *p;
1264 int plen;
1265 void (*printer) __P((void *, const char *, ...));
1266 void *arg;
1268 u_char *p0, *optend, cichar;
1269 int code, id, len;
1270 int optlen, clen;
1271 u_short cishort;
1272 #ifdef CI_MPPC
1273 u_int32_t cilong;
1274 #endif
1276 p0 = p;
1277 if (plen < HEADERLEN) {
1278 printer(arg, "too short (%d<%d)", plen, HEADERLEN);
1279 return (0);
1281 GETCHAR(code, p);
1282 GETCHAR(id, p);
1283 GETSHORT(len, p);
1285 printer(arg, " %s id=0x%x", code_name(code, 1), id);
1287 if (len < HEADERLEN) {
1288 printer(arg, " header length %d<%d", len, HEADERLEN);
1289 return (HEADERLEN);
1291 if (len > plen) {
1292 printer(arg, " truncated (%d>%d)", len, plen);
1293 len = plen;
1295 len -= HEADERLEN;
1297 switch (code) {
1298 case CODE_CONFREQ:
1299 case CODE_CONFACK:
1300 case CODE_CONFNAK:
1301 case CODE_CONFREJ:
1302 /* print list of possible compression methods */
1303 while (len >= 2) {
1304 GETCHAR(code, p);
1305 GETCHAR(clen, p);
1306 optlen = clen;
1307 printer(arg, " <");
1308 if (optlen > len)
1309 optlen = len;
1310 if (optlen < 2)
1311 optlen = 2;
1312 len -= optlen;
1313 optend = p + optlen - 2;
1314 switch (code) {
1315 case CI_DEFLATE:
1316 case CI_DEFLATE_DRAFT:
1317 printer(arg, "deflate%s",
1318 (code == CI_DEFLATE_DRAFT? "(old#)": ""));
1319 if (clen != CILEN_DEFLATE)
1320 printer(arg, " length %d", clen);
1321 if (optlen >= CILEN_DEFLATE) {
1322 GETCHAR(cichar, p);
1323 printer(arg, " %d", DEFLATE_SIZE(cichar));
1324 if (DEFLATE_METHOD(cichar) != DEFLATE_METHOD_VAL)
1325 printer(arg, " method %d", DEFLATE_METHOD(cichar));
1326 GETCHAR(cichar, p);
1327 if (cichar != DEFLATE_CHK_SEQUENCE)
1328 printer(arg, " check %d", cichar);
1330 break;
1331 case CI_BSD_COMPRESS:
1332 printer(arg, "bsd");
1333 if (clen != CILEN_BSD_COMPRESS)
1334 printer(arg, " length %d", clen);
1335 if (optlen >= CILEN_BSD_COMPRESS) {
1336 GETCHAR(cichar, p);
1337 printer(arg, " v%d %d", BSD_VERSION(cichar),
1338 BSD_NBITS(cichar));
1340 break;
1341 case CI_PREDICTOR_1:
1342 printer(arg, "predictor-1");
1343 if (clen != CILEN_PREDICTOR_1)
1344 printer(arg, " length %d", clen);
1345 break;
1346 case CI_PREDICTOR_2:
1347 printer(arg, "predictor-2");
1348 if (clen != CILEN_PREDICTOR_2)
1349 printer(arg, " length %d", clen);
1350 break;
1351 #ifdef CI_STAC
1352 case CI_STAC:
1353 printer(arg, "Stac");
1354 if (clen != CILEN_STAC)
1355 printer(arg, " length %d", clen);
1356 if (optlen >= CILEN_STAC) {
1357 GETSHORT(cishort, p);
1358 GETCHAR(cichar, p);
1359 printer(arg, " h%d/m%d", cishort, cichar);
1361 break;
1362 #endif
1363 #ifdef CI_MPPC
1364 case CI_MPPC:
1365 /* There appears to be no good generic name for this one. */
1366 if (optlen >= CILEN_MPPC) {
1367 GETLONG(cilong, p);
1368 if (!(cilong & MPPC_COMP)) {
1369 if (cilong & MPPC_MPPE)
1370 printer(arg, "MPPE");
1371 else
1372 printer(arg, "MS-PPC?");
1373 } else {
1374 if (cilong & MPPC_MPPE)
1375 printer(arg, "MPPC+MPPE");
1376 else
1377 printer(arg, "MPPC");
1379 } else {
1380 printer(arg, "MS-?");
1382 if (clen != CILEN_STAC)
1383 printer(arg, " length %d", clen);
1384 break;
1385 #endif
1386 default:
1387 printer(arg, "typ%d len%d ", code, clen);
1388 break;
1390 if (p < optend) {
1391 if (p+8 < optend)
1392 printer(arg, " %.8B ...", p);
1393 else
1394 printer(arg, " %.*B", optend-p, p);
1395 p = optend;
1397 printer(arg, ">");
1399 break;
1401 case CODE_TERMACK:
1402 case CODE_TERMREQ:
1403 if (len > 0) {
1404 if (len == 2) {
1405 GETSHORT(cishort, p);
1406 printer(arg, " history %d", cishort);
1407 len = 0;
1408 } else if (*p >= ' ' && *p < 0x7f) {
1409 printer(arg, " ");
1410 print_string((char *)p, len, printer, arg);
1411 p += len;
1412 len = 0;
1415 break;
1418 /* dump out the rest of the packet in hex */
1419 if (len > 0) {
1420 if (len > 8)
1421 printer(arg, " %.8B ...", p);
1422 else
1423 printer(arg, " %.*B", len, p);
1424 p += len;
1427 return p - p0;
1431 * We have received a packet that the decompressor failed to
1432 * decompress. Here we would expect to issue a reset-request, but
1433 * Motorola has a patent on resetting the compressor as a result of
1434 * detecting an error in the decompressed data after decompression.
1435 * (See US patent 5,130,993; international patent publication number
1436 * WO 91/10289; Australian patent 73296/91.)
1438 * So we ask the kernel whether the error was detected after
1439 * decompression; if it was, we take CCP down, thus disabling
1440 * compression :-(, otherwise we issue the reset-request.
1442 /*ARGSUSED*/
1443 static void
1444 ccp_datainput(unit, pkt, len)
1445 int unit;
1446 u_char *pkt;
1447 int len;
1449 fsm *f;
1451 f = &ccp_fsm[unit];
1452 if (f->state == OPENED) {
1453 if (ccp_fatal_error(unit)) {
1455 * Disable compression by taking CCP down.
1457 error("Lost compression sync: disabling compression");
1458 ccp_close(unit, "Lost compression sync");
1459 } else {
1461 * Send a reset-request to reset the peer's compressor, if
1462 * possible. We don't do anything if we are still waiting
1463 * for an acknowledgement to a previous reset-request (to
1464 * avoid flooding the peer). We reopen CCP if the peer
1465 * doesn't like hearing about CCP Reset-Request (Cisco
1466 * sends CCP Code-Reject for Reset-Request). (Reopen
1467 * automatically clears the flags and cancels the
1468 * timeout.)
1470 if (ccp_localstate[f->unit] & RREQ_REJECTED) {
1471 dbglog("reopening CCP to reset peer's compressor");
1472 ccp_open(f->unit);
1473 } else if (ccp_localstate[f->unit] & RACK_PENDING) {
1474 /* Send another reset request; we're out of sequence. */
1475 ccp_localstate[f->unit] |= RREQ_REPEAT;
1476 } else {
1477 dbglog("sending CCP Reset-Request to reset peer's compressor");
1478 fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0);
1479 TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT);
1480 ccp_localstate[f->unit] |= RACK_PENDING;
1487 * Timeout waiting for reset-ack.
1489 static void
1490 ccp_rack_timeout(arg)
1491 void *arg;
1493 fsm *f = arg;
1495 /* Timeout; no longer pending. */
1496 ccp_localstate[f->unit] &= ~RACK_PENDING;
1498 /* Frankly, it's a coding flaw if this occurs. */
1499 if (f->state != OPENED)
1500 return;
1502 if (ccp_localstate[f->unit] & RREQ_IGNORED) {
1503 info("peer ignored our CCP Reset-Request twice; reopen instead");
1504 ccp_localstate[f->unit] =
1505 (ccp_localstate[f->unit] & ~RREQ_IGNORED) | RREQ_REJECTED;
1506 ccp_open(f->unit);
1507 } else if (ccp_localstate[f->unit] & RREQ_REPEAT) {
1508 dbglog("sending another CCP Reset-Request on timeout");
1509 fsm_sdata(f, CCP_RESETREQ, f->reqid, NULL, 0);
1510 TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT);
1511 ccp_localstate[f->unit] =
1512 (ccp_localstate[f->unit] & ~RREQ_REPEAT) | RREQ_IGNORED |
1513 RACK_PENDING;
1514 } else {
1515 dbglog("timeout waiting for CCP Reset-Ack; hope for the best");
1516 ccp_localstate[f->unit] |= RREQ_IGNORED;