xref: /illumos-gate/usr/src/cmd/cmd-inet/usr.bin/pppd/ccp.c (revision d1aea6f139360e9e7f1504facb24f8521047b15c)
1 /*
2  * ccp.c - PPP Compression Control Protocol.
3  *
4  * Copyright (c) 2000 by Sun Microsystems, Inc.
5  * All rights reserved.
6  *
7  * Copyright (c) 1994 The Australian National University.
8  * All rights reserved.
9  *
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.
16  *
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.
22  *
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.
29  */
30 /*
31  * Copyright (c) 2016 by Delphix. All rights reserved.
32  */
33 
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 $"
36 
37 #include <stdlib.h>
38 #include <string.h>
39 
40 #include "pppd.h"
41 #include "fsm.h"
42 #include "ccp.h"
43 #include <net/ppp-comp.h>
44 
45 #if !defined(lint) && !defined(_lint)
46 static const char rcsid[] = RCSID;
47 #endif
48 
49 /*
50  * Command-line options.
51  */
52 static int setbsdcomp __P((char **, option_t *));
53 static int setdeflate __P((char **, option_t *));
54 
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 },
87 
88     { NULL }
89 };
90 
91 /*
92  * Protocol entry points from main code.
93  */
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));
105 
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,
117     1,
118     "CCP",
119     "Compressed",
120     ccp_option_list,
121     NULL,
122     NULL,
123     NULL
124 };
125 
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 */
131 
132 /*
133  * Callbacks for fsm code.
134  */
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));
147 
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 */
164 };
165 
166 /*
167  * Local statics.
168  */
169 static void ccp_rack_timeout __P((void *));
170 static char * method_name __P((ccp_options *, ccp_options *));
171 
172 /*
173  * Do we want / did we get any compression?
174  */
175 #define ANY_COMPRESS(opt)	((opt).deflate || (opt).bsd_compress \
176 				 || (opt).predictor_1 || (opt).predictor_2)
177 
178 /*
179  * Local state (mainly for handling reset-reqs and reset-acks).
180  */
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 */
187 
188 #define RACKTIMEOUT	1	/* time in seconds between Reset-Requests */
189 
190 static int all_rejected[NUM_PPP];	/* we rejected all peer's options */
191 
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 */
197 
198 /*
199  * Option parsing.
200  */
201 /*ARGSUSED*/
202 static int
203 setbsdcomp(argv, opt)
204     char **argv;
205     option_t *opt;
206 {
207     int rbits, abits;
208     char *str, *endp;
209 
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);
215     }
216     if (*endp != '\0' || endp == str) {
217 	option_error("invalid parameter '%s' for bsdcomp option", *argv);
218 	return 0;
219     }
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;
225     }
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;
237 }
238 
239 /*ARGSUSED*/
240 static int
241 setdeflate(argv, opt)
242     char **argv;
243     option_t *opt;
244 {
245     int rbits, abits, def_rmax, def_amax;
246     char *str, *endp;
247 
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);
259     }
260 #ifdef COMP_TUNE
261     if (*endp == ',' && privileged_option) {
262 	str = ++endp;
263 	deflate_tune = strtol(str, &endp, 0);
264     }
265 #endif
266     if (*endp != '\0' || endp == str) {
267 	option_error("invalid parameter '%s' for deflate option", *argv);
268 	return 0;
269     }
270     if (privileged_option) {
271 	def_rmax = def_amax = DEFLATE_MAX_SIZE;
272     } else {
273 	def_rmax = deflate_rmax;
274 	def_amax = deflate_amax;
275     }
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;
286     }
287     if (privileged_option) {
288 	deflate_rmax = rbits;
289 	deflate_amax = abits;
290     }
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;
302 }
303 
304 
305 /*
306  * ccp_init - initialize CCP.
307  */
308 static void
309 ccp_init(unit)
310     int unit;
311 {
312     fsm *f = &ccp_fsm[unit];
313 
314     f->unit = unit;
315     f->protocol = PPP_CCP;
316     f->callbacks = &ccp_callbacks;
317     fsm_init(f);
318     f->flags |= OPT_RESTART;
319 
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));
324 
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;
333 
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;
338 
339     ccp_allowoptions[0].predictor_1 = 1;
340 }
341 
342 /*
343  * ccp_open - CCP is allowed to come up.
344  */
345 static void
346 ccp_open(unit)
347     int unit;
348 {
349     fsm *f = &ccp_fsm[unit];
350 
351     /*
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.
355      */
356     if (f->state != OPENED)
357 	ccp_flags_set(unit, 1, 0);
358 
359     /*
360      * Find out which compressors the kernel supports before
361      * deciding whether to open in silent mode.
362      */
363     ccp_resetci(f);
364     if (!ANY_COMPRESS(ccp_gotoptions[unit]))
365 	f->flags |= OPT_SILENT;
366 
367     fsm_open(f);
368 }
369 
370 /*
371  * ccp_close - Terminate CCP.
372  */
373 static void
374 ccp_close(unit, reason)
375     int unit;
376     char *reason;
377 {
378     ccp_flags_set(unit, 0, 0);
379     fsm_close(&ccp_fsm[unit], reason);
380 }
381 
382 /*
383  * ccp_lowerup - we may now transmit CCP packets.
384  */
385 static void
386 ccp_lowerup(unit)
387     int unit;
388 {
389     fsm_lowerup(&ccp_fsm[unit]);
390 }
391 
392 /*
393  * ccp_lowerdown - we may not transmit CCP packets.
394  */
395 static void
396 ccp_lowerdown(unit)
397     int unit;
398 {
399     fsm_lowerdown(&ccp_fsm[unit]);
400 }
401 
402 /*
403  * ccp_input - process a received CCP packet.
404  */
405 static void
406 ccp_input(unit, p, len)
407     int unit;
408     u_char *p;
409     int len;
410 {
411     fsm *f = &ccp_fsm[unit];
412     int oldstate;
413 
414     /*
415      * Check for a terminate-request so we can print a message.
416      */
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.");
421 
422     /*
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.)
425      */
426     if (oldstate == REQSENT && p[0] == CODE_TERMACK
427 	&& !ANY_COMPRESS(ccp_gotoptions[unit]))
428 	ccp_close(unit, "No compression negotiated");
429 }
430 
431 /*
432  * Handle a CCP-specific code.
433  */
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;
440 {
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;
450 
451     case CCP_RESETACK:
452 	/*
453 	 * Note that the compression module isn't picky about ID
454 	 * numbers and such.
455 	 */
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);
460 	}
461 	break;
462 
463     default:
464 	/* Tell fsm to send code reject */
465 	return (0);
466     }
467 
468     return (1);
469 }
470 
471 /*
472  * Handle Code-Reject for one of our extended codes by dropping back to
473  * reopen as mechanism to restart compression.
474  */
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;
482 {
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);
489 	}
490 	ccp_localstate[f->unit] |= RREQ_REJECTED;
491 	return (0);
492 
493     case CCP_RESETACK:
494 	/*
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.
498 	 */
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;
504 
505     default:
506 	f->term_reason = "peer sent invalid Code-Reject";
507 	break;
508     }
509 
510     f->term_reason_len = strlen(f->term_reason);
511     return (1);
512 }
513 
514 /*
515  * ccp_protrej - peer doesn't talk CCP.
516  */
517 static void
518 ccp_protrej(unit)
519     int unit;
520 {
521     /* Neither open nor up. */
522     ccp_flags_set(unit, 0, 0);
523     fsm_lowerdown(&ccp_fsm[unit]);
524 }
525 
526 /*
527  * ccp_resetci - initialize at start of negotiation.
528  */
529 static void
530 ccp_resetci(f)
531     fsm *f;
532 {
533     ccp_options *go = &ccp_gotoptions[f->unit];
534     u_char opt_buf[16];
535 
536     *go = ccp_wantoptions[f->unit];
537     all_rejected[f->unit] = 0;
538 
539     /*
540      * Check whether the kernel knows about the various
541      * decompression methods we might request.
542      */
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;
549     }
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;
558 	}
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;
566 	}
567 	if (!go->deflate_correct && !go->deflate_draft)
568 	    go->deflate = 0;
569     }
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;
575     }
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;
581     }
582 }
583 
584 /*
585  * ccp_cilen - Return total length of our configuration info.
586  */
587 static int
588 ccp_cilen(f)
589     fsm *f;
590 {
591     ccp_options *go = &ccp_gotoptions[f->unit];
592 
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);
598 }
599 
600 /*
601  * ccp_addci - put our requests in a packet.
602  */
603 static void
604 ccp_addci(f, p, lenp)
605     fsm *f;
606     u_char *p;
607     int *lenp;
608 {
609     int res;
610     ccp_options *go = &ccp_gotoptions[f->unit];
611     u_char *p0 = p;
612 
613     /*
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.
617      */
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;
628 	    }
629 	    if (res < 0 || go->deflate_size <= DEFLATE_MIN_SIZE+1) {
630 		go->deflate = 0;
631 		break;
632 	    }
633 	    --go->deflate_size;
634 	    p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
635 	}
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;
643 	}
644     }
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;
657 		}
658 		if (res < 0 || go->bsd_bits <= BSD_MIN_BITS) {
659 		    go->bsd_compress = 0;
660 		    break;
661 		}
662 		--go->bsd_bits;
663 		p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
664 	    }
665 	}
666     }
667     /*
668      * Prefer Predictor-1 over Predictor-2.  (The latter requires the use
669      * of LAP-B and has no known implementations.)
670      */
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;
678 	}
679     }
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;
687 	}
688     }
689 
690     go->method = (p > p0)? p0[0]: -1;
691 
692     *lenp = p - p0;
693 }
694 
695 /*
696  * ccp_ackci - process a received configure-ack, and return
697  * 1 iff the packet was OK.
698  */
699 static int
700 ccp_ackci(f, p, len)
701     fsm *f;
702     u_char *p;
703     int len;
704 {
705     ccp_options *go = &ccp_gotoptions[f->unit];
706     u_char *p0 = p;
707 
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;
719     }
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;
731     }
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;
742     }
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;
752     }
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;
762     }
763 
764     /* Peer cannot ack something that wasn't sent. */
765     if (len != 0)
766 	return 0;
767     return 1;
768 }
769 
770 /*
771  * ccp_nakci - process received configure-nak.
772  * Returns 1 iff the nak was OK.
773  */
774 static int
775 ccp_nakci(f, p, len)
776     fsm *f;
777     u_char *p;
778     int len;
779 {
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 */
783 
784     BZERO(&no, sizeof(no));
785     try = *go;
786 
787     if (go->deflate && go->deflate_correct && len >= CILEN_DEFLATE &&
788 	p[0] == CI_DEFLATE) {
789 	no.deflate = 1;
790 	/*
791 	 * Peer wants us to use a different code size or something.
792 	 * Stop asking for Deflate if we don't understand its suggestion.
793 	 */
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];
803     }
804 
805     if (go->deflate && go->deflate_draft && len >= CILEN_DEFLATE &&
806 	p[0] == CI_DEFLATE_DRAFT) {
807 	no.deflate = 1;
808 	/*
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.)
814 	 */
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];
824     }
825 
826     if (!try.deflate_correct && !try.deflate_draft)
827 	try.deflate = 0;
828 
829     if (go->bsd_compress && len >= CILEN_BSD_COMPRESS &&
830 	p[0] == CI_BSD_COMPRESS) {
831 	no.bsd_compress = 1;
832 	/*
833 	 * Peer wants us to use a different number of bits
834 	 * or a different version.
835 	 */
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];
843     }
844 
845     /*
846      * Predictor-1 and 2 have no options, so they can't be Naked.
847      *
848      * There may be remaining options but we ignore them.
849      */
850 
851     if (f->state != OPENED)
852 	*go = try;
853     return 1;
854 }
855 
856 /*
857  * ccp_rejci - peer rejects some of our suggested compression methods.
858  */
859 static int
860 ccp_rejci(f, p, len)
861     fsm *f;
862     u_char *p;
863     int len;
864 {
865     ccp_options *go = &ccp_gotoptions[f->unit];
866     ccp_options try;		/* options to request next time */
867 
868     try = *go;
869 
870     /*
871      * Cope with empty configure-rejects by ceasing to send
872      * configure-requests.
873      */
874     if (len == 0 && all_rejected[f->unit])
875 	return -1;
876 
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;
885     }
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;
894     }
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;
904     }
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;
910     }
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;
916     }
917 
918     if (len != 0)
919 	return 0;
920 
921     if (f->state != OPENED)
922 	*go = try;
923 
924     return 1;
925 }
926 
927 /*
928  * ccp_reqci - process a received configure-request.
929  *
930  * Returns CODE_CONFACK, CODE_CONFNAK or CODE_CONFREJ and the packet
931  * is modified appropriately.
932  */
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;
939 {
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];
945 
946     ret = CODE_CONFACK;
947     rejp = p0 = p;
948     nakp = nak_buffer;
949     len = *lenp;
950 
951     BZERO(ho, sizeof(ccp_options));
952     ho->method = (len > 0)? p[0]: -1;
953 
954     for (; len > 0; len -= clen, p += clen) {
955 	newret = CODE_CONFACK;
956 	if (len < 2 || p[1] > len) {
957 	    /*
958 	     * RFC 1661 page 40 -- if the option extends beyond the
959 	     * packet, then discard the entire packet.
960 	     */
961 	    return (0);
962 	}
963 
964 	type = p[0];
965 	clen = p[1];
966 
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;
976 	    }
977 
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);
997 	    }
998 
999 	    /*
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.
1004 	     */
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;
1013 		    }
1014 		    if (newret == CODE_CONFACK) {
1015 			BCOPY(pv, nakp, CILEN_DEFLATE);
1016 			pv = nakp;
1017 			nakp += CILEN_DEFLATE;
1018 			newret = CODE_CONFNAK;
1019 		    }
1020 		    --nb;
1021 		    pv[2] = DEFLATE_MAKE_OPT(nb);
1022 		}
1023 #ifdef COMP_TUNE
1024 		/* Tune Deflate compression effort. */
1025 		if (newret == CODE_CONFACK)
1026 		    ccp_tune(f->unit, deflate_tune);
1027 #endif
1028 	    }
1029 	    break;
1030 
1031 	case CI_BSD_COMPRESS:
1032 	    if (!ao->bsd_compress) {
1033 		newret = CODE_CONFREJ;
1034 		break;
1035 	    }
1036 
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);
1054 	    }
1055 
1056 	    /*
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.
1061 	     */
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;
1070 		    }
1071 		    if (newret == CODE_CONFACK) {
1072 			BCOPY(pv, nakp, CILEN_BSD_COMPRESS);
1073 			pv = nakp;
1074 			nakp += CILEN_BSD_COMPRESS;
1075 			newret = CODE_CONFNAK;
1076 		    }
1077 		    --nb;
1078 		    pv[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, nb);
1079 		}
1080 	    }
1081 	    break;
1082 
1083 	case CI_PREDICTOR_1:
1084 	    if (!ao->predictor_1) {
1085 		newret = CODE_CONFREJ;
1086 		break;
1087 	    }
1088 
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);
1097 	    }
1098 	    if (p == p0 &&
1099 		ccp_test(f->unit, pv, CILEN_PREDICTOR_1, 1) <= 0) {
1100 		newret = CODE_CONFREJ;
1101 	    }
1102 	    break;
1103 
1104 	case CI_PREDICTOR_2:
1105 	    if (!ao->predictor_2) {
1106 		newret = CODE_CONFREJ;
1107 		break;
1108 	    }
1109 
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);
1118 	    }
1119 	    if (p == p0 &&
1120 		ccp_test(f->unit, p, CILEN_PREDICTOR_2, 1) <= 0) {
1121 		newret = CODE_CONFREJ;
1122 	    }
1123 	    break;
1124 
1125 	default:
1126 	    newret = CODE_CONFREJ;
1127 	    break;
1128 	}
1129 
1130 	/* Cope with confused peers. */
1131 	if (clen < 2)
1132 	    clen = 2;
1133 
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;
1144 	    }
1145 	}
1146 	if (newret == CODE_CONFREJ) {
1147 	    ret = CODE_CONFREJ;
1148 	    if (p != rejp)
1149 		BCOPY(p, rejp, clen);
1150 	    rejp += clen;
1151 	}
1152     }
1153 
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;
1165     }
1166     return ret;
1167 }
1168 
1169 /*
1170  * Make a string name for a compression method (or 2).
1171  */
1172 static char *
1173 method_name(opt, opt2)
1174     ccp_options *opt, *opt2;
1175 {
1176     static char result[64];
1177 
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);
1214     }
1215     return result;
1216 }
1217 
1218 /*
1219  * CCP has come up - inform the kernel driver and log a message.
1220  */
1221 static void
1222 ccp_up(f)
1223     fsm *f;
1224 {
1225     ccp_options *go = &ccp_gotoptions[f->unit];
1226     ccp_options *ho = &ccp_hisoptions[f->unit];
1227     char method1[64];
1228 
1229     /*
1230      * We're now open and up (running).
1231      */
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));
1241 	    }
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));
1246 }
1247 
1248 /*
1249  * CCP has gone down - inform the kernel driver.
1250  */
1251 static void
1252 ccp_down(f)
1253     fsm *f;
1254 {
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);
1261 }
1262 
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;
1269 {
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
1277 
1278     p0 = p;
1279     if (plen < HEADERLEN) {
1280 	printer(arg, "too short (%d<%d)", plen, HEADERLEN);
1281 	return (0);
1282     }
1283     GETCHAR(code, p);
1284     GETCHAR(id, p);
1285     GETSHORT(len, p);
1286 
1287     printer(arg, " %s id=0x%x", code_name(code, 1), id);
1288 
1289     if (len < HEADERLEN) {
1290 	printer(arg, " header length %d<%d", len, HEADERLEN);
1291 	return (HEADERLEN);
1292     }
1293     if (len > plen) {
1294 	printer(arg, " truncated (%d>%d)", len, plen);
1295 	len = plen;
1296     }
1297     len -= HEADERLEN;
1298 
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);
1331 		}
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));
1341 		}
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);
1362 		}
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");
1380 		    }
1381 		} else {
1382 		    printer(arg, "MS-?");
1383 		}
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;
1391 	    }
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;
1398 	    }
1399 	    printer(arg, ">");
1400 	}
1401 	break;
1402 
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;
1415 	    }
1416 	}
1417 	break;
1418     }
1419 
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;
1427     }
1428 
1429     return p - p0;
1430 }
1431 
1432 /*
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.)
1439  *
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.
1443  */
1444 /*ARGSUSED*/
1445 static void
1446 ccp_datainput(unit, pkt, len)
1447     int unit;
1448     u_char *pkt;
1449     int len;
1450 {
1451     fsm *f;
1452 
1453     f = &ccp_fsm[unit];
1454     if (f->state == OPENED) {
1455 	if (ccp_fatal_error(unit)) {
1456 	    /*
1457 	     * Disable compression by taking CCP down.
1458 	     */
1459 	    error("Lost compression sync: disabling compression");
1460 	    ccp_close(unit, "Lost compression sync");
1461 	} else {
1462 	    /*
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.)
1471 	     */
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;
1483 	    }
1484 	}
1485     }
1486 }
1487 
1488 /*
1489  * Timeout waiting for reset-ack.
1490  */
1491 static void
1492 ccp_rack_timeout(arg)
1493     void *arg;
1494 {
1495     fsm *f = arg;
1496 
1497     /* Timeout; no longer pending. */
1498     ccp_localstate[f->unit] &= ~RACK_PENDING;
1499 
1500     /* Frankly, it's a coding flaw if this occurs. */
1501     if (f->state != OPENED)
1502 	return;
1503 
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;
1519     }
1520 }
1521