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