1/* 2 * ccp.c - PPP Compression Control Protocol. 3 * 4 * Copyright (c) 1994 The Australian National University. 5 * All rights reserved. 6 * 7 * Permission to use, copy, modify, and distribute this software and its 8 * documentation is hereby granted, provided that the above copyright 9 * notice appears in all copies. This software is provided without any 10 * warranty, express or implied. The Australian National University 11 * makes no representations about the suitability of this software for 12 * any purpose. 13 * 14 * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY 15 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 16 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 17 * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY 18 * OF SUCH DAMAGE. 19 * 20 * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, 21 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 22 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 23 * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO 24 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, 25 * OR MODIFICATIONS. 26 */ 27 28#define RCSID "$Id: ccp.c,v 1.1.1.1 2008/10/15 03:30:12 james26_jang Exp $" 29 30#include <stdlib.h> 31#include <string.h> 32 33#include <pppd.h> 34#include "fsm.h" 35#include "ccp.h" 36#include <net/ppp-comp.h> 37 38static const char rcsid[] = RCSID; 39 40/* 41 * Unfortunately there is a bug in zlib which means that using a 42 * size of 8 (window size = 256) for Deflate compression will cause 43 * buffer overruns and kernel crashes in the deflate module. 44 * Until this is fixed we only accept sizes in the range 9 .. 15. 45 * Thanks to James Carlson for pointing this out. 46 */ 47#define DEFLATE_MIN_WORKS 9 48 49/* 50 * Command-line options. 51 */ 52static int setbsdcomp __P((char **)); 53static int setdeflate __P((char **)); 54static char bsd_value[8]; 55static char deflate_value[8]; 56 57static option_t ccp_option_list[] = { 58 { "noccp", o_bool, &ccp_protent.enabled_flag, 59 "Disable CCP negotiation" }, 60 { "-ccp", o_bool, &ccp_protent.enabled_flag, 61 "Disable CCP negotiation", OPT_ALIAS }, 62 63 { "bsdcomp", o_special, (void *)setbsdcomp, 64 "Request BSD-Compress packet compression", 65 OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, bsd_value }, 66 { "nobsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress, 67 "don't allow BSD-Compress", OPT_PRIOSUB | OPT_A2CLR, 68 &ccp_allowoptions[0].bsd_compress }, 69 { "-bsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress, 70 "don't allow BSD-Compress", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, 71 &ccp_allowoptions[0].bsd_compress }, 72 73 { "deflate", o_special, (void *)setdeflate, 74 "request Deflate compression", 75 OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, deflate_value }, 76 { "nodeflate", o_bool, &ccp_wantoptions[0].deflate, 77 "don't allow Deflate compression", OPT_PRIOSUB | OPT_A2CLR, 78 &ccp_allowoptions[0].deflate }, 79 { "-deflate", o_bool, &ccp_wantoptions[0].deflate, 80 "don't allow Deflate compression", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, 81 &ccp_allowoptions[0].deflate }, 82 83 { "nodeflatedraft", o_bool, &ccp_wantoptions[0].deflate_draft, 84 "don't use draft deflate #", OPT_A2COPY, 85 &ccp_allowoptions[0].deflate_draft }, 86 87 { "predictor1", o_bool, &ccp_wantoptions[0].predictor_1, 88 "request Predictor-1", 1, &ccp_allowoptions[0].predictor_1, OPT_PRIO }, 89 { "nopredictor1", o_bool, &ccp_wantoptions[0].predictor_1, 90 "don't allow Predictor-1", OPT_PRIOSUB | OPT_A2CLR, 91 &ccp_allowoptions[0].predictor_1 }, 92 { "-predictor1", o_bool, &ccp_wantoptions[0].predictor_1, 93 "don't allow Predictor-1", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, 94 &ccp_allowoptions[0].predictor_1 }, 95 96 { NULL } 97}; 98 99/* 100 * Protocol entry points from main code. 101 */ 102static void ccp_init __P((int unit)); 103static void ccp_open __P((int unit)); 104static void ccp_close __P((int unit, char *)); 105static void ccp_lowerup __P((int unit)); 106static void ccp_lowerdown __P((int)); 107static void ccp_input __P((int unit, u_char *pkt, int len)); 108static void ccp_protrej __P((int unit)); 109static int ccp_printpkt __P((u_char *pkt, int len, 110 void (*printer) __P((void *, char *, ...)), 111 void *arg)); 112static void ccp_datainput __P((int unit, u_char *pkt, int len)); 113 114struct protent ccp_protent = { 115 PPP_CCP, 116 ccp_init, 117 ccp_input, 118 ccp_protrej, 119 ccp_lowerup, 120 ccp_lowerdown, 121 ccp_open, 122 ccp_close, 123 ccp_printpkt, 124 ccp_datainput, 125 1, 126 "CCP", 127 "Compressed", 128 ccp_option_list, 129 NULL, 130 NULL, 131 NULL 132}; 133 134fsm ccp_fsm[NUM_PPP]; 135ccp_options ccp_wantoptions[NUM_PPP]; /* what to request the peer to use */ 136ccp_options ccp_gotoptions[NUM_PPP]; /* what the peer agreed to do */ 137ccp_options ccp_allowoptions[NUM_PPP]; /* what we'll agree to do */ 138ccp_options ccp_hisoptions[NUM_PPP]; /* what we agreed to do */ 139 140/* 141 * Callbacks for fsm code. 142 */ 143static void ccp_resetci __P((fsm *)); 144static int ccp_cilen __P((fsm *)); 145static void ccp_addci __P((fsm *, u_char *, int *)); 146static int ccp_ackci __P((fsm *, u_char *, int)); 147static int ccp_nakci __P((fsm *, u_char *, int)); 148static int ccp_rejci __P((fsm *, u_char *, int)); 149static int ccp_reqci __P((fsm *, u_char *, int *, int)); 150static void ccp_up __P((fsm *)); 151static void ccp_down __P((fsm *)); 152static int ccp_extcode __P((fsm *, int, int, u_char *, int)); 153static void ccp_rack_timeout __P((void *)); 154static char *method_name __P((ccp_options *, ccp_options *)); 155 156static fsm_callbacks ccp_callbacks = { 157 ccp_resetci, 158 ccp_cilen, 159 ccp_addci, 160 ccp_ackci, 161 ccp_nakci, 162 ccp_rejci, 163 ccp_reqci, 164 ccp_up, 165 ccp_down, 166 NULL, 167 NULL, 168 NULL, 169 NULL, 170 ccp_extcode, 171 "CCP" 172}; 173 174/* 175 * Do we want / did we get any compression? 176 */ 177#define ANY_COMPRESS(opt) ((opt).deflate || (opt).bsd_compress \ 178 || (opt).predictor_1 || (opt).predictor_2) 179 180/* 181 * Local state (mainly for handling reset-reqs and reset-acks). 182 */ 183static int ccp_localstate[NUM_PPP]; 184#define RACK_PENDING 1 /* waiting for reset-ack */ 185#define RREQ_REPEAT 2 /* send another reset-req if no reset-ack */ 186 187#define RACKTIMEOUT 1 /* second */ 188 189static int all_rejected[NUM_PPP]; /* we rejected all peer's options */ 190 191/* 192 * Option parsing. 193 */ 194static int 195setbsdcomp(argv) 196 char **argv; 197{ 198 int rbits, abits; 199 char *str, *endp; 200 201 str = *argv; 202 abits = rbits = strtol(str, &endp, 0); 203 if (endp != str && *endp == ',') { 204 str = endp + 1; 205 abits = strtol(str, &endp, 0); 206 } 207 if (*endp != 0 || endp == str) { 208 option_error("invalid parameter '%s' for bsdcomp option", *argv); 209 return 0; 210 } 211 if ((rbits != 0 && (rbits < BSD_MIN_BITS || rbits > BSD_MAX_BITS)) 212 || (abits != 0 && (abits < BSD_MIN_BITS || abits > BSD_MAX_BITS))) { 213 option_error("bsdcomp option values must be 0 or %d .. %d", 214 BSD_MIN_BITS, BSD_MAX_BITS); 215 return 0; 216 } 217 if (rbits > 0) { 218 ccp_wantoptions[0].bsd_compress = 1; 219 ccp_wantoptions[0].bsd_bits = rbits; 220 } else 221 ccp_wantoptions[0].bsd_compress = 0; 222 if (abits > 0) { 223 ccp_allowoptions[0].bsd_compress = 1; 224 ccp_allowoptions[0].bsd_bits = abits; 225 } else 226 ccp_allowoptions[0].bsd_compress = 0; 227 slprintf(bsd_value, sizeof(bsd_value), 228 rbits == abits? "%d": "%d,%d", rbits, abits); 229 230 return 1; 231} 232 233static int 234setdeflate(argv) 235 char **argv; 236{ 237 int rbits, abits; 238 char *str, *endp; 239 240 str = *argv; 241 abits = rbits = strtol(str, &endp, 0); 242 if (endp != str && *endp == ',') { 243 str = endp + 1; 244 abits = strtol(str, &endp, 0); 245 } 246 if (*endp != 0 || endp == str) { 247 option_error("invalid parameter '%s' for deflate option", *argv); 248 return 0; 249 } 250 if ((rbits != 0 && (rbits < DEFLATE_MIN_SIZE || rbits > DEFLATE_MAX_SIZE)) 251 || (abits != 0 && (abits < DEFLATE_MIN_SIZE 252 || abits > DEFLATE_MAX_SIZE))) { 253 option_error("deflate option values must be 0 or %d .. %d", 254 DEFLATE_MIN_SIZE, DEFLATE_MAX_SIZE); 255 return 0; 256 } 257 if (rbits == DEFLATE_MIN_SIZE || abits == DEFLATE_MIN_SIZE) { 258 if (rbits == DEFLATE_MIN_SIZE) 259 rbits = DEFLATE_MIN_WORKS; 260 if (abits == DEFLATE_MIN_SIZE) 261 abits = DEFLATE_MIN_WORKS; 262 warn("deflate option value of %d changed to %d to avoid zlib bug", 263 DEFLATE_MIN_SIZE, DEFLATE_MIN_WORKS); 264 } 265 if (rbits > 0) { 266 ccp_wantoptions[0].deflate = 1; 267 ccp_wantoptions[0].deflate_size = rbits; 268 } else 269 ccp_wantoptions[0].deflate = 0; 270 if (abits > 0) { 271 ccp_allowoptions[0].deflate = 1; 272 ccp_allowoptions[0].deflate_size = abits; 273 } else 274 ccp_allowoptions[0].deflate = 0; 275 slprintf(deflate_value, sizeof(deflate_value), 276 rbits == abits? "%d": "%d,%d", rbits, abits); 277 278 return 1; 279} 280 281/* 282 * ccp_init - initialize CCP. 283 */ 284static void 285ccp_init(unit) 286 int unit; 287{ 288 fsm *f = &ccp_fsm[unit]; 289 290 f->unit = unit; 291 f->protocol = PPP_CCP; 292 f->callbacks = &ccp_callbacks; 293 fsm_init(f); 294 295 memset(&ccp_wantoptions[unit], 0, sizeof(ccp_options)); 296 memset(&ccp_gotoptions[unit], 0, sizeof(ccp_options)); 297 memset(&ccp_allowoptions[unit], 0, sizeof(ccp_options)); 298 memset(&ccp_hisoptions[unit], 0, sizeof(ccp_options)); 299 300 ccp_wantoptions[0].deflate = 1; 301 ccp_wantoptions[0].deflate_size = DEFLATE_MAX_SIZE; 302 ccp_wantoptions[0].deflate_correct = 1; 303 ccp_wantoptions[0].deflate_draft = 1; 304 ccp_allowoptions[0].deflate = 1; 305 ccp_allowoptions[0].deflate_size = DEFLATE_MAX_SIZE; 306 ccp_allowoptions[0].deflate_correct = 1; 307 ccp_allowoptions[0].deflate_draft = 1; 308 309 ccp_wantoptions[0].bsd_compress = 1; 310 ccp_wantoptions[0].bsd_bits = BSD_MAX_BITS; 311 ccp_allowoptions[0].bsd_compress = 1; 312 ccp_allowoptions[0].bsd_bits = BSD_MAX_BITS; 313 314 ccp_allowoptions[0].predictor_1 = 1; 315} 316 317/* 318 * ccp_open - CCP is allowed to come up. 319 */ 320static void 321ccp_open(unit) 322 int unit; 323{ 324 fsm *f = &ccp_fsm[unit]; 325 326 if (f->state != OPENED) 327 ccp_flags_set(unit, 1, 0); 328 329 /* 330 * Find out which compressors the kernel supports before 331 * deciding whether to open in silent mode. 332 */ 333 ccp_resetci(f); 334 if (!ANY_COMPRESS(ccp_gotoptions[unit])) 335 f->flags |= OPT_SILENT; 336 337 fsm_open(f); 338} 339 340/* 341 * ccp_close - Terminate CCP. 342 */ 343static void 344ccp_close(unit, reason) 345 int unit; 346 char *reason; 347{ 348 ccp_flags_set(unit, 0, 0); 349 fsm_close(&ccp_fsm[unit], reason); 350} 351 352/* 353 * ccp_lowerup - we may now transmit CCP packets. 354 */ 355static void 356ccp_lowerup(unit) 357 int unit; 358{ 359 fsm_lowerup(&ccp_fsm[unit]); 360} 361 362/* 363 * ccp_lowerdown - we may not transmit CCP packets. 364 */ 365static void 366ccp_lowerdown(unit) 367 int unit; 368{ 369 fsm_lowerdown(&ccp_fsm[unit]); 370} 371 372/* 373 * ccp_input - process a received CCP packet. 374 */ 375static void 376ccp_input(unit, p, len) 377 int unit; 378 u_char *p; 379 int len; 380{ 381 fsm *f = &ccp_fsm[unit]; 382 int oldstate; 383 384 /* 385 * Check for a terminate-request so we can print a message. 386 */ 387 oldstate = f->state; 388 fsm_input(f, p, len); 389 if (oldstate == OPENED && p[0] == TERMREQ && f->state != OPENED) 390 notice("Compression disabled by peer."); 391 392 /* 393 * If we get a terminate-ack and we're not asking for compression, 394 * close CCP. 395 */ 396 if (oldstate == REQSENT && p[0] == TERMACK 397 && !ANY_COMPRESS(ccp_gotoptions[unit])) 398 ccp_close(unit, "No compression negotiated"); 399} 400 401/* 402 * Handle a CCP-specific code. 403 */ 404static int 405ccp_extcode(f, code, id, p, len) 406 fsm *f; 407 int code, id; 408 u_char *p; 409 int len; 410{ 411 switch (code) { 412 case CCP_RESETREQ: 413 if (f->state != OPENED) 414 break; 415 /* send a reset-ack, which the transmitter will see and 416 reset its compression state. */ 417 fsm_sdata(f, CCP_RESETACK, id, NULL, 0); 418 break; 419 420 case CCP_RESETACK: 421 if (ccp_localstate[f->unit] & RACK_PENDING && id == f->reqid) { 422 ccp_localstate[f->unit] &= ~(RACK_PENDING | RREQ_REPEAT); 423 UNTIMEOUT(ccp_rack_timeout, f); 424 } 425 break; 426 427 default: 428 return 0; 429 } 430 431 return 1; 432} 433 434/* 435 * ccp_protrej - peer doesn't talk CCP. 436 */ 437static void 438ccp_protrej(unit) 439 int unit; 440{ 441 ccp_flags_set(unit, 0, 0); 442 fsm_lowerdown(&ccp_fsm[unit]); 443} 444 445/* 446 * ccp_resetci - initialize at start of negotiation. 447 */ 448static void 449ccp_resetci(f) 450 fsm *f; 451{ 452 ccp_options *go = &ccp_gotoptions[f->unit]; 453 u_char opt_buf[16]; 454 455 *go = ccp_wantoptions[f->unit]; 456 all_rejected[f->unit] = 0; 457 458 /* 459 * Check whether the kernel knows about the various 460 * compression methods we might request. 461 */ 462 if (go->bsd_compress) { 463 opt_buf[0] = CI_BSD_COMPRESS; 464 opt_buf[1] = CILEN_BSD_COMPRESS; 465 opt_buf[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, BSD_MIN_BITS); 466 if (ccp_test(f->unit, opt_buf, CILEN_BSD_COMPRESS, 0) <= 0) 467 go->bsd_compress = 0; 468 } 469 if (go->deflate) { 470 if (go->deflate_correct) { 471 opt_buf[0] = CI_DEFLATE; 472 opt_buf[1] = CILEN_DEFLATE; 473 opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_WORKS); 474 opt_buf[3] = DEFLATE_CHK_SEQUENCE; 475 if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0) 476 go->deflate_correct = 0; 477 } 478 if (go->deflate_draft) { 479 opt_buf[0] = CI_DEFLATE_DRAFT; 480 opt_buf[1] = CILEN_DEFLATE; 481 opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_WORKS); 482 opt_buf[3] = DEFLATE_CHK_SEQUENCE; 483 if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0) 484 go->deflate_draft = 0; 485 } 486 if (!go->deflate_correct && !go->deflate_draft) 487 go->deflate = 0; 488 } 489 if (go->predictor_1) { 490 opt_buf[0] = CI_PREDICTOR_1; 491 opt_buf[1] = CILEN_PREDICTOR_1; 492 if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_1, 0) <= 0) 493 go->predictor_1 = 0; 494 } 495 if (go->predictor_2) { 496 opt_buf[0] = CI_PREDICTOR_2; 497 opt_buf[1] = CILEN_PREDICTOR_2; 498 if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_2, 0) <= 0) 499 go->predictor_2 = 0; 500 } 501} 502 503/* 504 * ccp_cilen - Return total length of our configuration info. 505 */ 506static int 507ccp_cilen(f) 508 fsm *f; 509{ 510 ccp_options *go = &ccp_gotoptions[f->unit]; 511 512 return (go->bsd_compress? CILEN_BSD_COMPRESS: 0) 513 + (go->deflate? CILEN_DEFLATE: 0) 514 + (go->predictor_1? CILEN_PREDICTOR_1: 0) 515 + (go->predictor_2? CILEN_PREDICTOR_2: 0); 516} 517 518/* 519 * ccp_addci - put our requests in a packet. 520 */ 521static void 522ccp_addci(f, p, lenp) 523 fsm *f; 524 u_char *p; 525 int *lenp; 526{ 527 int res; 528 ccp_options *go = &ccp_gotoptions[f->unit]; 529 u_char *p0 = p; 530 531 /* 532 * Add the compression types that we can receive, in decreasing 533 * preference order. Get the kernel to allocate the first one 534 * in case it gets Acked. 535 */ 536 if (go->deflate) { 537 p[0] = go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT; 538 p[1] = CILEN_DEFLATE; 539 p[2] = DEFLATE_MAKE_OPT(go->deflate_size); 540 p[3] = DEFLATE_CHK_SEQUENCE; 541 for (;;) { 542 res = ccp_test(f->unit, p, CILEN_DEFLATE, 0); 543 if (res > 0) { 544 p += CILEN_DEFLATE; 545 break; 546 } 547 if (res < 0 || go->deflate_size <= DEFLATE_MIN_WORKS) { 548 go->deflate = 0; 549 break; 550 } 551 --go->deflate_size; 552 p[2] = DEFLATE_MAKE_OPT(go->deflate_size); 553 } 554 if (p != p0 && go->deflate_correct && go->deflate_draft) { 555 p[0] = CI_DEFLATE_DRAFT; 556 p[1] = CILEN_DEFLATE; 557 p[2] = p[2 - CILEN_DEFLATE]; 558 p[3] = DEFLATE_CHK_SEQUENCE; 559 p += CILEN_DEFLATE; 560 } 561 } 562 if (go->bsd_compress) { 563 p[0] = CI_BSD_COMPRESS; 564 p[1] = CILEN_BSD_COMPRESS; 565 p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits); 566 if (p != p0) { 567 p += CILEN_BSD_COMPRESS; /* not the first option */ 568 } else { 569 for (;;) { 570 res = ccp_test(f->unit, p, CILEN_BSD_COMPRESS, 0); 571 if (res > 0) { 572 p += CILEN_BSD_COMPRESS; 573 break; 574 } 575 if (res < 0 || go->bsd_bits <= BSD_MIN_BITS) { 576 go->bsd_compress = 0; 577 break; 578 } 579 --go->bsd_bits; 580 p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits); 581 } 582 } 583 } 584 if (go->predictor_1) { 585 p[0] = CI_PREDICTOR_1; 586 p[1] = CILEN_PREDICTOR_1; 587 if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_1, 0) <= 0) { 588 go->predictor_1 = 0; 589 } else { 590 p += CILEN_PREDICTOR_1; 591 } 592 } 593 if (go->predictor_2) { 594 p[0] = CI_PREDICTOR_2; 595 p[1] = CILEN_PREDICTOR_2; 596 if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_2, 0) <= 0) { 597 go->predictor_2 = 0; 598 } else { 599 p += CILEN_PREDICTOR_2; 600 } 601 } 602 603 go->method = (p > p0)? p0[0]: -1; 604 605 *lenp = p - p0; 606} 607 608/* 609 * ccp_ackci - process a received configure-ack, and return 610 * 1 iff the packet was OK. 611 */ 612static int 613ccp_ackci(f, p, len) 614 fsm *f; 615 u_char *p; 616 int len; 617{ 618 ccp_options *go = &ccp_gotoptions[f->unit]; 619 u_char *p0 = p; 620 621 if (go->deflate) { 622 if (len < CILEN_DEFLATE 623 || p[0] != (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT) 624 || p[1] != CILEN_DEFLATE 625 || p[2] != DEFLATE_MAKE_OPT(go->deflate_size) 626 || p[3] != DEFLATE_CHK_SEQUENCE) 627 return 0; 628 p += CILEN_DEFLATE; 629 len -= CILEN_DEFLATE; 630 if (len == 0) 631 return 1; 632 if (go->deflate_correct && go->deflate_draft) { 633 if (len < CILEN_DEFLATE 634 || p[0] != CI_DEFLATE_DRAFT 635 || p[1] != CILEN_DEFLATE 636 || p[2] != DEFLATE_MAKE_OPT(go->deflate_size) 637 || p[3] != DEFLATE_CHK_SEQUENCE) 638 return 0; 639 p += CILEN_DEFLATE; 640 len -= CILEN_DEFLATE; 641 } 642 } 643 if (go->bsd_compress) { 644 if (len < CILEN_BSD_COMPRESS 645 || p[0] != CI_BSD_COMPRESS || p[1] != CILEN_BSD_COMPRESS 646 || p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits)) 647 return 0; 648 p += CILEN_BSD_COMPRESS; 649 len -= CILEN_BSD_COMPRESS; 650 if (p == p0 && len == 0) 651 return 1; 652 } 653 if (go->predictor_1) { 654 if (len < CILEN_PREDICTOR_1 655 || p[0] != CI_PREDICTOR_1 || p[1] != CILEN_PREDICTOR_1) 656 return 0; 657 p += CILEN_PREDICTOR_1; 658 len -= CILEN_PREDICTOR_1; 659 if (p == p0 && len == 0) 660 return 1; 661 } 662 if (go->predictor_2) { 663 if (len < CILEN_PREDICTOR_2 664 || p[0] != CI_PREDICTOR_2 || p[1] != CILEN_PREDICTOR_2) 665 return 0; 666 p += CILEN_PREDICTOR_2; 667 len -= CILEN_PREDICTOR_2; 668 if (p == p0 && len == 0) 669 return 1; 670 } 671 672 if (len != 0) 673 return 0; 674 return 1; 675} 676 677/* 678 * ccp_nakci - process received configure-nak. 679 * Returns 1 iff the nak was OK. 680 */ 681static int 682ccp_nakci(f, p, len) 683 fsm *f; 684 u_char *p; 685 int len; 686{ 687 ccp_options *go = &ccp_gotoptions[f->unit]; 688 ccp_options no; /* options we've seen already */ 689 ccp_options try; /* options to ask for next time */ 690 691 memset(&no, 0, sizeof(no)); 692 try = *go; 693 694 if (go->deflate && len >= CILEN_DEFLATE 695 && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT) 696 && p[1] == CILEN_DEFLATE) { 697 no.deflate = 1; 698 /* 699 * Peer wants us to use a different code size or something. 700 * Stop asking for Deflate if we don't understand his suggestion. 701 */ 702 if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL 703 || DEFLATE_SIZE(p[2]) < DEFLATE_MIN_WORKS 704 || p[3] != DEFLATE_CHK_SEQUENCE) 705 try.deflate = 0; 706 else if (DEFLATE_SIZE(p[2]) < go->deflate_size) 707 try.deflate_size = DEFLATE_SIZE(p[2]); 708 p += CILEN_DEFLATE; 709 len -= CILEN_DEFLATE; 710 if (go->deflate_correct && go->deflate_draft 711 && len >= CILEN_DEFLATE && p[0] == CI_DEFLATE_DRAFT 712 && p[1] == CILEN_DEFLATE) { 713 p += CILEN_DEFLATE; 714 len -= CILEN_DEFLATE; 715 } 716 } 717 718 if (go->bsd_compress && len >= CILEN_BSD_COMPRESS 719 && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) { 720 no.bsd_compress = 1; 721 /* 722 * Peer wants us to use a different number of bits 723 * or a different version. 724 */ 725 if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION) 726 try.bsd_compress = 0; 727 else if (BSD_NBITS(p[2]) < go->bsd_bits) 728 try.bsd_bits = BSD_NBITS(p[2]); 729 p += CILEN_BSD_COMPRESS; 730 len -= CILEN_BSD_COMPRESS; 731 } 732 733 /* 734 * Predictor-1 and 2 have no options, so they can't be Naked. 735 * 736 * There may be remaining options but we ignore them. 737 */ 738 739 if (f->state != OPENED) 740 *go = try; 741 return 1; 742} 743 744/* 745 * ccp_rejci - reject some of our suggested compression methods. 746 */ 747static int 748ccp_rejci(f, p, len) 749 fsm *f; 750 u_char *p; 751 int len; 752{ 753 ccp_options *go = &ccp_gotoptions[f->unit]; 754 ccp_options try; /* options to request next time */ 755 756 try = *go; 757 758 /* 759 * Cope with empty configure-rejects by ceasing to send 760 * configure-requests. 761 */ 762 if (len == 0 && all_rejected[f->unit]) 763 return -1; 764 765 if (go->deflate && len >= CILEN_DEFLATE 766 && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT) 767 && p[1] == CILEN_DEFLATE) { 768 if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size) 769 || p[3] != DEFLATE_CHK_SEQUENCE) 770 return 0; /* Rej is bad */ 771 if (go->deflate_correct) 772 try.deflate_correct = 0; 773 else 774 try.deflate_draft = 0; 775 p += CILEN_DEFLATE; 776 len -= CILEN_DEFLATE; 777 if (go->deflate_correct && go->deflate_draft 778 && len >= CILEN_DEFLATE && p[0] == CI_DEFLATE_DRAFT 779 && p[1] == CILEN_DEFLATE) { 780 if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size) 781 || p[3] != DEFLATE_CHK_SEQUENCE) 782 return 0; /* Rej is bad */ 783 try.deflate_draft = 0; 784 p += CILEN_DEFLATE; 785 len -= CILEN_DEFLATE; 786 } 787 if (!try.deflate_correct && !try.deflate_draft) 788 try.deflate = 0; 789 } 790 if (go->bsd_compress && len >= CILEN_BSD_COMPRESS 791 && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) { 792 if (p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits)) 793 return 0; 794 try.bsd_compress = 0; 795 p += CILEN_BSD_COMPRESS; 796 len -= CILEN_BSD_COMPRESS; 797 } 798 if (go->predictor_1 && len >= CILEN_PREDICTOR_1 799 && p[0] == CI_PREDICTOR_1 && p[1] == CILEN_PREDICTOR_1) { 800 try.predictor_1 = 0; 801 p += CILEN_PREDICTOR_1; 802 len -= CILEN_PREDICTOR_1; 803 } 804 if (go->predictor_2 && len >= CILEN_PREDICTOR_2 805 && p[0] == CI_PREDICTOR_2 && p[1] == CILEN_PREDICTOR_2) { 806 try.predictor_2 = 0; 807 p += CILEN_PREDICTOR_2; 808 len -= CILEN_PREDICTOR_2; 809 } 810 811 if (len != 0) 812 return 0; 813 814 if (f->state != OPENED) 815 *go = try; 816 817 return 1; 818} 819 820/* 821 * ccp_reqci - processed a received configure-request. 822 * Returns CONFACK, CONFNAK or CONFREJ and the packet modified 823 * appropriately. 824 */ 825static int 826ccp_reqci(f, p, lenp, dont_nak) 827 fsm *f; 828 u_char *p; 829 int *lenp; 830 int dont_nak; 831{ 832 int ret, newret, res; 833 u_char *p0, *retp; 834 int len, clen, type, nb; 835 ccp_options *ho = &ccp_hisoptions[f->unit]; 836 ccp_options *ao = &ccp_allowoptions[f->unit]; 837 838 ret = CONFACK; 839 retp = p0 = p; 840 len = *lenp; 841 842 memset(ho, 0, sizeof(ccp_options)); 843 ho->method = (len > 0)? p[0]: -1; 844 845 while (len > 0) { 846 newret = CONFACK; 847 if (len < 2 || p[1] < 2 || p[1] > len) { 848 /* length is bad */ 849 clen = len; 850 newret = CONFREJ; 851 852 } else { 853 type = p[0]; 854 clen = p[1]; 855 856 switch (type) { 857 case CI_DEFLATE: 858 case CI_DEFLATE_DRAFT: 859 if (!ao->deflate || clen != CILEN_DEFLATE 860 || (!ao->deflate_correct && type == CI_DEFLATE) 861 || (!ao->deflate_draft && type == CI_DEFLATE_DRAFT)) { 862 newret = CONFREJ; 863 break; 864 } 865 866 ho->deflate = 1; 867 ho->deflate_size = nb = DEFLATE_SIZE(p[2]); 868 if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL 869 || p[3] != DEFLATE_CHK_SEQUENCE 870 || nb > ao->deflate_size || nb < DEFLATE_MIN_WORKS) { 871 newret = CONFNAK; 872 if (!dont_nak) { 873 p[2] = DEFLATE_MAKE_OPT(ao->deflate_size); 874 p[3] = DEFLATE_CHK_SEQUENCE; 875 /* fall through to test this #bits below */ 876 } else 877 break; 878 } 879 880 /* 881 * Check whether we can do Deflate with the window 882 * size they want. If the window is too big, reduce 883 * it until the kernel can cope and nak with that. 884 * We only check this for the first option. 885 */ 886 if (p == p0) { 887 for (;;) { 888 res = ccp_test(f->unit, p, CILEN_DEFLATE, 1); 889 if (res > 0) 890 break; /* it's OK now */ 891 if (res < 0 || nb == DEFLATE_MIN_WORKS || dont_nak) { 892 newret = CONFREJ; 893 p[2] = DEFLATE_MAKE_OPT(ho->deflate_size); 894 break; 895 } 896 newret = CONFNAK; 897 --nb; 898 p[2] = DEFLATE_MAKE_OPT(nb); 899 } 900 } 901 break; 902 903 case CI_BSD_COMPRESS: 904 if (!ao->bsd_compress || clen != CILEN_BSD_COMPRESS) { 905 newret = CONFREJ; 906 break; 907 } 908 909 ho->bsd_compress = 1; 910 ho->bsd_bits = nb = BSD_NBITS(p[2]); 911 if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION 912 || nb > ao->bsd_bits || nb < BSD_MIN_BITS) { 913 newret = CONFNAK; 914 if (!dont_nak) { 915 p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, ao->bsd_bits); 916 /* fall through to test this #bits below */ 917 } else 918 break; 919 } 920 921 /* 922 * Check whether we can do BSD-Compress with the code 923 * size they want. If the code size is too big, reduce 924 * it until the kernel can cope and nak with that. 925 * We only check this for the first option. 926 */ 927 if (p == p0) { 928 for (;;) { 929 res = ccp_test(f->unit, p, CILEN_BSD_COMPRESS, 1); 930 if (res > 0) 931 break; 932 if (res < 0 || nb == BSD_MIN_BITS || dont_nak) { 933 newret = CONFREJ; 934 p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, 935 ho->bsd_bits); 936 break; 937 } 938 newret = CONFNAK; 939 --nb; 940 p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, nb); 941 } 942 } 943 break; 944 945 case CI_PREDICTOR_1: 946 if (!ao->predictor_1 || clen != CILEN_PREDICTOR_1) { 947 newret = CONFREJ; 948 break; 949 } 950 951 ho->predictor_1 = 1; 952 if (p == p0 953 && ccp_test(f->unit, p, CILEN_PREDICTOR_1, 1) <= 0) { 954 newret = CONFREJ; 955 } 956 break; 957 958 case CI_PREDICTOR_2: 959 if (!ao->predictor_2 || clen != CILEN_PREDICTOR_2) { 960 newret = CONFREJ; 961 break; 962 } 963 964 ho->predictor_2 = 1; 965 if (p == p0 966 && ccp_test(f->unit, p, CILEN_PREDICTOR_2, 1) <= 0) { 967 newret = CONFREJ; 968 } 969 break; 970 971 default: 972 newret = CONFREJ; 973 } 974 } 975 976 if (newret == CONFNAK && dont_nak) 977 newret = CONFREJ; 978 if (!(newret == CONFACK || (newret == CONFNAK && ret == CONFREJ))) { 979 /* we're returning this option */ 980 if (newret == CONFREJ && ret == CONFNAK) 981 retp = p0; 982 ret = newret; 983 if (p != retp) 984 BCOPY(p, retp, clen); 985 retp += clen; 986 } 987 988 p += clen; 989 len -= clen; 990 } 991 992 if (ret != CONFACK) { 993 if (ret == CONFREJ && *lenp == retp - p0) 994 all_rejected[f->unit] = 1; 995 else 996 *lenp = retp - p0; 997 } 998 return ret; 999} 1000 1001/* 1002 * Make a string name for a compression method (or 2). 1003 */ 1004static char * 1005method_name(opt, opt2) 1006 ccp_options *opt, *opt2; 1007{ 1008 static char result[64]; 1009 1010 if (!ANY_COMPRESS(*opt)) 1011 return "(none)"; 1012 switch (opt->method) { 1013 case CI_DEFLATE: 1014 case CI_DEFLATE_DRAFT: 1015 if (opt2 != NULL && opt2->deflate_size != opt->deflate_size) 1016 slprintf(result, sizeof(result), "Deflate%s (%d/%d)", 1017 (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""), 1018 opt->deflate_size, opt2->deflate_size); 1019 else 1020 slprintf(result, sizeof(result), "Deflate%s (%d)", 1021 (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""), 1022 opt->deflate_size); 1023 break; 1024 case CI_BSD_COMPRESS: 1025 if (opt2 != NULL && opt2->bsd_bits != opt->bsd_bits) 1026 slprintf(result, sizeof(result), "BSD-Compress (%d/%d)", 1027 opt->bsd_bits, opt2->bsd_bits); 1028 else 1029 slprintf(result, sizeof(result), "BSD-Compress (%d)", 1030 opt->bsd_bits); 1031 break; 1032 case CI_PREDICTOR_1: 1033 return "Predictor 1"; 1034 case CI_PREDICTOR_2: 1035 return "Predictor 2"; 1036 default: 1037 slprintf(result, sizeof(result), "Method %d", opt->method); 1038 } 1039 return result; 1040} 1041 1042/* 1043 * CCP has come up - inform the kernel driver and log a message. 1044 */ 1045static void 1046ccp_up(f) 1047 fsm *f; 1048{ 1049 ccp_options *go = &ccp_gotoptions[f->unit]; 1050 ccp_options *ho = &ccp_hisoptions[f->unit]; 1051 char method1[64]; 1052 1053 ccp_flags_set(f->unit, 1, 1); 1054 if (ANY_COMPRESS(*go)) { 1055 if (ANY_COMPRESS(*ho)) { 1056 if (go->method == ho->method) { 1057 notice("%s compression enabled", method_name(go, ho)); 1058 } else { 1059 strlcpy(method1, method_name(go, NULL), sizeof(method1)); 1060 notice("%s / %s compression enabled", 1061 method1, method_name(ho, NULL)); 1062 } 1063 } else 1064 notice("%s receive compression enabled", method_name(go, NULL)); 1065 } else if (ANY_COMPRESS(*ho)) 1066 notice("%s transmit compression enabled", method_name(ho, NULL)); 1067} 1068 1069/* 1070 * CCP has gone down - inform the kernel driver. 1071 */ 1072static void 1073ccp_down(f) 1074 fsm *f; 1075{ 1076 if (ccp_localstate[f->unit] & RACK_PENDING) 1077 UNTIMEOUT(ccp_rack_timeout, f); 1078 ccp_localstate[f->unit] = 0; 1079 ccp_flags_set(f->unit, 1, 0); 1080} 1081 1082/* 1083 * Print the contents of a CCP packet. 1084 */ 1085static char *ccp_codenames[] = { 1086 "ConfReq", "ConfAck", "ConfNak", "ConfRej", 1087 "TermReq", "TermAck", "CodeRej", 1088 NULL, NULL, NULL, NULL, NULL, NULL, 1089 "ResetReq", "ResetAck", 1090}; 1091 1092static int 1093ccp_printpkt(p, plen, printer, arg) 1094 u_char *p; 1095 int plen; 1096 void (*printer) __P((void *, char *, ...)); 1097 void *arg; 1098{ 1099 u_char *p0, *optend; 1100 int code, id, len; 1101 int optlen; 1102 1103 p0 = p; 1104 if (plen < HEADERLEN) 1105 return 0; 1106 code = p[0]; 1107 id = p[1]; 1108 len = (p[2] << 8) + p[3]; 1109 if (len < HEADERLEN || len > plen) 1110 return 0; 1111 1112 if (code >= 1 && code <= sizeof(ccp_codenames) / sizeof(char *) 1113 && ccp_codenames[code-1] != NULL) 1114 printer(arg, " %s", ccp_codenames[code-1]); 1115 else 1116 printer(arg, " code=0x%x", code); 1117 printer(arg, " id=0x%x", id); 1118 len -= HEADERLEN; 1119 p += HEADERLEN; 1120 1121 switch (code) { 1122 case CONFREQ: 1123 case CONFACK: 1124 case CONFNAK: 1125 case CONFREJ: 1126 /* print list of possible compression methods */ 1127 while (len >= 2) { 1128 code = p[0]; 1129 optlen = p[1]; 1130 if (optlen < 2 || optlen > len) 1131 break; 1132 printer(arg, " <"); 1133 len -= optlen; 1134 optend = p + optlen; 1135 switch (code) { 1136 case CI_DEFLATE: 1137 case CI_DEFLATE_DRAFT: 1138 if (optlen >= CILEN_DEFLATE) { 1139 printer(arg, "deflate%s %d", 1140 (code == CI_DEFLATE_DRAFT? "(old#)": ""), 1141 DEFLATE_SIZE(p[2])); 1142 if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL) 1143 printer(arg, " method %d", DEFLATE_METHOD(p[2])); 1144 if (p[3] != DEFLATE_CHK_SEQUENCE) 1145 printer(arg, " check %d", p[3]); 1146 p += CILEN_DEFLATE; 1147 } 1148 break; 1149 case CI_BSD_COMPRESS: 1150 if (optlen >= CILEN_BSD_COMPRESS) { 1151 printer(arg, "bsd v%d %d", BSD_VERSION(p[2]), 1152 BSD_NBITS(p[2])); 1153 p += CILEN_BSD_COMPRESS; 1154 } 1155 break; 1156 case CI_PREDICTOR_1: 1157 if (optlen >= CILEN_PREDICTOR_1) { 1158 printer(arg, "predictor 1"); 1159 p += CILEN_PREDICTOR_1; 1160 } 1161 break; 1162 case CI_PREDICTOR_2: 1163 if (optlen >= CILEN_PREDICTOR_2) { 1164 printer(arg, "predictor 2"); 1165 p += CILEN_PREDICTOR_2; 1166 } 1167 break; 1168 } 1169 while (p < optend) 1170 printer(arg, " %.2x", *p++); 1171 printer(arg, ">"); 1172 } 1173 break; 1174 1175 case TERMACK: 1176 case TERMREQ: 1177 if (len > 0 && *p >= ' ' && *p < 0x7f) { 1178 print_string((char *)p, len, printer, arg); 1179 p += len; 1180 len = 0; 1181 } 1182 break; 1183 } 1184 1185 /* dump out the rest of the packet in hex */ 1186 while (--len >= 0) 1187 printer(arg, " %.2x", *p++); 1188 1189 return p - p0; 1190} 1191 1192/* 1193 * We have received a packet that the decompressor failed to 1194 * decompress. Here we would expect to issue a reset-request, but 1195 * Motorola has a patent on resetting the compressor as a result of 1196 * detecting an error in the decompressed data after decompression. 1197 * (See US patent 5,130,993; international patent publication number 1198 * WO 91/10289; Australian patent 73296/91.) 1199 * 1200 * So we ask the kernel whether the error was detected after 1201 * decompression; if it was, we take CCP down, thus disabling 1202 * compression :-(, otherwise we issue the reset-request. 1203 */ 1204static void 1205ccp_datainput(unit, pkt, len) 1206 int unit; 1207 u_char *pkt; 1208 int len; 1209{ 1210 fsm *f; 1211 1212 f = &ccp_fsm[unit]; 1213 if (f->state == OPENED) { 1214 if (ccp_fatal_error(unit)) { 1215 /* 1216 * Disable compression by taking CCP down. 1217 */ 1218 error("Lost compression sync: disabling compression"); 1219 ccp_close(unit, "Lost compression sync"); 1220 } else { 1221 /* 1222 * Send a reset-request to reset the peer's compressor. 1223 * We don't do that if we are still waiting for an 1224 * acknowledgement to a previous reset-request. 1225 */ 1226 if (!(ccp_localstate[f->unit] & RACK_PENDING)) { 1227 fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0); 1228 TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT); 1229 ccp_localstate[f->unit] |= RACK_PENDING; 1230 } else 1231 ccp_localstate[f->unit] |= RREQ_REPEAT; 1232 } 1233 } 1234} 1235 1236/* 1237 * Timeout waiting for reset-ack. 1238 */ 1239static void 1240ccp_rack_timeout(arg) 1241 void *arg; 1242{ 1243 fsm *f = arg; 1244 1245 if (f->state == OPENED && ccp_localstate[f->unit] & RREQ_REPEAT) { 1246 fsm_sdata(f, CCP_RESETREQ, f->reqid, NULL, 0); 1247 TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT); 1248 ccp_localstate[f->unit] &= ~RREQ_REPEAT; 1249 } else 1250 ccp_localstate[f->unit] &= ~RACK_PENDING; 1251} 1252 1253