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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 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 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 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 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 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