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