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