]> git.ozlabs.org Git - ppp.git/blobdiff - modules/deflate.c
Install Microsoft dictionaries (patch from Frank Cusack)
[ppp.git] / modules / deflate.c
index 57294a9503a94215d1682f7253733c7f512669ba..f77f6eb657dfbca1a932961677f6357d853bcc18 100644 (file)
@@ -27,7 +27,7 @@
  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
  * OR MODIFICATIONS.
  *
- * $Id: deflate.c,v 1.2 1996/04/04 02:44:56 paulus Exp $
+ * $Id: deflate.c,v 1.10 2001/03/09 01:03:50 paulus Exp $
  */
 
 #ifdef AIX4
 
 #define PACKETPTR      mblk_t *
 #include <net/ppp-comp.h>
-#include "common/zlib.h"
+
+#ifdef __osf__
+#include "zlib.h"
+#else
+#include "../common/zlib.h"
+#endif
 
 #if DO_DEFLATE
 
+#define DEFLATE_DEBUG  1
+
 /*
  * State for a Deflate (de)compressor.
  */
@@ -61,8 +68,9 @@ struct deflate_state {
 
 #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_alloc __P((void *, u_int items, u_int size));
+static void    *z_alloc_init __P((void *, u_int items, u_int size));
+static void    z_free __P((void *, void *ptr));
 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));
