]> git.ozlabs.org Git - ppp.git/blob - pppdump/bsd-comp.c
For Linux, use the Linux / Glibc based defines instead of included headers
[ppp.git] / pppdump / bsd-comp.c
1 /* Because this code is derived from the 4.3BSD compress source:
2  *
3  *
4  * Copyright (c) 1985, 1986 The Regents of the University of California.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * James A. Woods, derived from original work by Spencer Thomas
9  * and Joseph Orost.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *      This product includes software developed by the University of
22  *      California, Berkeley and its contributors.
23  * 4. Neither the name of the University nor the names of its contributors
24  *    may be used to endorse or promote products derived from this software
25  *    without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37  * SUCH DAMAGE.
38  */
39
40 /*
41  * $Id: bsd-comp.c,v 1.4 2004/01/17 05:47:55 carlsonj Exp $
42  */
43
44 #include <sys/types.h>
45 #include <stdio.h>
46 #include <stddef.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <net/ppp_defs.h>
50
51 #include "ppp-comp.h"
52
53 #if DO_BSD_COMPRESS
54
55 /*
56  * PPP "BSD compress" compression
57  *  The differences between this compression and the classic BSD LZW
58  *  source are obvious from the requirement that the classic code worked
59  *  with files while this handles arbitrarily long streams that
60  *  are broken into packets.  They are:
61  *
62  *      When the code size expands, a block of junk is not emitted by
63  *          the compressor and not expected by the decompressor.
64  *
65  *      New codes are not necessarily assigned every time an old
66  *          code is output by the compressor.  This is because a packet
67  *          end forces a code to be emitted, but does not imply that a
68  *          new sequence has been seen.
69  *
70  *      The compression ratio is checked at the first end of a packet
71  *          after the appropriate gap.  Besides simplifying and speeding
72  *          things up, this makes it more likely that the transmitter
73  *          and receiver will agree when the dictionary is cleared when
74  *          compression is not going well.
75  */
76
77 /*
78  * A dictionary for doing BSD compress.
79  */
80 struct bsd_db {
81     int     totlen;                     /* length of this structure */
82     u_int   hsize;                      /* size of the hash table */
83     u_char  hshift;                     /* used in hash function */
84     u_char  n_bits;                     /* current bits/code */
85     u_char  maxbits;
86     u_char  debug;
87     u_char  unit;
88     u_short seqno;                      /* sequence number of next packet */
89     u_int   hdrlen;                     /* header length to preallocate */
90     u_int   mru;
91     u_int   maxmaxcode;                 /* largest valid code */
92     u_int   max_ent;                    /* largest code in use */
93     u_int   in_count;                   /* uncompressed bytes, aged */
94     u_int   bytes_out;                  /* compressed bytes, aged */
95     u_int   ratio;                      /* recent compression ratio */
96     u_int   checkpoint;                 /* when to next check the ratio */
97     u_int   clear_count;                /* times dictionary cleared */
98     u_int   incomp_count;               /* incompressible packets */
99     u_int   incomp_bytes;               /* incompressible bytes */
100     u_int   uncomp_count;               /* uncompressed packets */
101     u_int   uncomp_bytes;               /* uncompressed bytes */
102     u_int   comp_count;                 /* compressed packets */
103     u_int   comp_bytes;                 /* compressed bytes */
104     u_short *lens;                      /* array of lengths of codes */
105     struct bsd_dict {
106         union {                         /* hash value */
107             u_int32_t   fcode;
108             struct {
109 #ifdef BSD_LITTLE_ENDIAN
110                 u_short prefix;         /* preceding code */
111                 u_char  suffix;         /* last character of new code */
112                 u_char  pad;
113 #else
114                 u_char  pad;
115                 u_char  suffix;         /* last character of new code */
116                 u_short prefix;         /* preceding code */
117 #endif
118             } hs;
119         } f;
120         u_short codem1;                 /* output of hash table -1 */
121         u_short cptr;                   /* map code to hash table entry */
122     } dict[1];
123 };
124
125 #define BSD_OVHD        2               /* BSD compress overhead/packet */
126 #define BSD_INIT_BITS   BSD_MIN_BITS
127
128 static void     *bsd_decomp_alloc(u_char *options, int opt_len);
129 static void     bsd_free(void *state);
130 static int      bsd_decomp_init(void *state, u_char *options, int opt_len,
131                                 int unit, int hdrlen, int mru, int debug);
132 static void     bsd_incomp(void *state, u_char *dmsg, int len);
133 static int      bsd_decompress(void *state, u_char *cmp, int inlen,
134                                u_char *dmp, int *outlen);
135 static void     bsd_reset(void *state);
136 static void     bsd_comp_stats(void *state, struct compstat *stats);
137
138 /*
139  * Exported procedures.
140  */
141 struct compressor ppp_bsd_compress = {
142     CI_BSD_COMPRESS,            /* compress_proto */
143     bsd_decomp_alloc,           /* decomp_alloc */
144     bsd_free,                   /* decomp_free */
145     bsd_decomp_init,            /* decomp_init */
146     bsd_reset,                  /* decomp_reset */
147     bsd_decompress,             /* decompress */
148     bsd_incomp,                 /* incomp */
149     bsd_comp_stats,             /* decomp_stat */
150 };
151
152 /*
153  * the next two codes should not be changed lightly, as they must not
154  * lie within the contiguous general code space.
155  */
156 #define CLEAR   256                     /* table clear output code */
157 #define FIRST   257                     /* first free entry */
158 #define LAST    255
159
160 #define MAXCODE(b)      ((1 << (b)) - 1)
161 #define BADCODEM1       MAXCODE(BSD_MAX_BITS)
162
163 #define BSD_HASH(prefix,suffix,hshift)  ((((u_int32_t)(suffix)) << (hshift)) \
164                                          ^ (u_int32_t)(prefix))
165 #define BSD_KEY(prefix,suffix)          ((((u_int32_t)(suffix)) << 16) \
166                                          + (u_int32_t)(prefix))
167
168 #define CHECK_GAP       10000           /* Ratio check interval */
169
170 #define RATIO_SCALE_LOG 8
171 #define RATIO_SCALE     (1<<RATIO_SCALE_LOG)
172 #define RATIO_MAX       (0x7fffffff>>RATIO_SCALE_LOG)
173
174 /*
175  * clear the dictionary
176  */
177 static void
178 bsd_clear(struct bsd_db *db)
179 {
180     db->clear_count++;
181     db->max_ent = FIRST-1;
182     db->n_bits = BSD_INIT_BITS;
183     db->ratio = 0;
184     db->bytes_out = 0;
185     db->in_count = 0;
186     db->checkpoint = CHECK_GAP;
187 }
188
189 /*
190  * If the dictionary is full, then see if it is time to reset it.
191  *
192  * Compute the compression ratio using fixed-point arithmetic
193  * with 8 fractional bits.
194  *
195  * Since we have an infinite stream instead of a single file,
196  * watch only the local compression ratio.
197  *
198  * Since both peers must reset the dictionary at the same time even in
199  * the absence of CLEAR codes (while packets are incompressible), they
200  * must compute the same ratio.
201  */
202 static int                              /* 1=output CLEAR */
203 bsd_check(struct bsd_db *db)
204 {
205     u_int new_ratio;
206
207     if (db->in_count >= db->checkpoint) {
208         /* age the ratio by limiting the size of the counts */
209         if (db->in_count >= RATIO_MAX
210             || db->bytes_out >= RATIO_MAX) {
211             db->in_count -= db->in_count/4;
212             db->bytes_out -= db->bytes_out/4;
213         }
214
215         db->checkpoint = db->in_count + CHECK_GAP;
216
217         if (db->max_ent >= db->maxmaxcode) {
218             /* Reset the dictionary only if the ratio is worse,
219              * or if it looks as if it has been poisoned
220              * by incompressible data.
221              *
222              * This does not overflow, because
223              *  db->in_count <= RATIO_MAX.
224              */
225             new_ratio = db->in_count << RATIO_SCALE_LOG;
226             if (db->bytes_out != 0)
227                 new_ratio /= db->bytes_out;
228
229             if (new_ratio < db->ratio || new_ratio < 1 * RATIO_SCALE) {
230                 bsd_clear(db);
231                 return 1;
232             }
233             db->ratio = new_ratio;
234         }
235     }
236     return 0;
237 }
238
239 /*
240  * Return statistics.
241  */
242 static void
243 bsd_comp_stats(void *state, struct compstat *stats)
244 {
245     struct bsd_db *db = (struct bsd_db *) state;
246     u_int out;
247
248     stats->unc_bytes = db->uncomp_bytes;
249     stats->unc_packets = db->uncomp_count;
250     stats->comp_bytes = db->comp_bytes;
251     stats->comp_packets = db->comp_count;
252     stats->inc_bytes = db->incomp_bytes;
253     stats->inc_packets = db->incomp_count;
254
255     u_int ratio = db->in_count;
256     out = db->bytes_out;
257     if (ratio <= 0x7fffff)
258         ratio <<= 8;
259     else
260         out >>= 8;
261     if (out != 0)
262         stats->ratio = ratio / out;
263 }
264
265 /*
266  * Reset state, as on a CCP ResetReq.
267  */
268 static void
269 bsd_reset(void *state)
270 {
271     struct bsd_db *db = (struct bsd_db *) state;
272
273     db->seqno = 0;
274     bsd_clear(db);
275     db->clear_count = 0;
276 }
277
278 /*
279  * Allocate space for a (de) compressor.
280  */
281 static void *
282 bsd_alloc(u_char *options, int opt_len, int decomp)
283 {
284     int bits;
285     u_int newlen, hsize, hshift, maxmaxcode;
286     struct bsd_db *db;
287
288     if (opt_len != 3 || options[0] != CI_BSD_COMPRESS || options[1] != 3
289         || BSD_VERSION(options[2]) != BSD_CURRENT_VERSION)
290         return NULL;
291
292     bits = BSD_NBITS(options[2]);
293     switch (bits) {
294     case 9:                     /* needs 82152 for both directions */
295     case 10:                    /* needs 84144 */
296     case 11:                    /* needs 88240 */
297     case 12:                    /* needs 96432 */
298         hsize = 5003;
299         hshift = 4;
300         break;
301     case 13:                    /* needs 176784 */
302         hsize = 9001;
303         hshift = 5;
304         break;
305     case 14:                    /* needs 353744 */
306         hsize = 18013;
307         hshift = 6;
308         break;
309     case 15:                    /* needs 691440 */
310         hsize = 35023;
311         hshift = 7;
312         break;
313     case 16:                    /* needs 1366160--far too much, */
314         /* hsize = 69001; */    /* and 69001 is too big for cptr */
315         /* hshift = 8; */       /* in struct bsd_db */
316         /* break; */
317     default:
318         return NULL;
319     }
320
321     maxmaxcode = MAXCODE(bits);
322     newlen = sizeof(*db) + (hsize-1) * (sizeof(db->dict[0]));
323     db = (struct bsd_db *) malloc(newlen);
324     if (!db)
325         return NULL;
326     memset(db, 0, sizeof(*db) - sizeof(db->dict));
327
328     if (!decomp) {
329         db->lens = NULL;
330     } else {
331         db->lens = (u_short *) malloc((maxmaxcode+1) * sizeof(db->lens[0]));
332         if (!db->lens) {
333             free(db);
334             return NULL;
335         }
336     }
337
338     db->totlen = newlen;
339     db->hsize = hsize;
340     db->hshift = hshift;
341     db->maxmaxcode = maxmaxcode;
342     db->maxbits = bits;
343
344     return (void *) db;
345 }
346
347 static void
348 bsd_free(void *state)
349 {
350     struct bsd_db *db = (struct bsd_db *) state;
351
352     if (db->lens)
353         free(db->lens);
354     free(db);
355 }
356
357 static void *
358 bsd_decomp_alloc(u_char *options, int opt_len)
359 {
360     return bsd_alloc(options, opt_len, 1);
361 }
362
363 /*
364  * Initialize the database.
365  */
366 static int
367 bsd_init(struct bsd_db *db, u_char *options, int opt_len, int unit,
368          int hdrlen, int mru, int debug, int decomp)
369 {
370     int i;
371
372     if (opt_len < CILEN_BSD_COMPRESS
373         || options[0] != CI_BSD_COMPRESS || options[1] != CILEN_BSD_COMPRESS
374         || BSD_VERSION(options[2]) != BSD_CURRENT_VERSION
375         || BSD_NBITS(options[2]) != db->maxbits
376         || (decomp && db->lens == NULL))
377         return 0;
378
379     if (decomp) {
380         i = LAST+1;
381         while (i != 0)
382             db->lens[--i] = 1;
383     }
384     i = db->hsize;
385     while (i != 0) {
386         db->dict[--i].codem1 = BADCODEM1;
387         db->dict[i].cptr = 0;
388     }
389
390     db->unit = unit;
391     db->hdrlen = hdrlen;
392     db->mru = mru;
393     if (debug)
394         db->debug = 1;
395
396     bsd_reset(db);
397
398     return 1;
399 }
400
401 static int
402 bsd_decomp_init(void *state, u_char *options, int opt_len,
403                 int unit, int hdrlen, int mru, int debug)
404 {
405     return bsd_init((struct bsd_db *) state, options, opt_len,
406                     unit, hdrlen, mru, debug, 1);
407 }
408
409
410 /*
411  * Update the "BSD Compress" dictionary on the receiver for
412  * incompressible data by pretending to compress the incoming data.
413  */
414 static void
415 bsd_incomp(void *state, u_char *dmsg, int mlen)
416 {
417     struct bsd_db *db = (struct bsd_db *) state;
418     u_int hshift = db->hshift;
419     u_int max_ent = db->max_ent;
420     u_int n_bits = db->n_bits;
421     struct bsd_dict *dictp;
422     u_int32_t fcode;
423     u_char c;
424     long hval, disp;
425     int slen, ilen;
426     u_int bitno = 7;
427     u_char *rptr;
428     u_int ent;
429
430     rptr = dmsg;
431     ent = rptr[0];              /* get the protocol */
432     if (ent == 0) {
433         ++rptr;
434         --mlen;
435         ent = rptr[0];
436     }
437     if ((ent & 1) == 0 || ent < 0x21 || ent > 0xf9)
438         return;
439
440     db->seqno++;
441     ilen = 1;           /* count the protocol as 1 byte */
442     ++rptr;
443     slen = dmsg + mlen - rptr;
444     ilen += slen;
445     for (; slen > 0; --slen) {
446         c = *rptr++;
447         fcode = BSD_KEY(ent, c);
448         hval = BSD_HASH(ent, c, hshift);
449         dictp = &db->dict[hval];
450
451         /* validate and then check the entry */
452         if (dictp->codem1 >= max_ent)
453             goto nomatch;
454         if (dictp->f.fcode == fcode) {
455             ent = dictp->codem1+1;
456             continue;   /* found (prefix,suffix) */
457         }
458
459         /* continue probing until a match or invalid entry */
460         disp = (hval == 0) ? 1 : hval;
461         do {
462             hval += disp;
463             if (hval >= db->hsize)
464                 hval -= db->hsize;
465             dictp = &db->dict[hval];
466             if (dictp->codem1 >= max_ent)
467                 goto nomatch;
468         } while (dictp->f.fcode != fcode);
469         ent = dictp->codem1+1;
470         continue;       /* finally found (prefix,suffix) */
471
472     nomatch:            /* output (count) the prefix */
473         bitno += n_bits;
474
475         /* code -> hashtable */
476         if (max_ent < db->maxmaxcode) {
477             struct bsd_dict *dictp2;
478             /* expand code size if needed */
479             if (max_ent >= MAXCODE(n_bits))
480                 db->n_bits = ++n_bits;
481
482             /* Invalidate previous hash table entry
483              * assigned this code, and then take it over.
484              */
485             dictp2 = &db->dict[max_ent+1];
486             if (db->dict[dictp2->cptr].codem1 == max_ent)
487                 db->dict[dictp2->cptr].codem1 = BADCODEM1;
488             dictp2->cptr = hval;
489             dictp->codem1 = max_ent;
490             dictp->f.fcode = fcode;
491
492             db->max_ent = ++max_ent;
493             db->lens[max_ent] = db->lens[ent]+1;
494         }
495         ent = c;
496     }
497     bitno += n_bits;            /* output (count) the last code */
498     db->bytes_out += bitno/8;
499     db->in_count += ilen;
500     (void)bsd_check(db);
501
502     ++db->incomp_count;
503     db->incomp_bytes += ilen;
504     ++db->uncomp_count;
505     db->uncomp_bytes += ilen;
506
507     /* Increase code size if we would have without the packet
508      * boundary and as the decompressor will.
509      */
510     if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode)
511         db->n_bits++;
512 }
513
514
515 /*
516  * Decompress "BSD Compress"
517  *
518  * Because of patent problems, we return DECOMP_ERROR for errors
519  * found by inspecting the input data and for system problems, but
520  * DECOMP_FATALERROR for any errors which could possibly be said to
521  * be being detected "after" decompression.  For DECOMP_ERROR,
522  * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
523  * infringing a patent of Motorola's if we do, so we take CCP down
524  * instead.
525  *
526  * Given that the frame has the correct sequence number and a good FCS,
527  * errors such as invalid codes in the input most likely indicate a
528  * bug, so we return DECOMP_FATALERROR for them in order to turn off
529  * compression, even though they are detected by inspecting the input.
530  */
531 static int
532 bsd_decompress(void *state, u_char *cmsg, int inlen, u_char *dmp, int *outlenp)
533 {
534     struct bsd_db *db = (struct bsd_db *) state;
535     u_int max_ent = db->max_ent;
536     u_int32_t accm = 0;
537     u_int bitno = 32;           /* 1st valid bit in accm */
538     u_int n_bits = db->n_bits;
539     u_int tgtbitno = 32-n_bits; /* bitno when we have a code */
540     struct bsd_dict *dictp;
541     int explen, seq, len;
542     u_int incode, oldcode, finchar;
543     u_char *p, *rptr, *wptr;
544     int ilen;
545     int codelen, extra;
546
547     rptr = cmsg;
548     if (*rptr == 0)
549         ++rptr;
550     ++rptr;                     /* skip protocol (assumed 0xfd) */
551     seq = (rptr[0] << 8) + rptr[1];
552     rptr += BSD_OVHD;
553     ilen = len = cmsg + inlen - rptr;
554
555     /*
556      * Check the sequence number and give up if it is not what we expect.
557      */
558     if (seq != db->seqno++) {
559         if (db->debug)
560             printf("bsd_decomp%d: bad sequence # %d, expected %d\n",
561                    db->unit, seq, db->seqno - 1);
562         return DECOMP_ERROR;
563     }
564
565     wptr = dmp + db->hdrlen;
566
567     oldcode = CLEAR;
568     explen = 0;
569     while (len > 0) {
570         /*
571          * Accumulate bytes until we have a complete code.
572          * Then get the next code, relying on the 32-bit,
573          * unsigned accm to mask the result.
574          */
575         bitno -= 8;
576         accm |= *rptr++ << bitno;
577         --len;
578         if (tgtbitno < bitno)
579             continue;
580         incode = accm >> tgtbitno;
581         accm <<= n_bits;
582         bitno += n_bits;
583
584         if (incode == CLEAR) {
585             /*
586              * The dictionary must only be cleared at
587              * the end of a packet.  But there could be an
588              * empty message block at the end.
589              */
590             if (len > 0) {
591                 if (db->debug)
592                     printf("bsd_decomp%d: bad CLEAR\n", db->unit);
593                 return DECOMP_FATALERROR;
594             }
595             bsd_clear(db);
596             explen = ilen = 0;
597             break;
598         }
599
600         if (incode > max_ent + 2 || incode > db->maxmaxcode
601             || (incode > max_ent && oldcode == CLEAR)) {
602             if (db->debug) {
603                 printf("bsd_decomp%d: bad code 0x%x oldcode=0x%x ",
604                        db->unit, incode, oldcode);
605                 printf("max_ent=0x%x seqno=%d\n",
606                        max_ent, db->seqno);
607             }
608             return DECOMP_FATALERROR;   /* probably a bug */
609         }
610
611         /* Special case for KwKwK string. */
612         if (incode > max_ent) {
613             finchar = oldcode;
614             extra = 1;
615         } else {
616             finchar = incode;
617             extra = 0;
618         }
619
620         codelen = db->lens[finchar];
621         explen += codelen + extra;
622         if (explen > db->mru + 1) {
623             if (db->debug)
624                 printf("bsd_decomp%d: ran out of mru\n", db->unit);
625             return DECOMP_FATALERROR;
626         }
627
628         /*
629          * Decode this code and install it in the decompressed buffer.
630          */
631         p = (wptr += codelen);
632         while (finchar > LAST) {
633             dictp = &db->dict[db->dict[finchar].cptr];
634 #ifdef DEBUG
635             --codelen;
636             if (codelen <= 0) {
637                 printf("bsd_decomp%d: fell off end of chain ", db->unit);
638                 printf("0x%x at 0x%x by 0x%x, max_ent=0x%x\n",
639                        incode, finchar, db->dict[finchar].cptr, max_ent);
640                 return DECOMP_FATALERROR;
641             }
642             if (dictp->codem1 != finchar-1) {
643                 printf("bsd_decomp%d: bad code chain 0x%x finchar=0x%x ",
644                        db->unit, incode, finchar);
645                 printf("oldcode=0x%x cptr=0x%x codem1=0x%x\n", oldcode,
646                        db->dict[finchar].cptr, dictp->codem1);
647                 return DECOMP_FATALERROR;
648             }
649 #endif
650             *--p = dictp->f.hs.suffix;
651             finchar = dictp->f.hs.prefix;
652         }
653         *--p = finchar;
654
655 #ifdef DEBUG
656         if (--codelen != 0)
657             printf("bsd_decomp%d: short by %d after code 0x%x, max_ent=0x%x\n",
658                    db->unit, codelen, incode, max_ent);
659 #endif
660
661         if (extra)              /* the KwKwK case again */
662             *wptr++ = finchar;
663
664         /*
665          * If not first code in a packet, and
666          * if not out of code space, then allocate a new code.
667          *
668          * Keep the hash table correct so it can be used
669          * with uncompressed packets.
670          */
671         if (oldcode != CLEAR && max_ent < db->maxmaxcode) {
672             struct bsd_dict *dictp2;
673             u_int32_t fcode;
674             int hval, disp;
675
676             fcode = BSD_KEY(oldcode,finchar);
677             hval = BSD_HASH(oldcode,finchar,db->hshift);
678             dictp = &db->dict[hval];
679
680             /* look for a free hash table entry */
681             if (dictp->codem1 < max_ent) {
682                 disp = (hval == 0) ? 1 : hval;
683                 do {
684                     hval += disp;
685                     if (hval >= db->hsize)
686                         hval -= db->hsize;
687                     dictp = &db->dict[hval];
688                 } while (dictp->codem1 < max_ent);
689             }
690
691             /*
692              * Invalidate previous hash table entry
693              * assigned this code, and then take it over
694              */
695             dictp2 = &db->dict[max_ent+1];
696             if (db->dict[dictp2->cptr].codem1 == max_ent) {
697                 db->dict[dictp2->cptr].codem1 = BADCODEM1;
698             }
699             dictp2->cptr = hval;
700             dictp->codem1 = max_ent;
701             dictp->f.fcode = fcode;
702
703             db->max_ent = ++max_ent;
704             db->lens[max_ent] = db->lens[oldcode]+1;
705
706             /* Expand code size if needed. */
707             if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode) {
708                 db->n_bits = ++n_bits;
709                 tgtbitno = 32-n_bits;
710             }
711         }
712         oldcode = incode;
713     }
714     *outlenp = wptr - (dmp + db->hdrlen);
715
716     /*
717      * Keep the checkpoint right so that incompressible packets
718      * clear the dictionary at the right times.
719      */
720     db->bytes_out += ilen;
721     db->in_count += explen;
722     if (bsd_check(db) && db->debug) {
723         printf("bsd_decomp%d: peer should have cleared dictionary\n",
724                db->unit);
725     }
726
727     ++db->comp_count;
728     db->comp_bytes += ilen + BSD_OVHD;
729     ++db->uncomp_count;
730     db->uncomp_bytes += explen;
731
732     return DECOMP_OK;
733 }
734 #endif /* DO_BSD_COMPRESS */