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