1 /* $NetBSD: bsd-comp.c,v 1.19 2008/11/25 02:40:36 cube Exp $ */ 2 /* Id: bsd-comp.c,v 1.6 1996/08/28 06:31:58 paulus Exp */ 3 4 /* Because this code is derived from the 4.3BSD compress source: 5 * 6 * 7 * Copyright (c) 1985, 1986 The Regents of the University of California. 8 * All rights reserved. 9 * 10 * This code is derived from software contributed to Berkeley by 11 * James A. Woods, derived from original work by Spencer Thomas 12 * and Joseph Orost. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 3. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 */ 38 39 /* 40 * This version is for use with mbufs on BSD-derived systems. 41 */ 42 43 #include <sys/cdefs.h> 44 __KERNEL_RCSID(0, "$NetBSD: bsd-comp.c,v 1.19 2008/11/25 02:40:36 cube Exp $"); 45 46 #include <sys/param.h> 47 #include <sys/systm.h> 48 #include <sys/mbuf.h> 49 #include <sys/socket.h> 50 #include <sys/module.h> 51 #include <net/if.h> 52 #include <net/if_types.h> 53 #include <net/ppp_defs.h> 54 #include <net/if_ppp.h> 55 56 #define PACKETPTR struct mbuf * 57 #include <net/ppp-comp.h> 58 59 #if DO_BSD_COMPRESS 60 /* 61 * PPP "BSD compress" compression 62 * The differences between this compression and the classic BSD LZW 63 * source are obvious from the requirement that the classic code worked 64 * with files while this handles arbitrarily long streams that 65 * are broken into packets. They are: 66 * 67 * When the code size expands, a block of junk is not emitted by 68 * the compressor and not expected by the decompressor. 69 * 70 * New codes are not necessarily assigned every time an old 71 * code is output by the compressor. This is because a packet 72 * end forces a code to be emitted, but does not imply that a 73 * new sequence has been seen. 74 * 75 * The compression ratio is checked at the first end of a packet 76 * after the appropriate gap. Besides simplifying and speeding 77 * things up, this makes it more likely that the transmitter 78 * and receiver will agree when the dictionary is cleared when 79 * compression is not going well. 80 */ 81 82 /* 83 * A dictionary for doing BSD compress. 84 */ 85 struct bsd_db { 86 int totlen; /* length of this structure */ 87 u_int hsize; /* size of the hash table */ 88 u_char hshift; /* used in hash function */ 89 u_char n_bits; /* current bits/code */ 90 u_char maxbits; 91 u_char debug; 92 u_char unit; 93 uint16_t seqno; /* sequence # of next packet */ 94 u_int hdrlen; /* header length to preallocate */ 95 u_int mru; 96 u_int maxmaxcode; /* largest valid code */ 97 u_int max_ent; /* largest code in use */ 98 u_int in_count; /* uncompressed bytes, aged */ 99 u_int bytes_out; /* compressed bytes, aged */ 100 u_int ratio; /* recent compression ratio */ 101 u_int checkpoint; /* when to next check the ratio */ 102 u_int clear_count; /* times dictionary cleared */ 103 u_int incomp_count; /* incompressible packets */ 104 u_int incomp_bytes; /* incompressible bytes */ 105 u_int uncomp_count; /* uncompressed packets */ 106 u_int uncomp_bytes; /* uncompressed bytes */ 107 u_int comp_count; /* compressed packets */ 108 u_int comp_bytes; /* compressed bytes */ 109 uint16_t *lens; /* array of lengths of codes */ 110 struct bsd_dict { 111 union { /* hash value */ 112 uint32_t fcode; 113 struct { 114 #if BYTE_ORDER == LITTLE_ENDIAN 115 uint16_t prefix; /* preceding code */ 116 u_char suffix; /* last character of new code */ 117 u_char pad; 118 #else 119 u_char pad; 120 u_char suffix; /* last character of new code */ 121 uint16_t prefix; /* preceding code */ 122 #endif 123 } hs; 124 } f; 125 uint16_t codem1; /* output of hash table -1 */ 126 uint16_t cptr; /* map code to hash table entry */ 127 } dict[1]; 128 }; 129 130 #define BSD_OVHD 2 /* BSD compress overhead/packet */ 131 #define BSD_INIT_BITS BSD_MIN_BITS 132 133 static void *bsd_comp_alloc(u_char *options, int opt_len); 134 static void *bsd_decomp_alloc(u_char *options, int opt_len); 135 static void bsd_free(void *state); 136 static int bsd_comp_init(void *state, u_char *options, int opt_len, 137 int unit, int hdrlen, int debug); 138 static int bsd_decomp_init(void *state, u_char *options, int opt_len, 139 int unit, int hdrlen, int mru, int debug); 140 static int bsd_compress(void *state, struct mbuf **mret, 141 struct mbuf *mp, int slen, int maxolen); 142 static void bsd_incomp(void *state, struct mbuf *dmsg); 143 static int bsd_decompress(void *state, struct mbuf *cmp, 144 struct mbuf **dmpp); 145 static void bsd_reset(void *state); 146 static void bsd_comp_stats(void *state, struct compstat *stats); 147 148 /* 149 * Procedures exported to if_ppp.c. 150 */ 151 static struct compressor ppp_bsd_compress = { 152 .compress_proto = CI_BSD_COMPRESS, 153 .comp_alloc = bsd_comp_alloc, 154 .comp_free = bsd_free, 155 .comp_init = bsd_comp_init, 156 .comp_reset = bsd_reset, 157 .compress = bsd_compress, 158 .comp_stat = bsd_comp_stats, 159 .decomp_alloc = bsd_decomp_alloc, 160 .decomp_free = bsd_free, 161 .decomp_init = bsd_decomp_init, 162 .decomp_reset = bsd_reset, 163 .decompress = bsd_decompress, 164 .incomp = bsd_incomp, 165 .decomp_stat = bsd_comp_stats, 166 .comp_name = "ppp_bsdcomp" 167 }; 168 169 /* 170 * the next two codes should not be changed lightly, as they must not 171 * lie within the contiguous general code space. 172 */ 173 #define CLEAR 256 /* table clear output code */ 174 #define FIRST 257 /* first free entry */ 175 #define LAST 255 176 177 #define MAXCODE(b) ((1 << (b)) - 1) 178 #define BADCODEM1 MAXCODE(BSD_MAX_BITS) 179 180 #define BSD_HASH(prefix,suffix,hshift) ((((uint32_t)(suffix)) << (hshift)) \ 181 ^ (uint32_t)(prefix)) 182 #define BSD_KEY(prefix,suffix) ((((uint32_t)(suffix)) << 16) \ 183 + (uint32_t)(prefix)) 184 185 #define CHECK_GAP 10000 /* Ratio check interval */ 186 187 #define RATIO_SCALE_LOG 8 188 #define RATIO_SCALE (1<<RATIO_SCALE_LOG) 189 #define RATIO_MAX (0x7fffffff>>RATIO_SCALE_LOG) 190 191 static void bsd_clear(struct bsd_db *); 192 static int bsd_check(struct bsd_db *); 193 static void *bsd_alloc(u_char *, int, int); 194 static int bsd_init(struct bsd_db *, u_char *, int, int, int, int, 195 int, int); 196 197 /* 198 * clear the dictionary 199 */ 200 static void 201 bsd_clear(struct bsd_db *db) 202 { 203 db->clear_count++; 204 db->max_ent = FIRST-1; 205 db->n_bits = BSD_INIT_BITS; 206 db->ratio = 0; 207 db->bytes_out = 0; 208 db->in_count = 0; 209 db->checkpoint = CHECK_GAP; 210 } 211 212 /* 213 * If the dictionary is full, then see if it is time to reset it. 214 * 215 * Compute the compression ratio using fixed-point arithmetic 216 * with 8 fractional bits. 217 * 218 * Since we have an infinite stream instead of a single file, 219 * watch only the local compression ratio. 220 * 221 * Since both peers must reset the dictionary at the same time even in 222 * the absence of CLEAR codes (while packets are incompressible), they 223 * must compute the same ratio. 224 */ 225 static int /* 1=output CLEAR */ 226 bsd_check(struct bsd_db *db) 227 { 228 u_int new_ratio; 229 230 if (db->in_count >= db->checkpoint) { 231 /* age the ratio by limiting the size of the counts */ 232 if (db->in_count >= RATIO_MAX 233 || db->bytes_out >= RATIO_MAX) { 234 db->in_count -= db->in_count/4; 235 db->bytes_out -= db->bytes_out/4; 236 } 237 238 db->checkpoint = db->in_count + CHECK_GAP; 239 240 if (db->max_ent >= db->maxmaxcode) { 241 /* Reset the dictionary only if the ratio is worse, 242 * or if it looks as if it has been poisoned 243 * by incompressible data. 244 * 245 * This does not overflow, because 246 * db->in_count <= RATIO_MAX. 247 */ 248 new_ratio = db->in_count << RATIO_SCALE_LOG; 249 if (db->bytes_out != 0) 250 new_ratio /= db->bytes_out; 251 252 if (new_ratio < db->ratio || new_ratio < 1 * RATIO_SCALE) { 253 bsd_clear(db); 254 return 1; 255 } 256 db->ratio = new_ratio; 257 } 258 } 259 return 0; 260 } 261 262 /* 263 * Return statistics. 264 */ 265 static void 266 bsd_comp_stats(void *state, struct compstat *stats) 267 { 268 struct bsd_db *db = (struct bsd_db *) state; 269 u_int out; 270 271 stats->unc_bytes = db->uncomp_bytes; 272 stats->unc_packets = db->uncomp_count; 273 stats->comp_bytes = db->comp_bytes; 274 stats->comp_packets = db->comp_count; 275 stats->inc_bytes = db->incomp_bytes; 276 stats->inc_packets = db->incomp_count; 277 stats->ratio = db->in_count; 278 out = db->bytes_out; 279 if (stats->ratio <= 0x7fffff) 280 stats->ratio <<= 8; 281 else 282 out >>= 8; 283 if (out != 0) 284 stats->ratio /= out; 285 } 286 287 /* 288 * Reset state, as on a CCP ResetReq. 289 */ 290 static void 291 bsd_reset(void *state) 292 { 293 struct bsd_db *db = (struct bsd_db *) state; 294 295 db->seqno = 0; 296 bsd_clear(db); 297 db->clear_count = 0; 298 } 299 300 /* 301 * Allocate space for a (de) compressor. 302 */ 303 static void * 304 bsd_alloc(u_char *options, int opt_len, int decomp) 305 { 306 int bits; 307 u_int newlen, hsize, hshift, maxmaxcode; 308 struct bsd_db *db; 309 310 if (opt_len < CILEN_BSD_COMPRESS || options[0] != CI_BSD_COMPRESS 311 || options[1] != CILEN_BSD_COMPRESS 312 || BSD_VERSION(options[2]) != BSD_CURRENT_VERSION) 313 return NULL; 314 bits = BSD_NBITS(options[2]); 315 switch (bits) { 316 case 9: /* needs 82152 for both directions */ 317 case 10: /* needs 84144 */ 318 case 11: /* needs 88240 */ 319 case 12: /* needs 96432 */ 320 hsize = 5003; 321 hshift = 4; 322 break; 323 case 13: /* needs 176784 */ 324 hsize = 9001; 325 hshift = 5; 326 break; 327 case 14: /* needs 353744 */ 328 hsize = 18013; 329 hshift = 6; 330 break; 331 case 15: /* needs 691440 */ 332 hsize = 35023; 333 hshift = 7; 334 break; 335 case 16: /* needs 1366160--far too much, */ 336 /* hsize = 69001; */ /* and 69001 is too big for cptr */ 337 /* hshift = 8; */ /* in struct bsd_db */ 338 /* break; */ 339 default: 340 return NULL; 341 } 342 343 maxmaxcode = MAXCODE(bits); 344 newlen = sizeof(*db) + (hsize-1) * (sizeof(db->dict[0])); 345 db = malloc(newlen, M_DEVBUF, M_NOWAIT|M_ZERO); 346 if (!db) 347 return NULL; 348 349 if (!decomp) { 350 db->lens = NULL; 351 } else { 352 db->lens = malloc((maxmaxcode+1) * sizeof(db->lens[0]), 353 M_DEVBUF, M_NOWAIT); 354 if (!db->lens) { 355 free(db, M_DEVBUF); 356 return NULL; 357 } 358 } 359 360 db->totlen = newlen; 361 db->hsize = hsize; 362 db->hshift = hshift; 363 db->maxmaxcode = maxmaxcode; 364 db->maxbits = bits; 365 366 return (void *) db; 367 } 368 369 static void 370 bsd_free(void *state) 371 { 372 struct bsd_db *db = (struct bsd_db *) state; 373 374 if (db->lens) 375 free(db->lens, M_DEVBUF); 376 free(db, M_DEVBUF); 377 } 378 379 static void * 380 bsd_comp_alloc(u_char *options, int opt_len) 381 { 382 return bsd_alloc(options, opt_len, 0); 383 } 384 385 static void * 386 bsd_decomp_alloc(u_char *options, int opt_len) 387 { 388 return bsd_alloc(options, opt_len, 1); 389 } 390 391 /* 392 * Initialize the database. 393 */ 394 static int 395 bsd_init(struct bsd_db *db, u_char *options, int opt_len, int unit, int hdrlen, 396 int mru, int debug, int decomp) 397 { 398 int i; 399 400 if (opt_len < CILEN_BSD_COMPRESS || options[0] != CI_BSD_COMPRESS 401 || options[1] != CILEN_BSD_COMPRESS 402 || BSD_VERSION(options[2]) != BSD_CURRENT_VERSION 403 || BSD_NBITS(options[2]) != db->maxbits 404 || (decomp && db->lens == NULL)) 405 return 0; 406 407 if (decomp) { 408 i = LAST+1; 409 while (i != 0) 410 db->lens[--i] = 1; 411 } 412 i = db->hsize; 413 while (i != 0) { 414 db->dict[--i].codem1 = BADCODEM1; 415 db->dict[i].cptr = 0; 416 } 417 418 db->unit = unit; 419 db->hdrlen = hdrlen; 420 db->mru = mru; 421 #ifndef DEBUG 422 if (debug) 423 #endif 424 db->debug = 1; 425 426 bsd_reset(db); 427 428 return 1; 429 } 430 431 static int 432 bsd_comp_init(void *state, u_char *options, int opt_len, int unit, int hdrlen, 433 int debug) 434 { 435 return bsd_init((struct bsd_db *) state, options, opt_len, 436 unit, hdrlen, 0, debug, 0); 437 } 438 439 static int 440 bsd_decomp_init(void *state, u_char *options, int opt_len, int unit, int hdrlen, 441 int mru, int debug) 442 { 443 return bsd_init((struct bsd_db *) state, options, opt_len, 444 unit, hdrlen, mru, debug, 1); 445 } 446 447 448 /* 449 * compress a packet 450 * One change from the BSD compress command is that when the 451 * code size expands, we do not output a bunch of padding. 452 */ 453 int /* new slen */ 454 bsd_compress(void *state, 455 struct mbuf **mret /* return compressed mbuf chain here */, 456 struct mbuf *mp /* from here */, 457 int slen, int maxolen) 458 { 459 struct bsd_db *db = (struct bsd_db *) state; 460 int hshift = db->hshift; 461 u_int max_ent = db->max_ent; 462 u_int n_bits = db->n_bits; 463 u_int bitno = 32; 464 uint32_t accm = 0, fcode; 465 struct bsd_dict *dictp; 466 u_char c; 467 int hval, disp, ent, ilen; 468 u_char *rptr, *wptr; 469 u_char *cp_end; 470 int olen; 471 struct mbuf *m; 472 473 #define PUTBYTE(v) { \ 474 ++olen; \ 475 if (wptr) { \ 476 *wptr++ = (v); \ 477 if (wptr >= cp_end) { \ 478 m->m_len = wptr - mtod(m, u_char *); \ 479 MGET(m->m_next, M_DONTWAIT, MT_DATA); \ 480 m = m->m_next; \ 481 if (m) { \ 482 m->m_len = 0; \ 483 if (maxolen - olen > MLEN) \ 484 MCLGET(m, M_DONTWAIT); \ 485 wptr = mtod(m, u_char *); \ 486 cp_end = wptr + M_TRAILINGSPACE(m); \ 487 } else \ 488 wptr = NULL; \ 489 } \ 490 } \ 491 } 492 493 #define OUTPUT(ent) { \ 494 bitno -= n_bits; \ 495 accm |= ((ent) << bitno); \ 496 do { \ 497 PUTBYTE(accm >> 24); \ 498 accm <<= 8; \ 499 bitno += 8; \ 500 } while (bitno <= 24); \ 501 } 502 503 /* 504 * If the protocol is not in the range we're interested in, 505 * just return without compressing the packet. If it is, 506 * the protocol becomes the first byte to compress. 507 */ 508 rptr = mtod(mp, u_char *); 509 ent = PPP_PROTOCOL(rptr); 510 if (ent < 0x21 || ent > 0xf9) { 511 *mret = NULL; 512 return slen; 513 } 514 515 /* Don't generate compressed packets which are larger than 516 the uncompressed packet. */ 517 if (maxolen > slen) 518 maxolen = slen; 519 520 /* Allocate one mbuf to start with. */ 521 MGET(m, M_DONTWAIT, MT_DATA); 522 *mret = m; 523 if (m != NULL) { 524 m->m_len = 0; 525 if (maxolen + db->hdrlen > MLEN) 526 MCLGET(m, M_DONTWAIT); 527 m->m_data += db->hdrlen; 528 wptr = mtod(m, u_char *); 529 cp_end = wptr + M_TRAILINGSPACE(m); 530 } else 531 wptr = cp_end = NULL; 532 533 /* 534 * Copy the PPP header over, changing the protocol, 535 * and install the 2-byte packet sequence number. 536 */ 537 if (wptr) { 538 *wptr++ = PPP_ADDRESS(rptr); /* assumes the ppp header is */ 539 *wptr++ = PPP_CONTROL(rptr); /* all in one mbuf */ 540 *wptr++ = 0; /* change the protocol */ 541 *wptr++ = PPP_COMP; 542 *wptr++ = db->seqno >> 8; 543 *wptr++ = db->seqno; 544 } 545 ++db->seqno; 546 547 olen = 0; 548 rptr += PPP_HDRLEN; 549 slen = mp->m_len - PPP_HDRLEN; 550 ilen = slen + 1; 551 for (;;) { 552 if (slen <= 0) { 553 mp = mp->m_next; 554 if (!mp) 555 break; 556 rptr = mtod(mp, u_char *); 557 slen = mp->m_len; 558 if (!slen) 559 continue; /* handle 0-length buffers */ 560 ilen += slen; 561 } 562 563 slen--; 564 c = *rptr++; 565 fcode = BSD_KEY(ent, c); 566 hval = BSD_HASH(ent, c, hshift); 567 dictp = &db->dict[hval]; 568 569 /* Validate and then check the entry. */ 570 if (dictp->codem1 >= max_ent) 571 goto nomatch; 572 if (dictp->f.fcode == fcode) { 573 ent = dictp->codem1+1; 574 continue; /* found (prefix,suffix) */ 575 } 576 577 /* continue probing until a match or invalid entry */ 578 disp = (hval == 0) ? 1 : hval; 579 do { 580 hval += disp; 581 if (hval >= db->hsize) 582 hval -= db->hsize; 583 dictp = &db->dict[hval]; 584 if (dictp->codem1 >= max_ent) 585 goto nomatch; 586 } while (dictp->f.fcode != fcode); 587 ent = dictp->codem1 + 1; /* finally found (prefix,suffix) */ 588 continue; 589 590 nomatch: 591 OUTPUT(ent); /* output the prefix */ 592 593 /* code -> hashtable */ 594 if (max_ent < db->maxmaxcode) { 595 struct bsd_dict *dictp2; 596 /* expand code size if needed */ 597 if (max_ent >= MAXCODE(n_bits)) 598 db->n_bits = ++n_bits; 599 600 /* Invalidate old hash table entry using 601 * this code, and then take it over. 602 */ 603 dictp2 = &db->dict[max_ent+1]; 604 if (db->dict[dictp2->cptr].codem1 == max_ent) 605 db->dict[dictp2->cptr].codem1 = BADCODEM1; 606 dictp2->cptr = hval; 607 dictp->codem1 = max_ent; 608 dictp->f.fcode = fcode; 609 610 db->max_ent = ++max_ent; 611 } 612 ent = c; 613 } 614 615 OUTPUT(ent); /* output the last code */ 616 db->bytes_out += olen; 617 db->in_count += ilen; 618 if (bitno < 32) 619 ++db->bytes_out; /* count complete bytes */ 620 621 if (bsd_check(db)) 622 OUTPUT(CLEAR); /* do not count the CLEAR */ 623 624 /* 625 * Pad dribble bits of last code with ones. 626 * Do not emit a completely useless byte of ones. 627 */ 628 if (bitno != 32) 629 PUTBYTE((accm | (0xff << (bitno-8))) >> 24); 630 631 if (m != NULL) { 632 m->m_len = wptr - mtod(m, u_char *); 633 m->m_next = NULL; 634 } 635 636 /* 637 * Increase code size if we would have without the packet 638 * boundary and as the decompressor will. 639 */ 640 if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode) 641 db->n_bits++; 642 643 db->uncomp_bytes += ilen; 644 ++db->uncomp_count; 645 if (olen + PPP_HDRLEN + BSD_OVHD > maxolen) { 646 /* throw away the compressed stuff if it is longer than uncompressed */ 647 if (*mret != NULL) { 648 m_freem(*mret); 649 *mret = NULL; 650 } 651 ++db->incomp_count; 652 db->incomp_bytes += ilen; 653 } else { 654 ++db->comp_count; 655 db->comp_bytes += olen + BSD_OVHD; 656 } 657 658 return olen + PPP_HDRLEN + BSD_OVHD; 659 #undef OUTPUT 660 #undef PUTBYTE 661 } 662 663 664 /* 665 * Update the "BSD Compress" dictionary on the receiver for 666 * incompressible data by pretending to compress the incoming data. 667 */ 668 static void 669 bsd_incomp(void *state, struct mbuf *dmsg) 670 { 671 struct bsd_db *db = (struct bsd_db *) state; 672 u_int hshift = db->hshift; 673 u_int max_ent = db->max_ent; 674 u_int n_bits = db->n_bits; 675 struct bsd_dict *dictp; 676 uint32_t fcode; 677 u_char c; 678 uint32_t hval, disp; 679 int slen, ilen; 680 u_int bitno = 7; 681 u_char *rptr; 682 u_int ent; 683 684 /* 685 * If the protocol is not in the range we're interested in, 686 * just return without looking at the packet. If it is, 687 * the protocol becomes the first byte to "compress". 688 */ 689 rptr = mtod(dmsg, u_char *); 690 ent = PPP_PROTOCOL(rptr); 691 if (ent < 0x21 || ent > 0xf9) 692 return; 693 694 db->seqno++; 695 ilen = 1; /* count the protocol as 1 byte */ 696 rptr += PPP_HDRLEN; 697 slen = dmsg->m_len - PPP_HDRLEN; 698 for (;;) { 699 if (slen <= 0) { 700 dmsg = dmsg->m_next; 701 if (!dmsg) 702 break; 703 rptr = mtod(dmsg, u_char *); 704 slen = dmsg->m_len; 705 continue; 706 } 707 ilen += slen; 708 709 do { 710 c = *rptr++; 711 fcode = BSD_KEY(ent, c); 712 hval = BSD_HASH(ent, c, hshift); 713 dictp = &db->dict[hval]; 714 715 /* validate and then check the entry */ 716 if (dictp->codem1 >= max_ent) 717 goto nomatch; 718 if (dictp->f.fcode == fcode) { 719 ent = dictp->codem1+1; 720 continue; /* found (prefix,suffix) */ 721 } 722 723 /* continue probing until a match or invalid entry */ 724 disp = (hval == 0) ? 1 : hval; 725 do { 726 hval += disp; 727 if (hval >= db->hsize) 728 hval -= db->hsize; 729 dictp = &db->dict[hval]; 730 if (dictp->codem1 >= max_ent) 731 goto nomatch; 732 } while (dictp->f.fcode != fcode); 733 ent = dictp->codem1+1; 734 continue; /* finally found (prefix,suffix) */ 735 736 nomatch: /* output (count) the prefix */ 737 bitno += n_bits; 738 739 /* code -> hashtable */ 740 if (max_ent < db->maxmaxcode) { 741 struct bsd_dict *dictp2; 742 /* expand code size if needed */ 743 if (max_ent >= MAXCODE(n_bits)) 744 db->n_bits = ++n_bits; 745 746 /* Invalidate previous hash table entry 747 * assigned this code, and then take it over. 748 */ 749 dictp2 = &db->dict[max_ent+1]; 750 if (db->dict[dictp2->cptr].codem1 == max_ent) 751 db->dict[dictp2->cptr].codem1 = BADCODEM1; 752 dictp2->cptr = hval; 753 dictp->codem1 = max_ent; 754 dictp->f.fcode = fcode; 755 756 db->max_ent = ++max_ent; 757 db->lens[max_ent] = db->lens[ent]+1; 758 } 759 ent = c; 760 } while (--slen != 0); 761 } 762 bitno += n_bits; /* output (count) the last code */ 763 db->bytes_out += bitno/8; 764 db->in_count += ilen; 765 (void)bsd_check(db); 766 767 ++db->incomp_count; 768 db->incomp_bytes += ilen; 769 ++db->uncomp_count; 770 db->uncomp_bytes += ilen; 771 772 /* Increase code size if we would have without the packet 773 * boundary and as the decompressor will. 774 */ 775 if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode) 776 db->n_bits++; 777 } 778 779 780 /* 781 * Decompress "BSD Compress". 782 * 783 * Because of patent problems, we return DECOMP_ERROR for errors 784 * found by inspecting the input data and for system problems, but 785 * DECOMP_FATALERROR for any errors which could possibly be said to 786 * be being detected "after" decompression. For DECOMP_ERROR, 787 * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be 788 * infringing a patent of Motorola's if we do, so we take CCP down 789 * instead. 790 * 791 * Given that the frame has the correct sequence number and a good FCS, 792 * errors such as invalid codes in the input most likely indicate a 793 * bug, so we return DECOMP_FATALERROR for them in order to turn off 794 * compression, even though they are detected by inspecting the input. 795 */ 796 int 797 bsd_decompress(void *state, struct mbuf *cmp, struct mbuf **dmpp) 798 { 799 struct bsd_db *db = (struct bsd_db *) state; 800 u_int max_ent = db->max_ent; 801 uint32_t accm = 0; 802 u_int bitno = 32; /* 1st valid bit in accm */ 803 u_int n_bits = db->n_bits; 804 u_int tgtbitno = 32-n_bits; /* bitno when we have a code */ 805 struct bsd_dict *dictp; 806 int explen, i, seq, len; 807 u_int incode, oldcode, finchar; 808 u_char *p, *rptr, *wptr; 809 struct mbuf *m, *dmp, *mret; 810 int adrs, ctrl, ilen; 811 int space, codelen, extra; 812 813 /* 814 * Save the address/control from the PPP header 815 * and then get the sequence number. 816 */ 817 *dmpp = NULL; 818 rptr = mtod(cmp, u_char *); 819 adrs = PPP_ADDRESS(rptr); 820 ctrl = PPP_CONTROL(rptr); 821 rptr += PPP_HDRLEN; 822 len = cmp->m_len - PPP_HDRLEN; 823 seq = 0; 824 for (i = 0; i < 2; ++i) { 825 while (len <= 0) { 826 cmp = cmp->m_next; 827 if (cmp == NULL) 828 return DECOMP_ERROR; 829 rptr = mtod(cmp, u_char *); 830 len = cmp->m_len; 831 } 832 seq = (seq << 8) + *rptr++; 833 --len; 834 } 835 836 /* 837 * Check the sequence number and give up if it differs from 838 * the value we're expecting. 839 */ 840 if (seq != db->seqno) { 841 if (db->debug) 842 printf("bsd_decomp%d: bad sequence # %d, expected %d\n", 843 db->unit, seq, db->seqno - 1); 844 return DECOMP_ERROR; 845 } 846 ++db->seqno; 847 848 /* 849 * Allocate one mbuf to start with. 850 */ 851 MGETHDR(dmp, M_DONTWAIT, MT_DATA); 852 if (dmp == NULL) 853 return DECOMP_ERROR; 854 mret = dmp; 855 dmp->m_len = 0; 856 dmp->m_next = NULL; 857 MCLGET(dmp, M_DONTWAIT); 858 dmp->m_data += db->hdrlen; 859 wptr = mtod(dmp, u_char *); 860 space = M_TRAILINGSPACE(dmp) - PPP_HDRLEN + 1; 861 862 /* 863 * Fill in the ppp header, but not the last byte of the protocol 864 * (that comes from the decompressed data). 865 */ 866 wptr[0] = adrs; 867 wptr[1] = ctrl; 868 wptr[2] = 0; 869 wptr += PPP_HDRLEN - 1; 870 871 ilen = len; 872 oldcode = CLEAR; 873 explen = 0; 874 for (;;) { 875 if (len == 0) { 876 cmp = cmp->m_next; 877 if (!cmp) /* quit at end of message */ 878 break; 879 rptr = mtod(cmp, u_char *); 880 len = cmp->m_len; 881 ilen += len; 882 continue; /* handle 0-length buffers */ 883 } 884 885 /* 886 * Accumulate bytes until we have a complete code. 887 * Then get the next code, relying on the 32-bit, 888 * unsigned accm to mask the result. 889 */ 890 bitno -= 8; 891 accm |= *rptr++ << bitno; 892 --len; 893 if (tgtbitno < bitno) 894 continue; 895 incode = accm >> tgtbitno; 896 accm <<= n_bits; 897 bitno += n_bits; 898 899 if (incode == CLEAR) { 900 /* 901 * The dictionary must only be cleared at 902 * the end of a packet. But there could be an 903 * empty mbuf at the end. 904 */ 905 if (len > 0 || cmp->m_next != NULL) { 906 while ((cmp = cmp->m_next) != NULL) 907 len += cmp->m_len; 908 if (len > 0) { 909 m_freem(mret); 910 if (db->debug) 911 printf("bsd_decomp%d: bad CLEAR\n", db->unit); 912 return DECOMP_FATALERROR; /* probably a bug */ 913 } 914 } 915 bsd_clear(db); 916 explen = ilen = 0; 917 break; 918 } 919 920 if (incode > max_ent + 2 || incode > db->maxmaxcode 921 || (incode > max_ent && oldcode == CLEAR)) { 922 m_freem(mret); 923 if (db->debug) { 924 printf("bsd_decomp%d: bad code 0x%x oldcode=0x%x ", 925 db->unit, incode, oldcode); 926 printf("max_ent=0x%x explen=%d seqno=%d\n", 927 max_ent, explen, db->seqno); 928 } 929 return DECOMP_FATALERROR; /* probably a bug */ 930 } 931 932 /* Special case for KwKwK string. */ 933 if (incode > max_ent) { 934 finchar = oldcode; 935 extra = 1; 936 } else { 937 finchar = incode; 938 extra = 0; 939 } 940 941 codelen = db->lens[finchar]; 942 explen += codelen + extra; 943 if (explen > db->mru + 1) { 944 m_freem(mret); 945 if (db->debug) { 946 printf("bsd_decomp%d: ran out of mru\n", db->unit); 947 #ifdef DEBUG 948 while ((cmp = cmp->m_next) != NULL) 949 len += cmp->m_len; 950 printf(" len=%d, finchar=0x%x, codelen=%d, explen=%d\n", 951 len, finchar, codelen, explen); 952 #endif 953 } 954 return DECOMP_FATALERROR; 955 } 956 957 /* 958 * For simplicity, the decoded characters go in a single mbuf, 959 * so we allocate a single extra cluster mbuf if necessary. 960 */ 961 if ((space -= codelen + extra) < 0) { 962 dmp->m_len = wptr - mtod(dmp, u_char *); 963 MGET(m, M_DONTWAIT, MT_DATA); 964 if (m == NULL) { 965 m_freem(mret); 966 return DECOMP_ERROR; 967 } 968 m->m_len = 0; 969 m->m_next = NULL; 970 dmp->m_next = m; 971 MCLGET(m, M_DONTWAIT); 972 space = M_TRAILINGSPACE(m) - (codelen + extra); 973 if (space < 0) { 974 /* now that's what I call *compression*. */ 975 m_freem(mret); 976 return DECOMP_ERROR; 977 } 978 dmp = m; 979 wptr = mtod(dmp, u_char *); 980 } 981 982 /* 983 * Decode this code and install it in the decompressed buffer. 984 */ 985 p = (wptr += codelen); 986 while (finchar > LAST) { 987 dictp = &db->dict[db->dict[finchar].cptr]; 988 #ifdef DEBUG 989 if (--codelen <= 0 || dictp->codem1 != finchar-1) 990 goto bad; 991 #endif 992 *--p = dictp->f.hs.suffix; 993 finchar = dictp->f.hs.prefix; 994 } 995 *--p = finchar; 996 997 #ifdef DEBUG 998 if (--codelen != 0) 999 printf("bsd_decomp%d: short by %d after code 0x%x, max_ent=0x%x\n", 1000 db->unit, codelen, incode, max_ent); 1001 #endif 1002 1003 if (extra) /* the KwKwK case again */ 1004 *wptr++ = finchar; 1005 1006 /* 1007 * If not first code in a packet, and 1008 * if not out of code space, then allocate a new code. 1009 * 1010 * Keep the hash table correct so it can be used 1011 * with uncompressed packets. 1012 */ 1013 if (oldcode != CLEAR && max_ent < db->maxmaxcode) { 1014 struct bsd_dict *dictp2; 1015 uint32_t fcode; 1016 uint32_t hval, disp; 1017 1018 fcode = BSD_KEY(oldcode,finchar); 1019 hval = BSD_HASH(oldcode,finchar,db->hshift); 1020 dictp = &db->dict[hval]; 1021 1022 /* look for a free hash table entry */ 1023 if (dictp->codem1 < max_ent) { 1024 disp = (hval == 0) ? 1 : hval; 1025 do { 1026 hval += disp; 1027 if (hval >= db->hsize) 1028 hval -= db->hsize; 1029 dictp = &db->dict[hval]; 1030 } while (dictp->codem1 < max_ent); 1031 } 1032 1033 /* 1034 * Invalidate previous hash table entry 1035 * assigned this code, and then take it over 1036 */ 1037 dictp2 = &db->dict[max_ent+1]; 1038 if (db->dict[dictp2->cptr].codem1 == max_ent) { 1039 db->dict[dictp2->cptr].codem1 = BADCODEM1; 1040 } 1041 dictp2->cptr = hval; 1042 dictp->codem1 = max_ent; 1043 dictp->f.fcode = fcode; 1044 1045 db->max_ent = ++max_ent; 1046 db->lens[max_ent] = db->lens[oldcode]+1; 1047 1048 /* Expand code size if needed. */ 1049 if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode) { 1050 db->n_bits = ++n_bits; 1051 tgtbitno = 32-n_bits; 1052 } 1053 } 1054 oldcode = incode; 1055 } 1056 dmp->m_len = wptr - mtod(dmp, u_char *); 1057 1058 /* 1059 * Keep the checkpoint right so that incompressible packets 1060 * clear the dictionary at the right times. 1061 */ 1062 db->bytes_out += ilen; 1063 db->in_count += explen; 1064 if (bsd_check(db) && db->debug) { 1065 printf("bsd_decomp%d: peer should have cleared dictionary\n", 1066 db->unit); 1067 } 1068 1069 ++db->comp_count; 1070 db->comp_bytes += ilen + BSD_OVHD; 1071 ++db->uncomp_count; 1072 db->uncomp_bytes += explen; 1073 1074 *dmpp = mret; 1075 return DECOMP_OK; 1076 1077 #ifdef DEBUG 1078 bad: 1079 if (codelen <= 0) { 1080 printf("bsd_decomp%d: fell off end of chain ", db->unit); 1081 printf("0x%x at 0x%x by 0x%x, max_ent=0x%x\n", 1082 incode, finchar, db->dict[finchar].cptr, max_ent); 1083 } else if (dictp->codem1 != finchar-1) { 1084 printf("bsd_decomp%d: bad code chain 0x%x finchar=0x%x ", 1085 db->unit, incode, finchar); 1086 printf("oldcode=0x%x cptr=0x%x codem1=0x%x\n", oldcode, 1087 db->dict[finchar].cptr, dictp->codem1); 1088 } 1089 m_freem(mret); 1090 return DECOMP_FATALERROR; 1091 #endif /* DEBUG */ 1092 } 1093 1094 MODULE(MODULE_CLASS_MISC, ppp_bsdcomp, NULL); 1095 1096 static int 1097 ppp_bsdcomp_modcmd(modcmd_t cmd, void *arg) 1098 { 1099 1100 switch (cmd) { 1101 case MODULE_CMD_INIT: 1102 return ppp_register_compressor(&ppp_bsd_compress); 1103 case MODULE_CMD_FINI: 1104 return ppp_unregister_compressor(&ppp_bsd_compress); 1105 case MODULE_CMD_STAT: 1106 return 0; 1107 default: 1108 return ENOTTY; 1109 } 1110 1111 return ENOTTY; 1112 } 1113 #endif /* DO_BSD_COMPRESS */ 1114