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