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