X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=modules%2Fdeflate.c;h=c896846db6718a43d513daffd2f8f9fb6ce9f2ec;hp=3be70d3d970b22d3939ccea761802c41775d8a0f;hb=224841f4799f4f1e2e71bc490c54448d66740f4f;hpb=42044316c06596aeeb7b398029dd0b1d381de60d diff --git a/modules/deflate.c b/modules/deflate.c index 3be70d3..c896846 100644 --- a/modules/deflate.c +++ b/modules/deflate.c @@ -4,30 +4,38 @@ * 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.4 1996/08/28 06:34:56 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 + * ". + * + * 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 @@ -45,7 +53,11 @@ #ifdef __osf__ #include "zlib.h" #else -#include "common/zlib.h" +#include "../common/zlib.h" +#endif + +#ifdef SOL2 +#include #endif #if DO_DEFLATE @@ -69,7 +81,8 @@ struct deflate_state { #define DEFLATE_OVHD 2 /* Deflate overhead/packet */ static void *z_alloc __P((void *, u_int items, u_int size)); -static void z_free __P((void *, void *ptr, u_int nb)); +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)); @@ -88,7 +101,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 */ @@ -107,30 +120,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(notused, items, size) +z_alloc_init(notused, items, size) void *notused; u_int items, size; { + struct zchunk *z; + + size = items * size + sizeof(struct zchunk); #ifdef __osf__ - return ALLOC_SLEEP(items * size); + z = (struct zchunk *) ALLOC_SLEEP(size); #else - return ALLOC_NOSLEEP(items * size); + z = (struct zchunk *) ALLOC_NOSLEEP(size); #endif + z->size = size; + z->guard = GUARD_MAGIC; + return (void *) (z + 1); +} + +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, 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); } /* @@ -144,28 +207,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) z_alloc; + 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; @@ -189,7 +264,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 @@ -245,8 +321,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) { @@ -302,11 +385,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; @@ -319,16 +407,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 { @@ -376,27 +463,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) z_alloc; + 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; @@ -420,7 +517,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 @@ -509,6 +607,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 @@ -531,7 +630,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. @@ -565,7 +663,6 @@ z_decompress(arg, mi, mop) wptr[2] = wptr[3]; --state->strm.next_out; ++state->strm.avail_out; - --olen; } decode_proto = 0; } else {