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