@@ -81,7 +89,7 @@ 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.
+ * Procedures exported to ppp_comp.c.
  */
 struct compressor ppp_deflate = {
     CI_DEFLATE,                        /* compress_proto */
@@ -100,26 +108,80 @@ struct compressor ppp_deflate = {
     z_comp_stats,              /* decomp_stat */
 };
 
+struct compressor ppp_deflate_draft = {
+    CI_DEFLATE_DRAFT,          /* 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.
  */
+struct zchunk {
+    u_int      size;
+    u_int      guard;
+};
+
+#define GUARD_MAGIC    0x77a6011a
+
+static void *
+z_alloc_init(notused, items, size)
+    void *notused;
+    u_int items, size;
+{
+    struct zchunk *z;
+
+    size = items * size + sizeof(struct zchunk);
+#ifdef __osf__
+    z = (struct zchunk *) ALLOC_SLEEP(size);
+#else
+    z = (struct zchunk *) ALLOC_NOSLEEP(size);
+#endif
+    z->size = size;
+    z->guard = GUARD_MAGIC;
+    return (void *) (z + 1);
+}
+
 static void *
-zalloc(notused, items, size)
+z_alloc(notused, items, size)
     void *notused;
     u_int items, size;
 {
-    return ALLOC_NOSLEEP(items * size);
+    struct zchunk *z;
+
+    size = items * size + sizeof(struct zchunk);
+    z = (struct zchunk *) ALLOC_NOSLEEP(size);
+    z->size = size;
+    z->guard = GUARD_MAGIC;
+    return (void *) (z + 1);
 }
 
 static void
-zfree(notused, ptr, nbytes)
+z_free(notused, ptr)
     void *notused;
     void *ptr;
-    u_int nbytes;
 {
-    FREE(ptr, nbytes);
+    struct zchunk *z = ((struct zchunk *) ptr) - 1;
+
+    if (z->guard != GUARD_MAGIC) {
+       printf("ppp: z_free of corrupted chunk at %x (%x, %x)\n",
+              z, z->size, z->guard);
+       return;
+    }
+    FREE(z, z->size);
 }
 
 /*
@@ -133,28 +195,40 @@ z_comp_alloc(options, opt_len)
     struct deflate_state *state;
     int w_size;
 
-    if (opt_len != CILEN_DEFLATE || options[0] != CI_DEFLATE
+    if (opt_len != CILEN_DEFLATE
+       || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
        || 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)
+    /*
+     * N.B. the 9 below should be DEFLATE_MIN_SIZE (8), but using
+     * 8 will cause kernel crashes because of a bug in zlib.
+     */
+    if (w_size < 9 || w_size > DEFLATE_MAX_SIZE)
        return NULL;
 
+
+#ifdef __osf__
+    state = (struct deflate_state *) ALLOC_SLEEP(sizeof(*state));
+#else
     state = (struct deflate_state *) ALLOC_NOSLEEP(sizeof(*state));
+#endif
+
     if (state == NULL)
        return NULL;
 
     state->strm.next_in = NULL;
-    state->strm.zalloc = (alloc_func) zalloc;
-    state->strm.zfree = (free_func) zfree;
+    state->strm.zalloc = (alloc_func) z_alloc_init;
+    state->strm.zfree = (free_func) z_free;
     if (deflateInit2(&state->strm, Z_DEFAULT_COMPRESSION, DEFLATE_METHOD_VAL,
-                    -w_size, 8, Z_DEFAULT_STRATEGY, DEFLATE_OVHD+2) != Z_OK) {
+                    -w_size, 8, Z_DEFAULT_STRATEGY) != Z_OK) {
        FREE(state, sizeof(*state));
        return NULL;
     }
 
+    state->strm.zalloc = (alloc_func) z_alloc;
     state->w_size = w_size;
     bzero(&state->stats, sizeof(state->stats));
     return (void *) state;
@@ -178,7 +252,8 @@ z_comp_init(arg, options, opt_len, unit, hdrlen, debug)
 {
     struct deflate_state *state = (struct deflate_state *) arg;
 
-    if (opt_len < CILEN_DEFLATE || options[0] != CI_DEFLATE
+    if (opt_len < CILEN_DEFLATE
+       || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
        || options[1] != CILEN_DEFLATE
        || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
        || DEFLATE_SIZE(options[2]) != state->w_size
@@ -234,8 +309,15 @@ z_compress(arg, mret, mp, orig_len, maxolen)
     /* Allocate one mblk initially. */
     if (maxolen > orig_len)
        maxolen = orig_len;
-    wspace = maxolen < 4096? maxolen: 4096;
-    m = allocb(wspace, BPRI_MED);
+    if (maxolen <= PPP_HDRLEN + 2) {
+       wspace = 0;
+       m = NULL;
+    } else {
+       wspace = maxolen + state->hdrlen;
+       if (wspace > 4096)
+           wspace = 4096;
+       m = allocb(wspace, BPRI_MED);
+    }
     if (m != NULL) {
        *mret = m;
        if (state->hdrlen + PPP_HDRLEN + 2 < wspace) {
@@ -291,11 +373,16 @@ z_compress(arg, mret, mp, orig_len, maxolen)
                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);
+               if (wspace <= 0) {
+                   wspace = 0;
+                   m->b_cont = NULL;
+               } else {
+                   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;
@@ -308,16 +395,15 @@ z_compress(arg, mret, mp, orig_len, maxolen)
            }
        }
     }
-    m->b_wptr += wspace - state->strm.avail_out;
-    olen += wspace - state->strm.avail_out;
+    if (m != NULL) {
+       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)) {
+    if (olen < orig_len && m != NULL) {
        state->stats.comp_bytes += olen;
        state->stats.comp_packets++;
     } else {
@@ -365,27 +451,37 @@ z_decomp_alloc(options, opt_len)
     struct deflate_state *state;
     int w_size;
 
-    if (opt_len != CILEN_DEFLATE || options[0] != CI_DEFLATE
+    if (opt_len != CILEN_DEFLATE
+       || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
        || 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)
+    /*
+     * N.B. the 9 below should be DEFLATE_MIN_SIZE (8), but using
+     * 8 will cause kernel crashes because of a bug in zlib.
+     */
+    if (w_size < 9 || w_size > DEFLATE_MAX_SIZE)
        return NULL;
 
+#ifdef __osf__
+    state = (struct deflate_state *) ALLOC_SLEEP(sizeof(*state));
+#else
     state = (struct deflate_state *) ALLOC_NOSLEEP(sizeof(*state));
+#endif
     if (state == NULL)
        return NULL;
 
     state->strm.next_out = NULL;
-    state->strm.zalloc = (alloc_func) zalloc;
-    state->strm.zfree = (free_func) zfree;
+    state->strm.zalloc = (alloc_func) z_alloc_init;
+    state->strm.zfree = (free_func) z_free;
     if (inflateInit2(&state->strm, -w_size) != Z_OK) {
        FREE(state, sizeof(*state));
        return NULL;
     }
 
+    state->strm.zalloc = (alloc_func) z_alloc;
     state->w_size = w_size;
     bzero(&state->stats, sizeof(state->stats));
     return (void *) state;
@@ -409,7 +505,8 @@ z_decomp_init(arg, options, opt_len, unit, hdrlen, mru, debug)
 {
     struct deflate_state *state = (struct deflate_state *) arg;
 
-    if (opt_len < CILEN_DEFLATE || options[0] != CI_DEFLATE
+    if (opt_len < CILEN_DEFLATE
+       || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
        || options[1] != CILEN_DEFLATE
        || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
        || DEFLATE_SIZE(options[2]) != state->w_size
@@ -480,7 +577,9 @@ z_decompress(arg, mi, mop)
     /* Check the sequence number. */
     seq = (hdr[PPP_HDRLEN] << 8) + hdr[PPP_HDRLEN+1];
     if (seq != state->seqno) {
+#if !DEFLATE_DEBUG
        if (state->debug)
+#endif
            printf("z_decompress%d: bad seq # %d, expected %d\n",
                   state->unit, seq, state->seqno);
        return DECOMP_ERROR;
@@ -496,6 +595,7 @@ z_decompress(arg, mi, mop)
     mo->b_rptr += state->hdrlen;
     mo->b_wptr = wptr = mo->b_rptr;
     ospace = DECOMP_CHUNK;
+    olen = 0;
 
     /*
      * Fill in the first part of the PPP header.  The protocol field
@@ -518,7 +618,6 @@ z_decompress(arg, mi, mop)
     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.
@@ -526,7 +625,9 @@ z_decompress(arg, mi, mop)
     for (;;) {
        r = inflate(&state->strm, flush);
        if (r != Z_OK) {
+#if !DEFLATE_DEBUG
            if (state->debug)
+#endif
                printf("z_decompress%d: inflate returned %d (%s)\n",
                       state->unit, r, (state->strm.msg? state->strm.msg: ""));
            freemsg(mo_head);
@@ -550,7 +651,6 @@ z_decompress(arg, mi, mop)
                    wptr[2] = wptr[3];
                    --state->strm.next_out;
                    ++state->strm.avail_out;
-                   --olen;
                }
                decode_proto = 0;
            } else {
@@ -574,6 +674,12 @@ z_decompress(arg, mi, mop)
     mo->b_wptr += ospace - state->strm.avail_out;
     olen += ospace - state->strm.avail_out;
 
+#if DEFLATE_DEBUG
+    if (olen > state->mru + PPP_HDRLEN)
+       printf("ppp_deflate%d: exceeded mru (%d > %d)\n",
+              state->unit, olen, state->mru + PPP_HDRLEN);
+#endif
+
     state->stats.unc_bytes += olen;
     state->stats.unc_packets++;
     state->stats.comp_bytes += rlen;
@@ -627,10 +733,11 @@ z_incomp(arg, mi)
        r = inflateIncomp(&state->strm);
        if (r != Z_OK) {
            /* gak! */
-           if (state->debug) {
+#if !DEFLATE_DEBUG
+           if (state->debug)
+#endif
                printf("z_incomp%d: inflateIncomp returned %d (%s)\n",
                       state->unit, r, (state->strm.msg? state->strm.msg: ""));
-           }
            return;
        }
        mi = mi->b_cont;