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