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