17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * deflate.c - interface the zlib procedures for Deflate compression
37c478bd9Sstevel@tonic-gate  * and decompression (as used by gzip) to the PPP code.
47c478bd9Sstevel@tonic-gate  *
57c478bd9Sstevel@tonic-gate  * This version is for use with STREAMS in Solaris 2
67c478bd9Sstevel@tonic-gate  *
77c478bd9Sstevel@tonic-gate  * Copyright (c) 2001 by Sun Microsystems, Inc.
87c478bd9Sstevel@tonic-gate  * All rights reserved.
97c478bd9Sstevel@tonic-gate  *
107c478bd9Sstevel@tonic-gate  * Copyright (c) 1994 The Australian National University.
117c478bd9Sstevel@tonic-gate  * All rights reserved.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * Permission to use, copy, modify, and distribute this software and its
147c478bd9Sstevel@tonic-gate  * documentation is hereby granted, provided that the above copyright
157c478bd9Sstevel@tonic-gate  * notice appears in all copies.  This software is provided without any
167c478bd9Sstevel@tonic-gate  * warranty, express or implied. The Australian National University
177c478bd9Sstevel@tonic-gate  * makes no representations about the suitability of this software for
187c478bd9Sstevel@tonic-gate  * any purpose.
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
217c478bd9Sstevel@tonic-gate  * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
227c478bd9Sstevel@tonic-gate  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
237c478bd9Sstevel@tonic-gate  * THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY
247c478bd9Sstevel@tonic-gate  * OF SUCH DAMAGE.
257c478bd9Sstevel@tonic-gate  *
267c478bd9Sstevel@tonic-gate  * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
277c478bd9Sstevel@tonic-gate  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
287c478bd9Sstevel@tonic-gate  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
297c478bd9Sstevel@tonic-gate  * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
307c478bd9Sstevel@tonic-gate  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
317c478bd9Sstevel@tonic-gate  * OR MODIFICATIONS.
327c478bd9Sstevel@tonic-gate  *
337c478bd9Sstevel@tonic-gate  * $Id: deflate.c,v 1.9 1999/01/19 23:58:35 paulus Exp $
347c478bd9Sstevel@tonic-gate  */
357c478bd9Sstevel@tonic-gate 
36*e8ed0869SJohn Beck #define	NO_DUMMY_DECL
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate #include <sys/param.h>
397c478bd9Sstevel@tonic-gate #include <sys/types.h>
407c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
417c478bd9Sstevel@tonic-gate #include <sys/stream.h>
427c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
437c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
447c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
457c478bd9Sstevel@tonic-gate #include <sys/errno.h>
467c478bd9Sstevel@tonic-gate #include <net/ppp_defs.h>
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate /* Defined for platform-neutral include file */
497c478bd9Sstevel@tonic-gate #define	PACKETPTR	mblk_t *
507c478bd9Sstevel@tonic-gate #include <net/ppp-comp.h>
517c478bd9Sstevel@tonic-gate #include "s_common.h"
527c478bd9Sstevel@tonic-gate #include "zlib.h"
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate #if DO_DEFLATE
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate /*
577c478bd9Sstevel@tonic-gate  * State for a Deflate (de)compressor.
587c478bd9Sstevel@tonic-gate  */
597c478bd9Sstevel@tonic-gate struct deflate_state {
607c478bd9Sstevel@tonic-gate 	int		seqno;
617c478bd9Sstevel@tonic-gate 	int		w_size;
627c478bd9Sstevel@tonic-gate 	int		unit;
637c478bd9Sstevel@tonic-gate 	int		hdrlen;
647c478bd9Sstevel@tonic-gate 	int		mru;
657c478bd9Sstevel@tonic-gate 	int		flags;
667c478bd9Sstevel@tonic-gate 	z_stream	strm;
677c478bd9Sstevel@tonic-gate 	struct compstat	stats;
687c478bd9Sstevel@tonic-gate };
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate #define	DEFLATE_OVHD	2		/* Deflate overhead/packet */
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate #define	DS_DEBUG	0x0001
737c478bd9Sstevel@tonic-gate #define	DS_TESTIN	0x0002
747c478bd9Sstevel@tonic-gate #define	DS_TESTOUT	0x0004
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate static void	*z_alloc(void *, uint_t items, uint_t size);
777c478bd9Sstevel@tonic-gate static void	z_free(void *, void *ptr);
787c478bd9Sstevel@tonic-gate static void	*z_comp_alloc(uchar_t *options, int opt_len);
797c478bd9Sstevel@tonic-gate static void	*z_decomp_alloc(uchar_t *options, int opt_len);
807c478bd9Sstevel@tonic-gate static void	z_comp_free(void *state);
817c478bd9Sstevel@tonic-gate static void	z_decomp_free(void *state);
827c478bd9Sstevel@tonic-gate static int	z_comp_init(void *state, uchar_t *options, int opt_len,
837c478bd9Sstevel@tonic-gate 			int unit, int hdrlen, int debug);
847c478bd9Sstevel@tonic-gate static int	z_decomp_init(void *state, uchar_t *options, int opt_len,
857c478bd9Sstevel@tonic-gate 			int unit, int hdrlen, int mru, int debug);
867c478bd9Sstevel@tonic-gate static int	z_compress(void *state, mblk_t **mret,
877c478bd9Sstevel@tonic-gate 			mblk_t *mp, int slen, int maxolen);
887c478bd9Sstevel@tonic-gate static int	z_incomp(void *state, mblk_t *dmsg);
897c478bd9Sstevel@tonic-gate static int	z_decompress(void *state, mblk_t **dmpp);
907c478bd9Sstevel@tonic-gate static void	z_comp_reset(void *state);
917c478bd9Sstevel@tonic-gate static void	z_decomp_reset(void *state);
927c478bd9Sstevel@tonic-gate static void	z_comp_stats(void *state, struct compstat *stats);
937c478bd9Sstevel@tonic-gate static int	z_set_effort(void *xstate, void *rstate, int effortlevel);
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate /*
967c478bd9Sstevel@tonic-gate  * Procedures exported to ppp_comp.c.
977c478bd9Sstevel@tonic-gate  */
987c478bd9Sstevel@tonic-gate struct compressor ppp_deflate = {
997c478bd9Sstevel@tonic-gate 	CI_DEFLATE,		/* compress_proto */
1007c478bd9Sstevel@tonic-gate 	z_comp_alloc,		/* comp_alloc */
1017c478bd9Sstevel@tonic-gate 	z_comp_free,		/* comp_free */
1027c478bd9Sstevel@tonic-gate 	z_comp_init,		/* comp_init */
1037c478bd9Sstevel@tonic-gate 	z_comp_reset,		/* comp_reset */
1047c478bd9Sstevel@tonic-gate 	z_compress,		/* compress */
1057c478bd9Sstevel@tonic-gate 	z_comp_stats,		/* comp_stat */
1067c478bd9Sstevel@tonic-gate 	z_decomp_alloc,		/* decomp_alloc */
1077c478bd9Sstevel@tonic-gate 	z_decomp_free,		/* decomp_free */
1087c478bd9Sstevel@tonic-gate 	z_decomp_init,		/* decomp_init */
1097c478bd9Sstevel@tonic-gate 	z_decomp_reset,		/* decomp_reset */
1107c478bd9Sstevel@tonic-gate 	z_decompress,		/* decompress */
1117c478bd9Sstevel@tonic-gate 	z_incomp,		/* incomp */
1127c478bd9Sstevel@tonic-gate 	z_comp_stats,		/* decomp_stat */
1137c478bd9Sstevel@tonic-gate 	z_set_effort,		/* set_effort */
1147c478bd9Sstevel@tonic-gate };
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate struct compressor ppp_deflate_draft = {
1177c478bd9Sstevel@tonic-gate 	CI_DEFLATE_DRAFT,	/* compress_proto */
1187c478bd9Sstevel@tonic-gate 	z_comp_alloc,		/* comp_alloc */
1197c478bd9Sstevel@tonic-gate 	z_comp_free,		/* comp_free */
1207c478bd9Sstevel@tonic-gate 	z_comp_init,		/* comp_init */
1217c478bd9Sstevel@tonic-gate 	z_comp_reset,		/* comp_reset */
1227c478bd9Sstevel@tonic-gate 	z_compress,		/* compress */
1237c478bd9Sstevel@tonic-gate 	z_comp_stats,		/* comp_stat */
1247c478bd9Sstevel@tonic-gate 	z_decomp_alloc,		/* decomp_alloc */
1257c478bd9Sstevel@tonic-gate 	z_decomp_free,		/* decomp_free */
1267c478bd9Sstevel@tonic-gate 	z_decomp_init,		/* decomp_init */
1277c478bd9Sstevel@tonic-gate 	z_decomp_reset,		/* decomp_reset */
1287c478bd9Sstevel@tonic-gate 	z_decompress,		/* decompress */
1297c478bd9Sstevel@tonic-gate 	z_incomp,		/* incomp */
1307c478bd9Sstevel@tonic-gate 	z_comp_stats,		/* decomp_stat */
1317c478bd9Sstevel@tonic-gate 	z_set_effort,		/* set_effort */
1327c478bd9Sstevel@tonic-gate };
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate #define	DECOMP_CHUNK	512
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate /*
1377c478bd9Sstevel@tonic-gate  * Space allocation and freeing routines for use by zlib routines.
1387c478bd9Sstevel@tonic-gate  */
1397c478bd9Sstevel@tonic-gate struct zchunk {
1407c478bd9Sstevel@tonic-gate 	uint_t		size;
1417c478bd9Sstevel@tonic-gate 	uint_t		guard;
1427c478bd9Sstevel@tonic-gate };
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate #define	GUARD_MAGIC	0x77a6011a
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate /*
1477c478bd9Sstevel@tonic-gate  * z_alloc()
1487c478bd9Sstevel@tonic-gate  */
1497c478bd9Sstevel@tonic-gate /* ARGSUSED */
1507c478bd9Sstevel@tonic-gate static void *
z_alloc(void * notused,uint_t items,uint_t size)1517c478bd9Sstevel@tonic-gate z_alloc(void *notused, uint_t items, uint_t size)
1527c478bd9Sstevel@tonic-gate {
1537c478bd9Sstevel@tonic-gate 	struct zchunk	*z;
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 	size = items * size + sizeof (struct zchunk);
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate 	z = (struct zchunk *)kmem_alloc(size, KM_NOSLEEP);
1587c478bd9Sstevel@tonic-gate 	if (z == NULL)
1597c478bd9Sstevel@tonic-gate 		return (NULL);
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 	z->size = size;
1627c478bd9Sstevel@tonic-gate 	z->guard = GUARD_MAGIC;
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 	return ((void *)(z + 1));
1657c478bd9Sstevel@tonic-gate }
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate /*
1687c478bd9Sstevel@tonic-gate  * z_free()
1697c478bd9Sstevel@tonic-gate  */
1707c478bd9Sstevel@tonic-gate /* ARGSUSED */
1717c478bd9Sstevel@tonic-gate static void
z_free(void * notused,void * ptr)1727c478bd9Sstevel@tonic-gate z_free(void *notused, void *ptr)
1737c478bd9Sstevel@tonic-gate {
1747c478bd9Sstevel@tonic-gate 	struct zchunk	*z = ((struct zchunk *)ptr) - 1;
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 	if (ptr == NULL)
1777c478bd9Sstevel@tonic-gate 		return;
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate 	if (z->guard != GUARD_MAGIC) {
1807c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT,
1817c478bd9Sstevel@tonic-gate 		    "deflate: z_free of corrupted chunk at 0x%p (%x, %x)\n",
1827c478bd9Sstevel@tonic-gate 		    (void *)z, z->size, z->guard);
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate 		return;
1857c478bd9Sstevel@tonic-gate 	}
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate 	kmem_free(z, z->size);
1887c478bd9Sstevel@tonic-gate }
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate /*
1917c478bd9Sstevel@tonic-gate  * Allocate space for a compressor.
1927c478bd9Sstevel@tonic-gate  */
1937c478bd9Sstevel@tonic-gate static void *
z_comp_alloc(uchar_t * options,int opt_len)1947c478bd9Sstevel@tonic-gate z_comp_alloc(uchar_t *options, int opt_len)
1957c478bd9Sstevel@tonic-gate {
1967c478bd9Sstevel@tonic-gate 	struct deflate_state	*state;
1977c478bd9Sstevel@tonic-gate 	int			w_size;
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate 	if (opt_len != CILEN_DEFLATE ||
2007c478bd9Sstevel@tonic-gate 		(options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) ||
2017c478bd9Sstevel@tonic-gate 		options[1] != CILEN_DEFLATE ||
2027c478bd9Sstevel@tonic-gate 		DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL ||
2037c478bd9Sstevel@tonic-gate 		options[3] != DEFLATE_CHK_SEQUENCE) {
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate 		return (NULL);
2067c478bd9Sstevel@tonic-gate 	}
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 	w_size = DEFLATE_SIZE(options[2]);
2097c478bd9Sstevel@tonic-gate 	/*
2107c478bd9Sstevel@tonic-gate 	 * Check <= minimum size to avoid unfixable zlib bug -- window size
2117c478bd9Sstevel@tonic-gate 	 * 256 (w_size 8) is not supported.
2127c478bd9Sstevel@tonic-gate 	 */
2137c478bd9Sstevel@tonic-gate 	if (w_size <= DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE) {
2147c478bd9Sstevel@tonic-gate 		return (NULL);
2157c478bd9Sstevel@tonic-gate 	}
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 	state = (struct deflate_state *)kmem_zalloc(sizeof (*state), KM_SLEEP);
2187c478bd9Sstevel@tonic-gate 	ASSERT(state != NULL);
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate 	state->strm.zalloc = (alloc_func)z_alloc;
2217c478bd9Sstevel@tonic-gate 	state->strm.zfree = (free_func)z_free;
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 	if (deflateInit2(&state->strm, Z_DEFAULT_COMPRESSION,
2247c478bd9Sstevel@tonic-gate 		DEFLATE_METHOD_VAL, -w_size, 8, Z_DEFAULT_STRATEGY) != Z_OK) {
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate 		kmem_free(state, sizeof (*state));
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate 		return (NULL);
2297c478bd9Sstevel@tonic-gate 	}
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate 	state->w_size = w_size;
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 	bzero(&state->stats, sizeof (state->stats));
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate 	return ((void *)state);
2367c478bd9Sstevel@tonic-gate }
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate /*
2397c478bd9Sstevel@tonic-gate  * z_comp_free()
2407c478bd9Sstevel@tonic-gate  */
2417c478bd9Sstevel@tonic-gate static void
z_comp_free(void * arg)2427c478bd9Sstevel@tonic-gate z_comp_free(void *arg)
2437c478bd9Sstevel@tonic-gate {
2447c478bd9Sstevel@tonic-gate 	struct deflate_state	*state = (struct deflate_state *)arg;
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 	(void) deflateEnd(&state->strm);
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 	kmem_free(state, sizeof (*state));
2497c478bd9Sstevel@tonic-gate }
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate /*
2527c478bd9Sstevel@tonic-gate  * z_comp_init()
2537c478bd9Sstevel@tonic-gate  */
2547c478bd9Sstevel@tonic-gate static int
z_comp_init(void * arg,uchar_t * options,int opt_len,int unit,int hdrlen,int debug)2557c478bd9Sstevel@tonic-gate z_comp_init(void *arg, uchar_t *options, int opt_len, int unit, int hdrlen,
2567c478bd9Sstevel@tonic-gate 	int debug)
2577c478bd9Sstevel@tonic-gate {
2587c478bd9Sstevel@tonic-gate 	struct deflate_state *state = (struct deflate_state *)arg;
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate 	if (opt_len < CILEN_DEFLATE ||
2617c478bd9Sstevel@tonic-gate 		(options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) ||
2627c478bd9Sstevel@tonic-gate 		options[1] != CILEN_DEFLATE ||
2637c478bd9Sstevel@tonic-gate 		DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL ||
2647c478bd9Sstevel@tonic-gate 		DEFLATE_SIZE(options[2]) != state->w_size ||
2657c478bd9Sstevel@tonic-gate 		options[3] != DEFLATE_CHK_SEQUENCE) {
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate 		return (0);
2687c478bd9Sstevel@tonic-gate 	}
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate 	state->seqno = 0;
2717c478bd9Sstevel@tonic-gate 	state->unit = unit;
2727c478bd9Sstevel@tonic-gate 	state->hdrlen = hdrlen;
2737c478bd9Sstevel@tonic-gate 	if (debug)
2747c478bd9Sstevel@tonic-gate 		state->flags |= DS_DEBUG;
2757c478bd9Sstevel@tonic-gate 	else
2767c478bd9Sstevel@tonic-gate 		state->flags &= ~DS_DEBUG;
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 	(void) deflateReset(&state->strm);
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate 	return (1);
2817c478bd9Sstevel@tonic-gate }
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate /*
2847c478bd9Sstevel@tonic-gate  * z_comp_reset()
2857c478bd9Sstevel@tonic-gate  */
2867c478bd9Sstevel@tonic-gate static void
z_comp_reset(void * arg)2877c478bd9Sstevel@tonic-gate z_comp_reset(void *arg)
2887c478bd9Sstevel@tonic-gate {
2897c478bd9Sstevel@tonic-gate 	struct deflate_state	*state = (struct deflate_state *)arg;
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 	state->seqno = 0;
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate 	(void) deflateReset(&state->strm);
2947c478bd9Sstevel@tonic-gate }
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate /*
2977c478bd9Sstevel@tonic-gate  * z_compress()
2987c478bd9Sstevel@tonic-gate  */
2997c478bd9Sstevel@tonic-gate static int
z_compress(void * arg,mblk_t ** mret,mblk_t * mp,int orig_len,int maxolen)3007c478bd9Sstevel@tonic-gate z_compress(void *arg, mblk_t **mret, mblk_t *mp, int orig_len, int maxolen)
3017c478bd9Sstevel@tonic-gate {
3027c478bd9Sstevel@tonic-gate 	struct deflate_state	*state = (struct deflate_state *)arg;
3037c478bd9Sstevel@tonic-gate 	uchar_t			*rptr, *rmax;
3047c478bd9Sstevel@tonic-gate 	uchar_t			*wptr;
3057c478bd9Sstevel@tonic-gate 	int			olen;
3067c478bd9Sstevel@tonic-gate 	int			wspace;
3077c478bd9Sstevel@tonic-gate 	int			r;
3087c478bd9Sstevel@tonic-gate 	int			flush;
3097c478bd9Sstevel@tonic-gate 	mblk_t			*m;
3107c478bd9Sstevel@tonic-gate #if defined(lint) || defined(_lint)
3117c478bd9Sstevel@tonic-gate 	uchar_t			hdlcaddr, hdlcctrl;
3127c478bd9Sstevel@tonic-gate #else
3137c478bd9Sstevel@tonic-gate 	int			hdlcaddr, hdlcctrl;
3147c478bd9Sstevel@tonic-gate #endif
3157c478bd9Sstevel@tonic-gate 
3167c478bd9Sstevel@tonic-gate #define	ADJRPTR() {						\
3177c478bd9Sstevel@tonic-gate 	if (rptr != NULL) {					\
3187c478bd9Sstevel@tonic-gate 		while (rptr >= rmax) {				\
3197c478bd9Sstevel@tonic-gate 			if ((mp = mp->b_cont) == NULL) {	\
3207c478bd9Sstevel@tonic-gate 				rptr = NULL;			\
3217c478bd9Sstevel@tonic-gate 				break;				\
3227c478bd9Sstevel@tonic-gate 			}					\
3237c478bd9Sstevel@tonic-gate 			rptr = mp->b_rptr;			\
3247c478bd9Sstevel@tonic-gate 			rmax = mp->b_wptr;			\
3257c478bd9Sstevel@tonic-gate 		}						\
3267c478bd9Sstevel@tonic-gate 	}							\
3277c478bd9Sstevel@tonic-gate }
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate #define	GETBYTE(v) {						\
3307c478bd9Sstevel@tonic-gate 	if (rptr != NULL) {					\
3317c478bd9Sstevel@tonic-gate 		(v) = *rptr++;					\
3327c478bd9Sstevel@tonic-gate 	}							\
3337c478bd9Sstevel@tonic-gate }
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate 	/*
3367c478bd9Sstevel@tonic-gate 	 * Check that the protocol is one we handle.  Pullup is *NOT*
3377c478bd9Sstevel@tonic-gate 	 * possible here.
3387c478bd9Sstevel@tonic-gate 	 */
3397c478bd9Sstevel@tonic-gate 	*mret = NULL;
3407c478bd9Sstevel@tonic-gate 	rptr = mp->b_rptr;
3417c478bd9Sstevel@tonic-gate 	rmax = mp->b_wptr;
3427c478bd9Sstevel@tonic-gate 	ADJRPTR();
3437c478bd9Sstevel@tonic-gate 	GETBYTE(hdlcaddr);
3447c478bd9Sstevel@tonic-gate 	ADJRPTR();
3457c478bd9Sstevel@tonic-gate 	GETBYTE(hdlcctrl);
3467c478bd9Sstevel@tonic-gate 	ADJRPTR();
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 	/*
3497c478bd9Sstevel@tonic-gate 	 * Per RFC 1979, the protocol field must be compressed using a
3507c478bd9Sstevel@tonic-gate 	 * PFC-like procedure.  Also, all protocols between 0000-3FFF
3517c478bd9Sstevel@tonic-gate 	 * except the two compression protocols must be LZ compressed.
3527c478bd9Sstevel@tonic-gate 	 */
3537c478bd9Sstevel@tonic-gate 	if (rptr == NULL)
3547c478bd9Sstevel@tonic-gate 		return (orig_len);
3557c478bd9Sstevel@tonic-gate 	r = *rptr;
3567c478bd9Sstevel@tonic-gate 	if (r == 0) {
3577c478bd9Sstevel@tonic-gate 		rptr++;
3587c478bd9Sstevel@tonic-gate 		ADJRPTR();
3597c478bd9Sstevel@tonic-gate 		if (rptr == NULL || *rptr == PPP_COMP || *rptr == PPP_COMPFRAG)
3607c478bd9Sstevel@tonic-gate 			return (orig_len);
3617c478bd9Sstevel@tonic-gate 	} else {
3627c478bd9Sstevel@tonic-gate 		if (r > 0x3F)
3637c478bd9Sstevel@tonic-gate 			return (orig_len);
3647c478bd9Sstevel@tonic-gate 	}
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 	/*
3677c478bd9Sstevel@tonic-gate 	 * Allocate one mblk initially
3687c478bd9Sstevel@tonic-gate 	 */
3697c478bd9Sstevel@tonic-gate 	if (maxolen > orig_len) {
3707c478bd9Sstevel@tonic-gate 		maxolen = orig_len;
3717c478bd9Sstevel@tonic-gate 	}
3727c478bd9Sstevel@tonic-gate 
3737c478bd9Sstevel@tonic-gate 	if (maxolen <= PPP_HDRLEN + 2) {
3747c478bd9Sstevel@tonic-gate 		wspace = 0;
3757c478bd9Sstevel@tonic-gate 		m = NULL;
3767c478bd9Sstevel@tonic-gate 	} else {
3777c478bd9Sstevel@tonic-gate 		wspace = maxolen + state->hdrlen;
3787c478bd9Sstevel@tonic-gate 		if (wspace > 4096) {
3797c478bd9Sstevel@tonic-gate 			wspace = 4096;
3807c478bd9Sstevel@tonic-gate 		}
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate 		m = allocb(wspace, BPRI_MED);
3837c478bd9Sstevel@tonic-gate 	}
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate 	if (m != NULL) {
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 		wspace = m->b_datap->db_lim - m->b_wptr;
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 		*mret = m;
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate 		if (state->hdrlen + PPP_HDRLEN + 2 < wspace) {
3927c478bd9Sstevel@tonic-gate 			m->b_rptr += state->hdrlen;
3937c478bd9Sstevel@tonic-gate 			m->b_wptr = m->b_rptr;
3947c478bd9Sstevel@tonic-gate 			wspace -= state->hdrlen;
3957c478bd9Sstevel@tonic-gate 		}
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 		wptr = m->b_wptr;
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate 		/*
4007c478bd9Sstevel@tonic-gate 		 * Copy over the PPP header and store the 2-byte
4017c478bd9Sstevel@tonic-gate 		 * sequence number
4027c478bd9Sstevel@tonic-gate 		 */
4037c478bd9Sstevel@tonic-gate 		wptr[0] = hdlcaddr;
4047c478bd9Sstevel@tonic-gate 		wptr[1] = hdlcctrl;
4057c478bd9Sstevel@tonic-gate 		wptr[2] = PPP_COMP >> 8;
4067c478bd9Sstevel@tonic-gate 		wptr[3] = PPP_COMP;
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate 		wptr += PPP_HDRLEN;
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 		wptr[0] = state->seqno >> 8;
4117c478bd9Sstevel@tonic-gate 		wptr[1] = state->seqno;
4127c478bd9Sstevel@tonic-gate 		wptr += 2;
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate #ifdef DEBUG
4157c478bd9Sstevel@tonic-gate 		/*
4167c478bd9Sstevel@tonic-gate 		 * If testing output, just garbling the sequence here
4177c478bd9Sstevel@tonic-gate 		 * does the trick.
4187c478bd9Sstevel@tonic-gate 		 */
4197c478bd9Sstevel@tonic-gate 		if ((state->flags & DS_TESTOUT) && (state->seqno % 100) == 50)
4207c478bd9Sstevel@tonic-gate 			wptr[-1] ^= 0xAA;
4217c478bd9Sstevel@tonic-gate #endif
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate 		state->strm.next_out = wptr;
4247c478bd9Sstevel@tonic-gate 		state->strm.avail_out = wspace - (PPP_HDRLEN + 2);
4257c478bd9Sstevel@tonic-gate 	} else {
4267c478bd9Sstevel@tonic-gate 		state->strm.next_out = NULL;
4277c478bd9Sstevel@tonic-gate 		state->strm.avail_out = 1000000;
4287c478bd9Sstevel@tonic-gate 	}
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate 	++state->seqno;
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate 	state->strm.next_in = rptr;
4337c478bd9Sstevel@tonic-gate 	state->strm.avail_in = mp->b_wptr - rptr;
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate 	olen = 0;
4367c478bd9Sstevel@tonic-gate 
4377c478bd9Sstevel@tonic-gate 	for (;;) {
4387c478bd9Sstevel@tonic-gate 		flush = (mp == NULL || mp->b_cont == NULL) ? Z_PACKET_FLUSH :
4397c478bd9Sstevel@tonic-gate 		    Z_NO_FLUSH;
4407c478bd9Sstevel@tonic-gate 		r = deflate(&state->strm, flush);
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate 		if (r != Z_OK) {
4437c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT,
4447c478bd9Sstevel@tonic-gate 			    "z_compress%d: deflate returned %d (%s)\n",
4457c478bd9Sstevel@tonic-gate 			    state->unit, r,
4467c478bd9Sstevel@tonic-gate 			    (state->strm.msg? state->strm.msg: ""));
4477c478bd9Sstevel@tonic-gate 
4487c478bd9Sstevel@tonic-gate 			break;
4497c478bd9Sstevel@tonic-gate 		}
4507c478bd9Sstevel@tonic-gate 
4517c478bd9Sstevel@tonic-gate 		if (state->strm.avail_in == 0) {
4527c478bd9Sstevel@tonic-gate 			if (mp != NULL)
4537c478bd9Sstevel@tonic-gate 				mp = mp->b_cont;
4547c478bd9Sstevel@tonic-gate 			if (mp == NULL) {
4557c478bd9Sstevel@tonic-gate 				if (state->strm.avail_out != 0)
4567c478bd9Sstevel@tonic-gate 					break;	/* all done */
4577c478bd9Sstevel@tonic-gate 			} else {
4587c478bd9Sstevel@tonic-gate 				state->strm.next_in = mp->b_rptr;
4597c478bd9Sstevel@tonic-gate 				state->strm.avail_in = mp->b_wptr - mp->b_rptr;
4607c478bd9Sstevel@tonic-gate 			}
4617c478bd9Sstevel@tonic-gate 		}
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate 		if (state->strm.avail_out == 0) {
4647c478bd9Sstevel@tonic-gate 			if (m != NULL) {
4657c478bd9Sstevel@tonic-gate 				m->b_wptr += wspace;
4667c478bd9Sstevel@tonic-gate 				olen += wspace;
4677c478bd9Sstevel@tonic-gate 				wspace = maxolen - olen;
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate 				if (wspace <= 0) {
4707c478bd9Sstevel@tonic-gate 					wspace = 0;
4717c478bd9Sstevel@tonic-gate 					m->b_cont = NULL;
4727c478bd9Sstevel@tonic-gate 				} else {
4737c478bd9Sstevel@tonic-gate 					if (wspace < 32) {
4747c478bd9Sstevel@tonic-gate 						wspace = 32;
4757c478bd9Sstevel@tonic-gate 					} else if (wspace > 4096) {
4767c478bd9Sstevel@tonic-gate 						wspace = 4096;
4777c478bd9Sstevel@tonic-gate 					}
4787c478bd9Sstevel@tonic-gate 
4797c478bd9Sstevel@tonic-gate 					m->b_cont = allocb(wspace, BPRI_MED);
4807c478bd9Sstevel@tonic-gate 				}
4817c478bd9Sstevel@tonic-gate 
4827c478bd9Sstevel@tonic-gate 				m = m->b_cont;
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate 				if (m != NULL) {
4857c478bd9Sstevel@tonic-gate 					state->strm.next_out = m->b_wptr;
4867c478bd9Sstevel@tonic-gate 					wspace = m->b_datap->db_lim -
4877c478bd9Sstevel@tonic-gate 					    m->b_wptr;
4887c478bd9Sstevel@tonic-gate 					state->strm.avail_out = wspace;
4897c478bd9Sstevel@tonic-gate 				}
4907c478bd9Sstevel@tonic-gate 			}
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate 			if (m == NULL) {
4937c478bd9Sstevel@tonic-gate 				state->strm.next_out = NULL;
4947c478bd9Sstevel@tonic-gate 				state->strm.avail_out = 1000000;
4957c478bd9Sstevel@tonic-gate 			}
4967c478bd9Sstevel@tonic-gate 		}
4977c478bd9Sstevel@tonic-gate 	}
4987c478bd9Sstevel@tonic-gate 
4997c478bd9Sstevel@tonic-gate 	if (m != NULL) {
5007c478bd9Sstevel@tonic-gate 		m->b_wptr += wspace - state->strm.avail_out;
5017c478bd9Sstevel@tonic-gate 		olen += wspace - state->strm.avail_out;
5027c478bd9Sstevel@tonic-gate 	}
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate 	/*
5057c478bd9Sstevel@tonic-gate 	 * See if we managed to reduce the size of the packet.
5067c478bd9Sstevel@tonic-gate 	 */
5077c478bd9Sstevel@tonic-gate 	if (olen < orig_len && m != NULL) {
5087c478bd9Sstevel@tonic-gate 		state->stats.comp_bytes += olen;
5097c478bd9Sstevel@tonic-gate 		state->stats.comp_packets++;
5107c478bd9Sstevel@tonic-gate 	} else {
5117c478bd9Sstevel@tonic-gate 		if (*mret != NULL) {
5127c478bd9Sstevel@tonic-gate 			freemsg(*mret);
5137c478bd9Sstevel@tonic-gate 			*mret = NULL;
5147c478bd9Sstevel@tonic-gate 		}
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate 		state->stats.inc_bytes += orig_len;
5177c478bd9Sstevel@tonic-gate 		state->stats.inc_packets++;
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 		olen = orig_len;
5207c478bd9Sstevel@tonic-gate 	}
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate 	state->stats.unc_bytes += orig_len;
5237c478bd9Sstevel@tonic-gate 	state->stats.unc_packets++;
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate 	return (olen);
5267c478bd9Sstevel@tonic-gate }
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate /*
5297c478bd9Sstevel@tonic-gate  * z_incomp()
5307c478bd9Sstevel@tonic-gate  *
5317c478bd9Sstevel@tonic-gate  * Incompressible data has arrived - add it to the history.
5327c478bd9Sstevel@tonic-gate  */
5337c478bd9Sstevel@tonic-gate static int
z_incomp(void * arg,mblk_t * mp)5347c478bd9Sstevel@tonic-gate z_incomp(void *arg, mblk_t *mp)
5357c478bd9Sstevel@tonic-gate {
5367c478bd9Sstevel@tonic-gate 	struct deflate_state	*state = (struct deflate_state *)arg;
5377c478bd9Sstevel@tonic-gate 	uchar_t			*rptr, *rmax;
5387c478bd9Sstevel@tonic-gate 	int			rlen;
5397c478bd9Sstevel@tonic-gate 	int			r;
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate 	/*
5427c478bd9Sstevel@tonic-gate 	 * Check that the protocol is one we handle.  Pullup is *NOT*
5437c478bd9Sstevel@tonic-gate 	 * possible here.
5447c478bd9Sstevel@tonic-gate 	 */
5457c478bd9Sstevel@tonic-gate 	rptr = mp->b_rptr;
5467c478bd9Sstevel@tonic-gate 	rmax = mp->b_wptr;
5477c478bd9Sstevel@tonic-gate 	ADJRPTR();
5487c478bd9Sstevel@tonic-gate 	rptr++;		/* skip address */
5497c478bd9Sstevel@tonic-gate 	ADJRPTR();
5507c478bd9Sstevel@tonic-gate 	rptr++;		/* skip control */
5517c478bd9Sstevel@tonic-gate 	ADJRPTR();
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate 	/*
5547c478bd9Sstevel@tonic-gate 	 * Per RFC 1979, the protocol field must be compressed using a
5557c478bd9Sstevel@tonic-gate 	 * PFC-like procedure.  Also, all protocols between 0000-3FFF
5567c478bd9Sstevel@tonic-gate 	 * except the two compression protocols must be LZ compressed.
5577c478bd9Sstevel@tonic-gate 	 */
5587c478bd9Sstevel@tonic-gate 	if (rptr == NULL)
5597c478bd9Sstevel@tonic-gate 		return (0);
5607c478bd9Sstevel@tonic-gate 	r = *rptr;
5617c478bd9Sstevel@tonic-gate 	if (r == 0) {
5627c478bd9Sstevel@tonic-gate 		rptr++;
5637c478bd9Sstevel@tonic-gate 		ADJRPTR();
5647c478bd9Sstevel@tonic-gate 		if (rptr == NULL || *rptr == PPP_COMP || *rptr == PPP_COMPFRAG)
5657c478bd9Sstevel@tonic-gate 			return (0);
5667c478bd9Sstevel@tonic-gate 	} else {
5677c478bd9Sstevel@tonic-gate 		if (r > 0x3F)
5687c478bd9Sstevel@tonic-gate 			return (0);
5697c478bd9Sstevel@tonic-gate 	}
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate 	++state->seqno;
5727c478bd9Sstevel@tonic-gate 
5737c478bd9Sstevel@tonic-gate 	/*
5747c478bd9Sstevel@tonic-gate 	 * Iterate through the message blocks, adding the characters
5757c478bd9Sstevel@tonic-gate 	 * in them to the decompressor's history.
5767c478bd9Sstevel@tonic-gate 	 */
5777c478bd9Sstevel@tonic-gate 	rlen = mp->b_wptr - rptr;
5787c478bd9Sstevel@tonic-gate 
5797c478bd9Sstevel@tonic-gate 	state->strm.next_in = rptr;
5807c478bd9Sstevel@tonic-gate 	state->strm.avail_in = rlen;
5817c478bd9Sstevel@tonic-gate 
5827c478bd9Sstevel@tonic-gate 	for (;;) {
5837c478bd9Sstevel@tonic-gate 		r = inflateIncomp(&state->strm);
5847c478bd9Sstevel@tonic-gate 
5857c478bd9Sstevel@tonic-gate 		if (r != Z_OK) {	/* gak! */
5867c478bd9Sstevel@tonic-gate 			if (state->flags & DS_DEBUG) {
5877c478bd9Sstevel@tonic-gate 				cmn_err(CE_CONT,
5887c478bd9Sstevel@tonic-gate 				    "z_incomp%d: inflateIncomp returned "
5897c478bd9Sstevel@tonic-gate 				    "%d (%s)\n", state->unit, r,
5907c478bd9Sstevel@tonic-gate 				    (state->strm.msg? state->strm.msg: ""));
5917c478bd9Sstevel@tonic-gate 			}
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 			return (-1);
5947c478bd9Sstevel@tonic-gate 		}
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate 		mp = mp->b_cont;
5977c478bd9Sstevel@tonic-gate 		if (mp == NULL) {
5987c478bd9Sstevel@tonic-gate 			break;
5997c478bd9Sstevel@tonic-gate 		}
6007c478bd9Sstevel@tonic-gate 
6017c478bd9Sstevel@tonic-gate 		state->strm.next_in = mp->b_rptr;
6027c478bd9Sstevel@tonic-gate 		state->strm.avail_in = mp->b_wptr - mp->b_rptr;
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate 		rlen += state->strm.avail_in;
6057c478bd9Sstevel@tonic-gate 	}
6067c478bd9Sstevel@tonic-gate 
6077c478bd9Sstevel@tonic-gate 	/*
6087c478bd9Sstevel@tonic-gate 	 * Update stats
6097c478bd9Sstevel@tonic-gate 	 */
6107c478bd9Sstevel@tonic-gate 	state->stats.inc_bytes += rlen;
6117c478bd9Sstevel@tonic-gate 	state->stats.inc_packets++;
6127c478bd9Sstevel@tonic-gate 	state->stats.unc_bytes += rlen;
6137c478bd9Sstevel@tonic-gate 	state->stats.unc_packets++;
6147c478bd9Sstevel@tonic-gate 	return (0);
6157c478bd9Sstevel@tonic-gate #undef ADJRPTR
6167c478bd9Sstevel@tonic-gate }
6177c478bd9Sstevel@tonic-gate 
6187c478bd9Sstevel@tonic-gate /*
6197c478bd9Sstevel@tonic-gate  * z_comp_stats()
6207c478bd9Sstevel@tonic-gate  */
6217c478bd9Sstevel@tonic-gate static void
z_comp_stats(void * arg,struct compstat * stats)6227c478bd9Sstevel@tonic-gate z_comp_stats(void *arg, struct compstat *stats)
6237c478bd9Sstevel@tonic-gate {
6247c478bd9Sstevel@tonic-gate 	struct deflate_state	*state = (struct deflate_state *)arg;
6257c478bd9Sstevel@tonic-gate 	uint_t			out;
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate 	*stats = state->stats;
6287c478bd9Sstevel@tonic-gate 	stats->ratio = stats->unc_bytes;
6297c478bd9Sstevel@tonic-gate 	out = stats->comp_bytes + stats->unc_bytes;
6307c478bd9Sstevel@tonic-gate 
6317c478bd9Sstevel@tonic-gate 	if (stats->ratio <= 0x7ffffff) {
6327c478bd9Sstevel@tonic-gate 		stats->ratio <<= 8;
6337c478bd9Sstevel@tonic-gate 	} else {
6347c478bd9Sstevel@tonic-gate 		out >>= 8;
6357c478bd9Sstevel@tonic-gate 	}
6367c478bd9Sstevel@tonic-gate 
6377c478bd9Sstevel@tonic-gate 	if (out != 0) {
6387c478bd9Sstevel@tonic-gate 		stats->ratio /= out;
6397c478bd9Sstevel@tonic-gate 	}
6407c478bd9Sstevel@tonic-gate }
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate /*
6437c478bd9Sstevel@tonic-gate  * z_decomp_alloc()
6447c478bd9Sstevel@tonic-gate  *
6457c478bd9Sstevel@tonic-gate  * Allocate space for a decompressor.
6467c478bd9Sstevel@tonic-gate  */
6477c478bd9Sstevel@tonic-gate static void *
z_decomp_alloc(uchar_t * options,int opt_len)6487c478bd9Sstevel@tonic-gate z_decomp_alloc(uchar_t *options, int opt_len)
6497c478bd9Sstevel@tonic-gate {
6507c478bd9Sstevel@tonic-gate 	struct deflate_state	*state;
6517c478bd9Sstevel@tonic-gate 	int			w_size;
6527c478bd9Sstevel@tonic-gate 
6537c478bd9Sstevel@tonic-gate 	if (opt_len != CILEN_DEFLATE ||
6547c478bd9Sstevel@tonic-gate 		(options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) ||
6557c478bd9Sstevel@tonic-gate 		options[1] != CILEN_DEFLATE ||
6567c478bd9Sstevel@tonic-gate 		DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL ||
6577c478bd9Sstevel@tonic-gate 		options[3] != DEFLATE_CHK_SEQUENCE) {
6587c478bd9Sstevel@tonic-gate 
6597c478bd9Sstevel@tonic-gate 		return (NULL);
6607c478bd9Sstevel@tonic-gate 	}
6617c478bd9Sstevel@tonic-gate 
6627c478bd9Sstevel@tonic-gate 	w_size = DEFLATE_SIZE(options[2]);
6637c478bd9Sstevel@tonic-gate 	/*
6647c478bd9Sstevel@tonic-gate 	 * Check <= minimum size to avoid unfixable zlib bug -- window size
6657c478bd9Sstevel@tonic-gate 	 * 256 (w_size 8) is not supported.
6667c478bd9Sstevel@tonic-gate 	 */
6677c478bd9Sstevel@tonic-gate 	if (w_size <= DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE) {
6687c478bd9Sstevel@tonic-gate 		return (NULL);
6697c478bd9Sstevel@tonic-gate 	}
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate 	state = (struct deflate_state *)kmem_zalloc(sizeof (*state), KM_SLEEP);
6727c478bd9Sstevel@tonic-gate 	ASSERT(state != NULL);
6737c478bd9Sstevel@tonic-gate 
6747c478bd9Sstevel@tonic-gate 	state->strm.zalloc = (alloc_func)z_alloc;
6757c478bd9Sstevel@tonic-gate 	state->strm.zfree = (free_func)z_free;
6767c478bd9Sstevel@tonic-gate 
6777c478bd9Sstevel@tonic-gate 	if (inflateInit2(&state->strm, -w_size) != Z_OK) {
6787c478bd9Sstevel@tonic-gate 		kmem_free(state, sizeof (*state));
6797c478bd9Sstevel@tonic-gate 		return (NULL);
6807c478bd9Sstevel@tonic-gate 	}
6817c478bd9Sstevel@tonic-gate 
6827c478bd9Sstevel@tonic-gate 	state->w_size = w_size;
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate 	bzero(&state->stats, sizeof (state->stats));
6857c478bd9Sstevel@tonic-gate 
6867c478bd9Sstevel@tonic-gate 	return ((void *)state);
6877c478bd9Sstevel@tonic-gate }
6887c478bd9Sstevel@tonic-gate 
6897c478bd9Sstevel@tonic-gate /*
6907c478bd9Sstevel@tonic-gate  * z_decomp_free()
6917c478bd9Sstevel@tonic-gate  */
6927c478bd9Sstevel@tonic-gate static void
z_decomp_free(void * arg)6937c478bd9Sstevel@tonic-gate z_decomp_free(void *arg)
6947c478bd9Sstevel@tonic-gate {
6957c478bd9Sstevel@tonic-gate 	struct deflate_state	*state = (struct deflate_state *)arg;
6967c478bd9Sstevel@tonic-gate 
6977c478bd9Sstevel@tonic-gate 	(void) inflateEnd(&state->strm);
6987c478bd9Sstevel@tonic-gate 
6997c478bd9Sstevel@tonic-gate 	kmem_free(state, sizeof (*state));
7007c478bd9Sstevel@tonic-gate }
7017c478bd9Sstevel@tonic-gate 
7027c478bd9Sstevel@tonic-gate /*
7037c478bd9Sstevel@tonic-gate  * z_decomp_init()
7047c478bd9Sstevel@tonic-gate  */
7057c478bd9Sstevel@tonic-gate static int
z_decomp_init(void * arg,uchar_t * options,int opt_len,int unit,int hdrlen,int mru,int debug)7067c478bd9Sstevel@tonic-gate z_decomp_init(void *arg, uchar_t *options, int opt_len, int unit, int hdrlen,
7077c478bd9Sstevel@tonic-gate 	int mru, int debug)
7087c478bd9Sstevel@tonic-gate {
7097c478bd9Sstevel@tonic-gate 	struct deflate_state *state = (struct deflate_state *)arg;
7107c478bd9Sstevel@tonic-gate 
7117c478bd9Sstevel@tonic-gate 	if (opt_len < CILEN_DEFLATE ||
7127c478bd9Sstevel@tonic-gate 		(options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) ||
7137c478bd9Sstevel@tonic-gate 		options[1] != CILEN_DEFLATE ||
7147c478bd9Sstevel@tonic-gate 		DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL ||
7157c478bd9Sstevel@tonic-gate 		DEFLATE_SIZE(options[2]) != state->w_size ||
7167c478bd9Sstevel@tonic-gate 		options[3] != DEFLATE_CHK_SEQUENCE) {
7177c478bd9Sstevel@tonic-gate 
7187c478bd9Sstevel@tonic-gate 		return (0);
7197c478bd9Sstevel@tonic-gate 	}
7207c478bd9Sstevel@tonic-gate 
7217c478bd9Sstevel@tonic-gate 	state->seqno = 0;
7227c478bd9Sstevel@tonic-gate 	state->unit = unit;
7237c478bd9Sstevel@tonic-gate 	state->hdrlen = hdrlen;
7247c478bd9Sstevel@tonic-gate 	if (debug)
7257c478bd9Sstevel@tonic-gate 		state->flags |= DS_DEBUG;
7267c478bd9Sstevel@tonic-gate 	else
7277c478bd9Sstevel@tonic-gate 		state->flags &= ~DS_DEBUG;
7287c478bd9Sstevel@tonic-gate 	state->mru = mru;
7297c478bd9Sstevel@tonic-gate 
7307c478bd9Sstevel@tonic-gate 	(void) inflateReset(&state->strm);
7317c478bd9Sstevel@tonic-gate 
7327c478bd9Sstevel@tonic-gate 	return (1);
7337c478bd9Sstevel@tonic-gate }
7347c478bd9Sstevel@tonic-gate 
7357c478bd9Sstevel@tonic-gate /*
7367c478bd9Sstevel@tonic-gate  * z_decomp_reset()
7377c478bd9Sstevel@tonic-gate  */
7387c478bd9Sstevel@tonic-gate static void
z_decomp_reset(void * arg)7397c478bd9Sstevel@tonic-gate z_decomp_reset(void *arg)
7407c478bd9Sstevel@tonic-gate {
7417c478bd9Sstevel@tonic-gate 	struct deflate_state	*state = (struct deflate_state *)arg;
7427c478bd9Sstevel@tonic-gate 
7437c478bd9Sstevel@tonic-gate 	state->seqno = 0;
7447c478bd9Sstevel@tonic-gate 
7457c478bd9Sstevel@tonic-gate 	(void) inflateReset(&state->strm);
7467c478bd9Sstevel@tonic-gate }
7477c478bd9Sstevel@tonic-gate 
7487c478bd9Sstevel@tonic-gate /*
7497c478bd9Sstevel@tonic-gate  * z_decompress()
7507c478bd9Sstevel@tonic-gate  *
7517c478bd9Sstevel@tonic-gate  * Decompress a Deflate-compressed packet.
7527c478bd9Sstevel@tonic-gate  *
7537c478bd9Sstevel@tonic-gate  * Because of patent problems, we return DECOMP_ERROR for errors
7547c478bd9Sstevel@tonic-gate  * found by inspecting the input data and for system problems, but
7557c478bd9Sstevel@tonic-gate  * DECOMP_FATALERROR for any errors which could possibly be said to
7567c478bd9Sstevel@tonic-gate  * be being detected "after" decompression.  For DECOMP_ERROR,
7577c478bd9Sstevel@tonic-gate  * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
7587c478bd9Sstevel@tonic-gate  * infringing a patent of Motorola's if we do, so we take CCP down
7597c478bd9Sstevel@tonic-gate  * instead.
7607c478bd9Sstevel@tonic-gate  *
7617c478bd9Sstevel@tonic-gate  * Given that the frame has the correct sequence number and a good FCS,
7627c478bd9Sstevel@tonic-gate  * errors such as invalid codes in the input most likely indicate a
7637c478bd9Sstevel@tonic-gate  * bug, so we return DECOMP_FATALERROR for them in order to turn off
7647c478bd9Sstevel@tonic-gate  * compression, even though they are detected by inspecting the input.
7657c478bd9Sstevel@tonic-gate  */
7667c478bd9Sstevel@tonic-gate static int
z_decompress(void * arg,mblk_t ** mop)7677c478bd9Sstevel@tonic-gate z_decompress(void *arg, mblk_t **mop)
7687c478bd9Sstevel@tonic-gate {
7697c478bd9Sstevel@tonic-gate 	struct deflate_state	*state = (struct deflate_state *)arg;
7707c478bd9Sstevel@tonic-gate 	mblk_t			*mi = *mop, *mnext;
7717c478bd9Sstevel@tonic-gate 	mblk_t			*mo;
7727c478bd9Sstevel@tonic-gate 	mblk_t			*mo_head;
7737c478bd9Sstevel@tonic-gate 	uchar_t			*rptr, *rmax;
7747c478bd9Sstevel@tonic-gate 	uchar_t			*wptr;
7757c478bd9Sstevel@tonic-gate 	int			rlen;
7767c478bd9Sstevel@tonic-gate 	int			olen;
7777c478bd9Sstevel@tonic-gate 	int			ospace;
7787c478bd9Sstevel@tonic-gate 	int			seq;
7797c478bd9Sstevel@tonic-gate 	int			flush;
7807c478bd9Sstevel@tonic-gate 	int			r;
7817c478bd9Sstevel@tonic-gate 	int			decode_proto;
7827c478bd9Sstevel@tonic-gate #if defined(lint) || defined(_lint)
7837c478bd9Sstevel@tonic-gate 	uchar_t			hdlcaddr, hdlcctrl;
7847c478bd9Sstevel@tonic-gate #else
7857c478bd9Sstevel@tonic-gate 	int			hdlcaddr, hdlcctrl;
7867c478bd9Sstevel@tonic-gate #endif
7877c478bd9Sstevel@tonic-gate 
7887c478bd9Sstevel@tonic-gate 	/* Note: spppcomp already did a pullup to fix the first buffer. */
7897c478bd9Sstevel@tonic-gate 	*mop = NULL;
7907c478bd9Sstevel@tonic-gate 	rptr = mi->b_rptr + PPP_HDRLEN;
7917c478bd9Sstevel@tonic-gate 	rmax = mi->b_wptr;
7927c478bd9Sstevel@tonic-gate 	if (rptr > rmax) {
7937c478bd9Sstevel@tonic-gate 		if (state->flags & DS_DEBUG) {
7947c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT, "z_decompress%d: bad buffer\n",
7957c478bd9Sstevel@tonic-gate 			    state->unit);
7967c478bd9Sstevel@tonic-gate 		}
7977c478bd9Sstevel@tonic-gate 		freemsg(mi);
7987c478bd9Sstevel@tonic-gate 		return (DECOMP_ERROR);
7997c478bd9Sstevel@tonic-gate 	}
8007c478bd9Sstevel@tonic-gate 
8017c478bd9Sstevel@tonic-gate 	hdlcaddr = rptr[-PPP_HDRLEN];
8027c478bd9Sstevel@tonic-gate 	hdlcctrl = rptr[-PPP_HDRLEN+1];
8037c478bd9Sstevel@tonic-gate 
8047c478bd9Sstevel@tonic-gate 	/*
8057c478bd9Sstevel@tonic-gate 	 * Note that we free as we go.  If we fail to decompress,
8067c478bd9Sstevel@tonic-gate 	 * there's nothing good that the caller can do.
8077c478bd9Sstevel@tonic-gate 	 */
8087c478bd9Sstevel@tonic-gate #define	ADJRPTR() {						\
8097c478bd9Sstevel@tonic-gate 	if (rptr != NULL) {					\
8107c478bd9Sstevel@tonic-gate 		while (rptr >= rmax) {				\
8117c478bd9Sstevel@tonic-gate 			mnext = mi->b_cont;			\
8127c478bd9Sstevel@tonic-gate 			freeb(mi);				\
8137c478bd9Sstevel@tonic-gate 			if ((mi = mnext) == NULL) {		\
8147c478bd9Sstevel@tonic-gate 				rptr = NULL;			\
8157c478bd9Sstevel@tonic-gate 				break;				\
8167c478bd9Sstevel@tonic-gate 			}					\
8177c478bd9Sstevel@tonic-gate 			rptr = mi->b_rptr;			\
8187c478bd9Sstevel@tonic-gate 			rmax = mi->b_wptr;			\
8197c478bd9Sstevel@tonic-gate 		}						\
8207c478bd9Sstevel@tonic-gate 	}							\
8217c478bd9Sstevel@tonic-gate }
8227c478bd9Sstevel@tonic-gate 
8237c478bd9Sstevel@tonic-gate 	/*
8247c478bd9Sstevel@tonic-gate 	 * Check the sequence number
8257c478bd9Sstevel@tonic-gate 	 */
8267c478bd9Sstevel@tonic-gate 	ADJRPTR();
8277c478bd9Sstevel@tonic-gate 	seq = rptr == NULL ? 0 : (*rptr++ << 8);
8287c478bd9Sstevel@tonic-gate 	ADJRPTR();
8297c478bd9Sstevel@tonic-gate 	if (rptr == NULL) {
8307c478bd9Sstevel@tonic-gate 		if (state->flags & DS_DEBUG) {
8317c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT, "z_decompress%d: bad buffer\n",
8327c478bd9Sstevel@tonic-gate 			    state->unit);
8337c478bd9Sstevel@tonic-gate 		}
8347c478bd9Sstevel@tonic-gate 		return (DECOMP_ERROR);
8357c478bd9Sstevel@tonic-gate 	}
8367c478bd9Sstevel@tonic-gate 
8377c478bd9Sstevel@tonic-gate 	seq |= *rptr++;
8387c478bd9Sstevel@tonic-gate 
8397c478bd9Sstevel@tonic-gate #ifdef DEBUG
8407c478bd9Sstevel@tonic-gate 	/*
8417c478bd9Sstevel@tonic-gate 	 * If testing input, just pretending the sequence is bad here
8427c478bd9Sstevel@tonic-gate 	 * does the trick.
8437c478bd9Sstevel@tonic-gate 	 */
8447c478bd9Sstevel@tonic-gate 	if ((state->flags & DS_TESTIN) && (state->seqno % 300) == 101)
8457c478bd9Sstevel@tonic-gate 		seq ^= 0x55;
8467c478bd9Sstevel@tonic-gate #endif
8477c478bd9Sstevel@tonic-gate 	if (seq != state->seqno++) {
8487c478bd9Sstevel@tonic-gate 		freemsg(mi);
8497c478bd9Sstevel@tonic-gate 		if (state->flags & DS_DEBUG) {
8507c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT,
8517c478bd9Sstevel@tonic-gate 				"z_decompress%d: bad seq # %d, expected %d\n",
8527c478bd9Sstevel@tonic-gate 				state->unit, seq, state->seqno - 1);
8537c478bd9Sstevel@tonic-gate 		}
8547c478bd9Sstevel@tonic-gate 		return (DECOMP_ERROR);
8557c478bd9Sstevel@tonic-gate 	}
8567c478bd9Sstevel@tonic-gate 
8577c478bd9Sstevel@tonic-gate 	/*
8587c478bd9Sstevel@tonic-gate 	 * Allocate an output message block
8597c478bd9Sstevel@tonic-gate 	 */
8607c478bd9Sstevel@tonic-gate 	mo = allocb(DECOMP_CHUNK + state->hdrlen, BPRI_MED);
8617c478bd9Sstevel@tonic-gate 	if (mo == NULL) {
8627c478bd9Sstevel@tonic-gate 		freemsg(mi);
8637c478bd9Sstevel@tonic-gate 		return (DECOMP_ERROR);
8647c478bd9Sstevel@tonic-gate 	}
8657c478bd9Sstevel@tonic-gate 
8667c478bd9Sstevel@tonic-gate 	mo_head = mo;
8677c478bd9Sstevel@tonic-gate 	mo->b_cont = NULL;
8687c478bd9Sstevel@tonic-gate 	mo->b_rptr += state->hdrlen;
8697c478bd9Sstevel@tonic-gate 	mo->b_wptr = wptr = mo->b_rptr;
8707c478bd9Sstevel@tonic-gate 
8717c478bd9Sstevel@tonic-gate 	ospace = DECOMP_CHUNK;
8727c478bd9Sstevel@tonic-gate 	olen = 0;
8737c478bd9Sstevel@tonic-gate 
8747c478bd9Sstevel@tonic-gate 	/*
8757c478bd9Sstevel@tonic-gate 	 * Fill in the first part of the PPP header.  The protocol field
8767c478bd9Sstevel@tonic-gate 	 * comes from the decompressed data.
8777c478bd9Sstevel@tonic-gate 	 */
8787c478bd9Sstevel@tonic-gate 	*wptr++ = hdlcaddr;
8797c478bd9Sstevel@tonic-gate 	*wptr++ = hdlcctrl;
8807c478bd9Sstevel@tonic-gate 	*wptr++ = 0;
8817c478bd9Sstevel@tonic-gate 
8827c478bd9Sstevel@tonic-gate 	/*
8837c478bd9Sstevel@tonic-gate 	 * Set up to call inflate.  We set avail_out to 1 initially so we can
8847c478bd9Sstevel@tonic-gate 	 * look at the first byte of the output and decide whether we have
8857c478bd9Sstevel@tonic-gate 	 * a 1-byte or 2-byte protocol field.
8867c478bd9Sstevel@tonic-gate 	 */
8877c478bd9Sstevel@tonic-gate 	state->strm.next_in = rptr;
8887c478bd9Sstevel@tonic-gate 	state->strm.avail_in = mi->b_wptr - rptr;
8897c478bd9Sstevel@tonic-gate 
8907c478bd9Sstevel@tonic-gate 	rlen = state->strm.avail_in + PPP_HDRLEN + DEFLATE_OVHD;
8917c478bd9Sstevel@tonic-gate 
8927c478bd9Sstevel@tonic-gate 	state->strm.next_out = wptr;
8937c478bd9Sstevel@tonic-gate 	state->strm.avail_out = 1;
8947c478bd9Sstevel@tonic-gate 
8957c478bd9Sstevel@tonic-gate 	decode_proto = 1;
8967c478bd9Sstevel@tonic-gate 
8977c478bd9Sstevel@tonic-gate 	/*
8987c478bd9Sstevel@tonic-gate 	 * Call inflate, supplying more input or output as needed.
8997c478bd9Sstevel@tonic-gate 	 */
9007c478bd9Sstevel@tonic-gate 	for (;;) {
9017c478bd9Sstevel@tonic-gate 
9027c478bd9Sstevel@tonic-gate 		flush = (mi == NULL || mi->b_cont == NULL) ?
9037c478bd9Sstevel@tonic-gate 		    Z_PACKET_FLUSH : Z_NO_FLUSH;
9047c478bd9Sstevel@tonic-gate 		r = inflate(&state->strm, flush);
9057c478bd9Sstevel@tonic-gate 
9067c478bd9Sstevel@tonic-gate 		if (r != Z_OK) {
9077c478bd9Sstevel@tonic-gate 
9087c478bd9Sstevel@tonic-gate 			if (state->flags & DS_DEBUG) {
9097c478bd9Sstevel@tonic-gate 				cmn_err(CE_CONT,
9107c478bd9Sstevel@tonic-gate 				    "z_decompress%d: inflate returned %d "
9117c478bd9Sstevel@tonic-gate 				    "(%s)\n", state->unit, r,
9127c478bd9Sstevel@tonic-gate 				    (state->strm.msg? state->strm.msg: ""));
9137c478bd9Sstevel@tonic-gate 			}
9147c478bd9Sstevel@tonic-gate 
9157c478bd9Sstevel@tonic-gate 			if (mi != NULL)
9167c478bd9Sstevel@tonic-gate 				freemsg(mi);
9177c478bd9Sstevel@tonic-gate 			freemsg(mo_head);
9187c478bd9Sstevel@tonic-gate 
9197c478bd9Sstevel@tonic-gate 			return (DECOMP_FATALERROR);
9207c478bd9Sstevel@tonic-gate 		}
9217c478bd9Sstevel@tonic-gate 
9227c478bd9Sstevel@tonic-gate 		if (state->strm.avail_in == 0) {
9237c478bd9Sstevel@tonic-gate 			if (mi != NULL) {
9247c478bd9Sstevel@tonic-gate 				mnext = mi->b_cont;
9257c478bd9Sstevel@tonic-gate 				freeb(mi);
9267c478bd9Sstevel@tonic-gate 				mi = mnext;
9277c478bd9Sstevel@tonic-gate 			}
9287c478bd9Sstevel@tonic-gate 			if (mi == NULL) {
9297c478bd9Sstevel@tonic-gate 				if (state->strm.avail_out != 0)
9307c478bd9Sstevel@tonic-gate 					break;	/* all done */
9317c478bd9Sstevel@tonic-gate 			} else {
9327c478bd9Sstevel@tonic-gate 				state->strm.next_in = mi->b_rptr;
9337c478bd9Sstevel@tonic-gate 				state->strm.avail_in = mi->b_wptr - mi->b_rptr;
9347c478bd9Sstevel@tonic-gate 
9357c478bd9Sstevel@tonic-gate 				rlen += state->strm.avail_in;
9367c478bd9Sstevel@tonic-gate 			}
9377c478bd9Sstevel@tonic-gate 		}
9387c478bd9Sstevel@tonic-gate 
9397c478bd9Sstevel@tonic-gate 		if (state->strm.avail_out == 0) {
9407c478bd9Sstevel@tonic-gate 			if (decode_proto) {
9417c478bd9Sstevel@tonic-gate 				state->strm.avail_out = ospace - PPP_HDRLEN;
9427c478bd9Sstevel@tonic-gate 
9437c478bd9Sstevel@tonic-gate 				if ((wptr[0] & 1) == 0) {
9447c478bd9Sstevel@tonic-gate 					/*
9457c478bd9Sstevel@tonic-gate 					 * 2-byte protocol field
9467c478bd9Sstevel@tonic-gate 					 */
9477c478bd9Sstevel@tonic-gate 					wptr[-1] = wptr[0];
9487c478bd9Sstevel@tonic-gate 
9497c478bd9Sstevel@tonic-gate 					--state->strm.next_out;
9507c478bd9Sstevel@tonic-gate 					++state->strm.avail_out;
9517c478bd9Sstevel@tonic-gate 				}
9527c478bd9Sstevel@tonic-gate 
9537c478bd9Sstevel@tonic-gate 				decode_proto = 0;
9547c478bd9Sstevel@tonic-gate 			} else {
9557c478bd9Sstevel@tonic-gate 				mo->b_wptr += ospace;
9567c478bd9Sstevel@tonic-gate 				olen += ospace;
9577c478bd9Sstevel@tonic-gate 
9587c478bd9Sstevel@tonic-gate 				mo->b_cont = allocb(DECOMP_CHUNK, BPRI_MED);
9597c478bd9Sstevel@tonic-gate 
9607c478bd9Sstevel@tonic-gate 				mo = mo->b_cont;
9617c478bd9Sstevel@tonic-gate 				if (mo == NULL) {
9627c478bd9Sstevel@tonic-gate 					if (mi != NULL)
9637c478bd9Sstevel@tonic-gate 						freemsg(mi);
9647c478bd9Sstevel@tonic-gate 					freemsg(mo_head);
9657c478bd9Sstevel@tonic-gate 					return (DECOMP_ERROR);
9667c478bd9Sstevel@tonic-gate 				}
9677c478bd9Sstevel@tonic-gate 
9687c478bd9Sstevel@tonic-gate 				state->strm.next_out = mo->b_rptr;
9697c478bd9Sstevel@tonic-gate 				state->strm.avail_out = ospace = DECOMP_CHUNK;
9707c478bd9Sstevel@tonic-gate 			}
9717c478bd9Sstevel@tonic-gate 		}
9727c478bd9Sstevel@tonic-gate 	}
9737c478bd9Sstevel@tonic-gate 
9747c478bd9Sstevel@tonic-gate 	if (decode_proto) {
9757c478bd9Sstevel@tonic-gate 		freemsg(mo_head);
9767c478bd9Sstevel@tonic-gate 		return (DECOMP_ERROR);
9777c478bd9Sstevel@tonic-gate 	}
9787c478bd9Sstevel@tonic-gate 
9797c478bd9Sstevel@tonic-gate 	mo->b_wptr += ospace - state->strm.avail_out;
9807c478bd9Sstevel@tonic-gate 	olen += ospace - state->strm.avail_out;
9817c478bd9Sstevel@tonic-gate 
9827c478bd9Sstevel@tonic-gate 	if ((olen > state->mru + PPP_HDRLEN) && (state->flags & DS_DEBUG)) {
9837c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "z_decompress%d: exceeded mru (%d > %d)\n",
9847c478bd9Sstevel@tonic-gate 		    state->unit, olen, state->mru + PPP_HDRLEN);
9857c478bd9Sstevel@tonic-gate 	}
9867c478bd9Sstevel@tonic-gate 
9877c478bd9Sstevel@tonic-gate 	state->stats.unc_bytes += olen;
9887c478bd9Sstevel@tonic-gate 	state->stats.unc_packets++;
9897c478bd9Sstevel@tonic-gate 	state->stats.comp_bytes += rlen;
9907c478bd9Sstevel@tonic-gate 	state->stats.comp_packets++;
9917c478bd9Sstevel@tonic-gate 
9927c478bd9Sstevel@tonic-gate 	*mop = mo_head;
9937c478bd9Sstevel@tonic-gate 
9947c478bd9Sstevel@tonic-gate 	return (DECOMP_OK);
9957c478bd9Sstevel@tonic-gate }
9967c478bd9Sstevel@tonic-gate 
9977c478bd9Sstevel@tonic-gate /* ARGSUSED */
9987c478bd9Sstevel@tonic-gate static int
z_set_effort(void * xarg,void * rarg,int effortlevel)9997c478bd9Sstevel@tonic-gate z_set_effort(void *xarg, void *rarg, int effortlevel)
10007c478bd9Sstevel@tonic-gate {
10017c478bd9Sstevel@tonic-gate 	struct deflate_state *xstate = (struct deflate_state *)xarg;
10027c478bd9Sstevel@tonic-gate #ifdef DEBUG
10037c478bd9Sstevel@tonic-gate 	struct deflate_state *rstate = (struct deflate_state *)rarg;
10047c478bd9Sstevel@tonic-gate #endif
10057c478bd9Sstevel@tonic-gate 	int retv;
10067c478bd9Sstevel@tonic-gate 
10077c478bd9Sstevel@tonic-gate #ifdef DEBUG
10087c478bd9Sstevel@tonic-gate 	if (effortlevel == 42 || effortlevel == 2112) {
10097c478bd9Sstevel@tonic-gate 		/* corrupt received data. */
10107c478bd9Sstevel@tonic-gate 		if (rstate != NULL) {
10117c478bd9Sstevel@tonic-gate 			rstate->flags |= DS_TESTIN;
10127c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT, "deflate: enabled input testing.");
10137c478bd9Sstevel@tonic-gate 		}
10147c478bd9Sstevel@tonic-gate 		if (effortlevel != 2112)
10157c478bd9Sstevel@tonic-gate 			return (0);
10167c478bd9Sstevel@tonic-gate 	}
10177c478bd9Sstevel@tonic-gate 	if (effortlevel == 2001 || effortlevel == 2112) {
10187c478bd9Sstevel@tonic-gate 		/* corrupt transmitted data. */
10197c478bd9Sstevel@tonic-gate 		if (xstate != NULL) {
10207c478bd9Sstevel@tonic-gate 			xstate->flags |= DS_TESTOUT;
10217c478bd9Sstevel@tonic-gate 			cmn_err(CE_CONT, "deflate: enabled output testing.");
10227c478bd9Sstevel@tonic-gate 		}
10237c478bd9Sstevel@tonic-gate 		return (0);
10247c478bd9Sstevel@tonic-gate 	}
10257c478bd9Sstevel@tonic-gate #endif
10267c478bd9Sstevel@tonic-gate 	if (effortlevel < -1 || effortlevel > 9)
10277c478bd9Sstevel@tonic-gate 		return (EINVAL);
10287c478bd9Sstevel@tonic-gate 	if (xstate == NULL)
10297c478bd9Sstevel@tonic-gate 		return (0);
10307c478bd9Sstevel@tonic-gate 	retv = deflateParams(&xstate->strm, effortlevel, Z_DEFAULT_STRATEGY);
10317c478bd9Sstevel@tonic-gate 	return (retv == Z_OK ? 0 : EINVAL);
10327c478bd9Sstevel@tonic-gate }
10337c478bd9Sstevel@tonic-gate 
10347c478bd9Sstevel@tonic-gate #endif /* DO_DEFLATE */
1035