moved protos here from ipcp.h; print reason on terminate-request;
[ppp.git] / pppd / ccp.c
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 #ifndef lint
29 static char rcsid[] = "$Id: ccp.c,v 1.17 1996/07/01 01:11:36 paulus Exp $";
30 #endif
31
32 #include <string.h>
33 #include <syslog.h>
34 #include <sys/ioctl.h>
35 #include <net/ppp-comp.h>
36
37 #include "pppd.h"
38 #include "fsm.h"
39 #include "ccp.h"
40
41 /*
42  * Protocol entry points from main code.
43  */
44 static void ccp_init __P((int unit));
45 static void ccp_open __P((int unit));
46 static void ccp_close __P((int unit, char *));
47 static void ccp_lowerup __P((int unit));
48 static void ccp_lowerdown __P((int));
49 static void ccp_input __P((int unit, u_char *pkt, int len));
50 static void ccp_protrej __P((int unit));
51 static int  ccp_printpkt __P((u_char *pkt, int len,
52                               void (*printer) __P((void *, char *, ...)),
53                               void *arg));
54 static void ccp_datainput __P((int unit, u_char *pkt, int len));
55
56 struct protent ccp_protent = {
57     PPP_CCP,
58     ccp_init,
59     ccp_input,
60     ccp_protrej,
61     ccp_lowerup,
62     ccp_lowerdown,
63     ccp_open,
64     ccp_close,
65     ccp_printpkt,
66     ccp_datainput,
67     1,
68     "CCP",
69     NULL,
70     NULL,
71     NULL
72 };
73
74 fsm ccp_fsm[NUM_PPP];
75 ccp_options ccp_wantoptions[NUM_PPP];   /* what to request the peer to use */
76 ccp_options ccp_gotoptions[NUM_PPP];    /* what the peer agreed to do */
77 ccp_options ccp_allowoptions[NUM_PPP];  /* what we'll agree to do */
78 ccp_options ccp_hisoptions[NUM_PPP];    /* what we agreed to do */
79
80 /*
81  * Callbacks for fsm code.
82  */
83 static void ccp_resetci __P((fsm *));
84 static int  ccp_cilen __P((fsm *));
85 static void ccp_addci __P((fsm *, u_char *, int *));
86 static int  ccp_ackci __P((fsm *, u_char *, int));
87 static int  ccp_nakci __P((fsm *, u_char *, int));
88 static int  ccp_rejci __P((fsm *, u_char *, int));
89 static int  ccp_reqci __P((fsm *, u_char *, int *, int));
90 static void ccp_up __P((fsm *));
91 static void ccp_down __P((fsm *));
92 static int  ccp_extcode __P((fsm *, int, int, u_char *, int));
93 static void ccp_rack_timeout __P(());
94 static char *method_name __P((ccp_options *, ccp_options *));
95
96 static fsm_callbacks ccp_callbacks = {
97     ccp_resetci,
98     ccp_cilen,
99     ccp_addci,
100     ccp_ackci,
101     ccp_nakci,
102     ccp_rejci,
103     ccp_reqci,
104     ccp_up,
105     ccp_down,
106     NULL,
107     NULL,
108     NULL,
109     NULL,
110     ccp_extcode,
111     "CCP"
112 };
113
114 /*
115  * Do we want / did we get any compression?
116  */
117 #define ANY_COMPRESS(opt)       ((opt).deflate || (opt).bsd_compress \
118                                  || (opt).predictor_1 || (opt).predictor_2)
119
120 /*
121  * Local state (mainly for handling reset-reqs and reset-acks).
122  */
123 static int ccp_localstate[NUM_PPP];
124 #define RACK_PENDING    1       /* waiting for reset-ack */
125 #define RREQ_REPEAT     2       /* send another reset-req if no reset-ack */
126
127 #define RACKTIMEOUT     1       /* second */
128
129 static int all_rejected[NUM_PPP];       /* we rejected all peer's options */
130
131 /*
132  * ccp_init - initialize CCP.
133  */
134 static void
135 ccp_init(unit)
136     int unit;
137 {
138     fsm *f = &ccp_fsm[unit];
139
140     f->unit = unit;
141     f->protocol = PPP_CCP;
142     f->callbacks = &ccp_callbacks;
143     fsm_init(f);
144
145     memset(&ccp_wantoptions[unit],  0, sizeof(ccp_options));
146     memset(&ccp_gotoptions[unit],   0, sizeof(ccp_options));
147     memset(&ccp_allowoptions[unit], 0, sizeof(ccp_options));
148     memset(&ccp_hisoptions[unit],   0, sizeof(ccp_options));
149
150     ccp_wantoptions[0].deflate = 1;
151     ccp_wantoptions[0].deflate_size = DEFLATE_MAX_SIZE;
152     ccp_allowoptions[0].deflate = 1;
153     ccp_allowoptions[0].deflate_size = DEFLATE_MAX_SIZE;
154
155     ccp_wantoptions[0].bsd_compress = 1;
156     ccp_wantoptions[0].bsd_bits = BSD_MAX_BITS;
157     ccp_allowoptions[0].bsd_compress = 1;
158     ccp_allowoptions[0].bsd_bits = BSD_MAX_BITS;
159
160     ccp_allowoptions[0].predictor_1 = 1;
161 }
162
163 /*
164  * ccp_open - CCP is allowed to come up.
165  */
166 void
167 ccp_open(unit)
168     int unit;
169 {
170     fsm *f = &ccp_fsm[unit];
171
172     if (f->state != OPENED)
173         ccp_flags_set(unit, 1, 0);
174
175     /*
176      * Find out which compressors the kernel supports before
177      * deciding whether to open in silent mode.
178      */
179     ccp_resetci(f);
180     if (!ANY_COMPRESS(ccp_gotoptions[unit]))
181         f->flags |= OPT_SILENT;
182
183     fsm_open(f);
184 }
185
186 /*
187  * ccp_close - Terminate CCP.
188  */
189 static void
190 ccp_close(unit, reason)
191     int unit;
192     char *reason;
193 {
194     ccp_flags_set(unit, 0, 0);
195     fsm_close(&ccp_fsm[unit], reason);
196 }
197
198 /*
199  * ccp_lowerup - we may now transmit CCP packets.
200  */
201 static void
202 ccp_lowerup(unit)
203     int unit;
204 {
205     fsm_lowerup(&ccp_fsm[unit]);
206 }
207
208 /*
209  * ccp_lowerdown - we may not transmit CCP packets.
210  */
211 static void
212 ccp_lowerdown(unit)
213     int unit;
214 {
215     fsm_lowerdown(&ccp_fsm[unit]);
216 }
217
218 /*
219  * ccp_input - process a received CCP packet.
220  */
221 static void
222 ccp_input(unit, p, len)
223     int unit;
224     u_char *p;
225     int len;
226 {
227     fsm *f = &ccp_fsm[unit];
228     int oldstate;
229
230     /*
231      * Check for a terminate-request so we can print a message.
232      */
233     oldstate = f->state;
234     fsm_input(f, p, len);
235     if (oldstate == OPENED && p[0] == TERMREQ && f->state != OPENED)
236         syslog(LOG_NOTICE, "Compression disabled by peer.");
237
238     /*
239      * If we get a terminate-ack and we're not asking for compression,
240      * close CCP.
241      */
242     if (oldstate == REQSENT && p[0] == TERMACK
243         && !ANY_COMPRESS(ccp_gotoptions[unit]))
244         ccp_close(unit, "No compression negotiated");
245 }
246
247 /*
248  * Handle a CCP-specific code.
249  */
250 static int
251 ccp_extcode(f, code, id, p, len)
252     fsm *f;
253     int code, id;
254     u_char *p;
255     int len;
256 {
257     switch (code) {
258     case CCP_RESETREQ:
259         if (f->state != OPENED)
260             break;
261         /* send a reset-ack, which the transmitter will see and
262            reset its compression state. */
263         fsm_sdata(f, CCP_RESETACK, id, NULL, 0);
264         break;
265
266     case CCP_RESETACK:
267         if (ccp_localstate[f->unit] & RACK_PENDING && id == f->reqid) {
268             ccp_localstate[f->unit] &= ~(RACK_PENDING | RREQ_REPEAT);
269             UNTIMEOUT(ccp_rack_timeout, (caddr_t) f);
270         }
271         break;
272
273     default:
274         return 0;
275     }
276
277     return 1;
278 }
279
280 /*
281  * ccp_protrej - peer doesn't talk CCP.
282  */
283 static void
284 ccp_protrej(unit)
285     int unit;
286 {
287     ccp_flags_set(unit, 0, 0);
288     fsm_lowerdown(&ccp_fsm[unit]);
289 }
290
291 /*
292  * ccp_resetci - initialize at start of negotiation.
293  */
294 static void
295 ccp_resetci(f)
296     fsm *f;
297 {
298     ccp_options *go = &ccp_gotoptions[f->unit];
299     u_char opt_buf[16];
300
301     *go = ccp_wantoptions[f->unit];
302     all_rejected[f->unit] = 0;
303
304     /*
305      * Check whether the kernel knows about the various
306      * compression methods we might request.
307      */
308     if (go->bsd_compress) {
309         opt_buf[0] = CI_BSD_COMPRESS;
310         opt_buf[1] = CILEN_BSD_COMPRESS;
311         opt_buf[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, BSD_MIN_BITS);
312         if (ccp_test(f->unit, opt_buf, CILEN_BSD_COMPRESS, 0) <= 0)
313             go->bsd_compress = 0;
314     }
315     if (go->deflate) {
316         opt_buf[0] = CI_DEFLATE;
317         opt_buf[1] = CILEN_DEFLATE;
318         opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_SIZE);
319         opt_buf[3] = DEFLATE_CHK_SEQUENCE;
320         if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0)
321             go->deflate = 0;
322     }
323     if (go->predictor_1) {
324         opt_buf[0] = CI_PREDICTOR_1;
325         opt_buf[1] = CILEN_PREDICTOR_1;
326         if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_1, 0) <= 0)
327             go->predictor_1 = 0;
328     }
329     if (go->predictor_2) {
330         opt_buf[0] = CI_PREDICTOR_2;
331         opt_buf[1] = CILEN_PREDICTOR_2;
332         if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_2, 0) <= 0)
333             go->predictor_2 = 0;
334     }
335 }
336
337 /*
338  * ccp_cilen - Return total length of our configuration info.
339  */
340 static int
341 ccp_cilen(f)
342     fsm *f;
343 {
344     ccp_options *go = &ccp_gotoptions[f->unit];
345
346     return (go->bsd_compress? CILEN_BSD_COMPRESS: 0)
347         + (go->deflate? CILEN_DEFLATE: 0)
348         + (go->predictor_1? CILEN_PREDICTOR_1: 0)
349         + (go->predictor_2? CILEN_PREDICTOR_2: 0);
350 }
351
352 /*
353  * ccp_addci - put our requests in a packet.
354  */
355 static void
356 ccp_addci(f, p, lenp)
357     fsm *f;
358     u_char *p;
359     int *lenp;
360 {
361     int res;
362     ccp_options *go = &ccp_gotoptions[f->unit];
363     u_char *p0 = p;
364
365     /*
366      * Add the compression types that we can receive, in decreasing
367      * preference order.  Get the kernel to allocate the first one
368      * in case it gets Acked.
369      */
370     if (go->deflate) {
371         p[0] = CI_DEFLATE;
372         p[1] = CILEN_DEFLATE;
373         p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
374         p[3] = DEFLATE_CHK_SEQUENCE;
375         for (;;) {
376             res = ccp_test(f->unit, p, CILEN_DEFLATE, 0);
377             if (res > 0) {
378                 p += CILEN_DEFLATE;
379                 break;
380             }
381             if (res < 0 || go->deflate_size <= DEFLATE_MIN_SIZE) {
382                 go->deflate = 0;
383                 break;
384             }
385             --go->deflate_size;
386             p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
387         }
388     }
389     if (go->bsd_compress) {
390         p[0] = CI_BSD_COMPRESS;
391         p[1] = CILEN_BSD_COMPRESS;
392         p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
393         if (p != p0) {
394             p += CILEN_BSD_COMPRESS;    /* not the first option */
395         } else {
396             for (;;) {
397                 res = ccp_test(f->unit, p, CILEN_BSD_COMPRESS, 0);
398                 if (res > 0) {
399                     p += CILEN_BSD_COMPRESS;
400                     break;
401                 }
402                 if (res < 0 || go->bsd_bits <= BSD_MIN_BITS) {
403                     go->bsd_compress = 0;
404                     break;
405                 }
406                 --go->bsd_bits;
407                 p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
408             }
409         }
410     }
411     /* XXX Should Predictor 2 be preferable to Predictor 1? */
412     if (go->predictor_1) {
413         p[0] = CI_PREDICTOR_1;
414         p[1] = CILEN_PREDICTOR_1;
415         if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_1, 0) <= 0) {
416             go->predictor_1 = 0;
417         } else {
418             p += CILEN_PREDICTOR_1;
419         }
420     }
421     if (go->predictor_2) {
422         p[0] = CI_PREDICTOR_2;
423         p[1] = CILEN_PREDICTOR_2;
424         if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_2, 0) <= 0) {
425             go->predictor_2 = 0;
426         } else {
427             p += CILEN_PREDICTOR_2;
428         }
429     }
430
431     go->method = (p > p0)? p0[0]: -1;
432
433     *lenp = p - p0;
434 }
435
436 /*
437  * ccp_ackci - process a received configure-ack, and return
438  * 1 iff the packet was OK.
439  */
440 static int
441 ccp_ackci(f, p, len)
442     fsm *f;
443     u_char *p;
444     int len;
445 {
446     ccp_options *go = &ccp_gotoptions[f->unit];
447     u_char *p0 = p;
448
449     if (go->deflate) {
450         if (len < CILEN_DEFLATE
451             || p[0] != CI_DEFLATE || p[1] != CILEN_DEFLATE
452             || p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
453             || p[3] != DEFLATE_CHK_SEQUENCE)
454             return 0;
455         p += CILEN_DEFLATE;
456         len -= CILEN_DEFLATE;
457         /* XXX Cope with first/fast ack */
458         if (len == 0)
459             return 1;
460     }
461     if (go->bsd_compress) {
462         if (len < CILEN_BSD_COMPRESS
463             || p[0] != CI_BSD_COMPRESS || p[1] != CILEN_BSD_COMPRESS
464             || p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits))
465             return 0;
466         p += CILEN_BSD_COMPRESS;
467         len -= CILEN_BSD_COMPRESS;
468         /* XXX Cope with first/fast ack */
469         if (p == p0 && len == 0)
470             return 1;
471     }
472     if (go->predictor_1) {
473         if (len < CILEN_PREDICTOR_1
474             || p[0] != CI_PREDICTOR_1 || p[1] != CILEN_PREDICTOR_1)
475             return 0;
476         p += CILEN_PREDICTOR_1;
477         len -= CILEN_PREDICTOR_1;
478         /* XXX Cope with first/fast ack */
479         if (p == p0 && len == 0)
480             return 1;
481     }
482     if (go->predictor_2) {
483         if (len < CILEN_PREDICTOR_2
484             || p[0] != CI_PREDICTOR_2 || p[1] != CILEN_PREDICTOR_2)
485             return 0;
486         p += CILEN_PREDICTOR_2;
487         len -= CILEN_PREDICTOR_2;
488         /* XXX Cope with first/fast ack */
489         if (p == p0 && len == 0)
490             return 1;
491     }
492
493     if (len != 0)
494         return 0;
495     return 1;
496 }
497
498 /*
499  * ccp_nakci - process received configure-nak.
500  * Returns 1 iff the nak was OK.
501  */
502 static int
503 ccp_nakci(f, p, len)
504     fsm *f;
505     u_char *p;
506     int len;
507 {
508     ccp_options *go = &ccp_gotoptions[f->unit];
509     ccp_options no;             /* options we've seen already */
510     ccp_options try;            /* options to ask for next time */
511
512     memset(&no, 0, sizeof(no));
513     try = *go;
514
515     if (go->deflate && len >= CILEN_DEFLATE
516         && p[0] == CI_DEFLATE && p[1] == CILEN_DEFLATE) {
517         no.deflate = 1;
518         /*
519          * Peer wants us to use a different code size or something.
520          * Stop asking for Deflate if we don't understand his suggestion.
521          */
522         if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL
523             || DEFLATE_SIZE(p[2]) < DEFLATE_MIN_SIZE
524             || p[3] != DEFLATE_CHK_SEQUENCE)
525             try.deflate = 0;
526         else if (DEFLATE_SIZE(p[2]) < go->deflate_size)
527             go->deflate_size = DEFLATE_SIZE(p[2]);
528         p += CILEN_DEFLATE;
529         len -= CILEN_DEFLATE;
530     }
531
532     if (go->bsd_compress && len >= CILEN_BSD_COMPRESS
533         && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) {
534         no.bsd_compress = 1;
535         /*
536          * Peer wants us to use a different number of bits
537          * or a different version.
538          */
539         if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION)
540             try.bsd_compress = 0;
541         else if (BSD_NBITS(p[2]) < go->bsd_bits)
542             try.bsd_bits = BSD_NBITS(p[2]);
543         p += CILEN_BSD_COMPRESS;
544         len -= CILEN_BSD_COMPRESS;
545     }
546
547     /*
548      * Predictor-1 and 2 have no options, so they can't be Naked.
549      *
550      * XXX What should we do with any remaining options?
551      */
552
553     if (len != 0)
554         return 0;
555
556     if (f->state != OPENED)
557         *go = try;
558     return 1;
559 }
560
561 /*
562  * ccp_rejci - reject some of our suggested compression methods.
563  */
564 static int
565 ccp_rejci(f, p, len)
566     fsm *f;
567     u_char *p;
568     int len;
569 {
570     ccp_options *go = &ccp_gotoptions[f->unit];
571     ccp_options try;            /* options to request next time */
572
573     try = *go;
574
575     /*
576      * Cope with empty configure-rejects by ceasing to send
577      * configure-requests.
578      */
579     if (len == 0 && all_rejected[f->unit])
580         return -1;
581
582     if (go->deflate && len >= CILEN_DEFLATE
583         && p[0] == CI_DEFLATE && p[1] == CILEN_DEFLATE) {
584         if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
585             || p[3] != DEFLATE_CHK_SEQUENCE)
586             return 0;           /* Rej is bad */
587         try.deflate = 0;
588         p += CILEN_DEFLATE;
589         len -= CILEN_DEFLATE;
590     }
591     if (go->bsd_compress && len >= CILEN_BSD_COMPRESS
592         && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) {
593         if (p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits))
594             return 0;
595         try.bsd_compress = 0;
596         p += CILEN_BSD_COMPRESS;
597         len -= CILEN_BSD_COMPRESS;
598     }
599     if (go->predictor_1 && len >= CILEN_PREDICTOR_1
600         && p[0] == CI_PREDICTOR_1 && p[1] == CILEN_PREDICTOR_1) {
601         try.predictor_1 = 0;
602         p += CILEN_PREDICTOR_1;
603         len -= CILEN_PREDICTOR_1;
604     }
605     if (go->predictor_2 && len >= CILEN_PREDICTOR_2
606         && p[0] == CI_PREDICTOR_2 && p[1] == CILEN_PREDICTOR_2) {
607         try.predictor_2 = 0;
608         p += CILEN_PREDICTOR_2;
609         len -= CILEN_PREDICTOR_2;
610     }
611
612     if (len != 0)
613         return 0;
614
615     if (f->state != OPENED)
616         *go = try;
617
618     return 1;
619 }
620
621 /*
622  * ccp_reqci - processed a received configure-request.
623  * Returns CONFACK, CONFNAK or CONFREJ and the packet modified
624  * appropriately.
625  */
626 static int
627 ccp_reqci(f, p, lenp, dont_nak)
628     fsm *f;
629     u_char *p;
630     int *lenp;
631     int dont_nak;
632 {
633     int ret, newret, res;
634     u_char *p0, *retp;
635     int len, clen, type, nb;
636     ccp_options *ho = &ccp_hisoptions[f->unit];
637     ccp_options *ao = &ccp_allowoptions[f->unit];
638
639     ret = CONFACK;
640     retp = p0 = p;
641     len = *lenp;
642
643     memset(ho, 0, sizeof(ccp_options));
644     ho->method = (len > 0)? p[0]: -1;
645
646     while (len > 0) {
647         newret = CONFACK;
648         if (len < 2 || p[1] < 2 || p[1] > len) {
649             /* length is bad */
650             clen = len;
651             newret = CONFREJ;
652
653         } else {
654             type = p[0];
655             clen = p[1];
656
657             switch (type) {
658             case CI_DEFLATE:
659                 if (!ao->deflate || clen != CILEN_DEFLATE) {
660                     newret = CONFREJ;
661                     break;
662                 }
663
664                 ho->deflate = 1;
665                 ho->deflate_size = nb = DEFLATE_SIZE(p[2]);
666                 if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL
667                     || p[3] != DEFLATE_CHK_SEQUENCE
668                     || nb > ao->deflate_size || nb < DEFLATE_MIN_SIZE) {
669                     newret = CONFNAK;
670                     if (!dont_nak) {
671                         p[2] = DEFLATE_MAKE_OPT(ao->deflate_size);
672                         p[3] = DEFLATE_CHK_SEQUENCE;
673                     }
674                     break;
675                 }
676
677                 /*
678                  * Check whether we can do Deflate with the window
679                  * size they want.  If the window is too big, reduce
680                  * it until the kernel can cope and nak with that.
681                  * We only check this for the first option.
682                  */
683                 if (p == p0) {
684                     for (;;) {
685                         res = ccp_test(f->unit, p, CILEN_DEFLATE, 1);
686                         if (res > 0)
687                             break;              /* it's OK now */
688                         if (res < 0 || nb == DEFLATE_MIN_SIZE || dont_nak) {
689                             newret = CONFREJ;
690                             p[2] = DEFLATE_MAKE_OPT(ho->deflate_size);
691                             break;
692                         }
693                         newret = CONFNAK;
694                         --nb;
695                         p[2] = DEFLATE_MAKE_OPT(nb);
696                     }
697                 }
698                 break;
699
700             case CI_BSD_COMPRESS:
701                 if (!ao->bsd_compress || clen != CILEN_BSD_COMPRESS) {
702                     newret = CONFREJ;
703                     break;
704                 }
705
706                 ho->bsd_compress = 1;
707                 ho->bsd_bits = nb = BSD_NBITS(p[2]);
708                 if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION
709                     || nb > ao->bsd_bits || nb < BSD_MIN_BITS) {
710                     newret = CONFNAK;
711                     if (!dont_nak)
712                         p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, ao->bsd_bits);
713                     break;
714                 }
715
716                 /*
717                  * Check whether we can do BSD-Compress with the code
718                  * size they want.  If the code size is too big, reduce
719                  * it until the kernel can cope and nak with that.
720                  * We only check this for the first option.
721                  */
722                 if (p == p0) {
723                     for (;;) {
724                         res = ccp_test(f->unit, p, CILEN_BSD_COMPRESS, 1);
725                         if (res > 0)
726                             break;
727                         if (res < 0 || nb == BSD_MIN_BITS || dont_nak) {
728                             newret = CONFREJ;
729                             p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION,
730                                                 ho->bsd_bits);
731                             break;
732                         }
733                         newret = CONFNAK;
734                         --nb;
735                         p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, nb);
736                     }
737                 }
738                 break;
739
740             case CI_PREDICTOR_1:
741                 if (!ao->predictor_1 || clen != CILEN_PREDICTOR_1) {
742                     newret = CONFREJ;
743                     break;
744                 }
745
746                 ho->predictor_1 = 1;
747                 if (p == p0
748                     && ccp_test(f->unit, p, CILEN_PREDICTOR_1, 1) <= 0) {
749                     newret = CONFREJ;
750                 }
751                 break;
752
753             case CI_PREDICTOR_2:
754                 if (!ao->predictor_2 || clen != CILEN_PREDICTOR_2) {
755                     newret = CONFREJ;
756                     break;
757                 }
758
759                 ho->predictor_2 = 1;
760                 if (p == p0
761                     && ccp_test(f->unit, p, CILEN_PREDICTOR_2, 1) <= 0) {
762                     newret = CONFREJ;
763                 }
764                 break;
765
766             default:
767                 newret = CONFREJ;
768             }
769         }
770
771         if (newret == CONFNAK && dont_nak)
772             newret = CONFREJ;
773         if (!(newret == CONFACK || newret == CONFNAK && ret == CONFREJ)) {
774             /* we're returning this option */
775             if (newret == CONFREJ && ret == CONFNAK)
776                 retp = p0;
777             ret = newret;
778             if (p != retp)
779                 BCOPY(p, retp, clen);
780             retp += clen;
781         }
782
783         p += clen;
784         len -= clen;
785     }
786
787     if (ret != CONFACK) {
788         if (ret == CONFREJ && *lenp == retp - p0)
789             all_rejected[f->unit] = 1;
790         else
791             *lenp = retp - p0;
792     }
793     return ret;
794 }
795
796 /*
797  * Make a string name for a compression method (or 2).
798  */
799 static char *
800 method_name(opt, opt2)
801     ccp_options *opt, *opt2;
802 {
803     static char result[64];
804
805     if (!ANY_COMPRESS(*opt))
806         return "(none)";
807     switch (opt->method) {
808     case CI_DEFLATE:
809         if (opt2 != NULL && opt2->deflate_size != opt->deflate_size)
810             sprintf(result, "Deflate (%d/%d)", opt->deflate_size,
811                     opt2->deflate_size);
812         else
813             sprintf(result, "Deflate (%d)", opt->deflate_size);
814         break;
815     case CI_BSD_COMPRESS:
816         if (opt2 != NULL && opt2->bsd_bits != opt->bsd_bits)
817             sprintf(result, "BSD-Compress (%d/%d)", opt->bsd_bits,
818                     opt2->bsd_bits);
819         else
820             sprintf(result, "BSD-Compress (%d)", opt->bsd_bits);
821         break;
822     case CI_PREDICTOR_1:
823         return "Predictor 1";
824     case CI_PREDICTOR_2:
825         return "Predictor 2";
826     default:
827         sprintf(result, "Method %d", opt->method);
828     }
829     return result;
830 }
831
832 /*
833  * CCP has come up - inform the kernel driver and log a message.
834  */
835 static void
836 ccp_up(f)
837     fsm *f;
838 {
839     ccp_options *go = &ccp_gotoptions[f->unit];
840     ccp_options *ho = &ccp_hisoptions[f->unit];
841     char method1[64];
842
843     ccp_flags_set(f->unit, 1, 1);
844     if (ANY_COMPRESS(*go)) {
845         if (ANY_COMPRESS(*ho)) {
846             if (go->method == ho->method) {
847                 syslog(LOG_NOTICE, "%s compression enabled",
848                        method_name(go, ho));
849             } else {
850                 strcpy(method1, method_name(go, NULL));
851                 syslog(LOG_NOTICE, "%s / %s compression enabled",
852                        method1, method_name(ho, NULL));
853             }
854         } else
855             syslog(LOG_NOTICE, "%s receive compression enabled",
856                    method_name(go, NULL));
857     } else
858         syslog(LOG_NOTICE, "%s transmit compression enabled",
859                method_name(ho, NULL));
860 }
861
862 /*
863  * CCP has gone down - inform the kernel driver.
864  */
865 static void
866 ccp_down(f)
867     fsm *f;
868 {
869     if (ccp_localstate[f->unit] & RACK_PENDING)
870         UNTIMEOUT(ccp_rack_timeout, (caddr_t) f);
871     ccp_localstate[f->unit] = 0;
872     ccp_flags_set(f->unit, 1, 0);
873 }
874
875 /*
876  * Print the contents of a CCP packet.
877  */
878 static char *ccp_codenames[] = {
879     "ConfReq", "ConfAck", "ConfNak", "ConfRej",
880     "TermReq", "TermAck", "CodeRej",
881     NULL, NULL, NULL, NULL, NULL, NULL,
882     "ResetReq", "ResetAck",
883 };
884
885 static int
886 ccp_printpkt(p, plen, printer, arg)
887     u_char *p;
888     int plen;
889     void (*printer) __P((void *, char *, ...));
890     void *arg;
891 {
892     u_char *p0, *optend;
893     int code, id, len;
894     int optlen;
895
896     p0 = p;
897     if (plen < HEADERLEN)
898         return 0;
899     code = p[0];
900     id = p[1];
901     len = (p[2] << 8) + p[3];
902     if (len < HEADERLEN || len > plen)
903         return 0;
904
905     if (code >= 1 && code <= sizeof(ccp_codenames) / sizeof(char *)
906         && ccp_codenames[code-1] != NULL)
907         printer(arg, " %s", ccp_codenames[code-1]);
908     else
909         printer(arg, " code=0x%x", code);
910     printer(arg, " id=0x%x", id);
911     len -= HEADERLEN;
912     p += HEADERLEN;
913
914     switch (code) {
915     case CONFREQ:
916     case CONFACK:
917     case CONFNAK:
918     case CONFREJ:
919         /* print list of possible compression methods */
920         while (len >= 2) {
921             code = p[0];
922             optlen = p[1];
923             if (optlen < 2 || optlen > len)
924                 break;
925             printer(arg, " <");
926             len -= optlen;
927             optend = p + optlen;
928             switch (code) {
929             case CI_DEFLATE:
930                 if (optlen >= CILEN_DEFLATE) {
931                     printer(arg, "deflate %d", DEFLATE_SIZE(p[2]));
932                     if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL)
933                         printer(arg, " method %d", DEFLATE_METHOD(p[2]));
934                     if (p[3] != DEFLATE_CHK_SEQUENCE)
935                         printer(arg, " check %d", p[3]);
936                     p += CILEN_DEFLATE;
937                 }
938                 break;
939             case CI_BSD_COMPRESS:
940                 if (optlen >= CILEN_BSD_COMPRESS) {
941                     printer(arg, "bsd v%d %d", BSD_VERSION(p[2]),
942                             BSD_NBITS(p[2]));
943                     p += CILEN_BSD_COMPRESS;
944                 }
945                 break;
946             case CI_PREDICTOR_1:
947                 if (optlen >= CILEN_PREDICTOR_1) {
948                     printer(arg, "predictor 1");
949                     p += CILEN_PREDICTOR_1;
950                 }
951                 break;
952             case CI_PREDICTOR_2:
953                 if (optlen >= CILEN_PREDICTOR_2) {
954                     printer(arg, "predictor 2");
955                     p += CILEN_PREDICTOR_2;
956                 }
957                 break;
958             }
959             while (p < optend)
960                 printer(arg, " %.2x", *p++);
961             printer(arg, ">");
962         }
963         break;
964
965     case TERMACK:
966     case TERMREQ:
967         if (len > 0 && *p >= ' ' && *p < 0x7f) {
968             print_string(p, len, printer, arg);
969             p += len;
970             len = 0;
971         }
972         break;
973     }
974
975     /* dump out the rest of the packet in hex */
976     while (--len >= 0)
977         printer(arg, " %.2x", *p++);
978
979     return p - p0;
980 }
981
982 /*
983  * We have received a packet that the decompressor failed to
984  * decompress.  Here we would expect to issue a reset-request, but
985  * Motorola has a patent on resetting the compressor as a result of
986  * detecting an error in the decompressed data after decompression.
987  * (See US patent 5,130,993; international patent publication number
988  * WO 91/10289; Australian patent 73296/91.)
989  *
990  * So we ask the kernel whether the error was detected after
991  * decompression; if it was, we take CCP down, thus disabling
992  * compression :-(, otherwise we issue the reset-request.
993  */
994 void
995 ccp_datainput(unit, pkt, len)
996     int unit;
997     u_char *pkt;
998     int len;
999 {
1000     fsm *f;
1001
1002     f = &ccp_fsm[unit];
1003     if (f->state == OPENED) {
1004         if (ccp_fatal_error(unit)) {
1005             /*
1006              * Disable compression by taking CCP down.
1007              */
1008             syslog(LOG_ERR, "Lost compression sync: disabling compression");
1009             ccp_close(unit, "Lost compression sync");
1010         } else {
1011             /*
1012              * Send a reset-request to reset the peer's compressor.
1013              * We don't do that if we are still waiting for an
1014              * acknowledgement to a previous reset-request.
1015              */
1016             if (!(ccp_localstate[f->unit] & RACK_PENDING)) {
1017                 fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0);
1018                 TIMEOUT(ccp_rack_timeout, (caddr_t) f, RACKTIMEOUT);
1019                 ccp_localstate[f->unit] |= RACK_PENDING;
1020             } else
1021                 ccp_localstate[f->unit] |= RREQ_REPEAT;
1022         }
1023     }
1024 }
1025
1026 /*
1027  * Timeout waiting for reset-ack.
1028  */
1029 static void
1030 ccp_rack_timeout(arg)
1031     caddr_t arg;
1032 {
1033     fsm *f = (fsm *) arg;
1034
1035     if (f->state == OPENED && ccp_localstate[f->unit] & RREQ_REPEAT) {
1036         fsm_sdata(f, CCP_RESETREQ, f->reqid, NULL, 0);
1037         TIMEOUT(ccp_rack_timeout, (caddr_t) f, RACKTIMEOUT);
1038         ccp_localstate[f->unit] &= ~RREQ_REPEAT;
1039     } else
1040         ccp_localstate[f->unit] &= ~RACK_PENDING;
1041 }
1042