Home | History | Annotate | Line # | Download | only in net
ppp-deflate.c revision 1.12
      1 /*	$NetBSD: ppp-deflate.c,v 1.12 2002/09/13 14:32:11 itojun Exp $	*/
      2 /*	Id: ppp-deflate.c,v 1.5 1997/03/04 03:33:28 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 (at) 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/cdefs.h>
     42 __KERNEL_RCSID(0, "$NetBSD: ppp-deflate.c,v 1.12 2002/09/13 14:32:11 itojun Exp $");
     43 
     44 #include <sys/param.h>
     45 #include <sys/systm.h>
     46 #include <sys/mbuf.h>
     47 #include <net/ppp_defs.h>
     48 #include <net/zlib.h>
     49 
     50 #define PACKETPTR	struct mbuf *
     51 #include <net/ppp-comp.h>
     52 
     53 #if DO_DEFLATE
     54 
     55 #define DEFLATE_DEBUG	1
     56 
     57 /*
     58  * State for a Deflate (de)compressor.
     59  */
     60 struct deflate_state {
     61     int		seqno;
     62     int		w_size;
     63     int		unit;
     64     int		hdrlen;
     65     int		mru;
     66     int		debug;
     67     z_stream	strm;
     68     struct compstat stats;
     69 };
     70 
     71 #define DEFLATE_OVHD	2		/* Deflate overhead/packet */
     72 
     73 static void	*zalloc __P((void *, u_int items, u_int size));
     74 static void	zfree __P((void *, void *ptr));
     75 static void	*z_comp_alloc __P((u_char *options, int opt_len));
     76 static void	*z_decomp_alloc __P((u_char *options, int opt_len));
     77 static void	z_comp_free __P((void *state));
     78 static void	z_decomp_free __P((void *state));
     79 static int	z_comp_init __P((void *state, u_char *options, int opt_len,
     80 				 int unit, int hdrlen, int debug));
     81 static int	z_decomp_init __P((void *state, u_char *options, int opt_len,
     82 				     int unit, int hdrlen, int mru, int debug));
     83 static int	z_compress __P((void *state, struct mbuf **mret,
     84 				  struct mbuf *mp, int slen, int maxolen));
     85 static void	z_incomp __P((void *state, struct mbuf *dmsg));
     86 static int	z_decompress __P((void *state, struct mbuf *cmp,
     87 				    struct mbuf **dmpp));
     88 static void	z_comp_reset __P((void *state));
     89 static void	z_decomp_reset __P((void *state));
     90 static void	z_comp_stats __P((void *state, struct compstat *stats));
     91 
     92 /*
     93  * Procedures exported to if_ppp.c.
     94  */
     95 struct compressor ppp_deflate = {
     96     CI_DEFLATE,			/* compress_proto */
     97     z_comp_alloc,		/* comp_alloc */
     98     z_comp_free,		/* comp_free */
     99     z_comp_init,		/* comp_init */
    100     z_comp_reset,		/* comp_reset */
    101     z_compress,			/* compress */
    102     z_comp_stats,		/* comp_stat */
    103     z_decomp_alloc,		/* decomp_alloc */
    104     z_decomp_free,		/* decomp_free */
    105     z_decomp_init,		/* decomp_init */
    106     z_decomp_reset,		/* decomp_reset */
    107     z_decompress,		/* decompress */
    108     z_incomp,			/* incomp */
    109     z_comp_stats,		/* decomp_stat */
    110 };
    111 
    112 struct compressor ppp_deflate_draft = {
    113     CI_DEFLATE_DRAFT,		/* compress_proto */
    114     z_comp_alloc,		/* comp_alloc */
    115     z_comp_free,		/* comp_free */
    116     z_comp_init,		/* comp_init */
    117     z_comp_reset,		/* comp_reset */
    118     z_compress,			/* compress */
    119     z_comp_stats,		/* comp_stat */
    120     z_decomp_alloc,		/* decomp_alloc */
    121     z_decomp_free,		/* decomp_free */
    122     z_decomp_init,		/* decomp_init */
    123     z_decomp_reset,		/* decomp_reset */
    124     z_decompress,		/* decompress */
    125     z_incomp,			/* incomp */
    126     z_comp_stats,		/* decomp_stat */
    127 };
    128 /*
    129  * Space allocation and freeing routines for use by zlib routines.
    130  */
    131 void *
    132 zalloc(notused, items, size)
    133     void *notused;
    134     u_int items, size;
    135 {
    136     void *ptr;
    137 
    138     ptr = malloc(items * size, M_DEVBUF, M_NOWAIT);
    139     return ptr;
    140 }
    141 
    142 void
    143 zfree(notused, ptr)
    144     void *notused;
    145     void *ptr;
    146 {
    147     free(ptr, M_DEVBUF);
    148 }
    149 
    150 /*
    151  * Allocate space for a compressor.
    152  */
    153 static void *
    154 z_comp_alloc(options, opt_len)
    155     u_char *options;
    156     int opt_len;
    157 {
    158     struct deflate_state *state;
    159     int w_size;
    160 
    161     if (opt_len != CILEN_DEFLATE
    162 	|| (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
    163 	|| options[1] != CILEN_DEFLATE
    164 	|| DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
    165 	|| options[3] != DEFLATE_CHK_SEQUENCE)
    166 	return NULL;
    167     w_size = DEFLATE_SIZE(options[2]);
    168     if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
    169 	return NULL;
    170 
    171     MALLOC(state, struct deflate_state *, sizeof(struct deflate_state),
    172 	   M_DEVBUF, M_NOWAIT);
    173     if (state == NULL)
    174 	return NULL;
    175 
    176     state->strm.next_in = NULL;
    177     state->strm.zalloc = zalloc;
    178     state->strm.zfree = zfree;
    179     if (deflateInit2(&state->strm, Z_DEFAULT_COMPRESSION, DEFLATE_METHOD_VAL,
    180 		     -w_size, 8, Z_DEFAULT_STRATEGY) != Z_OK) {
    181 	FREE(state, M_DEVBUF);
    182 	return NULL;
    183     }
    184 
    185     state->w_size = w_size;
    186     memset(&state->stats, 0, sizeof(state->stats));
    187     return (void *) state;
    188 }
    189 
    190 static void
    191 z_comp_free(arg)
    192     void *arg;
    193 {
    194     struct deflate_state *state = (struct deflate_state *) arg;
    195 
    196     deflateEnd(&state->strm);
    197     FREE(state, M_DEVBUF);
    198 }
    199 
    200 static int
    201 z_comp_init(arg, options, opt_len, unit, hdrlen, debug)
    202     void *arg;
    203     u_char *options;
    204     int opt_len, unit, hdrlen, debug;
    205 {
    206     struct deflate_state *state = (struct deflate_state *) arg;
    207 
    208     if (opt_len < CILEN_DEFLATE
    209 	|| (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
    210 	|| options[1] != CILEN_DEFLATE
    211 	|| DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
    212 	|| DEFLATE_SIZE(options[2]) != state->w_size
    213 	|| options[3] != DEFLATE_CHK_SEQUENCE)
    214 	return 0;
    215 
    216     state->seqno = 0;
    217     state->unit = unit;
    218     state->hdrlen = hdrlen;
    219     state->debug = debug;
    220 
    221     deflateReset(&state->strm);
    222 
    223     return 1;
    224 }
    225 
    226 static void
    227 z_comp_reset(arg)
    228     void *arg;
    229 {
    230     struct deflate_state *state = (struct deflate_state *) arg;
    231 
    232     state->seqno = 0;
    233     deflateReset(&state->strm);
    234 }
    235 
    236 int
    237 z_compress(arg, mret, mp, orig_len, maxolen)
    238     void *arg;
    239     struct mbuf **mret;		/* compressed packet (out) */
    240     struct mbuf *mp;		/* uncompressed packet (in) */
    241     int orig_len, maxolen;
    242 {
    243     struct deflate_state *state = (struct deflate_state *) arg;
    244     u_char *rptr, *wptr;
    245     int proto, olen, wspace, r, flush;
    246     struct mbuf *m;
    247 
    248     /*
    249      * Check that the protocol is in the range we handle.
    250      */
    251     rptr = mtod(mp, u_char *);
    252     proto = PPP_PROTOCOL(rptr);
    253     if (proto > 0x3fff || proto == 0xfd || proto == 0xfb) {
    254 	*mret = NULL;
    255 	return orig_len;
    256     }
    257 
    258     /* Allocate one mbuf initially. */
    259     if (maxolen > orig_len)
    260 	maxolen = orig_len;
    261     MGET(m, M_DONTWAIT, MT_DATA);
    262     *mret = m;
    263     if (m != NULL) {
    264 	m->m_len = 0;
    265 	if (maxolen + state->hdrlen > MLEN)
    266 	    MCLGET(m, M_DONTWAIT);
    267 	wspace = M_TRAILINGSPACE(m);
    268 	if (state->hdrlen + PPP_HDRLEN + 2 < wspace) {
    269 	    m->m_data += state->hdrlen;
    270 	    wspace -= state->hdrlen;
    271 	}
    272 	wptr = mtod(m, u_char *);
    273 
    274 	/*
    275 	 * Copy over the PPP header and store the 2-byte sequence number.
    276 	 */
    277 	wptr[0] = PPP_ADDRESS(rptr);
    278 	wptr[1] = PPP_CONTROL(rptr);
    279 	wptr[2] = PPP_COMP >> 8;
    280 	wptr[3] = PPP_COMP;
    281 	wptr += PPP_HDRLEN;
    282 	wptr[0] = state->seqno >> 8;
    283 	wptr[1] = state->seqno;
    284 	wptr += 2;
    285 	state->strm.next_out = wptr;
    286 	state->strm.avail_out = wspace - (PPP_HDRLEN + 2);
    287     } else {
    288 	state->strm.next_out = NULL;
    289 	state->strm.avail_out = 1000000;
    290 	wptr = NULL;
    291 	wspace = 0;
    292     }
    293     ++state->seqno;
    294 
    295     rptr += (proto > 0xff)? 2: 3;	/* skip 1st proto byte if 0 */
    296     state->strm.next_in = rptr;
    297     state->strm.avail_in = mtod(mp, u_char *) + mp->m_len - rptr;
    298     mp = mp->m_next;
    299     flush = (mp == NULL)? Z_PACKET_FLUSH: Z_NO_FLUSH;
    300     olen = 0;
    301     for (;;) {
    302 	r = deflate(&state->strm, flush);
    303 	if (r != Z_OK) {
    304 	    printf("z_compress: deflate returned %d (%s)\n",
    305 		   r, (state->strm.msg? state->strm.msg: ""));
    306 	    break;
    307 	}
    308 	if (flush != Z_NO_FLUSH && state->strm.avail_out != 0)
    309 	    break;		/* all done */
    310 	if (state->strm.avail_in == 0 && mp != NULL) {
    311 	    state->strm.next_in = mtod(mp, u_char *);
    312 	    state->strm.avail_in = mp->m_len;
    313 	    mp = mp->m_next;
    314 	    if (mp == NULL)
    315 		flush = Z_PACKET_FLUSH;
    316 	}
    317 	if (state->strm.avail_out == 0) {
    318 	    if (m != NULL) {
    319 		m->m_len = wspace;
    320 		olen += wspace;
    321 		MGET(m->m_next, M_DONTWAIT, MT_DATA);
    322 		m = m->m_next;
    323 		if (m != NULL) {
    324 		    m->m_len = 0;
    325 		    if (maxolen - olen > MLEN)
    326 			MCLGET(m, M_DONTWAIT);
    327 		    state->strm.next_out = mtod(m, u_char *);
    328 		    state->strm.avail_out = wspace = M_TRAILINGSPACE(m);
    329 		}
    330 	    }
    331 	    if (m == NULL) {
    332 		state->strm.next_out = NULL;
    333 		state->strm.avail_out = 1000000;
    334 	    }
    335 	}
    336     }
    337     if (m != NULL)
    338 	olen += (m->m_len = wspace - state->strm.avail_out);
    339 
    340     /*
    341      * See if we managed to reduce the size of the packet.
    342      */
    343     if (m != NULL && olen < orig_len) {
    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     memset(&state->stats, 0, 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 = 0;
    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 #if !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 #if 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 #if !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 */
    691