2 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
5 * Because this code is derived from the 4.3BSD compress source:
7 * Copyright (c) 1985, 1986 The Regents of the University of California.
10 * This code is derived from software contributed to Berkeley by
11 * James A. Woods, derived from original work by Spencer Thomas
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
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.
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
43 #pragma ident "%Z%%M% %I% %E% SMI"
46 * This version is for use with STREAMS in Solaris 2
48 * $Id: bsd-comp.c,v 1.20 1996/08/28 06:31:57 paulus Exp $
51 #include <sys/param.h>
52 #include <sys/types.h>
54 #include <sys/stream.h>
55 #include <sys/cmn_err.h>
57 #include <sys/sunddi.h>
58 #include <sys/byteorder.h>
59 #include <net/ppp_defs.h>
61 /* Defined for platform-neutral include file */
62 #define PACKETPTR mblk_t *
63 #include <net/ppp-comp.h>
66 #define BSD_LITTLE_ENDIAN
72 * PPP "BSD compress" compression
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:
79 * When the code size expands, a block of junk is not emitted by
80 * the compressor and not expected by the decompressor.
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.
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.
95 * A dictionary for doing BSD compress.
98 int totlen
; /* length of this structure */
99 uint_t hsize
; /* size of the hash table */
101 uchar_t hshift
; /* used in hash function */
102 uchar_t n_bits
; /* current bits/code */
105 ushort_t seqno
; /* sequence number of next packet */
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 */
123 union { /* hash value */
126 #ifdef BSD_LITTLE_ENDIAN
127 ushort_t prefix
; /* preceding code */
128 uchar_t suffix
; /* last character of new code */
132 uchar_t suffix
; /* last character of new code */
133 ushort_t prefix
; /* preceding code */
137 ushort_t codem1
; /* output of hash table -1 */
138 ushort_t cptr
; /* map code to hash entry */
142 #define BSD_OVHD 2 /* BSD compress overhead/packet */
143 #define BSD_INIT_BITS BSD_MIN_BITS
145 /* db->flags values */
146 #define DS_DEBUG 0x01
147 #define DS_TESTIN 0x02
148 #define DS_TESTOUT 0x04
149 #define DS_INITDONE 0x08
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
);
167 * Procedures exported to ppp_comp.c.
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 */
188 * the next two codes should not be changed lightly, as they must not
189 * lie within the contiguous general code space.
191 #define CLEAR 256 /* table clear output code */
192 #define FIRST 257 /* first free entry */
195 #define MAXCODE(b) ((1 << (b)) - 1)
196 #define BADCODEM1 MAXCODE(BSD_MAX_BITS)
198 #define BSD_HASH(prefix, suffix, hshift) \
199 ((((uint32_t)(suffix)) << (hshift)) ^ (uint32_t)(prefix))
201 #define BSD_KEY(prefix, suffix) \
202 ((((uint32_t)(suffix)) << 16) + (uint32_t)(prefix))
204 #define CHECK_GAP 10000 /* Ratio check interval */
206 #define RATIO_SCALE_LOG 8
207 #define RATIO_SCALE (1 << RATIO_SCALE_LOG)
208 #define RATIO_MAX (0x7fffffff >> RATIO_SCALE_LOG)
210 #define DECOMP_CHUNK 256
215 * clear the dictionary
218 bsd_clear(struct bsd_db
*db
)
221 db
->max_ent
= FIRST
-1;
222 db
->n_bits
= BSD_INIT_BITS
;
226 db
->checkpoint
= CHECK_GAP
;
232 * If the dictionary is full, then see if it is time to reset it.
234 * Compute the compression ratio using fixed-point arithmetic
235 * with 8 fractional bits.
237 * Since we have an infinite stream instead of a single file,
238 * watch only the local compression ratio.
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.
244 static int /* 1=output CLEAR */
245 bsd_check(struct bsd_db
*db
)
249 if (db
->in_count
>= db
->checkpoint
) {
252 * age the ratio by limiting the size of the counts
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;
259 db
->checkpoint
= db
->in_count
+ CHECK_GAP
;
261 if (db
->max_ent
>= db
->maxmaxcode
) {
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.
268 * This does not overflow, because
269 * db->in_count <= RATIO_MAX.
271 new_ratio
= db
->in_count
<< RATIO_SCALE_LOG
;
273 if (db
->bytes_out
!= 0) {
274 new_ratio
/= db
->bytes_out
;
277 if (new_ratio
< db
->ratio
||
278 new_ratio
< 1 * RATIO_SCALE
) {
283 db
->ratio
= new_ratio
;
296 bsd_comp_stats(void *state
, struct compstat
*stats
)
298 struct bsd_db
*db
= (struct bsd_db
*)state
;
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
;
311 if (stats
->ratio
<= 0x7fffff) {
325 * Reset state, as on a CCP ResetReq.
328 bsd_reset(void *state
)
330 struct bsd_db
*db
= (struct bsd_db
*)state
;
332 if (db
->hsize
!= 0) {
344 * Allocate space for a (de) compressor.
347 bsd_alloc(uchar_t
*options
, int opt_len
, int decomp
)
358 options
[0] != CI_BSD_COMPRESS
||
360 BSD_VERSION(options
[2]) != BSD_CURRENT_VERSION
) {
365 bits
= BSD_NBITS(options
[2]);
369 case 9: /* needs 82152 for both directions */
370 case 10: /* needs 84144 */
371 case 11: /* needs 88240 */
372 case 12: /* needs 96432 */
379 case 13: /* needs 176784 */
386 case 14: /* needs 353744 */
393 case 15: /* needs 691440 */
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 */
411 maxmaxcode
= MAXCODE(bits
);
412 ilen
= newlen
= sizeof (*db
) + (hsize
-1) * sizeof (db
->dict
[0]);
414 newlen
+= (maxmaxcode
+1) * sizeof (db
->lens
[0]);
415 db
= kmem_alloc(newlen
, KM_NOSLEEP
);
420 bzero(db
, sizeof (*db
) - sizeof (db
->dict
));
425 db
->lens
= (ushort_t
*)((caddr_t
)db
+ ilen
);
430 db
->hshift
= (uchar_t
)hshift
;
431 db
->maxmaxcode
= maxmaxcode
;
432 db
->maxbits
= (uchar_t
)bits
;
441 bsd_free(void *state
)
443 struct bsd_db
*db
= (struct bsd_db
*)state
;
445 if (db
->hsize
!= 0) {
446 /* XXX feeble attempt to catch bad references. */
449 kmem_free(db
, db
->totlen
);
457 bsd_comp_alloc(uchar_t
*options
, int opt_len
)
459 return (bsd_alloc(options
, opt_len
, 0));
466 bsd_decomp_alloc(uchar_t
*options
, int opt_len
)
468 return (bsd_alloc(options
, opt_len
, 1));
474 * Initialize the database.
477 bsd_init(struct bsd_db
*db
, uchar_t
*options
, int opt_len
, int unit
,
478 int hdrlen
, int mru
, int debug
, int decomp
)
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
) {
503 db
->dict
[--i
].codem1
= BADCODEM1
;
504 db
->dict
[i
].cptr
= 0;
509 db
->mru
= (ushort_t
)mru
;
512 db
->flags
|= DS_DEBUG
;
517 db
->flags
|= DS_INITDONE
;
526 bsd_comp_init(void *state
, uchar_t
*options
, int opt_len
, int unit
, int hdrlen
,
529 return (bsd_init((struct bsd_db
*)state
, options
, opt_len
,
530 unit
, hdrlen
, 0, debug
, 0));
537 bsd_decomp_init(void *state
, uchar_t
*options
, int opt_len
, int unit
,
538 int hdrlen
, int mru
, int debug
)
540 return (bsd_init((struct bsd_db
*)state
, options
, opt_len
,
541 unit
, hdrlen
, mru
, debug
, 1));
549 * One change from the BSD compress command is that when the
550 * code size expands, we do not output a bunch of padding.
552 * N.B. at present, we ignore the hdrlen specified in the comp_init call.
554 static int /* new slen */
555 bsd_compress(void *state
, mblk_t
**mretp
, mblk_t
*mp
, int slen
, int maxolen
)
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
;
564 struct bsd_dict
*dictp
;
569 int ilen
= slen
- (PPP_HDRLEN
-1);
571 uchar_t
*rptr
, *rmax
;
577 int hdlcaddr
, hdlcctl
;
579 ASSERT(db
->flags
& DS_INITDONE
);
581 #define PUTBYTE(v) { \
584 if (wptr >= cp_end) { \
589 cp_end = m->b_datap->db_lim; \
598 #define OUTPUT(ent) { \
600 accm |= ((ent) << bitno); \
602 PUTBYTE(accm >> 24); \
605 } while (bitno <= 24); \
608 #define ADJRPTR() { \
609 if (rptr != NULL) { \
610 while (rptr >= rmax) { \
611 if ((mp = mp->b_cont) == NULL) { \
621 #define GETBYTE(v) { \
622 if (rptr != NULL) { \
631 * First get the protocol and check that we're
632 * interested in this packet.
638 /* We CANNOT do a pullup here; it's not our buffer to toy with. */
648 * Per RFC 1977, the protocol field must be compressed using a
649 * PFC-like procedure. Also, all protocols between 0000-3FFF
650 * except the two compression protocols must be LZ compressed.
654 if (rptr
== NULL
|| ent
== PPP_COMP
|| ent
== PPP_COMPFRAG
)
663 * Don't generate compressed packets that are larger than the
664 * source (uncompressed) packet.
666 if (maxolen
> slen
) {
673 * Allocate enough message blocks to give maxolen total space
676 for (olen
= maxolen
; olen
> 0; ) {
678 m
= allocb((olen
< 4096? olen
: 4096), BPRI_MED
);
684 /* We allocated some; hope for the best. */
689 olen
-= m
->b_datap
->db_lim
- m
->b_wptr
;
696 cp_end
= m
->b_datap
->db_lim
;
701 * Copy the PPP header over, changing the protocol,
702 * and install the 2-byte sequence number
706 *wptr
++ = PPP_COMP
>>8; /* change the protocol */
708 *wptr
++ = db
->seqno
>> 8;
713 * If testing output, just garbling the sequence here does the
716 if ((db
->flags
& DS_TESTOUT
) && (db
->seqno
% 100) == 50)
729 fcode
= BSD_KEY(ent
, c
);
730 hval
= BSD_HASH(ent
, c
, hshift
);
732 dictp
= &db
->dict
[hval
];
735 * Validate and then check the entry
737 if (dictp
->codem1
>= max_ent
) {
741 if (dictp
->f
.fcode
== fcode
) {
742 ent
= dictp
->codem1
+1;
745 * found (prefix,suffix)
751 * continue probing until a match or invalid entry
753 disp
= (hval
== 0) ? 1 : hval
;
757 if (hval
>= db
->hsize
) {
759 if (hval
>= db
->hsize
) {
760 if (db
->flags
& DS_DEBUG
) {
762 "bsd_comp%d: internal "
766 /* Caller will free it all */
771 dictp
= &db
->dict
[hval
];
773 if (dictp
->codem1
>= max_ent
) {
776 } while (dictp
->f
.fcode
!= fcode
);
779 * finally found (prefix,suffix)
781 ent
= dictp
->codem1
+ 1;
794 if (max_ent
< db
->maxmaxcode
) {
795 struct bsd_dict
*dictp2
;
798 * expand code size if needed
800 if (max_ent
>= MAXCODE(n_bits
)) {
801 db
->n_bits
= ++n_bits
;
805 * Invalidate old hash table entry using
806 * this code, and then take it over.
808 dictp2
= &db
->dict
[max_ent
+1];
810 if (db
->dict
[dictp2
->cptr
].codem1
== max_ent
) {
811 db
->dict
[dictp2
->cptr
].codem1
= BADCODEM1
;
814 dictp2
->cptr
= (ushort_t
)hval
;
815 dictp
->codem1
= max_ent
;
816 dictp
->f
.fcode
= fcode
;
818 db
->max_ent
= ++max_ent
;
825 * output the last code
829 olen
+= (32-bitno
+7)/8; /* count complete bytes */
831 db
->bytes_out
+= olen
;
832 db
->in_count
+= ilen
;
835 OUTPUT(CLEAR
); /* do not count the CLEAR */
839 * Pad dribble bits of last code with ones.
840 * Do not emit a completely useless byte of ones.
843 PUTBYTE((accm
| (0xff << (bitno
- 8))) >> 24);
847 * Increase code size if we would have without the packet
848 * boundary and as the decompressor will.
850 if (max_ent
>= MAXCODE(n_bits
) && max_ent
< db
->maxmaxcode
) {
854 db
->uncomp_bytes
+= ilen
;
857 if (wptr
== NULL
|| olen
+ PPP_HDRLEN
+ BSD_OVHD
>= maxolen
) {
859 * throw away the compressed stuff if it is longer
867 db
->incomp_bytes
+= ilen
;
878 db
->comp_bytes
+= olen
+ BSD_OVHD
;
883 return (olen
+ PPP_HDRLEN
+ BSD_OVHD
);
892 * Update the "BSD Compress" dictionary on the receiver for
893 * incompressible data by pretending to compress the incoming data.
896 bsd_incomp(void *state
, mblk_t
*mp
)
898 struct bsd_db
*db
= (struct bsd_db
*)state
;
899 uint_t hshift
= db
->hshift
;
900 uint_t max_ent
= db
->max_ent
;
901 uint_t n_bits
= db
->n_bits
;
902 struct bsd_dict
*dictp
;
910 uchar_t
*rptr
, *rmax
;
913 ASSERT(db
->flags
& DS_INITDONE
);
921 GETBYTE(ent
); /* address */
923 GETBYTE(ent
); /* control */
925 GETBYTE(ent
); /* protocol high */
929 * Per RFC 1977, the protocol field must be compressed using a
930 * PFC-like procedure. Also, all protocols between 0000-3FFF
931 * except the two compression protocols must be LZ compressed.
933 ilen
= 1; /* count the protocol as 1 byte */
936 if (rptr
== NULL
|| ent
== PPP_COMP
|| ent
== PPP_COMPFRAG
)
948 slen
= mp
->b_wptr
- rptr
;
956 continue; /* skip zero-length buffers */
964 fcode
= BSD_KEY(ent
, c
);
965 hval
= BSD_HASH(ent
, c
, hshift
);
967 dictp
= &db
->dict
[hval
];
970 * validate and then check the entry
972 if (dictp
->codem1
>= max_ent
) {
976 if (dictp
->f
.fcode
== fcode
) {
977 ent
= dictp
->codem1
+ 1;
978 continue; /* found (prefix,suffix) */
982 * continue probing until a match or invalid entry
984 disp
= (hval
== 0) ? 1 : hval
;
987 if (hval
>= db
->hsize
) {
989 if (hval
>= db
->hsize
) {
990 if (db
->flags
& DS_DEBUG
) {
1000 dictp
= &db
->dict
[hval
];
1001 if (dictp
->codem1
>= max_ent
) {
1004 } while (dictp
->f
.fcode
!= fcode
);
1006 ent
= dictp
->codem1
+1;
1007 continue; /* finally found (prefix,suffix) */
1009 nomatch
: /* output (count) the prefix */
1015 if (max_ent
< db
->maxmaxcode
) {
1016 struct bsd_dict
*dictp2
;
1019 * expand code size if needed
1021 if (max_ent
>= MAXCODE(n_bits
)) {
1022 db
->n_bits
= ++n_bits
;
1026 * Invalidate previous hash table entry
1027 * assigned this code, and then take it over.
1029 dictp2
= &db
->dict
[max_ent
+1];
1030 if (db
->dict
[dictp2
->cptr
].codem1
== max_ent
) {
1031 db
->dict
[dictp2
->cptr
].codem1
=
1035 dictp2
->cptr
= (ushort_t
)hval
;
1036 dictp
->codem1
= max_ent
;
1037 dictp
->f
.fcode
= fcode
;
1039 db
->max_ent
= ++max_ent
;
1040 db
->lens
[max_ent
] = db
->lens
[ent
]+1;
1044 } while (--slen
!= 0);
1047 bitno
+= n_bits
; /* output (count) the last code */
1049 db
->bytes_out
+= bitno
/8;
1050 db
->in_count
+= ilen
;
1052 (void) bsd_check(db
);
1055 db
->incomp_bytes
+= ilen
;
1057 db
->uncomp_bytes
+= ilen
;
1060 * Increase code size if we would have without the packet
1061 * boundary and as the decompressor will.
1063 if (max_ent
>= MAXCODE(n_bits
) && max_ent
< db
->maxmaxcode
) {
1074 * Decompress "BSD Compress"
1076 * Because of patent problems, we return DECOMP_ERROR for errors
1077 * found by inspecting the input data and for system problems, but
1078 * DECOMP_FATALERROR for any errors which could possibly be said to
1079 * be being detected "after" decompression. For DECOMP_ERROR,
1080 * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
1081 * infringing a patent of Motorola's if we do, so we take CCP down
1084 * Given that the frame has the correct sequence number and a good FCS,
1085 * errors such as invalid codes in the input most likely indicate a
1086 * bug, so we return DECOMP_FATALERROR for them in order to turn off
1087 * compression, even though they are detected by inspecting the input.
1090 bsd_decompress(void *state
, mblk_t
**dmpp
)
1092 mblk_t
*cmsg
= *dmpp
, *mnext
;
1093 struct bsd_db
*db
= (struct bsd_db
*)state
;
1094 uint_t max_ent
= db
->max_ent
;
1096 uint_t bitno
= 32; /* 1st valid bit in accm */
1097 uint_t n_bits
= db
->n_bits
;
1098 uint_t tgtbitno
= 32 - n_bits
; /* bitno when we have a code */
1099 struct bsd_dict
*dictp
;
1104 uint_t finchar
= 0, ofinchar
;
1106 uchar_t
*rptr
, *rmax
;
1107 uchar_t
*wptr
, *prepos
;
1119 ASSERT(db
->flags
& DS_INITDONE
);
1121 /* Note: spppcomp already did a pullup to fix the first buffer. */
1123 rptr
= cmsg
->b_rptr
;
1124 rmax
= cmsg
->b_wptr
;
1128 * Note that we free as we go. If we fail to decompress,
1129 * there's nothing good that the caller can do.
1132 while (rptr >= rmax) { \
1133 mnext = cmsg->b_cont; \
1135 if ((cmsg = mnext) == NULL) { \
1139 rptr = cmsg->b_rptr; \
1140 rmax = cmsg->b_wptr; \
1141 ilen += rmax-rptr; \
1145 * Save the address/control from the PPP header
1146 * and then get the sequence number.
1152 seq
= rptr
== NULL
? 0 : (*rptr
++ << 8);
1155 if (db
->flags
& DS_DEBUG
) {
1156 cmn_err(CE_CONT
, "bsd_decomp%d: bad buffer\n",
1159 return (DECOMP_ERROR
);
1165 * If testing input, just pretending the sequence is bad here
1168 if ((db
->flags
& DS_TESTIN
) && (db
->seqno
% 300) == 101)
1173 * Check the sequence number and give up if it is not what we expect.
1175 if (db
->hsize
== 0 || seq
!= db
->seqno
++) {
1177 if (db
->flags
& DS_DEBUG
) {
1178 cmn_err(CE_CONT
, "bsd_decomp%d: bad sequence # %d, "
1179 "expected %d\n", db
->unit
, seq
, db
->seqno
- 1);
1182 return (DECOMP_ERROR
);
1186 * Allocate one message block to start with.
1188 if ((dmsg
= allocb(DECOMP_CHUNK
+ db
->hdrlen
, BPRI_MED
)) == NULL
) {
1190 if (db
->flags
& DS_DEBUG
) {
1192 "bsd_decomp%d: can't allocate first buffer\n",
1195 return (DECOMP_ERROR
);
1199 * Avoid an error that might cause us to allocate all available memory.
1200 * Enforce a maximum number of blocks to allocate for message. We add
1201 * a fudge factor of 5 extra blocks, in order to avoid unnecessary
1202 * DECOMP_ERROR when the code size is small (9).
1204 blockctr
= ((db
->mru
+ 32 + DECOMP_CHUNK
- 1) / DECOMP_CHUNK
) + 5;
1207 dmsg
->b_wptr
+= db
->hdrlen
;
1208 dmsg
->b_rptr
= wptr
= dmsg
->b_wptr
;
1211 * Insert PPP header. This shouldn't be needed!
1217 dmsg
->b_wptr
= wptr
;
1219 explen
= dmsg
->b_datap
->db_lim
- wptr
;
1231 * Accumulate bytes until we have a complete code.
1232 * Then get the next code, relying on the 32-bit,
1233 * unsigned accm to mask the result.
1237 accm
|= *rptr
++ << bitno
;
1239 if (tgtbitno
< bitno
) {
1243 incode
= accm
>> tgtbitno
;
1247 if (incode
== CLEAR
) {
1250 * The dictionary must only be cleared at
1251 * the end of a packet. But there could be an
1252 * empty message block at the end.
1258 if (db
->flags
& DS_DEBUG
) {
1260 "bsd_decomp%d: bad CLEAR\n",
1264 return (DECOMP_FATALERROR
);
1268 /* Have to keep cleared state variables! */
1269 outlen
+= wptr
-dmsg
->b_wptr
;
1270 dmsg
->b_wptr
= wptr
;
1271 db
->comp_bytes
+= ilen
;
1277 * Special case for KwKwK string
1280 if (incode
> max_ent
) {
1281 if (incode
> max_ent
+ 2 ||
1282 incode
> db
->maxmaxcode
||
1287 /* probably a bug if we get here */
1288 if (db
->flags
& DS_DEBUG
) {
1290 "bsd_decomp%d: bad code 0x%x "
1291 "oldcode=0x%x ", db
->unit
, incode
,
1295 return (DECOMP_FATALERROR
);
1303 codelen
= db
->lens
[finchar
];
1306 * Decode this code and install it in the decompressed buffer
1308 explen
-= codelen
+ extra
;
1311 * Allocate another message block
1313 dlen
= wptr
- dmsg
->b_wptr
;
1315 db
->in_count
+= dlen
;
1316 dmsg
->b_wptr
= wptr
;
1317 dlen
= codelen
+ extra
;
1319 if (dlen
< DECOMP_CHUNK
) {
1320 dlen
= DECOMP_CHUNK
;
1323 if ((--blockctr
< 0) ||
1324 (dmsg
->b_cont
= allocb(dlen
, BPRI_MED
)) == NULL
) {
1327 if (db
->flags
& DS_DEBUG
) {
1329 "bsd_decomp%d: %s output "
1330 "buffers; outlen %d+%d\n",
1332 (blockctr
< 0 ? "too many" :
1336 return (DECOMP_ERROR
);
1339 dmsg
= dmsg
->b_cont
;
1340 wptr
= dmsg
->b_wptr
;
1341 explen
= dmsg
->b_datap
->db_lim
- wptr
- codelen
-
1345 p
= (wptr
+= codelen
);
1347 while (finchar
> LAST
) {
1348 dictp
= &db
->dict
[db
->dict
[finchar
].cptr
];
1349 *--p
= dictp
->f
.hs
.suffix
;
1350 finchar
= dictp
->f
.hs
.prefix
;
1357 /* Wow, is *this* ugly! */
1358 if (!(finchar
& 1)) {
1359 if (p
== prepos
+1) {
1360 bcopy(p
, prepos
, wptr
-p
);
1365 /* This is safe, but doesn't look it */
1372 if (extra
) { /* the KwKwK case again */
1377 * If not first code in a packet, and
1378 * if not out of code space, then allocate a new code.
1380 * Keep the hash table correct so it can be used
1381 * with uncompressed packets.
1383 if (oldcode
!= CLEAR
&& max_ent
< db
->maxmaxcode
) {
1384 struct bsd_dict
*dictp2
;
1389 fcode
= BSD_KEY(oldcode
, finchar
);
1390 hval
= BSD_HASH(oldcode
, finchar
, db
->hshift
);
1392 dictp
= &db
->dict
[hval
];
1395 * look for a free hash table entry
1397 if (dictp
->codem1
< max_ent
) {
1398 disp
= (hval
== 0) ? 1 : hval
;
1403 if (hval
>= db
->hsize
) {
1405 if (hval
>= db
->hsize
) {
1410 cmn_err(CE_CONT
, "bsd_decomp%d: internal error\n",
1414 (DECOMP_FATALERROR
);
1418 dictp
= &db
->dict
[hval
];
1420 } while (dictp
->codem1
< max_ent
);
1424 * Invalidate previous hash table entry
1425 * assigned this code, and then take it over
1427 dictp2
= &db
->dict
[max_ent
+1];
1429 if (db
->dict
[dictp2
->cptr
].codem1
== max_ent
) {
1430 db
->dict
[dictp2
->cptr
].codem1
= BADCODEM1
;
1433 dictp2
->cptr
= (ushort_t
)hval
;
1434 dictp
->codem1
= max_ent
;
1435 dictp
->f
.fcode
= fcode
;
1437 db
->max_ent
= ++max_ent
;
1438 db
->lens
[max_ent
] = db
->lens
[oldcode
]+1;
1441 * Expand code size if needed
1443 if (max_ent
>= MAXCODE(n_bits
) &&
1444 max_ent
< db
->maxmaxcode
) {
1446 db
->n_bits
= ++n_bits
;
1447 tgtbitno
= 32-n_bits
;
1454 dlen
= wptr
-dmsg
->b_wptr
;
1456 db
->in_count
+= dlen
;
1457 dmsg
->b_wptr
= wptr
;
1458 db
->bytes_out
+= ilen
;
1461 * Keep the checkpoint right so that incompressible packets
1462 * clear the dictionary at the right times.
1464 if (bsd_check(db
) && (db
->flags
& DS_DEBUG
)) {
1466 "bsd_decomp%d: peer should have cleared dictionary\n",
1471 db
->comp_bytes
+= ilen
+ BSD_OVHD
;
1473 db
->uncomp_bytes
+= outlen
;
1482 bsd_set_effort(void *xarg
, void *rarg
, int effortlevel
)
1485 struct bsd_db
*xdb
= (struct bsd_db
*)xarg
;
1486 struct bsd_db
*rdb
= (struct bsd_db
*)rarg
;
1488 if (effortlevel
== 42 || effortlevel
== 2112) {
1489 /* corrupt received data. */
1491 rdb
->flags
|= DS_TESTIN
;
1492 cmn_err(CE_CONT
, "bsd-comp: enabled input testing.");
1494 if (effortlevel
!= 2112)
1497 if (effortlevel
== 2001 || effortlevel
== 2112) {
1498 /* corrupt transmitted data. */
1500 xdb
->flags
|= DS_TESTOUT
;
1501 cmn_err(CE_CONT
, "bsd-comp: enabled output testing.");
1508 #endif /* DO_BSD_COMPRESS */