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