Support PPP Deflate compression
authorPaul Mackerras <paulus@samba.org>
Thu, 18 Jan 1996 03:19:11 +0000 (03:19 +0000)
committerPaul Mackerras <paulus@samba.org>
Thu, 18 Jan 1996 03:19:11 +0000 (03:19 +0000)
modules/deflate.c [new file with mode: 0644]
modules/ppp_comp.c
netbsd-1.1/ppp-deflate.c [new file with mode: 0644]

diff --git a/modules/deflate.c b/modules/deflate.c
new file mode 100644 (file)
index 0000000..405b404
--- /dev/null
@@ -0,0 +1,653 @@
+/*
+ * ppp_deflate.c - interface the zlib procedures for Deflate compression
+ * and decompression (as used by gzip) to the PPP code.
+ * This version is for use with STREAMS under SunOS 4.x, Solaris 2,
+ * SVR4, OSF/1 and AIX 4.x.
+ *
+ * Copyright (c) 1994 The Australian National University.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, provided that the above copyright
+ * notice appears in all copies.  This software is provided without any
+ * warranty, express or implied. The Australian National University
+ * makes no representations about the suitability of this software for
+ * any purpose.
+ *
+ * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+ * THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
+ * OR MODIFICATIONS.
+ *
+ * $Id: deflate.c,v 1.1 1996/01/18 03:17:48 paulus Exp $
+ */
+
+#ifdef AIX4
+#include <net/net_globals.h>
+#endif
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stream.h>
+#include <net/ppp_defs.h>
+#include "ppp_mod.h"
+
+#define PACKETPTR      mblk_t *
+#include <net/ppp-comp.h>
+#include "common/zlib.h"
+
+#if DO_DEFLATE
+
+/*
+ * State for a Deflate (de)compressor.
+ */
+struct deflate_state {
+    int                seqno;
+    int                w_size;
+    int                unit;
+    int                hdrlen;
+    int                mru;
+    int                debug;
+    z_stream   strm;
+    struct compstat stats;
+};
+
+#define DEFLATE_OVHD   2               /* Deflate overhead/packet */
+
+static void    *zalloc __P((void *, u_int items, u_int size));
+static void    zfree __P((void *, void *ptr, u_int nb));
+static void    *z_comp_alloc __P((u_char *options, int opt_len));
+static void    *z_decomp_alloc __P((u_char *options, int opt_len));
+static void    z_comp_free __P((void *state));
+static void    z_decomp_free __P((void *state));
+static int     z_comp_init __P((void *state, u_char *options, int opt_len,
+                                int unit, int hdrlen, int debug));
+static int     z_decomp_init __P((void *state, u_char *options, int opt_len,
+                                    int unit, int hdrlen, int mru, int debug));
+static int     z_compress __P((void *state, mblk_t **mret,
+                                 mblk_t *mp, int slen, int maxolen));
+static void    z_incomp __P((void *state, mblk_t *dmsg));
+static int     z_decompress __P((void *state, mblk_t *cmp,
+                                   mblk_t **dmpp));
+static void    z_comp_reset __P((void *state));
+static void    z_decomp_reset __P((void *state));
+static void    z_comp_stats __P((void *state, struct compstat *stats));
+
+/*
+ * Procedures exported to if_ppp.c.
+ */
+struct compressor ppp_deflate = {
+    CI_DEFLATE,                        /* compress_proto */
+    z_comp_alloc,              /* comp_alloc */
+    z_comp_free,               /* comp_free */
+    z_comp_init,               /* comp_init */
+    z_comp_reset,              /* comp_reset */
+    z_compress,                        /* compress */
+    z_comp_stats,              /* comp_stat */
+    z_decomp_alloc,            /* decomp_alloc */
+    z_decomp_free,             /* decomp_free */
+    z_decomp_init,             /* decomp_init */
+    z_decomp_reset,            /* decomp_reset */
+    z_decompress,              /* decompress */
+    z_incomp,                  /* incomp */
+    z_comp_stats,              /* decomp_stat */
+};
+
+#define DECOMP_CHUNK   512
+
+/*
+ * Space allocation and freeing routines for use by zlib routines.
+ */
+void *
+zalloc(notused, items, size)
+    void *notused;
+    u_int items, size;
+{
+    return ALLOC_NOSLEEP(items * size);
+}
+
+void
+zfree(notused, ptr, nbytes)
+    void *notused;
+    void *ptr;
+    u_int nbytes;
+{
+    FREE(ptr, nbytes);
+}
+
+/*
+ * Allocate space for a compressor.
+ */
+static void *
+z_comp_alloc(options, opt_len)
+    u_char *options;
+    int opt_len;
+{
+    struct deflate_state *state;
+    int w_size;
+
+    if (opt_len != CILEN_DEFLATE || options[0] != CI_DEFLATE
+       || options[1] != CILEN_DEFLATE
+       || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
+       || options[3] != DEFLATE_CHK_SEQUENCE)
+       return NULL;
+    w_size = DEFLATE_SIZE(options[2]);
+    if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
+       return NULL;
+
+    state = (struct deflate_state *) ALLOC_NOSLEEP(sizeof(*state));
+    if (state == NULL)
+       return NULL;
+
+    state->strm.next_in = NULL;
+    state->strm.zalloc = zalloc;
+    state->strm.zfree = zfree;
+    if (deflateInit2(&state->strm, Z_DEFAULT_COMPRESSION, DEFLATE_METHOD_VAL,
+                    -w_size, 8, Z_DEFAULT_STRATEGY, DEFLATE_OVHD+2) != Z_OK) {
+       FREE(state, sizeof(*state));
+       return NULL;
+    }
+
+    state->w_size = w_size;
+    bzero(&state->stats, sizeof(state->stats));
+    return (void *) state;
+}
+
+static void
+z_comp_free(arg)
+    void *arg;
+{
+    struct deflate_state *state = (struct deflate_state *) arg;
+
+    deflateEnd(&state->strm);
+    FREE(state, sizeof(*state));
+}
+
+static int
+z_comp_init(arg, options, opt_len, unit, hdrlen, debug)
+    void *arg;
+    u_char *options;
+    int opt_len, unit, hdrlen, debug;
+{
+    struct deflate_state *state = (struct deflate_state *) arg;
+
+    if (opt_len < CILEN_DEFLATE || options[0] != CI_DEFLATE
+       || options[1] != CILEN_DEFLATE
+       || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
+       || DEFLATE_SIZE(options[2]) != state->w_size
+       || options[3] != DEFLATE_CHK_SEQUENCE)
+       return 0;
+
+    state->seqno = 0;
+    state->unit = unit;
+    state->hdrlen = hdrlen;
+    state->debug = debug;
+
+    deflateReset(&state->strm);
+
+    return 1;
+}
+
+static void
+z_comp_reset(arg)
+    void *arg;
+{
+    struct deflate_state *state = (struct deflate_state *) arg;
+
+    state->seqno = 0;
+    deflateReset(&state->strm);
+}
+
+int
+z_compress(arg, mret, mp, orig_len, maxolen)
+    void *arg;
+    mblk_t **mret;             /* compressed packet (out) */
+    mblk_t *mp;                /* uncompressed packet (in) */
+    int orig_len, maxolen;
+{
+    struct deflate_state *state = (struct deflate_state *) arg;
+    u_char *rptr, *wptr;
+    int proto, olen, wspace, r, flush;
+    mblk_t *m;
+
+    /*
+     * Check that the protocol is in the range we handle.
+     */
+    *mret = NULL;
+    rptr = mp->b_rptr;
+    if (rptr + PPP_HDRLEN > mp->b_wptr) {
+       if (!pullupmsg(mp, PPP_HDRLEN))
+           return 0;
+       rptr = mp->b_rptr;
+    }
+    proto = PPP_PROTOCOL(rptr);
+    if (proto > 0x3fff || proto == 0xfd || proto == 0xfb)
+       return orig_len;
+
+    /* Allocate one mblk initially. */
+    if (maxolen > orig_len)
+       maxolen = orig_len;
+    wspace = maxolen < 4096? maxolen: 4096;
+    m = allocb(wspace, BPRI_MED);
+    if (m != NULL) {
+       *mret = m;
+       if (state->hdrlen + PPP_HDRLEN + 2 < wspace) {
+           m->b_rptr += state->hdrlen;
+           m->b_wptr = m->b_rptr;
+           wspace -= state->hdrlen;
+       }
+       wptr = m->b_wptr;
+
+       /*
+        * Copy over the PPP header and store the 2-byte sequence number.
+        */
+       wptr[0] = PPP_ADDRESS(rptr);
+       wptr[1] = PPP_CONTROL(rptr);
+       wptr[2] = PPP_COMP >> 8;
+       wptr[3] = PPP_COMP;
+       wptr += PPP_HDRLEN;
+       wptr[0] = state->seqno >> 8;
+       wptr[1] = state->seqno;
+       wptr += 2;
+       state->strm.next_out = wptr;
+       state->strm.avail_out = wspace - (PPP_HDRLEN + 2);
+    } else {
+       state->strm.next_out = NULL;
+       state->strm.avail_out = 1000000;
+    }
+    ++state->seqno;
+
+    rptr += (proto > 0xff)? 2: 3;      /* skip 1st proto byte if 0 */
+    state->strm.next_in = rptr;
+    state->strm.avail_in = mp->b_wptr - rptr;
+    mp = mp->b_cont;
+    flush = (mp == NULL)? Z_PACKET_FLUSH: Z_NO_FLUSH;
+    olen = 0;
+    for (;;) {
+       r = deflate(&state->strm, flush);
+       if (r != Z_OK) {
+           printf("z_compress: deflate returned %d (%s)\n",
+                  r, (state->strm.msg? state->strm.msg: ""));
+           break;
+       }
+       if (flush != Z_NO_FLUSH && state->strm.avail_out != 0)
+           break;              /* all done */
+       if (state->strm.avail_in == 0 && mp != NULL) {
+           state->strm.next_in = mp->b_rptr;
+           state->strm.avail_in = mp->b_wptr - mp->b_rptr;
+           mp = mp->b_cont;
+           if (mp == NULL)
+               flush = Z_PACKET_FLUSH;
+       }
+       if (state->strm.avail_out == 0) {
+           if (m != NULL) {
+               m->b_wptr += wspace;
+               olen += wspace;
+               wspace = maxolen - olen;
+               if (wspace < 32)
+                   wspace = 32;
+               else if (wspace > 4096)
+                   wspace = 4096;
+               m->b_cont = allocb(wspace, BPRI_MED);
+               m = m->b_cont;
+               if (m != NULL) {
+                   state->strm.next_out = m->b_wptr;
+                   state->strm.avail_out = wspace;
+               }
+           }
+           if (m == NULL) {
+               state->strm.next_out = NULL;
+               state->strm.avail_out = 1000000;
+           }
+       }
+    }
+    m->b_wptr += wspace - state->strm.avail_out;
+    olen += wspace - state->strm.avail_out;
+
+    /*
+     * See if we managed to reduce the size of the packet.
+     * If the compressor just gave us a single zero byte, it means
+     * the packet was incompressible.
+     */
+    if (olen < orig_len && m != NULL
+       && !(olen == PPP_HDRLEN + 3 && *wptr == 0)) {
+       state->stats.comp_bytes += olen;
+       state->stats.comp_packets++;
+    } else {
+       if (*mret != NULL) {
+           freemsg(*mret);
+           *mret = NULL;
+       }
+       state->stats.inc_bytes += orig_len;
+       state->stats.inc_packets++;
+       olen = orig_len;
+    }
+    state->stats.unc_bytes += orig_len;
+    state->stats.unc_packets++;
+
+    return olen;
+}
+
+static void
+z_comp_stats(arg, stats)
+    void *arg;
+    struct compstat *stats;
+{
+    struct deflate_state *state = (struct deflate_state *) arg;
+    u_int out;
+
+    *stats = state->stats;
+    stats->ratio = stats->unc_bytes;
+    out = stats->comp_bytes + stats->unc_bytes;
+    if (stats->ratio <= 0x7ffffff)
+       stats->ratio <<= 8;
+    else
+       out >>= 8;
+    if (out != 0)
+       stats->ratio /= out;
+}
+
+/*
+ * Allocate space for a decompressor.
+ */
+static void *
+z_decomp_alloc(options, opt_len)
+    u_char *options;
+    int opt_len;
+{
+    struct deflate_state *state;
+    int w_size;
+
+    if (opt_len != CILEN_DEFLATE || options[0] != CI_DEFLATE
+       || options[1] != CILEN_DEFLATE
+       || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
+       || options[3] != DEFLATE_CHK_SEQUENCE)
+       return NULL;
+    w_size = DEFLATE_SIZE(options[2]);
+    if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
+       return NULL;
+
+    state = (struct deflate_state *) ALLOC_NOSLEEP(sizeof(*state));
+    if (state == NULL)
+       return NULL;
+
+    state->strm.next_out = NULL;
+    state->strm.zalloc = zalloc;
+    state->strm.zfree = zfree;
+    if (inflateInit2(&state->strm, -w_size) != Z_OK) {
+       FREE(state, sizeof(*state));
+       return NULL;
+    }
+
+    state->w_size = w_size;
+    bzero(&state->stats, sizeof(state->stats));
+    return (void *) state;
+}
+
+static void
+z_decomp_free(arg)
+    void *arg;
+{
+    struct deflate_state *state = (struct deflate_state *) arg;
+
+    inflateEnd(&state->strm);
+    FREE(state, sizeof(*state));
+}
+
+static int
+z_decomp_init(arg, options, opt_len, unit, hdrlen, mru, debug)
+    void *arg;
+    u_char *options;
+    int opt_len, unit, hdrlen, mru, debug;
+{
+    struct deflate_state *state = (struct deflate_state *) arg;
+
+    if (opt_len < CILEN_DEFLATE || options[0] != CI_DEFLATE
+       || options[1] != CILEN_DEFLATE
+       || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
+       || DEFLATE_SIZE(options[2]) != state->w_size
+       || options[3] != DEFLATE_CHK_SEQUENCE)
+       return 0;
+
+    state->seqno = 0;
+    state->unit = unit;
+    state->hdrlen = hdrlen;
+    state->debug = debug;
+    state->mru = mru;
+
+    inflateReset(&state->strm);
+
+    return 1;
+}
+
+static void
+z_decomp_reset(arg)
+    void *arg;
+{
+    struct deflate_state *state = (struct deflate_state *) arg;
+
+    state->seqno = 0;
+    inflateReset(&state->strm);
+}
+
+/*
+ * Decompress a Deflate-compressed packet.
+ *
+ * Because of patent problems, we return DECOMP_ERROR for errors
+ * found by inspecting the input data and for system problems, but
+ * DECOMP_FATALERROR for any errors which could possibly be said to
+ * be being detected "after" decompression.  For DECOMP_ERROR,
+ * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
+ * infringing a patent of Motorola's if we do, so we take CCP down
+ * instead.
+ *
+ * Given that the frame has the correct sequence number and a good FCS,
+ * errors such as invalid codes in the input most likely indicate a
+ * bug, so we return DECOMP_FATALERROR for them in order to turn off
+ * compression, even though they are detected by inspecting the input.
+ */
+int
+z_decompress(arg, mi, mop)
+    void *arg;
+    mblk_t *mi, **mop;
+{
+    struct deflate_state *state = (struct deflate_state *) arg;
+    mblk_t *mo, *mo_head;
+    u_char *rptr, *wptr;
+    int rlen, olen, ospace;
+    int seq, i, flush, r, decode_proto;
+    u_char hdr[PPP_HDRLEN + DEFLATE_OVHD];
+
+    *mop = NULL;
+    rptr = mi->b_rptr;
+    for (i = 0; i < PPP_HDRLEN + DEFLATE_OVHD; ++i) {
+       while (rptr >= mi->b_wptr) {
+           mi = mi->b_cont;
+           if (mi == NULL)
+               return DECOMP_ERROR;
+           rptr = mi->b_rptr;
+       }
+       hdr[i] = *rptr++;
+    }
+
+    /* Check the sequence number. */
+    seq = (hdr[PPP_HDRLEN] << 8) + hdr[PPP_HDRLEN+1];
+    if (seq != state->seqno) {
+       if (state->debug)
+           printf("z_decompress%d: bad seq # %d, expected %d\n",
+                  state->unit, seq, state->seqno);
+       return DECOMP_ERROR;
+    }
+    ++state->seqno;
+
+    /* Allocate an output message block. */
+    mo = allocb(DECOMP_CHUNK + state->hdrlen, BPRI_MED);
+    if (mo == NULL)
+       return DECOMP_ERROR;
+    mo_head = mo;
+    mo->b_cont = NULL;
+    mo->b_rptr += state->hdrlen;
+    mo->b_wptr = wptr = mo->b_rptr;
+    ospace = DECOMP_CHUNK;
+
+    /*
+     * Fill in the first part of the PPP header.  The protocol field
+     * comes from the decompressed data.
+     */
+    wptr[0] = PPP_ADDRESS(hdr);
+    wptr[1] = PPP_CONTROL(hdr);
+    wptr[2] = 0;
+
+    /*
+     * Set up to call inflate.  We set avail_out to 1 initially so we can
+     * look at the first byte of the output and decide whether we have
+     * a 1-byte or 2-byte protocol field.
+     */
+    state->strm.next_in = rptr;
+    state->strm.avail_in = mi->b_wptr - rptr;
+    mi = mi->b_cont;
+    flush = (mi == NULL)? Z_PACKET_FLUSH: Z_NO_FLUSH;
+    rlen = state->strm.avail_in + PPP_HDRLEN + DEFLATE_OVHD;
+    state->strm.next_out = wptr + 3;
+    state->strm.avail_out = 1;
+    decode_proto = 1;
+    olen = PPP_HDRLEN;
+
+    /*
+     * Call inflate, supplying more input or output as needed.
+     */
+    for (;;) {
+       r = inflate(&state->strm, flush);
+       if (r != Z_OK) {
+           if (state->debug)
+               printf("z_decompress%d: inflate returned %d (%s)\n",
+                      state->unit, r, (state->strm.msg? state->strm.msg: ""));
+           freemsg(mo_head);
+           return DECOMP_FATALERROR;
+       }
+       if (flush != Z_NO_FLUSH && state->strm.avail_out != 0)
+           break;              /* all done */
+       if (state->strm.avail_in == 0 && mi != NULL) {
+           state->strm.next_in = mi->b_rptr;
+           state->strm.avail_in = mi->b_wptr - mi->b_rptr;
+           rlen += state->strm.avail_in;
+           mi = mi->b_cont;
+           if (mi == NULL)
+               flush = Z_PACKET_FLUSH;
+       }
+       if (state->strm.avail_out == 0) {
+           if (decode_proto) {
+               state->strm.avail_out = ospace - PPP_HDRLEN;
+               if ((wptr[3] & 1) == 0) {
+                   /* 2-byte protocol field */
+                   wptr[2] = wptr[3];
+                   --state->strm.next_out;
+                   ++state->strm.avail_out;
+                   --olen;
+               }
+               decode_proto = 0;
+           } else {
+               mo->b_wptr += ospace;
+               olen += ospace;
+               mo->b_cont = allocb(DECOMP_CHUNK, BPRI_MED);
+               mo = mo->b_cont;
+               if (mo == NULL) {
+                   freemsg(mo_head);
+                   return DECOMP_ERROR;
+               }
+               state->strm.next_out = mo->b_rptr;
+               state->strm.avail_out = ospace = DECOMP_CHUNK;
+           }
+       }
+    }
+    if (decode_proto) {
+       freemsg(mo_head);
+       return DECOMP_ERROR;
+    }
+    mo->b_wptr += ospace - state->strm.avail_out;
+    olen += ospace - state->strm.avail_out;
+
+    state->stats.unc_bytes += olen;
+    state->stats.unc_packets++;
+    state->stats.comp_bytes += rlen;
+    state->stats.comp_packets++;
+
+    *mop = mo_head;
+    return DECOMP_OK;
+}
+
+/*
+ * Incompressible data has arrived - add it to the history.
+ */
+static void
+z_incomp(arg, mi)
+    void *arg;
+    mblk_t *mi;
+{
+    struct deflate_state *state = (struct deflate_state *) arg;
+    u_char *rptr;
+    int rlen, proto, r;
+
+    /*
+     * Check that the protocol is one we handle.
+     */
+    rptr = mi->b_rptr;
+    if (rptr + PPP_HDRLEN > mi->b_wptr) {
+       if (!pullupmsg(mi, PPP_HDRLEN))
+           return;
+       rptr = mi->b_rptr;
+    }
+    proto = PPP_PROTOCOL(rptr);
+    if (proto > 0x3fff || proto == 0xfd || proto == 0xfb)
+       return;
+
+    ++state->seqno;
+
+    /*
+     * Iterate through the message blocks, adding the characters in them
+     * to the decompressor's history.  For the first block, we start
+     * at the either the 1st or 2nd byte of the protocol field,
+     * depending on whether the protocol value is compressible.
+     */
+    rlen = mi->b_wptr - mi->b_rptr;
+    state->strm.next_in = rptr + 3;
+    state->strm.avail_in = rlen - 3;
+    if (proto > 0xff) {
+       --state->strm.next_in;
+       ++state->strm.avail_in;
+    }
+    for (;;) {
+       r = inflateIncomp(&state->strm);
+       if (r != Z_OK) {
+           /* gak! */
+           if (state->debug) {
+               printf("z_incomp%d: inflateIncomp returned %d (%s)\n",
+                      state->unit, r, (state->strm.msg? state->strm.msg: ""));
+           }
+           return;
+       }
+       mi = mi->b_cont;
+       if (mi == NULL)
+           break;
+       state->strm.next_in = mi->b_rptr;
+       state->strm.avail_in = mi->b_wptr - mi->b_rptr;
+       rlen += state->strm.avail_in;
+    }
+
+    /*
+     * Update stats.
+     */
+    state->stats.inc_bytes += rlen;
+    state->stats.inc_packets++;
+    state->stats.unc_bytes += rlen;
+    state->stats.unc_packets++;
+}
+
+#endif /* DO_DEFLATE */
index 3795647c3d94c7f6c975fb142d296fb3e1096e2c..215830eeaa7166dbf048ece6d0c7d048e2d8428a 100644 (file)
@@ -24,7 +24,7 @@
  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
  * OR MODIFICATIONS.
  *
