Home | History | Annotate | Download | only in spppcomp
      1 /*
      2  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
      3  * Use is subject to license terms.
      4  *
      5  * Because this code is derived from the 4.3BSD compress source:
      6  *
      7  * Copyright (c) 1985, 1986 The Regents of the University of California.
      8  * All rights reserved.
      9  *
     10  * This code is derived from software contributed to Berkeley by
     11  * James A. Woods, derived from original work by Spencer Thomas
     12  * and Joseph Orost.
     13  *
     14  * Redistribution and use in source and binary forms, with or without
     15  * modification, are permitted provided that the following conditions
     16  * are met:
     17  * 1. Redistributions of source code must retain the above copyright
     18  *    notice, this list of conditions and the following disclaimer.
     19  * 2. Redistributions in binary form must reproduce the above copyright
     20  *    notice, this list of conditions and the following disclaimer in the
     21  *    documentation and/or other materials provided with the distribution.
     22  * 3. All advertising materials mentioning features or use of this software
     23  *    must display the following acknowledgement:
     24  *	This product includes software developed by the University of
     25  *	California, Berkeley and its contributors.
     26  * 4. Neither the name of the University nor the names of its contributors
     27  *    may be used to endorse or promote products derived from this software
     28  *    without specific prior written permission.
     29  *
     30  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     31  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     32  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     33  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     34  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     35  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     36  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     37  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     38  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     39  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     40  * SUCH DAMAGE.
     41  */
     42 
     43 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     44 
     45 /*
     46  * This version is for use with STREAMS in Solaris 2
     47  *
     48  * $Id: bsd-comp.c,v 1.20 1996/08/28 06:31:57 paulus Exp $
     49  */
     50 
     51 #include <sys/param.h>
     52 #include <sys/types.h>
     53 #include <sys/kmem.h>
     54 #include <sys/stream.h>
     55 #include <sys/cmn_err.h>
     56 #include <sys/ddi.h>
     57 #include <sys/sunddi.h>
     58 #include <sys/byteorder.h>
     59 #include <net/ppp_defs.h>
     60 
     61 /* Defined for platform-neutral include file */
     62 #define	PACKETPTR		mblk_t *
     63 #include <net/ppp-comp.h>
     64 
     65 #ifndef _BIG_ENDIAN
     66 #define	BSD_LITTLE_ENDIAN
     67 #endif
     68 
     69 #if DO_BSD_COMPRESS
     70 
     71 /*
     72  * PPP "BSD compress" compression
     73  *
     74  *  The differences between this compression and the classic BSD LZW
     75  *  source are obvious from the requirement that the classic code worked
     76  *  with files while this handles arbitrarily long streams that
     77  *  are broken into packets.  They are:
     78  *
     79  *	When the code size expands, a block of junk is not emitted by
     80  *	    the compressor and not expected by the decompressor.
     81  *
     82  *	New codes are not necessarily assigned every time an old
     83  *	    code is output by the compressor.  This is because a packet
     84  *	    end forces a code to be emitted, but does not imply that a
     85  *	    new sequence has been seen.
     86  *
     87  *	The compression ratio is checked at the first end of a packet
     88  *	    after the appropriate gap.	Besides simplifying and speeding
     89  *	    things up, this makes it more likely that the transmitter
     90  *	    and receiver will agree when the dictionary is cleared when
     91  *	    compression is not going well.
     92  */
     93 
     94 /*
     95  * A dictionary for doing BSD compress.
     96  */
     97 struct bsd_db {
     98 	int		totlen;		/* length of this structure */
     99 	uint_t		hsize;		/* size of the hash table */
    100 	uint32_t	unit;
    101 	uchar_t		hshift;		/* used in hash function */
    102 	uchar_t		n_bits;		/* current bits/code */
    103 	uchar_t		maxbits;
    104 	uchar_t		flags;
    105 	ushort_t	seqno;		/* sequence number of next packet */
    106 	ushort_t	mru;
    107 	uint_t		hdrlen;		/* header length to preallocate */
    108 	uint_t		maxmaxcode;	/* largest valid code */
    109 	uint_t		max_ent;	/* largest code in use */
    110 	uint_t		in_count;	/* uncompressed bytes, aged */
    111 	uint_t		bytes_out;	/* compressed bytes, aged */
    112 	uint_t		ratio;		/* recent compression ratio */
    113 	uint_t		checkpoint;	/* when to next check the ratio */
    114 	uint_t		clear_count;	/* times dictionary cleared */
    115 	uint_t		incomp_count;	/* incompressible packets */
    116 	uint_t		incomp_bytes;	/* incompressible bytes */
    117 	uint_t		uncomp_count;	/* uncompressed packets */
    118 	uint_t		uncomp_bytes;	/* uncompressed bytes */
    119 	uint_t		comp_count;	/* compressed packets */
    120 	uint_t		comp_bytes;	/* compressed bytes */
    121 	ushort_t	*lens;		/* array of lengths of codes */
    122 	struct bsd_dict {
    123 	union {				/* hash value */
    124 		uint32_t	fcode;
    125 		struct {
    126 #ifdef BSD_LITTLE_ENDIAN
    127 			ushort_t	prefix;	/* preceding code */
    128 			uchar_t		suffix;	/* last character of new code */
    129 			uchar_t		pad;
    130 #else
    131 			uchar_t		pad;
    132 			uchar_t		suffix;	/* last character of new code */
    133 			ushort_t	prefix;	/* preceding code */
    134 #endif
    135 		} hs;
    136 	} f;
    137 		ushort_t	codem1;		/* output of hash table -1 */
    138 		ushort_t	cptr;		/* map code to hash entry */
    139 	} dict[1];
    140 };
    141 
    142 #define	BSD_OVHD	2		/* BSD compress overhead/packet */
    143 #define	BSD_INIT_BITS	BSD_MIN_BITS
    144 
    145 /* db->flags values */
    146 #define	DS_DEBUG	0x01
    147 #define	DS_TESTIN	0x02
    148 #define	DS_TESTOUT	0x04
    149 #define	DS_INITDONE	0x08
    150 
    151 static void	*bsd_comp_alloc(uchar_t *options, int opt_len);
    152 static void	*bsd_decomp_alloc(uchar_t *options, int opt_len);
    153 static void	bsd_free(void *state);
    154 static int	bsd_comp_init(void *state, uchar_t *options, int opt_len,
    155 				int unit, int hdrlen, int debug);
    156 static int	bsd_decomp_init(void *state, uchar_t *options, int opt_len,
    157 				int unit, int hdrlen, int mru, int debug);
    158 static int	bsd_compress(void *state, mblk_t **mret,
    159 				mblk_t *mp, int slen, int maxolen);
    160 static int	bsd_incomp(void *state, mblk_t *dmsg);
    161 static int	bsd_decompress(void *state, mblk_t **dmpp);
    162 static void	bsd_reset(void *state);
    163 static void	bsd_comp_stats(void *state, struct compstat *stats);
    164 static int	bsd_set_effort(void *xarg, void *rarg, int effortlevel);
    165 
    166 /*
    167  * Procedures exported to ppp_comp.c.
    168  */
    169 struct compressor ppp_bsd_compress = {
    170 	CI_BSD_COMPRESS,		/* compress_proto */
    171 	bsd_comp_alloc,			/* comp_alloc */
    172 	bsd_free,			/* comp_free */
    173 	bsd_comp_init,			/* comp_init */
    174 	bsd_reset,			/* comp_reset */
    175 	bsd_compress,			/* compress */
    176 	bsd_comp_stats,			/* comp_stat */
    177 	bsd_decomp_alloc,		/* decomp_alloc */
    178 	bsd_free,			/* decomp_free */
    179 	bsd_decomp_init,		/* decomp_init */
    180 	bsd_reset,			/* decomp_reset */
    181 	bsd_decompress,			/* decompress */
    182 	bsd_incomp,			/* incomp */
    183 	bsd_comp_stats,			/* decomp_stat */
    184 	bsd_set_effort,			/* set_effort */
    185 };
    186 
    187 /*
    188  * the next two codes should not be changed lightly, as they must not
    189  * lie within the contiguous general code space.
    190  */
    191 #define	CLEAR		256		/* table clear output code */
    192 #define	FIRST		257		/* first free entry */
    193 #define	LAST		255
    194 
    195 #define	MAXCODE(b)	((1 << (b)) - 1)
    196 #define	BADCODEM1	MAXCODE(BSD_MAX_BITS)
    197 
    198 #define	BSD_HASH(prefix, suffix, hshift)	\
    199 	((((uint32_t)(suffix)) << (hshift)) ^ (uint32_t)(prefix))
    200 
    201 #define	BSD_KEY(prefix, suffix)		\
    202 	((((uint32_t)(suffix)) << 16) + (uint32_t)(prefix))
    203 
    204 #define	CHECK_GAP	10000		/* Ratio check interval */
    205 
    206 #define	RATIO_SCALE_LOG	8
    207 #define	RATIO_SCALE	(1 << RATIO_SCALE_LOG)
    208 #define	RATIO_MAX	(0x7fffffff >> RATIO_SCALE_LOG)
    209 
    210 #define	DECOMP_CHUNK	256
    211 
    212 /*
    213  * bsd_clear()
    214  *
    215  * clear the dictionary
    216  */
    217 static void
    218 bsd_clear(struct bsd_db *db)
    219 {
    220 	db->clear_count++;
    221 	db->max_ent = FIRST-1;
    222 	db->n_bits = BSD_INIT_BITS;
    223 	db->ratio = 0;
    224 	db->bytes_out = 0;
    225 	db->in_count = 0;
    226 	db->checkpoint = CHECK_GAP;
    227 }
    228 
    229 /*
    230  * bsd_check()
    231  *
    232  * If the dictionary is full, then see if it is time to reset it.
    233  *
    234  * Compute the compression ratio using fixed-point arithmetic
    235  * with 8 fractional bits.
    236  *
    237  * Since we have an infinite stream instead of a single file,
    238  * watch only the local compression ratio.
    239  *
    240  * Since both peers must reset the dictionary at the same time even in
    241  * the absence of CLEAR codes (while packets are incompressible), they
    242  * must compute the same ratio.
    243  */
    244 static int				/* 1=output CLEAR */
    245 bsd_check(struct bsd_db *db)
    246 {
    247 	uint_t	new_ratio;
    248 
    249 	if (db->in_count >= db->checkpoint) {
    250 
    251 		/*
    252 		 * age the ratio by limiting the size of the counts
    253 		 */
    254 		if (db->in_count >= RATIO_MAX || db->bytes_out >= RATIO_MAX) {
    255 			db->in_count -= db->in_count/4;
    256 			db->bytes_out -= db->bytes_out/4;
    257 		}
    258 
    259 		db->checkpoint = db->in_count + CHECK_GAP;
    260 
    261 		if (db->max_ent >= db->maxmaxcode) {
    262 
    263 			/*
    264 			 * Reset the dictionary only if the ratio is worse,
    265 			 * or if it looks as if it has been poisoned
    266 			 * by incompressible data.
    267 			 *
    268 			 * This does not overflow, because
    269 			 * db->in_count <= RATIO_MAX.
    270 			 */
    271 			new_ratio = db->in_count << RATIO_SCALE_LOG;
    272 
    273 			if (db->bytes_out != 0) {
    274 				new_ratio /= db->bytes_out;
    275 			}
    276 
    277 			if (new_ratio < db->ratio ||
    278 			    new_ratio < 1 * RATIO_SCALE) {
    279 				bsd_clear(db);
    280 				return (1);
    281 			}
    282 
    283 			db->ratio = new_ratio;
    284 		}
    285 	}
    286 
    287 	return (0);
    288 }
    289 
    290 /*
    291  * bsd_comp_stats()
    292  *
    293  * Return statistics.
    294  */
    295 static void
    296 bsd_comp_stats(void *state, struct compstat *stats)
    297 {
    298 	struct bsd_db	*db = (struct bsd_db *)state;
    299 	uint_t		out;
    300 
    301 	stats->unc_bytes = db->uncomp_bytes;
    302 	stats->unc_packets = db->uncomp_count;
    303 	stats->comp_bytes = db->comp_bytes;
    304 	stats->comp_packets = db->comp_count;
    305 	stats->inc_bytes = db->incomp_bytes;
    306 	stats->inc_packets = db->incomp_count;
    307 	stats->ratio = db->in_count;
    308 
    309 	out = db->bytes_out;
    310 
    311 	if (stats->ratio <= 0x7fffff) {
    312 		stats->ratio <<= 8;
    313 	} else {
    314 		out >>= 8;
    315 	}
    316 
    317 	if (out != 0) {
    318 		stats->ratio /= out;
    319 	}
    320 }
    321 
    322 /*
    323  * bsd_reset()
    324  *
    325  * Reset state, as on a CCP ResetReq.
    326  */
    327 static void
    328 bsd_reset(void *state)
    329 {
    330 	struct bsd_db	*db = (struct bsd_db *)state;
    331 
    332 	if (db->hsize != 0) {
    333 		db->seqno = 0;
    334 
    335 		bsd_clear(db);
    336 
    337 		db->clear_count = 0;
    338 	}
    339 }
    340 
    341 /*
    342  * bsd_alloc()
    343  *
    344  * Allocate space for a (de) compressor.
    345  */
    346 static void *
    347 bsd_alloc(uchar_t *options, int opt_len, int decomp)
    348 {
    349 	int		bits;
    350 	uint_t		newlen;
    351 	uint_t		hsize;
    352 	uint_t		hshift;
    353 	uint_t		maxmaxcode;
    354 	uint_t		ilen;
    355 	struct bsd_db	*db;
    356 
    357 	if (opt_len != 3 ||
    358 	    options[0] != CI_BSD_COMPRESS ||
    359 	    options[1] != 3 ||
    360 	    BSD_VERSION(options[2]) != BSD_CURRENT_VERSION) {
    361 
    362 		return (NULL);
    363 	}
    364 
    365 	bits = BSD_NBITS(options[2]);
    366 
    367 	switch (bits) {
    368 
    369 	case 9:				/* needs 82152 for both directions */
    370 	case 10:			/* needs 84144 */
    371 	case 11:			/* needs 88240 */
    372 	case 12:			/* needs 96432 */
    373 
    374 		hsize = 5003;
    375 		hshift = 4;
    376 
    377 		break;
    378 
    379 	case 13:			/* needs 176784 */
    380 
    381 		hsize = 9001;
    382 		hshift = 5;
    383 
    384 		break;
    385 
    386 	case 14:			/* needs 353744 */
    387 
    388 		hsize = 18013;
    389 		hshift = 6;
    390 
    391 		break;
    392 
    393 	case 15:			/* needs 691440 */
    394 
    395 		hsize = 35023;
    396 		hshift = 7;
    397 
    398 		break;
    399 
    400 	/* XXX: this falls thru - it was originally commented */
    401 	case 16:			/* needs 1366160--far too much, */
    402 		/* hsize = 69001; */	/* and 69001 is too big for cptr */
    403 		/* hshift = 8; */	/* in struct bsd_db */
    404 		/* break; */
    405 
    406 	default:
    407 
    408 		return (NULL);
    409 	}
    410 
    411 	maxmaxcode = MAXCODE(bits);
    412 	ilen = newlen = sizeof (*db) + (hsize-1) * sizeof (db->dict[0]);
    413 	if (decomp)
    414 		newlen += (maxmaxcode+1) * sizeof (db->lens[0]);
    415 	db = (struct bsd_db *)kmem_alloc(newlen, KM_NOSLEEP);
    416 	if (!db) {
    417 		return (NULL);
    418 	}
    419 
    420 	bzero(db, sizeof (*db) - sizeof (db->dict));
    421 
    422 	if (!decomp) {
    423 		db->lens = NULL;
    424 	} else {
    425 		db->lens = (ushort_t *)((caddr_t)db + ilen);
    426 	}
    427 
    428 	db->totlen = newlen;
    429 	db->hsize = hsize;
    430 	db->hshift = (uchar_t)hshift;
    431 	db->maxmaxcode = maxmaxcode;
    432 	db->maxbits = (uchar_t)bits;
    433 
    434 	return ((void *)db);
    435 }
    436 
    437 /*
    438  * bsd_free()
    439  */
    440 static void
    441 bsd_free(void *state)
    442 {
    443 	struct bsd_db	*db = (struct bsd_db *)state;
    444 
    445 	if (db->hsize != 0) {
    446 		/* XXX feeble attempt to catch bad references. */
    447 		db->hsize = 0;
    448 
    449 		kmem_free(db, db->totlen);
    450 	}
    451 }
    452 
    453 /*
    454  * bsd_comp_alloc()
    455  */
    456 static void *
    457 bsd_comp_alloc(uchar_t *options, int opt_len)
    458 {
    459 	return (bsd_alloc(options, opt_len, 0));
    460 }
    461 
    462 /*
    463  * bsd_decomp_alloc()
    464  */
    465 static void *
    466 bsd_decomp_alloc(uchar_t *options, int opt_len)
    467 {
    468 	return (bsd_alloc(options, opt_len, 1));
    469 }
    470 
    471 /*
    472  * bsd_init()
    473  *
    474  * Initialize the database.
    475  */
    476 static int
    477 bsd_init(struct bsd_db *db, uchar_t *options, int opt_len, int unit,
    478 	int hdrlen, int mru, int debug, int decomp)
    479 {
    480 	int	i;
    481 
    482 	if (db->hsize == 0 || opt_len < CILEN_BSD_COMPRESS ||
    483 	    options[0] != CI_BSD_COMPRESS ||
    484 	    options[1] != CILEN_BSD_COMPRESS ||
    485 	    BSD_VERSION(options[2]) != BSD_CURRENT_VERSION ||
    486 	    BSD_NBITS(options[2]) != db->maxbits ||
    487 	    decomp && db->lens == NULL) {
    488 
    489 		return (0);
    490 	}
    491 
    492 	if (decomp) {
    493 		i = LAST + 1;
    494 
    495 		while (i != 0) {
    496 			db->lens[--i] = 1;
    497 		}
    498 	}
    499 
    500 	i = db->hsize;
    501 
    502 	while (i != 0) {
    503 		db->dict[--i].codem1 = BADCODEM1;
    504 		db->dict[i].cptr = 0;
    505 	}
    506 
    507 	db->unit = unit;
    508 	db->hdrlen = hdrlen;
    509 	db->mru = (ushort_t)mru;
    510 
    511 	if (debug) {
    512 		db->flags |= DS_DEBUG;
    513 	}
    514 
    515 	bsd_reset(db);
    516 
    517 	db->flags |= DS_INITDONE;
    518 
    519 	return (1);
    520 }
    521 
    522 /*
    523  * bsd_comp_init()
    524  */
    525 static int
    526 bsd_comp_init(void *state, uchar_t *options, int opt_len, int unit, int hdrlen,
    527 	int debug)
    528 {
    529 	return (bsd_init((struct bsd_db *)state, options, opt_len,
    530 	    unit, hdrlen, 0, debug, 0));
    531 }
    532 
    533 /*
    534  * bsd_decomp_init()
    535  */
    536 static int
    537 bsd_decomp_init(void *state, uchar_t *options, int opt_len, int unit,
    538 	int hdrlen, int mru, int debug)
    539 {
    540 	return (bsd_init((struct bsd_db *)state, options, opt_len,
    541 	    unit, hdrlen, mru, debug, 1));
    542 }
    543 
    544 
    545 /*
    546  * bsd_compress()
    547  *
    548  * compress a packet
    549  *	One change from the BSD compress command is that when the
    550  *	code size expands, we do not output a bunch of padding.
    551  *
    552  * N.B. at present, we ignore the hdrlen specified in the comp_init call.
    553  */
    554 static int			/* new slen */
    555 bsd_compress(void *state, mblk_t **mretp, mblk_t *mp, int slen,	int maxolen)
    556 {
    557 	struct bsd_db	*db = (struct bsd_db *)state;
    558 	int		hshift = db->hshift;
    559 	uint_t		max_ent = db->max_ent;
    560 	uint_t		n_bits = db->n_bits;
    561 	uint_t		bitno = 32;
    562 	uint32_t	accm = 0;
    563 	uint32_t	fcode;
    564 	struct bsd_dict	*dictp;
    565 	uchar_t		c;
    566 	int		hval;
    567 	int		disp;
    568 	int		ent;
    569 	int		ilen = slen - (PPP_HDRLEN-1);
    570 	mblk_t		*mret;
    571 	uchar_t		*rptr, *rmax;
    572 	uchar_t		*wptr;
    573 	uchar_t		*cp_end;
    574 	int		olen;
    575 	mblk_t		*m;
    576 	mblk_t		**mnp;
    577 #if defined(lint) || defined(_lint)
    578 	uchar_t		hdlcaddr, hdlcctl;
    579 #else
    580 	int		hdlcaddr, hdlcctl;
    581 #endif
    582 
    583 	ASSERT(db->flags & DS_INITDONE);
    584 
    585 #define	PUTBYTE(v) {						\
    586 	if (wptr) {						\
    587 		*wptr++ = (v);					\
    588 		if (wptr >= cp_end) {				\
    589 			m->b_wptr = wptr;			\
    590 			m = m->b_cont;				\
    591 			if (m) {				\
    592 				wptr = m->b_wptr;		\
    593 				cp_end = m->b_datap->db_lim;	\
    594 			} else {				\
    595 				wptr = NULL;			\
    596 			}					\
    597 		}						\
    598 	}							\
    599 	++olen;							\
    600 }
    601 
    602 #define	OUTPUT(ent) {						\
    603 	bitno -= n_bits;					\
    604 	accm |= ((ent) << bitno);				\
    605 	do {							\
    606 		PUTBYTE(accm >> 24);				\
    607 		accm <<= 8;					\
    608 		bitno += 8;					\
    609 	} while (bitno <= 24);					\
    610 }
    611 
    612 #define	ADJRPTR() {						\
    613 	if (rptr != NULL) {					\
    614 		while (rptr >= rmax) {				\
    615 			if ((mp = mp->b_cont) == NULL) {	\
    616 				rptr = NULL;			\
    617 				break;				\
    618 			}					\
    619 			rptr = mp->b_rptr;			\
    620 			rmax = mp->b_wptr;			\
    621 		}						\
    622 	}							\
    623 }
    624 
    625 #define	GETBYTE(v) {						\
    626 	if (rptr != NULL) {					\
    627 		(v) = *rptr++;					\
    628 	}							\
    629 }
    630 
    631 	if (db->hsize == 0)
    632 		return (-1);
    633 
    634 	/*
    635 	 * First get the protocol and check that we're
    636 	 * interested in this packet.
    637 	 */
    638 	*mretp = NULL;
    639 	rptr = mp->b_rptr;
    640 	rmax = mp->b_wptr;
    641 
    642 	/* We CANNOT do a pullup here; it's not our buffer to toy with. */
    643 	ADJRPTR();
    644 	GETBYTE(hdlcaddr);
    645 	ADJRPTR();
    646 	GETBYTE(hdlcctl);
    647 	ADJRPTR();
    648 	GETBYTE(ent);
    649 	ADJRPTR();
    650 
    651 	/*
    652 	 * Per RFC 1977, the protocol field must be compressed using a
    653 	 * PFC-like procedure.  Also, all protocols between 0000-3FFF
    654 	 * except the two compression protocols must be LZ compressed.
    655 	 */
    656 	if (ent == 0) {
    657 		GETBYTE(ent);
    658 		if (rptr == NULL || ent == PPP_COMP || ent == PPP_COMPFRAG)
    659 			return (0);
    660 	} else {
    661 		if (ent > 0x3F)
    662 			return (0);
    663 		ilen++;
    664 	}
    665 
    666 	/*
    667 	 * Don't generate compressed packets that are larger than the
    668 	 * source (uncompressed) packet.
    669 	 */
    670 	if (maxolen > slen) {
    671 		maxolen = slen;
    672 	}
    673 	if (maxolen < 6)
    674 		maxolen = 6;
    675 
    676 	/*
    677 	 * Allocate enough message blocks to give maxolen total space
    678 	 */
    679 	mnp = &mret;
    680 	for (olen = maxolen; olen > 0; ) {
    681 
    682 		m = allocb((olen < 4096? olen: 4096), BPRI_MED);
    683 
    684 		*mnp = m;
    685 		if (m == NULL) {
    686 			if (mnp == &mret)
    687 				return (0);
    688 			/* We allocated some; hope for the best. */
    689 			break;
    690 		}
    691 
    692 		mnp = &m->b_cont;
    693 		olen -= m->b_datap->db_lim - m->b_wptr;
    694 	}
    695 
    696 	*mnp = NULL;
    697 
    698 	m = mret;
    699 	wptr = m->b_wptr;
    700 	cp_end = m->b_datap->db_lim;
    701 
    702 	olen = 0;
    703 
    704 	/*
    705 	 * Copy the PPP header over, changing the protocol,
    706 	 * and install the 2-byte sequence number
    707 	 */
    708 	*wptr++ = hdlcaddr;
    709 	*wptr++ = hdlcctl;
    710 	*wptr++ = PPP_COMP>>8;		/* change the protocol */
    711 	*wptr++ = PPP_COMP;
    712 	*wptr++ = db->seqno >> 8;
    713 	*wptr++ = db->seqno;
    714 
    715 #ifdef DEBUG
    716 	/*
    717 	 * If testing output, just garbling the sequence here does the
    718 	 * trick.
    719 	 */
    720 	if ((db->flags & DS_TESTOUT) && (db->seqno % 100) == 50)
    721 		wptr[-1] ^= 0xAA;
    722 #endif
    723 
    724 	++db->seqno;
    725 
    726 	for (;;) {
    727 		ADJRPTR();
    728 		if (rptr == NULL)
    729 			break;
    730 
    731 		GETBYTE(c);
    732 
    733 		fcode = BSD_KEY(ent, c);
    734 		hval = BSD_HASH(ent, c, hshift);
    735 
    736 		dictp = &db->dict[hval];
    737 
    738 		/*
    739 		 * Validate and then check the entry
    740 		 */
    741 		if (dictp->codem1 >= max_ent) {
    742 			goto nomatch;
    743 		}
    744 
    745 		if (dictp->f.fcode == fcode) {
    746 			ent = dictp->codem1+1;
    747 
    748 			/*
    749 			 * found (prefix,suffix)
    750 			 */
    751 			continue;
    752 		}
    753 
    754 		/*
    755 		 * continue probing until a match or invalid entry
    756 		 */
    757 		disp = (hval == 0) ? 1 : hval;
    758 
    759 		do {
    760 			hval += disp;
    761 			if (hval >= db->hsize) {
    762 				hval -= db->hsize;
    763 				if (hval >= db->hsize) {
    764 					if (db->flags & DS_DEBUG) {
    765 						cmn_err(CE_CONT,
    766 						    "bsd_comp%d: internal "
    767 						    "error\n",
    768 						    db->unit);
    769 					}
    770 					/* Caller will free it all */
    771 					return (-1);
    772 				}
    773 			}
    774 
    775 			dictp = &db->dict[hval];
    776 
    777 			if (dictp->codem1 >= max_ent) {
    778 				goto nomatch;
    779 			}
    780 		} while (dictp->f.fcode != fcode);
    781 
    782 		/*
    783 		 * finally found (prefix,suffix)
    784 		 */
    785 		ent = dictp->codem1 + 1;
    786 
    787 		continue;
    788 
    789 nomatch:
    790 		/*
    791 		 * output the prefix
    792 		 */
    793 		OUTPUT(ent);
    794 
    795 		/*
    796 		 * code -> hashtable
    797 		 */
    798 		if (max_ent < db->maxmaxcode) {
    799 			struct bsd_dict *dictp2;
    800 
    801 			/*
    802 			 * expand code size if needed
    803 			 */
    804 			if (max_ent >= MAXCODE(n_bits)) {
    805 				db->n_bits = ++n_bits;
    806 			}
    807 
    808 			/*
    809 			 * Invalidate old hash table entry using
    810 			 * this code, and then take it over.
    811 			 */
    812 			dictp2 = &db->dict[max_ent+1];
    813 
    814 			if (db->dict[dictp2->cptr].codem1 == max_ent) {
    815 				db->dict[dictp2->cptr].codem1 = BADCODEM1;
    816 			}
    817 
    818 			dictp2->cptr = (ushort_t)hval;
    819 			dictp->codem1 = max_ent;
    820 			dictp->f.fcode = fcode;
    821 
    822 			db->max_ent = ++max_ent;
    823 		}
    824 
    825 		ent = c;
    826 	}
    827 
    828 	/*
    829 	 * output the last code
    830 	 */
    831 	OUTPUT(ent);
    832 
    833 	olen += (32-bitno+7)/8;	/* count complete bytes */
    834 
    835 	db->bytes_out += olen;
    836 	db->in_count += ilen;
    837 
    838 	if (bsd_check(db)) {
    839 		OUTPUT(CLEAR);		/* do not count the CLEAR */
    840 	}
    841 
    842 	/*
    843 	 * Pad dribble bits of last code with ones.
    844 	 * Do not emit a completely useless byte of ones.
    845 	 */
    846 	if (bitno != 32) {
    847 		PUTBYTE((accm | (0xff << (bitno - 8))) >> 24);
    848 	}
    849 
    850 	/*
    851 	 * Increase code size if we would have without the packet
    852 	 * boundary and as the decompressor will.
    853 	 */
    854 	if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode) {
    855 		db->n_bits++;
    856 	}
    857 
    858 	db->uncomp_bytes += ilen;
    859 	++db->uncomp_count;
    860 
    861 	if (wptr == NULL || olen + PPP_HDRLEN + BSD_OVHD >= maxolen) {
    862 		/*
    863 		 * throw away the compressed stuff if it is longer
    864 		 * than uncompressed
    865 		 */
    866 		freemsg(mret);
    867 
    868 		mret = NULL;
    869 
    870 		++db->incomp_count;
    871 		db->incomp_bytes += ilen;
    872 
    873 	} else {
    874 
    875 		m->b_wptr = wptr;
    876 		if (m->b_cont) {
    877 			freemsg(m->b_cont);
    878 			m->b_cont = NULL;
    879 		}
    880 
    881 		++db->comp_count;
    882 		db->comp_bytes += olen + BSD_OVHD;
    883 	}
    884 
    885 	*mretp = mret;
    886 
    887 	return (olen + PPP_HDRLEN + BSD_OVHD);
    888 #undef OUTPUT
    889 #undef PUTBYTE
    890 }
    891 
    892 
    893 /*
    894  * bsd_incomp()
    895  *
    896  * Update the "BSD Compress" dictionary on the receiver for
    897  * incompressible data by pretending to compress the incoming data.
    898  */
    899 static int
    900 bsd_incomp(void *state, mblk_t *mp)
    901 {
    902 	struct bsd_db	*db = (struct bsd_db *)state;
    903 	uint_t		hshift = db->hshift;
    904 	uint_t		max_ent = db->max_ent;
    905 	uint_t		n_bits = db->n_bits;
    906 	struct bsd_dict	*dictp;
    907 	uint32_t	fcode;
    908 	uchar_t		c;
    909 	long		hval;
    910 	long		disp;
    911 	int		slen;
    912 	int		ilen;
    913 	uint_t		bitno = 7;
    914 	uchar_t		*rptr, *rmax;
    915 	uint_t		ent;
    916 
    917 	ASSERT(db->flags & DS_INITDONE);
    918 
    919 	if (db->hsize == 0)
    920 		return (-1);
    921 
    922 	rptr = mp->b_rptr;
    923 	rmax = mp->b_wptr;
    924 	ADJRPTR();
    925 	GETBYTE(ent);	/* address */
    926 	ADJRPTR();
    927 	GETBYTE(ent);	/* control */
    928 	ADJRPTR();
    929 	GETBYTE(ent);	/* protocol high */
    930 	ADJRPTR();
    931 
    932 	/*
    933 	 * Per RFC 1977, the protocol field must be compressed using a
    934 	 * PFC-like procedure.  Also, all protocols between 0000-3FFF
    935 	 * except the two compression protocols must be LZ compressed.
    936 	 */
    937 	ilen = 1;			/* count the protocol as 1 byte */
    938 	if (ent == 0) {
    939 		GETBYTE(ent);
    940 		if (rptr == NULL || ent == PPP_COMP || ent == PPP_COMPFRAG)
    941 			return (0);
    942 	} else {
    943 		if (ent > 0x3F)
    944 			return (0);
    945 		ilen++;
    946 	}
    947 
    948 	db->seqno++;
    949 
    950 	for (;;) {
    951 
    952 		slen = mp->b_wptr - rptr;
    953 		if (slen <= 0) {
    954 			mp = mp->b_cont;
    955 			if (!mp) {
    956 				break;
    957 			}
    958 
    959 			rptr = mp->b_rptr;
    960 			continue;	/* skip zero-length buffers */
    961 		}
    962 
    963 		ilen += slen;
    964 
    965 		do {
    966 			c = *rptr++;
    967 
    968 			fcode = BSD_KEY(ent, c);
    969 			hval = BSD_HASH(ent, c, hshift);
    970 
    971 			dictp = &db->dict[hval];
    972 
    973 			/*
    974 			 * validate and then check the entry
    975 			 */
    976 			if (dictp->codem1 >= max_ent) {
    977 				goto nomatch;
    978 			}
    979 
    980 			if (dictp->f.fcode == fcode) {
    981 				ent = dictp->codem1 + 1;
    982 				continue;   /* found (prefix,suffix) */
    983 			}
    984 
    985 			/*
    986 			 * continue probing until a match or invalid entry
    987 			 */
    988 			disp = (hval == 0) ? 1 : hval;
    989 			do {
    990 				hval += disp;
    991 				if (hval >= db->hsize) {
    992 					hval -= db->hsize;
    993 					if (hval >= db->hsize) {
    994 						if (db->flags & DS_DEBUG) {
    995 							cmn_err(CE_CONT,
    996 							    "bsd_incomp%d: "
    997 							    "internal error\n",
    998 							    db->unit);
    999 						}
   1000 						return (-1);
   1001 					}
   1002 				}
   1003 
   1004 				dictp = &db->dict[hval];
   1005 				if (dictp->codem1 >= max_ent) {
   1006 					goto nomatch;
   1007 				}
   1008 			} while (dictp->f.fcode != fcode);
   1009 
   1010 			ent = dictp->codem1+1;
   1011 			continue;	/* finally found (prefix,suffix) */
   1012 
   1013 nomatch:				/* output (count) the prefix */
   1014 			bitno += n_bits;
   1015 
   1016 			/*
   1017 			 * code -> hashtable
   1018 			 */
   1019 			if (max_ent < db->maxmaxcode) {
   1020 				struct bsd_dict *dictp2;
   1021 
   1022 				/*
   1023 				 * expand code size if needed
   1024 				 */
   1025 				if (max_ent >= MAXCODE(n_bits)) {
   1026 					db->n_bits = ++n_bits;
   1027 				}
   1028 
   1029 				/*
   1030 				 * Invalidate previous hash table entry
   1031 				 * assigned this code, and then take it over.
   1032 				 */
   1033 				dictp2 = &db->dict[max_ent+1];
   1034 				if (db->dict[dictp2->cptr].codem1 == max_ent) {
   1035 					db->dict[dictp2->cptr].codem1 =
   1036 					    BADCODEM1;
   1037 				}
   1038 
   1039 				dictp2->cptr = (ushort_t)hval;
   1040 				dictp->codem1 = max_ent;
   1041 				dictp->f.fcode = fcode;
   1042 
   1043 				db->max_ent = ++max_ent;
   1044 				db->lens[max_ent] = db->lens[ent]+1;
   1045 			}
   1046 
   1047 			ent = c;
   1048 		} while (--slen != 0);
   1049 	}
   1050 
   1051 	bitno += n_bits;		/* output (count) the last code */
   1052 
   1053 	db->bytes_out += bitno/8;
   1054 	db->in_count += ilen;
   1055 
   1056 	(void) bsd_check(db);
   1057 
   1058 	++db->incomp_count;
   1059 	db->incomp_bytes += ilen;
   1060 	++db->uncomp_count;
   1061 	db->uncomp_bytes += ilen;
   1062 
   1063 	/*
   1064 	 * Increase code size if we would have without the packet
   1065 	 * boundary and as the decompressor will.
   1066 	 */
   1067 	if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode) {
   1068 		db->n_bits++;
   1069 	}
   1070 	return (0);
   1071 #undef ADJRPTR
   1072 }
   1073 
   1074 
   1075 /*
   1076  * bsd_decompress()
   1077  *
   1078  * Decompress "BSD Compress"
   1079  *
   1080  * Because of patent problems, we return DECOMP_ERROR for errors
   1081  * found by inspecting the input data and for system problems, but
   1082  * DECOMP_FATALERROR for any errors which could possibly be said to
   1083  * be being detected "after" decompression.  For DECOMP_ERROR,
   1084  * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
   1085  * infringing a patent of Motorola's if we do, so we take CCP down
   1086  * instead.
   1087  *
   1088  * Given that the frame has the correct sequence number and a good FCS,
   1089  * errors such as invalid codes in the input most likely indicate a
   1090  * bug, so we return DECOMP_FATALERROR for them in order to turn off
   1091  * compression, even though they are detected by inspecting the input.
   1092  */
   1093 static int
   1094 bsd_decompress(void *state, mblk_t **dmpp)
   1095 {
   1096 	mblk_t		*cmsg = *dmpp, *mnext;
   1097 	struct bsd_db	*db = (struct bsd_db *)state;
   1098 	uint_t		max_ent = db->max_ent;
   1099 	uint32_t	accm = 0;
   1100 	uint_t		bitno = 32;		/* 1st valid bit in accm */
   1101 	uint_t		n_bits = db->n_bits;
   1102 	uint_t		tgtbitno = 32 - n_bits;	/* bitno when we have a code */
   1103 	struct bsd_dict	*dictp;
   1104 	int		explen;
   1105 	int		seq;
   1106 	uint_t		incode;
   1107 	uint_t		oldcode;
   1108 	uint_t		finchar = 0, ofinchar;
   1109 	uchar_t		*p;
   1110 	uchar_t		*rptr, *rmax;
   1111 	uchar_t		*wptr, *prepos;
   1112 	mblk_t		*dmsg;
   1113 	mblk_t		*mret;
   1114 	int		ilen;
   1115 	int		dlen;
   1116 	int		codelen;
   1117 	int		extra;
   1118 	int		decode_proto;
   1119 	int		blockctr;
   1120 	int		outlen;
   1121 #if defined(lint) || defined(_lint)
   1122 	uchar_t		adrs, ctrl;
   1123 #else
   1124 	int		adrs, ctrl;
   1125 #endif
   1126 
   1127 	ASSERT(db->flags & DS_INITDONE);
   1128 
   1129 	/* Note: spppcomp already did a pullup to fix the first buffer. */
   1130 	*dmpp = NULL;
   1131 	rptr = cmsg->b_rptr;
   1132 	rmax = cmsg->b_wptr;
   1133 	ilen = 0;
   1134 
   1135 	/*
   1136 	 * Note that we free as we go.  If we fail to decompress,
   1137 	 * there's nothing good that the caller can do.
   1138 	 */
   1139 #define	ADJRPTR()					\
   1140 	while (rptr >= rmax) {				\
   1141 		mnext = cmsg->b_cont;			\
   1142 		freeb(cmsg);				\
   1143 		if ((cmsg = mnext) == NULL) {		\
   1144 			rptr = NULL;			\
   1145 			break;				\
   1146 		}					\
   1147 		rptr = cmsg->b_rptr;			\
   1148 		rmax = cmsg->b_wptr;			\
   1149 		ilen += rmax-rptr;			\
   1150 	}
   1151 
   1152 	/*
   1153 	 * Save the address/control from the PPP header
   1154 	 * and then get the sequence number.
   1155 	 */
   1156 	adrs = rptr[0];
   1157 	ctrl = rptr[1];
   1158 	rptr += 4;
   1159 	ADJRPTR();
   1160 	seq = rptr == NULL ? 0 : (*rptr++ << 8);
   1161 	ADJRPTR();
   1162 	if (rptr == NULL) {
   1163 		if (db->flags & DS_DEBUG) {
   1164 			cmn_err(CE_CONT, "bsd_decomp%d: bad buffer\n",
   1165 			    db->unit);
   1166 		}
   1167 		return (DECOMP_ERROR);
   1168 	}
   1169 	seq |= *rptr++;
   1170 
   1171 #ifdef DEBUG
   1172 	/*
   1173 	 * If testing input, just pretending the sequence is bad here
   1174 	 * does the trick.
   1175 	 */
   1176 	if ((db->flags & DS_TESTIN) && (db->seqno % 300) == 101)
   1177 		seq ^= 0x55;
   1178 #endif
   1179 
   1180 	/*
   1181 	 * Check the sequence number and give up if it is not what we expect.
   1182 	 */
   1183 	if (db->hsize == 0 || seq != db->seqno++) {
   1184 		freemsg(cmsg);
   1185 		if (db->flags & DS_DEBUG) {
   1186 			cmn_err(CE_CONT, "bsd_decomp%d: bad sequence # %d, "
   1187 			    "expected %d\n", db->unit, seq, db->seqno - 1);
   1188 		}
   1189 
   1190 		return (DECOMP_ERROR);
   1191 	}
   1192 
   1193 	/*
   1194 	 * Allocate one message block to start with.
   1195 	 */
   1196 	if ((dmsg = allocb(DECOMP_CHUNK + db->hdrlen, BPRI_MED)) == NULL) {
   1197 		freemsg(cmsg);
   1198 		if (db->flags & DS_DEBUG) {
   1199 			cmn_err(CE_CONT,
   1200 			    "bsd_decomp%d: can't allocate first buffer\n",
   1201 			    db->unit);
   1202 		}
   1203 		return (DECOMP_ERROR);
   1204 	}
   1205 
   1206 	/*
   1207 	 * Avoid an error that might cause us to allocate all available memory.
   1208 	 * Enforce a maximum number of blocks to allocate for message. We add
   1209 	 * a fudge factor of 5 extra blocks, in order to avoid unnecessary
   1210 	 * DECOMP_ERROR when the code size is small (9).
   1211 	 */
   1212 	blockctr = ((db->mru + 32 + DECOMP_CHUNK - 1) / DECOMP_CHUNK) + 5;
   1213 
   1214 	mret = dmsg;
   1215 	dmsg->b_wptr += db->hdrlen;
   1216 	dmsg->b_rptr = wptr = dmsg->b_wptr;
   1217 
   1218 	/*
   1219 	 * Insert PPP header.  This shouldn't be needed!
   1220 	 */
   1221 	*wptr++ = adrs;
   1222 	*wptr++ = ctrl;
   1223 	prepos = wptr;
   1224 	*wptr++ = 0;
   1225 	dmsg->b_wptr = wptr;
   1226 
   1227 	explen = dmsg->b_datap->db_lim - wptr;
   1228 	oldcode = CLEAR;
   1229 	ilen = rmax-rptr;
   1230 
   1231 	outlen = 0;
   1232 	decode_proto = 1;
   1233 	for (;;) {
   1234 		ADJRPTR();
   1235 		if (rptr == NULL)
   1236 			break;
   1237 
   1238 		/*
   1239 		 * Accumulate bytes until we have a complete code.
   1240 		 * Then get the next code, relying on the 32-bit,
   1241 		 * unsigned accm to mask the result.
   1242 		 */
   1243 		bitno -= 8;
   1244 
   1245 		accm |= *rptr++ << bitno;
   1246 
   1247 		if (tgtbitno < bitno) {
   1248 			continue;
   1249 		}
   1250 
   1251 		incode = accm >> tgtbitno;
   1252 		accm <<= n_bits;
   1253 		bitno += n_bits;
   1254 
   1255 		if (incode == CLEAR) {
   1256 
   1257 			/*
   1258 			 * The dictionary must only be cleared at
   1259 			 * the end of a packet.  But there could be an
   1260 			 * empty message block at the end.
   1261 			 */
   1262 			ADJRPTR();
   1263 			if (rptr != NULL) {
   1264 				freemsg(mret);
   1265 				freemsg(cmsg);
   1266 				if (db->flags & DS_DEBUG) {
   1267 					cmn_err(CE_CONT,
   1268 					    "bsd_decomp%d: bad CLEAR\n",
   1269 					    db->unit);
   1270 				}
   1271 
   1272 				return (DECOMP_FATALERROR);
   1273 			}
   1274 
   1275 			bsd_clear(db);
   1276 			/* Have to keep cleared state variables! */
   1277 			outlen += wptr-dmsg->b_wptr;
   1278 			dmsg->b_wptr = wptr;
   1279 			db->comp_bytes += ilen;
   1280 			ilen = 0;
   1281 			break;
   1282 		}
   1283 
   1284 		/*
   1285 		 * Special case for KwKwK string
   1286 		 */
   1287 		ofinchar = finchar;
   1288 		if (incode > max_ent) {
   1289 			if (incode > max_ent + 2 ||
   1290 			    incode > db->maxmaxcode ||
   1291 			    oldcode == CLEAR) {
   1292 				freemsg(cmsg);
   1293 				freemsg(mret);
   1294 
   1295 				/* probably a bug if we get here */
   1296 				if (db->flags & DS_DEBUG) {
   1297 					cmn_err(CE_CONT,
   1298 					    "bsd_decomp%d: bad code 0x%x "
   1299 					    "oldcode=0x%x ", db->unit, incode,
   1300 					    oldcode);
   1301 				}
   1302 
   1303 				return (DECOMP_FATALERROR);
   1304 			}
   1305 			finchar = oldcode;
   1306 			extra = 1;
   1307 		} else {
   1308 			finchar = incode;
   1309 			extra = 0;
   1310 		}
   1311 		codelen = db->lens[finchar];
   1312 
   1313 		/*
   1314 		 * Decode this code and install it in the decompressed buffer
   1315 		 */
   1316 		explen -= codelen + extra;
   1317 		if (explen < 0) {
   1318 			/*
   1319 			 * Allocate another message block
   1320 			 */
   1321 			dlen = wptr - dmsg->b_wptr;
   1322 			outlen += dlen;
   1323 			db->in_count += dlen;
   1324 			dmsg->b_wptr = wptr;
   1325 			dlen = codelen + extra;
   1326 
   1327 			if (dlen < DECOMP_CHUNK) {
   1328 				dlen = DECOMP_CHUNK;
   1329 			}
   1330 
   1331 			if ((--blockctr < 0) ||
   1332 			    (dmsg->b_cont = allocb(dlen, BPRI_MED)) == NULL) {
   1333 				freemsg(cmsg);
   1334 				freemsg(mret);
   1335 				if (db->flags & DS_DEBUG) {
   1336 					cmn_err(CE_CONT,
   1337 					    "bsd_decomp%d: %s output "
   1338 					    "buffers; outlen %d+%d\n",
   1339 					    db->unit,
   1340 					    (blockctr < 0 ? "too many" :
   1341 					    "can't allocate"),
   1342 					    outlen, dlen);
   1343 				}
   1344 				return (DECOMP_ERROR);
   1345 			}
   1346 
   1347 			dmsg = dmsg->b_cont;
   1348 			wptr = dmsg->b_wptr;
   1349 			explen = dmsg->b_datap->db_lim - wptr - codelen -
   1350 			    extra;
   1351 		}
   1352 
   1353 		p = (wptr += codelen);
   1354 
   1355 		while (finchar > LAST) {
   1356 			dictp = &db->dict[db->dict[finchar].cptr];
   1357 			*--p = dictp->f.hs.suffix;
   1358 			finchar = dictp->f.hs.prefix;
   1359 		}
   1360 
   1361 		*--p = finchar;
   1362 
   1363 		if (decode_proto) {
   1364 			decode_proto = 0;
   1365 			/* Wow, is *this* ugly! */
   1366 			if (!(finchar & 1)) {
   1367 				if (p == prepos+1) {
   1368 					bcopy(p, prepos, wptr-p);
   1369 					wptr--;
   1370 					explen++;
   1371 					db->in_count++;
   1372 				} else {
   1373 					/* This is safe, but doesn't look it */
   1374 					*prepos = *p++;
   1375 					dmsg->b_rptr = p;
   1376 				}
   1377 			}
   1378 		}
   1379 
   1380 		if (extra) {	/* the KwKwK case again */
   1381 			*wptr++ = ofinchar;
   1382 		}
   1383 
   1384 		/*
   1385 		 * If not first code in a packet, and
   1386 		 * if not out of code space, then allocate a new code.
   1387 		 *
   1388 		 * Keep the hash table correct so it can be used
   1389 		 * with uncompressed packets.
   1390 		 */
   1391 		if (oldcode != CLEAR && max_ent < db->maxmaxcode) {
   1392 			struct bsd_dict	*dictp2;
   1393 			uint32_t	fcode;
   1394 			int		hval;
   1395 			int		disp;
   1396 
   1397 			fcode = BSD_KEY(oldcode, finchar);
   1398 			hval = BSD_HASH(oldcode, finchar, db->hshift);
   1399 
   1400 			dictp = &db->dict[hval];
   1401 
   1402 			/*
   1403 			 * look for a free hash table entry
   1404 			 */
   1405 			if (dictp->codem1 < max_ent) {
   1406 				disp = (hval == 0) ? 1 : hval;
   1407 
   1408 				do {
   1409 					hval += disp;
   1410 
   1411 					if (hval >= db->hsize) {
   1412 						hval -= db->hsize;
   1413 						if (hval >= db->hsize) {
   1414 							freemsg(cmsg);
   1415 							freemsg(mret);
   1416 							if (db->flags &
   1417 							    DS_DEBUG) {
   1418 			cmn_err(CE_CONT, "bsd_decomp%d: internal error\n",
   1419 			    db->unit);
   1420 							}
   1421 							return
   1422 							    (DECOMP_FATALERROR);
   1423 						}
   1424 					}
   1425 
   1426 					dictp = &db->dict[hval];
   1427 
   1428 				} while (dictp->codem1 < max_ent);
   1429 			}
   1430 
   1431 			/*
   1432 			 * Invalidate previous hash table entry
   1433 			 * assigned this code, and then take it over
   1434 			 */
   1435 			dictp2 = &db->dict[max_ent+1];
   1436 
   1437 			if (db->dict[dictp2->cptr].codem1 == max_ent) {
   1438 				db->dict[dictp2->cptr].codem1 = BADCODEM1;
   1439 			}
   1440 
   1441 			dictp2->cptr = (ushort_t)hval;
   1442 			dictp->codem1 = max_ent;
   1443 			dictp->f.fcode = fcode;
   1444 
   1445 			db->max_ent = ++max_ent;
   1446 			db->lens[max_ent] = db->lens[oldcode]+1;
   1447 
   1448 			/*
   1449 			 * Expand code size if needed
   1450 			 */
   1451 			if (max_ent >= MAXCODE(n_bits) &&
   1452 			    max_ent < db->maxmaxcode) {
   1453 
   1454 				db->n_bits = ++n_bits;
   1455 				tgtbitno = 32-n_bits;
   1456 			}
   1457 		}
   1458 
   1459 		oldcode = incode;
   1460 	}
   1461 
   1462 	dlen = wptr-dmsg->b_wptr;
   1463 	outlen += dlen;
   1464 	db->in_count += dlen;
   1465 	dmsg->b_wptr = wptr;
   1466 	db->bytes_out += ilen;
   1467 
   1468 	/*
   1469 	 * Keep the checkpoint right so that incompressible packets
   1470 	 * clear the dictionary at the right times.
   1471 	 */
   1472 	if (bsd_check(db) && (db->flags & DS_DEBUG)) {
   1473 		cmn_err(CE_CONT,
   1474 		    "bsd_decomp%d: peer should have cleared dictionary\n",
   1475 		    db->unit);
   1476 	}
   1477 
   1478 	++db->comp_count;
   1479 	db->comp_bytes += ilen + BSD_OVHD;
   1480 	++db->uncomp_count;
   1481 	db->uncomp_bytes += outlen;
   1482 
   1483 	*dmpp = mret;
   1484 
   1485 	return (DECOMP_OK);
   1486 }
   1487 
   1488 /* ARGSUSED */
   1489 static int
   1490 bsd_set_effort(void *xarg, void *rarg, int effortlevel)
   1491 {
   1492 #ifdef DEBUG
   1493 	struct bsd_db *xdb = (struct bsd_db *)xarg;
   1494 	struct bsd_db *rdb = (struct bsd_db *)rarg;
   1495 
   1496 	if (effortlevel == 42 || effortlevel == 2112) {
   1497 		/* corrupt received data. */
   1498 		if (rdb != NULL) {
   1499 			rdb->flags |= DS_TESTIN;
   1500 			cmn_err(CE_CONT, "bsd-comp: enabled input testing.");
   1501 		}
   1502 		if (effortlevel != 2112)
   1503 			return (0);
   1504 	}
   1505 	if (effortlevel == 2001 || effortlevel == 2112) {
   1506 		/* corrupt transmitted data. */
   1507 		if (xdb != NULL) {
   1508 			xdb->flags |= DS_TESTOUT;
   1509 			cmn_err(CE_CONT, "bsd-comp: enabled output testing.");
   1510 		}
   1511 		return (0);
   1512 	}
   1513 #endif
   1514 	return (0);
   1515 }
   1516 #endif /* DO_BSD_COMPRESS */
   1517