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