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