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