- * $Id: ppp_comp.c,v 1.1 1995/12/11 05:06:43 paulus Exp $
+ * $Id: ppp_comp.c,v 1.2 1996/01/18 03:18:07 paulus Exp $
  */
 
 /*
@@ -120,10 +120,14 @@ typedef struct comp_state {
  */
 
 extern struct compressor ppp_bsd_compress;
+extern struct compressor ppp_deflate;
 
 struct compressor *ppp_compressors[] = {
 #if DO_BSD_COMPRESS
     &ppp_bsd_compress,
+#endif
+#if DO_DEFLATE
+    &ppp_deflate,
 #endif
     NULL
 };
diff --git a/netbsd-1.1/ppp-deflate.c b/netbsd-1.1/ppp-deflate.c
new file mode 100644 (file)
index 0000000..425d2d2
--- /dev/null
@@ -0,0 +1,684 @@
+/*
+ * ppp_deflate.c - interface the zlib procedures for Deflate compression
+ * and decompression (as used by gzip) to the PPP code.
+ * This version is for use with mbufs on BSD-derived systems.
+ *
+ * Copyright (c) 1994 The Australian National University.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, provided that the above copyright
+ * notice appears in all copies.  This software is provided without any
+ * warranty, express or implied. The Australian National University
+ * makes no representations about the suitability of this software for
+ * any purpose.
+ *
+ * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+ * THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
+ * OR MODIFICATIONS.
+ *
+ * $Id: ppp-deflate.c,v 1.1 1996/01/18 03:19:11 paulus Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/mbuf.h>
+#include <net/ppp_defs.h>
+
+#define PACKETPTR      struct mbuf *
+#include <net/ppp-comp.h>
+#include "common/zlib.h"
+
+#if DO_DEFLATE
+
+/*
+ * State for a Deflate (de)compressor.
+ */
+struct deflate_state {
+    int                seqno;
+    int                w_size;
+    int                unit;
+    int                hdrlen;
+    int                mru;
+    int                debug;
+    z_stream   strm;
+    struct compstat stats;
+};
+
+#define DEFLATE_OVHD   2               /* Deflate overhead/packet */
+
+static void    *zalloc __P((void *, u_int items, u_int size));
+static void    zfree __P((void *, void *ptr, u_int nb));
+static void    *z_comp_alloc __P((u_char *options, int opt_len));
+static void    *z_decomp_alloc __P((u_char *options, int opt_len));
+static void    z_comp_free __P((void *state));
+static void    z_decomp_free __P((void *state));
+static int     z_comp_init __P((void *state, u_char *options, int opt_len,
+                                int unit, int hdrlen, int debug));
+static int     z_decomp_init __P((void *state, u_char *options, int opt_len,
+                                    int unit, int hdrlen, int mru, int debug));
+static int     z_compress __P((void *state, struct mbuf **mret,
+                                 struct mbuf *mp, int slen, int maxolen));
+static void    z_incomp __P((void *state, struct mbuf *dmsg));
+static int     z_decompress __P((void *state, struct mbuf *cmp,
+                                   struct mbuf **dmpp));
+static void    z_comp_reset __P((void *state));
+static void    z_decomp_reset __P((void *state));
+static void    z_comp_stats __P((void *state, struct compstat *stats));
+
+/*
+ * Procedures exported to if_ppp.c.
+ */
+struct compressor ppp_deflate = {
+    CI_DEFLATE,                        /* compress_proto */
+    z_comp_alloc,              /* comp_alloc */
+    z_comp_free,               /* comp_free */
+    z_comp_init,               /* comp_init */
+    z_comp_reset,              /* comp_reset */
+    z_compress,                        /* compress */
+    z_comp_stats,              /* comp_stat */
+    z_decomp_alloc,            /* decomp_alloc */
+    z_decomp_free,             /* decomp_free */
+    z_decomp_init,             /* decomp_init */
+    z_decomp_reset,            /* decomp_reset */
+    z_decompress,              /* decompress */
+    z_incomp,                  /* incomp */
+    z_comp_stats,              /* decomp_stat */
+};
+
+/*
+ * Space allocation and freeing routines for use by zlib routines.
+ */
+void *
+zalloc(notused, items, size)
+    void *notused;
+    u_int items, size;
+{
+    void *ptr;
+
+    MALLOC(ptr, void *, items * size, M_DEVBUF, M_NOWAIT);
+    return ptr;
+}
+
+void
+zfree(notused, ptr, nbytes)
+    void *notused;
+    void *ptr;
+    u_int nbytes;
+{
+    FREE(ptr, M_DEVBUF);
+}
+
+/*
+ * Allocate space for a compressor.
+ */
+static void *
+z_comp_alloc(options, opt_len)
+    u_char *options;
+    int opt_len;
+{
+    struct deflate_state *state;
+    int w_size;
+
+    if (opt_len != CILEN_DEFLATE || options[0] != CI_DEFLATE
+       || options[1] != CILEN_DEFLATE
+       || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
+       || options[3] != DEFLATE_CHK_SEQUENCE)
+       return NULL;
+    w_size = DEFLATE_SIZE(options[2]);
+    if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
+       return NULL;
+
+    MALLOC(state, struct deflate_state *, sizeof(struct deflate_state),
+          M_DEVBUF, M_NOWAIT);
+    if (state == NULL)
+       return NULL;
+
+    state->strm.next_in = NULL;
+    state->strm.zalloc = zalloc;
+    state->strm.zfree = zfree;
+    if (deflateInit2(&state->strm, Z_DEFAULT_COMPRESSION, DEFLATE_METHOD_VAL,
+                    -w_size, 8, Z_DEFAULT_STRATEGY, DEFLATE_OVHD+2) != Z_OK) {
+       FREE(state, M_DEVBUF);
+       return NULL;
+    }
+
+    state->w_size = w_size;
+    bzero(&state->stats, sizeof(state->stats));
+    return (void *) state;
+}
+
+static void
+z_comp_free(arg)
+    void *arg;
+{
+    struct deflate_state *state = (struct deflate_state *) arg;
+
+    deflateEnd(&state->strm);
+    FREE(state, M_DEVBUF);
+}
+
+static int
+z_comp_init(arg, options, opt_len, unit, hdrlen, debug)
+    void *arg;
+    u_char *options;
+    int opt_len, unit, hdrlen, debug;
+{
+    struct deflate_state *state = (struct deflate_state *) arg;
+
+    if (opt_len < CILEN_DEFLATE || options[0] != CI_DEFLATE
+       || options[1] != CILEN_DEFLATE
+       || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
+       || DEFLATE_SIZE(options[2]) != state->w_size
+       || options[3] != DEFLATE_CHK_SEQUENCE)
+       return 0;
+
+    state->seqno = 0;
+    state->unit = unit;
+    state->hdrlen = hdrlen;
+    state->debug = debug;
+
+    deflateReset(&state->strm);
+
+    return 1;
+}
+
+static void
+z_comp_reset(arg)
+    void *arg;
+{
+    struct deflate_state *state = (struct deflate_state *) arg;
+
+    state->seqno = 0;
+    deflateReset(&state->strm);
+}
+
+int
+z_compress(arg, mret, mp, orig_len, maxolen)
+    void *arg;
+    struct mbuf **mret;                /* compressed packet (out) */
+    struct mbuf *mp;           /* uncompressed packet (in) */
+    int orig_len, maxolen;
+{
+    struct deflate_state *state = (struct deflate_state *) arg;
+    u_char *rptr, *wptr, *wp0;
+    int proto, olen, wspace, r, flush;
+    struct mbuf *m;
+
+    /*
+     * Check that the protocol is in the range we handle.
+     */
+    rptr = mtod(mp, u_char *);
+    proto = PPP_PROTOCOL(rptr);
+    if (proto > 0x3fff || proto == 0xfd || proto == 0xfb) {
+       *mret = NULL;
+       return orig_len;
+    }
+
+    if (state->debug)
+       printf("z_comp%d: pkt in len=%d proto=%x seq=%d\n",
+              state->unit, orig_len, proto, state->seqno);
+    /* Allocate one mbuf initially. */
+    if (maxolen > orig_len)
+       maxolen = orig_len;
+    MGET(m, M_DONTWAIT, MT_DATA);
+    *mret = m;
+    if (m != NULL) {
+       m->m_len = 0;
+       if (maxolen + state->hdrlen > MLEN)
+           MCLGET(m, M_DONTWAIT);
+       wspace = M_TRAILINGSPACE(m);
+       if (state->hdrlen + PPP_HDRLEN + 2 < wspace) {
+           m->m_data += state->hdrlen;
+           wspace -= state->hdrlen;
+       }
+       wptr = mtod(m, u_char *);
+
+       /*
+        * Copy over the PPP header and store the 2-byte sequence number.
+        */
+       wptr[0] = PPP_ADDRESS(rptr);
+       wptr[1] = PPP_CONTROL(rptr);
+       wptr[2] = PPP_COMP >> 8;
+       wptr[3] = PPP_COMP;
+       wptr += PPP_HDRLEN;
+       wptr[0] = state->seqno >> 8;
+       wptr[1] = state->seqno;
+       wptr += 2;
+       state->strm.next_out = wptr;
+       state->strm.avail_out = wspace - (PPP_HDRLEN + 2);
+    } else {
+       state->strm.next_out = NULL;
+       state->strm.avail_out = 1000000;
+    }
+    ++state->seqno;
+
+    rptr += (proto > 0xff)? 2: 3;      /* skip 1st proto byte if 0 */
+    state->strm.next_in = rptr;
+    state->strm.avail_in = mtod(mp, u_char *) + mp->m_len - rptr;
+    mp = mp->m_next;
+    flush = (mp == NULL)? Z_PACKET_FLUSH: Z_NO_FLUSH;
+    olen = 0;
+    for (;;) {
+       if (state->debug) {
+           wp0 = state->strm.next_in;
+           printf("z_comp%d: deflate flush=%d in=%d[%x %x %x %x]\n",
+                  state->unit, flush, state->strm.avail_in,
+                  wp0[0], wp0[1], wp0[2], wp0[3]);
+           wp0 = state->strm.next_out;
+       }
+       r = deflate(&state->strm, flush);
+       if (state->debug) {
+           printf("z_comp%d: ret %d inleft=%d gen %d[%x %x %x %x]\n",
+                  state->unit, r, state->strm.avail_in,
+                  state->strm.next_out - wp0, wp0[0], wp0[1], wp0[2], wp0[3]);
+       }
+       if (r != Z_OK) {
+           printf("z_compress: deflate returned %d (%s)\n",
+                  r, (state->strm.msg? state->strm.msg: ""));
+           break;
+       }
+       if (flush != Z_NO_FLUSH && state->strm.avail_out != 0)
+           break;              /* all done */
+       if (state->strm.avail_in == 0 && mp != NULL) {
+           state->strm.next_in = mtod(mp, u_char *);
+           state->strm.avail_in = mp->m_len;
+           mp = mp->m_next;
+           if (mp == NULL)
+               flush = Z_PACKET_FLUSH;
+       }
+       if (state->strm.avail_out == 0) {
+           if (m != NULL) {
+               m->m_len = wspace;
+               olen += wspace;
+               MGET(m->m_next, M_DONTWAIT, MT_DATA);
+               m = m->m_next;
+               if (m != NULL) {
+                   m->m_len = 0;
+                   if (maxolen - olen > MLEN)
+                       MCLGET(m, M_DONTWAIT);
+                   state->strm.next_out = mtod(m, u_char *);
+                   state->strm.avail_out = wspace = M_TRAILINGSPACE(m);
+               }
+           }
+           if (m == NULL) {
+               state->strm.next_out = NULL;
+               state->strm.avail_out = 1000000;
+           }
+       }
+    }
+    olen += (m->m_len = wspace - state->strm.avail_out);
+
+    /*
+     * See if we managed to reduce the size of the packet.
+     * If the compressor just gave us a single zero byte, it means
+     * the packet was incompressible.
+     */
+    if (olen < orig_len && m != NULL
+       && !(olen == PPP_HDRLEN + 3 && *wptr == 0)) {
+       state->stats.comp_bytes += olen;
+       state->stats.comp_packets++;
+    } else {
+       if (*mret != NULL) {
+           m_freem(*mret);
+           *mret = NULL;
+       }
+       state->stats.inc_bytes += orig_len;
+       state->stats.inc_packets++;
+       olen = orig_len;
+    }
+    state->stats.unc_bytes += orig_len;
+    state->stats.unc_packets++;
+
+    return olen;
+}
+
+static void
+z_comp_stats(arg, stats)
+    void *arg;
+    struct compstat *stats;
+{
+    struct deflate_state *state = (struct deflate_state *) arg;
+    u_int out;
+
+    *stats = state->stats;
+    stats->ratio = stats->unc_bytes;
+    out = stats->comp_bytes + stats->unc_bytes;
+    if (stats->ratio <= 0x7ffffff)
+       stats->ratio <<= 8;
+    else
+       out >>= 8;
+    if (out != 0)
+       stats->ratio /= out;
+}
+
+/*
+ * Allocate space for a decompressor.
+ */
+static void *
+z_decomp_alloc(options, opt_len)
+    u_char *options;
+    int opt_len;
+{
+    struct deflate_state *state;
+    int w_size;
+
+    if (opt_len != CILEN_DEFLATE || options[0] != CI_DEFLATE
+       || options[1] != CILEN_DEFLATE
+       || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
+       || options[3] != DEFLATE_CHK_SEQUENCE)
+       return NULL;
+    w_size = DEFLATE_SIZE(options[2]);
+    if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
+       return NULL;
+
+    MALLOC(state, struct deflate_state *, sizeof(struct deflate_state),
+          M_DEVBUF, M_NOWAIT);
+    if (state == NULL)
+       return NULL;
+
+    state->strm.next_out = NULL;
+    state->strm.zalloc = zalloc;
+    state->strm.zfree = zfree;
+    if (inflateInit2(&state->strm, -w_size) != Z_OK) {
+       FREE(state, M_DEVBUF);
+       return NULL;
+    }
+
+    state->w_size = w_size;
+    bzero(&state->stats, sizeof(state->stats));
+    return (void *) state;
+}
+
+static void
+z_decomp_free(arg)
+    void *arg;
+{
+    struct deflate_state *state = (struct deflate_state *) arg;
+
+    inflateEnd(&state->strm);
+    FREE(state, M_DEVBUF);
+}
+
+static int
+z_decomp_init(arg, options, opt_len, unit, hdrlen, mru, debug)
+    void *arg;
+    u_char *options;
+    int opt_len, unit, hdrlen, mru, debug;
+{
+    struct deflate_state *state = (struct deflate_state *) arg;
+
+    if (opt_len < CILEN_DEFLATE || options[0] != CI_DEFLATE
+       || options[1] != CILEN_DEFLATE
+       || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
+       || DEFLATE_SIZE(options[2]) != state->w_size
+       || options[3] != DEFLATE_CHK_SEQUENCE)
+       return 0;
+
+    state->seqno = 0;
+    state->unit = unit;
+    state->hdrlen = hdrlen;
+    state->debug = debug;
+    state->mru = mru;
+
+    inflateReset(&state->strm);
+
+    return 1;
+}
+
+static void
+z_decomp_reset(arg)
+    void *arg;
+{
+    struct deflate_state *state = (struct deflate_state *) arg;
+
+    state->seqno = 0;
+    inflateReset(&state->strm);
+}
+
+/*
+ * Decompress a Deflate-compressed packet.
+ *
+ * Because of patent problems, we return DECOMP_ERROR for errors
+ * found by inspecting the input data and for system problems, but
+ * DECOMP_FATALERROR for any errors which could possibly be said to
+ * be being detected "after" decompression.  For DECOMP_ERROR,
+ * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
+ * infringing a patent of Motorola's if we do, so we take CCP down
+ * instead.
+ *
+ * Given that the frame has the correct sequence number and a good FCS,
+ * errors such as invalid codes in the input most likely indicate a
+ * bug, so we return DECOMP_FATALERROR for them in order to turn off
+ * compression, even though they are detected by inspecting the input.
+ */
+int
+z_decompress(arg, mi, mop)
+    void *arg;
+    struct mbuf *mi, **mop;
+{
+    struct deflate_state *state = (struct deflate_state *) arg;
+    struct mbuf *mo, *mo_head;
+    u_char *rptr, *wptr, *wp0;
+    int rlen, olen, ospace;
+    int seq, i, flush, r, decode_proto;
+    u_char hdr[PPP_HDRLEN + DEFLATE_OVHD];
+
+    *mop = NULL;
+    rptr = mtod(mi, u_char *);
+    rlen = mi->m_len;
+    for (i = 0; i < PPP_HDRLEN + DEFLATE_OVHD; ++i) {
+       while (rlen <= 0) {
+           mi = mi->m_next;
+           if (mi == NULL)
+               return DECOMP_ERROR;
+           rptr = mtod(mi, u_char *);
+           rlen = mi->m_len;
+       }
+       hdr[i] = *rptr++;
+       --rlen;
+    }
+
+    /* Check the sequence number. */
+    seq = (hdr[PPP_HDRLEN] << 8) + hdr[PPP_HDRLEN+1];
+    if (seq != state->seqno) {
+       if (state->debug)
+           printf("z_decompress%d: bad seq # %d, expected %d\n",
+                  state->unit, seq, state->seqno);
+       return DECOMP_ERROR;
+    }
+    ++state->seqno;
+
+    if (state->debug) {
+       struct mbuf *x;
+       int l = rlen;
+
+       for (x = mi; (x = x->m_next) != NULL; )
+           l += x->m_len;
+       printf("z_decomp%d: pkt in len=%d seq=%d\n", state->unit, l, seq);
+    }
+    /* Allocate an output mbuf. */
+    MGETHDR(mo, M_DONTWAIT, MT_DATA);
+    if (mo == NULL)
+       return DECOMP_ERROR;
+    mo_head = mo;
+    mo->m_len = 0;
+    mo->m_next = NULL;
+    MCLGET(mo, M_DONTWAIT);
+    ospace = M_TRAILINGSPACE(mo);
+    if (state->hdrlen + PPP_HDRLEN < ospace) {
+       mo->m_data += state->hdrlen;
+       ospace -= state->hdrlen;
+    }
+
+    /*
+     * Fill in the first part of the PPP header.  The protocol field
+     * comes from the decompressed data.
+     */
+    wptr = mtod(mo, u_char *);
+    wptr[0] = PPP_ADDRESS(hdr);
+    wptr[1] = PPP_CONTROL(hdr);
+    wptr[2] = 0;
+
+    /*
+     * Set up to call inflate.  We set avail_out to 1 initially so we can
+     * look at the first byte of the output and decide whether we have
+     * a 1-byte or 2-byte protocol field.
+     */
+    state->strm.next_in = rptr;
+    state->strm.avail_in = rlen;
+    mi = mi->m_next;
+    flush = (mi == NULL)? Z_PACKET_FLUSH: Z_NO_FLUSH;
+    rlen += PPP_HDRLEN + DEFLATE_OVHD;
+    state->strm.next_out = wptr + 3;
+    state->strm.avail_out = 1;
+    decode_proto = 1;
+    olen = PPP_HDRLEN;
+
+    /*
+     * Call inflate, supplying more input or output as needed.
+     */
+    for (;;) {
+       if (state->debug) {
+           wp0 = state->strm.next_in;
+           printf("z_decomp%d: inflate flush=%d in=%d[%x %x %x %x]\n",
+                  state->unit, flush, state->strm.avail_in,
+                  wp0[0], wp0[1], wp0[2], wp0[3]);
+           wp0 = state->strm.next_out;
+       }
+       r = inflate(&state->strm, flush);
+       if (state->debug) {
+           printf("z_decomp%d: ret %d inleft=%d gen %d[%x %x %x %x]\n",
+                  state->unit, r, state->strm.avail_in,
+                  state->strm.next_out - wp0, wp0[0], wp0[1], wp0[2], wp0[3]);
+       }
+       if (r != Z_OK) {
+           if (state->debug)
+               printf("z_decompress%d: inflate returned %d (%s)\n",
+                      state->unit, r, (state->strm.msg? state->strm.msg: ""));
+           m_freem(mo_head);
+           return DECOMP_FATALERROR;
+       }
+       if (flush != Z_NO_FLUSH && state->strm.avail_out != 0)
+           break;              /* all done */
+       if (state->strm.avail_in == 0 && mi != NULL) {
+           state->strm.next_in = mtod(mi, u_char *);
+           state->strm.avail_in = mi->m_len;
+           rlen += mi->m_len;
+           mi = mi->m_next;
+           if (mi == NULL)
+               flush = Z_PACKET_FLUSH;
+       }
+       if (state->strm.avail_out == 0) {
+           if (decode_proto) {
+               state->strm.avail_out = ospace - PPP_HDRLEN;
+               if ((wptr[3] & 1) == 0) {
+                   /* 2-byte protocol field */
+                   wptr[2] = wptr[3];
+                   --state->strm.next_out;
+                   ++state->strm.avail_out;
+                   --olen;
+               }
+               decode_proto = 0;
+           } else {
+               mo->m_len = ospace;
+               olen += ospace;
+               MGET(mo->m_next, M_DONTWAIT, MT_DATA);
+               mo = mo->m_next;
+               if (mo == NULL) {
+                   m_freem(mo_head);
+                   return DECOMP_ERROR;
+               }
+               MCLGET(mo, M_DONTWAIT);
+               state->strm.next_out = mtod(mo, u_char *);
+               state->strm.avail_out = ospace = M_TRAILINGSPACE(mo);
+           }
+       }
+    }
+    if (decode_proto) {
+       m_freem(mo_head);
+       return DECOMP_ERROR;
+    }
+    olen += (mo->m_len = ospace - state->strm.avail_out);
+
+    state->stats.unc_bytes += olen;
+    state->stats.unc_packets++;
+    state->stats.comp_bytes += rlen;
+    state->stats.comp_packets++;
+
+    *mop = mo_head;
+    return DECOMP_OK;
+}
+
+/*
+ * Incompressible data has arrived - add it to the history.
+ */
+static void
+z_incomp(arg, mi)
+    void *arg;
+    struct mbuf *mi;
+{
+    struct deflate_state *state = (struct deflate_state *) arg;
+    u_char *rptr;
+    int rlen, proto, r;
+
+    /*
+     * Check that the protocol is one we handle.
+     */
+    rptr = mtod(mi, u_char *);
+    proto = PPP_PROTOCOL(rptr);
+    if (proto > 0x3fff || proto == 0xfd || proto == 0xfb)
+       return;
+
+    ++state->seqno;
+
+    /*
+     * Iterate through the mbufs, adding the characters in them
+     * to the decompressor's history.  For the first mbuf, we start
+     * at the either the 1st or 2nd byte of the protocol field,
+     * depending on whether the protocol value is compressible.
+     */
+    rlen = mi->m_len;
+    state->strm.next_in = rptr + 3;
+    state->strm.avail_in = rlen - 3;
+    if (proto > 0xff) {
+       --state->strm.next_in;
+       ++state->strm.avail_in;
+    }
+    for (;;) {
+       r = inflateIncomp(&state->strm);
+       if (r != Z_OK) {
+           /* gak! */
+           if (state->debug) {
+               printf("z_incomp%d: inflateIncomp returned %d (%s)\n",
+                      state->unit, r, (state->strm.msg? state->strm.msg: ""));
+           }
+           return;
+       }
+       mi = mi->m_next;
+       if (mi == NULL)
+           break;
+       state->strm.next_in = mtod(mi, u_char *);
+       state->strm.avail_in = mi->m_len;
+       rlen += mi->m_len;
+    }
+
+    /*
+     * Update stats.
+     */
+    state->stats.inc_bytes += rlen;
+    state->stats.inc_packets++;
+    state->stats.unc_bytes += rlen;
+    state->stats.unc_packets++;
+}
+
+#endif /* DO_DEFLATE */