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