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