1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * deflate.c - interface the zlib procedures for Deflate compression 3*7c478bd9Sstevel@tonic-gate * and decompression (as used by gzip) to the PPP code. 4*7c478bd9Sstevel@tonic-gate * 5*7c478bd9Sstevel@tonic-gate * This version is for use with STREAMS in Solaris 2 6*7c478bd9Sstevel@tonic-gate * 7*7c478bd9Sstevel@tonic-gate * Copyright (c) 2001 by Sun Microsystems, Inc. 8*7c478bd9Sstevel@tonic-gate * All rights reserved. 9*7c478bd9Sstevel@tonic-gate * 10*7c478bd9Sstevel@tonic-gate * Copyright (c) 1994 The Australian National University. 11*7c478bd9Sstevel@tonic-gate * All rights reserved. 12*7c478bd9Sstevel@tonic-gate * 13*7c478bd9Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software and its 14*7c478bd9Sstevel@tonic-gate * documentation is hereby granted, provided that the above copyright 15*7c478bd9Sstevel@tonic-gate * notice appears in all copies. This software is provided without any 16*7c478bd9Sstevel@tonic-gate * warranty, express or implied. The Australian National University 17*7c478bd9Sstevel@tonic-gate * makes no representations about the suitability of this software for 18*7c478bd9Sstevel@tonic-gate * any purpose. 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY 21*7c478bd9Sstevel@tonic-gate * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 22*7c478bd9Sstevel@tonic-gate * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 23*7c478bd9Sstevel@tonic-gate * THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY 24*7c478bd9Sstevel@tonic-gate * OF SUCH DAMAGE. 25*7c478bd9Sstevel@tonic-gate * 26*7c478bd9Sstevel@tonic-gate * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, 27*7c478bd9Sstevel@tonic-gate * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 28*7c478bd9Sstevel@tonic-gate * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 29*7c478bd9Sstevel@tonic-gate * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO 30*7c478bd9Sstevel@tonic-gate * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, 31*7c478bd9Sstevel@tonic-gate * OR MODIFICATIONS. 32*7c478bd9Sstevel@tonic-gate * 33*7c478bd9Sstevel@tonic-gate * $Id: deflate.c,v 1.9 1999/01/19 23:58:35 paulus Exp $ 34*7c478bd9Sstevel@tonic-gate */ 35*7c478bd9Sstevel@tonic-gate 36*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 37*7c478bd9Sstevel@tonic-gate 38*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/stream.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 46*7c478bd9Sstevel@tonic-gate #include <net/ppp_defs.h> 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate /* Defined for platform-neutral include file */ 49*7c478bd9Sstevel@tonic-gate #define PACKETPTR mblk_t * 50*7c478bd9Sstevel@tonic-gate #include <net/ppp-comp.h> 51*7c478bd9Sstevel@tonic-gate #include "s_common.h" 52*7c478bd9Sstevel@tonic-gate #include "zlib.h" 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate #if DO_DEFLATE 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate /* 57*7c478bd9Sstevel@tonic-gate * State for a Deflate (de)compressor. 58*7c478bd9Sstevel@tonic-gate */ 59*7c478bd9Sstevel@tonic-gate struct deflate_state { 60*7c478bd9Sstevel@tonic-gate int seqno; 61*7c478bd9Sstevel@tonic-gate int w_size; 62*7c478bd9Sstevel@tonic-gate int unit; 63*7c478bd9Sstevel@tonic-gate int hdrlen; 64*7c478bd9Sstevel@tonic-gate int mru; 65*7c478bd9Sstevel@tonic-gate int flags; 66*7c478bd9Sstevel@tonic-gate z_stream strm; 67*7c478bd9Sstevel@tonic-gate struct compstat stats; 68*7c478bd9Sstevel@tonic-gate }; 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate #define DEFLATE_OVHD 2 /* Deflate overhead/packet */ 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate #define DS_DEBUG 0x0001 73*7c478bd9Sstevel@tonic-gate #define DS_TESTIN 0x0002 74*7c478bd9Sstevel@tonic-gate #define DS_TESTOUT 0x0004 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate static void *z_alloc(void *, uint_t items, uint_t size); 77*7c478bd9Sstevel@tonic-gate static void z_free(void *, void *ptr); 78*7c478bd9Sstevel@tonic-gate static void *z_comp_alloc(uchar_t *options, int opt_len); 79*7c478bd9Sstevel@tonic-gate static void *z_decomp_alloc(uchar_t *options, int opt_len); 80*7c478bd9Sstevel@tonic-gate static void z_comp_free(void *state); 81*7c478bd9Sstevel@tonic-gate static void z_decomp_free(void *state); 82*7c478bd9Sstevel@tonic-gate static int z_comp_init(void *state, uchar_t *options, int opt_len, 83*7c478bd9Sstevel@tonic-gate int unit, int hdrlen, int debug); 84*7c478bd9Sstevel@tonic-gate static int z_decomp_init(void *state, uchar_t *options, int opt_len, 85*7c478bd9Sstevel@tonic-gate int unit, int hdrlen, int mru, int debug); 86*7c478bd9Sstevel@tonic-gate static int z_compress(void *state, mblk_t **mret, 87*7c478bd9Sstevel@tonic-gate mblk_t *mp, int slen, int maxolen); 88*7c478bd9Sstevel@tonic-gate static int z_incomp(void *state, mblk_t *dmsg); 89*7c478bd9Sstevel@tonic-gate static int z_decompress(void *state, mblk_t **dmpp); 90*7c478bd9Sstevel@tonic-gate static void z_comp_reset(void *state); 91*7c478bd9Sstevel@tonic-gate static void z_decomp_reset(void *state); 92*7c478bd9Sstevel@tonic-gate static void z_comp_stats(void *state, struct compstat *stats); 93*7c478bd9Sstevel@tonic-gate static int z_set_effort(void *xstate, void *rstate, int effortlevel); 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate /* 96*7c478bd9Sstevel@tonic-gate * Procedures exported to ppp_comp.c. 97*7c478bd9Sstevel@tonic-gate */ 98*7c478bd9Sstevel@tonic-gate struct compressor ppp_deflate = { 99*7c478bd9Sstevel@tonic-gate CI_DEFLATE, /* compress_proto */ 100*7c478bd9Sstevel@tonic-gate z_comp_alloc, /* comp_alloc */ 101*7c478bd9Sstevel@tonic-gate z_comp_free, /* comp_free */ 102*7c478bd9Sstevel@tonic-gate z_comp_init, /* comp_init */ 103*7c478bd9Sstevel@tonic-gate z_comp_reset, /* comp_reset */ 104*7c478bd9Sstevel@tonic-gate z_compress, /* compress */ 105*7c478bd9Sstevel@tonic-gate z_comp_stats, /* comp_stat */ 106*7c478bd9Sstevel@tonic-gate z_decomp_alloc, /* decomp_alloc */ 107*7c478bd9Sstevel@tonic-gate z_decomp_free, /* decomp_free */ 108*7c478bd9Sstevel@tonic-gate z_decomp_init, /* decomp_init */ 109*7c478bd9Sstevel@tonic-gate z_decomp_reset, /* decomp_reset */ 110*7c478bd9Sstevel@tonic-gate z_decompress, /* decompress */ 111*7c478bd9Sstevel@tonic-gate z_incomp, /* incomp */ 112*7c478bd9Sstevel@tonic-gate z_comp_stats, /* decomp_stat */ 113*7c478bd9Sstevel@tonic-gate z_set_effort, /* set_effort */ 114*7c478bd9Sstevel@tonic-gate }; 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate struct compressor ppp_deflate_draft = { 117*7c478bd9Sstevel@tonic-gate CI_DEFLATE_DRAFT, /* compress_proto */ 118*7c478bd9Sstevel@tonic-gate z_comp_alloc, /* comp_alloc */ 119*7c478bd9Sstevel@tonic-gate z_comp_free, /* comp_free */ 120*7c478bd9Sstevel@tonic-gate z_comp_init, /* comp_init */ 121*7c478bd9Sstevel@tonic-gate z_comp_reset, /* comp_reset */ 122*7c478bd9Sstevel@tonic-gate z_compress, /* compress */ 123*7c478bd9Sstevel@tonic-gate z_comp_stats, /* comp_stat */ 124*7c478bd9Sstevel@tonic-gate z_decomp_alloc, /* decomp_alloc */ 125*7c478bd9Sstevel@tonic-gate z_decomp_free, /* decomp_free */ 126*7c478bd9Sstevel@tonic-gate z_decomp_init, /* decomp_init */ 127*7c478bd9Sstevel@tonic-gate z_decomp_reset, /* decomp_reset */ 128*7c478bd9Sstevel@tonic-gate z_decompress, /* decompress */ 129*7c478bd9Sstevel@tonic-gate z_incomp, /* incomp */ 130*7c478bd9Sstevel@tonic-gate z_comp_stats, /* decomp_stat */ 131*7c478bd9Sstevel@tonic-gate z_set_effort, /* set_effort */ 132*7c478bd9Sstevel@tonic-gate }; 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate #define DECOMP_CHUNK 512 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate /* 137*7c478bd9Sstevel@tonic-gate * Space allocation and freeing routines for use by zlib routines. 138*7c478bd9Sstevel@tonic-gate */ 139*7c478bd9Sstevel@tonic-gate struct zchunk { 140*7c478bd9Sstevel@tonic-gate uint_t size; 141*7c478bd9Sstevel@tonic-gate uint_t guard; 142*7c478bd9Sstevel@tonic-gate }; 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate #define GUARD_MAGIC 0x77a6011a 145*7c478bd9Sstevel@tonic-gate 146*7c478bd9Sstevel@tonic-gate /* 147*7c478bd9Sstevel@tonic-gate * z_alloc() 148*7c478bd9Sstevel@tonic-gate */ 149*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 150*7c478bd9Sstevel@tonic-gate static void * 151*7c478bd9Sstevel@tonic-gate z_alloc(void *notused, uint_t items, uint_t size) 152*7c478bd9Sstevel@tonic-gate { 153*7c478bd9Sstevel@tonic-gate struct zchunk *z; 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate size = items * size + sizeof (struct zchunk); 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate z = (struct zchunk *)kmem_alloc(size, KM_NOSLEEP); 158*7c478bd9Sstevel@tonic-gate if (z == NULL) 159*7c478bd9Sstevel@tonic-gate return (NULL); 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate z->size = size; 162*7c478bd9Sstevel@tonic-gate z->guard = GUARD_MAGIC; 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate return ((void *)(z + 1)); 165*7c478bd9Sstevel@tonic-gate } 166*7c478bd9Sstevel@tonic-gate 167*7c478bd9Sstevel@tonic-gate /* 168*7c478bd9Sstevel@tonic-gate * z_free() 169*7c478bd9Sstevel@tonic-gate */ 170*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 171*7c478bd9Sstevel@tonic-gate static void 172*7c478bd9Sstevel@tonic-gate z_free(void *notused, void *ptr) 173*7c478bd9Sstevel@tonic-gate { 174*7c478bd9Sstevel@tonic-gate struct zchunk *z = ((struct zchunk *)ptr) - 1; 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate if (ptr == NULL) 177*7c478bd9Sstevel@tonic-gate return; 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate if (z->guard != GUARD_MAGIC) { 180*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 181*7c478bd9Sstevel@tonic-gate "deflate: z_free of corrupted chunk at 0x%p (%x, %x)\n", 182*7c478bd9Sstevel@tonic-gate (void *)z, z->size, z->guard); 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate return; 185*7c478bd9Sstevel@tonic-gate } 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate kmem_free(z, z->size); 188*7c478bd9Sstevel@tonic-gate } 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate /* 191*7c478bd9Sstevel@tonic-gate * Allocate space for a compressor. 192*7c478bd9Sstevel@tonic-gate */ 193*7c478bd9Sstevel@tonic-gate static void * 194*7c478bd9Sstevel@tonic-gate z_comp_alloc(uchar_t *options, int opt_len) 195*7c478bd9Sstevel@tonic-gate { 196*7c478bd9Sstevel@tonic-gate struct deflate_state *state; 197*7c478bd9Sstevel@tonic-gate int w_size; 198*7c478bd9Sstevel@tonic-gate 199*7c478bd9Sstevel@tonic-gate if (opt_len != CILEN_DEFLATE || 200*7c478bd9Sstevel@tonic-gate (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) || 201*7c478bd9Sstevel@tonic-gate options[1] != CILEN_DEFLATE || 202*7c478bd9Sstevel@tonic-gate DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL || 203*7c478bd9Sstevel@tonic-gate options[3] != DEFLATE_CHK_SEQUENCE) { 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate return (NULL); 206*7c478bd9Sstevel@tonic-gate } 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate w_size = DEFLATE_SIZE(options[2]); 209*7c478bd9Sstevel@tonic-gate /* 210*7c478bd9Sstevel@tonic-gate * Check <= minimum size to avoid unfixable zlib bug -- window size 211*7c478bd9Sstevel@tonic-gate * 256 (w_size 8) is not supported. 212*7c478bd9Sstevel@tonic-gate */ 213*7c478bd9Sstevel@tonic-gate if (w_size <= DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE) { 214*7c478bd9Sstevel@tonic-gate return (NULL); 215*7c478bd9Sstevel@tonic-gate } 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate state = (struct deflate_state *)kmem_zalloc(sizeof (*state), KM_SLEEP); 218*7c478bd9Sstevel@tonic-gate ASSERT(state != NULL); 219*7c478bd9Sstevel@tonic-gate 220*7c478bd9Sstevel@tonic-gate state->strm.zalloc = (alloc_func)z_alloc; 221*7c478bd9Sstevel@tonic-gate state->strm.zfree = (free_func)z_free; 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate if (deflateInit2(&state->strm, Z_DEFAULT_COMPRESSION, 224*7c478bd9Sstevel@tonic-gate DEFLATE_METHOD_VAL, -w_size, 8, Z_DEFAULT_STRATEGY) != Z_OK) { 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate kmem_free(state, sizeof (*state)); 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate return (NULL); 229*7c478bd9Sstevel@tonic-gate } 230*7c478bd9Sstevel@tonic-gate 231*7c478bd9Sstevel@tonic-gate state->w_size = w_size; 232*7c478bd9Sstevel@tonic-gate 233*7c478bd9Sstevel@tonic-gate bzero(&state->stats, sizeof (state->stats)); 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate return ((void *)state); 236*7c478bd9Sstevel@tonic-gate } 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate /* 239*7c478bd9Sstevel@tonic-gate * z_comp_free() 240*7c478bd9Sstevel@tonic-gate */ 241*7c478bd9Sstevel@tonic-gate static void 242*7c478bd9Sstevel@tonic-gate z_comp_free(void *arg) 243*7c478bd9Sstevel@tonic-gate { 244*7c478bd9Sstevel@tonic-gate struct deflate_state *state = (struct deflate_state *)arg; 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate (void) deflateEnd(&state->strm); 247*7c478bd9Sstevel@tonic-gate 248*7c478bd9Sstevel@tonic-gate kmem_free(state, sizeof (*state)); 249*7c478bd9Sstevel@tonic-gate } 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate /* 252*7c478bd9Sstevel@tonic-gate * z_comp_init() 253*7c478bd9Sstevel@tonic-gate */ 254*7c478bd9Sstevel@tonic-gate static int 255*7c478bd9Sstevel@tonic-gate z_comp_init(void *arg, uchar_t *options, int opt_len, int unit, int hdrlen, 256*7c478bd9Sstevel@tonic-gate int debug) 257*7c478bd9Sstevel@tonic-gate { 258*7c478bd9Sstevel@tonic-gate struct deflate_state *state = (struct deflate_state *)arg; 259*7c478bd9Sstevel@tonic-gate 260*7c478bd9Sstevel@tonic-gate if (opt_len < CILEN_DEFLATE || 261*7c478bd9Sstevel@tonic-gate (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) || 262*7c478bd9Sstevel@tonic-gate options[1] != CILEN_DEFLATE || 263*7c478bd9Sstevel@tonic-gate DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL || 264*7c478bd9Sstevel@tonic-gate DEFLATE_SIZE(options[2]) != state->w_size || 265*7c478bd9Sstevel@tonic-gate options[3] != DEFLATE_CHK_SEQUENCE) { 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate return (0); 268*7c478bd9Sstevel@tonic-gate } 269*7c478bd9Sstevel@tonic-gate 270*7c478bd9Sstevel@tonic-gate state->seqno = 0; 271*7c478bd9Sstevel@tonic-gate state->unit = unit; 272*7c478bd9Sstevel@tonic-gate state->hdrlen = hdrlen; 273*7c478bd9Sstevel@tonic-gate if (debug) 274*7c478bd9Sstevel@tonic-gate state->flags |= DS_DEBUG; 275*7c478bd9Sstevel@tonic-gate else 276*7c478bd9Sstevel@tonic-gate state->flags &= ~DS_DEBUG; 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate (void) deflateReset(&state->strm); 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate return (1); 281*7c478bd9Sstevel@tonic-gate } 282*7c478bd9Sstevel@tonic-gate 283*7c478bd9Sstevel@tonic-gate /* 284*7c478bd9Sstevel@tonic-gate * z_comp_reset() 285*7c478bd9Sstevel@tonic-gate */ 286*7c478bd9Sstevel@tonic-gate static void 287*7c478bd9Sstevel@tonic-gate z_comp_reset(void *arg) 288*7c478bd9Sstevel@tonic-gate { 289*7c478bd9Sstevel@tonic-gate struct deflate_state *state = (struct deflate_state *)arg; 290*7c478bd9Sstevel@tonic-gate 291*7c478bd9Sstevel@tonic-gate state->seqno = 0; 292*7c478bd9Sstevel@tonic-gate 293*7c478bd9Sstevel@tonic-gate (void) deflateReset(&state->strm); 294*7c478bd9Sstevel@tonic-gate } 295*7c478bd9Sstevel@tonic-gate 296*7c478bd9Sstevel@tonic-gate /* 297*7c478bd9Sstevel@tonic-gate * z_compress() 298*7c478bd9Sstevel@tonic-gate */ 299*7c478bd9Sstevel@tonic-gate static int 300*7c478bd9Sstevel@tonic-gate z_compress(void *arg, mblk_t **mret, mblk_t *mp, int orig_len, int maxolen) 301*7c478bd9Sstevel@tonic-gate { 302*7c478bd9Sstevel@tonic-gate struct deflate_state *state = (struct deflate_state *)arg; 303*7c478bd9Sstevel@tonic-gate uchar_t *rptr, *rmax; 304*7c478bd9Sstevel@tonic-gate uchar_t *wptr; 305*7c478bd9Sstevel@tonic-gate int olen; 306*7c478bd9Sstevel@tonic-gate int wspace; 307*7c478bd9Sstevel@tonic-gate int r; 308*7c478bd9Sstevel@tonic-gate int flush; 309*7c478bd9Sstevel@tonic-gate mblk_t *m; 310*7c478bd9Sstevel@tonic-gate #if defined(lint) || defined(_lint) 311*7c478bd9Sstevel@tonic-gate uchar_t hdlcaddr, hdlcctrl; 312*7c478bd9Sstevel@tonic-gate #else 313*7c478bd9Sstevel@tonic-gate int hdlcaddr, hdlcctrl; 314*7c478bd9Sstevel@tonic-gate #endif 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate #define ADJRPTR() { \ 317*7c478bd9Sstevel@tonic-gate if (rptr != NULL) { \ 318*7c478bd9Sstevel@tonic-gate while (rptr >= rmax) { \ 319*7c478bd9Sstevel@tonic-gate if ((mp = mp->b_cont) == NULL) { \ 320*7c478bd9Sstevel@tonic-gate rptr = NULL; \ 321*7c478bd9Sstevel@tonic-gate break; \ 322*7c478bd9Sstevel@tonic-gate } \ 323*7c478bd9Sstevel@tonic-gate rptr = mp->b_rptr; \ 324*7c478bd9Sstevel@tonic-gate rmax = mp->b_wptr; \ 325*7c478bd9Sstevel@tonic-gate } \ 326*7c478bd9Sstevel@tonic-gate } \ 327*7c478bd9Sstevel@tonic-gate } 328*7c478bd9Sstevel@tonic-gate 329*7c478bd9Sstevel@tonic-gate #define GETBYTE(v) { \ 330*7c478bd9Sstevel@tonic-gate if (rptr != NULL) { \ 331*7c478bd9Sstevel@tonic-gate (v) = *rptr++; \ 332*7c478bd9Sstevel@tonic-gate } \ 333*7c478bd9Sstevel@tonic-gate } 334*7c478bd9Sstevel@tonic-gate 335*7c478bd9Sstevel@tonic-gate /* 336*7c478bd9Sstevel@tonic-gate * Check that the protocol is one we handle. Pullup is *NOT* 337*7c478bd9Sstevel@tonic-gate * possible here. 338*7c478bd9Sstevel@tonic-gate */ 339*7c478bd9Sstevel@tonic-gate *mret = NULL; 340*7c478bd9Sstevel@tonic-gate rptr = mp->b_rptr; 341*7c478bd9Sstevel@tonic-gate rmax = mp->b_wptr; 342*7c478bd9Sstevel@tonic-gate ADJRPTR(); 343*7c478bd9Sstevel@tonic-gate GETBYTE(hdlcaddr); 344*7c478bd9Sstevel@tonic-gate ADJRPTR(); 345*7c478bd9Sstevel@tonic-gate GETBYTE(hdlcctrl); 346*7c478bd9Sstevel@tonic-gate ADJRPTR(); 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate /* 349*7c478bd9Sstevel@tonic-gate * Per RFC 1979, the protocol field must be compressed using a 350*7c478bd9Sstevel@tonic-gate * PFC-like procedure. Also, all protocols between 0000-3FFF 351*7c478bd9Sstevel@tonic-gate * except the two compression protocols must be LZ compressed. 352*7c478bd9Sstevel@tonic-gate */ 353*7c478bd9Sstevel@tonic-gate if (rptr == NULL) 354*7c478bd9Sstevel@tonic-gate return (orig_len); 355*7c478bd9Sstevel@tonic-gate r = *rptr; 356*7c478bd9Sstevel@tonic-gate if (r == 0) { 357*7c478bd9Sstevel@tonic-gate rptr++; 358*7c478bd9Sstevel@tonic-gate ADJRPTR(); 359*7c478bd9Sstevel@tonic-gate if (rptr == NULL || *rptr == PPP_COMP || *rptr == PPP_COMPFRAG) 360*7c478bd9Sstevel@tonic-gate return (orig_len); 361*7c478bd9Sstevel@tonic-gate } else { 362*7c478bd9Sstevel@tonic-gate if (r > 0x3F) 363*7c478bd9Sstevel@tonic-gate return (orig_len); 364*7c478bd9Sstevel@tonic-gate } 365*7c478bd9Sstevel@tonic-gate 366*7c478bd9Sstevel@tonic-gate /* 367*7c478bd9Sstevel@tonic-gate * Allocate one mblk initially 368*7c478bd9Sstevel@tonic-gate */ 369*7c478bd9Sstevel@tonic-gate if (maxolen > orig_len) { 370*7c478bd9Sstevel@tonic-gate maxolen = orig_len; 371*7c478bd9Sstevel@tonic-gate } 372*7c478bd9Sstevel@tonic-gate 373*7c478bd9Sstevel@tonic-gate if (maxolen <= PPP_HDRLEN + 2) { 374*7c478bd9Sstevel@tonic-gate wspace = 0; 375*7c478bd9Sstevel@tonic-gate m = NULL; 376*7c478bd9Sstevel@tonic-gate } else { 377*7c478bd9Sstevel@tonic-gate wspace = maxolen + state->hdrlen; 378*7c478bd9Sstevel@tonic-gate if (wspace > 4096) { 379*7c478bd9Sstevel@tonic-gate wspace = 4096; 380*7c478bd9Sstevel@tonic-gate } 381*7c478bd9Sstevel@tonic-gate 382*7c478bd9Sstevel@tonic-gate m = allocb(wspace, BPRI_MED); 383*7c478bd9Sstevel@tonic-gate } 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate if (m != NULL) { 386*7c478bd9Sstevel@tonic-gate 387*7c478bd9Sstevel@tonic-gate wspace = m->b_datap->db_lim - m->b_wptr; 388*7c478bd9Sstevel@tonic-gate 389*7c478bd9Sstevel@tonic-gate *mret = m; 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate if (state->hdrlen + PPP_HDRLEN + 2 < wspace) { 392*7c478bd9Sstevel@tonic-gate m->b_rptr += state->hdrlen; 393*7c478bd9Sstevel@tonic-gate m->b_wptr = m->b_rptr; 394*7c478bd9Sstevel@tonic-gate wspace -= state->hdrlen; 395*7c478bd9Sstevel@tonic-gate } 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate wptr = m->b_wptr; 398*7c478bd9Sstevel@tonic-gate 399*7c478bd9Sstevel@tonic-gate /* 400*7c478bd9Sstevel@tonic-gate * Copy over the PPP header and store the 2-byte 401*7c478bd9Sstevel@tonic-gate * sequence number 402*7c478bd9Sstevel@tonic-gate */ 403*7c478bd9Sstevel@tonic-gate wptr[0] = hdlcaddr; 404*7c478bd9Sstevel@tonic-gate wptr[1] = hdlcctrl; 405*7c478bd9Sstevel@tonic-gate wptr[2] = PPP_COMP >> 8; 406*7c478bd9Sstevel@tonic-gate wptr[3] = PPP_COMP; 407*7c478bd9Sstevel@tonic-gate 408*7c478bd9Sstevel@tonic-gate wptr += PPP_HDRLEN; 409*7c478bd9Sstevel@tonic-gate 410*7c478bd9Sstevel@tonic-gate wptr[0] = state->seqno >> 8; 411*7c478bd9Sstevel@tonic-gate wptr[1] = state->seqno; 412*7c478bd9Sstevel@tonic-gate wptr += 2; 413*7c478bd9Sstevel@tonic-gate 414*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 415*7c478bd9Sstevel@tonic-gate /* 416*7c478bd9Sstevel@tonic-gate * If testing output, just garbling the sequence here 417*7c478bd9Sstevel@tonic-gate * does the trick. 418*7c478bd9Sstevel@tonic-gate */ 419*7c478bd9Sstevel@tonic-gate if ((state->flags & DS_TESTOUT) && (state->seqno % 100) == 50) 420*7c478bd9Sstevel@tonic-gate wptr[-1] ^= 0xAA; 421*7c478bd9Sstevel@tonic-gate #endif 422*7c478bd9Sstevel@tonic-gate 423*7c478bd9Sstevel@tonic-gate state->strm.next_out = wptr; 424*7c478bd9Sstevel@tonic-gate state->strm.avail_out = wspace - (PPP_HDRLEN + 2); 425*7c478bd9Sstevel@tonic-gate } else { 426*7c478bd9Sstevel@tonic-gate state->strm.next_out = NULL; 427*7c478bd9Sstevel@tonic-gate state->strm.avail_out = 1000000; 428*7c478bd9Sstevel@tonic-gate } 429*7c478bd9Sstevel@tonic-gate 430*7c478bd9Sstevel@tonic-gate ++state->seqno; 431*7c478bd9Sstevel@tonic-gate 432*7c478bd9Sstevel@tonic-gate state->strm.next_in = rptr; 433*7c478bd9Sstevel@tonic-gate state->strm.avail_in = mp->b_wptr - rptr; 434*7c478bd9Sstevel@tonic-gate 435*7c478bd9Sstevel@tonic-gate olen = 0; 436*7c478bd9Sstevel@tonic-gate 437*7c478bd9Sstevel@tonic-gate for (;;) { 438*7c478bd9Sstevel@tonic-gate flush = (mp == NULL || mp->b_cont == NULL) ? Z_PACKET_FLUSH : 439*7c478bd9Sstevel@tonic-gate Z_NO_FLUSH; 440*7c478bd9Sstevel@tonic-gate r = deflate(&state->strm, flush); 441*7c478bd9Sstevel@tonic-gate 442*7c478bd9Sstevel@tonic-gate if (r != Z_OK) { 443*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 444*7c478bd9Sstevel@tonic-gate "z_compress%d: deflate returned %d (%s)\n", 445*7c478bd9Sstevel@tonic-gate state->unit, r, 446*7c478bd9Sstevel@tonic-gate (state->strm.msg? state->strm.msg: "")); 447*7c478bd9Sstevel@tonic-gate 448*7c478bd9Sstevel@tonic-gate break; 449*7c478bd9Sstevel@tonic-gate } 450*7c478bd9Sstevel@tonic-gate 451*7c478bd9Sstevel@tonic-gate if (state->strm.avail_in == 0) { 452*7c478bd9Sstevel@tonic-gate if (mp != NULL) 453*7c478bd9Sstevel@tonic-gate mp = mp->b_cont; 454*7c478bd9Sstevel@tonic-gate if (mp == NULL) { 455*7c478bd9Sstevel@tonic-gate if (state->strm.avail_out != 0) 456*7c478bd9Sstevel@tonic-gate break; /* all done */ 457*7c478bd9Sstevel@tonic-gate } else { 458*7c478bd9Sstevel@tonic-gate state->strm.next_in = mp->b_rptr; 459*7c478bd9Sstevel@tonic-gate state->strm.avail_in = mp->b_wptr - mp->b_rptr; 460*7c478bd9Sstevel@tonic-gate } 461*7c478bd9Sstevel@tonic-gate } 462*7c478bd9Sstevel@tonic-gate 463*7c478bd9Sstevel@tonic-gate if (state->strm.avail_out == 0) { 464*7c478bd9Sstevel@tonic-gate if (m != NULL) { 465*7c478bd9Sstevel@tonic-gate m->b_wptr += wspace; 466*7c478bd9Sstevel@tonic-gate olen += wspace; 467*7c478bd9Sstevel@tonic-gate wspace = maxolen - olen; 468*7c478bd9Sstevel@tonic-gate 469*7c478bd9Sstevel@tonic-gate if (wspace <= 0) { 470*7c478bd9Sstevel@tonic-gate wspace = 0; 471*7c478bd9Sstevel@tonic-gate m->b_cont = NULL; 472*7c478bd9Sstevel@tonic-gate } else { 473*7c478bd9Sstevel@tonic-gate if (wspace < 32) { 474*7c478bd9Sstevel@tonic-gate wspace = 32; 475*7c478bd9Sstevel@tonic-gate } else if (wspace > 4096) { 476*7c478bd9Sstevel@tonic-gate wspace = 4096; 477*7c478bd9Sstevel@tonic-gate } 478*7c478bd9Sstevel@tonic-gate 479*7c478bd9Sstevel@tonic-gate m->b_cont = allocb(wspace, BPRI_MED); 480*7c478bd9Sstevel@tonic-gate } 481*7c478bd9Sstevel@tonic-gate 482*7c478bd9Sstevel@tonic-gate m = m->b_cont; 483*7c478bd9Sstevel@tonic-gate 484*7c478bd9Sstevel@tonic-gate if (m != NULL) { 485*7c478bd9Sstevel@tonic-gate state->strm.next_out = m->b_wptr; 486*7c478bd9Sstevel@tonic-gate wspace = m->b_datap->db_lim - 487*7c478bd9Sstevel@tonic-gate m->b_wptr; 488*7c478bd9Sstevel@tonic-gate state->strm.avail_out = wspace; 489*7c478bd9Sstevel@tonic-gate } 490*7c478bd9Sstevel@tonic-gate } 491*7c478bd9Sstevel@tonic-gate 492*7c478bd9Sstevel@tonic-gate if (m == NULL) { 493*7c478bd9Sstevel@tonic-gate state->strm.next_out = NULL; 494*7c478bd9Sstevel@tonic-gate state->strm.avail_out = 1000000; 495*7c478bd9Sstevel@tonic-gate } 496*7c478bd9Sstevel@tonic-gate } 497*7c478bd9Sstevel@tonic-gate } 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate if (m != NULL) { 500*7c478bd9Sstevel@tonic-gate m->b_wptr += wspace - state->strm.avail_out; 501*7c478bd9Sstevel@tonic-gate olen += wspace - state->strm.avail_out; 502*7c478bd9Sstevel@tonic-gate } 503*7c478bd9Sstevel@tonic-gate 504*7c478bd9Sstevel@tonic-gate /* 505*7c478bd9Sstevel@tonic-gate * See if we managed to reduce the size of the packet. 506*7c478bd9Sstevel@tonic-gate */ 507*7c478bd9Sstevel@tonic-gate if (olen < orig_len && m != NULL) { 508*7c478bd9Sstevel@tonic-gate state->stats.comp_bytes += olen; 509*7c478bd9Sstevel@tonic-gate state->stats.comp_packets++; 510*7c478bd9Sstevel@tonic-gate } else { 511*7c478bd9Sstevel@tonic-gate if (*mret != NULL) { 512*7c478bd9Sstevel@tonic-gate freemsg(*mret); 513*7c478bd9Sstevel@tonic-gate *mret = NULL; 514*7c478bd9Sstevel@tonic-gate } 515*7c478bd9Sstevel@tonic-gate 516*7c478bd9Sstevel@tonic-gate state->stats.inc_bytes += orig_len; 517*7c478bd9Sstevel@tonic-gate state->stats.inc_packets++; 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate olen = orig_len; 520*7c478bd9Sstevel@tonic-gate } 521*7c478bd9Sstevel@tonic-gate 522*7c478bd9Sstevel@tonic-gate state->stats.unc_bytes += orig_len; 523*7c478bd9Sstevel@tonic-gate state->stats.unc_packets++; 524*7c478bd9Sstevel@tonic-gate 525*7c478bd9Sstevel@tonic-gate return (olen); 526*7c478bd9Sstevel@tonic-gate } 527*7c478bd9Sstevel@tonic-gate 528*7c478bd9Sstevel@tonic-gate /* 529*7c478bd9Sstevel@tonic-gate * z_incomp() 530*7c478bd9Sstevel@tonic-gate * 531*7c478bd9Sstevel@tonic-gate * Incompressible data has arrived - add it to the history. 532*7c478bd9Sstevel@tonic-gate */ 533*7c478bd9Sstevel@tonic-gate static int 534*7c478bd9Sstevel@tonic-gate z_incomp(void *arg, mblk_t *mp) 535*7c478bd9Sstevel@tonic-gate { 536*7c478bd9Sstevel@tonic-gate struct deflate_state *state = (struct deflate_state *)arg; 537*7c478bd9Sstevel@tonic-gate uchar_t *rptr, *rmax; 538*7c478bd9Sstevel@tonic-gate int rlen; 539*7c478bd9Sstevel@tonic-gate int r; 540*7c478bd9Sstevel@tonic-gate 541*7c478bd9Sstevel@tonic-gate /* 542*7c478bd9Sstevel@tonic-gate * Check that the protocol is one we handle. Pullup is *NOT* 543*7c478bd9Sstevel@tonic-gate * possible here. 544*7c478bd9Sstevel@tonic-gate */ 545*7c478bd9Sstevel@tonic-gate rptr = mp->b_rptr; 546*7c478bd9Sstevel@tonic-gate rmax = mp->b_wptr; 547*7c478bd9Sstevel@tonic-gate ADJRPTR(); 548*7c478bd9Sstevel@tonic-gate rptr++; /* skip address */ 549*7c478bd9Sstevel@tonic-gate ADJRPTR(); 550*7c478bd9Sstevel@tonic-gate rptr++; /* skip control */ 551*7c478bd9Sstevel@tonic-gate ADJRPTR(); 552*7c478bd9Sstevel@tonic-gate 553*7c478bd9Sstevel@tonic-gate /* 554*7c478bd9Sstevel@tonic-gate * Per RFC 1979, the protocol field must be compressed using a 555*7c478bd9Sstevel@tonic-gate * PFC-like procedure. Also, all protocols between 0000-3FFF 556*7c478bd9Sstevel@tonic-gate * except the two compression protocols must be LZ compressed. 557*7c478bd9Sstevel@tonic-gate */ 558*7c478bd9Sstevel@tonic-gate if (rptr == NULL) 559*7c478bd9Sstevel@tonic-gate return (0); 560*7c478bd9Sstevel@tonic-gate r = *rptr; 561*7c478bd9Sstevel@tonic-gate if (r == 0) { 562*7c478bd9Sstevel@tonic-gate rptr++; 563*7c478bd9Sstevel@tonic-gate ADJRPTR(); 564*7c478bd9Sstevel@tonic-gate if (rptr == NULL || *rptr == PPP_COMP || *rptr == PPP_COMPFRAG) 565*7c478bd9Sstevel@tonic-gate return (0); 566*7c478bd9Sstevel@tonic-gate } else { 567*7c478bd9Sstevel@tonic-gate if (r > 0x3F) 568*7c478bd9Sstevel@tonic-gate return (0); 569*7c478bd9Sstevel@tonic-gate } 570*7c478bd9Sstevel@tonic-gate 571*7c478bd9Sstevel@tonic-gate ++state->seqno; 572*7c478bd9Sstevel@tonic-gate 573*7c478bd9Sstevel@tonic-gate /* 574*7c478bd9Sstevel@tonic-gate * Iterate through the message blocks, adding the characters 575*7c478bd9Sstevel@tonic-gate * in them to the decompressor's history. 576*7c478bd9Sstevel@tonic-gate */ 577*7c478bd9Sstevel@tonic-gate rlen = mp->b_wptr - rptr; 578*7c478bd9Sstevel@tonic-gate 579*7c478bd9Sstevel@tonic-gate state->strm.next_in = rptr; 580*7c478bd9Sstevel@tonic-gate state->strm.avail_in = rlen; 581*7c478bd9Sstevel@tonic-gate 582*7c478bd9Sstevel@tonic-gate for (;;) { 583*7c478bd9Sstevel@tonic-gate r = inflateIncomp(&state->strm); 584*7c478bd9Sstevel@tonic-gate 585*7c478bd9Sstevel@tonic-gate if (r != Z_OK) { /* gak! */ 586*7c478bd9Sstevel@tonic-gate if (state->flags & DS_DEBUG) { 587*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 588*7c478bd9Sstevel@tonic-gate "z_incomp%d: inflateIncomp returned " 589*7c478bd9Sstevel@tonic-gate "%d (%s)\n", state->unit, r, 590*7c478bd9Sstevel@tonic-gate (state->strm.msg? state->strm.msg: "")); 591*7c478bd9Sstevel@tonic-gate } 592*7c478bd9Sstevel@tonic-gate 593*7c478bd9Sstevel@tonic-gate return (-1); 594*7c478bd9Sstevel@tonic-gate } 595*7c478bd9Sstevel@tonic-gate 596*7c478bd9Sstevel@tonic-gate mp = mp->b_cont; 597*7c478bd9Sstevel@tonic-gate if (mp == NULL) { 598*7c478bd9Sstevel@tonic-gate break; 599*7c478bd9Sstevel@tonic-gate } 600*7c478bd9Sstevel@tonic-gate 601*7c478bd9Sstevel@tonic-gate state->strm.next_in = mp->b_rptr; 602*7c478bd9Sstevel@tonic-gate state->strm.avail_in = mp->b_wptr - mp->b_rptr; 603*7c478bd9Sstevel@tonic-gate 604*7c478bd9Sstevel@tonic-gate rlen += state->strm.avail_in; 605*7c478bd9Sstevel@tonic-gate } 606*7c478bd9Sstevel@tonic-gate 607*7c478bd9Sstevel@tonic-gate /* 608*7c478bd9Sstevel@tonic-gate * Update stats 609*7c478bd9Sstevel@tonic-gate */ 610*7c478bd9Sstevel@tonic-gate state->stats.inc_bytes += rlen; 611*7c478bd9Sstevel@tonic-gate state->stats.inc_packets++; 612*7c478bd9Sstevel@tonic-gate state->stats.unc_bytes += rlen; 613*7c478bd9Sstevel@tonic-gate state->stats.unc_packets++; 614*7c478bd9Sstevel@tonic-gate return (0); 615*7c478bd9Sstevel@tonic-gate #undef ADJRPTR 616*7c478bd9Sstevel@tonic-gate } 617*7c478bd9Sstevel@tonic-gate 618*7c478bd9Sstevel@tonic-gate /* 619*7c478bd9Sstevel@tonic-gate * z_comp_stats() 620*7c478bd9Sstevel@tonic-gate */ 621*7c478bd9Sstevel@tonic-gate static void 622*7c478bd9Sstevel@tonic-gate z_comp_stats(void *arg, struct compstat *stats) 623*7c478bd9Sstevel@tonic-gate { 624*7c478bd9Sstevel@tonic-gate struct deflate_state *state = (struct deflate_state *)arg; 625*7c478bd9Sstevel@tonic-gate uint_t out; 626*7c478bd9Sstevel@tonic-gate 627*7c478bd9Sstevel@tonic-gate *stats = state->stats; 628*7c478bd9Sstevel@tonic-gate stats->ratio = stats->unc_bytes; 629*7c478bd9Sstevel@tonic-gate out = stats->comp_bytes + stats->unc_bytes; 630*7c478bd9Sstevel@tonic-gate 631*7c478bd9Sstevel@tonic-gate if (stats->ratio <= 0x7ffffff) { 632*7c478bd9Sstevel@tonic-gate stats->ratio <<= 8; 633*7c478bd9Sstevel@tonic-gate } else { 634*7c478bd9Sstevel@tonic-gate out >>= 8; 635*7c478bd9Sstevel@tonic-gate } 636*7c478bd9Sstevel@tonic-gate 637*7c478bd9Sstevel@tonic-gate if (out != 0) { 638*7c478bd9Sstevel@tonic-gate stats->ratio /= out; 639*7c478bd9Sstevel@tonic-gate } 640*7c478bd9Sstevel@tonic-gate } 641*7c478bd9Sstevel@tonic-gate 642*7c478bd9Sstevel@tonic-gate /* 643*7c478bd9Sstevel@tonic-gate * z_decomp_alloc() 644*7c478bd9Sstevel@tonic-gate * 645*7c478bd9Sstevel@tonic-gate * Allocate space for a decompressor. 646*7c478bd9Sstevel@tonic-gate */ 647*7c478bd9Sstevel@tonic-gate static void * 648*7c478bd9Sstevel@tonic-gate z_decomp_alloc(uchar_t *options, int opt_len) 649*7c478bd9Sstevel@tonic-gate { 650*7c478bd9Sstevel@tonic-gate struct deflate_state *state; 651*7c478bd9Sstevel@tonic-gate int w_size; 652*7c478bd9Sstevel@tonic-gate 653*7c478bd9Sstevel@tonic-gate if (opt_len != CILEN_DEFLATE || 654*7c478bd9Sstevel@tonic-gate (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) || 655*7c478bd9Sstevel@tonic-gate options[1] != CILEN_DEFLATE || 656*7c478bd9Sstevel@tonic-gate DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL || 657*7c478bd9Sstevel@tonic-gate options[3] != DEFLATE_CHK_SEQUENCE) { 658*7c478bd9Sstevel@tonic-gate 659*7c478bd9Sstevel@tonic-gate return (NULL); 660*7c478bd9Sstevel@tonic-gate } 661*7c478bd9Sstevel@tonic-gate 662*7c478bd9Sstevel@tonic-gate w_size = DEFLATE_SIZE(options[2]); 663*7c478bd9Sstevel@tonic-gate /* 664*7c478bd9Sstevel@tonic-gate * Check <= minimum size to avoid unfixable zlib bug -- window size 665*7c478bd9Sstevel@tonic-gate * 256 (w_size 8) is not supported. 666*7c478bd9Sstevel@tonic-gate */ 667*7c478bd9Sstevel@tonic-gate if (w_size <= DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE) { 668*7c478bd9Sstevel@tonic-gate return (NULL); 669*7c478bd9Sstevel@tonic-gate } 670*7c478bd9Sstevel@tonic-gate 671*7c478bd9Sstevel@tonic-gate state = (struct deflate_state *)kmem_zalloc(sizeof (*state), KM_SLEEP); 672*7c478bd9Sstevel@tonic-gate ASSERT(state != NULL); 673*7c478bd9Sstevel@tonic-gate 674*7c478bd9Sstevel@tonic-gate state->strm.zalloc = (alloc_func)z_alloc; 675*7c478bd9Sstevel@tonic-gate state->strm.zfree = (free_func)z_free; 676*7c478bd9Sstevel@tonic-gate 677*7c478bd9Sstevel@tonic-gate if (inflateInit2(&state->strm, -w_size) != Z_OK) { 678*7c478bd9Sstevel@tonic-gate kmem_free(state, sizeof (*state)); 679*7c478bd9Sstevel@tonic-gate return (NULL); 680*7c478bd9Sstevel@tonic-gate } 681*7c478bd9Sstevel@tonic-gate 682*7c478bd9Sstevel@tonic-gate state->w_size = w_size; 683*7c478bd9Sstevel@tonic-gate 684*7c478bd9Sstevel@tonic-gate bzero(&state->stats, sizeof (state->stats)); 685*7c478bd9Sstevel@tonic-gate 686*7c478bd9Sstevel@tonic-gate return ((void *)state); 687*7c478bd9Sstevel@tonic-gate } 688*7c478bd9Sstevel@tonic-gate 689*7c478bd9Sstevel@tonic-gate /* 690*7c478bd9Sstevel@tonic-gate * z_decomp_free() 691*7c478bd9Sstevel@tonic-gate */ 692*7c478bd9Sstevel@tonic-gate static void 693*7c478bd9Sstevel@tonic-gate z_decomp_free(void *arg) 694*7c478bd9Sstevel@tonic-gate { 695*7c478bd9Sstevel@tonic-gate struct deflate_state *state = (struct deflate_state *)arg; 696*7c478bd9Sstevel@tonic-gate 697*7c478bd9Sstevel@tonic-gate (void) inflateEnd(&state->strm); 698*7c478bd9Sstevel@tonic-gate 699*7c478bd9Sstevel@tonic-gate kmem_free(state, sizeof (*state)); 700*7c478bd9Sstevel@tonic-gate } 701*7c478bd9Sstevel@tonic-gate 702*7c478bd9Sstevel@tonic-gate /* 703*7c478bd9Sstevel@tonic-gate * z_decomp_init() 704*7c478bd9Sstevel@tonic-gate */ 705*7c478bd9Sstevel@tonic-gate static int 706*7c478bd9Sstevel@tonic-gate z_decomp_init(void *arg, uchar_t *options, int opt_len, int unit, int hdrlen, 707*7c478bd9Sstevel@tonic-gate int mru, int debug) 708*7c478bd9Sstevel@tonic-gate { 709*7c478bd9Sstevel@tonic-gate struct deflate_state *state = (struct deflate_state *)arg; 710*7c478bd9Sstevel@tonic-gate 711*7c478bd9Sstevel@tonic-gate if (opt_len < CILEN_DEFLATE || 712*7c478bd9Sstevel@tonic-gate (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) || 713*7c478bd9Sstevel@tonic-gate options[1] != CILEN_DEFLATE || 714*7c478bd9Sstevel@tonic-gate DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL || 715*7c478bd9Sstevel@tonic-gate DEFLATE_SIZE(options[2]) != state->w_size || 716*7c478bd9Sstevel@tonic-gate options[3] != DEFLATE_CHK_SEQUENCE) { 717*7c478bd9Sstevel@tonic-gate 718*7c478bd9Sstevel@tonic-gate return (0); 719*7c478bd9Sstevel@tonic-gate } 720*7c478bd9Sstevel@tonic-gate 721*7c478bd9Sstevel@tonic-gate state->seqno = 0; 722*7c478bd9Sstevel@tonic-gate state->unit = unit; 723*7c478bd9Sstevel@tonic-gate state->hdrlen = hdrlen; 724*7c478bd9Sstevel@tonic-gate if (debug) 725*7c478bd9Sstevel@tonic-gate state->flags |= DS_DEBUG; 726*7c478bd9Sstevel@tonic-gate else 727*7c478bd9Sstevel@tonic-gate state->flags &= ~DS_DEBUG; 728*7c478bd9Sstevel@tonic-gate state->mru = mru; 729*7c478bd9Sstevel@tonic-gate 730*7c478bd9Sstevel@tonic-gate (void) inflateReset(&state->strm); 731*7c478bd9Sstevel@tonic-gate 732*7c478bd9Sstevel@tonic-gate return (1); 733*7c478bd9Sstevel@tonic-gate } 734*7c478bd9Sstevel@tonic-gate 735*7c478bd9Sstevel@tonic-gate /* 736*7c478bd9Sstevel@tonic-gate * z_decomp_reset() 737*7c478bd9Sstevel@tonic-gate */ 738*7c478bd9Sstevel@tonic-gate static void 739*7c478bd9Sstevel@tonic-gate z_decomp_reset(void *arg) 740*7c478bd9Sstevel@tonic-gate { 741*7c478bd9Sstevel@tonic-gate struct deflate_state *state = (struct deflate_state *)arg; 742*7c478bd9Sstevel@tonic-gate 743*7c478bd9Sstevel@tonic-gate state->seqno = 0; 744*7c478bd9Sstevel@tonic-gate 745*7c478bd9Sstevel@tonic-gate (void) inflateReset(&state->strm); 746*7c478bd9Sstevel@tonic-gate } 747*7c478bd9Sstevel@tonic-gate 748*7c478bd9Sstevel@tonic-gate /* 749*7c478bd9Sstevel@tonic-gate * z_decompress() 750*7c478bd9Sstevel@tonic-gate * 751*7c478bd9Sstevel@tonic-gate * Decompress a Deflate-compressed packet. 752*7c478bd9Sstevel@tonic-gate * 753*7c478bd9Sstevel@tonic-gate * Because of patent problems, we return DECOMP_ERROR for errors 754*7c478bd9Sstevel@tonic-gate * found by inspecting the input data and for system problems, but 755*7c478bd9Sstevel@tonic-gate * DECOMP_FATALERROR for any errors which could possibly be said to 756*7c478bd9Sstevel@tonic-gate * be being detected "after" decompression. For DECOMP_ERROR, 757*7c478bd9Sstevel@tonic-gate * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be 758*7c478bd9Sstevel@tonic-gate * infringing a patent of Motorola's if we do, so we take CCP down 759*7c478bd9Sstevel@tonic-gate * instead. 760*7c478bd9Sstevel@tonic-gate * 761*7c478bd9Sstevel@tonic-gate * Given that the frame has the correct sequence number and a good FCS, 762*7c478bd9Sstevel@tonic-gate * errors such as invalid codes in the input most likely indicate a 763*7c478bd9Sstevel@tonic-gate * bug, so we return DECOMP_FATALERROR for them in order to turn off 764*7c478bd9Sstevel@tonic-gate * compression, even though they are detected by inspecting the input. 765*7c478bd9Sstevel@tonic-gate */ 766*7c478bd9Sstevel@tonic-gate static int 767*7c478bd9Sstevel@tonic-gate z_decompress(void *arg, mblk_t **mop) 768*7c478bd9Sstevel@tonic-gate { 769*7c478bd9Sstevel@tonic-gate struct deflate_state *state = (struct deflate_state *)arg; 770*7c478bd9Sstevel@tonic-gate mblk_t *mi = *mop, *mnext; 771*7c478bd9Sstevel@tonic-gate mblk_t *mo; 772*7c478bd9Sstevel@tonic-gate mblk_t *mo_head; 773*7c478bd9Sstevel@tonic-gate uchar_t *rptr, *rmax; 774*7c478bd9Sstevel@tonic-gate uchar_t *wptr; 775*7c478bd9Sstevel@tonic-gate int rlen; 776*7c478bd9Sstevel@tonic-gate int olen; 777*7c478bd9Sstevel@tonic-gate int ospace; 778*7c478bd9Sstevel@tonic-gate int seq; 779*7c478bd9Sstevel@tonic-gate int flush; 780*7c478bd9Sstevel@tonic-gate int r; 781*7c478bd9Sstevel@tonic-gate int decode_proto; 782*7c478bd9Sstevel@tonic-gate #if defined(lint) || defined(_lint) 783*7c478bd9Sstevel@tonic-gate uchar_t hdlcaddr, hdlcctrl; 784*7c478bd9Sstevel@tonic-gate #else 785*7c478bd9Sstevel@tonic-gate int hdlcaddr, hdlcctrl; 786*7c478bd9Sstevel@tonic-gate #endif 787*7c478bd9Sstevel@tonic-gate 788*7c478bd9Sstevel@tonic-gate /* Note: spppcomp already did a pullup to fix the first buffer. */ 789*7c478bd9Sstevel@tonic-gate *mop = NULL; 790*7c478bd9Sstevel@tonic-gate rptr = mi->b_rptr + PPP_HDRLEN; 791*7c478bd9Sstevel@tonic-gate rmax = mi->b_wptr; 792*7c478bd9Sstevel@tonic-gate if (rptr > rmax) { 793*7c478bd9Sstevel@tonic-gate if (state->flags & DS_DEBUG) { 794*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "z_decompress%d: bad buffer\n", 795*7c478bd9Sstevel@tonic-gate state->unit); 796*7c478bd9Sstevel@tonic-gate } 797*7c478bd9Sstevel@tonic-gate freemsg(mi); 798*7c478bd9Sstevel@tonic-gate return (DECOMP_ERROR); 799*7c478bd9Sstevel@tonic-gate } 800*7c478bd9Sstevel@tonic-gate 801*7c478bd9Sstevel@tonic-gate hdlcaddr = rptr[-PPP_HDRLEN]; 802*7c478bd9Sstevel@tonic-gate hdlcctrl = rptr[-PPP_HDRLEN+1]; 803*7c478bd9Sstevel@tonic-gate 804*7c478bd9Sstevel@tonic-gate /* 805*7c478bd9Sstevel@tonic-gate * Note that we free as we go. If we fail to decompress, 806*7c478bd9Sstevel@tonic-gate * there's nothing good that the caller can do. 807*7c478bd9Sstevel@tonic-gate */ 808*7c478bd9Sstevel@tonic-gate #define ADJRPTR() { \ 809*7c478bd9Sstevel@tonic-gate if (rptr != NULL) { \ 810*7c478bd9Sstevel@tonic-gate while (rptr >= rmax) { \ 811*7c478bd9Sstevel@tonic-gate mnext = mi->b_cont; \ 812*7c478bd9Sstevel@tonic-gate freeb(mi); \ 813*7c478bd9Sstevel@tonic-gate if ((mi = mnext) == NULL) { \ 814*7c478bd9Sstevel@tonic-gate rptr = NULL; \ 815*7c478bd9Sstevel@tonic-gate break; \ 816*7c478bd9Sstevel@tonic-gate } \ 817*7c478bd9Sstevel@tonic-gate rptr = mi->b_rptr; \ 818*7c478bd9Sstevel@tonic-gate rmax = mi->b_wptr; \ 819*7c478bd9Sstevel@tonic-gate } \ 820*7c478bd9Sstevel@tonic-gate } \ 821*7c478bd9Sstevel@tonic-gate } 822*7c478bd9Sstevel@tonic-gate 823*7c478bd9Sstevel@tonic-gate /* 824*7c478bd9Sstevel@tonic-gate * Check the sequence number 825*7c478bd9Sstevel@tonic-gate */ 826*7c478bd9Sstevel@tonic-gate ADJRPTR(); 827*7c478bd9Sstevel@tonic-gate seq = rptr == NULL ? 0 : (*rptr++ << 8); 828*7c478bd9Sstevel@tonic-gate ADJRPTR(); 829*7c478bd9Sstevel@tonic-gate if (rptr == NULL) { 830*7c478bd9Sstevel@tonic-gate if (state->flags & DS_DEBUG) { 831*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "z_decompress%d: bad buffer\n", 832*7c478bd9Sstevel@tonic-gate state->unit); 833*7c478bd9Sstevel@tonic-gate } 834*7c478bd9Sstevel@tonic-gate return (DECOMP_ERROR); 835*7c478bd9Sstevel@tonic-gate } 836*7c478bd9Sstevel@tonic-gate 837*7c478bd9Sstevel@tonic-gate seq |= *rptr++; 838*7c478bd9Sstevel@tonic-gate 839*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 840*7c478bd9Sstevel@tonic-gate /* 841*7c478bd9Sstevel@tonic-gate * If testing input, just pretending the sequence is bad here 842*7c478bd9Sstevel@tonic-gate * does the trick. 843*7c478bd9Sstevel@tonic-gate */ 844*7c478bd9Sstevel@tonic-gate if ((state->flags & DS_TESTIN) && (state->seqno % 300) == 101) 845*7c478bd9Sstevel@tonic-gate seq ^= 0x55; 846*7c478bd9Sstevel@tonic-gate #endif 847*7c478bd9Sstevel@tonic-gate if (seq != state->seqno++) { 848*7c478bd9Sstevel@tonic-gate freemsg(mi); 849*7c478bd9Sstevel@tonic-gate if (state->flags & DS_DEBUG) { 850*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 851*7c478bd9Sstevel@tonic-gate "z_decompress%d: bad seq # %d, expected %d\n", 852*7c478bd9Sstevel@tonic-gate state->unit, seq, state->seqno - 1); 853*7c478bd9Sstevel@tonic-gate } 854*7c478bd9Sstevel@tonic-gate return (DECOMP_ERROR); 855*7c478bd9Sstevel@tonic-gate } 856*7c478bd9Sstevel@tonic-gate 857*7c478bd9Sstevel@tonic-gate /* 858*7c478bd9Sstevel@tonic-gate * Allocate an output message block 859*7c478bd9Sstevel@tonic-gate */ 860*7c478bd9Sstevel@tonic-gate mo = allocb(DECOMP_CHUNK + state->hdrlen, BPRI_MED); 861*7c478bd9Sstevel@tonic-gate if (mo == NULL) { 862*7c478bd9Sstevel@tonic-gate freemsg(mi); 863*7c478bd9Sstevel@tonic-gate return (DECOMP_ERROR); 864*7c478bd9Sstevel@tonic-gate } 865*7c478bd9Sstevel@tonic-gate 866*7c478bd9Sstevel@tonic-gate mo_head = mo; 867*7c478bd9Sstevel@tonic-gate mo->b_cont = NULL; 868*7c478bd9Sstevel@tonic-gate mo->b_rptr += state->hdrlen; 869*7c478bd9Sstevel@tonic-gate mo->b_wptr = wptr = mo->b_rptr; 870*7c478bd9Sstevel@tonic-gate 871*7c478bd9Sstevel@tonic-gate ospace = DECOMP_CHUNK; 872*7c478bd9Sstevel@tonic-gate olen = 0; 873*7c478bd9Sstevel@tonic-gate 874*7c478bd9Sstevel@tonic-gate /* 875*7c478bd9Sstevel@tonic-gate * Fill in the first part of the PPP header. The protocol field 876*7c478bd9Sstevel@tonic-gate * comes from the decompressed data. 877*7c478bd9Sstevel@tonic-gate */ 878*7c478bd9Sstevel@tonic-gate *wptr++ = hdlcaddr; 879*7c478bd9Sstevel@tonic-gate *wptr++ = hdlcctrl; 880*7c478bd9Sstevel@tonic-gate *wptr++ = 0; 881*7c478bd9Sstevel@tonic-gate 882*7c478bd9Sstevel@tonic-gate /* 883*7c478bd9Sstevel@tonic-gate * Set up to call inflate. We set avail_out to 1 initially so we can 884*7c478bd9Sstevel@tonic-gate * look at the first byte of the output and decide whether we have 885*7c478bd9Sstevel@tonic-gate * a 1-byte or 2-byte protocol field. 886*7c478bd9Sstevel@tonic-gate */ 887*7c478bd9Sstevel@tonic-gate state->strm.next_in = rptr; 888*7c478bd9Sstevel@tonic-gate state->strm.avail_in = mi->b_wptr - rptr; 889*7c478bd9Sstevel@tonic-gate 890*7c478bd9Sstevel@tonic-gate rlen = state->strm.avail_in + PPP_HDRLEN + DEFLATE_OVHD; 891*7c478bd9Sstevel@tonic-gate 892*7c478bd9Sstevel@tonic-gate state->strm.next_out = wptr; 893*7c478bd9Sstevel@tonic-gate state->strm.avail_out = 1; 894*7c478bd9Sstevel@tonic-gate 895*7c478bd9Sstevel@tonic-gate decode_proto = 1; 896*7c478bd9Sstevel@tonic-gate 897*7c478bd9Sstevel@tonic-gate /* 898*7c478bd9Sstevel@tonic-gate * Call inflate, supplying more input or output as needed. 899*7c478bd9Sstevel@tonic-gate */ 900*7c478bd9Sstevel@tonic-gate for (;;) { 901*7c478bd9Sstevel@tonic-gate 902*7c478bd9Sstevel@tonic-gate flush = (mi == NULL || mi->b_cont == NULL) ? 903*7c478bd9Sstevel@tonic-gate Z_PACKET_FLUSH : Z_NO_FLUSH; 904*7c478bd9Sstevel@tonic-gate r = inflate(&state->strm, flush); 905*7c478bd9Sstevel@tonic-gate 906*7c478bd9Sstevel@tonic-gate if (r != Z_OK) { 907*7c478bd9Sstevel@tonic-gate 908*7c478bd9Sstevel@tonic-gate if (state->flags & DS_DEBUG) { 909*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 910*7c478bd9Sstevel@tonic-gate "z_decompress%d: inflate returned %d " 911*7c478bd9Sstevel@tonic-gate "(%s)\n", state->unit, r, 912*7c478bd9Sstevel@tonic-gate (state->strm.msg? state->strm.msg: "")); 913*7c478bd9Sstevel@tonic-gate } 914*7c478bd9Sstevel@tonic-gate 915*7c478bd9Sstevel@tonic-gate if (mi != NULL) 916*7c478bd9Sstevel@tonic-gate freemsg(mi); 917*7c478bd9Sstevel@tonic-gate freemsg(mo_head); 918*7c478bd9Sstevel@tonic-gate 919*7c478bd9Sstevel@tonic-gate return (DECOMP_FATALERROR); 920*7c478bd9Sstevel@tonic-gate } 921*7c478bd9Sstevel@tonic-gate 922*7c478bd9Sstevel@tonic-gate if (state->strm.avail_in == 0) { 923*7c478bd9Sstevel@tonic-gate if (mi != NULL) { 924*7c478bd9Sstevel@tonic-gate mnext = mi->b_cont; 925*7c478bd9Sstevel@tonic-gate freeb(mi); 926*7c478bd9Sstevel@tonic-gate mi = mnext; 927*7c478bd9Sstevel@tonic-gate } 928*7c478bd9Sstevel@tonic-gate if (mi == NULL) { 929*7c478bd9Sstevel@tonic-gate if (state->strm.avail_out != 0) 930*7c478bd9Sstevel@tonic-gate break; /* all done */ 931*7c478bd9Sstevel@tonic-gate } else { 932*7c478bd9Sstevel@tonic-gate state->strm.next_in = mi->b_rptr; 933*7c478bd9Sstevel@tonic-gate state->strm.avail_in = mi->b_wptr - mi->b_rptr; 934*7c478bd9Sstevel@tonic-gate 935*7c478bd9Sstevel@tonic-gate rlen += state->strm.avail_in; 936*7c478bd9Sstevel@tonic-gate } 937*7c478bd9Sstevel@tonic-gate } 938*7c478bd9Sstevel@tonic-gate 939*7c478bd9Sstevel@tonic-gate if (state->strm.avail_out == 0) { 940*7c478bd9Sstevel@tonic-gate if (decode_proto) { 941*7c478bd9Sstevel@tonic-gate state->strm.avail_out = ospace - PPP_HDRLEN; 942*7c478bd9Sstevel@tonic-gate 943*7c478bd9Sstevel@tonic-gate if ((wptr[0] & 1) == 0) { 944*7c478bd9Sstevel@tonic-gate /* 945*7c478bd9Sstevel@tonic-gate * 2-byte protocol field 946*7c478bd9Sstevel@tonic-gate */ 947*7c478bd9Sstevel@tonic-gate wptr[-1] = wptr[0]; 948*7c478bd9Sstevel@tonic-gate 949*7c478bd9Sstevel@tonic-gate --state->strm.next_out; 950*7c478bd9Sstevel@tonic-gate ++state->strm.avail_out; 951*7c478bd9Sstevel@tonic-gate } 952*7c478bd9Sstevel@tonic-gate 953*7c478bd9Sstevel@tonic-gate decode_proto = 0; 954*7c478bd9Sstevel@tonic-gate } else { 955*7c478bd9Sstevel@tonic-gate mo->b_wptr += ospace; 956*7c478bd9Sstevel@tonic-gate olen += ospace; 957*7c478bd9Sstevel@tonic-gate 958*7c478bd9Sstevel@tonic-gate mo->b_cont = allocb(DECOMP_CHUNK, BPRI_MED); 959*7c478bd9Sstevel@tonic-gate 960*7c478bd9Sstevel@tonic-gate mo = mo->b_cont; 961*7c478bd9Sstevel@tonic-gate if (mo == NULL) { 962*7c478bd9Sstevel@tonic-gate if (mi != NULL) 963*7c478bd9Sstevel@tonic-gate freemsg(mi); 964*7c478bd9Sstevel@tonic-gate freemsg(mo_head); 965*7c478bd9Sstevel@tonic-gate return (DECOMP_ERROR); 966*7c478bd9Sstevel@tonic-gate } 967*7c478bd9Sstevel@tonic-gate 968*7c478bd9Sstevel@tonic-gate state->strm.next_out = mo->b_rptr; 969*7c478bd9Sstevel@tonic-gate state->strm.avail_out = ospace = DECOMP_CHUNK; 970*7c478bd9Sstevel@tonic-gate } 971*7c478bd9Sstevel@tonic-gate } 972*7c478bd9Sstevel@tonic-gate } 973*7c478bd9Sstevel@tonic-gate 974*7c478bd9Sstevel@tonic-gate if (decode_proto) { 975*7c478bd9Sstevel@tonic-gate freemsg(mo_head); 976*7c478bd9Sstevel@tonic-gate return (DECOMP_ERROR); 977*7c478bd9Sstevel@tonic-gate } 978*7c478bd9Sstevel@tonic-gate 979*7c478bd9Sstevel@tonic-gate mo->b_wptr += ospace - state->strm.avail_out; 980*7c478bd9Sstevel@tonic-gate olen += ospace - state->strm.avail_out; 981*7c478bd9Sstevel@tonic-gate 982*7c478bd9Sstevel@tonic-gate if ((olen > state->mru + PPP_HDRLEN) && (state->flags & DS_DEBUG)) { 983*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "z_decompress%d: exceeded mru (%d > %d)\n", 984*7c478bd9Sstevel@tonic-gate state->unit, olen, state->mru + PPP_HDRLEN); 985*7c478bd9Sstevel@tonic-gate } 986*7c478bd9Sstevel@tonic-gate 987*7c478bd9Sstevel@tonic-gate state->stats.unc_bytes += olen; 988*7c478bd9Sstevel@tonic-gate state->stats.unc_packets++; 989*7c478bd9Sstevel@tonic-gate state->stats.comp_bytes += rlen; 990*7c478bd9Sstevel@tonic-gate state->stats.comp_packets++; 991*7c478bd9Sstevel@tonic-gate 992*7c478bd9Sstevel@tonic-gate *mop = mo_head; 993*7c478bd9Sstevel@tonic-gate 994*7c478bd9Sstevel@tonic-gate return (DECOMP_OK); 995*7c478bd9Sstevel@tonic-gate } 996*7c478bd9Sstevel@tonic-gate 997*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 998*7c478bd9Sstevel@tonic-gate static int 999*7c478bd9Sstevel@tonic-gate z_set_effort(void *xarg, void *rarg, int effortlevel) 1000*7c478bd9Sstevel@tonic-gate { 1001*7c478bd9Sstevel@tonic-gate struct deflate_state *xstate = (struct deflate_state *)xarg; 1002*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 1003*7c478bd9Sstevel@tonic-gate struct deflate_state *rstate = (struct deflate_state *)rarg; 1004*7c478bd9Sstevel@tonic-gate #endif 1005*7c478bd9Sstevel@tonic-gate int retv; 1006*7c478bd9Sstevel@tonic-gate 1007*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 1008*7c478bd9Sstevel@tonic-gate if (effortlevel == 42 || effortlevel == 2112) { 1009*7c478bd9Sstevel@tonic-gate /* corrupt received data. */ 1010*7c478bd9Sstevel@tonic-gate if (rstate != NULL) { 1011*7c478bd9Sstevel@tonic-gate rstate->flags |= DS_TESTIN; 1012*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "deflate: enabled input testing."); 1013*7c478bd9Sstevel@tonic-gate } 1014*7c478bd9Sstevel@tonic-gate if (effortlevel != 2112) 1015*7c478bd9Sstevel@tonic-gate return (0); 1016*7c478bd9Sstevel@tonic-gate } 1017*7c478bd9Sstevel@tonic-gate if (effortlevel == 2001 || effortlevel == 2112) { 1018*7c478bd9Sstevel@tonic-gate /* corrupt transmitted data. */ 1019*7c478bd9Sstevel@tonic-gate if (xstate != NULL) { 1020*7c478bd9Sstevel@tonic-gate xstate->flags |= DS_TESTOUT; 1021*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "deflate: enabled output testing."); 1022*7c478bd9Sstevel@tonic-gate } 1023*7c478bd9Sstevel@tonic-gate return (0); 1024*7c478bd9Sstevel@tonic-gate } 1025*7c478bd9Sstevel@tonic-gate #endif 1026*7c478bd9Sstevel@tonic-gate if (effortlevel < -1 || effortlevel > 9) 1027*7c478bd9Sstevel@tonic-gate return (EINVAL); 1028*7c478bd9Sstevel@tonic-gate if (xstate == NULL) 1029*7c478bd9Sstevel@tonic-gate return (0); 1030*7c478bd9Sstevel@tonic-gate retv = deflateParams(&xstate->strm, effortlevel, Z_DEFAULT_STRATEGY); 1031*7c478bd9Sstevel@tonic-gate return (retv == Z_OK ? 0 : EINVAL); 1032*7c478bd9Sstevel@tonic-gate } 1033*7c478bd9Sstevel@tonic-gate 1034*7c478bd9Sstevel@tonic-gate #endif /* DO_DEFLATE */ 1035