* 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.
+ * Copyright (c) 1994 Paul Mackerras. 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.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
*
- * 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.
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
*
- * 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.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
*
- * $Id: deflate.c,v 1.1 1996/01/18 03:17:48 paulus Exp $
+ * 3. The name(s) of the authors of this software must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission.
+ *
+ * 4. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by Paul Mackerras
+ * <paulus@samba.org>".
+ *
+ * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
+ * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $Id: deflate.c,v 1.12 2004/01/17 05:47:55 carlsonj 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
+
+#ifdef SOL2
+#include <sys/sunddi.h>
+#endif
#if DO_DEFLATE
+#define DEFLATE_DEBUG 1
+
/*
* State for a Deflate (de)compressor.
*/
#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));
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 */
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.
*/
-void *
-zalloc(notused, items, size)
+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;
{
- return ALLOC_NOSLEEP(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);
}
-void
-zfree(notused, ptr, nbytes)
+static void *
+z_alloc(notused, items, size)
+ void *notused;
+ u_int 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
+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);
}
/*
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 = zalloc;
- state->strm.zfree = 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;
{
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
deflateReset(&state->strm);
}
-int
+static int
z_compress(arg, mret, mp, orig_len, maxolen)
void *arg;
mblk_t **mret; /* compressed packet (out) */
/* 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) {
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;
}
}
}
- 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 {
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 = zalloc;
- state->strm.zfree = 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;
{
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
* bug, so we return DECOMP_FATALERROR for them in order to turn off
* compression, even though they are detected by inspecting the input.
*/
-int
+static int
z_decompress(arg, mi, mop)
void *arg;
mblk_t *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;
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
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 !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);
wptr[2] = wptr[3];
--state->strm.next_out;
++state->strm.avail_out;
- --olen;
}
decode_proto = 0;
} else {
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;
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;