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