]> git.ozlabs.org Git - ppp.git/blob - netbsd-1.2/ppp-deflate.c
Repaired bad LCP Configure-Nak generated to request EAP instead of PAP.
[ppp.git] / netbsd-1.2 / ppp-deflate.c
1 /*      $NetBSD: ppp-deflate.c,v 1.6 1998/05/02 14:34:25 christos Exp $ */
2 /*      Id: ppp-deflate.c,v 1.5 1997/03/04 03:33:28 paulus Exp  */
3
4 /*
5  * ppp_deflate.c - interface the zlib procedures for Deflate compression
6  * and decompression (as used by gzip) to the PPP code.
7  * This version is for use with mbufs on BSD-derived systems.
8  *
9  * Copyright (c) 1994 Paul Mackerras. All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  *
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  *
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in
20  *    the documentation and/or other materials provided with the
21  *    distribution.
22  *
23  * 3. The name(s) of the authors of this software must not be used to
24  *    endorse or promote products derived from this software without
25  *    prior written permission.
26  *
27  * 4. Redistributions of any form whatsoever must retain the following
28  *    acknowledgment:
29  *    "This product includes software developed by Paul Mackerras
30  *     <paulus@samba.org>".
31  *
32  * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
33  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
34  * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
35  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
36  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
37  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
38  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
39  */
40
41 #include <sys/param.h>
42 #include <sys/types.h>
43 #include <sys/systm.h>
44 #include <sys/mbuf.h>
45 #include <net/ppp_defs.h>
46 #include <net/zlib.h>
47
48 #define PACKETPTR       struct mbuf *
49 #include <net/ppp-comp.h>
50
51 #if DO_DEFLATE
52
53 #define DEFLATE_DEBUG   1
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 __P((void *, u_int items, u_int size));
72 static void     zfree __P((void *, void *ptr));
73 static void     *z_comp_alloc __P((u_char *options, int opt_len));
74 static void     *z_decomp_alloc __P((u_char *options, int opt_len));
75 static void     z_comp_free __P((void *state));
76 static void     z_decomp_free __P((void *state));
77 static int      z_comp_init __P((void *state, u_char *options, int opt_len,
78                                  int unit, int hdrlen, int debug));
79 static int      z_decomp_init __P((void *state, u_char *options, int opt_len,
80                                      int unit, int hdrlen, int mru, int debug));
81 static int      z_compress __P((void *state, struct mbuf **mret,
82                                   struct mbuf *mp, int slen, int maxolen));
83 static void     z_incomp __P((void *state, struct mbuf *dmsg));
84 static int      z_decompress __P((void *state, struct mbuf *cmp,
85                                     struct mbuf **dmpp));
86 static void     z_comp_reset __P((void *state));
87 static void     z_decomp_reset __P((void *state));
88 static void     z_comp_stats __P((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 *
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
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 *
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) != 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
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
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
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
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      */
341     if (m != NULL && olen < orig_len) {
342         state->stats.comp_bytes += olen;
343         state->stats.comp_packets++;
344     } else {
345         if (*mret != NULL) {
346             m_freem(*mret);
347             *mret = NULL;
348         }
349         state->stats.inc_bytes += orig_len;
350         state->stats.inc_packets++;
351         olen = orig_len;
352     }
353     state->stats.unc_bytes += orig_len;
354     state->stats.unc_packets++;
355
356     return olen;
357 }
358
359 static void
360 z_comp_stats(arg, stats)
361     void *arg;
362     struct compstat *stats;
363 {
364     struct deflate_state *state = (struct deflate_state *) arg;
365     u_int out;
366
367     *stats = state->stats;
368     stats->ratio = stats->unc_bytes;
369     out = stats->comp_bytes + stats->inc_bytes;
370     if (stats->ratio <= 0x7ffffff)
371         stats->ratio <<= 8;
372     else
373         out >>= 8;
374     if (out != 0)
375         stats->ratio /= out;
376 }
377
378 /*
379  * Allocate space for a decompressor.
380  */
381 static void *
382 z_decomp_alloc(options, opt_len)
383     u_char *options;
384     int opt_len;
385 {
386     struct deflate_state *state;
387     int w_size;
388
389     if (opt_len != CILEN_DEFLATE
390         || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
391         || options[1] != CILEN_DEFLATE
392         || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
393         || options[3] != DEFLATE_CHK_SEQUENCE)
394         return NULL;
395     w_size = DEFLATE_SIZE(options[2]);
396     if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
397         return NULL;
398
399     MALLOC(state, struct deflate_state *, sizeof(struct deflate_state),
400            M_DEVBUF, M_NOWAIT);
401     if (state == NULL)
402         return NULL;
403
404     state->strm.next_out = NULL;
405     state->strm.zalloc = zalloc;
406     state->strm.zfree = zfree;
407     if (inflateInit2(&state->strm, -w_size) != Z_OK) {
408         FREE(state, M_DEVBUF);
409         return NULL;
410     }
411
412     state->w_size = w_size;
413     bzero(&state->stats, sizeof(state->stats));
414     return (void *) state;
415 }
416
417 static void
418 z_decomp_free(arg)
419     void *arg;
420 {
421     struct deflate_state *state = (struct deflate_state *) arg;
422
423     inflateEnd(&state->strm);
424     FREE(state, M_DEVBUF);
425 }
426
427 static int
428 z_decomp_init(arg, options, opt_len, unit, hdrlen, mru, debug)
429     void *arg;
430     u_char *options;
431     int opt_len, unit, hdrlen, mru, debug;
432 {
433     struct deflate_state *state = (struct deflate_state *) arg;
434
435     if (opt_len < CILEN_DEFLATE
436         || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
437         || options[1] != CILEN_DEFLATE
438         || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
439         || DEFLATE_SIZE(options[2]) != state->w_size
440         || options[3] != DEFLATE_CHK_SEQUENCE)
441         return 0;
442
443     state->seqno = 0;
444     state->unit = unit;
445     state->hdrlen = hdrlen;
446     state->debug = debug;
447     state->mru = mru;
448
449     inflateReset(&state->strm);
450
451     return 1;
452 }
453
454 static void
455 z_decomp_reset(arg)
456     void *arg;
457 {
458     struct deflate_state *state = (struct deflate_state *) arg;
459
460     state->seqno = 0;
461     inflateReset(&state->strm);
462 }
463
464 /*
465  * Decompress a Deflate-compressed packet.
466  *
467  * Because of patent problems, we return DECOMP_ERROR for errors
468  * found by inspecting the input data and for system problems, but
469  * DECOMP_FATALERROR for any errors which could possibly be said to
470  * be being detected "after" decompression.  For DECOMP_ERROR,
471  * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
472  * infringing a patent of Motorola's if we do, so we take CCP down
473  * instead.
474  *
475  * Given that the frame has the correct sequence number and a good FCS,
476  * errors such as invalid codes in the input most likely indicate a
477  * bug, so we return DECOMP_FATALERROR for them in order to turn off
478  * compression, even though they are detected by inspecting the input.
479  */
480 int
481 z_decompress(arg, mi, mop)
482     void *arg;
483     struct mbuf *mi, **mop;
484 {
485     struct deflate_state *state = (struct deflate_state *) arg;
486     struct mbuf *mo, *mo_head;
487     u_char *rptr, *wptr;
488     int rlen, olen, ospace;
489     int seq, i, flush, r, decode_proto;
490     u_char hdr[PPP_HDRLEN + DEFLATE_OVHD];
491
492     *mop = NULL;
493     rptr = mtod(mi, u_char *);
494     rlen = mi->m_len;
495     for (i = 0; i < PPP_HDRLEN + DEFLATE_OVHD; ++i) {
496         while (rlen <= 0) {
497             mi = mi->m_next;
498             if (mi == NULL)
499                 return DECOMP_ERROR;
500             rptr = mtod(mi, u_char *);
501             rlen = mi->m_len;
502         }
503         hdr[i] = *rptr++;
504         --rlen;
505     }
506
507     /* Check the sequence number. */
508     seq = (hdr[PPP_HDRLEN] << 8) + hdr[PPP_HDRLEN+1];
509     if (seq != state->seqno) {
510         if (state->debug)
511             printf("z_decompress%d: bad seq # %d, expected %d\n",
512                    state->unit, seq, state->seqno);
513         return DECOMP_ERROR;
514     }
515     ++state->seqno;
516
517     /* Allocate an output mbuf. */
518     MGETHDR(mo, M_DONTWAIT, MT_DATA);
519     if (mo == NULL)
520         return DECOMP_ERROR;
521     mo_head = mo;
522     mo->m_len = 0;
523     mo->m_next = NULL;
524     MCLGET(mo, M_DONTWAIT);
525     ospace = M_TRAILINGSPACE(mo);
526     if (state->hdrlen + PPP_HDRLEN < ospace) {
527         mo->m_data += state->hdrlen;
528         ospace -= state->hdrlen;
529     }
530
531     /*
532      * Fill in the first part of the PPP header.  The protocol field
533      * comes from the decompressed data.
534      */
535     wptr = mtod(mo, u_char *);
536     wptr[0] = PPP_ADDRESS(hdr);
537     wptr[1] = PPP_CONTROL(hdr);
538     wptr[2] = 0;
539
540     /*
541      * Set up to call inflate.  We set avail_out to 1 initially so we can
542      * look at the first byte of the output and decide whether we have
543      * a 1-byte or 2-byte protocol field.
544      */
545     state->strm.next_in = rptr;
546     state->strm.avail_in = rlen;
547     mi = mi->m_next;
548     flush = (mi == NULL)? Z_PACKET_FLUSH: Z_NO_FLUSH;
549     rlen += PPP_HDRLEN + DEFLATE_OVHD;
550     state->strm.next_out = wptr + 3;
551     state->strm.avail_out = 1;
552     decode_proto = 1;
553     olen = PPP_HDRLEN;
554
555     /*
556      * Call inflate, supplying more input or output as needed.
557      */
558     for (;;) {
559         r = inflate(&state->strm, flush);
560         if (r != Z_OK) {
561 #if !DEFLATE_DEBUG
562             if (state->debug)
563 #endif
564                 printf("z_decompress%d: inflate returned %d (%s)\n",
565                        state->unit, r, (state->strm.msg? state->strm.msg: ""));
566             m_freem(mo_head);
567             return DECOMP_FATALERROR;
568         }
569         if (flush != Z_NO_FLUSH && state->strm.avail_out != 0)
570             break;              /* all done */
571         if (state->strm.avail_in == 0 && mi != NULL) {
572             state->strm.next_in = mtod(mi, u_char *);
573             state->strm.avail_in = mi->m_len;
574             rlen += mi->m_len;
575             mi = mi->m_next;
576             if (mi == NULL)
577                 flush = Z_PACKET_FLUSH;
578         }
579         if (state->strm.avail_out == 0) {
580             if (decode_proto) {
581                 state->strm.avail_out = ospace - PPP_HDRLEN;
582                 if ((wptr[3] & 1) == 0) {
583                     /* 2-byte protocol field */
584                     wptr[2] = wptr[3];
585                     --state->strm.next_out;
586                     ++state->strm.avail_out;
587                     --olen;
588                 }
589                 decode_proto = 0;
590             } else {
591                 mo->m_len = ospace;
592                 olen += ospace;
593                 MGET(mo->m_next, M_DONTWAIT, MT_DATA);
594                 mo = mo->m_next;
595                 if (mo == NULL) {
596                     m_freem(mo_head);
597                     return DECOMP_ERROR;
598                 }
599                 MCLGET(mo, M_DONTWAIT);
600                 state->strm.next_out = mtod(mo, u_char *);
601                 state->strm.avail_out = ospace = M_TRAILINGSPACE(mo);
602             }
603         }
604     }
605     if (decode_proto) {
606         m_freem(mo_head);
607         return DECOMP_ERROR;
608     }
609     olen += (mo->m_len = ospace - state->strm.avail_out);
610 #if DEFLATE_DEBUG
611     if (olen > state->mru + PPP_HDRLEN)
612         printf("ppp_deflate%d: exceeded mru (%d > %d)\n",
613                state->unit, olen, state->mru + PPP_HDRLEN);
614 #endif
615
616     state->stats.unc_bytes += olen;
617     state->stats.unc_packets++;
618     state->stats.comp_bytes += rlen;
619     state->stats.comp_packets++;
620
621     *mop = mo_head;
622     return DECOMP_OK;
623 }
624
625 /*
626  * Incompressible data has arrived - add it to the history.
627  */
628 static void
629 z_incomp(arg, mi)
630     void *arg;
631     struct mbuf *mi;
632 {
633     struct deflate_state *state = (struct deflate_state *) arg;
634     u_char *rptr;
635     int rlen, proto, r;
636
637     /*
638      * Check that the protocol is one we handle.
639      */
640     rptr = mtod(mi, u_char *);
641     proto = PPP_PROTOCOL(rptr);
642     if (proto > 0x3fff || proto == 0xfd || proto == 0xfb)
643         return;
644
645     ++state->seqno;
646
647     /*
648      * Iterate through the mbufs, adding the characters in them
649      * to the decompressor's history.  For the first mbuf, we start
650      * at the either the 1st or 2nd byte of the protocol field,
651      * depending on whether the protocol value is compressible.
652      */
653     rlen = mi->m_len;
654     state->strm.next_in = rptr + 3;
655     state->strm.avail_in = rlen - 3;
656     if (proto > 0xff) {
657         --state->strm.next_in;
658         ++state->strm.avail_in;
659     }
660     for (;;) {
661         r = inflateIncomp(&state->strm);
662         if (r != Z_OK) {
663             /* gak! */
664 #if !DEFLATE_DEBUG
665             if (state->debug)
666 #endif
667                 printf("z_incomp%d: inflateIncomp returned %d (%s)\n",
668                        state->unit, r, (state->strm.msg? state->strm.msg: ""));
669             return;
670         }
671         mi = mi->m_next;
672         if (mi == NULL)
673             break;
674         state->strm.next_in = mtod(mi, u_char *);
675         state->strm.avail_in = mi->m_len;
676         rlen += mi->m_len;
677     }
678
679     /*
680      * Update stats.
681      */
682     state->stats.inc_bytes += rlen;
683     state->stats.inc_packets++;
684     state->stats.unc_bytes += rlen;
685     state->stats.unc_packets++;
686 }
687
688 #endif /* DO_DEFLATE */