10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * deflate.c - interface the zlib procedures for Deflate compression
30Sstevel@tonic-gate * and decompression (as used by gzip) to the PPP code.
40Sstevel@tonic-gate *
50Sstevel@tonic-gate * This version is for use with STREAMS in Solaris 2
60Sstevel@tonic-gate *
70Sstevel@tonic-gate * Copyright (c) 2001 by Sun Microsystems, Inc.
80Sstevel@tonic-gate * All rights reserved.
90Sstevel@tonic-gate *
100Sstevel@tonic-gate * Copyright (c) 1994 The Australian National University.
110Sstevel@tonic-gate * All rights reserved.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software and its
140Sstevel@tonic-gate * documentation is hereby granted, provided that the above copyright
150Sstevel@tonic-gate * notice appears in all copies. This software is provided without any
160Sstevel@tonic-gate * warranty, express or implied. The Australian National University
170Sstevel@tonic-gate * makes no representations about the suitability of this software for
180Sstevel@tonic-gate * any purpose.
190Sstevel@tonic-gate *
200Sstevel@tonic-gate * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
210Sstevel@tonic-gate * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
220Sstevel@tonic-gate * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
230Sstevel@tonic-gate * THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY
240Sstevel@tonic-gate * OF SUCH DAMAGE.
250Sstevel@tonic-gate *
260Sstevel@tonic-gate * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
270Sstevel@tonic-gate * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
280Sstevel@tonic-gate * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
290Sstevel@tonic-gate * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
300Sstevel@tonic-gate * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
310Sstevel@tonic-gate * OR MODIFICATIONS.
320Sstevel@tonic-gate *
330Sstevel@tonic-gate * $Id: deflate.c,v 1.9 1999/01/19 23:58:35 paulus Exp $
340Sstevel@tonic-gate */
350Sstevel@tonic-gate
36*7767SJohn.Beck@Sun.COM #define NO_DUMMY_DECL
370Sstevel@tonic-gate
380Sstevel@tonic-gate #include <sys/param.h>
390Sstevel@tonic-gate #include <sys/types.h>
400Sstevel@tonic-gate #include <sys/kmem.h>
410Sstevel@tonic-gate #include <sys/stream.h>
420Sstevel@tonic-gate #include <sys/cmn_err.h>
430Sstevel@tonic-gate #include <sys/ddi.h>
440Sstevel@tonic-gate #include <sys/sunddi.h>
450Sstevel@tonic-gate #include <sys/errno.h>
460Sstevel@tonic-gate #include <net/ppp_defs.h>
470Sstevel@tonic-gate
480Sstevel@tonic-gate /* Defined for platform-neutral include file */
490Sstevel@tonic-gate #define PACKETPTR mblk_t *
500Sstevel@tonic-gate #include <net/ppp-comp.h>
510Sstevel@tonic-gate #include "s_common.h"
520Sstevel@tonic-gate #include "zlib.h"
530Sstevel@tonic-gate
540Sstevel@tonic-gate #if DO_DEFLATE
550Sstevel@tonic-gate
560Sstevel@tonic-gate /*
570Sstevel@tonic-gate * State for a Deflate (de)compressor.
580Sstevel@tonic-gate */
590Sstevel@tonic-gate struct deflate_state {
600Sstevel@tonic-gate int seqno;
610Sstevel@tonic-gate int w_size;
620Sstevel@tonic-gate int unit;
630Sstevel@tonic-gate int hdrlen;
640Sstevel@tonic-gate int mru;
650Sstevel@tonic-gate int flags;
660Sstevel@tonic-gate z_stream strm;
670Sstevel@tonic-gate struct compstat stats;
680Sstevel@tonic-gate };
690Sstevel@tonic-gate
700Sstevel@tonic-gate #define DEFLATE_OVHD 2 /* Deflate overhead/packet */
710Sstevel@tonic-gate
720Sstevel@tonic-gate #define DS_DEBUG 0x0001
730Sstevel@tonic-gate #define DS_TESTIN 0x0002
740Sstevel@tonic-gate #define DS_TESTOUT 0x0004
750Sstevel@tonic-gate
760Sstevel@tonic-gate static void *z_alloc(void *, uint_t items, uint_t size);
770Sstevel@tonic-gate static void z_free(void *, void *ptr);
780Sstevel@tonic-gate static void *z_comp_alloc(uchar_t *options, int opt_len);
790Sstevel@tonic-gate static void *z_decomp_alloc(uchar_t *options, int opt_len);
800Sstevel@tonic-gate static void z_comp_free(void *state);
810Sstevel@tonic-gate static void z_decomp_free(void *state);
820Sstevel@tonic-gate static int z_comp_init(void *state, uchar_t *options, int opt_len,
830Sstevel@tonic-gate int unit, int hdrlen, int debug);
840Sstevel@tonic-gate static int z_decomp_init(void *state, uchar_t *options, int opt_len,
850Sstevel@tonic-gate int unit, int hdrlen, int mru, int debug);
860Sstevel@tonic-gate static int z_compress(void *state, mblk_t **mret,
870Sstevel@tonic-gate mblk_t *mp, int slen, int maxolen);
880Sstevel@tonic-gate static int z_incomp(void *state, mblk_t *dmsg);
890Sstevel@tonic-gate static int z_decompress(void *state, mblk_t **dmpp);
900Sstevel@tonic-gate static void z_comp_reset(void *state);
910Sstevel@tonic-gate static void z_decomp_reset(void *state);
920Sstevel@tonic-gate static void z_comp_stats(void *state, struct compstat *stats);
930Sstevel@tonic-gate static int z_set_effort(void *xstate, void *rstate, int effortlevel);
940Sstevel@tonic-gate
950Sstevel@tonic-gate /*
960Sstevel@tonic-gate * Procedures exported to ppp_comp.c.
970Sstevel@tonic-gate */
980Sstevel@tonic-gate struct compressor ppp_deflate = {
990Sstevel@tonic-gate CI_DEFLATE, /* compress_proto */
1000Sstevel@tonic-gate z_comp_alloc, /* comp_alloc */
1010Sstevel@tonic-gate z_comp_free, /* comp_free */
1020Sstevel@tonic-gate z_comp_init, /* comp_init */
1030Sstevel@tonic-gate z_comp_reset, /* comp_reset */
1040Sstevel@tonic-gate z_compress, /* compress */
1050Sstevel@tonic-gate z_comp_stats, /* comp_stat */
1060Sstevel@tonic-gate z_decomp_alloc, /* decomp_alloc */
1070Sstevel@tonic-gate z_decomp_free, /* decomp_free */
1080Sstevel@tonic-gate z_decomp_init, /* decomp_init */
1090Sstevel@tonic-gate z_decomp_reset, /* decomp_reset */
1100Sstevel@tonic-gate z_decompress, /* decompress */
1110Sstevel@tonic-gate z_incomp, /* incomp */
1120Sstevel@tonic-gate z_comp_stats, /* decomp_stat */
1130Sstevel@tonic-gate z_set_effort, /* set_effort */
1140Sstevel@tonic-gate };
1150Sstevel@tonic-gate
1160Sstevel@tonic-gate struct compressor ppp_deflate_draft = {
1170Sstevel@tonic-gate CI_DEFLATE_DRAFT, /* compress_proto */
1180Sstevel@tonic-gate z_comp_alloc, /* comp_alloc */
1190Sstevel@tonic-gate z_comp_free, /* comp_free */
1200Sstevel@tonic-gate z_comp_init, /* comp_init */
1210Sstevel@tonic-gate z_comp_reset, /* comp_reset */
1220Sstevel@tonic-gate z_compress, /* compress */
1230Sstevel@tonic-gate z_comp_stats, /* comp_stat */
1240Sstevel@tonic-gate z_decomp_alloc, /* decomp_alloc */
1250Sstevel@tonic-gate z_decomp_free, /* decomp_free */
1260Sstevel@tonic-gate z_decomp_init, /* decomp_init */
1270Sstevel@tonic-gate z_decomp_reset, /* decomp_reset */
1280Sstevel@tonic-gate z_decompress, /* decompress */
1290Sstevel@tonic-gate z_incomp, /* incomp */
1300Sstevel@tonic-gate z_comp_stats, /* decomp_stat */
1310Sstevel@tonic-gate z_set_effort, /* set_effort */
1320Sstevel@tonic-gate };
1330Sstevel@tonic-gate
1340Sstevel@tonic-gate #define DECOMP_CHUNK 512
1350Sstevel@tonic-gate
1360Sstevel@tonic-gate /*
1370Sstevel@tonic-gate * Space allocation and freeing routines for use by zlib routines.
1380Sstevel@tonic-gate */
1390Sstevel@tonic-gate struct zchunk {
1400Sstevel@tonic-gate uint_t size;
1410Sstevel@tonic-gate uint_t guard;
1420Sstevel@tonic-gate };
1430Sstevel@tonic-gate
1440Sstevel@tonic-gate #define GUARD_MAGIC 0x77a6011a
1450Sstevel@tonic-gate
1460Sstevel@tonic-gate /*
1470Sstevel@tonic-gate * z_alloc()
1480Sstevel@tonic-gate */
1490Sstevel@tonic-gate /* ARGSUSED */
1500Sstevel@tonic-gate static void *
z_alloc(void * notused,uint_t items,uint_t size)1510Sstevel@tonic-gate z_alloc(void *notused, uint_t items, uint_t size)
1520Sstevel@tonic-gate {
1530Sstevel@tonic-gate struct zchunk *z;
1540Sstevel@tonic-gate
1550Sstevel@tonic-gate size = items * size + sizeof (struct zchunk);
1560Sstevel@tonic-gate
1570Sstevel@tonic-gate z = (struct zchunk *)kmem_alloc(size, KM_NOSLEEP);
1580Sstevel@tonic-gate if (z == NULL)
1590Sstevel@tonic-gate return (NULL);
1600Sstevel@tonic-gate
1610Sstevel@tonic-gate z->size = size;
1620Sstevel@tonic-gate z->guard = GUARD_MAGIC;
1630Sstevel@tonic-gate
1640Sstevel@tonic-gate return ((void *)(z + 1));
1650Sstevel@tonic-gate }
1660Sstevel@tonic-gate
1670Sstevel@tonic-gate /*
1680Sstevel@tonic-gate * z_free()
1690Sstevel@tonic-gate */
1700Sstevel@tonic-gate /* ARGSUSED */
1710Sstevel@tonic-gate static void
z_free(void * notused,void * ptr)1720Sstevel@tonic-gate z_free(void *notused, void *ptr)
1730Sstevel@tonic-gate {
1740Sstevel@tonic-gate struct zchunk *z = ((struct zchunk *)ptr) - 1;
1750Sstevel@tonic-gate
1760Sstevel@tonic-gate if (ptr == NULL)
1770Sstevel@tonic-gate return;
1780Sstevel@tonic-gate
1790Sstevel@tonic-gate if (z->guard != GUARD_MAGIC) {
1800Sstevel@tonic-gate cmn_err(CE_CONT,
1810Sstevel@tonic-gate "deflate: z_free of corrupted chunk at 0x%p (%x, %x)\n",
1820Sstevel@tonic-gate (void *)z, z->size, z->guard);
1830Sstevel@tonic-gate
1840Sstevel@tonic-gate return;
1850Sstevel@tonic-gate }
1860Sstevel@tonic-gate
1870Sstevel@tonic-gate kmem_free(z, z->size);
1880Sstevel@tonic-gate }
1890Sstevel@tonic-gate
1900Sstevel@tonic-gate /*
1910Sstevel@tonic-gate * Allocate space for a compressor.
1920Sstevel@tonic-gate */
1930Sstevel@tonic-gate static void *
z_comp_alloc(uchar_t * options,int opt_len)1940Sstevel@tonic-gate z_comp_alloc(uchar_t *options, int opt_len)
1950Sstevel@tonic-gate {
1960Sstevel@tonic-gate struct deflate_state *state;
1970Sstevel@tonic-gate int w_size;
1980Sstevel@tonic-gate
1990Sstevel@tonic-gate if (opt_len != CILEN_DEFLATE ||
2000Sstevel@tonic-gate (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) ||
2010Sstevel@tonic-gate options[1] != CILEN_DEFLATE ||
2020Sstevel@tonic-gate DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL ||
2030Sstevel@tonic-gate options[3] != DEFLATE_CHK_SEQUENCE) {
2040Sstevel@tonic-gate
2050Sstevel@tonic-gate return (NULL);
2060Sstevel@tonic-gate }
2070Sstevel@tonic-gate
2080Sstevel@tonic-gate w_size = DEFLATE_SIZE(options[2]);
2090Sstevel@tonic-gate /*
2100Sstevel@tonic-gate * Check <= minimum size to avoid unfixable zlib bug -- window size
2110Sstevel@tonic-gate * 256 (w_size 8) is not supported.
2120Sstevel@tonic-gate */
2130Sstevel@tonic-gate if (w_size <= DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE) {
2140Sstevel@tonic-gate return (NULL);
2150Sstevel@tonic-gate }
2160Sstevel@tonic-gate
2170Sstevel@tonic-gate state = (struct deflate_state *)kmem_zalloc(sizeof (*state), KM_SLEEP);
2180Sstevel@tonic-gate ASSERT(state != NULL);
2190Sstevel@tonic-gate
2200Sstevel@tonic-gate state->strm.zalloc = (alloc_func)z_alloc;
2210Sstevel@tonic-gate state->strm.zfree = (free_func)z_free;
2220Sstevel@tonic-gate
2230Sstevel@tonic-gate if (deflateInit2(&state->strm, Z_DEFAULT_COMPRESSION,
2240Sstevel@tonic-gate DEFLATE_METHOD_VAL, -w_size, 8, Z_DEFAULT_STRATEGY) != Z_OK) {
2250Sstevel@tonic-gate
2260Sstevel@tonic-gate kmem_free(state, sizeof (*state));
2270Sstevel@tonic-gate
2280Sstevel@tonic-gate return (NULL);
2290Sstevel@tonic-gate }
2300Sstevel@tonic-gate
2310Sstevel@tonic-gate state->w_size = w_size;
2320Sstevel@tonic-gate
2330Sstevel@tonic-gate bzero(&state->stats, sizeof (state->stats));
2340Sstevel@tonic-gate
2350Sstevel@tonic-gate return ((void *)state);
2360Sstevel@tonic-gate }
2370Sstevel@tonic-gate
2380Sstevel@tonic-gate /*
2390Sstevel@tonic-gate * z_comp_free()
2400Sstevel@tonic-gate */
2410Sstevel@tonic-gate static void
z_comp_free(void * arg)2420Sstevel@tonic-gate z_comp_free(void *arg)
2430Sstevel@tonic-gate {
2440Sstevel@tonic-gate struct deflate_state *state = (struct deflate_state *)arg;
2450Sstevel@tonic-gate
2460Sstevel@tonic-gate (void) deflateEnd(&state->strm);
2470Sstevel@tonic-gate
2480Sstevel@tonic-gate kmem_free(state, sizeof (*state));
2490Sstevel@tonic-gate }
2500Sstevel@tonic-gate
2510Sstevel@tonic-gate /*
2520Sstevel@tonic-gate * z_comp_init()
2530Sstevel@tonic-gate */
2540Sstevel@tonic-gate static int
z_comp_init(void * arg,uchar_t * options,int opt_len,int unit,int hdrlen,int debug)2550Sstevel@tonic-gate z_comp_init(void *arg, uchar_t *options, int opt_len, int unit, int hdrlen,
2560Sstevel@tonic-gate int debug)
2570Sstevel@tonic-gate {
2580Sstevel@tonic-gate struct deflate_state *state = (struct deflate_state *)arg;
2590Sstevel@tonic-gate
2600Sstevel@tonic-gate if (opt_len < CILEN_DEFLATE ||
2610Sstevel@tonic-gate (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) ||
2620Sstevel@tonic-gate options[1] != CILEN_DEFLATE ||
2630Sstevel@tonic-gate DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL ||
2640Sstevel@tonic-gate DEFLATE_SIZE(options[2]) != state->w_size ||
2650Sstevel@tonic-gate options[3] != DEFLATE_CHK_SEQUENCE) {
2660Sstevel@tonic-gate
2670Sstevel@tonic-gate return (0);
2680Sstevel@tonic-gate }
2690Sstevel@tonic-gate
2700Sstevel@tonic-gate state->seqno = 0;
2710Sstevel@tonic-gate state->unit = unit;
2720Sstevel@tonic-gate state->hdrlen = hdrlen;
2730Sstevel@tonic-gate if (debug)
2740Sstevel@tonic-gate state->flags |= DS_DEBUG;
2750Sstevel@tonic-gate else
2760Sstevel@tonic-gate state->flags &= ~DS_DEBUG;
2770Sstevel@tonic-gate
2780Sstevel@tonic-gate (void) deflateReset(&state->strm);
2790Sstevel@tonic-gate
2800Sstevel@tonic-gate return (1);
2810Sstevel@tonic-gate }
2820Sstevel@tonic-gate
2830Sstevel@tonic-gate /*
2840Sstevel@tonic-gate * z_comp_reset()
2850Sstevel@tonic-gate */
2860Sstevel@tonic-gate static void
z_comp_reset(void * arg)2870Sstevel@tonic-gate z_comp_reset(void *arg)
2880Sstevel@tonic-gate {
2890Sstevel@tonic-gate struct deflate_state *state = (struct deflate_state *)arg;
2900Sstevel@tonic-gate
2910Sstevel@tonic-gate state->seqno = 0;
2920Sstevel@tonic-gate
2930Sstevel@tonic-gate (void) deflateReset(&state->strm);
2940Sstevel@tonic-gate }
2950Sstevel@tonic-gate
2960Sstevel@tonic-gate /*
2970Sstevel@tonic-gate * z_compress()
2980Sstevel@tonic-gate */
2990Sstevel@tonic-gate static int
z_compress(void * arg,mblk_t ** mret,mblk_t * mp,int orig_len,int maxolen)3000Sstevel@tonic-gate z_compress(void *arg, mblk_t **mret, mblk_t *mp, int orig_len, int maxolen)
3010Sstevel@tonic-gate {
3020Sstevel@tonic-gate struct deflate_state *state = (struct deflate_state *)arg;
3030Sstevel@tonic-gate uchar_t *rptr, *rmax;
3040Sstevel@tonic-gate uchar_t *wptr;
3050Sstevel@tonic-gate int olen;
3060Sstevel@tonic-gate int wspace;
3070Sstevel@tonic-gate int r;
3080Sstevel@tonic-gate int flush;
3090Sstevel@tonic-gate mblk_t *m;
3100Sstevel@tonic-gate #if defined(lint) || defined(_lint)
3110Sstevel@tonic-gate uchar_t hdlcaddr, hdlcctrl;
3120Sstevel@tonic-gate #else
3130Sstevel@tonic-gate int hdlcaddr, hdlcctrl;
3140Sstevel@tonic-gate #endif
3150Sstevel@tonic-gate
3160Sstevel@tonic-gate #define ADJRPTR() { \
3170Sstevel@tonic-gate if (rptr != NULL) { \
3180Sstevel@tonic-gate while (rptr >= rmax) { \
3190Sstevel@tonic-gate if ((mp = mp->b_cont) == NULL) { \
3200Sstevel@tonic-gate rptr = NULL; \
3210Sstevel@tonic-gate break; \
3220Sstevel@tonic-gate } \
3230Sstevel@tonic-gate rptr = mp->b_rptr; \
3240Sstevel@tonic-gate rmax = mp->b_wptr; \
3250Sstevel@tonic-gate } \
3260Sstevel@tonic-gate } \
3270Sstevel@tonic-gate }
3280Sstevel@tonic-gate
3290Sstevel@tonic-gate #define GETBYTE(v) { \
3300Sstevel@tonic-gate if (rptr != NULL) { \
3310Sstevel@tonic-gate (v) = *rptr++; \
3320Sstevel@tonic-gate } \
3330Sstevel@tonic-gate }
3340Sstevel@tonic-gate
3350Sstevel@tonic-gate /*
3360Sstevel@tonic-gate * Check that the protocol is one we handle. Pullup is *NOT*
3370Sstevel@tonic-gate * possible here.
3380Sstevel@tonic-gate */
3390Sstevel@tonic-gate *mret = NULL;
3400Sstevel@tonic-gate rptr = mp->b_rptr;
3410Sstevel@tonic-gate rmax = mp->b_wptr;
3420Sstevel@tonic-gate ADJRPTR();
3430Sstevel@tonic-gate GETBYTE(hdlcaddr);
3440Sstevel@tonic-gate ADJRPTR();
3450Sstevel@tonic-gate GETBYTE(hdlcctrl);
3460Sstevel@tonic-gate ADJRPTR();
3470Sstevel@tonic-gate
3480Sstevel@tonic-gate /*
3490Sstevel@tonic-gate * Per RFC 1979, the protocol field must be compressed using a
3500Sstevel@tonic-gate * PFC-like procedure. Also, all protocols between 0000-3FFF
3510Sstevel@tonic-gate * except the two compression protocols must be LZ compressed.
3520Sstevel@tonic-gate */
3530Sstevel@tonic-gate if (rptr == NULL)
3540Sstevel@tonic-gate return (orig_len);
3550Sstevel@tonic-gate r = *rptr;
3560Sstevel@tonic-gate if (r == 0) {
3570Sstevel@tonic-gate rptr++;
3580Sstevel@tonic-gate ADJRPTR();
3590Sstevel@tonic-gate if (rptr == NULL || *rptr == PPP_COMP || *rptr == PPP_COMPFRAG)
3600Sstevel@tonic-gate return (orig_len);
3610Sstevel@tonic-gate } else {
3620Sstevel@tonic-gate if (r > 0x3F)
3630Sstevel@tonic-gate return (orig_len);
3640Sstevel@tonic-gate }
3650Sstevel@tonic-gate
3660Sstevel@tonic-gate /*
3670Sstevel@tonic-gate * Allocate one mblk initially
3680Sstevel@tonic-gate */
3690Sstevel@tonic-gate if (maxolen > orig_len) {
3700Sstevel@tonic-gate maxolen = orig_len;
3710Sstevel@tonic-gate }
3720Sstevel@tonic-gate
3730Sstevel@tonic-gate if (maxolen <= PPP_HDRLEN + 2) {
3740Sstevel@tonic-gate wspace = 0;
3750Sstevel@tonic-gate m = NULL;
3760Sstevel@tonic-gate } else {
3770Sstevel@tonic-gate wspace = maxolen + state->hdrlen;
3780Sstevel@tonic-gate if (wspace > 4096) {
3790Sstevel@tonic-gate wspace = 4096;
3800Sstevel@tonic-gate }
3810Sstevel@tonic-gate
3820Sstevel@tonic-gate m = allocb(wspace, BPRI_MED);
3830Sstevel@tonic-gate }
3840Sstevel@tonic-gate
3850Sstevel@tonic-gate if (m != NULL) {
3860Sstevel@tonic-gate
3870Sstevel@tonic-gate wspace = m->b_datap->db_lim - m->b_wptr;
3880Sstevel@tonic-gate
3890Sstevel@tonic-gate *mret = m;
3900Sstevel@tonic-gate
3910Sstevel@tonic-gate if (state->hdrlen + PPP_HDRLEN + 2 < wspace) {
3920Sstevel@tonic-gate m->b_rptr += state->hdrlen;
3930Sstevel@tonic-gate m->b_wptr = m->b_rptr;
3940Sstevel@tonic-gate wspace -= state->hdrlen;
3950Sstevel@tonic-gate }
3960Sstevel@tonic-gate
3970Sstevel@tonic-gate wptr = m->b_wptr;
3980Sstevel@tonic-gate
3990Sstevel@tonic-gate /*
4000Sstevel@tonic-gate * Copy over the PPP header and store the 2-byte
4010Sstevel@tonic-gate * sequence number
4020Sstevel@tonic-gate */
4030Sstevel@tonic-gate wptr[0] = hdlcaddr;
4040Sstevel@tonic-gate wptr[1] = hdlcctrl;
4050Sstevel@tonic-gate wptr[2] = PPP_COMP >> 8;
4060Sstevel@tonic-gate wptr[3] = PPP_COMP;
4070Sstevel@tonic-gate
4080Sstevel@tonic-gate wptr += PPP_HDRLEN;
4090Sstevel@tonic-gate
4100Sstevel@tonic-gate wptr[0] = state->seqno >> 8;
4110Sstevel@tonic-gate wptr[1] = state->seqno;
4120Sstevel@tonic-gate wptr += 2;
4130Sstevel@tonic-gate
4140Sstevel@tonic-gate #ifdef DEBUG
4150Sstevel@tonic-gate /*
4160Sstevel@tonic-gate * If testing output, just garbling the sequence here
4170Sstevel@tonic-gate * does the trick.
4180Sstevel@tonic-gate */
4190Sstevel@tonic-gate if ((state->flags & DS_TESTOUT) && (state->seqno % 100) == 50)
4200Sstevel@tonic-gate wptr[-1] ^= 0xAA;
4210Sstevel@tonic-gate #endif
4220Sstevel@tonic-gate
4230Sstevel@tonic-gate state->strm.next_out = wptr;
4240Sstevel@tonic-gate state->strm.avail_out = wspace - (PPP_HDRLEN + 2);
4250Sstevel@tonic-gate } else {
4260Sstevel@tonic-gate state->strm.next_out = NULL;
4270Sstevel@tonic-gate state->strm.avail_out = 1000000;
4280Sstevel@tonic-gate }
4290Sstevel@tonic-gate
4300Sstevel@tonic-gate ++state->seqno;
4310Sstevel@tonic-gate
4320Sstevel@tonic-gate state->strm.next_in = rptr;
4330Sstevel@tonic-gate state->strm.avail_in = mp->b_wptr - rptr;
4340Sstevel@tonic-gate
4350Sstevel@tonic-gate olen = 0;
4360Sstevel@tonic-gate
4370Sstevel@tonic-gate for (;;) {
4380Sstevel@tonic-gate flush = (mp == NULL || mp->b_cont == NULL) ? Z_PACKET_FLUSH :
4390Sstevel@tonic-gate Z_NO_FLUSH;
4400Sstevel@tonic-gate r = deflate(&state->strm, flush);
4410Sstevel@tonic-gate
4420Sstevel@tonic-gate if (r != Z_OK) {
4430Sstevel@tonic-gate cmn_err(CE_CONT,
4440Sstevel@tonic-gate "z_compress%d: deflate returned %d (%s)\n",
4450Sstevel@tonic-gate state->unit, r,
4460Sstevel@tonic-gate (state->strm.msg? state->strm.msg: ""));
4470Sstevel@tonic-gate
4480Sstevel@tonic-gate break;
4490Sstevel@tonic-gate }
4500Sstevel@tonic-gate
4510Sstevel@tonic-gate if (state->strm.avail_in == 0) {
4520Sstevel@tonic-gate if (mp != NULL)
4530Sstevel@tonic-gate mp = mp->b_cont;
4540Sstevel@tonic-gate if (mp == NULL) {
4550Sstevel@tonic-gate if (state->strm.avail_out != 0)
4560Sstevel@tonic-gate break; /* all done */
4570Sstevel@tonic-gate } else {
4580Sstevel@tonic-gate state->strm.next_in = mp->b_rptr;
4590Sstevel@tonic-gate state->strm.avail_in = mp->b_wptr - mp->b_rptr;
4600Sstevel@tonic-gate }
4610Sstevel@tonic-gate }
4620Sstevel@tonic-gate
4630Sstevel@tonic-gate if (state->strm.avail_out == 0) {
4640Sstevel@tonic-gate if (m != NULL) {
4650Sstevel@tonic-gate m->b_wptr += wspace;
4660Sstevel@tonic-gate olen += wspace;
4670Sstevel@tonic-gate wspace = maxolen - olen;
4680Sstevel@tonic-gate
4690Sstevel@tonic-gate if (wspace <= 0) {
4700Sstevel@tonic-gate wspace = 0;
4710Sstevel@tonic-gate m->b_cont = NULL;
4720Sstevel@tonic-gate } else {
4730Sstevel@tonic-gate if (wspace < 32) {
4740Sstevel@tonic-gate wspace = 32;
4750Sstevel@tonic-gate } else if (wspace > 4096) {
4760Sstevel@tonic-gate wspace = 4096;
4770Sstevel@tonic-gate }
4780Sstevel@tonic-gate
4790Sstevel@tonic-gate m->b_cont = allocb(wspace, BPRI_MED);
4800Sstevel@tonic-gate }
4810Sstevel@tonic-gate
4820Sstevel@tonic-gate m = m->b_cont;
4830Sstevel@tonic-gate
4840Sstevel@tonic-gate if (m != NULL) {
4850Sstevel@tonic-gate state->strm.next_out = m->b_wptr;
4860Sstevel@tonic-gate wspace = m->b_datap->db_lim -
4870Sstevel@tonic-gate m->b_wptr;
4880Sstevel@tonic-gate state->strm.avail_out = wspace;
4890Sstevel@tonic-gate }
4900Sstevel@tonic-gate }
4910Sstevel@tonic-gate
4920Sstevel@tonic-gate if (m == NULL) {
4930Sstevel@tonic-gate state->strm.next_out = NULL;
4940Sstevel@tonic-gate state->strm.avail_out = 1000000;
4950Sstevel@tonic-gate }
4960Sstevel@tonic-gate }
4970Sstevel@tonic-gate }
4980Sstevel@tonic-gate
4990Sstevel@tonic-gate if (m != NULL) {
5000Sstevel@tonic-gate m->b_wptr += wspace - state->strm.avail_out;
5010Sstevel@tonic-gate olen += wspace - state->strm.avail_out;
5020Sstevel@tonic-gate }
5030Sstevel@tonic-gate
5040Sstevel@tonic-gate /*
5050Sstevel@tonic-gate * See if we managed to reduce the size of the packet.
5060Sstevel@tonic-gate */
5070Sstevel@tonic-gate if (olen < orig_len && m != NULL) {
5080Sstevel@tonic-gate state->stats.comp_bytes += olen;
5090Sstevel@tonic-gate state->stats.comp_packets++;
5100Sstevel@tonic-gate } else {
5110Sstevel@tonic-gate if (*mret != NULL) {
5120Sstevel@tonic-gate freemsg(*mret);
5130Sstevel@tonic-gate *mret = NULL;
5140Sstevel@tonic-gate }
5150Sstevel@tonic-gate
5160Sstevel@tonic-gate state->stats.inc_bytes += orig_len;
5170Sstevel@tonic-gate state->stats.inc_packets++;
5180Sstevel@tonic-gate
5190Sstevel@tonic-gate olen = orig_len;
5200Sstevel@tonic-gate }
5210Sstevel@tonic-gate
5220Sstevel@tonic-gate state->stats.unc_bytes += orig_len;
5230Sstevel@tonic-gate state->stats.unc_packets++;
5240Sstevel@tonic-gate
5250Sstevel@tonic-gate return (olen);
5260Sstevel@tonic-gate }
5270Sstevel@tonic-gate
5280Sstevel@tonic-gate /*
5290Sstevel@tonic-gate * z_incomp()
5300Sstevel@tonic-gate *
5310Sstevel@tonic-gate * Incompressible data has arrived - add it to the history.
5320Sstevel@tonic-gate */
5330Sstevel@tonic-gate static int
z_incomp(void * arg,mblk_t * mp)5340Sstevel@tonic-gate z_incomp(void *arg, mblk_t *mp)
5350Sstevel@tonic-gate {
5360Sstevel@tonic-gate struct deflate_state *state = (struct deflate_state *)arg;
5370Sstevel@tonic-gate uchar_t *rptr, *rmax;
5380Sstevel@tonic-gate int rlen;
5390Sstevel@tonic-gate int r;
5400Sstevel@tonic-gate
5410Sstevel@tonic-gate /*
5420Sstevel@tonic-gate * Check that the protocol is one we handle. Pullup is *NOT*
5430Sstevel@tonic-gate * possible here.
5440Sstevel@tonic-gate */
5450Sstevel@tonic-gate rptr = mp->b_rptr;
5460Sstevel@tonic-gate rmax = mp->b_wptr;
5470Sstevel@tonic-gate ADJRPTR();
5480Sstevel@tonic-gate rptr++; /* skip address */
5490Sstevel@tonic-gate ADJRPTR();
5500Sstevel@tonic-gate rptr++; /* skip control */
5510Sstevel@tonic-gate ADJRPTR();
5520Sstevel@tonic-gate
5530Sstevel@tonic-gate /*
5540Sstevel@tonic-gate * Per RFC 1979, the protocol field must be compressed using a
5550Sstevel@tonic-gate * PFC-like procedure. Also, all protocols between 0000-3FFF
5560Sstevel@tonic-gate * except the two compression protocols must be LZ compressed.
5570Sstevel@tonic-gate */
5580Sstevel@tonic-gate if (rptr == NULL)
5590Sstevel@tonic-gate return (0);
5600Sstevel@tonic-gate r = *rptr;
5610Sstevel@tonic-gate if (r == 0) {
5620Sstevel@tonic-gate rptr++;
5630Sstevel@tonic-gate ADJRPTR();
5640Sstevel@tonic-gate if (rptr == NULL || *rptr == PPP_COMP || *rptr == PPP_COMPFRAG)
5650Sstevel@tonic-gate return (0);
5660Sstevel@tonic-gate } else {
5670Sstevel@tonic-gate if (r > 0x3F)
5680Sstevel@tonic-gate return (0);
5690Sstevel@tonic-gate }
5700Sstevel@tonic-gate
5710Sstevel@tonic-gate ++state->seqno;
5720Sstevel@tonic-gate
5730Sstevel@tonic-gate /*
5740Sstevel@tonic-gate * Iterate through the message blocks, adding the characters
5750Sstevel@tonic-gate * in them to the decompressor's history.
5760Sstevel@tonic-gate */
5770Sstevel@tonic-gate rlen = mp->b_wptr - rptr;
5780Sstevel@tonic-gate
5790Sstevel@tonic-gate state->strm.next_in = rptr;
5800Sstevel@tonic-gate state->strm.avail_in = rlen;
5810Sstevel@tonic-gate
5820Sstevel@tonic-gate for (;;) {
5830Sstevel@tonic-gate r = inflateIncomp(&state->strm);
5840Sstevel@tonic-gate
5850Sstevel@tonic-gate if (r != Z_OK) { /* gak! */
5860Sstevel@tonic-gate if (state->flags & DS_DEBUG) {
5870Sstevel@tonic-gate cmn_err(CE_CONT,
5880Sstevel@tonic-gate "z_incomp%d: inflateIncomp returned "
5890Sstevel@tonic-gate "%d (%s)\n", state->unit, r,
5900Sstevel@tonic-gate (state->strm.msg? state->strm.msg: ""));
5910Sstevel@tonic-gate }
5920Sstevel@tonic-gate
5930Sstevel@tonic-gate return (-1);
5940Sstevel@tonic-gate }
5950Sstevel@tonic-gate
5960Sstevel@tonic-gate mp = mp->b_cont;
5970Sstevel@tonic-gate if (mp == NULL) {
5980Sstevel@tonic-gate break;
5990Sstevel@tonic-gate }
6000Sstevel@tonic-gate
6010Sstevel@tonic-gate state->strm.next_in = mp->b_rptr;
6020Sstevel@tonic-gate state->strm.avail_in = mp->b_wptr - mp->b_rptr;
6030Sstevel@tonic-gate
6040Sstevel@tonic-gate rlen += state->strm.avail_in;
6050Sstevel@tonic-gate }
6060Sstevel@tonic-gate
6070Sstevel@tonic-gate /*
6080Sstevel@tonic-gate * Update stats
6090Sstevel@tonic-gate */
6100Sstevel@tonic-gate state->stats.inc_bytes += rlen;
6110Sstevel@tonic-gate state->stats.inc_packets++;
6120Sstevel@tonic-gate state->stats.unc_bytes += rlen;
6130Sstevel@tonic-gate state->stats.unc_packets++;
6140Sstevel@tonic-gate return (0);
6150Sstevel@tonic-gate #undef ADJRPTR
6160Sstevel@tonic-gate }
6170Sstevel@tonic-gate
6180Sstevel@tonic-gate /*
6190Sstevel@tonic-gate * z_comp_stats()
6200Sstevel@tonic-gate */
6210Sstevel@tonic-gate static void
z_comp_stats(void * arg,struct compstat * stats)6220Sstevel@tonic-gate z_comp_stats(void *arg, struct compstat *stats)
6230Sstevel@tonic-gate {
6240Sstevel@tonic-gate struct deflate_state *state = (struct deflate_state *)arg;
6250Sstevel@tonic-gate uint_t out;
6260Sstevel@tonic-gate
6270Sstevel@tonic-gate *stats = state->stats;
6280Sstevel@tonic-gate stats->ratio = stats->unc_bytes;
6290Sstevel@tonic-gate out = stats->comp_bytes + stats->unc_bytes;
6300Sstevel@tonic-gate
6310Sstevel@tonic-gate if (stats->ratio <= 0x7ffffff) {
6320Sstevel@tonic-gate stats->ratio <<= 8;
6330Sstevel@tonic-gate } else {
6340Sstevel@tonic-gate out >>= 8;
6350Sstevel@tonic-gate }
6360Sstevel@tonic-gate
6370Sstevel@tonic-gate if (out != 0) {
6380Sstevel@tonic-gate stats->ratio /= out;
6390Sstevel@tonic-gate }
6400Sstevel@tonic-gate }
6410Sstevel@tonic-gate
6420Sstevel@tonic-gate /*
6430Sstevel@tonic-gate * z_decomp_alloc()
6440Sstevel@tonic-gate *
6450Sstevel@tonic-gate * Allocate space for a decompressor.
6460Sstevel@tonic-gate */
6470Sstevel@tonic-gate static void *
z_decomp_alloc(uchar_t * options,int opt_len)6480Sstevel@tonic-gate z_decomp_alloc(uchar_t *options, int opt_len)
6490Sstevel@tonic-gate {
6500Sstevel@tonic-gate struct deflate_state *state;
6510Sstevel@tonic-gate int w_size;
6520Sstevel@tonic-gate
6530Sstevel@tonic-gate if (opt_len != CILEN_DEFLATE ||
6540Sstevel@tonic-gate (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) ||
6550Sstevel@tonic-gate options[1] != CILEN_DEFLATE ||
6560Sstevel@tonic-gate DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL ||
6570Sstevel@tonic-gate options[3] != DEFLATE_CHK_SEQUENCE) {
6580Sstevel@tonic-gate
6590Sstevel@tonic-gate return (NULL);
6600Sstevel@tonic-gate }
6610Sstevel@tonic-gate
6620Sstevel@tonic-gate w_size = DEFLATE_SIZE(options[2]);
6630Sstevel@tonic-gate /*
6640Sstevel@tonic-gate * Check <= minimum size to avoid unfixable zlib bug -- window size
6650Sstevel@tonic-gate * 256 (w_size 8) is not supported.
6660Sstevel@tonic-gate */
6670Sstevel@tonic-gate if (w_size <= DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE) {
6680Sstevel@tonic-gate return (NULL);
6690Sstevel@tonic-gate }
6700Sstevel@tonic-gate
6710Sstevel@tonic-gate state = (struct deflate_state *)kmem_zalloc(sizeof (*state), KM_SLEEP);
6720Sstevel@tonic-gate ASSERT(state != NULL);
6730Sstevel@tonic-gate
6740Sstevel@tonic-gate state->strm.zalloc = (alloc_func)z_alloc;
6750Sstevel@tonic-gate state->strm.zfree = (free_func)z_free;
6760Sstevel@tonic-gate
6770Sstevel@tonic-gate if (inflateInit2(&state->strm, -w_size) != Z_OK) {
6780Sstevel@tonic-gate kmem_free(state, sizeof (*state));
6790Sstevel@tonic-gate return (NULL);
6800Sstevel@tonic-gate }
6810Sstevel@tonic-gate
6820Sstevel@tonic-gate state->w_size = w_size;
6830Sstevel@tonic-gate
6840Sstevel@tonic-gate bzero(&state->stats, sizeof (state->stats));
6850Sstevel@tonic-gate
6860Sstevel@tonic-gate return ((void *)state);
6870Sstevel@tonic-gate }
6880Sstevel@tonic-gate
6890Sstevel@tonic-gate /*
6900Sstevel@tonic-gate * z_decomp_free()
6910Sstevel@tonic-gate */
6920Sstevel@tonic-gate static void
z_decomp_free(void * arg)6930Sstevel@tonic-gate z_decomp_free(void *arg)
6940Sstevel@tonic-gate {
6950Sstevel@tonic-gate struct deflate_state *state = (struct deflate_state *)arg;
6960Sstevel@tonic-gate
6970Sstevel@tonic-gate (void) inflateEnd(&state->strm);
6980Sstevel@tonic-gate
6990Sstevel@tonic-gate kmem_free(state, sizeof (*state));
7000Sstevel@tonic-gate }
7010Sstevel@tonic-gate
7020Sstevel@tonic-gate /*
7030Sstevel@tonic-gate * z_decomp_init()
7040Sstevel@tonic-gate */
7050Sstevel@tonic-gate static int
z_decomp_init(void * arg,uchar_t * options,int opt_len,int unit,int hdrlen,int mru,int debug)7060Sstevel@tonic-gate z_decomp_init(void *arg, uchar_t *options, int opt_len, int unit, int hdrlen,
7070Sstevel@tonic-gate int mru, int debug)
7080Sstevel@tonic-gate {
7090Sstevel@tonic-gate struct deflate_state *state = (struct deflate_state *)arg;
7100Sstevel@tonic-gate
7110Sstevel@tonic-gate if (opt_len < CILEN_DEFLATE ||
7120Sstevel@tonic-gate (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) ||
7130Sstevel@tonic-gate options[1] != CILEN_DEFLATE ||
7140Sstevel@tonic-gate DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL ||
7150Sstevel@tonic-gate DEFLATE_SIZE(options[2]) != state->w_size ||
7160Sstevel@tonic-gate options[3] != DEFLATE_CHK_SEQUENCE) {
7170Sstevel@tonic-gate
7180Sstevel@tonic-gate return (0);
7190Sstevel@tonic-gate }
7200Sstevel@tonic-gate
7210Sstevel@tonic-gate state->seqno = 0;
7220Sstevel@tonic-gate state->unit = unit;
7230Sstevel@tonic-gate state->hdrlen = hdrlen;
7240Sstevel@tonic-gate if (debug)
7250Sstevel@tonic-gate state->flags |= DS_DEBUG;
7260Sstevel@tonic-gate else
7270Sstevel@tonic-gate state->flags &= ~DS_DEBUG;
7280Sstevel@tonic-gate state->mru = mru;
7290Sstevel@tonic-gate
7300Sstevel@tonic-gate (void) inflateReset(&state->strm);
7310Sstevel@tonic-gate
7320Sstevel@tonic-gate return (1);
7330Sstevel@tonic-gate }
7340Sstevel@tonic-gate
7350Sstevel@tonic-gate /*
7360Sstevel@tonic-gate * z_decomp_reset()
7370Sstevel@tonic-gate */
7380Sstevel@tonic-gate static void
z_decomp_reset(void * arg)7390Sstevel@tonic-gate z_decomp_reset(void *arg)
7400Sstevel@tonic-gate {
7410Sstevel@tonic-gate struct deflate_state *state = (struct deflate_state *)arg;
7420Sstevel@tonic-gate
7430Sstevel@tonic-gate state->seqno = 0;
7440Sstevel@tonic-gate
7450Sstevel@tonic-gate (void) inflateReset(&state->strm);
7460Sstevel@tonic-gate }
7470Sstevel@tonic-gate
7480Sstevel@tonic-gate /*
7490Sstevel@tonic-gate * z_decompress()
7500Sstevel@tonic-gate *
7510Sstevel@tonic-gate * Decompress a Deflate-compressed packet.
7520Sstevel@tonic-gate *
7530Sstevel@tonic-gate * Because of patent problems, we return DECOMP_ERROR for errors
7540Sstevel@tonic-gate * found by inspecting the input data and for system problems, but
7550Sstevel@tonic-gate * DECOMP_FATALERROR for any errors which could possibly be said to
7560Sstevel@tonic-gate * be being detected "after" decompression. For DECOMP_ERROR,
7570Sstevel@tonic-gate * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
7580Sstevel@tonic-gate * infringing a patent of Motorola's if we do, so we take CCP down
7590Sstevel@tonic-gate * instead.
7600Sstevel@tonic-gate *
7610Sstevel@tonic-gate * Given that the frame has the correct sequence number and a good FCS,
7620Sstevel@tonic-gate * errors such as invalid codes in the input most likely indicate a
7630Sstevel@tonic-gate * bug, so we return DECOMP_FATALERROR for them in order to turn off
7640Sstevel@tonic-gate * compression, even though they are detected by inspecting the input.
7650Sstevel@tonic-gate */
7660Sstevel@tonic-gate static int
z_decompress(void * arg,mblk_t ** mop)7670Sstevel@tonic-gate z_decompress(void *arg, mblk_t **mop)
7680Sstevel@tonic-gate {
7690Sstevel@tonic-gate struct deflate_state *state = (struct deflate_state *)arg;
7700Sstevel@tonic-gate mblk_t *mi = *mop, *mnext;
7710Sstevel@tonic-gate mblk_t *mo;
7720Sstevel@tonic-gate mblk_t *mo_head;
7730Sstevel@tonic-gate uchar_t *rptr, *rmax;
7740Sstevel@tonic-gate uchar_t *wptr;
7750Sstevel@tonic-gate int rlen;
7760Sstevel@tonic-gate int olen;
7770Sstevel@tonic-gate int ospace;
7780Sstevel@tonic-gate int seq;
7790Sstevel@tonic-gate int flush;
7800Sstevel@tonic-gate int r;
7810Sstevel@tonic-gate int decode_proto;
7820Sstevel@tonic-gate #if defined(lint) || defined(_lint)
7830Sstevel@tonic-gate uchar_t hdlcaddr, hdlcctrl;
7840Sstevel@tonic-gate #else
7850Sstevel@tonic-gate int hdlcaddr, hdlcctrl;
7860Sstevel@tonic-gate #endif
7870Sstevel@tonic-gate
7880Sstevel@tonic-gate /* Note: spppcomp already did a pullup to fix the first buffer. */
7890Sstevel@tonic-gate *mop = NULL;
7900Sstevel@tonic-gate rptr = mi->b_rptr + PPP_HDRLEN;
7910Sstevel@tonic-gate rmax = mi->b_wptr;
7920Sstevel@tonic-gate if (rptr > rmax) {
7930Sstevel@tonic-gate if (state->flags & DS_DEBUG) {
7940Sstevel@tonic-gate cmn_err(CE_CONT, "z_decompress%d: bad buffer\n",
7950Sstevel@tonic-gate state->unit);
7960Sstevel@tonic-gate }
7970Sstevel@tonic-gate freemsg(mi);
7980Sstevel@tonic-gate return (DECOMP_ERROR);
7990Sstevel@tonic-gate }
8000Sstevel@tonic-gate
8010Sstevel@tonic-gate hdlcaddr = rptr[-PPP_HDRLEN];
8020Sstevel@tonic-gate hdlcctrl = rptr[-PPP_HDRLEN+1];
8030Sstevel@tonic-gate
8040Sstevel@tonic-gate /*
8050Sstevel@tonic-gate * Note that we free as we go. If we fail to decompress,
8060Sstevel@tonic-gate * there's nothing good that the caller can do.
8070Sstevel@tonic-gate */
8080Sstevel@tonic-gate #define ADJRPTR() { \
8090Sstevel@tonic-gate if (rptr != NULL) { \
8100Sstevel@tonic-gate while (rptr >= rmax) { \
8110Sstevel@tonic-gate mnext = mi->b_cont; \
8120Sstevel@tonic-gate freeb(mi); \
8130Sstevel@tonic-gate if ((mi = mnext) == NULL) { \
8140Sstevel@tonic-gate rptr = NULL; \
8150Sstevel@tonic-gate break; \
8160Sstevel@tonic-gate } \
8170Sstevel@tonic-gate rptr = mi->b_rptr; \
8180Sstevel@tonic-gate rmax = mi->b_wptr; \
8190Sstevel@tonic-gate } \
8200Sstevel@tonic-gate } \
8210Sstevel@tonic-gate }
8220Sstevel@tonic-gate
8230Sstevel@tonic-gate /*
8240Sstevel@tonic-gate * Check the sequence number
8250Sstevel@tonic-gate */
8260Sstevel@tonic-gate ADJRPTR();
8270Sstevel@tonic-gate seq = rptr == NULL ? 0 : (*rptr++ << 8);
8280Sstevel@tonic-gate ADJRPTR();
8290Sstevel@tonic-gate if (rptr == NULL) {
8300Sstevel@tonic-gate if (state->flags & DS_DEBUG) {
8310Sstevel@tonic-gate cmn_err(CE_CONT, "z_decompress%d: bad buffer\n",
8320Sstevel@tonic-gate state->unit);
8330Sstevel@tonic-gate }
8340Sstevel@tonic-gate return (DECOMP_ERROR);
8350Sstevel@tonic-gate }
8360Sstevel@tonic-gate
8370Sstevel@tonic-gate seq |= *rptr++;
8380Sstevel@tonic-gate
8390Sstevel@tonic-gate #ifdef DEBUG
8400Sstevel@tonic-gate /*
8410Sstevel@tonic-gate * If testing input, just pretending the sequence is bad here
8420Sstevel@tonic-gate * does the trick.
8430Sstevel@tonic-gate */
8440Sstevel@tonic-gate if ((state->flags & DS_TESTIN) && (state->seqno % 300) == 101)
8450Sstevel@tonic-gate seq ^= 0x55;
8460Sstevel@tonic-gate #endif
8470Sstevel@tonic-gate if (seq != state->seqno++) {
8480Sstevel@tonic-gate freemsg(mi);
8490Sstevel@tonic-gate if (state->flags & DS_DEBUG) {
8500Sstevel@tonic-gate cmn_err(CE_CONT,
8510Sstevel@tonic-gate "z_decompress%d: bad seq # %d, expected %d\n",
8520Sstevel@tonic-gate state->unit, seq, state->seqno - 1);
8530Sstevel@tonic-gate }
8540Sstevel@tonic-gate return (DECOMP_ERROR);
8550Sstevel@tonic-gate }
8560Sstevel@tonic-gate
8570Sstevel@tonic-gate /*
8580Sstevel@tonic-gate * Allocate an output message block
8590Sstevel@tonic-gate */
8600Sstevel@tonic-gate mo = allocb(DECOMP_CHUNK + state->hdrlen, BPRI_MED);
8610Sstevel@tonic-gate if (mo == NULL) {
8620Sstevel@tonic-gate freemsg(mi);
8630Sstevel@tonic-gate return (DECOMP_ERROR);
8640Sstevel@tonic-gate }
8650Sstevel@tonic-gate
8660Sstevel@tonic-gate mo_head = mo;
8670Sstevel@tonic-gate mo->b_cont = NULL;
8680Sstevel@tonic-gate mo->b_rptr += state->hdrlen;
8690Sstevel@tonic-gate mo->b_wptr = wptr = mo->b_rptr;
8700Sstevel@tonic-gate
8710Sstevel@tonic-gate ospace = DECOMP_CHUNK;
8720Sstevel@tonic-gate olen = 0;
8730Sstevel@tonic-gate
8740Sstevel@tonic-gate /*
8750Sstevel@tonic-gate * Fill in the first part of the PPP header. The protocol field
8760Sstevel@tonic-gate * comes from the decompressed data.
8770Sstevel@tonic-gate */
8780Sstevel@tonic-gate *wptr++ = hdlcaddr;
8790Sstevel@tonic-gate *wptr++ = hdlcctrl;
8800Sstevel@tonic-gate *wptr++ = 0;
8810Sstevel@tonic-gate
8820Sstevel@tonic-gate /*
8830Sstevel@tonic-gate * Set up to call inflate. We set avail_out to 1 initially so we can
8840Sstevel@tonic-gate * look at the first byte of the output and decide whether we have
8850Sstevel@tonic-gate * a 1-byte or 2-byte protocol field.
8860Sstevel@tonic-gate */
8870Sstevel@tonic-gate state->strm.next_in = rptr;
8880Sstevel@tonic-gate state->strm.avail_in = mi->b_wptr - rptr;
8890Sstevel@tonic-gate
8900Sstevel@tonic-gate rlen = state->strm.avail_in + PPP_HDRLEN + DEFLATE_OVHD;
8910Sstevel@tonic-gate
8920Sstevel@tonic-gate state->strm.next_out = wptr;
8930Sstevel@tonic-gate state->strm.avail_out = 1;
8940Sstevel@tonic-gate
8950Sstevel@tonic-gate decode_proto = 1;
8960Sstevel@tonic-gate
8970Sstevel@tonic-gate /*
8980Sstevel@tonic-gate * Call inflate, supplying more input or output as needed.
8990Sstevel@tonic-gate */
9000Sstevel@tonic-gate for (;;) {
9010Sstevel@tonic-gate
9020Sstevel@tonic-gate flush = (mi == NULL || mi->b_cont == NULL) ?
9030Sstevel@tonic-gate Z_PACKET_FLUSH : Z_NO_FLUSH;
9040Sstevel@tonic-gate r = inflate(&state->strm, flush);
9050Sstevel@tonic-gate
9060Sstevel@tonic-gate if (r != Z_OK) {
9070Sstevel@tonic-gate
9080Sstevel@tonic-gate if (state->flags & DS_DEBUG) {
9090Sstevel@tonic-gate cmn_err(CE_CONT,
9100Sstevel@tonic-gate "z_decompress%d: inflate returned %d "
9110Sstevel@tonic-gate "(%s)\n", state->unit, r,
9120Sstevel@tonic-gate (state->strm.msg? state->strm.msg: ""));
9130Sstevel@tonic-gate }
9140Sstevel@tonic-gate
9150Sstevel@tonic-gate if (mi != NULL)
9160Sstevel@tonic-gate freemsg(mi);
9170Sstevel@tonic-gate freemsg(mo_head);
9180Sstevel@tonic-gate
9190Sstevel@tonic-gate return (DECOMP_FATALERROR);
9200Sstevel@tonic-gate }
9210Sstevel@tonic-gate
9220Sstevel@tonic-gate if (state->strm.avail_in == 0) {
9230Sstevel@tonic-gate if (mi != NULL) {
9240Sstevel@tonic-gate mnext = mi->b_cont;
9250Sstevel@tonic-gate freeb(mi);
9260Sstevel@tonic-gate mi = mnext;
9270Sstevel@tonic-gate }
9280Sstevel@tonic-gate if (mi == NULL) {
9290Sstevel@tonic-gate if (state->strm.avail_out != 0)
9300Sstevel@tonic-gate break; /* all done */
9310Sstevel@tonic-gate } else {
9320Sstevel@tonic-gate state->strm.next_in = mi->b_rptr;
9330Sstevel@tonic-gate state->strm.avail_in = mi->b_wptr - mi->b_rptr;
9340Sstevel@tonic-gate
9350Sstevel@tonic-gate rlen += state->strm.avail_in;
9360Sstevel@tonic-gate }
9370Sstevel@tonic-gate }
9380Sstevel@tonic-gate
9390Sstevel@tonic-gate if (state->strm.avail_out == 0) {
9400Sstevel@tonic-gate if (decode_proto) {
9410Sstevel@tonic-gate state->strm.avail_out = ospace - PPP_HDRLEN;
9420Sstevel@tonic-gate
9430Sstevel@tonic-gate if ((wptr[0] & 1) == 0) {
9440Sstevel@tonic-gate /*
9450Sstevel@tonic-gate * 2-byte protocol field
9460Sstevel@tonic-gate */
9470Sstevel@tonic-gate wptr[-1] = wptr[0];
9480Sstevel@tonic-gate
9490Sstevel@tonic-gate --state->strm.next_out;
9500Sstevel@tonic-gate ++state->strm.avail_out;
9510Sstevel@tonic-gate }
9520Sstevel@tonic-gate
9530Sstevel@tonic-gate decode_proto = 0;
9540Sstevel@tonic-gate } else {
9550Sstevel@tonic-gate mo->b_wptr += ospace;
9560Sstevel@tonic-gate olen += ospace;
9570Sstevel@tonic-gate
9580Sstevel@tonic-gate mo->b_cont = allocb(DECOMP_CHUNK, BPRI_MED);
9590Sstevel@tonic-gate
9600Sstevel@tonic-gate mo = mo->b_cont;
9610Sstevel@tonic-gate if (mo == NULL) {
9620Sstevel@tonic-gate if (mi != NULL)
9630Sstevel@tonic-gate freemsg(mi);
9640Sstevel@tonic-gate freemsg(mo_head);
9650Sstevel@tonic-gate return (DECOMP_ERROR);
9660Sstevel@tonic-gate }
9670Sstevel@tonic-gate
9680Sstevel@tonic-gate state->strm.next_out = mo->b_rptr;
9690Sstevel@tonic-gate state->strm.avail_out = ospace = DECOMP_CHUNK;
9700Sstevel@tonic-gate }
9710Sstevel@tonic-gate }
9720Sstevel@tonic-gate }
9730Sstevel@tonic-gate
9740Sstevel@tonic-gate if (decode_proto) {
9750Sstevel@tonic-gate freemsg(mo_head);
9760Sstevel@tonic-gate return (DECOMP_ERROR);
9770Sstevel@tonic-gate }
9780Sstevel@tonic-gate
9790Sstevel@tonic-gate mo->b_wptr += ospace - state->strm.avail_out;
9800Sstevel@tonic-gate olen += ospace - state->strm.avail_out;
9810Sstevel@tonic-gate
9820Sstevel@tonic-gate if ((olen > state->mru + PPP_HDRLEN) && (state->flags & DS_DEBUG)) {
9830Sstevel@tonic-gate cmn_err(CE_CONT, "z_decompress%d: exceeded mru (%d > %d)\n",
9840Sstevel@tonic-gate state->unit, olen, state->mru + PPP_HDRLEN);
9850Sstevel@tonic-gate }
9860Sstevel@tonic-gate
9870Sstevel@tonic-gate state->stats.unc_bytes += olen;
9880Sstevel@tonic-gate state->stats.unc_packets++;
9890Sstevel@tonic-gate state->stats.comp_bytes += rlen;
9900Sstevel@tonic-gate state->stats.comp_packets++;
9910Sstevel@tonic-gate
9920Sstevel@tonic-gate *mop = mo_head;
9930Sstevel@tonic-gate
9940Sstevel@tonic-gate return (DECOMP_OK);
9950Sstevel@tonic-gate }
9960Sstevel@tonic-gate
9970Sstevel@tonic-gate /* ARGSUSED */
9980Sstevel@tonic-gate static int
z_set_effort(void * xarg,void * rarg,int effortlevel)9990Sstevel@tonic-gate z_set_effort(void *xarg, void *rarg, int effortlevel)
10000Sstevel@tonic-gate {
10010Sstevel@tonic-gate struct deflate_state *xstate = (struct deflate_state *)xarg;
10020Sstevel@tonic-gate #ifdef DEBUG
10030Sstevel@tonic-gate struct deflate_state *rstate = (struct deflate_state *)rarg;
10040Sstevel@tonic-gate #endif
10050Sstevel@tonic-gate int retv;
10060Sstevel@tonic-gate
10070Sstevel@tonic-gate #ifdef DEBUG
10080Sstevel@tonic-gate if (effortlevel == 42 || effortlevel == 2112) {
10090Sstevel@tonic-gate /* corrupt received data. */
10100Sstevel@tonic-gate if (rstate != NULL) {
10110Sstevel@tonic-gate rstate->flags |= DS_TESTIN;
10120Sstevel@tonic-gate cmn_err(CE_CONT, "deflate: enabled input testing.");
10130Sstevel@tonic-gate }
10140Sstevel@tonic-gate if (effortlevel != 2112)
10150Sstevel@tonic-gate return (0);
10160Sstevel@tonic-gate }
10170Sstevel@tonic-gate if (effortlevel == 2001 || effortlevel == 2112) {
10180Sstevel@tonic-gate /* corrupt transmitted data. */
10190Sstevel@tonic-gate if (xstate != NULL) {
10200Sstevel@tonic-gate xstate->flags |= DS_TESTOUT;
10210Sstevel@tonic-gate cmn_err(CE_CONT, "deflate: enabled output testing.");
10220Sstevel@tonic-gate }
10230Sstevel@tonic-gate return (0);
10240Sstevel@tonic-gate }
10250Sstevel@tonic-gate #endif
10260Sstevel@tonic-gate if (effortlevel < -1 || effortlevel > 9)
10270Sstevel@tonic-gate return (EINVAL);
10280Sstevel@tonic-gate if (xstate == NULL)
10290Sstevel@tonic-gate return (0);
10300Sstevel@tonic-gate retv = deflateParams(&xstate->strm, effortlevel, Z_DEFAULT_STRATEGY);
10310Sstevel@tonic-gate return (retv == Z_OK ? 0 : EINVAL);
10320Sstevel@tonic-gate }
10330Sstevel@tonic-gate
10340Sstevel@tonic-gate #endif /* DO_DEFLATE */
1035