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