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