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