]> git.ozlabs.org Git - ppp.git/blob - ultrix/ppp-deflate.c
Update
[ppp.git] / ultrix / ppp-deflate.c
1 /*      $Id: ppp-deflate.c,v 1.6 2002/12/06 09:49:16 paulus Exp $       */
2
3 /*
4  * ppp_deflate.c - interface the zlib procedures for Deflate compression
5  * and decompression (as used by gzip) to the PPP code.
6  * This version is for use with mbufs on BSD-derived systems.
7  *
8  * Copyright (c) 1994 Paul Mackerras. All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  *
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  *
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in
19  *    the documentation and/or other materials provided with the
20  *    distribution.
21  *
22  * 3. The name(s) of the authors of this software must not be used to
23  *    endorse or promote products derived from this software without
24  *    prior written permission.
25  *
26  * 4. Redistributions of any form whatsoever must retain the following
27  *    acknowledgment:
28  *    "This product includes software developed by Paul Mackerras
29  *     <paulus@samba.org>".
30  *
31  * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
32  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
33  * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
34  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
35  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
36  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
37  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
38  */
39
40 #include "../h/param.h"
41 #include "../h/types.h"
42 #include "../h/mbuf.h"
43 #include "../h/socket.h"
44 #include "../net/net/if.h"
45 #include "ppp_defs.h"
46 #include "zlib.h"
47
48 #define PACKETPTR       struct mbuf *
49 #include "ppp-comp.h"
50
51 #if DO_DEFLATE
52
53 /*
54  * State for a Deflate (de)compressor.
55  */
56 struct deflate_state {
57     int         seqno;
58     int         w_size;
59     int         unit;
60     int         hdrlen;
61     int         mru;
62     int         debug;
63     z_stream    strm;
64     struct compstat stats;
65 };
66
67 #define DEFLATE_OVHD    2               /* Deflate overhead/packet */
68
69 static void     *zalloc __P((void *, u_int items, u_int size));
70 static void     zfree __P((void *, void *ptr));
71 static void     *z_comp_alloc __P((u_char *options, int opt_len));
72 static void     *z_decomp_alloc __P((u_char *options, int opt_len));
73 static void     z_comp_free __P((void *state));
74 static void     z_decomp_free __P((void *state));
75 static int      z_comp_init __P((void *state, u_char *options, int opt_len,
76                                  int unit, int hdrlen, int debug));
77 static int      z_decomp_init __P((void *state, u_char *options, int opt_len,
78                                      int unit, int hdrlen, int mru, int debug));
79 static int      z_compress __P((void *state, struct mbuf **mret,
80                                   struct mbuf *mp, int slen, int maxolen));
81 static void     z_incomp __P((void *state, struct mbuf *dmsg));
82 static int      z_decompress __P((void *state, struct mbuf *cmp,
83                                     struct mbuf **dmpp));
84 static void     z_comp_reset __P((void *state));
85 static void     z_decomp_reset __P((void *state));
86 static void     z_comp_stats __P((void *state, struct compstat *stats));
87
88 /*
89  * Procedures exported to if_ppp.c.
90  */
91 struct compressor ppp_deflate = {
92     CI_DEFLATE,                 /* compress_proto */
93     z_comp_alloc,               /* comp_alloc */
94     z_comp_free,                /* comp_free */
95     z_comp_init,                /* comp_init */
96     z_comp_reset,               /* comp_reset */
97     z_compress,                 /* compress */
98     z_comp_stats,               /* comp_stat */
99     z_decomp_alloc,             /* decomp_alloc */
100     z_decomp_free,              /* decomp_free */
101     z_decomp_init,              /* decomp_init */
102     z_decomp_reset,             /* decomp_reset */
103     z_decompress,               /* decompress */
104     z_incomp,                   /* incomp */
105     z_comp_stats,               /* decomp_stat */
106 };
107
108 struct compressor ppp_deflate_draft = {
109     CI_DEFLATE_DRAFT,           /* 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 /*
126  * Some useful mbuf macros not in mbuf.h.
127  */
128 #define M_IS_CLUSTER(m) ((m)->m_off > MMAXOFF)
129
130 #define M_TRAILINGSPACE(m) \
131         ((M_IS_CLUSTER(m) ? (u_int)(m)->m_clptr + M_CLUSTERSZ : MSIZE) \
132          - ((m)->m_off + (m)->m_len))
133
134 /*
135  * Space allocation and freeing routines for use by zlib routines.
136  */
137 void *
138 zalloc(notused, items, size)
139     void *notused;
140     u_int items, size;
141 {
142     void *ptr;
143
144     KM_ALLOC(ptr, void *, items * size, KM_DEVBUF, KM_NOARG);
145     return ptr;
146 }
147
148 void
149 zfree(notused, ptr)
150     void *notused;
151     void *ptr;
152 {
153     KM_FREE(ptr, KM_DEVBUF);
154 }
155
156 /*
157  * Allocate space for a compressor.
158  */
159 static void *
160 z_comp_alloc(options, opt_len)
161     u_char *options;
162     int opt_len;
163 {
164     struct deflate_state *state;
165     int w_size;
166
167     if (opt_len != CILEN_DEFLATE
168         || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
169         || options[1] != CILEN_DEFLATE
170         || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
171         || options[3] != DEFLATE_CHK_SEQUENCE)
172         return NULL;
173     w_size = DEFLATE_SIZE(options[2]);
174     if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
175         return NULL;
176
177     KM_ALLOC(state, struct deflate_state *, sizeof(struct deflate_state),
178              KM_DEVBUF, KM_NOARG);
179     if (state == NULL)
180         return NULL;
181     bzero(state, sizeof(struct deflate_state));
182
183     state->strm.next_in = NULL;
184     state->strm.zalloc = (alloc_func) zalloc;
185     state->strm.zfree = (free_func) zfree;
186     if (deflateInit2(&state->strm, Z_DEFAULT_COMPRESSION, DEFLATE_METHOD_VAL,
187                      -w_size, 8, Z_DEFAULT_STRATEGY) != Z_OK) {
188         KM_FREE(state, KM_DEVBUF);
189         return NULL;
190     }
191
192     state->w_size = w_size;
193     bzero(&state->stats, sizeof(state->stats));
194     return (void *) state;
195 }
196
197 static void
198 z_comp_free(arg)
199     void *arg;
200 {
201     struct deflate_state *state = (struct deflate_state *) arg;
202
203     deflateEnd(&state->strm);
204     KM_FREE(state, KM_DEVBUF);
205 }
206
207 static int
208 z_comp_init(arg, options, opt_len, unit, hdrlen, debug)
209     void *arg;
210     u_char *options;
211     int opt_len, unit, hdrlen, debug;
212 {
213     struct deflate_state *state = (struct deflate_state *) arg;
214
215     if (opt_len < CILEN_DEFLATE
216         || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
217         || options[1] != CILEN_DEFLATE
218         || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
219         || DEFLATE_SIZE(options[2]) != state->w_size
220         || options[3] != DEFLATE_CHK_SEQUENCE)
221         return 0;
222
223     state->seqno = 0;
224     state->unit = unit;
225     state->hdrlen = hdrlen;
226     state->debug = debug;
227
228     deflateReset(&state->strm);
229
230     return 1;
231 }
232
233 static void
234 z_comp_reset(arg)
235     void *arg;
236 {
237     struct deflate_state *state = (struct deflate_state *) arg;
238
239     state->seqno = 0;
240     deflateReset(&state->strm);
241 }
242
243 int
244 z_compress(arg, mret, mp, orig_len, maxolen)
245     void *arg;
246     struct mbuf **mret;         /* compressed packet (out) */
247     struct mbuf *mp;            /* uncompressed packet (in) */
248     int orig_len, maxolen;
249 {
250     struct deflate_state *state = (struct deflate_state *) arg;
251     u_char *rptr, *wptr;
252     int proto, olen, wspace, r, flush;
253     struct mbuf *m, *clp;
254
255     /*
256      * Check that the protocol is in the range we handle.
257      */
258     rptr = mtod(mp, u_char *);
259     proto = PPP_PROTOCOL(rptr);
260     if (proto > 0x3fff || proto == 0xfd || proto == 0xfb) {
261         *mret = NULL;
262         return orig_len;
263     }
264
265     /* Allocate one mbuf initially. */
266     if (maxolen > orig_len)
267         maxolen = orig_len;
268     MGET(m, M_DONTWAIT, MT_DATA);
269     *mret = m;
270     if (m != NULL) {
271         if (maxolen + state->hdrlen > MLEN) {
272             /* MCLGET is not a single statement!!! */
273             MCLGET(m, clp)
274         }
275         m->m_len = 0;
276         wspace = M_TRAILINGSPACE(m);
277         if (state->hdrlen > 0 && state->hdrlen + PPP_HDRLEN + 2 < wspace) {
278             m->m_off += 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                     if (maxolen - olen > MLEN) {
334                         MCLGET(m, clp)
335                     }
336                     m->m_len = 0;
337                     state->strm.next_out = mtod(m, u_char *);
338                     state->strm.avail_out = wspace = M_TRAILINGSPACE(m);
339                 }
340             }
341             if (m == NULL) {
342                 state->strm.next_out = NULL;
343                 state->strm.avail_out = 1000000;
344             }
345         }
346     }
347     if (m != NULL)
348         olen += (m->m_len = wspace - state->strm.avail_out);
349
350     /*
351      * See if we managed to reduce the size of the packet.
352      * If the compressor just gave us a single zero byte, it means
353      * the packet was incompressible.
354      */
355     if (m != NULL && olen < orig_len
356         && !(olen == PPP_HDRLEN + 3 && *wptr == 0)) {
357         state->stats.comp_bytes += olen;
358         state->stats.comp_packets++;
359     } else {
360         if (*mret != NULL) {
361             m_freem(*mret);
362             *mret = NULL;
363         }
364         state->stats.inc_bytes += orig_len;
365         state->stats.inc_packets++;
366         olen = orig_len;
367     }
368     state->stats.unc_bytes += orig_len;
369     state->stats.unc_packets++;
370
371     return olen;
372 }
373
374 static void
375 z_comp_stats(arg, stats)
376     void *arg;
377     struct compstat *stats;
378 {
379     struct deflate_state *state = (struct deflate_state *) arg;
380     u_int out;
381
382     *stats = state->stats;
383     stats->ratio = stats->unc_bytes;
384     out = stats->comp_bytes + stats->inc_bytes;
385     if (stats->ratio <= 0x7ffffff)
386         stats->ratio <<= 8;
387     else
388         out >>= 8;
389     if (out != 0)
390         stats->ratio /= out;
391 }
392
393 /*
394  * Allocate space for a decompressor.
395  */
396 static void *
397 z_decomp_alloc(options, opt_len)
398     u_char *options;
399     int opt_len;
400 {
401     struct deflate_state *state;
402     int w_size;
403
404     if (opt_len != CILEN_DEFLATE
405         || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
406         || options[1] != CILEN_DEFLATE
407         || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
408         || options[3] != DEFLATE_CHK_SEQUENCE)
409         return NULL;
410     w_size = DEFLATE_SIZE(options[2]);
411     if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
412         return NULL;
413
414     KM_ALLOC(state, struct deflate_state *, sizeof(struct deflate_state),
415              KM_DEVBUF, KM_NOARG);
416     if (state == NULL)
417         return NULL;
418     bzero(state, sizeof(struct deflate_state));
419
420     state->strm.next_out = NULL;
421     state->strm.zalloc = (alloc_func) zalloc;
422     state->strm.zfree = (free_func) zfree;
423     if (inflateInit2(&state->strm, -w_size) != Z_OK) {
424         KM_FREE(state, KM_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     KM_FREE(state, KM_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, *clp;
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     MGET(mo, M_DONTWAIT, MT_DATA);
535     if (mo == NULL)
536         return DECOMP_ERROR;
537     mo_head = mo;
538     mo->m_next = NULL;
539     MCLGET(mo, clp)
540     mo->m_len = 0;
541     ospace = M_TRAILINGSPACE(mo);
542     if (state->hdrlen > 0 && state->hdrlen + PPP_HDRLEN < ospace) {
543         mo->m_off += 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 (state->debug)
578                 printf("z_decompress%d: inflate returned %d (%s)\n",
579                        state->unit, r, (state->strm.msg? state->strm.msg: ""));
580             m_freem(mo_head);
581             return DECOMP_FATALERROR;
582         }
583         if (flush != Z_NO_FLUSH && state->strm.avail_out != 0)
584             break;              /* all done */
585         if (state->strm.avail_in == 0 && mi != NULL) {
586             state->strm.next_in = mtod(mi, u_char *);
587             state->strm.avail_in = mi->m_len;
588             rlen += mi->m_len;
589             mi = mi->m_next;
590             if (mi == NULL)
591                 flush = Z_PACKET_FLUSH;
592         }
593         if (state->strm.avail_out == 0) {
594             if (decode_proto) {
595                 state->strm.avail_out = ospace - PPP_HDRLEN;
596                 if ((wptr[3] & 1) == 0) {
597                     /* 2-byte protocol field */
598                     wptr[2] = wptr[3];
599                     --state->strm.next_out;
600                     ++state->strm.avail_out;
601                     --olen;
602                 }
603                 decode_proto = 0;
604             } else {
605                 mo->m_len = ospace;
606                 olen += ospace;
607                 MGET(mo->m_next, M_DONTWAIT, MT_DATA);
608                 mo = mo->m_next;
609                 if (mo == NULL) {
610                     m_freem(mo_head);
611                     return DECOMP_ERROR;
612                 }
613                 MCLGET(mo, clp)
614                 mo->m_len = 0;
615                 state->strm.next_out = mtod(mo, u_char *);
616                 state->strm.avail_out = ospace = M_TRAILINGSPACE(mo);
617             }
618         }
619     }
620     if (decode_proto) {
621         m_freem(mo_head);
622         return DECOMP_ERROR;
623     }
624     olen += (mo->m_len = ospace - state->strm.avail_out);
625
626     state->stats.unc_bytes += olen;
627     state->stats.unc_packets++;
628     state->stats.comp_bytes += rlen;
629     state->stats.comp_packets++;
630
631     *mop = mo_head;
632     return DECOMP_OK;
633 }
634
635 /*
636  * Incompressible data has arrived - add it to the history.
637  */
638 static void
639 z_incomp(arg, mi)
640     void *arg;
641     struct mbuf *mi;
642 {
643     struct deflate_state *state = (struct deflate_state *) arg;
644     u_char *rptr;
645     int rlen, proto, r;
646
647     /*
648      * Check that the protocol is one we handle.
649      */
650     rptr = mtod(mi, u_char *);
651     proto = PPP_PROTOCOL(rptr);
652     if (proto > 0x3fff || proto == 0xfd || proto == 0xfb)
653         return;
654
655     ++state->seqno;
656
657     /*
658      * Iterate through the mbufs, adding the characters in them
659      * to the decompressor's history.  For the first mbuf, we start
660      * at the either the 1st or 2nd byte of the protocol field,
661      * depending on whether the protocol value is compressible.
662      */
663     rlen = mi->m_len;
664     state->strm.next_in = rptr + 3;
665     state->strm.avail_in = rlen - 3;
666     if (proto > 0xff) {
667         --state->strm.next_in;
668         ++state->strm.avail_in;
669     }
670     for (;;) {
671         r = inflateIncomp(&state->strm);
672         if (r != Z_OK) {
673             /* gak! */
674             if (state->debug) {
675                 printf("z_incomp%d: inflateIncomp returned %d (%s)\n",
676                        state->unit, r, (state->strm.msg? state->strm.msg: ""));
677             }
678             return;
679         }
680         mi = mi->m_next;
681         if (mi == NULL)
682             break;
683         state->strm.next_in = mtod(mi, u_char *);
684         state->strm.avail_in = mi->m_len;
685         rlen += mi->m_len;
686     }
687
688     /*
689      * Update stats.
690      */
691     state->stats.inc_bytes += rlen;
692     state->stats.inc_packets++;
693     state->stats.unc_bytes += rlen;
694     state->stats.unc_packets++;
695 }
696
697 #endif /* DO_DEFLATE */