1 /*
2 * ccp.c - PPP Compression Control Protocol.
3 *
4 * Copyright (c) 2000 by Sun Microsystems, Inc.
5 * All rights reserved.
6 *
7 * Copyright (c) 1994 The Australian National University.
8 * All rights reserved.
9 *
10 * Permission to use, copy, modify, and distribute this software and its
11 * documentation is hereby granted, provided that the above copyright
12 * notice appears in all copies. This software is provided without any
13 * warranty, express or implied. The Australian National University
14 * makes no representations about the suitability of this software for
15 * any purpose.
16 *
17 * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
18 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
19 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
20 * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
21 * OF SUCH DAMAGE.
22 *
23 * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
25 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
26 * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
27 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
28 * OR MODIFICATIONS.
29 */
30
31 #pragma ident "%Z%%M% %I% %E% SMI"
32 #define RCSID "$Id: ccp.c,v 1.30 2000/04/15 01:27:11 masputra Exp $"
33
34 #include <stdlib.h>
35 #include <string.h>
36
37 #include "pppd.h"
38 #include "fsm.h"
39 #include "ccp.h"
40 #include <net/ppp-comp.h>
41
42 #if !defined(lint) && !defined(_lint)
43 static const char rcsid[] = RCSID;
44 #endif
45
46 /*
47 * Command-line options.
48 */
49 static int setbsdcomp __P((char **, option_t *));
50 static int setdeflate __P((char **, option_t *));
51
52 static option_t ccp_option_list[] = {
53 { "noccp", o_bool, &ccp_protent.enabled_flag,
54 "Disable CCP negotiation" },
55 { "-ccp", o_bool, &ccp_protent.enabled_flag,
56 "Disable CCP negotiation" },
57 { "bsdcomp", o_special, (void *)setbsdcomp,
58 "Request BSD-Compress packet compression" },
59 { "nobsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress,
60 "don't allow BSD-Compress", OPT_A2COPY,
61 &ccp_allowoptions[0].bsd_compress },
62 { "-bsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress,
63 "don't allow BSD-Compress", OPT_A2COPY,
64 &ccp_allowoptions[0].bsd_compress },
65 { "deflate", o_special, (void *)setdeflate,
66 "request Deflate compression" },
67 { "nodeflate", o_bool, &ccp_wantoptions[0].deflate,
68 "don't allow Deflate compression", OPT_A2COPY,
69 &ccp_allowoptions[0].deflate },
70 { "-deflate", o_bool, &ccp_wantoptions[0].deflate,
71 "don't allow Deflate compression", OPT_A2COPY,
72 &ccp_allowoptions[0].deflate },
73 { "nodeflatedraft", o_bool, &ccp_wantoptions[0].deflate_draft,
74 "don't use draft deflate #", OPT_A2COPY,
75 &ccp_allowoptions[0].deflate_draft },
76 { "predictor1", o_bool, &ccp_wantoptions[0].predictor_1,
77 "request Predictor-1", 1, &ccp_allowoptions[0].predictor_1 },
78 { "nopredictor1", o_bool, &ccp_wantoptions[0].predictor_1,
79 "don't allow Predictor-1", OPT_A2COPY,
80 &ccp_allowoptions[0].predictor_1 },
81 { "-predictor1", o_bool, &ccp_wantoptions[0].predictor_1,
82 "don't allow Predictor-1", OPT_A2COPY,
83 &ccp_allowoptions[0].predictor_1 },
84
85 { NULL }
86 };
87
88 /*
89 * Protocol entry points from main code.
90 */
91 static void ccp_init __P((int unit));
92 static void ccp_open __P((int unit));
93 static void ccp_close __P((int unit, char *));
94 static void ccp_lowerup __P((int unit));
95 static void ccp_lowerdown __P((int));
96 static void ccp_input __P((int unit, u_char *pkt, int len));
97 static void ccp_protrej __P((int unit));
98 static int ccp_printpkt __P((u_char *pkt, int len,
99 void (*printer) __P((void *, const char *, ...)),
100 void *arg));
101 static void ccp_datainput __P((int unit, u_char *pkt, int len));
102
103 struct protent ccp_protent = {
104 PPP_CCP,
105 ccp_init,
106 ccp_input,
107 ccp_protrej,
108 ccp_lowerup,
109 ccp_lowerdown,
110 ccp_open,
111 ccp_close,
112 ccp_printpkt,
113 ccp_datainput,
114 1,
115 "CCP",
116 "Compressed",
117 ccp_option_list,
118 NULL,
119 NULL,
120 NULL
121 };
122
123 fsm ccp_fsm[NUM_PPP];
124 ccp_options ccp_wantoptions[NUM_PPP]; /* what to request the peer to use */
125 ccp_options ccp_gotoptions[NUM_PPP]; /* what the peer agreed to do */
126 ccp_options ccp_allowoptions[NUM_PPP]; /* what we'll agree to do */
127 ccp_options ccp_hisoptions[NUM_PPP]; /* what we agreed to do */
128
129 /*
130 * Callbacks for fsm code.
131 */
132 static void ccp_resetci __P((fsm *));
133 static int ccp_cilen __P((fsm *));
134 static void ccp_addci __P((fsm *, u_char *, int *));
135 static int ccp_ackci __P((fsm *, u_char *, int));
136 static int ccp_nakci __P((fsm *, u_char *, int));
137 static int ccp_rejci __P((fsm *, u_char *, int));
138 static int ccp_reqci __P((fsm *, u_char *, int *, int));
139 static void ccp_up __P((fsm *));
140 static void ccp_down __P((fsm *));
141 static int ccp_extcode __P((fsm *, int, int, u_char *, int));
142 static int ccp_codereject __P((fsm *p, int code, int id, u_char *inp,
143 int len));
144
145 static fsm_callbacks ccp_callbacks = {
146 ccp_resetci, /* Reset our Configuration Information */
147 ccp_cilen, /* Length of our Configuration Information */
148 ccp_addci, /* Add our Configuration Information */
149 ccp_ackci, /* ACK our Configuration Information */
150 ccp_nakci, /* NAK our Configuration Information */
151 ccp_rejci, /* Reject our Configuration Information */
152 ccp_reqci, /* Request peer's Configuration Information */
153 ccp_up, /* Called when fsm reaches OPENED state */
154 ccp_down, /* Called when fsm leaves OPENED state */
155 NULL, /* Called when we want the lower layer up */
156 NULL, /* Called when we want the lower layer down */
157 NULL, /* Retransmission is necessary */
158 ccp_extcode, /* Called to handle LCP-specific codes */
159 "CCP", /* String name of protocol */
160 ccp_codereject, /* Peer rejected a code number */
161 };
162
163 /*
164 * Local statics.
165 */
166 static void ccp_rack_timeout __P((void *));
167 static char * method_name __P((ccp_options *, ccp_options *));
168
169 /*
170 * Do we want / did we get any compression?
171 */
172 #define ANY_COMPRESS(opt) ((opt).deflate || (opt).bsd_compress \
173 || (opt).predictor_1 || (opt).predictor_2)
174
175 /*
176 * Local state (mainly for handling reset-reqs and reset-acks).
177 */
178 static int ccp_localstate[NUM_PPP];
179 #define RACK_PENDING 0x0001 /* waiting for reset-ack */
180 #define RREQ_REPEAT 0x0002 /* send another reset-req if no reset-ack */
181 #define RREQ_REJECTED 0x0004 /* peer code-rejected reset-request */
182 #define RACK_REJECTED 0x0008 /* peer code-rejected reset-ack */
183 #define RREQ_IGNORED 0x0010 /* peer just ignored reset-request */
184
185 #define RACKTIMEOUT 1 /* time in seconds between Reset-Requests */
186
187 static int all_rejected[NUM_PPP]; /* we rejected all peer's options */
188
189 #ifdef COMP_TUNE
190 static int deflate_tune = -1; /* compression effort level for deflate */
191 #endif
192 static int deflate_rmax = DEFLATE_MAX_SIZE; /* max rbits */
193 static int deflate_amax = DEFLATE_MAX_SIZE; /* max abits */
194
195 /*
196 * Option parsing.
197 */
198 /*ARGSUSED*/
199 static int
setbsdcomp(argv,opt)200 setbsdcomp(argv, opt)
201 char **argv;
202 option_t *opt;
203 {
204 int rbits, abits;
205 char *str, *endp;
206
207 str = *argv;
208 abits = rbits = strtol(str, &endp, 0);
209 if (endp != str && *endp == ',') {
210 str = endp + 1;
211 abits = strtol(str, &endp, 0);
212 }
213 if (*endp != '\0' || endp == str) {
214 option_error("invalid parameter '%s' for bsdcomp option", *argv);
215 return 0;
216 }
217 if ((rbits != 0 && (rbits < BSD_MIN_BITS || rbits > BSD_MAX_BITS))
218 || (abits != 0 && (abits < BSD_MIN_BITS || abits > BSD_MAX_BITS))) {
219 option_error("bsdcomp option values must be 0 or %d .. %d",
220 BSD_MIN_BITS, BSD_MAX_BITS);
221 return 0;
222 }
223 if (rbits > 0) {
224 ccp_wantoptions[0].bsd_compress = 1;
225 ccp_wantoptions[0].bsd_bits = rbits;
226 } else
227 ccp_wantoptions[0].bsd_compress = 0;
228 if (abits > 0) {
229 ccp_allowoptions[0].bsd_compress = 1;
230 ccp_allowoptions[0].bsd_bits = abits;
231 } else
232 ccp_allowoptions[0].bsd_compress = 0;
233 return 1;
234 }
235
236 /*ARGSUSED*/
237 static int
setdeflate(argv,opt)238 setdeflate(argv, opt)
239 char **argv;
240 option_t *opt;
241 {
242 int rbits, abits, def_rmax, def_amax;
243 char *str, *endp;
244
245 str = endp = *argv;
246 if (*str == ',')
247 abits = rbits = -1;
248 else
249 abits = rbits = strtol(str, &endp, 0);
250 if (*endp == ',') {
251 str = ++endp;
252 if (*str == ',')
253 abits = rbits;
254 else
255 abits = strtol(str, &endp, 0);
256 }
257 #ifdef COMP_TUNE
258 if (*endp == ',' && privileged_option) {
259 str = ++endp;
260 deflate_tune = strtol(str, &endp, 0);
261 }
262 #endif
263 if (*endp != '\0' || endp == str) {
264 option_error("invalid parameter '%s' for deflate option", *argv);
265 return 0;
266 }
267 if (privileged_option) {
268 def_rmax = def_amax = DEFLATE_MAX_SIZE;
269 } else {
270 def_rmax = deflate_rmax;
271 def_amax = deflate_amax;
272 }
273 if (rbits < 0)
274 rbits = def_rmax;
275 if (abits < 0)
276 abits = def_amax;
277 if ((rbits != 0 && (rbits <= DEFLATE_MIN_SIZE || rbits > def_rmax))
278 || (abits != 0 && (abits <= DEFLATE_MIN_SIZE || abits > def_amax))) {
279 option_error("deflate option values must be 0 or {%d,%d} .. {%d,%d}",
280 DEFLATE_MIN_SIZE+1, DEFLATE_MIN_SIZE+1,
281 def_rmax, def_amax);
282 return 0;
283 }
284 if (privileged_option) {
285 deflate_rmax = rbits;
286 deflate_amax = abits;
287 }
288 if (rbits > 0) {
289 ccp_wantoptions[0].deflate = 1;
290 ccp_wantoptions[0].deflate_size = rbits;
291 } else
292 ccp_wantoptions[0].deflate = 0;
293 if (abits > 0) {
294 ccp_allowoptions[0].deflate = 1;
295 ccp_allowoptions[0].deflate_size = abits;
296 } else
297 ccp_allowoptions[0].deflate = 0;
298 return 1;
299 }
300
301
302 /*
303 * ccp_init - initialize CCP.
304 */
305 static void
ccp_init(unit)306 ccp_init(unit)
307 int unit;
308 {
309 fsm *f = &ccp_fsm[unit];
310
311 f->unit = unit;
312 f->protocol = PPP_CCP;
313 f->callbacks = &ccp_callbacks;
314 fsm_init(f);
315 f->flags |= OPT_RESTART;
316
317 BZERO(&ccp_wantoptions[unit], sizeof(ccp_options));
318 BZERO(&ccp_gotoptions[unit], sizeof(ccp_options));
319 BZERO(&ccp_allowoptions[unit], sizeof(ccp_options));
320 BZERO(&ccp_hisoptions[unit], sizeof(ccp_options));
321
322 ccp_wantoptions[0].deflate = 1;
323 ccp_wantoptions[0].deflate_size = DEFLATE_MAX_SIZE;
324 ccp_wantoptions[0].deflate_correct = 1;
325 ccp_wantoptions[0].deflate_draft = 1;
326 ccp_allowoptions[0].deflate = 1;
327 ccp_allowoptions[0].deflate_size = DEFLATE_MAX_SIZE;
328 ccp_allowoptions[0].deflate_correct = 1;
329 ccp_allowoptions[0].deflate_draft = 1;
330
331 ccp_wantoptions[0].bsd_compress = 1;
332 ccp_wantoptions[0].bsd_bits = BSD_MAX_BITS;
333 ccp_allowoptions[0].bsd_compress = 1;
334 ccp_allowoptions[0].bsd_bits = BSD_MAX_BITS;
335
336 ccp_allowoptions[0].predictor_1 = 1;
337 }
338
339 /*
340 * ccp_open - CCP is allowed to come up.
341 */
342 static void
ccp_open(unit)343 ccp_open(unit)
344 int unit;
345 {
346 fsm *f = &ccp_fsm[unit];
347
348 /*
349 * If we haven't gone open yet (first time through), then go open
350 * but not up. Otherwise, skip this to allow reopen to reset the
351 * compressor.
352 */
353 if (f->state != OPENED)
354 ccp_flags_set(unit, 1, 0);
355
356 /*
357 * Find out which compressors the kernel supports before
358 * deciding whether to open in silent mode.
359 */
360 ccp_resetci(f);
361 if (!ANY_COMPRESS(ccp_gotoptions[unit]))
362 f->flags |= OPT_SILENT;
363
364 fsm_open(f);
365 }
366
367 /*
368 * ccp_close - Terminate CCP.
369 */
370 static void
ccp_close(unit,reason)371 ccp_close(unit, reason)
372 int unit;
373 char *reason;
374 {
375 ccp_flags_set(unit, 0, 0);
376 fsm_close(&ccp_fsm[unit], reason);
377 }
378
379 /*
380 * ccp_lowerup - we may now transmit CCP packets.
381 */
382 static void
ccp_lowerup(unit)383 ccp_lowerup(unit)
384 int unit;
385 {
386 fsm_lowerup(&ccp_fsm[unit]);
387 }
388
389 /*
390 * ccp_lowerdown - we may not transmit CCP packets.
391 */
392 static void
ccp_lowerdown(unit)393 ccp_lowerdown(unit)
394 int unit;
395 {
396 fsm_lowerdown(&ccp_fsm[unit]);
397 }
398
399 /*
400 * ccp_input - process a received CCP packet.
401 */
402 static void
ccp_input(unit,p,len)403 ccp_input(unit, p, len)
404 int unit;
405 u_char *p;
406 int len;
407 {
408 fsm *f = &ccp_fsm[unit];
409 int oldstate;
410
411 /*
412 * Check for a terminate-request so we can print a message.
413 */
414 oldstate = f->state;
415 fsm_input(f, p, len);
416 if (oldstate == OPENED && p[0] == CODE_TERMREQ && f->state != OPENED)
417 notice("Compression disabled by peer.");
418
419 /*
420 * If we get a terminate-ack and we're not asking for compression,
421 * close CCP. (Terminate-Request is handled by fsm_input() above.)
422 */
423 if (oldstate == REQSENT && p[0] == CODE_TERMACK
424 && !ANY_COMPRESS(ccp_gotoptions[unit]))
425 ccp_close(unit, "No compression negotiated");
426 }
427
428 /*
429 * Handle a CCP-specific code.
430 */
431 static int
ccp_extcode(f,code,id,p,len)432 ccp_extcode(f, code, id, p, len)
433 fsm *f;
434 int code, id;
435 u_char *p;
436 int len;
437 {
438 switch (code) {
439 case CCP_RESETREQ:
440 /* If not open, then silently ignore. */
441 if (f->state != OPENED)
442 break;
443 /* send a reset-ack, which our transmitter module will see and
444 reset its compression state. */
445 fsm_sdata(f, CCP_RESETACK, id, p, len);
446 break;
447
448 case CCP_RESETACK:
449 /*
450 * Note that the compression module isn't picky about ID
451 * numbers and such.
452 */
453 ccp_localstate[f->unit] &= ~RREQ_IGNORED & ~RREQ_REJECTED;
454 if ((ccp_localstate[f->unit] & RACK_PENDING) && id == f->reqid) {
455 ccp_localstate[f->unit] &= ~RACK_PENDING & ~RREQ_REPEAT;
456 UNTIMEOUT(ccp_rack_timeout, f);
457 }
458 break;
459
460 default:
461 /* Tell fsm to send code reject */
462 return (0);
463 }
464
465 return (1);
466 }
467
468 /*
469 * Handle Code-Reject for one of our extended codes by dropping back to
470 * reopen as mechanism to restart compression.
471 */
472 /*ARGSUSED*/
473 static int
ccp_codereject(f,code,id,inp,len)474 ccp_codereject(f, code, id, inp, len)
475 fsm *f;
476 int code, id;
477 u_char *inp;
478 int len;
479 {
480 switch (code) {
481 case CCP_RESETREQ:
482 if (!(ccp_localstate[f->unit] & RREQ_REJECTED)) {
483 info("peer has rejected CCP Reset-Request; falling back on Open");
484 if (f->state == OPENED)
485 ccp_open(f->unit);
486 }
487 ccp_localstate[f->unit] |= RREQ_REJECTED;
488 return (0);
489
490 case CCP_RESETACK:
491 /*
492 * Peer must have sent us CCP Reset-Request but then code-rejected
493 * when we sent CCP Reset-Ack. He's a moron, be we have to obey
494 * his wishes.
495 */
496 ccp_localstate[f->unit] |= RACK_REJECTED;
497 notice("peer has erroneously rejected CCP Reset-Ack");
498 f->term_reason = "peer sent Code-Reject for CCP Reset-Ack";
499 f->term_reason_len = strlen(f->term_reason);
500 break;
501
502 default:
503 f->term_reason = "peer sent invalid Code-Reject";
504 break;
505 }
506
507 f->term_reason_len = strlen(f->term_reason);
508 return (1);
509 }
510
511 /*
512 * ccp_protrej - peer doesn't talk CCP.
513 */
514 static void
ccp_protrej(unit)515 ccp_protrej(unit)
516 int unit;
517 {
518 /* Neither open nor up. */
519 ccp_flags_set(unit, 0, 0);
520 fsm_lowerdown(&ccp_fsm[unit]);
521 }
522
523 /*
524 * ccp_resetci - initialize at start of negotiation.
525 */
526 static void
ccp_resetci(f)527 ccp_resetci(f)
528 fsm *f;
529 {
530 ccp_options *go = &ccp_gotoptions[f->unit];
531 u_char opt_buf[16];
532
533 *go = ccp_wantoptions[f->unit];
534 all_rejected[f->unit] = 0;
535
536 /*
537 * Check whether the kernel knows about the various
538 * decompression methods we might request.
539 */
540 if (go->bsd_compress) {
541 opt_buf[0] = CI_BSD_COMPRESS;
542 opt_buf[1] = CILEN_BSD_COMPRESS;
543 opt_buf[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, BSD_MIN_BITS);
544 if (ccp_test(f->unit, opt_buf, CILEN_BSD_COMPRESS, 0) <= 0)
545 go->bsd_compress = 0;
546 }
547 if (go->deflate) {
548 if (go->deflate_correct) {
549 opt_buf[0] = CI_DEFLATE;
550 opt_buf[1] = CILEN_DEFLATE;
551 opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_SIZE+1);
552 opt_buf[3] = DEFLATE_CHK_SEQUENCE;
553 if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0)
554 go->deflate_correct = 0;
555 }
556 if (go->deflate_draft) {
557 opt_buf[0] = CI_DEFLATE_DRAFT;
558 opt_buf[1] = CILEN_DEFLATE;
559 opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_SIZE+1);
560 opt_buf[3] = DEFLATE_CHK_SEQUENCE;
561 if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0)
562 go->deflate_draft = 0;
563 }
564 if (!go->deflate_correct && !go->deflate_draft)
565 go->deflate = 0;
566 }
567 if (go->predictor_1) {
568 opt_buf[0] = CI_PREDICTOR_1;
569 opt_buf[1] = CILEN_PREDICTOR_1;
570 if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_1, 0) <= 0)
571 go->predictor_1 = 0;
572 }
573 if (go->predictor_2) {
574 opt_buf[0] = CI_PREDICTOR_2;
575 opt_buf[1] = CILEN_PREDICTOR_2;
576 if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_2, 0) <= 0)
577 go->predictor_2 = 0;
578 }
579 }
580
581 /*
582 * ccp_cilen - Return total length of our configuration info.
583 */
584 static int
ccp_cilen(f)585 ccp_cilen(f)
586 fsm *f;
587 {
588 ccp_options *go = &ccp_gotoptions[f->unit];
589
590 return (go->bsd_compress? CILEN_BSD_COMPRESS: 0)
591 + (go->deflate && go->deflate_correct ? CILEN_DEFLATE : 0)
592 + (go->deflate && go->deflate_draft ? CILEN_DEFLATE : 0)
593 + (go->predictor_1? CILEN_PREDICTOR_1: 0)
594 + (go->predictor_2? CILEN_PREDICTOR_2: 0);
595 }
596
597 /*
598 * ccp_addci - put our requests in a packet.
599 */
600 static void
ccp_addci(f,p,lenp)601 ccp_addci(f, p, lenp)
602 fsm *f;
603 u_char *p;
604 int *lenp;
605 {
606 int res;
607 ccp_options *go = &ccp_gotoptions[f->unit];
608 u_char *p0 = p;
609
610 /*
611 * Add the compression types that we can receive, in decreasing
612 * preference order. Get the kernel to allocate the first one
613 * in case it gets Acked.
614 */
615 if (go->deflate) {
616 p[0] = go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT;
617 p[1] = CILEN_DEFLATE;
618 p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
619 p[3] = DEFLATE_CHK_SEQUENCE;
620 for (;;) {
621 res = ccp_test(f->unit, p, CILEN_DEFLATE, 0);
622 if (res > 0) {
623 p += CILEN_DEFLATE;
624 break;
625 }
626 if (res < 0 || go->deflate_size <= DEFLATE_MIN_SIZE+1) {
627 go->deflate = 0;
628 break;
629 }
630 --go->deflate_size;
631 p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
632 }
633 /* If we're offering both, then this is second. */
634 if (p != p0 && go->deflate_correct && go->deflate_draft) {
635 p[0] = CI_DEFLATE_DRAFT;
636 p[1] = CILEN_DEFLATE;
637 p[2] = p[2 - CILEN_DEFLATE];
638 p[3] = DEFLATE_CHK_SEQUENCE;
639 p += CILEN_DEFLATE;
640 }
641 }
642 if (go->bsd_compress) {
643 p[0] = CI_BSD_COMPRESS;
644 p[1] = CILEN_BSD_COMPRESS;
645 p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
646 if (p != p0) {
647 p += CILEN_BSD_COMPRESS; /* not the first option */
648 } else {
649 for (;;) {
650 res = ccp_test(f->unit, p, CILEN_BSD_COMPRESS, 0);
651 if (res > 0) {
652 p += CILEN_BSD_COMPRESS;
653 break;
654 }
655 if (res < 0 || go->bsd_bits <= BSD_MIN_BITS) {
656 go->bsd_compress = 0;
657 break;
658 }
659 --go->bsd_bits;
660 p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
661 }
662 }
663 }
664 /*
665 * Prefer Predictor-1 over Predictor-2. (The latter requires the use
666 * of LAP-B and has no known implementations.)
667 */
668 if (go->predictor_1) {
669 p[0] = CI_PREDICTOR_1;
670 p[1] = CILEN_PREDICTOR_1;
671 if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_1, 0) <= 0) {
672 go->predictor_1 = 0;
673 } else {
674 p += CILEN_PREDICTOR_1;
675 }
676 }
677 if (go->predictor_2) {
678 p[0] = CI_PREDICTOR_2;
679 p[1] = CILEN_PREDICTOR_2;
680 if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_2, 0) <= 0) {
681 go->predictor_2 = 0;
682 } else {
683 p += CILEN_PREDICTOR_2;
684 }
685 }
686
687 go->method = (p > p0)? p0[0]: -1;
688
689 *lenp = p - p0;
690 }
691
692 /*
693 * ccp_ackci - process a received configure-ack, and return
694 * 1 iff the packet was OK.
695 */
696 static int
ccp_ackci(f,p,len)697 ccp_ackci(f, p, len)
698 fsm *f;
699 u_char *p;
700 int len;
701 {
702 ccp_options *go = &ccp_gotoptions[f->unit];
703 u_char *p0 = p;
704
705 if (go->deflate && go->deflate_correct) {
706 if (len < CILEN_DEFLATE
707 || p[0] != CI_DEFLATE || p[1] != CILEN_DEFLATE
708 || p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
709 || p[3] != DEFLATE_CHK_SEQUENCE)
710 return 0;
711 /* Cope with non-standard first/fast ack */
712 if (p == p0 && len == 0)
713 return 1;
714 p += CILEN_DEFLATE;
715 len -= CILEN_DEFLATE;
716 }
717 if (go->deflate && go->deflate_draft) {
718 if (len < CILEN_DEFLATE
719 || p[0] != CI_DEFLATE_DRAFT || p[1] != CILEN_DEFLATE
720 || p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
721 || p[3] != DEFLATE_CHK_SEQUENCE)
722 return 0;
723 /* Cope with non-standard first/fast ack */
724 if (p == p0 && len == 0)
725 return 1;
726 p += CILEN_DEFLATE;
727 len -= CILEN_DEFLATE;
728 }
729 if (go->bsd_compress) {
730 if (len < CILEN_BSD_COMPRESS
731 || p[0] != CI_BSD_COMPRESS || p[1] != CILEN_BSD_COMPRESS
732 || p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits))
733 return 0;
734 /* Cope with non-standard first/fast ack */
735 if (p == p0 && len == 0)
736 return 1;
737 p += CILEN_BSD_COMPRESS;
738 len -= CILEN_BSD_COMPRESS;
739 }
740 if (go->predictor_1) {
741 if (len < CILEN_PREDICTOR_1
742 || p[0] != CI_PREDICTOR_1 || p[1] != CILEN_PREDICTOR_1)
743 return 0;
744 /* Cope with non-standard first/fast ack */
745 if (p == p0 && len == 0)
746 return 1;
747 p += CILEN_PREDICTOR_1;
748 len -= CILEN_PREDICTOR_1;
749 }
750 if (go->predictor_2) {
751 if (len < CILEN_PREDICTOR_2
752 || p[0] != CI_PREDICTOR_2 || p[1] != CILEN_PREDICTOR_2)
753 return 0;
754 /* Cope with non-standard first/fast ack */
755 if (p == p0 && len == 0)
756 return 1;
757 p += CILEN_PREDICTOR_2;
758 len -= CILEN_PREDICTOR_2;
759 }
760
761 /* Peer cannot ack something that wasn't sent. */
762 if (len != 0)
763 return 0;
764 return 1;
765 }
766
767 /*
768 * ccp_nakci - process received configure-nak.
769 * Returns 1 iff the nak was OK.
770 */
771 static int
ccp_nakci(f,p,len)772 ccp_nakci(f, p, len)
773 fsm *f;
774 u_char *p;
775 int len;
776 {
777 ccp_options *go = &ccp_gotoptions[f->unit];
778 ccp_options no; /* options we've seen already */
779 ccp_options try; /* options to ask for next time */
780
781 BZERO(&no, sizeof(no));
782 try = *go;
783
784 if (go->deflate && go->deflate_correct && len >= CILEN_DEFLATE &&
785 p[0] == CI_DEFLATE) {
786 no.deflate = 1;
787 /*
788 * Peer wants us to use a different code size or something.
789 * Stop asking for Deflate if we don't understand his suggestion.
790 */
791 if (p[1] != CILEN_DEFLATE
792 || DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL
793 || DEFLATE_SIZE(p[2]) <= DEFLATE_MIN_SIZE
794 || p[3] != DEFLATE_CHK_SEQUENCE)
795 try.deflate_correct = 0;
796 else if (DEFLATE_SIZE(p[2]) < go->deflate_size)
797 try.deflate_size = DEFLATE_SIZE(p[2]);
798 len -= p[1];
799 p += p[1];
800 }
801
802 if (go->deflate && go->deflate_draft && len >= CILEN_DEFLATE &&
803 p[0] == CI_DEFLATE_DRAFT) {
804 no.deflate = 1;
805 /*
806 * Peer wants us to use a different code size or something.
807 * Stop asking for Deflate using the old algorithm number if
808 * we don't understand his suggestion. (Note that this will
809 * happen if the peer is running Magnalink instead of
810 * old-style Deflate.)
811 */
812 if (p[1] != CILEN_DEFLATE
813 || DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL
814 || DEFLATE_SIZE(p[2]) <= DEFLATE_MIN_SIZE
815 || p[3] != DEFLATE_CHK_SEQUENCE)
816 try.deflate_draft = 0;
817 else if (DEFLATE_SIZE(p[2]) < go->deflate_size)
818 try.deflate_size = DEFLATE_SIZE(p[2]);
819 len -= p[1];
820 p += p[1];
821 }
822
823 if (!try.deflate_correct && !try.deflate_draft)
824 try.deflate = 0;
825
826 if (go->bsd_compress && len >= CILEN_BSD_COMPRESS &&
827 p[0] == CI_BSD_COMPRESS) {
828 no.bsd_compress = 1;
829 /*
830 * Peer wants us to use a different number of bits
831 * or a different version.
832 */
833 if (p[1] != CILEN_BSD_COMPRESS ||
834 BSD_VERSION(p[2]) != BSD_CURRENT_VERSION)
835 try.bsd_compress = 0;
836 else if (BSD_NBITS(p[2]) < go->bsd_bits)
837 try.bsd_bits = BSD_NBITS(p[2]);
838 len -= p[1];
839 p += p[1];
840 }
841
842 /*
843 * Predictor-1 and 2 have no options, so they can't be Naked.
844 *
845 * There may be remaining options but we ignore them.
846 */
847
848 if (f->state != OPENED)
849 *go = try;
850 return 1;
851 }
852
853 /*
854 * ccp_rejci - peer rejects some of our suggested compression methods.
855 */
856 static int
ccp_rejci(f,p,len)857 ccp_rejci(f, p, len)
858 fsm *f;
859 u_char *p;
860 int len;
861 {
862 ccp_options *go = &ccp_gotoptions[f->unit];
863 ccp_options try; /* options to request next time */
864
865 try = *go;
866
867 /*
868 * Cope with empty configure-rejects by ceasing to send
869 * configure-requests.
870 */
871 if (len == 0 && all_rejected[f->unit])
872 return -1;
873
874 if (go->deflate && go->deflate_correct && len >= CILEN_DEFLATE &&
875 p[0] == CI_DEFLATE && p[1] == CILEN_DEFLATE) {
876 if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
877 || p[3] != DEFLATE_CHK_SEQUENCE)
878 return 0; /* Rej is bad */
879 try.deflate_correct = 0;
880 p += CILEN_DEFLATE;
881 len -= CILEN_DEFLATE;
882 }
883 if (go->deflate && go->deflate_draft && len >= CILEN_DEFLATE &&
884 p[0] == CI_DEFLATE_DRAFT && p[1] == CILEN_DEFLATE) {
885 if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
886 || p[3] != DEFLATE_CHK_SEQUENCE)
887 return 0; /* Rej is bad */
888 try.deflate_draft = 0;
889 p += CILEN_DEFLATE;
890 len -= CILEN_DEFLATE;
891 }
892 if (!try.deflate_correct && !try.deflate_draft)
893 try.deflate = 0;
894 if (go->bsd_compress && len >= CILEN_BSD_COMPRESS
895 && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) {
896 if (p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits))
897 return 0;
898 try.bsd_compress = 0;
899 p += CILEN_BSD_COMPRESS;
900 len -= CILEN_BSD_COMPRESS;
901 }
902 if (go->predictor_1 && len >= CILEN_PREDICTOR_1
903 && p[0] == CI_PREDICTOR_1 && p[1] == CILEN_PREDICTOR_1) {
904 try.predictor_1 = 0;
905 p += CILEN_PREDICTOR_1;
906 len -= CILEN_PREDICTOR_1;
907 }
908 if (go->predictor_2 && len >= CILEN_PREDICTOR_2
909 && p[0] == CI_PREDICTOR_2 && p[1] == CILEN_PREDICTOR_2) {
910 try.predictor_2 = 0;
911 p += CILEN_PREDICTOR_2;
912 len -= CILEN_PREDICTOR_2;
913 }
914
915 if (len != 0)
916 return 0;
917
918 if (f->state != OPENED)
919 *go = try;
920
921 return 1;
922 }
923
924 /*
925 * ccp_reqci - process a received configure-request.
926 *
927 * Returns CODE_CONFACK, CODE_CONFNAK or CODE_CONFREJ and the packet
928 * is modified appropriately.
929 */
930 static int
ccp_reqci(f,p,lenp,dont_nak)931 ccp_reqci(f, p, lenp, dont_nak)
932 fsm *f;
933 u_char *p;
934 int *lenp;
935 int dont_nak;
936 {
937 int ret, newret, res;
938 u_char *p0, *nakp, *rejp, *pv;
939 int len, clen, type, nb;
940 ccp_options *ho = &ccp_hisoptions[f->unit];
941 ccp_options *ao = &ccp_allowoptions[f->unit];
942
943 ret = CODE_CONFACK;
944 rejp = p0 = p;
945 nakp = nak_buffer;
946 len = *lenp;
947
948 BZERO(ho, sizeof(ccp_options));
949 ho->method = (len > 0)? p[0]: -1;
950
951 for (; len > 0; len -= clen, p += clen) {
952 newret = CODE_CONFACK;
953 if (len < 2 || p[1] > len) {
954 /*
955 * RFC 1661 page 40 -- if the option extends beyond the
956 * packet, then discard the entire packet.
957 */
958 return (0);
959 }
960
961 type = p[0];
962 clen = p[1];
963
964 pv = p;
965 switch (type) {
966 case CI_DEFLATE:
967 case CI_DEFLATE_DRAFT:
968 if (!ao->deflate ||
969 (!ao->deflate_correct && type == CI_DEFLATE) ||
970 (!ao->deflate_draft && type == CI_DEFLATE_DRAFT)) {
971 newret = CODE_CONFREJ;
972 break;
973 }
974
975 ho->deflate = 1;
976 nb = clen < CILEN_DEFLATE ? ao->deflate_size : DEFLATE_SIZE(p[2]);
977 ho->deflate_size = nb;
978 if (clen != CILEN_DEFLATE ||
979 DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL ||
980 p[3] != DEFLATE_CHK_SEQUENCE || nb > ao->deflate_size ||
981 nb <= DEFLATE_MIN_SIZE) {
982 newret = CODE_CONFNAK;
983 if (dont_nak)
984 break;
985 if (nb > ao->deflate_size)
986 nb = ao->deflate_size;
987 else if (nb <= DEFLATE_MIN_SIZE)
988 nb = DEFLATE_MIN_SIZE+1;
989 pv = nakp;
990 PUTCHAR(type, nakp);
991 PUTCHAR(CILEN_DEFLATE, nakp);
992 PUTCHAR(DEFLATE_MAKE_OPT(nb), nakp);
993 PUTCHAR(DEFLATE_CHK_SEQUENCE, nakp);
994 }
995
996 /*
997 * Check whether we can do Deflate with the window
998 * size they want. If the window is too big, reduce
999 * it until the kernel can cope and nak with that.
1000 * We only check this for the first option.
1001 */
1002 if (p == p0) {
1003 for (;;) {
1004 res = ccp_test(f->unit, pv, CILEN_DEFLATE, 1);
1005 if (res > 0)
1006 break; /* it's OK now */
1007 if (res < 0 || nb <= DEFLATE_MIN_SIZE+1 || dont_nak) {
1008 newret = CODE_CONFREJ;
1009 break;
1010 }
1011 if (newret == CODE_CONFACK) {
1012 BCOPY(pv, nakp, CILEN_DEFLATE);
1013 pv = nakp;
1014 nakp += CILEN_DEFLATE;
1015 newret = CODE_CONFNAK;
1016 }
1017 --nb;
1018 pv[2] = DEFLATE_MAKE_OPT(nb);
1019 }
1020 #ifdef COMP_TUNE
1021 /* Tune Deflate compression effort. */
1022 if (newret == CODE_CONFACK)
1023 ccp_tune(f->unit, deflate_tune);
1024 #endif
1025 }
1026 break;
1027
1028 case CI_BSD_COMPRESS:
1029 if (!ao->bsd_compress) {
1030 newret = CODE_CONFREJ;
1031 break;
1032 }
1033
1034 ho->bsd_compress = 1;
1035 nb = clen < CILEN_BSD_COMPRESS ? ao->bsd_bits : BSD_NBITS(p[2]);
1036 ho->bsd_bits = nb;
1037 if (clen != CILEN_BSD_COMPRESS ||
1038 BSD_VERSION(p[2]) != BSD_CURRENT_VERSION ||
1039 nb > ao->bsd_bits || nb < BSD_MIN_BITS) {
1040 newret = CODE_CONFNAK;
1041 if (dont_nak)
1042 break;
1043 if (nb > ao->bsd_bits)
1044 nb = ao->bsd_bits;
1045 else if (nb < BSD_MIN_BITS)
1046 nb = BSD_MIN_BITS;
1047 pv = nakp;
1048 PUTCHAR(type, nakp);
1049 PUTCHAR(CILEN_BSD_COMPRESS, nakp);
1050 PUTCHAR(BSD_MAKE_OPT(BSD_CURRENT_VERSION, nb), nakp);
1051 }
1052
1053 /*
1054 * Check whether we can do BSD-Compress with the code
1055 * size they want. If the code size is too big, reduce
1056 * it until the kernel can cope and nak with that.
1057 * We only check this for the first option.
1058 */
1059 if (p == p0) {
1060 for (;;) {
1061 res = ccp_test(f->unit, pv, CILEN_BSD_COMPRESS, 1);
1062 if (res > 0)
1063 break;
1064 if (res < 0 || nb == BSD_MIN_BITS || dont_nak) {
1065 newret = CODE_CONFREJ;
1066 break;
1067 }
1068 if (newret == CODE_CONFACK) {
1069 BCOPY(pv, nakp, CILEN_BSD_COMPRESS);
1070 pv = nakp;
1071 nakp += CILEN_BSD_COMPRESS;
1072 newret = CODE_CONFNAK;
1073 }
1074 --nb;
1075 pv[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, nb);
1076 }
1077 }
1078 break;
1079
1080 case CI_PREDICTOR_1:
1081 if (!ao->predictor_1) {
1082 newret = CODE_CONFREJ;
1083 break;
1084 }
1085
1086 ho->predictor_1 = 1;
1087 if (clen != CILEN_PREDICTOR_1) {
1088 newret = CODE_CONFNAK;
1089 if (dont_nak)
1090 break;
1091 pv = nakp;
1092 PUTCHAR(type, nakp);
1093 PUTCHAR(CILEN_PREDICTOR_1, nakp);
1094 }
1095 if (p == p0 &&
1096 ccp_test(f->unit, pv, CILEN_PREDICTOR_1, 1) <= 0) {
1097 newret = CODE_CONFREJ;
1098 }
1099 break;
1100
1101 case CI_PREDICTOR_2:
1102 if (!ao->predictor_2) {
1103 newret = CODE_CONFREJ;
1104 break;
1105 }
1106
1107 ho->predictor_2 = 1;
1108 if (clen != CILEN_PREDICTOR_2) {
1109 newret = CODE_CONFNAK;
1110 if (dont_nak)
1111 break;
1112 pv = nakp;
1113 PUTCHAR(type, nakp);
1114 PUTCHAR(CILEN_PREDICTOR_2, nakp);
1115 }
1116 if (p == p0 &&
1117 ccp_test(f->unit, p, CILEN_PREDICTOR_2, 1) <= 0) {
1118 newret = CODE_CONFREJ;
1119 }
1120 break;
1121
1122 default:
1123 newret = CODE_CONFREJ;
1124 break;
1125 }
1126
1127 /* Cope with confused peers. */
1128 if (clen < 2)
1129 clen = 2;
1130
1131 if (newret == CODE_CONFACK && ret != CODE_CONFACK)
1132 continue;
1133 if (newret == CODE_CONFNAK) {
1134 if (dont_nak) {
1135 newret = CODE_CONFREJ;
1136 } else {
1137 /* Ignore subsequent nakable things if rejecting. */
1138 if (ret == CODE_CONFREJ)
1139 continue;
1140 ret = CODE_CONFNAK;
1141 }
1142 }
1143 if (newret == CODE_CONFREJ) {
1144 ret = CODE_CONFREJ;
1145 if (p != rejp)
1146 BCOPY(p, rejp, clen);
1147 rejp += clen;
1148 }
1149 }
1150
1151 switch (ret) {
1152 case CODE_CONFACK:
1153 *lenp = p - p0;
1154 break;
1155 case CODE_CONFNAK:
1156 *lenp = nakp - nak_buffer;
1157 BCOPY(nak_buffer, p0, *lenp);
1158 break;
1159 case CODE_CONFREJ:
1160 *lenp = rejp - p0;
1161 break;
1162 }
1163 return ret;
1164 }
1165
1166 /*
1167 * Make a string name for a compression method (or 2).
1168 */
1169 static char *
method_name(opt,opt2)1170 method_name(opt, opt2)
1171 ccp_options *opt, *opt2;
1172 {
1173 static char result[64];
1174
1175 if (!ANY_COMPRESS(*opt))
1176 return "(none)";
1177 switch (opt->method) {
1178 case CI_DEFLATE:
1179 case CI_DEFLATE_DRAFT:
1180 if (opt2 != NULL && opt2->deflate_size != opt->deflate_size)
1181 (void) slprintf(result, sizeof(result), "Deflate%s (%d/%d)",
1182 (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""),
1183 opt->deflate_size, opt2->deflate_size);
1184 else
1185 (void) slprintf(result, sizeof(result), "Deflate%s (%d)",
1186 (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""),
1187 opt->deflate_size);
1188 break;
1189 case CI_BSD_COMPRESS:
1190 if (opt2 != NULL && opt2->bsd_bits != opt->bsd_bits)
1191 (void) slprintf(result, sizeof(result), "BSD-Compress (%d/%d)",
1192 opt->bsd_bits, opt2->bsd_bits);
1193 else
1194 (void) slprintf(result, sizeof(result), "BSD-Compress (%d)",
1195 opt->bsd_bits);
1196 break;
1197 case CI_PREDICTOR_1:
1198 return "Predictor 1";
1199 case CI_PREDICTOR_2:
1200 return "Predictor 2";
1201 #ifdef CI_STAC
1202 case CI_STAC:
1203 return "Stac";
1204 #endif
1205 #ifdef CI_MPPC
1206 case CI_MPPC:
1207 return "MS-PPC";
1208 #endif
1209 default:
1210 (void) slprintf(result, sizeof(result), "Method %d", opt->method);
1211 }
1212 return result;
1213 }
1214
1215 /*
1216 * CCP has come up - inform the kernel driver and log a message.
1217 */
1218 static void
ccp_up(f)1219 ccp_up(f)
1220 fsm *f;
1221 {
1222 ccp_options *go = &ccp_gotoptions[f->unit];
1223 ccp_options *ho = &ccp_hisoptions[f->unit];
1224 char method1[64];
1225
1226 /*
1227 * We're now open and up (running).
1228 */
1229 ccp_flags_set(f->unit, 1, 1);
1230 if (ANY_COMPRESS(*go)) {
1231 if (ANY_COMPRESS(*ho)) {
1232 if (go->method == ho->method) {
1233 notice("%s compression enabled", method_name(go, ho));
1234 } else {
1235 (void) strlcpy(method1, method_name(go, NULL), sizeof(method1));
1236 notice("%s / %s compression enabled",
1237 method1, method_name(ho, NULL));
1238 }
1239 } else
1240 notice("%s receive decompression enabled", method_name(go, NULL));
1241 } else if (ANY_COMPRESS(*ho))
1242 notice("%s transmit compression enabled", method_name(ho, NULL));
1243 }
1244
1245 /*
1246 * CCP has gone down - inform the kernel driver.
1247 */
1248 static void
ccp_down(f)1249 ccp_down(f)
1250 fsm *f;
1251 {
1252 if (ccp_localstate[f->unit] & RACK_PENDING)
1253 UNTIMEOUT(ccp_rack_timeout, f);
1254 /* Don't forget about peer's code rejects or ignoring of requests. */
1255 ccp_localstate[f->unit] &= ~RACK_PENDING & ~RREQ_REPEAT;
1256 /* We're still open, but no longer up. */
1257 ccp_flags_set(f->unit, 1, 0);
1258 }
1259
1260 static int
ccp_printpkt(p,plen,printer,arg)1261 ccp_printpkt(p, plen, printer, arg)
1262 u_char *p;
1263 int plen;
1264 void (*printer) __P((void *, const char *, ...));
1265 void *arg;
1266 {
1267 u_char *p0, *optend, cichar;
1268 int code, id, len;
1269 int optlen, clen;
1270 u_short cishort;
1271 #ifdef CI_MPPC
1272 u_int32_t cilong;
1273 #endif
1274
1275 p0 = p;
1276 if (plen < HEADERLEN) {
1277 printer(arg, "too short (%d<%d)", plen, HEADERLEN);
1278 return (0);
1279 }
1280 GETCHAR(code, p);
1281 GETCHAR(id, p);
1282 GETSHORT(len, p);
1283
1284 printer(arg, " %s id=0x%x", code_name(code, 1), id);
1285
1286 if (len < HEADERLEN) {
1287 printer(arg, " header length %d<%d", len, HEADERLEN);
1288 return (HEADERLEN);
1289 }
1290 if (len > plen) {
1291 printer(arg, " truncated (%d>%d)", len, plen);
1292 len = plen;
1293 }
1294 len -= HEADERLEN;
1295
1296 switch (code) {
1297 case CODE_CONFREQ:
1298 case CODE_CONFACK:
1299 case CODE_CONFNAK:
1300 case CODE_CONFREJ:
1301 /* print list of possible compression methods */
1302 while (len >= 2) {
1303 GETCHAR(code, p);
1304 GETCHAR(clen, p);
1305 optlen = clen;
1306 printer(arg, " <");
1307 if (optlen > len)
1308 optlen = len;
1309 if (optlen < 2)
1310 optlen = 2;
1311 len -= optlen;
1312 optend = p + optlen - 2;
1313 switch (code) {
1314 case CI_DEFLATE:
1315 case CI_DEFLATE_DRAFT:
1316 printer(arg, "deflate%s",
1317 (code == CI_DEFLATE_DRAFT? "(old#)": ""));
1318 if (clen != CILEN_DEFLATE)
1319 printer(arg, " length %d", clen);
1320 if (optlen >= CILEN_DEFLATE) {
1321 GETCHAR(cichar, p);
1322 printer(arg, " %d", DEFLATE_SIZE(cichar));
1323 if (DEFLATE_METHOD(cichar) != DEFLATE_METHOD_VAL)
1324 printer(arg, " method %d", DEFLATE_METHOD(cichar));
1325 GETCHAR(cichar, p);
1326 if (cichar != DEFLATE_CHK_SEQUENCE)
1327 printer(arg, " check %d", cichar);
1328 }
1329 break;
1330 case CI_BSD_COMPRESS:
1331 printer(arg, "bsd");
1332 if (clen != CILEN_BSD_COMPRESS)
1333 printer(arg, " length %d", clen);
1334 if (optlen >= CILEN_BSD_COMPRESS) {
1335 GETCHAR(cichar, p);
1336 printer(arg, " v%d %d", BSD_VERSION(cichar),
1337 BSD_NBITS(cichar));
1338 }
1339 break;
1340 case CI_PREDICTOR_1:
1341 printer(arg, "predictor-1");
1342 if (clen != CILEN_PREDICTOR_1)
1343 printer(arg, " length %d", clen);
1344 break;
1345 case CI_PREDICTOR_2:
1346 printer(arg, "predictor-2");
1347 if (clen != CILEN_PREDICTOR_2)
1348 printer(arg, " length %d", clen);
1349 break;
1350 #ifdef CI_STAC
1351 case CI_STAC:
1352 printer(arg, "Stac");
1353 if (clen != CILEN_STAC)
1354 printer(arg, " length %d", clen);
1355 if (optlen >= CILEN_STAC) {
1356 GETSHORT(cishort, p);
1357 GETCHAR(cichar, p);
1358 printer(arg, " h%d/m%d", cishort, cichar);
1359 }
1360 break;
1361 #endif
1362 #ifdef CI_MPPC
1363 case CI_MPPC:
1364 /* There appears to be no good generic name for this one. */
1365 if (optlen >= CILEN_MPPC) {
1366 GETLONG(cilong, p);
1367 if (!(cilong & MPPC_COMP)) {
1368 if (cilong & MPPC_MPPE)
1369 printer(arg, "MPPE");
1370 else
1371 printer(arg, "MS-PPC?");
1372 } else {
1373 if (cilong & MPPC_MPPE)
1374 printer(arg, "MPPC+MPPE");
1375 else
1376 printer(arg, "MPPC");
1377 }
1378 } else {
1379 printer(arg, "MS-?");
1380 }
1381 if (clen != CILEN_STAC)
1382 printer(arg, " length %d", clen);
1383 break;
1384 #endif
1385 default:
1386 printer(arg, "typ%d len%d ", code, clen);
1387 break;
1388 }
1389 if (p < optend) {
1390 if (p+8 < optend)
1391 printer(arg, " %.8B ...", p);
1392 else
1393 printer(arg, " %.*B", optend-p, p);
1394 p = optend;
1395 }
1396 printer(arg, ">");
1397 }
1398 break;
1399
1400 case CODE_TERMACK:
1401 case CODE_TERMREQ:
1402 if (len > 0) {
1403 if (len == 2) {
1404 GETSHORT(cishort, p);
1405 printer(arg, " history %d", cishort);
1406 len = 0;
1407 } else if (*p >= ' ' && *p < 0x7f) {
1408 printer(arg, " ");
1409 print_string((char *)p, len, printer, arg);
1410 p += len;
1411 len = 0;
1412 }
1413 }
1414 break;
1415 }
1416
1417 /* dump out the rest of the packet in hex */
1418 if (len > 0) {
1419 if (len > 8)
1420 printer(arg, " %.8B ...", p);
1421 else
1422 printer(arg, " %.*B", len, p);
1423 p += len;
1424 }
1425
1426 return p - p0;
1427 }
1428
1429 /*
1430 * We have received a packet that the decompressor failed to
1431 * decompress. Here we would expect to issue a reset-request, but
1432 * Motorola has a patent on resetting the compressor as a result of
1433 * detecting an error in the decompressed data after decompression.
1434 * (See US patent 5,130,993; international patent publication number
1435 * WO 91/10289; Australian patent 73296/91.)
1436 *
1437 * So we ask the kernel whether the error was detected after
1438 * decompression; if it was, we take CCP down, thus disabling
1439 * compression :-(, otherwise we issue the reset-request.
1440 */
1441 /*ARGSUSED*/
1442 static void
ccp_datainput(unit,pkt,len)1443 ccp_datainput(unit, pkt, len)
1444 int unit;
1445 u_char *pkt;
1446 int len;
1447 {
1448 fsm *f;
1449
1450 f = &ccp_fsm[unit];
1451 if (f->state == OPENED) {
1452 if (ccp_fatal_error(unit)) {
1453 /*
1454 * Disable compression by taking CCP down.
1455 */
1456 error("Lost compression sync: disabling compression");
1457 ccp_close(unit, "Lost compression sync");
1458 } else {
1459 /*
1460 * Send a reset-request to reset the peer's compressor, if
1461 * possible. We don't do anything if we are still waiting
1462 * for an acknowledgement to a previous reset-request (to
1463 * avoid flooding the peer). We reopen CCP if the peer
1464 * doesn't like hearing about CCP Reset-Request (Cisco
1465 * sends CCP Code-Reject for Reset-Request). (Reopen
1466 * automatically clears the flags and cancels the
1467 * timeout.)
1468 */
1469 if (ccp_localstate[f->unit] & RREQ_REJECTED) {
1470 dbglog("reopening CCP to reset peer's compressor");
1471 ccp_open(f->unit);
1472 } else if (ccp_localstate[f->unit] & RACK_PENDING) {
1473 /* Send another reset request; we're out of sequence. */
1474 ccp_localstate[f->unit] |= RREQ_REPEAT;
1475 } else {
1476 dbglog("sending CCP Reset-Request to reset peer's compressor");
1477 fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0);
1478 TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT);
1479 ccp_localstate[f->unit] |= RACK_PENDING;
1480 }
1481 }
1482 }
1483 }
1484
1485 /*
1486 * Timeout waiting for reset-ack.
1487 */
1488 static void
ccp_rack_timeout(arg)1489 ccp_rack_timeout(arg)
1490 void *arg;
1491 {
1492 fsm *f = arg;
1493
1494 /* Timeout; no longer pending. */
1495 ccp_localstate[f->unit] &= ~RACK_PENDING;
1496
1497 /* Frankly, it's a coding flaw if this occurs. */
1498 if (f->state != OPENED)
1499 return;
1500
1501 if (ccp_localstate[f->unit] & RREQ_IGNORED) {
1502 info("peer ignored our CCP Reset-Request twice; reopen instead");
1503 ccp_localstate[f->unit] =
1504 (ccp_localstate[f->unit] & ~RREQ_IGNORED) | RREQ_REJECTED;
1505 ccp_open(f->unit);
1506 } else if (ccp_localstate[f->unit] & RREQ_REPEAT) {
1507 dbglog("sending another CCP Reset-Request on timeout");
1508 fsm_sdata(f, CCP_RESETREQ, f->reqid, NULL, 0);
1509 TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT);
1510 ccp_localstate[f->unit] =
1511 (ccp_localstate[f->unit] & ~RREQ_REPEAT) | RREQ_IGNORED |
1512 RACK_PENDING;
1513 } else {
1514 dbglog("timeout waiting for CCP Reset-Ack; hope for the best");
1515 ccp_localstate[f->unit] |= RREQ_IGNORED;
1516 }
1517 }
1518