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