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