1/* 2 * ppp_deflate.c - interface the zlib procedures for Deflate compression 3 * and decompression (as used by gzip) to the PPP code. 4 * This version is for use with STREAMS under SunOS 4.x, Solaris 2, 5 * SVR4, OSF/1 and AIX 4.x. 6 * 7 * Copyright (c) 1994 Paul Mackerras. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * 3. The name(s) of the authors of this software must not be used to 22 * endorse or promote products derived from this software without 23 * prior written permission. 24 * 25 * 4. Redistributions of any form whatsoever must retain the following 26 * acknowledgment: 27 * "This product includes software developed by Paul Mackerras 28 * <paulus@samba.org>". 29 * 30 * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO 31 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 32 * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY 33 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 34 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 35 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 36 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 37 * 38 * $Id: deflate.c,v 1.12 2004/01/17 05:47:55 carlsonj Exp $ 39 */ 40 41#ifdef AIX4 42#include <net/net_globals.h> 43#endif 44#include <sys/param.h> 45#include <sys/types.h> 46#include <sys/stream.h> 47#include <net/ppp_defs.h> 48#include "ppp_mod.h" 49 50#define PACKETPTR mblk_t * 51#include <net/ppp-comp.h> 52 53#ifdef __osf__ 54#include "zlib.h" 55#else 56#include "../common/zlib.h" 57#endif 58 59#ifdef SOL2 60#include <sys/sunddi.h> 61#endif 62 63#if DO_DEFLATE 64 65#define DEFLATE_DEBUG 1 66 67/* 68 * State for a Deflate (de)compressor. 69 */ 70struct deflate_state { 71 int seqno; 72 int w_size; 73 int unit; 74 int hdrlen; 75 int mru; 76 int debug; 77 z_stream strm; 78 struct compstat stats; 79}; 80 81#define DEFLATE_OVHD 2 /* Deflate overhead/packet */ 82 83static void *z_alloc __P((void *, u_int items, u_int size)); 84static void *z_alloc_init __P((void *, u_int items, u_int size)); 85static void z_free __P((void *, void *ptr)); 86static void *z_comp_alloc __P((u_char *options, int opt_len)); 87static void *z_decomp_alloc __P((u_char *options, int opt_len)); 88static void z_comp_free __P((void *state)); 89static void z_decomp_free __P((void *state)); 90static int z_comp_init __P((void *state, u_char *options, int opt_len, 91 int unit, int hdrlen, int debug)); 92static int z_decomp_init __P((void *state, u_char *options, int opt_len, 93 int unit, int hdrlen, int mru, int debug)); 94static int z_compress __P((void *state, mblk_t **mret, 95 mblk_t *mp, int slen, int maxolen)); 96static void z_incomp __P((void *state, mblk_t *dmsg)); 97static int z_decompress __P((void *state, mblk_t *cmp, 98 mblk_t **dmpp)); 99static void z_comp_reset __P((void *state)); 100static void z_decomp_reset __P((void *state)); 101static void z_comp_stats __P((void *state, struct compstat *stats)); 102 103/* 104 * Procedures exported to ppp_comp.c. 105 */ 106struct compressor ppp_deflate = { 107 CI_DEFLATE, /* compress_proto */ 108 z_comp_alloc, /* comp_alloc */ 109 z_comp_free, /* comp_free */ 110 z_comp_init, /* comp_init */ 111 z_comp_reset, /* comp_reset */ 112 z_compress, /* compress */ 113 z_comp_stats, /* comp_stat */ 114 z_decomp_alloc, /* decomp_alloc */ 115 z_decomp_free, /* decomp_free */ 116 z_decomp_init, /* decomp_init */ 117 z_decomp_reset, /* decomp_reset */ 118 z_decompress, /* decompress */ 119 z_incomp, /* incomp */ 120 z_comp_stats, /* decomp_stat */ 121}; 122 123struct compressor ppp_deflate_draft = { 124 CI_DEFLATE_DRAFT, /* compress_proto */ 125 z_comp_alloc, /* comp_alloc */ 126 z_comp_free, /* comp_free */ 127 z_comp_init, /* comp_init */ 128 z_comp_reset, /* comp_reset */ 129 z_compress, /* compress */ 130 z_comp_stats, /* comp_stat */ 131 z_decomp_alloc, /* decomp_alloc */ 132 z_decomp_free, /* decomp_free */ 133 z_decomp_init, /* decomp_init */ 134 z_decomp_reset, /* decomp_reset */ 135 z_decompress, /* decompress */ 136 z_incomp, /* incomp */ 137 z_comp_stats, /* decomp_stat */ 138}; 139 140#define DECOMP_CHUNK 512 141 142/* 143 * Space allocation and freeing routines for use by zlib routines. 144 */ 145struct zchunk { 146 u_int size; 147 u_int guard; 148}; 149 150#define GUARD_MAGIC 0x77a6011a 151 152static void * 153z_alloc_init(notused, items, size) 154 void *notused; 155 u_int items, size; 156{ 157 struct zchunk *z; 158 159 size = items * size + sizeof(struct zchunk); 160#ifdef __osf__ 161 z = (struct zchunk *) ALLOC_SLEEP(size); 162#else 163 z = (struct zchunk *) ALLOC_NOSLEEP(size); 164#endif 165 z->size = size; 166 z->guard = GUARD_MAGIC; 167 return (void *) (z + 1); 168} 169 170static void * 171z_alloc(notused, items, size) 172 void *notused; 173 u_int items, size; 174{ 175 struct zchunk *z; 176 177 size = items * size + sizeof(struct zchunk); 178 z = (struct zchunk *) ALLOC_NOSLEEP(size); 179 z->size = size; 180 z->guard = GUARD_MAGIC; 181 return (void *) (z + 1); 182} 183 184static void 185z_free(notused, ptr) 186 void *notused; 187 void *ptr; 188{ 189 struct zchunk *z = ((struct zchunk *) ptr) - 1; 190 191 if (z->guard != GUARD_MAGIC) { 192 printf("ppp: z_free of corrupted chunk at %x (%x, %x)\n", 193 z, z->size, z->guard); 194 return; 195 } 196 FREE(z, z->size); 197} 198 199/* 200 * Allocate space for a compressor. 201 */ 202static void * 203z_comp_alloc(options, opt_len) 204 u_char *options; 205 int opt_len; 206{ 207 struct deflate_state *state; 208 int w_size; 209 210 if (opt_len != CILEN_DEFLATE 211 || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) 212 || options[1] != CILEN_DEFLATE 213 || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL 214 || options[3] != DEFLATE_CHK_SEQUENCE) 215 return NULL; 216 w_size = DEFLATE_SIZE(options[2]); 217 /* 218 * N.B. the 9 below should be DEFLATE_MIN_SIZE (8), but using 219 * 8 will cause kernel crashes because of a bug in zlib. 220 */ 221 if (w_size < 9 || w_size > DEFLATE_MAX_SIZE) 222 return NULL; 223 224 225#ifdef __osf__ 226 state = (struct deflate_state *) ALLOC_SLEEP(sizeof(*state)); 227#else 228 state = (struct deflate_state *) ALLOC_NOSLEEP(sizeof(*state)); 229#endif 230 231 if (state == NULL) 232 return NULL; 233 234 state->strm.next_in = NULL; 235 state->strm.zalloc = (alloc_func) z_alloc_init; 236 state->strm.zfree = (free_func) z_free; 237 if (deflateInit2(&state->strm, Z_DEFAULT_COMPRESSION, DEFLATE_METHOD_VAL, 238 -w_size, 8, Z_DEFAULT_STRATEGY) != Z_OK) { 239 FREE(state, sizeof(*state)); 240 return NULL; 241 } 242 243 state->strm.zalloc = (alloc_func) z_alloc; 244 state->w_size = w_size; 245 bzero(&state->stats, sizeof(state->stats)); 246 return (void *) state; 247} 248 249static void 250z_comp_free(arg) 251 void *arg; 252{ 253 struct deflate_state *state = (struct deflate_state *) arg; 254 255 deflateEnd(&state->strm); 256 FREE(state, sizeof(*state)); 257} 258 259static int 260z_comp_init(arg, options, opt_len, unit, hdrlen, debug) 261 void *arg; 262 u_char *options; 263 int opt_len, unit, hdrlen, debug; 264{ 265 struct deflate_state *state = (struct deflate_state *) arg; 266 267 if (opt_len < CILEN_DEFLATE 268 || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) 269 || options[1] != CILEN_DEFLATE 270 || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL 271 || DEFLATE_SIZE(options[2]) != state->w_size 272 || options[3] != DEFLATE_CHK_SEQUENCE) 273 return 0; 274 275 state->seqno = 0; 276 state->unit = unit; 277 state->hdrlen = hdrlen; 278 state->debug = debug; 279 280 deflateReset(&state->strm); 281 282 return 1; 283} 284 285static void 286z_comp_reset(arg) 287 void *arg; 288{ 289 struct deflate_state *state = (struct deflate_state *) arg; 290 291 state->seqno = 0; 292 deflateReset(&state->strm); 293} 294 295static int 296z_compress(arg, mret, mp, orig_len, maxolen) 297 void *arg; 298 mblk_t **mret; /* compressed packet (out) */ 299 mblk_t *mp; /* uncompressed packet (in) */ 300 int orig_len, maxolen; 301{ 302 struct deflate_state *state = (struct deflate_state *) arg; 303 u_char *rptr, *wptr; 304 int proto, olen, wspace, r, flush; 305 mblk_t *m; 306 307 /* 308 * Check that the protocol is in the range we handle. 309 */ 310 *mret = NULL; 311 rptr = mp->b_rptr; 312 if (rptr + PPP_HDRLEN > mp->b_wptr) { 313 if (!pullupmsg(mp, PPP_HDRLEN)) 314 return 0; 315 rptr = mp->b_rptr; 316 } 317 proto = PPP_PROTOCOL(rptr); 318 if (proto > 0x3fff || proto == 0xfd || proto == 0xfb) 319 return orig_len; 320 321 /* Allocate one mblk initially. */ 322 if (maxolen > orig_len) 323 maxolen = orig_len; 324 if (maxolen <= PPP_HDRLEN + 2) { 325 wspace = 0; 326 m = NULL; 327 } else { 328 wspace = maxolen + state->hdrlen; 329 if (wspace > 4096) 330 wspace = 4096; 331 m = allocb(wspace, BPRI_MED); 332 } 333 if (m != NULL) { 334 *mret = m; 335 if (state->hdrlen + PPP_HDRLEN + 2 < wspace) { 336 m->b_rptr += state->hdrlen; 337 m->b_wptr = m->b_rptr; 338 wspace -= state->hdrlen; 339 } 340 wptr = m->b_wptr; 341 342 /* 343 * Copy over the PPP header and store the 2-byte sequence number. 344 */ 345 wptr[0] = PPP_ADDRESS(rptr); 346 wptr[1] = PPP_CONTROL(rptr); 347 wptr[2] = PPP_COMP >> 8; 348 wptr[3] = PPP_COMP; 349 wptr += PPP_HDRLEN; 350 wptr[0] = state->seqno >> 8; 351 wptr[1] = state->seqno; 352 wptr += 2; 353 state->strm.next_out = wptr; 354 state->strm.avail_out = wspace - (PPP_HDRLEN + 2); 355 } else { 356 state->strm.next_out = NULL; 357 state->strm.avail_out = 1000000; 358 } 359 ++state->seqno; 360 361 rptr += (proto > 0xff)? 2: 3; /* skip 1st proto byte if 0 */ 362 state->strm.next_in = rptr; 363 state->strm.avail_in = mp->b_wptr - rptr; 364 mp = mp->b_cont; 365 flush = (mp == NULL)? Z_PACKET_FLUSH: Z_NO_FLUSH; 366 olen = 0; 367 for (;;) { 368 r = deflate(&state->strm, flush); 369 if (r != Z_OK) { 370 printf("z_compress: deflate returned %d (%s)\n", 371 r, (state->strm.msg? state->strm.msg: "")); 372 break; 373 } 374 if (flush != Z_NO_FLUSH && state->strm.avail_out != 0) 375 break; /* all done */ 376 if (state->strm.avail_in == 0 && mp != NULL) { 377 state->strm.next_in = mp->b_rptr; 378 state->strm.avail_in = mp->b_wptr - mp->b_rptr; 379 mp = mp->b_cont; 380 if (mp == NULL) 381 flush = Z_PACKET_FLUSH; 382 } 383 if (state->strm.avail_out == 0) { 384 if (m != NULL) { 385 m->b_wptr += wspace; 386 olen += wspace; 387 wspace = maxolen - olen; 388 if (wspace <= 0) { 389 wspace = 0; 390 m->b_cont = NULL; 391 } else { 392 if (wspace < 32) 393 wspace = 32; 394 else if (wspace > 4096) 395 wspace = 4096; 396 m->b_cont = allocb(wspace, BPRI_MED); 397 } 398 m = m->b_cont; 399 if (m != NULL) { 400 state->strm.next_out = m->b_wptr; 401 state->strm.avail_out = wspace; 402 } 403 } 404 if (m == NULL) { 405 state->strm.next_out = NULL; 406 state->strm.avail_out = 1000000; 407 } 408 } 409 } 410 if (m != NULL) { 411 m->b_wptr += wspace - state->strm.avail_out; 412 olen += wspace - state->strm.avail_out; 413 } 414 415 /* 416 * See if we managed to reduce the size of the packet. 417 */ 418 if (olen < orig_len && m != NULL) { 419 state->stats.comp_bytes += olen; 420 state->stats.comp_packets++; 421 } else { 422 if (*mret != NULL) { 423 freemsg(*mret); 424 *mret = NULL; 425 } 426 state->stats.inc_bytes += orig_len; 427 state->stats.inc_packets++; 428 olen = orig_len; 429 } 430 state->stats.unc_bytes += orig_len; 431 state->stats.unc_packets++; 432 433 return olen; 434} 435 436static void 437z_comp_stats(arg, stats) 438 void *arg; 439 struct compstat *stats; 440{ 441 struct deflate_state *state = (struct deflate_state *) arg; 442 u_int out; 443 444 *stats = state->stats; 445 stats->ratio = stats->unc_bytes; 446 out = stats->comp_bytes + stats->unc_bytes; 447 if (stats->ratio <= 0x7ffffff) 448 stats->ratio <<= 8; 449 else 450 out >>= 8; 451 if (out != 0) 452 stats->ratio /= out; 453} 454 455/* 456 * Allocate space for a decompressor. 457 */ 458static void * 459z_decomp_alloc(options, opt_len) 460 u_char *options; 461 int opt_len; 462{ 463 struct deflate_state *state; 464 int w_size; 465 466 if (opt_len != CILEN_DEFLATE 467 || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) 468 || options[1] != CILEN_DEFLATE 469 || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL 470 || options[3] != DEFLATE_CHK_SEQUENCE) 471 return NULL; 472 w_size = DEFLATE_SIZE(options[2]); 473 /* 474 * N.B. the 9 below should be DEFLATE_MIN_SIZE (8), but using 475 * 8 will cause kernel crashes because of a bug in zlib. 476 */ 477 if (w_size < 9 || w_size > DEFLATE_MAX_SIZE) 478 return NULL; 479 480#ifdef __osf__ 481 state = (struct deflate_state *) ALLOC_SLEEP(sizeof(*state)); 482#else 483 state = (struct deflate_state *) ALLOC_NOSLEEP(sizeof(*state)); 484#endif 485 if (state == NULL) 486 return NULL; 487 488 state->strm.next_out = NULL; 489 state->strm.zalloc = (alloc_func) z_alloc_init; 490 state->strm.zfree = (free_func) z_free; 491 if (inflateInit2(&state->strm, -w_size) != Z_OK) { 492 FREE(state, sizeof(*state)); 493 return NULL; 494 } 495 496 state->strm.zalloc = (alloc_func) z_alloc; 497 state->w_size = w_size; 498 bzero(&state->stats, sizeof(state->stats)); 499 return (void *) state; 500} 501 502static void 503z_decomp_free(arg) 504 void *arg; 505{ 506 struct deflate_state *state = (struct deflate_state *) arg; 507 508 inflateEnd(&state->strm); 509 FREE(state, sizeof(*state)); 510} 511 512static int 513z_decomp_init(arg, options, opt_len, unit, hdrlen, mru, debug) 514 void *arg; 515 u_char *options; 516 int opt_len, unit, hdrlen, mru, debug; 517{ 518 struct deflate_state *state = (struct deflate_state *) arg; 519 520 if (opt_len < CILEN_DEFLATE 521 || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) 522 || options[1] != CILEN_DEFLATE 523 || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL 524 || DEFLATE_SIZE(options[2]) != state->w_size 525 || options[3] != DEFLATE_CHK_SEQUENCE) 526 return 0; 527 528 state->seqno = 0; 529 state->unit = unit; 530 state->hdrlen = hdrlen; 531 state->debug = debug; 532 state->mru = mru; 533 534 inflateReset(&state->strm); 535 536 return 1; 537} 538 539static void 540z_decomp_reset(arg) 541 void *arg; 542{ 543 struct deflate_state *state = (struct deflate_state *) arg; 544 545 state->seqno = 0; 546 inflateReset(&state->strm); 547} 548 549/* 550 * Decompress a Deflate-compressed packet. 551 * 552 * Because of patent problems, we return DECOMP_ERROR for errors 553 * found by inspecting the input data and for system problems, but 554 * DECOMP_FATALERROR for any errors which could possibly be said to 555 * be being detected "after" decompression. For DECOMP_ERROR, 556 * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be 557 * infringing a patent of Motorola's if we do, so we take CCP down 558 * instead. 559 * 560 * Given that the frame has the correct sequence number and a good FCS, 561 * errors such as invalid codes in the input most likely indicate a 562 * bug, so we return DECOMP_FATALERROR for them in order to turn off 563 * compression, even though they are detected by inspecting the input. 564 */ 565static int 566z_decompress(arg, mi, mop) 567 void *arg; 568 mblk_t *mi, **mop; 569{ 570 struct deflate_state *state = (struct deflate_state *) arg; 571 mblk_t *mo, *mo_head; 572 u_char *rptr, *wptr; 573 int rlen, olen, ospace; 574 int seq, i, flush, r, decode_proto; 575 u_char hdr[PPP_HDRLEN + DEFLATE_OVHD]; 576 577 *mop = NULL; 578 rptr = mi->b_rptr; 579 for (i = 0; i < PPP_HDRLEN + DEFLATE_OVHD; ++i) { 580 while (rptr >= mi->b_wptr) { 581 mi = mi->b_cont; 582 if (mi == NULL) 583 return DECOMP_ERROR; 584 rptr = mi->b_rptr; 585 } 586 hdr[i] = *rptr++; 587 } 588 589 /* Check the sequence number. */ 590 seq = (hdr[PPP_HDRLEN] << 8) + hdr[PPP_HDRLEN+1]; 591 if (seq != state->seqno) { 592#if !DEFLATE_DEBUG 593 if (state->debug) 594#endif 595 printf("z_decompress%d: bad seq # %d, expected %d\n", 596 state->unit, seq, state->seqno); 597 return DECOMP_ERROR; 598 } 599 ++state->seqno; 600 601 /* Allocate an output message block. */ 602 mo = allocb(DECOMP_CHUNK + state->hdrlen, BPRI_MED); 603 if (mo == NULL) 604 return DECOMP_ERROR; 605 mo_head = mo; 606 mo->b_cont = NULL; 607 mo->b_rptr += state->hdrlen; 608 mo->b_wptr = wptr = mo->b_rptr; 609 ospace = DECOMP_CHUNK; 610 olen = 0; 611 612 /* 613 * Fill in the first part of the PPP header. The protocol field 614 * comes from the decompressed data. 615 */ 616 wptr[0] = PPP_ADDRESS(hdr); 617 wptr[1] = PPP_CONTROL(hdr); 618 wptr[2] = 0; 619 620 /* 621 * Set up to call inflate. We set avail_out to 1 initially so we can 622 * look at the first byte of the output and decide whether we have 623 * a 1-byte or 2-byte protocol field. 624 */ 625 state->strm.next_in = rptr; 626 state->strm.avail_in = mi->b_wptr - rptr; 627 mi = mi->b_cont; 628 flush = (mi == NULL)? Z_PACKET_FLUSH: Z_NO_FLUSH; 629 rlen = state->strm.avail_in + PPP_HDRLEN + DEFLATE_OVHD; 630 state->strm.next_out = wptr + 3; 631 state->strm.avail_out = 1; 632 decode_proto = 1; 633 634 /* 635 * Call inflate, supplying more input or output as needed. 636 */ 637 for (;;) { 638 r = inflate(&state->strm, flush); 639 if (r != Z_OK) { 640#if !DEFLATE_DEBUG 641 if (state->debug) 642#endif 643 printf("z_decompress%d: inflate returned %d (%s)\n", 644 state->unit, r, (state->strm.msg? state->strm.msg: "")); 645 freemsg(mo_head); 646 return DECOMP_FATALERROR; 647 } 648 if (flush != Z_NO_FLUSH && state->strm.avail_out != 0) 649 break; /* all done */ 650 if (state->strm.avail_in == 0 && mi != NULL) { 651 state->strm.next_in = mi->b_rptr; 652 state->strm.avail_in = mi->b_wptr - mi->b_rptr; 653 rlen += state->strm.avail_in; 654 mi = mi->b_cont; 655 if (mi == NULL) 656 flush = Z_PACKET_FLUSH; 657 } 658 if (state->strm.avail_out == 0) { 659 if (decode_proto) { 660 state->strm.avail_out = ospace - PPP_HDRLEN; 661 if ((wptr[3] & 1) == 0) { 662 /* 2-byte protocol field */ 663 wptr[2] = wptr[3]; 664 --state->strm.next_out; 665 ++state->strm.avail_out; 666 } 667 decode_proto = 0; 668 } else { 669 mo->b_wptr += ospace; 670 olen += ospace; 671 mo->b_cont = allocb(DECOMP_CHUNK, BPRI_MED); 672 mo = mo->b_cont; 673 if (mo == NULL) { 674 freemsg(mo_head); 675 return DECOMP_ERROR; 676 } 677 state->strm.next_out = mo->b_rptr; 678 state->strm.avail_out = ospace = DECOMP_CHUNK; 679 } 680 } 681 } 682 if (decode_proto) { 683 freemsg(mo_head); 684 return DECOMP_ERROR; 685 } 686 mo->b_wptr += ospace - state->strm.avail_out; 687 olen += ospace - state->strm.avail_out; 688 689#if DEFLATE_DEBUG 690 if (olen > state->mru + PPP_HDRLEN) 691 printf("ppp_deflate%d: exceeded mru (%d > %d)\n", 692 state->unit, olen, state->mru + PPP_HDRLEN); 693#endif 694 695 state->stats.unc_bytes += olen; 696 state->stats.unc_packets++; 697 state->stats.comp_bytes += rlen; 698 state->stats.comp_packets++; 699 700 *mop = mo_head; 701 return DECOMP_OK; 702} 703 704/* 705 * Incompressible data has arrived - add it to the history. 706 */ 707static void 708z_incomp(arg, mi) 709 void *arg; 710 mblk_t *mi; 711{ 712 struct deflate_state *state = (struct deflate_state *) arg; 713 u_char *rptr; 714 int rlen, proto, r; 715 716 /* 717 * Check that the protocol is one we handle. 718 */ 719 rptr = mi->b_rptr; 720 if (rptr + PPP_HDRLEN > mi->b_wptr) { 721 if (!pullupmsg(mi, PPP_HDRLEN)) 722 return; 723 rptr = mi->b_rptr; 724 } 725 proto = PPP_PROTOCOL(rptr); 726 if (proto > 0x3fff || proto == 0xfd || proto == 0xfb) 727 return; 728 729 ++state->seqno; 730 731 /* 732 * Iterate through the message blocks, adding the characters in them 733 * to the decompressor's history. For the first block, we start 734 * at the either the 1st or 2nd byte of the protocol field, 735 * depending on whether the protocol value is compressible. 736 */ 737 rlen = mi->b_wptr - mi->b_rptr; 738 state->strm.next_in = rptr + 3; 739 state->strm.avail_in = rlen - 3; 740 if (proto > 0xff) { 741 --state->strm.next_in; 742 ++state->strm.avail_in; 743 } 744 for (;;) { 745 r = inflateIncomp(&state->strm); 746 if (r != Z_OK) { 747 /* gak! */ 748#if !DEFLATE_DEBUG 749 if (state->debug) 750#endif 751 printf("z_incomp%d: inflateIncomp returned %d (%s)\n", 752 state->unit, r, (state->strm.msg? state->strm.msg: "")); 753 return; 754 } 755 mi = mi->b_cont; 756 if (mi == NULL) 757 break; 758 state->strm.next_in = mi->b_rptr; 759 state->strm.avail_in = mi->b_wptr - mi->b_rptr; 760 rlen += state->strm.avail_in; 761 } 762 763 /* 764 * Update stats. 765 */ 766 state->stats.inc_bytes += rlen; 767 state->stats.inc_packets++; 768 state->stats.unc_bytes += rlen; 769 state->stats.unc_packets++; 770} 771 772#endif /* DO_DEFLATE */ 773