8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / cmd-inet / usr.bin / pppd / ccp.c
blobb3bc84b0e14975efdd4023005511ff73a7adbfcb
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 #if !defined(lint) && !defined(_lint)
46 static const char rcsid[] = RCSID;
47 #endif
50 * Command-line options.
52 static int setbsdcomp __P((char **, option_t *));
53 static int setdeflate __P((char **, option_t *));
55 static option_t ccp_option_list[] = {
56 { "noccp", o_bool, &ccp_protent.enabled_flag,
57 "Disable CCP negotiation" },
58 { "-ccp", o_bool, &ccp_protent.enabled_flag,
59 "Disable CCP negotiation" },
60 { "bsdcomp", o_special, (void *)setbsdcomp,
61 "Request BSD-Compress packet compression" },
62 { "nobsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress,
63 "don't allow BSD-Compress", OPT_A2COPY,
64 &ccp_allowoptions[0].bsd_compress },
65 { "-bsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress,
66 "don't allow BSD-Compress", OPT_A2COPY,
67 &ccp_allowoptions[0].bsd_compress },
68 { "deflate", o_special, (void *)setdeflate,
69 "request Deflate compression" },
70 { "nodeflate", o_bool, &ccp_wantoptions[0].deflate,
71 "don't allow Deflate compression", OPT_A2COPY,
72 &ccp_allowoptions[0].deflate },
73 { "-deflate", o_bool, &ccp_wantoptions[0].deflate,
74 "don't allow Deflate compression", OPT_A2COPY,
75 &ccp_allowoptions[0].deflate },
76 { "nodeflatedraft", o_bool, &ccp_wantoptions[0].deflate_draft,
77 "don't use draft deflate #", OPT_A2COPY,
78 &ccp_allowoptions[0].deflate_draft },
79 { "predictor1", o_bool, &ccp_wantoptions[0].predictor_1,
80 "request Predictor-1", 1, &ccp_allowoptions[0].predictor_1 },
81 { "nopredictor1", o_bool, &ccp_wantoptions[0].predictor_1,
82 "don't allow Predictor-1", OPT_A2COPY,
83 &ccp_allowoptions[0].predictor_1 },
84 { "-predictor1", o_bool, &ccp_wantoptions[0].predictor_1,
85 "don't allow Predictor-1", OPT_A2COPY,
86 &ccp_allowoptions[0].predictor_1 },
88 { NULL }
92 * Protocol entry points from main code.
94 static void ccp_init __P((int unit));
95 static void ccp_open __P((int unit));
96 static void ccp_close __P((int unit, char *));
97 static void ccp_lowerup __P((int unit));
98 static void ccp_lowerdown __P((int));
99 static void ccp_input __P((int unit, u_char *pkt, int len));
100 static void ccp_protrej __P((int unit));
101 static int ccp_printpkt __P((u_char *pkt, int len,
102 void (*printer) __P((void *, const char *, ...)),
103 void *arg));
104 static void ccp_datainput __P((int unit, u_char *pkt, int len));
106 struct protent ccp_protent = {
107 PPP_CCP,
108 ccp_init,
109 ccp_input,
110 ccp_protrej,
111 ccp_lowerup,
112 ccp_lowerdown,
113 ccp_open,
114 ccp_close,
115 ccp_printpkt,
116 ccp_datainput,
118 "CCP",
119 "Compressed",
120 ccp_option_list,
121 NULL,
122 NULL,
123 NULL
126 fsm ccp_fsm[NUM_PPP];
127 ccp_options ccp_wantoptions[NUM_PPP]; /* what to request the peer to use */
128 ccp_options ccp_gotoptions[NUM_PPP]; /* what the peer agreed to do */
129 ccp_options ccp_allowoptions[NUM_PPP]; /* what we'll agree to do */
130 ccp_options ccp_hisoptions[NUM_PPP]; /* what we agreed to do */
133 * Callbacks for fsm code.
135 static void ccp_resetci __P((fsm *));
136 static int ccp_cilen __P((fsm *));
137 static void ccp_addci __P((fsm *, u_char *, int *));
138 static int ccp_ackci __P((fsm *, u_char *, int));
139 static int ccp_nakci __P((fsm *, u_char *, int));
140 static int ccp_rejci __P((fsm *, u_char *, int));
141 static int ccp_reqci __P((fsm *, u_char *, int *, int));
142 static void ccp_up __P((fsm *));
143 static void ccp_down __P((fsm *));
144 static int ccp_extcode __P((fsm *, int, int, u_char *, int));
145 static int ccp_codereject __P((fsm *p, int code, int id, u_char *inp,
146 int len));
148 static fsm_callbacks ccp_callbacks = {
149 ccp_resetci, /* Reset our Configuration Information */
150 ccp_cilen, /* Length of our Configuration Information */
151 ccp_addci, /* Add our Configuration Information */
152 ccp_ackci, /* ACK our Configuration Information */
153 ccp_nakci, /* NAK our Configuration Information */
154 ccp_rejci, /* Reject our Configuration Information */
155 ccp_reqci, /* Request peer's Configuration Information */
156 ccp_up, /* Called when fsm reaches OPENED state */
157 ccp_down, /* Called when fsm leaves OPENED state */
158 NULL, /* Called when we want the lower layer up */
159 NULL, /* Called when we want the lower layer down */
160 NULL, /* Retransmission is necessary */
161 ccp_extcode, /* Called to handle LCP-specific codes */
162 "CCP", /* String name of protocol */
163 ccp_codereject, /* Peer rejected a code number */
167 * Local statics.
169 static void ccp_rack_timeout __P((void *));
170 static char * method_name __P((ccp_options *, ccp_options *));
173 * Do we want / did we get any compression?
175 #define ANY_COMPRESS(opt) ((opt).deflate || (opt).bsd_compress \
176 || (opt).predictor_1 || (opt).predictor_2)
179 * Local state (mainly for handling reset-reqs and reset-acks).
181 static int ccp_localstate[NUM_PPP];
182 #define RACK_PENDING 0x0001 /* waiting for reset-ack */
183 #define RREQ_REPEAT 0x0002 /* send another reset-req if no reset-ack */
184 #define RREQ_REJECTED 0x0004 /* peer code-rejected reset-request */
185 #define RACK_REJECTED 0x0008 /* peer code-rejected reset-ack */
186 #define RREQ_IGNORED 0x0010 /* peer just ignored reset-request */
188 #define RACKTIMEOUT 1 /* time in seconds between Reset-Requests */
190 static int all_rejected[NUM_PPP]; /* we rejected all peer's options */
192 #ifdef COMP_TUNE
193 static int deflate_tune = -1; /* compression effort level for deflate */
194 #endif
195 static int deflate_rmax = DEFLATE_MAX_SIZE; /* max rbits */
196 static int deflate_amax = DEFLATE_MAX_SIZE; /* max abits */
199 * Option parsing.
201 /*ARGSUSED*/
202 static int
203 setbsdcomp(argv, opt)
204 char **argv;
205 option_t *opt;
207 int rbits, abits;
208 char *str, *endp;
210 str = *argv;
211 abits = rbits = strtol(str, &endp, 0);
212 if (endp != str && *endp == ',') {
213 str = endp + 1;
214 abits = strtol(str, &endp, 0);
216 if (*endp != '\0' || endp == str) {
217 option_error("invalid parameter '%s' for bsdcomp option", *argv);
218 return 0;
220 if ((rbits != 0 && (rbits < BSD_MIN_BITS || rbits > BSD_MAX_BITS))
221 || (abits != 0 && (abits < BSD_MIN_BITS || abits > BSD_MAX_BITS))) {
222 option_error("bsdcomp option values must be 0 or %d .. %d",
223 BSD_MIN_BITS, BSD_MAX_BITS);
224 return 0;
226 if (rbits > 0) {
227 ccp_wantoptions[0].bsd_compress = 1;
228 ccp_wantoptions[0].bsd_bits = rbits;
229 } else
230 ccp_wantoptions[0].bsd_compress = 0;
231 if (abits > 0) {
232 ccp_allowoptions[0].bsd_compress = 1;
233 ccp_allowoptions[0].bsd_bits = abits;
234 } else
235 ccp_allowoptions[0].bsd_compress = 0;
236 return 1;
239 /*ARGSUSED*/
240 static int
241 setdeflate(argv, opt)
242 char **argv;
243 option_t *opt;
245 int rbits, abits, def_rmax, def_amax;
246 char *str, *endp;
248 str = endp = *argv;
249 if (*str == ',')
250 abits = rbits = -1;
251 else
252 abits = rbits = strtol(str, &endp, 0);
253 if (*endp == ',') {
254 str = ++endp;
255 if (*str == ',')
256 abits = rbits;
257 else
258 abits = strtol(str, &endp, 0);
260 #ifdef COMP_TUNE
261 if (*endp == ',' && privileged_option) {
262 str = ++endp;
263 deflate_tune = strtol(str, &endp, 0);
265 #endif
266 if (*endp != '\0' || endp == str) {
267 option_error("invalid parameter '%s' for deflate option", *argv);
268 return 0;
270 if (privileged_option) {
271 def_rmax = def_amax = DEFLATE_MAX_SIZE;
272 } else {
273 def_rmax = deflate_rmax;
274 def_amax = deflate_amax;
276 if (rbits < 0)
277 rbits = def_rmax;
278 if (abits < 0)
279 abits = def_amax;
280 if ((rbits != 0 && (rbits <= DEFLATE_MIN_SIZE || rbits > def_rmax))
281 || (abits != 0 && (abits <= DEFLATE_MIN_SIZE || abits > def_amax))) {
282 option_error("deflate option values must be 0 or {%d,%d} .. {%d,%d}",
283 DEFLATE_MIN_SIZE+1, DEFLATE_MIN_SIZE+1,
284 def_rmax, def_amax);
285 return 0;
287 if (privileged_option) {
288 deflate_rmax = rbits;
289 deflate_amax = abits;
291 if (rbits > 0) {
292 ccp_wantoptions[0].deflate = 1;
293 ccp_wantoptions[0].deflate_size = rbits;
294 } else
295 ccp_wantoptions[0].deflate = 0;
296 if (abits > 0) {
297 ccp_allowoptions[0].deflate = 1;
298 ccp_allowoptions[0].deflate_size = abits;
299 } else
300 ccp_allowoptions[0].deflate = 0;
301 return 1;
306 * ccp_init - initialize CCP.
308 static void
309 ccp_init(unit)
310 int unit;
312 fsm *f = &ccp_fsm[unit];
314 f->unit = unit;
315 f->protocol = PPP_CCP;
316 f->callbacks = &ccp_callbacks;
317 fsm_init(f);
318 f->flags |= OPT_RESTART;
320 BZERO(&ccp_wantoptions[unit], sizeof(ccp_options));
321 BZERO(&ccp_gotoptions[unit], sizeof(ccp_options));
322 BZERO(&ccp_allowoptions[unit], sizeof(ccp_options));
323 BZERO(&ccp_hisoptions[unit], sizeof(ccp_options));
325 ccp_wantoptions[0].deflate = 1;
326 ccp_wantoptions[0].deflate_size = DEFLATE_MAX_SIZE;
327 ccp_wantoptions[0].deflate_correct = 1;
328 ccp_wantoptions[0].deflate_draft = 1;
329 ccp_allowoptions[0].deflate = 1;
330 ccp_allowoptions[0].deflate_size = DEFLATE_MAX_SIZE;
331 ccp_allowoptions[0].deflate_correct = 1;
332 ccp_allowoptions[0].deflate_draft = 1;
334 ccp_wantoptions[0].bsd_compress = 1;
335 ccp_wantoptions[0].bsd_bits = BSD_MAX_BITS;
336 ccp_allowoptions[0].bsd_compress = 1;
337 ccp_allowoptions[0].bsd_bits = BSD_MAX_BITS;
339 ccp_allowoptions[0].predictor_1 = 1;
343 * ccp_open - CCP is allowed to come up.
345 static void
346 ccp_open(unit)
347 int unit;
349 fsm *f = &ccp_fsm[unit];
352 * If we haven't gone open yet (first time through), then go open
353 * but not up. Otherwise, skip this to allow reopen to reset the
354 * compressor.
356 if (f->state != OPENED)
357 ccp_flags_set(unit, 1, 0);
360 * Find out which compressors the kernel supports before
361 * deciding whether to open in silent mode.
363 ccp_resetci(f);
364 if (!ANY_COMPRESS(ccp_gotoptions[unit]))
365 f->flags |= OPT_SILENT;
367 fsm_open(f);
371 * ccp_close - Terminate CCP.
373 static void
374 ccp_close(unit, reason)
375 int unit;
376 char *reason;
378 ccp_flags_set(unit, 0, 0);
379 fsm_close(&ccp_fsm[unit], reason);
383 * ccp_lowerup - we may now transmit CCP packets.
385 static void
386 ccp_lowerup(unit)
387 int unit;
389 fsm_lowerup(&ccp_fsm[unit]);
393 * ccp_lowerdown - we may not transmit CCP packets.
395 static void
396 ccp_lowerdown(unit)
397 int unit;
399 fsm_lowerdown(&ccp_fsm[unit]);
403 * ccp_input - process a received CCP packet.
405 static void
406 ccp_input(unit, p, len)
407 int unit;
408 u_char *p;
409 int len;
411 fsm *f = &ccp_fsm[unit];
412 int oldstate;
415 * Check for a terminate-request so we can print a message.
417 oldstate = f->state;
418 fsm_input(f, p, len);
419 if (oldstate == OPENED && p[0] == CODE_TERMREQ && f->state != OPENED)
420 notice("Compression disabled by peer.");
423 * If we get a terminate-ack and we're not asking for compression,
424 * close CCP. (Terminate-Request is handled by fsm_input() above.)
426 if (oldstate == REQSENT && p[0] == CODE_TERMACK
427 && !ANY_COMPRESS(ccp_gotoptions[unit]))
428 ccp_close(unit, "No compression negotiated");
432 * Handle a CCP-specific code.
434 static int
435 ccp_extcode(f, code, id, p, len)
436 fsm *f;
437 int code, id;
438 u_char *p;
439 int len;
441 switch (code) {
442 case CCP_RESETREQ:
443 /* If not open, then silently ignore. */
444 if (f->state != OPENED)
445 break;
446 /* send a reset-ack, which our transmitter module will see and
447 reset its compression state. */
448 fsm_sdata(f, CCP_RESETACK, id, p, len);
449 break;
451 case CCP_RESETACK:
453 * Note that the compression module isn't picky about ID
454 * numbers and such.
456 ccp_localstate[f->unit] &= ~RREQ_IGNORED & ~RREQ_REJECTED;
457 if ((ccp_localstate[f->unit] & RACK_PENDING) && id == f->reqid) {
458 ccp_localstate[f->unit] &= ~RACK_PENDING & ~RREQ_REPEAT;
459 UNTIMEOUT(ccp_rack_timeout, f);
461 break;
463 default:
464 /* Tell fsm to send code reject */
465 return (0);
468 return (1);
472 * Handle Code-Reject for one of our extended codes by dropping back to
473 * reopen as mechanism to restart compression.
475 /*ARGSUSED*/
476 static int
477 ccp_codereject(f, code, id, inp, len)
478 fsm *f;
479 int code, id;
480 u_char *inp;
481 int len;
483 switch (code) {
484 case CCP_RESETREQ:
485 if (!(ccp_localstate[f->unit] & RREQ_REJECTED)) {
486 info("peer has rejected CCP Reset-Request; falling back on Open");
487 if (f->state == OPENED)
488 ccp_open(f->unit);
490 ccp_localstate[f->unit] |= RREQ_REJECTED;
491 return (0);
493 case CCP_RESETACK:
495 * Peer must have sent us CCP Reset-Request but then code-rejected when
496 * we sent CCP Reset-Ack. It seems to have changed its mind, and we
497 * have to obey its wishes.
499 ccp_localstate[f->unit] |= RACK_REJECTED;
500 notice("peer has erroneously rejected CCP Reset-Ack");
501 f->term_reason = "peer sent Code-Reject for CCP Reset-Ack";
502 f->term_reason_len = strlen(f->term_reason);
503 break;
505 default:
506 f->term_reason = "peer sent invalid Code-Reject";
507 break;
510 f->term_reason_len = strlen(f->term_reason);
511 return (1);
515 * ccp_protrej - peer doesn't talk CCP.
517 static void
518 ccp_protrej(unit)
519 int unit;
521 /* Neither open nor up. */
522 ccp_flags_set(unit, 0, 0);
523 fsm_lowerdown(&ccp_fsm[unit]);
527 * ccp_resetci - initialize at start of negotiation.
529 static void
530 ccp_resetci(f)
531 fsm *f;
533 ccp_options *go = &ccp_gotoptions[f->unit];
534 u_char opt_buf[16];
536 *go = ccp_wantoptions[f->unit];
537 all_rejected[f->unit] = 0;
540 * Check whether the kernel knows about the various
541 * decompression methods we might request.
543 if (go->bsd_compress) {
544 opt_buf[0] = CI_BSD_COMPRESS;
545 opt_buf[1] = CILEN_BSD_COMPRESS;
546 opt_buf[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, BSD_MIN_BITS);
547 if (ccp_test(f->unit, opt_buf, CILEN_BSD_COMPRESS, 0) <= 0)
548 go->bsd_compress = 0;
550 if (go->deflate) {
551 if (go->deflate_correct) {
552 opt_buf[0] = CI_DEFLATE;
553 opt_buf[1] = CILEN_DEFLATE;
554 opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_SIZE+1);
555 opt_buf[3] = DEFLATE_CHK_SEQUENCE;
556 if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0)
557 go->deflate_correct = 0;
559 if (go->deflate_draft) {
560 opt_buf[0] = CI_DEFLATE_DRAFT;
561 opt_buf[1] = CILEN_DEFLATE;
562 opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_SIZE+1);
563 opt_buf[3] = DEFLATE_CHK_SEQUENCE;
564 if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0)
565 go->deflate_draft = 0;
567 if (!go->deflate_correct && !go->deflate_draft)
568 go->deflate = 0;
570 if (go->predictor_1) {
571 opt_buf[0] = CI_PREDICTOR_1;
572 opt_buf[1] = CILEN_PREDICTOR_1;
573 if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_1, 0) <= 0)
574 go->predictor_1 = 0;
576 if (go->predictor_2) {
577 opt_buf[0] = CI_PREDICTOR_2;
578 opt_buf[1] = CILEN_PREDICTOR_2;
579 if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_2, 0) <= 0)
580 go->predictor_2 = 0;
585 * ccp_cilen - Return total length of our configuration info.
587 static int
588 ccp_cilen(f)
589 fsm *f;
591 ccp_options *go = &ccp_gotoptions[f->unit];
593 return (go->bsd_compress? CILEN_BSD_COMPRESS: 0)
594 + (go->deflate && go->deflate_correct ? CILEN_DEFLATE : 0)
595 + (go->deflate && go->deflate_draft ? CILEN_DEFLATE : 0)
596 + (go->predictor_1? CILEN_PREDICTOR_1: 0)
597 + (go->predictor_2? CILEN_PREDICTOR_2: 0);
601 * ccp_addci - put our requests in a packet.
603 static void
604 ccp_addci(f, p, lenp)
605 fsm *f;
606 u_char *p;
607 int *lenp;
609 int res;
610 ccp_options *go = &ccp_gotoptions[f->unit];
611 u_char *p0 = p;
614 * Add the compression types that we can receive, in decreasing
615 * preference order. Get the kernel to allocate the first one
616 * in case it gets Acked.
618 if (go->deflate) {
619 p[0] = go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT;
620 p[1] = CILEN_DEFLATE;
621 p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
622 p[3] = DEFLATE_CHK_SEQUENCE;
623 for (;;) {
624 res = ccp_test(f->unit, p, CILEN_DEFLATE, 0);
625 if (res > 0) {
626 p += CILEN_DEFLATE;
627 break;
629 if (res < 0 || go->deflate_size <= DEFLATE_MIN_SIZE+1) {
630 go->deflate = 0;
631 break;
633 --go->deflate_size;
634 p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
636 /* If we're offering both, then this is second. */
637 if (p != p0 && go->deflate_correct && go->deflate_draft) {
638 p[0] = CI_DEFLATE_DRAFT;
639 p[1] = CILEN_DEFLATE;
640 p[2] = p[2 - CILEN_DEFLATE];
641 p[3] = DEFLATE_CHK_SEQUENCE;
642 p += CILEN_DEFLATE;
645 if (go->bsd_compress) {
646 p[0] = CI_BSD_COMPRESS;
647 p[1] = CILEN_BSD_COMPRESS;
648 p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
649 if (p != p0) {
650 p += CILEN_BSD_COMPRESS; /* not the first option */
651 } else {
652 for (;;) {
653 res = ccp_test(f->unit, p, CILEN_BSD_COMPRESS, 0);
654 if (res > 0) {
655 p += CILEN_BSD_COMPRESS;
656 break;
658 if (res < 0 || go->bsd_bits <= BSD_MIN_BITS) {
659 go->bsd_compress = 0;
660 break;
662 --go->bsd_bits;
663 p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
668 * Prefer Predictor-1 over Predictor-2. (The latter requires the use
669 * of LAP-B and has no known implementations.)
671 if (go->predictor_1) {
672 p[0] = CI_PREDICTOR_1;
673 p[1] = CILEN_PREDICTOR_1;
674 if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_1, 0) <= 0) {
675 go->predictor_1 = 0;
676 } else {
677 p += CILEN_PREDICTOR_1;
680 if (go->predictor_2) {
681 p[0] = CI_PREDICTOR_2;
682 p[1] = CILEN_PREDICTOR_2;
683 if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_2, 0) <= 0) {
684 go->predictor_2 = 0;
685 } else {
686 p += CILEN_PREDICTOR_2;
690 go->method = (p > p0)? p0[0]: -1;
692 *lenp = p - p0;
696 * ccp_ackci - process a received configure-ack, and return
697 * 1 iff the packet was OK.
699 static int
700 ccp_ackci(f, p, len)
701 fsm *f;
702 u_char *p;
703 int len;
705 ccp_options *go = &ccp_gotoptions[f->unit];
706 u_char *p0 = p;
708 if (go->deflate && go->deflate_correct) {
709 if (len < CILEN_DEFLATE
710 || p[0] != CI_DEFLATE || p[1] != CILEN_DEFLATE
711 || p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
712 || p[3] != DEFLATE_CHK_SEQUENCE)
713 return 0;
714 /* Cope with non-standard first/fast ack */
715 if (p == p0 && len == 0)
716 return 1;
717 p += CILEN_DEFLATE;
718 len -= CILEN_DEFLATE;
720 if (go->deflate && go->deflate_draft) {
721 if (len < CILEN_DEFLATE
722 || p[0] != CI_DEFLATE_DRAFT || p[1] != CILEN_DEFLATE
723 || p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
724 || p[3] != DEFLATE_CHK_SEQUENCE)
725 return 0;
726 /* Cope with non-standard first/fast ack */
727 if (p == p0 && len == 0)
728 return 1;
729 p += CILEN_DEFLATE;
730 len -= CILEN_DEFLATE;
732 if (go->bsd_compress) {
733 if (len < CILEN_BSD_COMPRESS
734 || p[0] != CI_BSD_COMPRESS || p[1] != CILEN_BSD_COMPRESS
735 || p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits))
736 return 0;
737 /* Cope with non-standard first/fast ack */
738 if (p == p0 && len == 0)
739 return 1;
740 p += CILEN_BSD_COMPRESS;
741 len -= CILEN_BSD_COMPRESS;
743 if (go->predictor_1) {
744 if (len < CILEN_PREDICTOR_1
745 || p[0] != CI_PREDICTOR_1 || p[1] != CILEN_PREDICTOR_1)
746 return 0;
747 /* Cope with non-standard first/fast ack */
748 if (p == p0 && len == 0)
749 return 1;
750 p += CILEN_PREDICTOR_1;
751 len -= CILEN_PREDICTOR_1;
753 if (go->predictor_2) {
754 if (len < CILEN_PREDICTOR_2
755 || p[0] != CI_PREDICTOR_2 || p[1] != CILEN_PREDICTOR_2)
756 return 0;
757 /* Cope with non-standard first/fast ack */
758 if (p == p0 && len == 0)
759 return 1;
760 p += CILEN_PREDICTOR_2;
761 len -= CILEN_PREDICTOR_2;
764 /* Peer cannot ack something that wasn't sent. */
765 if (len != 0)
766 return 0;
767 return 1;
771 * ccp_nakci - process received configure-nak.
772 * Returns 1 iff the nak was OK.
774 static int
775 ccp_nakci(f, p, len)
776 fsm *f;
777 u_char *p;
778 int len;
780 ccp_options *go = &ccp_gotoptions[f->unit];
781 ccp_options no; /* options we've seen already */
782 ccp_options try; /* options to ask for next time */
784 BZERO(&no, sizeof(no));
785 try = *go;
787 if (go->deflate && go->deflate_correct && len >= CILEN_DEFLATE &&
788 p[0] == CI_DEFLATE) {
789 no.deflate = 1;
791 * Peer wants us to use a different code size or something.
792 * Stop asking for Deflate if we don't understand its suggestion.
794 if (p[1] != CILEN_DEFLATE
795 || DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL
796 || DEFLATE_SIZE(p[2]) <= DEFLATE_MIN_SIZE
797 || p[3] != DEFLATE_CHK_SEQUENCE)
798 try.deflate_correct = 0;
799 else if (DEFLATE_SIZE(p[2]) < go->deflate_size)
800 try.deflate_size = DEFLATE_SIZE(p[2]);
801 len -= p[1];
802 p += p[1];
805 if (go->deflate && go->deflate_draft && len >= CILEN_DEFLATE &&
806 p[0] == CI_DEFLATE_DRAFT) {
807 no.deflate = 1;
809 * Peer wants us to use a different code size or something.
810 * Stop asking for Deflate using the old algorithm number if
811 * we don't understand its suggestion. (Note that this will
812 * happen if the peer is running Magnalink instead of
813 * old-style Deflate.)
815 if (p[1] != CILEN_DEFLATE
816 || DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL
817 || DEFLATE_SIZE(p[2]) <= DEFLATE_MIN_SIZE
818 || p[3] != DEFLATE_CHK_SEQUENCE)
819 try.deflate_draft = 0;
820 else if (DEFLATE_SIZE(p[2]) < go->deflate_size)
821 try.deflate_size = DEFLATE_SIZE(p[2]);
822 len -= p[1];
823 p += p[1];
826 if (!try.deflate_correct && !try.deflate_draft)
827 try.deflate = 0;
829 if (go->bsd_compress && len >= CILEN_BSD_COMPRESS &&
830 p[0] == CI_BSD_COMPRESS) {
831 no.bsd_compress = 1;
833 * Peer wants us to use a different number of bits
834 * or a different version.
836 if (p[1] != CILEN_BSD_COMPRESS ||
837 BSD_VERSION(p[2]) != BSD_CURRENT_VERSION)
838 try.bsd_compress = 0;
839 else if (BSD_NBITS(p[2]) < go->bsd_bits)
840 try.bsd_bits = BSD_NBITS(p[2]);
841 len -= p[1];
842 p += p[1];
846 * Predictor-1 and 2 have no options, so they can't be Naked.
848 * There may be remaining options but we ignore them.
851 if (f->state != OPENED)
852 *go = try;
853 return 1;
857 * ccp_rejci - peer rejects some of our suggested compression methods.
859 static int
860 ccp_rejci(f, p, len)
861 fsm *f;
862 u_char *p;
863 int len;
865 ccp_options *go = &ccp_gotoptions[f->unit];
866 ccp_options try; /* options to request next time */
868 try = *go;
871 * Cope with empty configure-rejects by ceasing to send
872 * configure-requests.
874 if (len == 0 && all_rejected[f->unit])
875 return -1;
877 if (go->deflate && go->deflate_correct && len >= CILEN_DEFLATE &&
878 p[0] == CI_DEFLATE && p[1] == CILEN_DEFLATE) {
879 if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
880 || p[3] != DEFLATE_CHK_SEQUENCE)
881 return 0; /* Rej is bad */
882 try.deflate_correct = 0;
883 p += CILEN_DEFLATE;
884 len -= CILEN_DEFLATE;
886 if (go->deflate && go->deflate_draft && len >= CILEN_DEFLATE &&
887 p[0] == CI_DEFLATE_DRAFT && p[1] == CILEN_DEFLATE) {
888 if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
889 || p[3] != DEFLATE_CHK_SEQUENCE)
890 return 0; /* Rej is bad */
891 try.deflate_draft = 0;
892 p += CILEN_DEFLATE;
893 len -= CILEN_DEFLATE;
895 if (!try.deflate_correct && !try.deflate_draft)
896 try.deflate = 0;
897 if (go->bsd_compress && len >= CILEN_BSD_COMPRESS
898 && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) {
899 if (p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits))
900 return 0;
901 try.bsd_compress = 0;
902 p += CILEN_BSD_COMPRESS;
903 len -= CILEN_BSD_COMPRESS;
905 if (go->predictor_1 && len >= CILEN_PREDICTOR_1
906 && p[0] == CI_PREDICTOR_1 && p[1] == CILEN_PREDICTOR_1) {
907 try.predictor_1 = 0;
908 p += CILEN_PREDICTOR_1;
909 len -= CILEN_PREDICTOR_1;
911 if (go->predictor_2 && len >= CILEN_PREDICTOR_2
912 && p[0] == CI_PREDICTOR_2 && p[1] == CILEN_PREDICTOR_2) {
913 try.predictor_2 = 0;
914 p += CILEN_PREDICTOR_2;
915 len -= CILEN_PREDICTOR_2;
918 if (len != 0)
919 return 0;
921 if (f->state != OPENED)
922 *go = try;
924 return 1;
928 * ccp_reqci - process a received configure-request.
930 * Returns CODE_CONFACK, CODE_CONFNAK or CODE_CONFREJ and the packet
931 * is modified appropriately.
933 static int
934 ccp_reqci(f, p, lenp, dont_nak)
935 fsm *f;
936 u_char *p;
937 int *lenp;
938 int dont_nak;
940 int ret, newret, res;
941 u_char *p0, *nakp, *rejp, *pv;
942 int len, clen, type, nb;
943 ccp_options *ho = &ccp_hisoptions[f->unit];
944 ccp_options *ao = &ccp_allowoptions[f->unit];
946 ret = CODE_CONFACK;
947 rejp = p0 = p;
948 nakp = nak_buffer;
949 len = *lenp;
951 BZERO(ho, sizeof(ccp_options));
952 ho->method = (len > 0)? p[0]: -1;
954 for (; len > 0; len -= clen, p += clen) {
955 newret = CODE_CONFACK;
956 if (len < 2 || p[1] > len) {
958 * RFC 1661 page 40 -- if the option extends beyond the
959 * packet, then discard the entire packet.
961 return (0);
964 type = p[0];
965 clen = p[1];
967 pv = p;
968 switch (type) {
969 case CI_DEFLATE:
970 case CI_DEFLATE_DRAFT:
971 if (!ao->deflate ||
972 (!ao->deflate_correct && type == CI_DEFLATE) ||
973 (!ao->deflate_draft && type == CI_DEFLATE_DRAFT)) {
974 newret = CODE_CONFREJ;
975 break;
978 ho->deflate = 1;
979 nb = clen < CILEN_DEFLATE ? ao->deflate_size : DEFLATE_SIZE(p[2]);
980 ho->deflate_size = nb;
981 if (clen != CILEN_DEFLATE ||
982 DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL ||
983 p[3] != DEFLATE_CHK_SEQUENCE || nb > ao->deflate_size ||
984 nb <= DEFLATE_MIN_SIZE) {
985 newret = CODE_CONFNAK;
986 if (dont_nak)
987 break;
988 if (nb > ao->deflate_size)
989 nb = ao->deflate_size;
990 else if (nb <= DEFLATE_MIN_SIZE)
991 nb = DEFLATE_MIN_SIZE+1;
992 pv = nakp;
993 PUTCHAR(type, nakp);
994 PUTCHAR(CILEN_DEFLATE, nakp);
995 PUTCHAR(DEFLATE_MAKE_OPT(nb), nakp);
996 PUTCHAR(DEFLATE_CHK_SEQUENCE, nakp);
1000 * Check whether we can do Deflate with the window
1001 * size they want. If the window is too big, reduce
1002 * it until the kernel can cope and nak with that.
1003 * We only check this for the first option.
1005 if (p == p0) {
1006 for (;;) {
1007 res = ccp_test(f->unit, pv, CILEN_DEFLATE, 1);
1008 if (res > 0)
1009 break; /* it's OK now */
1010 if (res < 0 || nb <= DEFLATE_MIN_SIZE+1 || dont_nak) {
1011 newret = CODE_CONFREJ;
1012 break;
1014 if (newret == CODE_CONFACK) {
1015 BCOPY(pv, nakp, CILEN_DEFLATE);
1016 pv = nakp;
1017 nakp += CILEN_DEFLATE;
1018 newret = CODE_CONFNAK;
1020 --nb;
1021 pv[2] = DEFLATE_MAKE_OPT(nb);
1023 #ifdef COMP_TUNE
1024 /* Tune Deflate compression effort. */
1025 if (newret == CODE_CONFACK)
1026 ccp_tune(f->unit, deflate_tune);
1027 #endif
1029 break;
1031 case CI_BSD_COMPRESS:
1032 if (!ao->bsd_compress) {
1033 newret = CODE_CONFREJ;
1034 break;
1037 ho->bsd_compress = 1;
1038 nb = clen < CILEN_BSD_COMPRESS ? ao->bsd_bits : BSD_NBITS(p[2]);
1039 ho->bsd_bits = nb;
1040 if (clen != CILEN_BSD_COMPRESS ||
1041 BSD_VERSION(p[2]) != BSD_CURRENT_VERSION ||
1042 nb > ao->bsd_bits || nb < BSD_MIN_BITS) {
1043 newret = CODE_CONFNAK;
1044 if (dont_nak)
1045 break;
1046 if (nb > ao->bsd_bits)
1047 nb = ao->bsd_bits;
1048 else if (nb < BSD_MIN_BITS)
1049 nb = BSD_MIN_BITS;
1050 pv = nakp;
1051 PUTCHAR(type, nakp);
1052 PUTCHAR(CILEN_BSD_COMPRESS, nakp);
1053 PUTCHAR(BSD_MAKE_OPT(BSD_CURRENT_VERSION, nb), nakp);
1057 * Check whether we can do BSD-Compress with the code
1058 * size they want. If the code size is too big, reduce
1059 * it until the kernel can cope and nak with that.
1060 * We only check this for the first option.
1062 if (p == p0) {
1063 for (;;) {
1064 res = ccp_test(f->unit, pv, CILEN_BSD_COMPRESS, 1);
1065 if (res > 0)
1066 break;
1067 if (res < 0 || nb == BSD_MIN_BITS || dont_nak) {
1068 newret = CODE_CONFREJ;
1069 break;
1071 if (newret == CODE_CONFACK) {
1072 BCOPY(pv, nakp, CILEN_BSD_COMPRESS);
1073 pv = nakp;
1074 nakp += CILEN_BSD_COMPRESS;
1075 newret = CODE_CONFNAK;
1077 --nb;
1078 pv[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, nb);
1081 break;
1083 case CI_PREDICTOR_1:
1084 if (!ao->predictor_1) {
1085 newret = CODE_CONFREJ;
1086 break;
1089 ho->predictor_1 = 1;
1090 if (clen != CILEN_PREDICTOR_1) {
1091 newret = CODE_CONFNAK;
1092 if (dont_nak)
1093 break;
1094 pv = nakp;
1095 PUTCHAR(type, nakp);
1096 PUTCHAR(CILEN_PREDICTOR_1, nakp);
1098 if (p == p0 &&
1099 ccp_test(f->unit, pv, CILEN_PREDICTOR_1, 1) <= 0) {
1100 newret = CODE_CONFREJ;
1102 break;
1104 case CI_PREDICTOR_2:
1105 if (!ao->predictor_2) {
1106 newret = CODE_CONFREJ;
1107 break;
1110 ho->predictor_2 = 1;
1111 if (clen != CILEN_PREDICTOR_2) {
1112 newret = CODE_CONFNAK;
1113 if (dont_nak)
1114 break;
1115 pv = nakp;
1116 PUTCHAR(type, nakp);
1117 PUTCHAR(CILEN_PREDICTOR_2, nakp);
1119 if (p == p0 &&
1120 ccp_test(f->unit, p, CILEN_PREDICTOR_2, 1) <= 0) {
1121 newret = CODE_CONFREJ;
1123 break;
1125 default:
1126 newret = CODE_CONFREJ;
1127 break;
1130 /* Cope with confused peers. */
1131 if (clen < 2)
1132 clen = 2;
1134 if (newret == CODE_CONFACK && ret != CODE_CONFACK)
1135 continue;
1136 if (newret == CODE_CONFNAK) {
1137 if (dont_nak) {
1138 newret = CODE_CONFREJ;
1139 } else {
1140 /* Ignore subsequent nakable things if rejecting. */
1141 if (ret == CODE_CONFREJ)
1142 continue;
1143 ret = CODE_CONFNAK;
1146 if (newret == CODE_CONFREJ) {
1147 ret = CODE_CONFREJ;
1148 if (p != rejp)
1149 BCOPY(p, rejp, clen);
1150 rejp += clen;
1154 switch (ret) {
1155 case CODE_CONFACK:
1156 *lenp = p - p0;
1157 break;
1158 case CODE_CONFNAK:
1159 *lenp = nakp - nak_buffer;
1160 BCOPY(nak_buffer, p0, *lenp);
1161 break;
1162 case CODE_CONFREJ:
1163 *lenp = rejp - p0;
1164 break;
1166 return ret;
1170 * Make a string name for a compression method (or 2).
1172 static char *
1173 method_name(opt, opt2)
1174 ccp_options *opt, *opt2;
1176 static char result[64];
1178 if (!ANY_COMPRESS(*opt))
1179 return "(none)";
1180 switch (opt->method) {
1181 case CI_DEFLATE:
1182 case CI_DEFLATE_DRAFT:
1183 if (opt2 != NULL && opt2->deflate_size != opt->deflate_size)
1184 (void) slprintf(result, sizeof(result), "Deflate%s (%d/%d)",
1185 (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""),
1186 opt->deflate_size, opt2->deflate_size);
1187 else
1188 (void) slprintf(result, sizeof(result), "Deflate%s (%d)",
1189 (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""),
1190 opt->deflate_size);
1191 break;
1192 case CI_BSD_COMPRESS:
1193 if (opt2 != NULL && opt2->bsd_bits != opt->bsd_bits)
1194 (void) slprintf(result, sizeof(result), "BSD-Compress (%d/%d)",
1195 opt->bsd_bits, opt2->bsd_bits);
1196 else
1197 (void) slprintf(result, sizeof(result), "BSD-Compress (%d)",
1198 opt->bsd_bits);
1199 break;
1200 case CI_PREDICTOR_1:
1201 return "Predictor 1";
1202 case CI_PREDICTOR_2:
1203 return "Predictor 2";
1204 #ifdef CI_STAC
1205 case CI_STAC:
1206 return "Stac";
1207 #endif
1208 #ifdef CI_MPPC
1209 case CI_MPPC:
1210 return "MS-PPC";
1211 #endif
1212 default:
1213 (void) slprintf(result, sizeof(result), "Method %d", opt->method);
1215 return result;
1219 * CCP has come up - inform the kernel driver and log a message.
1221 static void
1222 ccp_up(f)
1223 fsm *f;
1225 ccp_options *go = &ccp_gotoptions[f->unit];
1226 ccp_options *ho = &ccp_hisoptions[f->unit];
1227 char method1[64];
1230 * We're now open and up (running).
1232 ccp_flags_set(f->unit, 1, 1);
1233 if (ANY_COMPRESS(*go)) {
1234 if (ANY_COMPRESS(*ho)) {
1235 if (go->method == ho->method) {
1236 notice("%s compression enabled", method_name(go, ho));
1237 } else {
1238 (void) strlcpy(method1, method_name(go, NULL), sizeof(method1));
1239 notice("%s / %s compression enabled",
1240 method1, method_name(ho, NULL));
1242 } else
1243 notice("%s receive decompression enabled", method_name(go, NULL));
1244 } else if (ANY_COMPRESS(*ho))
1245 notice("%s transmit compression enabled", method_name(ho, NULL));
1249 * CCP has gone down - inform the kernel driver.
1251 static void
1252 ccp_down(f)
1253 fsm *f;
1255 if (ccp_localstate[f->unit] & RACK_PENDING)
1256 UNTIMEOUT(ccp_rack_timeout, f);
1257 /* Don't forget about peer's code rejects or ignoring of requests. */
1258 ccp_localstate[f->unit] &= ~RACK_PENDING & ~RREQ_REPEAT;
1259 /* We're still open, but no longer up. */
1260 ccp_flags_set(f->unit, 1, 0);
1263 static int
1264 ccp_printpkt(p, plen, printer, arg)
1265 u_char *p;
1266 int plen;
1267 void (*printer) __P((void *, const char *, ...));
1268 void *arg;
1270 u_char *p0, *optend, cichar;
1271 int code, id, len;
1272 int optlen, clen;
1273 u_short cishort;
1274 #ifdef CI_MPPC
1275 u_int32_t cilong;
1276 #endif
1278 p0 = p;
1279 if (plen < HEADERLEN) {
1280 printer(arg, "too short (%d<%d)", plen, HEADERLEN);
1281 return (0);
1283 GETCHAR(code, p);
1284 GETCHAR(id, p);
1285 GETSHORT(len, p);
1287 printer(arg, " %s id=0x%x", code_name(code, 1), id);
1289 if (len < HEADERLEN) {
1290 printer(arg, " header length %d<%d", len, HEADERLEN);
1291 return (HEADERLEN);
1293 if (len > plen) {
1294 printer(arg, " truncated (%d>%d)", len, plen);
1295 len = plen;
1297 len -= HEADERLEN;
1299 switch (code) {
1300 case CODE_CONFREQ:
1301 case CODE_CONFACK:
1302 case CODE_CONFNAK:
1303 case CODE_CONFREJ:
1304 /* print list of possible compression methods */
1305 while (len >= 2) {
1306 GETCHAR(code, p);
1307 GETCHAR(clen, p);
1308 optlen = clen;
1309 printer(arg, " <");
1310 if (optlen > len)
1311 optlen = len;
1312 if (optlen < 2)
1313 optlen = 2;
1314 len -= optlen;
1315 optend = p + optlen - 2;
1316 switch (code) {
1317 case CI_DEFLATE:
1318 case CI_DEFLATE_DRAFT:
1319 printer(arg, "deflate%s",
1320 (code == CI_DEFLATE_DRAFT? "(old#)": ""));
1321 if (clen != CILEN_DEFLATE)
1322 printer(arg, " length %d", clen);
1323 if (optlen >= CILEN_DEFLATE) {
1324 GETCHAR(cichar, p);
1325 printer(arg, " %d", DEFLATE_SIZE(cichar));
1326 if (DEFLATE_METHOD(cichar) != DEFLATE_METHOD_VAL)
1327 printer(arg, " method %d", DEFLATE_METHOD(cichar));
1328 GETCHAR(cichar, p);
1329 if (cichar != DEFLATE_CHK_SEQUENCE)
1330 printer(arg, " check %d", cichar);
1332 break;
1333 case CI_BSD_COMPRESS:
1334 printer(arg, "bsd");
1335 if (clen != CILEN_BSD_COMPRESS)
1336 printer(arg, " length %d", clen);
1337 if (optlen >= CILEN_BSD_COMPRESS) {
1338 GETCHAR(cichar, p);
1339 printer(arg, " v%d %d", BSD_VERSION(cichar),
1340 BSD_NBITS(cichar));
1342 break;
1343 case CI_PREDICTOR_1:
1344 printer(arg, "predictor-1");
1345 if (clen != CILEN_PREDICTOR_1)
1346 printer(arg, " length %d", clen);
1347 break;
1348 case CI_PREDICTOR_2:
1349 printer(arg, "predictor-2");
1350 if (clen != CILEN_PREDICTOR_2)
1351 printer(arg, " length %d", clen);
1352 break;
1353 #ifdef CI_STAC
1354 case CI_STAC:
1355 printer(arg, "Stac");
1356 if (clen != CILEN_STAC)
1357 printer(arg, " length %d", clen);
1358 if (optlen >= CILEN_STAC) {
1359 GETSHORT(cishort, p);
1360 GETCHAR(cichar, p);
1361 printer(arg, " h%d/m%d", cishort, cichar);
1363 break;
1364 #endif
1365 #ifdef CI_MPPC
1366 case CI_MPPC:
1367 /* There appears to be no good generic name for this one. */
1368 if (optlen >= CILEN_MPPC) {
1369 GETLONG(cilong, p);
1370 if (!(cilong & MPPC_COMP)) {
1371 if (cilong & MPPC_MPPE)
1372 printer(arg, "MPPE");
1373 else
1374 printer(arg, "MS-PPC?");
1375 } else {
1376 if (cilong & MPPC_MPPE)
1377 printer(arg, "MPPC+MPPE");
1378 else
1379 printer(arg, "MPPC");
1381 } else {
1382 printer(arg, "MS-?");
1384 if (clen != CILEN_STAC)
1385 printer(arg, " length %d", clen);
1386 break;
1387 #endif
1388 default:
1389 printer(arg, "typ%d len%d ", code, clen);
1390 break;
1392 if (p < optend) {
1393 if (p+8 < optend)
1394 printer(arg, " %.8B ...", p);
1395 else
1396 printer(arg, " %.*B", optend-p, p);
1397 p = optend;
1399 printer(arg, ">");
1401 break;
1403 case CODE_TERMACK:
1404 case CODE_TERMREQ:
1405 if (len > 0) {
1406 if (len == 2) {
1407 GETSHORT(cishort, p);
1408 printer(arg, " history %d", cishort);
1409 len = 0;
1410 } else if (*p >= ' ' && *p < 0x7f) {
1411 printer(arg, " ");
1412 print_string((char *)p, len, printer, arg);
1413 p += len;
1414 len = 0;
1417 break;
1420 /* dump out the rest of the packet in hex */
1421 if (len > 0) {
1422 if (len > 8)
1423 printer(arg, " %.8B ...", p);
1424 else
1425 printer(arg, " %.*B", len, p);
1426 p += len;
1429 return p - p0;
1433 * We have received a packet that the decompressor failed to
1434 * decompress. Here we would expect to issue a reset-request, but
1435 * Motorola has a patent on resetting the compressor as a result of
1436 * detecting an error in the decompressed data after decompression.
1437 * (See US patent 5,130,993; international patent publication number
1438 * WO 91/10289; Australian patent 73296/91.)
1440 * So we ask the kernel whether the error was detected after
1441 * decompression; if it was, we take CCP down, thus disabling
1442 * compression :-(, otherwise we issue the reset-request.
1444 /*ARGSUSED*/
1445 static void
1446 ccp_datainput(unit, pkt, len)
1447 int unit;
1448 u_char *pkt;
1449 int len;
1451 fsm *f;
1453 f = &ccp_fsm[unit];
1454 if (f->state == OPENED) {
1455 if (ccp_fatal_error(unit)) {
1457 * Disable compression by taking CCP down.
1459 error("Lost compression sync: disabling compression");
1460 ccp_close(unit, "Lost compression sync");
1461 } else {
1463 * Send a reset-request to reset the peer's compressor, if
1464 * possible. We don't do anything if we are still waiting
1465 * for an acknowledgement to a previous reset-request (to
1466 * avoid flooding the peer). We reopen CCP if the peer
1467 * doesn't like hearing about CCP Reset-Request (Cisco
1468 * sends CCP Code-Reject for Reset-Request). (Reopen
1469 * automatically clears the flags and cancels the
1470 * timeout.)
1472 if (ccp_localstate[f->unit] & RREQ_REJECTED) {
1473 dbglog("reopening CCP to reset peer's compressor");
1474 ccp_open(f->unit);
1475 } else if (ccp_localstate[f->unit] & RACK_PENDING) {
1476 /* Send another reset request; we're out of sequence. */
1477 ccp_localstate[f->unit] |= RREQ_REPEAT;
1478 } else {
1479 dbglog("sending CCP Reset-Request to reset peer's compressor");
1480 fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0);
1481 TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT);
1482 ccp_localstate[f->unit] |= RACK_PENDING;
1489 * Timeout waiting for reset-ack.
1491 static void
1492 ccp_rack_timeout(arg)
1493 void *arg;
1495 fsm *f = arg;
1497 /* Timeout; no longer pending. */
1498 ccp_localstate[f->unit] &= ~RACK_PENDING;
1500 /* Frankly, it's a coding flaw if this occurs. */
1501 if (f->state != OPENED)
1502 return;
1504 if (ccp_localstate[f->unit] & RREQ_IGNORED) {
1505 info("peer ignored our CCP Reset-Request twice; reopen instead");
1506 ccp_localstate[f->unit] =
1507 (ccp_localstate[f->unit] & ~RREQ_IGNORED) | RREQ_REJECTED;
1508 ccp_open(f->unit);
1509 } else if (ccp_localstate[f->unit] & RREQ_REPEAT) {
1510 dbglog("sending another CCP Reset-Request on timeout");
1511 fsm_sdata(f, CCP_RESETREQ, f->reqid, NULL, 0);
1512 TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT);
1513 ccp_localstate[f->unit] =
1514 (ccp_localstate[f->unit] & ~RREQ_REPEAT) | RREQ_IGNORED |
1515 RACK_PENDING;
1516 } else {
1517 dbglog("timeout waiting for CCP Reset-Ack; hope for the best");
1518 ccp_localstate[f->unit] |= RREQ_IGNORED;