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