1/*
2 * ccp.c - PPP Compression Control Protocol.
3 *
4 * Copyright (c) 1994 The Australian National University.
5 * All rights reserved.
6 *
7 * Permission to use, copy, modify, and distribute this software and its
8 * documentation is hereby granted, provided that the above copyright
9 * notice appears in all copies.  This software is provided without any
10 * warranty, express or implied. The Australian National University
11 * makes no representations about the suitability of this software for
12 * any purpose.
13 *
14 * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
15 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
16 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
17 * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
18 * OF SUCH DAMAGE.
19 *
20 * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
21 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
22 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
23 * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
24 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
25 * OR MODIFICATIONS.
26 */
27
28#define RCSID	"$Id: ccp.c,v 1.1.1.1 2008/10/15 03:30:12 james26_jang Exp $"
29
30#include <stdlib.h>
31#include <string.h>
32
33#include <pppd.h>
34#include "fsm.h"
35#include "ccp.h"
36#include <net/ppp-comp.h>
37
38static const char rcsid[] = RCSID;
39
40/*
41 * Unfortunately there is a bug in zlib which means that using a
42 * size of 8 (window size = 256) for Deflate compression will cause
43 * buffer overruns and kernel crashes in the deflate module.
44 * Until this is fixed we only accept sizes in the range 9 .. 15.
45 * Thanks to James Carlson for pointing this out.
46 */
47#define DEFLATE_MIN_WORKS	9
48
49/*
50 * Command-line options.
51 */
52static int setbsdcomp __P((char **));
53static int setdeflate __P((char **));
54static char bsd_value[8];
55static char deflate_value[8];
56
57static option_t ccp_option_list[] = {
58    { "noccp", o_bool, &ccp_protent.enabled_flag,
59      "Disable CCP negotiation" },
60    { "-ccp", o_bool, &ccp_protent.enabled_flag,
61      "Disable CCP negotiation", OPT_ALIAS },
62
63    { "bsdcomp", o_special, (void *)setbsdcomp,
64      "Request BSD-Compress packet compression",
65      OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, bsd_value },
66    { "nobsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress,
67      "don't allow BSD-Compress", OPT_PRIOSUB | OPT_A2CLR,
68      &ccp_allowoptions[0].bsd_compress },
69    { "-bsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress,
70      "don't allow BSD-Compress", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR,
71      &ccp_allowoptions[0].bsd_compress },
72
73    { "deflate", o_special, (void *)setdeflate,
74      "request Deflate compression",
75      OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, deflate_value },
76    { "nodeflate", o_bool, &ccp_wantoptions[0].deflate,
77      "don't allow Deflate compression", OPT_PRIOSUB | OPT_A2CLR,
78      &ccp_allowoptions[0].deflate },
79    { "-deflate", o_bool, &ccp_wantoptions[0].deflate,
80      "don't allow Deflate compression", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR,
81      &ccp_allowoptions[0].deflate },
82
83    { "nodeflatedraft", o_bool, &ccp_wantoptions[0].deflate_draft,
84      "don't use draft deflate #", OPT_A2COPY,
85      &ccp_allowoptions[0].deflate_draft },
86
87    { "predictor1", o_bool, &ccp_wantoptions[0].predictor_1,
88      "request Predictor-1", 1, &ccp_allowoptions[0].predictor_1, OPT_PRIO },
89    { "nopredictor1", o_bool, &ccp_wantoptions[0].predictor_1,
90      "don't allow Predictor-1", OPT_PRIOSUB | OPT_A2CLR,
91      &ccp_allowoptions[0].predictor_1 },
92    { "-predictor1", o_bool, &ccp_wantoptions[0].predictor_1,
93      "don't allow Predictor-1", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR,
94      &ccp_allowoptions[0].predictor_1 },
95
96    { NULL }
97};
98
99/*
100 * Protocol entry points from main code.
101 */
102static void ccp_init __P((int unit));
103static void ccp_open __P((int unit));
104static void ccp_close __P((int unit, char *));
105static void ccp_lowerup __P((int unit));
106static void ccp_lowerdown __P((int));
107static void ccp_input __P((int unit, u_char *pkt, int len));
108static void ccp_protrej __P((int unit));
109static int  ccp_printpkt __P((u_char *pkt, int len,
110			      void (*printer) __P((void *, char *, ...)),
111			      void *arg));
112static void ccp_datainput __P((int unit, u_char *pkt, int len));
113
114struct protent ccp_protent = {
115    PPP_CCP,
116    ccp_init,
117    ccp_input,
118    ccp_protrej,
119    ccp_lowerup,
120    ccp_lowerdown,
121    ccp_open,
122    ccp_close,
123    ccp_printpkt,
124    ccp_datainput,
125    1,
126    "CCP",
127    "Compressed",
128    ccp_option_list,
129    NULL,
130    NULL,
131    NULL
132};
133
134fsm ccp_fsm[NUM_PPP];
135ccp_options ccp_wantoptions[NUM_PPP];	/* what to request the peer to use */
136ccp_options ccp_gotoptions[NUM_PPP];	/* what the peer agreed to do */
137ccp_options ccp_allowoptions[NUM_PPP];	/* what we'll agree to do */
138ccp_options ccp_hisoptions[NUM_PPP];	/* what we agreed to do */
139
140/*
141 * Callbacks for fsm code.
142 */
143static void ccp_resetci __P((fsm *));
144static int  ccp_cilen __P((fsm *));
145static void ccp_addci __P((fsm *, u_char *, int *));
146static int  ccp_ackci __P((fsm *, u_char *, int));
147static int  ccp_nakci __P((fsm *, u_char *, int));
148static int  ccp_rejci __P((fsm *, u_char *, int));
149static int  ccp_reqci __P((fsm *, u_char *, int *, int));
150static void ccp_up __P((fsm *));
151static void ccp_down __P((fsm *));
152static int  ccp_extcode __P((fsm *, int, int, u_char *, int));
153static void ccp_rack_timeout __P((void *));
154static char *method_name __P((ccp_options *, ccp_options *));
155
156static fsm_callbacks ccp_callbacks = {
157    ccp_resetci,
158    ccp_cilen,
159    ccp_addci,
160    ccp_ackci,
161    ccp_nakci,
162    ccp_rejci,
163    ccp_reqci,
164    ccp_up,
165    ccp_down,
166    NULL,
167    NULL,
168    NULL,
169    NULL,
170    ccp_extcode,
171    "CCP"
172};
173
174/*
175 * Do we want / did we get any compression?
176 */
177#define ANY_COMPRESS(opt)	((opt).deflate || (opt).bsd_compress \
178				 || (opt).predictor_1 || (opt).predictor_2)
179
180/*
181 * Local state (mainly for handling reset-reqs and reset-acks).
182 */
183static int ccp_localstate[NUM_PPP];
184#define RACK_PENDING	1	/* waiting for reset-ack */
185#define RREQ_REPEAT	2	/* send another reset-req if no reset-ack */
186
187#define RACKTIMEOUT	1	/* second */
188
189static int all_rejected[NUM_PPP];	/* we rejected all peer's options */
190
191/*
192 * Option parsing.
193 */
194static int
195setbsdcomp(argv)
196    char **argv;
197{
198    int rbits, abits;
199    char *str, *endp;
200
201    str = *argv;
202    abits = rbits = strtol(str, &endp, 0);
203    if (endp != str && *endp == ',') {
204	str = endp + 1;
205	abits = strtol(str, &endp, 0);
206    }
207    if (*endp != 0 || endp == str) {
208	option_error("invalid parameter '%s' for bsdcomp option", *argv);
209	return 0;
210    }
211    if ((rbits != 0 && (rbits < BSD_MIN_BITS || rbits > BSD_MAX_BITS))
212	|| (abits != 0 && (abits < BSD_MIN_BITS || abits > BSD_MAX_BITS))) {
213	option_error("bsdcomp option values must be 0 or %d .. %d",
214		     BSD_MIN_BITS, BSD_MAX_BITS);
215	return 0;
216    }
217    if (rbits > 0) {
218	ccp_wantoptions[0].bsd_compress = 1;
219	ccp_wantoptions[0].bsd_bits = rbits;
220    } else
221	ccp_wantoptions[0].bsd_compress = 0;
222    if (abits > 0) {
223	ccp_allowoptions[0].bsd_compress = 1;
224	ccp_allowoptions[0].bsd_bits = abits;
225    } else
226	ccp_allowoptions[0].bsd_compress = 0;
227    slprintf(bsd_value, sizeof(bsd_value),
228	     rbits == abits? "%d": "%d,%d", rbits, abits);
229
230    return 1;
231}
232
233static int
234setdeflate(argv)
235    char **argv;
236{
237    int rbits, abits;
238    char *str, *endp;
239
240    str = *argv;
241    abits = rbits = strtol(str, &endp, 0);
242    if (endp != str && *endp == ',') {
243	str = endp + 1;
244	abits = strtol(str, &endp, 0);
245    }
246    if (*endp != 0 || endp == str) {
247	option_error("invalid parameter '%s' for deflate option", *argv);
248	return 0;
249    }
250    if ((rbits != 0 && (rbits < DEFLATE_MIN_SIZE || rbits > DEFLATE_MAX_SIZE))
251	|| (abits != 0 && (abits < DEFLATE_MIN_SIZE
252			  || abits > DEFLATE_MAX_SIZE))) {
253	option_error("deflate option values must be 0 or %d .. %d",
254		     DEFLATE_MIN_SIZE, DEFLATE_MAX_SIZE);
255	return 0;
256    }
257    if (rbits == DEFLATE_MIN_SIZE || abits == DEFLATE_MIN_SIZE) {
258	if (rbits == DEFLATE_MIN_SIZE)
259	    rbits = DEFLATE_MIN_WORKS;
260	if (abits == DEFLATE_MIN_SIZE)
261	    abits = DEFLATE_MIN_WORKS;
262	warn("deflate option value of %d changed to %d to avoid zlib bug",
263	     DEFLATE_MIN_SIZE, DEFLATE_MIN_WORKS);
264    }
265    if (rbits > 0) {
266	ccp_wantoptions[0].deflate = 1;
267	ccp_wantoptions[0].deflate_size = rbits;
268    } else
269	ccp_wantoptions[0].deflate = 0;
270    if (abits > 0) {
271	ccp_allowoptions[0].deflate = 1;
272	ccp_allowoptions[0].deflate_size = abits;
273    } else
274	ccp_allowoptions[0].deflate = 0;
275    slprintf(deflate_value, sizeof(deflate_value),
276	     rbits == abits? "%d": "%d,%d", rbits, abits);
277
278    return 1;
279}
280
281/*
282 * ccp_init - initialize CCP.
283 */
284static void
285ccp_init(unit)
286    int unit;
287{
288    fsm *f = &ccp_fsm[unit];
289
290    f->unit = unit;
291    f->protocol = PPP_CCP;
292    f->callbacks = &ccp_callbacks;
293    fsm_init(f);
294
295    memset(&ccp_wantoptions[unit],  0, sizeof(ccp_options));
296    memset(&ccp_gotoptions[unit],   0, sizeof(ccp_options));
297    memset(&ccp_allowoptions[unit], 0, sizeof(ccp_options));
298    memset(&ccp_hisoptions[unit],   0, sizeof(ccp_options));
299
300    ccp_wantoptions[0].deflate = 1;
301    ccp_wantoptions[0].deflate_size = DEFLATE_MAX_SIZE;
302    ccp_wantoptions[0].deflate_correct = 1;
303    ccp_wantoptions[0].deflate_draft = 1;
304    ccp_allowoptions[0].deflate = 1;
305    ccp_allowoptions[0].deflate_size = DEFLATE_MAX_SIZE;
306    ccp_allowoptions[0].deflate_correct = 1;
307    ccp_allowoptions[0].deflate_draft = 1;
308
309    ccp_wantoptions[0].bsd_compress = 1;
310    ccp_wantoptions[0].bsd_bits = BSD_MAX_BITS;
311    ccp_allowoptions[0].bsd_compress = 1;
312    ccp_allowoptions[0].bsd_bits = BSD_MAX_BITS;
313
314    ccp_allowoptions[0].predictor_1 = 1;
315}
316
317/*
318 * ccp_open - CCP is allowed to come up.
319 */
320static void
321ccp_open(unit)
322    int unit;
323{
324    fsm *f = &ccp_fsm[unit];
325
326    if (f->state != OPENED)
327	ccp_flags_set(unit, 1, 0);
328
329    /*
330     * Find out which compressors the kernel supports before
331     * deciding whether to open in silent mode.
332     */
333    ccp_resetci(f);
334    if (!ANY_COMPRESS(ccp_gotoptions[unit]))
335	f->flags |= OPT_SILENT;
336
337    fsm_open(f);
338}
339
340/*
341 * ccp_close - Terminate CCP.
342 */
343static void
344ccp_close(unit, reason)
345    int unit;
346    char *reason;
347{
348    ccp_flags_set(unit, 0, 0);
349    fsm_close(&ccp_fsm[unit], reason);
350}
351
352/*
353 * ccp_lowerup - we may now transmit CCP packets.
354 */
355static void
356ccp_lowerup(unit)
357    int unit;
358{
359    fsm_lowerup(&ccp_fsm[unit]);
360}
361
362/*
363 * ccp_lowerdown - we may not transmit CCP packets.
364 */
365static void
366ccp_lowerdown(unit)
367    int unit;
368{
369    fsm_lowerdown(&ccp_fsm[unit]);
370}
371
372/*
373 * ccp_input - process a received CCP packet.
374 */
375static void
376ccp_input(unit, p, len)
377    int unit;
378    u_char *p;
379    int len;
380{
381    fsm *f = &ccp_fsm[unit];
382    int oldstate;
383
384    /*
385     * Check for a terminate-request so we can print a message.
386     */
387    oldstate = f->state;
388    fsm_input(f, p, len);
389    if (oldstate == OPENED && p[0] == TERMREQ && f->state != OPENED)
390	notice("Compression disabled by peer.");
391
392    /*
393     * If we get a terminate-ack and we're not asking for compression,
394     * close CCP.
395     */
396    if (oldstate == REQSENT && p[0] == TERMACK
397	&& !ANY_COMPRESS(ccp_gotoptions[unit]))
398	ccp_close(unit, "No compression negotiated");
399}
400
401/*
402 * Handle a CCP-specific code.
403 */
404static int
405ccp_extcode(f, code, id, p, len)
406    fsm *f;
407    int code, id;
408    u_char *p;
409    int len;
410{
411    switch (code) {
412    case CCP_RESETREQ:
413	if (f->state != OPENED)
414	    break;
415	/* send a reset-ack, which the transmitter will see and
416	   reset its compression state. */
417	fsm_sdata(f, CCP_RESETACK, id, NULL, 0);
418	break;
419
420    case CCP_RESETACK:
421	if (ccp_localstate[f->unit] & RACK_PENDING && id == f->reqid) {
422	    ccp_localstate[f->unit] &= ~(RACK_PENDING | RREQ_REPEAT);
423	    UNTIMEOUT(ccp_rack_timeout, f);
424	}
425	break;
426
427    default:
428	return 0;
429    }
430
431    return 1;
432}
433
434/*
435 * ccp_protrej - peer doesn't talk CCP.
436 */
437static void
438ccp_protrej(unit)
439    int unit;
440{
441    ccp_flags_set(unit, 0, 0);
442    fsm_lowerdown(&ccp_fsm[unit]);
443}
444
445/*
446 * ccp_resetci - initialize at start of negotiation.
447 */
448static void
449ccp_resetci(f)
450    fsm *f;
451{
452    ccp_options *go = &ccp_gotoptions[f->unit];
453    u_char opt_buf[16];
454
455    *go = ccp_wantoptions[f->unit];
456    all_rejected[f->unit] = 0;
457
458    /*
459     * Check whether the kernel knows about the various
460     * compression methods we might request.
461     */
462    if (go->bsd_compress) {
463	opt_buf[0] = CI_BSD_COMPRESS;
464	opt_buf[1] = CILEN_BSD_COMPRESS;
465	opt_buf[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, BSD_MIN_BITS);
466	if (ccp_test(f->unit, opt_buf, CILEN_BSD_COMPRESS, 0) <= 0)
467	    go->bsd_compress = 0;
468    }
469    if (go->deflate) {
470	if (go->deflate_correct) {
471	    opt_buf[0] = CI_DEFLATE;
472	    opt_buf[1] = CILEN_DEFLATE;
473	    opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_WORKS);
474	    opt_buf[3] = DEFLATE_CHK_SEQUENCE;
475	    if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0)
476		go->deflate_correct = 0;
477	}
478	if (go->deflate_draft) {
479	    opt_buf[0] = CI_DEFLATE_DRAFT;
480	    opt_buf[1] = CILEN_DEFLATE;
481	    opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_WORKS);
482	    opt_buf[3] = DEFLATE_CHK_SEQUENCE;
483	    if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0)
484		go->deflate_draft = 0;
485	}
486	if (!go->deflate_correct && !go->deflate_draft)
487	    go->deflate = 0;
488    }
489    if (go->predictor_1) {
490	opt_buf[0] = CI_PREDICTOR_1;
491	opt_buf[1] = CILEN_PREDICTOR_1;
492	if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_1, 0) <= 0)
493	    go->predictor_1 = 0;
494    }
495    if (go->predictor_2) {
496	opt_buf[0] = CI_PREDICTOR_2;
497	opt_buf[1] = CILEN_PREDICTOR_2;
498	if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_2, 0) <= 0)
499	    go->predictor_2 = 0;
500    }
501}
502
503/*
504 * ccp_cilen - Return total length of our configuration info.
505 */
506static int
507ccp_cilen(f)
508    fsm *f;
509{
510    ccp_options *go = &ccp_gotoptions[f->unit];
511
512    return (go->bsd_compress? CILEN_BSD_COMPRESS: 0)
513	+ (go->deflate? CILEN_DEFLATE: 0)
514	+ (go->predictor_1? CILEN_PREDICTOR_1: 0)
515	+ (go->predictor_2? CILEN_PREDICTOR_2: 0);
516}
517
518/*
519 * ccp_addci - put our requests in a packet.
520 */
521static void
522ccp_addci(f, p, lenp)
523    fsm *f;
524    u_char *p;
525    int *lenp;
526{
527    int res;
528    ccp_options *go = &ccp_gotoptions[f->unit];
529    u_char *p0 = p;
530
531    /*
532     * Add the compression types that we can receive, in decreasing
533     * preference order.  Get the kernel to allocate the first one
534     * in case it gets Acked.
535     */
536    if (go->deflate) {
537	p[0] = go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT;
538	p[1] = CILEN_DEFLATE;
539	p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
540	p[3] = DEFLATE_CHK_SEQUENCE;
541	for (;;) {
542	    res = ccp_test(f->unit, p, CILEN_DEFLATE, 0);
543	    if (res > 0) {
544		p += CILEN_DEFLATE;
545		break;
546	    }
547	    if (res < 0 || go->deflate_size <= DEFLATE_MIN_WORKS) {
548		go->deflate = 0;
549		break;
550	    }
551	    --go->deflate_size;
552	    p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
553	}
554	if (p != p0 && go->deflate_correct && go->deflate_draft) {
555	    p[0] = CI_DEFLATE_DRAFT;
556	    p[1] = CILEN_DEFLATE;
557	    p[2] = p[2 - CILEN_DEFLATE];
558	    p[3] = DEFLATE_CHK_SEQUENCE;
559	    p += CILEN_DEFLATE;
560	}
561    }
562    if (go->bsd_compress) {
563	p[0] = CI_BSD_COMPRESS;
564	p[1] = CILEN_BSD_COMPRESS;
565	p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
566	if (p != p0) {
567	    p += CILEN_BSD_COMPRESS;	/* not the first option */
568	} else {
569	    for (;;) {
570		res = ccp_test(f->unit, p, CILEN_BSD_COMPRESS, 0);
571		if (res > 0) {
572		    p += CILEN_BSD_COMPRESS;
573		    break;
574		}
575		if (res < 0 || go->bsd_bits <= BSD_MIN_BITS) {
576		    go->bsd_compress = 0;
577		    break;
578		}
579		--go->bsd_bits;
580		p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
581	    }
582	}
583    }
584    if (go->predictor_1) {
585	p[0] = CI_PREDICTOR_1;
586	p[1] = CILEN_PREDICTOR_1;
587	if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_1, 0) <= 0) {
588	    go->predictor_1 = 0;
589	} else {
590	    p += CILEN_PREDICTOR_1;
591	}
592    }
593    if (go->predictor_2) {
594	p[0] = CI_PREDICTOR_2;
595	p[1] = CILEN_PREDICTOR_2;
596	if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_2, 0) <= 0) {
597	    go->predictor_2 = 0;
598	} else {
599	    p += CILEN_PREDICTOR_2;
600	}
601    }
602
603    go->method = (p > p0)? p0[0]: -1;
604
605    *lenp = p - p0;
606}
607
608/*
609 * ccp_ackci - process a received configure-ack, and return
610 * 1 iff the packet was OK.
611 */
612static int
613ccp_ackci(f, p, len)
614    fsm *f;
615    u_char *p;
616    int len;
617{
618    ccp_options *go = &ccp_gotoptions[f->unit];
619    u_char *p0 = p;
620
621    if (go->deflate) {
622	if (len < CILEN_DEFLATE
623	    || p[0] != (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
624	    || p[1] != CILEN_DEFLATE
625	    || p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
626	    || p[3] != DEFLATE_CHK_SEQUENCE)
627	    return 0;
628	p += CILEN_DEFLATE;
629	len -= CILEN_DEFLATE;
630	if (len == 0)
631	    return 1;
632	if (go->deflate_correct && go->deflate_draft) {
633	    if (len < CILEN_DEFLATE
634		|| p[0] != CI_DEFLATE_DRAFT
635		|| p[1] != CILEN_DEFLATE
636		|| p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
637		|| p[3] != DEFLATE_CHK_SEQUENCE)
638		return 0;
639	    p += CILEN_DEFLATE;
640	    len -= CILEN_DEFLATE;
641	}
642    }
643    if (go->bsd_compress) {
644	if (len < CILEN_BSD_COMPRESS
645	    || p[0] != CI_BSD_COMPRESS || p[1] != CILEN_BSD_COMPRESS
646	    || p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits))
647	    return 0;
648	p += CILEN_BSD_COMPRESS;
649	len -= CILEN_BSD_COMPRESS;
650	if (p == p0 && len == 0)
651	    return 1;
652    }
653    if (go->predictor_1) {
654	if (len < CILEN_PREDICTOR_1
655	    || p[0] != CI_PREDICTOR_1 || p[1] != CILEN_PREDICTOR_1)
656	    return 0;
657	p += CILEN_PREDICTOR_1;
658	len -= CILEN_PREDICTOR_1;
659	if (p == p0 && len == 0)
660	    return 1;
661    }
662    if (go->predictor_2) {
663	if (len < CILEN_PREDICTOR_2
664	    || p[0] != CI_PREDICTOR_2 || p[1] != CILEN_PREDICTOR_2)
665	    return 0;
666	p += CILEN_PREDICTOR_2;
667	len -= CILEN_PREDICTOR_2;
668	if (p == p0 && len == 0)
669	    return 1;
670    }
671
672    if (len != 0)
673	return 0;
674    return 1;
675}
676
677/*
678 * ccp_nakci - process received configure-nak.
679 * Returns 1 iff the nak was OK.
680 */
681static int
682ccp_nakci(f, p, len)
683    fsm *f;
684    u_char *p;
685    int len;
686{
687    ccp_options *go = &ccp_gotoptions[f->unit];
688    ccp_options no;		/* options we've seen already */
689    ccp_options try;		/* options to ask for next time */
690
691    memset(&no, 0, sizeof(no));
692    try = *go;
693
694    if (go->deflate && len >= CILEN_DEFLATE
695	&& p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
696	&& p[1] == CILEN_DEFLATE) {
697	no.deflate = 1;
698	/*
699	 * Peer wants us to use a different code size or something.
700	 * Stop asking for Deflate if we don't understand his suggestion.
701	 */
702	if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL
703	    || DEFLATE_SIZE(p[2]) < DEFLATE_MIN_WORKS
704	    || p[3] != DEFLATE_CHK_SEQUENCE)
705	    try.deflate = 0;
706	else if (DEFLATE_SIZE(p[2]) < go->deflate_size)
707	    try.deflate_size = DEFLATE_SIZE(p[2]);
708	p += CILEN_DEFLATE;
709	len -= CILEN_DEFLATE;
710	if (go->deflate_correct && go->deflate_draft
711	    && len >= CILEN_DEFLATE && p[0] == CI_DEFLATE_DRAFT
712	    && p[1] == CILEN_DEFLATE) {
713	    p += CILEN_DEFLATE;
714	    len -= CILEN_DEFLATE;
715	}
716    }
717
718    if (go->bsd_compress && len >= CILEN_BSD_COMPRESS
719	&& p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) {
720	no.bsd_compress = 1;
721	/*
722	 * Peer wants us to use a different number of bits
723	 * or a different version.
724	 */
725	if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION)
726	    try.bsd_compress = 0;
727	else if (BSD_NBITS(p[2]) < go->bsd_bits)
728	    try.bsd_bits = BSD_NBITS(p[2]);
729	p += CILEN_BSD_COMPRESS;
730	len -= CILEN_BSD_COMPRESS;
731    }
732
733    /*
734     * Predictor-1 and 2 have no options, so they can't be Naked.
735     *
736     * There may be remaining options but we ignore them.
737     */
738
739    if (f->state != OPENED)
740	*go = try;
741    return 1;
742}
743
744/*
745 * ccp_rejci - reject some of our suggested compression methods.
746 */
747static int
748ccp_rejci(f, p, len)
749    fsm *f;
750    u_char *p;
751    int len;
752{
753    ccp_options *go = &ccp_gotoptions[f->unit];
754    ccp_options try;		/* options to request next time */
755
756    try = *go;
757
758    /*
759     * Cope with empty configure-rejects by ceasing to send
760     * configure-requests.
761     */
762    if (len == 0 && all_rejected[f->unit])
763	return -1;
764
765    if (go->deflate && len >= CILEN_DEFLATE
766	&& p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
767	&& p[1] == CILEN_DEFLATE) {
768	if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
769	    || p[3] != DEFLATE_CHK_SEQUENCE)
770	    return 0;		/* Rej is bad */
771	if (go->deflate_correct)
772	    try.deflate_correct = 0;
773	else
774	    try.deflate_draft = 0;
775	p += CILEN_DEFLATE;
776	len -= CILEN_DEFLATE;
777	if (go->deflate_correct && go->deflate_draft
778	    && len >= CILEN_DEFLATE && p[0] == CI_DEFLATE_DRAFT
779	    && p[1] == CILEN_DEFLATE) {
780	    if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
781		|| p[3] != DEFLATE_CHK_SEQUENCE)
782		return 0;		/* Rej is bad */
783	    try.deflate_draft = 0;
784	    p += CILEN_DEFLATE;
785	    len -= CILEN_DEFLATE;
786	}
787	if (!try.deflate_correct && !try.deflate_draft)
788	    try.deflate = 0;
789    }
790    if (go->bsd_compress && len >= CILEN_BSD_COMPRESS
791	&& p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) {
792	if (p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits))
793	    return 0;
794	try.bsd_compress = 0;
795	p += CILEN_BSD_COMPRESS;
796	len -= CILEN_BSD_COMPRESS;
797    }
798    if (go->predictor_1 && len >= CILEN_PREDICTOR_1
799	&& p[0] == CI_PREDICTOR_1 && p[1] == CILEN_PREDICTOR_1) {
800	try.predictor_1 = 0;
801	p += CILEN_PREDICTOR_1;
802	len -= CILEN_PREDICTOR_1;
803    }
804    if (go->predictor_2 && len >= CILEN_PREDICTOR_2
805	&& p[0] == CI_PREDICTOR_2 && p[1] == CILEN_PREDICTOR_2) {
806	try.predictor_2 = 0;
807	p += CILEN_PREDICTOR_2;
808	len -= CILEN_PREDICTOR_2;
809    }
810
811    if (len != 0)
812	return 0;
813
814    if (f->state != OPENED)
815	*go = try;
816
817    return 1;
818}
819
820/*
821 * ccp_reqci - processed a received configure-request.
822 * Returns CONFACK, CONFNAK or CONFREJ and the packet modified
823 * appropriately.
824 */
825static int
826ccp_reqci(f, p, lenp, dont_nak)
827    fsm *f;
828    u_char *p;
829    int *lenp;
830    int dont_nak;
831{
832    int ret, newret, res;
833    u_char *p0, *retp;
834    int len, clen, type, nb;
835    ccp_options *ho = &ccp_hisoptions[f->unit];
836    ccp_options *ao = &ccp_allowoptions[f->unit];
837
838    ret = CONFACK;
839    retp = p0 = p;
840    len = *lenp;
841
842    memset(ho, 0, sizeof(ccp_options));
843    ho->method = (len > 0)? p[0]: -1;
844
845    while (len > 0) {
846	newret = CONFACK;
847	if (len < 2 || p[1] < 2 || p[1] > len) {
848	    /* length is bad */
849	    clen = len;
850	    newret = CONFREJ;
851
852	} else {
853	    type = p[0];
854	    clen = p[1];
855
856	    switch (type) {
857	    case CI_DEFLATE:
858	    case CI_DEFLATE_DRAFT:
859		if (!ao->deflate || clen != CILEN_DEFLATE
860		    || (!ao->deflate_correct && type == CI_DEFLATE)
861		    || (!ao->deflate_draft && type == CI_DEFLATE_DRAFT)) {
862		    newret = CONFREJ;
863		    break;
864		}
865
866		ho->deflate = 1;
867		ho->deflate_size = nb = DEFLATE_SIZE(p[2]);
868		if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL
869		    || p[3] != DEFLATE_CHK_SEQUENCE
870		    || nb > ao->deflate_size || nb < DEFLATE_MIN_WORKS) {
871		    newret = CONFNAK;
872		    if (!dont_nak) {
873			p[2] = DEFLATE_MAKE_OPT(ao->deflate_size);
874			p[3] = DEFLATE_CHK_SEQUENCE;
875			/* fall through to test this #bits below */
876		    } else
877			break;
878		}
879
880		/*
881		 * Check whether we can do Deflate with the window
882		 * size they want.  If the window is too big, reduce
883		 * it until the kernel can cope and nak with that.
884		 * We only check this for the first option.
885		 */
886		if (p == p0) {
887		    for (;;) {
888			res = ccp_test(f->unit, p, CILEN_DEFLATE, 1);
889			if (res > 0)
890			    break;		/* it's OK now */
891			if (res < 0 || nb == DEFLATE_MIN_WORKS || dont_nak) {
892			    newret = CONFREJ;
893			    p[2] = DEFLATE_MAKE_OPT(ho->deflate_size);
894			    break;
895			}
896			newret = CONFNAK;
897			--nb;
898			p[2] = DEFLATE_MAKE_OPT(nb);
899		    }
900		}
901		break;
902
903	    case CI_BSD_COMPRESS:
904		if (!ao->bsd_compress || clen != CILEN_BSD_COMPRESS) {
905		    newret = CONFREJ;
906		    break;
907		}
908
909		ho->bsd_compress = 1;
910		ho->bsd_bits = nb = BSD_NBITS(p[2]);
911		if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION
912		    || nb > ao->bsd_bits || nb < BSD_MIN_BITS) {
913		    newret = CONFNAK;
914		    if (!dont_nak) {
915			p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, ao->bsd_bits);
916			/* fall through to test this #bits below */
917		    } else
918			break;
919		}
920
921		/*
922		 * Check whether we can do BSD-Compress with the code
923		 * size they want.  If the code size is too big, reduce
924		 * it until the kernel can cope and nak with that.
925		 * We only check this for the first option.
926		 */
927		if (p == p0) {
928		    for (;;) {
929			res = ccp_test(f->unit, p, CILEN_BSD_COMPRESS, 1);
930			if (res > 0)
931			    break;
932			if (res < 0 || nb == BSD_MIN_BITS || dont_nak) {
933			    newret = CONFREJ;
934			    p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION,
935						ho->bsd_bits);
936			    break;
937			}
938			newret = CONFNAK;
939			--nb;
940			p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, nb);
941		    }
942		}
943		break;
944
945	    case CI_PREDICTOR_1:
946		if (!ao->predictor_1 || clen != CILEN_PREDICTOR_1) {
947		    newret = CONFREJ;
948		    break;
949		}
950
951		ho->predictor_1 = 1;
952		if (p == p0
953		    && ccp_test(f->unit, p, CILEN_PREDICTOR_1, 1) <= 0) {
954		    newret = CONFREJ;
955		}
956		break;
957
958	    case CI_PREDICTOR_2:
959		if (!ao->predictor_2 || clen != CILEN_PREDICTOR_2) {
960		    newret = CONFREJ;
961		    break;
962		}
963
964		ho->predictor_2 = 1;
965		if (p == p0
966		    && ccp_test(f->unit, p, CILEN_PREDICTOR_2, 1) <= 0) {
967		    newret = CONFREJ;
968		}
969		break;
970
971	    default:
972		newret = CONFREJ;
973	    }
974	}
975
976	if (newret == CONFNAK && dont_nak)
977	    newret = CONFREJ;
978	if (!(newret == CONFACK || (newret == CONFNAK && ret == CONFREJ))) {
979	    /* we're returning this option */
980	    if (newret == CONFREJ && ret == CONFNAK)
981		retp = p0;
982	    ret = newret;
983	    if (p != retp)
984		BCOPY(p, retp, clen);
985	    retp += clen;
986	}
987
988	p += clen;
989	len -= clen;
990    }
991
992    if (ret != CONFACK) {
993	if (ret == CONFREJ && *lenp == retp - p0)
994	    all_rejected[f->unit] = 1;
995	else
996	    *lenp = retp - p0;
997    }
998    return ret;
999}
1000
1001/*
1002 * Make a string name for a compression method (or 2).
1003 */
1004static char *
1005method_name(opt, opt2)
1006    ccp_options *opt, *opt2;
1007{
1008    static char result[64];
1009
1010    if (!ANY_COMPRESS(*opt))
1011	return "(none)";
1012    switch (opt->method) {
1013    case CI_DEFLATE:
1014    case CI_DEFLATE_DRAFT:
1015	if (opt2 != NULL && opt2->deflate_size != opt->deflate_size)
1016	    slprintf(result, sizeof(result), "Deflate%s (%d/%d)",
1017		     (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""),
1018		     opt->deflate_size, opt2->deflate_size);
1019	else
1020	    slprintf(result, sizeof(result), "Deflate%s (%d)",
1021		     (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""),
1022		     opt->deflate_size);
1023	break;
1024    case CI_BSD_COMPRESS:
1025	if (opt2 != NULL && opt2->bsd_bits != opt->bsd_bits)
1026	    slprintf(result, sizeof(result), "BSD-Compress (%d/%d)",
1027		     opt->bsd_bits, opt2->bsd_bits);
1028	else
1029	    slprintf(result, sizeof(result), "BSD-Compress (%d)",
1030		     opt->bsd_bits);
1031	break;
1032    case CI_PREDICTOR_1:
1033	return "Predictor 1";
1034    case CI_PREDICTOR_2:
1035	return "Predictor 2";
1036    default:
1037	slprintf(result, sizeof(result), "Method %d", opt->method);
1038    }
1039    return result;
1040}
1041
1042/*
1043 * CCP has come up - inform the kernel driver and log a message.
1044 */
1045static void
1046ccp_up(f)
1047    fsm *f;
1048{
1049    ccp_options *go = &ccp_gotoptions[f->unit];
1050    ccp_options *ho = &ccp_hisoptions[f->unit];
1051    char method1[64];
1052
1053    ccp_flags_set(f->unit, 1, 1);
1054    if (ANY_COMPRESS(*go)) {
1055	if (ANY_COMPRESS(*ho)) {
1056	    if (go->method == ho->method) {
1057		notice("%s compression enabled", method_name(go, ho));
1058	    } else {
1059		strlcpy(method1, method_name(go, NULL), sizeof(method1));
1060		notice("%s / %s compression enabled",
1061		       method1, method_name(ho, NULL));
1062	    }
1063	} else
1064	    notice("%s receive compression enabled", method_name(go, NULL));
1065    } else if (ANY_COMPRESS(*ho))
1066	notice("%s transmit compression enabled", method_name(ho, NULL));
1067}
1068
1069/*
1070 * CCP has gone down - inform the kernel driver.
1071 */
1072static void
1073ccp_down(f)
1074    fsm *f;
1075{
1076    if (ccp_localstate[f->unit] & RACK_PENDING)
1077	UNTIMEOUT(ccp_rack_timeout, f);
1078    ccp_localstate[f->unit] = 0;
1079    ccp_flags_set(f->unit, 1, 0);
1080}
1081
1082/*
1083 * Print the contents of a CCP packet.
1084 */
1085static char *ccp_codenames[] = {
1086    "ConfReq", "ConfAck", "ConfNak", "ConfRej",
1087    "TermReq", "TermAck", "CodeRej",
1088    NULL, NULL, NULL, NULL, NULL, NULL,
1089    "ResetReq", "ResetAck",
1090};
1091
1092static int
1093ccp_printpkt(p, plen, printer, arg)
1094    u_char *p;
1095    int plen;
1096    void (*printer) __P((void *, char *, ...));
1097    void *arg;
1098{
1099    u_char *p0, *optend;
1100    int code, id, len;
1101    int optlen;
1102
1103    p0 = p;
1104    if (plen < HEADERLEN)
1105	return 0;
1106    code = p[0];
1107    id = p[1];
1108    len = (p[2] << 8) + p[3];
1109    if (len < HEADERLEN || len > plen)
1110	return 0;
1111
1112    if (code >= 1 && code <= sizeof(ccp_codenames) / sizeof(char *)
1113	&& ccp_codenames[code-1] != NULL)
1114	printer(arg, " %s", ccp_codenames[code-1]);
1115    else
1116	printer(arg, " code=0x%x", code);
1117    printer(arg, " id=0x%x", id);
1118    len -= HEADERLEN;
1119    p += HEADERLEN;
1120
1121    switch (code) {
1122    case CONFREQ:
1123    case CONFACK:
1124    case CONFNAK:
1125    case CONFREJ:
1126	/* print list of possible compression methods */
1127	while (len >= 2) {
1128	    code = p[0];
1129	    optlen = p[1];
1130	    if (optlen < 2 || optlen > len)
1131		break;
1132	    printer(arg, " <");
1133	    len -= optlen;
1134	    optend = p + optlen;
1135	    switch (code) {
1136	    case CI_DEFLATE:
1137	    case CI_DEFLATE_DRAFT:
1138		if (optlen >= CILEN_DEFLATE) {
1139		    printer(arg, "deflate%s %d",
1140			    (code == CI_DEFLATE_DRAFT? "(old#)": ""),
1141			    DEFLATE_SIZE(p[2]));
1142		    if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL)
1143			printer(arg, " method %d", DEFLATE_METHOD(p[2]));
1144		    if (p[3] != DEFLATE_CHK_SEQUENCE)
1145			printer(arg, " check %d", p[3]);
1146		    p += CILEN_DEFLATE;
1147		}
1148		break;
1149	    case CI_BSD_COMPRESS:
1150		if (optlen >= CILEN_BSD_COMPRESS) {
1151		    printer(arg, "bsd v%d %d", BSD_VERSION(p[2]),
1152			    BSD_NBITS(p[2]));
1153		    p += CILEN_BSD_COMPRESS;
1154		}
1155		break;
1156	    case CI_PREDICTOR_1:
1157		if (optlen >= CILEN_PREDICTOR_1) {
1158		    printer(arg, "predictor 1");
1159		    p += CILEN_PREDICTOR_1;
1160		}
1161		break;
1162	    case CI_PREDICTOR_2:
1163		if (optlen >= CILEN_PREDICTOR_2) {
1164		    printer(arg, "predictor 2");
1165		    p += CILEN_PREDICTOR_2;
1166		}
1167		break;
1168	    }
1169	    while (p < optend)
1170		printer(arg, " %.2x", *p++);
1171	    printer(arg, ">");
1172	}
1173	break;
1174
1175    case TERMACK:
1176    case TERMREQ:
1177	if (len > 0 && *p >= ' ' && *p < 0x7f) {
1178	    print_string((char *)p, len, printer, arg);
1179	    p += len;
1180	    len = 0;
1181	}
1182	break;
1183    }
1184
1185    /* dump out the rest of the packet in hex */
1186    while (--len >= 0)
1187	printer(arg, " %.2x", *p++);
1188
1189    return p - p0;
1190}
1191
1192/*
1193 * We have received a packet that the decompressor failed to
1194 * decompress.  Here we would expect to issue a reset-request, but
1195 * Motorola has a patent on resetting the compressor as a result of
1196 * detecting an error in the decompressed data after decompression.
1197 * (See US patent 5,130,993; international patent publication number
1198 * WO 91/10289; Australian patent 73296/91.)
1199 *
1200 * So we ask the kernel whether the error was detected after
1201 * decompression; if it was, we take CCP down, thus disabling
1202 * compression :-(, otherwise we issue the reset-request.
1203 */
1204static void
1205ccp_datainput(unit, pkt, len)
1206    int unit;
1207    u_char *pkt;
1208    int len;
1209{
1210    fsm *f;
1211
1212    f = &ccp_fsm[unit];
1213    if (f->state == OPENED) {
1214	if (ccp_fatal_error(unit)) {
1215	    /*
1216	     * Disable compression by taking CCP down.
1217	     */
1218	    error("Lost compression sync: disabling compression");
1219	    ccp_close(unit, "Lost compression sync");
1220	} else {
1221	    /*
1222	     * Send a reset-request to reset the peer's compressor.
1223	     * We don't do that if we are still waiting for an
1224	     * acknowledgement to a previous reset-request.
1225	     */
1226	    if (!(ccp_localstate[f->unit] & RACK_PENDING)) {
1227		fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0);
1228		TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT);
1229		ccp_localstate[f->unit] |= RACK_PENDING;
1230	    } else
1231		ccp_localstate[f->unit] |= RREQ_REPEAT;
1232	}
1233    }
1234}
1235
1236/*
1237 * Timeout waiting for reset-ack.
1238 */
1239static void
1240ccp_rack_timeout(arg)
1241    void *arg;
1242{
1243    fsm *f = arg;
1244
1245    if (f->state == OPENED && ccp_localstate[f->unit] & RREQ_REPEAT) {
1246	fsm_sdata(f, CCP_RESETREQ, f->reqid, NULL, 0);
1247	TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT);
1248	ccp_localstate[f->unit] &= ~RREQ_REPEAT;
1249    } else
1250	ccp_localstate[f->unit] &= ~RACK_PENDING;
1251}
1252
1253