]> git.ozlabs.org Git - ppp.git/blob - NeXT/bsd-comp.c
include netbsd-1.2
[ppp.git] / NeXT / 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  * Rewritten for NextStep's funky kernel functions, I/O threads,
40  * and netbufs (instead of real mbufs).  Also, ifnets don't install
41  * into the kernel under NS as they do under BSD.  We have tried to
42  * make the code remain as similar to the NetBSD version without
43  * incurring too much hassle.  This code is the merge of 
44  * Philip Prindeville's <philipp@res.enst.fr>/Pete French's <pete@ohm.york.ac.uk>
45  * and Stephen Perkins'  <perkins@cps.msu.edu> independent ports.
46  *
47  */
48
49 /*
50  * This version is for use with mbufs on BSD-derived systems.
51  *
52  * $Id: bsd-comp.c,v 1.3 1996/09/14 05:08:26 paulus Exp $
53  */
54
55 #include <sys/param.h>
56 #include <sys/types.h>
57 #include <sys/socket.h>
58
59 #define KERNEL 1
60 #include <net/netbuf.h>
61 #include <net/if.h>
62
63 #include <net/ppp_defs.h>
64 #include <net/if_ppp.h>
65
66 #define PACKETPTR       netbuf_t
67 #include <net/ppp-comp.h>
68
69 #include "nbq.h"
70
71 /*
72  * We align with this number of bits zero. The code makes the somewhat
73  * suspect assumption that an address can be held in an unsigned long.
74  * Sadly this is necessary to do bit operations on it.
75  */
76
77 #define Z_ALIGN 3       /* 8 byte boudary */
78 #define Z_EXTRA ((unsigned long)((1<<Z_ALIGN)-1))
79 #define ALIGN(x) ((x+Z_EXTRA) & ~Z_EXTRA)
80
81 #if DO_BSD_COMPRESS
82
83 /*
84  * The following includes are necessary to correctly
85  * support BYTE_ORDER.  -SJP
86  */
87
88 #include <netinet/in.h>
89 #include <netinet/in_systm.h>
90 #include <netinet/in_var.h>
91 #include <netinet/ip.h>
92
93 #define mtod(m,type)    ((type)nb_map(m))
94 typedef unsigned short u_int16_t;
95
96 /*
97  * PPP "BSD compress" compression
98  *  The differences between this compression and the classic BSD LZW
99  *  source are obvious from the requirement that the classic code worked
100  *  with files while this handles arbitrarily long streams that
101  *  are broken into packets.  They are:
102  *
103  *      When the code size expands, a block of junk is not emitted by
104  *          the compressor and not expected by the decompressor.
105  *
106  *      New codes are not necessarily assigned every time an old
107  *          code is output by the compressor.  This is because a packet
108  *          end forces a code to be emitted, but does not imply that a
109  *          new sequence has been seen.
110  *
111  *      The compression ratio is checked at the first end of a packet
112  *          after the appropriate gap.  Besides simplifying and speeding
113  *          things up, this makes it more likely that the transmitter
114  *          and receiver will agree when the dictionary is cleared when
115  *          compression is not going well.
116  */
117
118 /*
119  * A dictionary for doing BSD compress.
120  */
121 struct bsd_db {
122     void    *kbase;                     /* actual kalloc'd address for struct */
123     void    *klens;                     /* actual kalloc'd address for lens */
124     int     totlen;                     /* length of this structure */
125     u_int   hsize;                      /* size of the hash table */
126     u_char  hshift;                     /* used in hash function */
127     u_char  n_bits;                     /* current bits/code */
128     u_char  maxbits;
129     u_char  debug;
130     u_char  unit;
131     u_int16_t seqno;                    /* sequence # of next packet */
132     u_int   hdrlen;                     /* header length to preallocate */
133     u_int   mru;
134     u_int   maxmaxcode;                 /* largest valid code */
135     u_int   max_ent;                    /* largest code in use */
136     u_int   in_count;                   /* uncompressed bytes, aged */
137     u_int   bytes_out;                  /* compressed bytes, aged */
138     u_int   ratio;                      /* recent compression ratio */
139     u_int   checkpoint;                 /* when to next check the ratio */
140     u_int   clear_count;                /* times dictionary cleared */
141     u_int   incomp_count;               /* incompressible packets */
142     u_int   incomp_bytes;               /* incompressible bytes */
143     u_int   uncomp_count;               /* uncompressed packets */
144     u_int   uncomp_bytes;               /* uncompressed bytes */
145     u_int   comp_count;                 /* compressed packets */
146     u_int   comp_bytes;                 /* compressed bytes */
147     u_int16_t *lens;                    /* array of lengths of codes */
148     struct bsd_dict {
149         union {                         /* hash value */
150             u_int32_t   fcode;
151             struct {
152 #if BYTE_ORDER == LITTLE_ENDIAN
153                 u_int16_t prefix;               /* preceding code */
154                 u_char  suffix;         /* last character of new code */
155                 u_char  pad;
156 #else
157                 u_char  pad;
158                 u_char  suffix;         /* last character of new code */
159                 u_int16_t prefix;               /* preceding code */
160 #endif
161             } hs;
162         } f;
163         u_int16_t codem1;                       /* output of hash table -1 */
164         u_int16_t cptr;                 /* map code to hash table entry */
165     } dict[1];
166 };
167
168 #define BSD_OVHD        2               /* BSD compress overhead/packet */
169 #define BSD_INIT_BITS   BSD_MIN_BITS
170
171 static void     *bsd_comp_alloc __P((u_char *options, int opt_len));
172 static void     *bsd_decomp_alloc __P((u_char *options, int opt_len));
173 static void     bsd_free __P((void *state));
174 static int      bsd_comp_init __P((void *state, u_char *options, int opt_len,
175                                    int unit, int hdrlen, int debug));
176 static int      bsd_decomp_init __P((void *state, u_char *options, int opt_len,
177                                      int unit, int hdrlen, int mru, int debug));
178 static int      bsd_compress __P((void *state, netbuf_t *mret,
179                                   netbuf_t mp, int slen, int maxolen));
180 static void     bsd_incomp __P((void *state, netbuf_t dmsg));
181 static int      bsd_decompress __P((void *state, netbuf_t cmp, netbuf_t *dmpp));
182 static void     bsd_reset __P((void *state));
183 static void     bsd_comp_stats __P((void *state, struct compstat *stats));
184
185 /*
186  * Procedures exported to if_ppp.c.
187  */
188 struct compressor ppp_bsd_compress = {
189     CI_BSD_COMPRESS,            /* compress_proto */
190     bsd_comp_alloc,             /* comp_alloc */
191     bsd_free,                   /* comp_free */
192     bsd_comp_init,              /* comp_init */
193     bsd_reset,                  /* comp_reset */
194     bsd_compress,               /* compress */
195     bsd_comp_stats,             /* comp_stat */
196     bsd_decomp_alloc,           /* decomp_alloc */
197     bsd_free,                   /* decomp_free */
198     bsd_decomp_init,            /* decomp_init */
199     bsd_reset,                  /* decomp_reset */
200     bsd_decompress,             /* decompress */
201     bsd_incomp,                 /* incomp */
202     bsd_comp_stats,             /* decomp_stat */
203 };
204
205 /*
206  * the next two codes should not be changed lightly, as they must not
207  * lie within the contiguous general code space.
208  */
209 #define CLEAR   256                     /* table clear output code */
210 #define FIRST   257                     /* first free entry */
211 #define LAST    255
212
213 #define MAXCODE(b)      ((1 << (b)) - 1)
214 #define BADCODEM1       MAXCODE(BSD_MAX_BITS)
215
216 #define BSD_HASH(prefix,suffix,hshift)  ((((u_int32_t)(suffix)) << (hshift)) \
217                                          ^ (u_int32_t)(prefix))
218 #define BSD_KEY(prefix,suffix)          ((((u_int32_t)(suffix)) << 16) \
219                                          + (u_int32_t)(prefix))
220
221 #define CHECK_GAP       10000           /* Ratio check interval */
222
223 #define RATIO_SCALE_LOG 8
224 #define RATIO_SCALE     (1<<RATIO_SCALE_LOG)
225 #define RATIO_MAX       (0x7fffffff>>RATIO_SCALE_LOG)
226
227 /* Could include inlines.h */
228 #ifndef IOLog
229 #define IOLog printf
230 #define IOLogDbg        if (db->debug) printf
231 #else
232 #define IOLogDbg        if (db->debug) IOLog
233 #endif
234
235 /*
236  * clear the dictionary
237  */
238 static void
239 bsd_clear(db)
240     struct bsd_db *db;
241 {
242     db->clear_count++;
243     db->max_ent = FIRST-1;
244     db->n_bits = BSD_INIT_BITS;
245     db->ratio = 0;
246     db->bytes_out = 0;
247     db->in_count = 0;
248     db->checkpoint = CHECK_GAP;
249 }
250
251 /*
252  * If the dictionary is full, then see if it is time to reset it.
253  *
254  * Compute the compression ratio using fixed-point arithmetic
255  * with 8 fractional bits.
256  *
257  * Since we have an infinite stream instead of a single file,
258  * watch only the local compression ratio.
259  *
260  * Since both peers must reset the dictionary at the same time even in
261  * the absence of CLEAR codes (while packets are incompressible), they
262  * must compute the same ratio.
263  */
264 static int                              /* 1=output CLEAR */
265 bsd_check(db)
266     struct bsd_db *db;
267 {
268     u_int new_ratio;
269
270     if (db->in_count >= db->checkpoint) {
271         /* age the ratio by limiting the size of the counts */
272         if (db->in_count >= RATIO_MAX
273             || db->bytes_out >= RATIO_MAX) {
274             db->in_count -= db->in_count/4;
275             db->bytes_out -= db->bytes_out/4;
276         }
277
278         db->checkpoint = db->in_count + CHECK_GAP;
279
280         if (db->max_ent >= db->maxmaxcode) {
281             /* Reset the dictionary only if the ratio is worse,
282              * or if it looks as if it has been poisoned
283              * by incompressible data.
284              *
285              * This does not overflow, because
286              *  db->in_count <= RATIO_MAX.
287              */
288             new_ratio = db->in_count << RATIO_SCALE_LOG;
289             if (db->bytes_out != 0)
290                 new_ratio /= db->bytes_out;
291
292             if (new_ratio < db->ratio || new_ratio < 1 * RATIO_SCALE) {
293                 bsd_clear(db);
294                 return 1;
295             }
296             db->ratio = new_ratio;
297         }
298     }
299     return 0;
300 }
301
302 /*
303  * Return statistics.
304  */
305 static void
306 bsd_comp_stats(state, stats)
307     void *state;
308     struct compstat *stats;
309 {
310     struct bsd_db *db = (struct bsd_db *) state;
311     u_int out;
312
313     stats->unc_bytes = db->uncomp_bytes;
314     stats->unc_packets = db->uncomp_count;
315     stats->comp_bytes = db->comp_bytes;
316     stats->comp_packets = db->comp_count;
317     stats->inc_bytes = db->incomp_bytes;
318     stats->inc_packets = db->incomp_count;
319     stats->ratio = db->in_count;
320     out = db->bytes_out;
321     if (stats->ratio <= 0x7fffff)
322       stats->ratio <<= 8;
323     else
324       out >>= 8;
325     if (out != 0)
326       stats->ratio /= out;
327 }
328
329 /*
330  * Reset state, as on a CCP ResetReq.
331  */
332 static void
333 bsd_reset(state)
334     void *state;
335 {
336     struct bsd_db *db = (struct bsd_db *) state;
337
338     db->seqno = 0;
339     bsd_clear(db);
340     db->clear_count = 0;
341 }
342
343 /*
344  * Allocate space for a (de) compressor.
345  */
346 static void *
347 bsd_alloc(options, opt_len, decomp)
348     u_char *options;
349     int opt_len, decomp;
350 {
351     int bits;
352     u_int newlen, hsize, hshift, maxmaxcode;
353     struct bsd_db *db;
354
355     if (opt_len != CILEN_BSD_COMPRESS || options[0] != CI_BSD_COMPRESS
356         || options[1] != CILEN_BSD_COMPRESS
357         || BSD_VERSION(options[2]) != BSD_CURRENT_VERSION)
358         return NULL;
359     bits = BSD_NBITS(options[2]);
360     switch (bits) {
361     case 9:                     /* needs 82152 for both directions */
362     case 10:                    /* needs 84144 */
363     case 11:                    /* needs 88240 */
364     case 12:                    /* needs 96432 */
365         hsize = 5003;
366         hshift = 4;
367         break;
368     case 13:                    /* needs 176784 */
369         hsize = 9001;
370         hshift = 5;
371         break;
372     case 14:                    /* needs 353744 */
373         hsize = 18013;
374         hshift = 6;
375         break;
376     case 15:                    /* needs 691440 */
377         hsize = 35023;
378         hshift = 7;
379         break;
380     case 16:                    /* needs 1366160--far too much, */
381         /* hsize = 69001; */    /* and 69001 is too big for cptr */
382         /* hshift = 8; */       /* in struct bsd_db */
383         /* break; */
384     default:
385         return NULL;
386     }
387
388     maxmaxcode = MAXCODE(bits);
389     newlen = sizeof(*db) + (hsize-1) * (sizeof(db->dict[0]));
390     {
391     unsigned long kret;
392     kret = (unsigned long) kalloc(Z_EXTRA + newlen);
393     if (!kret)
394         return NULL;
395     db = (struct bsd_db *) ALIGN(kret);
396     bzero(db, sizeof(*db) - sizeof(db->dict));
397     db->kbase = (void *)kret;
398     }
399
400     if (!decomp) {
401         db->lens = NULL;
402     } else {
403         unsigned long kret;
404         kret = (unsigned long) kalloc(Z_EXTRA +
405                                ((maxmaxcode+1) * sizeof(db->lens[0])));
406         if (!kret) {
407             kfree(db->kbase, newlen + Z_EXTRA);
408             return NULL;
409         }
410         db->lens = (u_int16_t *) ALIGN(kret);
411         db->klens = (void *) kret;
412     }
413
414     db->totlen = newlen;
415     db->hsize = hsize;
416     db->hshift = hshift;
417     db->maxmaxcode = maxmaxcode;
418     db->maxbits = bits;
419
420     return (void *) db;
421 }
422
423 static void
424 bsd_free(state)
425     void *state;
426 {
427     struct bsd_db *db = (struct bsd_db *) state;
428
429     if (db->lens)
430         kfree(db->klens, ((db->maxmaxcode+1) * sizeof(db->lens[0])) + Z_EXTRA);
431     kfree(db->kbase, db->totlen + Z_EXTRA);
432 }
433
434 static void *
435 bsd_comp_alloc(options, opt_len)
436     u_char *options;
437     int opt_len;
438 {
439     return bsd_alloc(options, opt_len, 0);
440 }
441
442 static void *
443 bsd_decomp_alloc(options, opt_len)
444     u_char *options;
445     int opt_len;
446 {
447     return bsd_alloc(options, opt_len, 1);
448 }
449
450 /*
451  * Initialize the database.
452  */
453 static int
454 bsd_init(db, options, opt_len, unit, hdrlen, mru, debug, decomp)
455     struct bsd_db *db;
456     u_char *options;
457     int opt_len, unit, hdrlen, mru, debug, decomp;
458 {
459     int i;
460
461     if (opt_len < CILEN_BSD_COMPRESS || options[0] != CI_BSD_COMPRESS
462         || options[1] != CILEN_BSD_COMPRESS
463         || BSD_VERSION(options[2]) != BSD_CURRENT_VERSION
464         || BSD_NBITS(options[2]) != db->maxbits
465         || decomp && db->lens == NULL)
466         return 0;
467
468     if (decomp) {
469         i = LAST+1;
470         while (i != 0)
471             db->lens[--i] = 1;
472     }
473     i = db->hsize;
474     while (i != 0) {
475         db->dict[--i].codem1 = BADCODEM1;
476         db->dict[i].cptr = 0;
477     }
478
479     db->unit = unit;
480     db->hdrlen = hdrlen;
481     db->mru = mru;
482 #ifndef DEBUG
483     if (debug)
484 #endif
485         db->debug = 1;
486
487     bsd_reset(db);
488
489     return 1;
490 }
491
492 static int
493 bsd_comp_init(state, options, opt_len, unit, hdrlen, debug)
494     void *state;
495     u_char *options;
496     int opt_len, unit, hdrlen, debug;
497 {
498     return bsd_init((struct bsd_db *) state, options, opt_len,
499                     unit, hdrlen, 0, debug, 0);
500 }
501
502 static int
503 bsd_decomp_init(state, options, opt_len, unit, hdrlen, mru, debug)
504     void *state;
505     u_char *options;
506     int opt_len, unit, hdrlen, mru, debug;
507 {
508     return bsd_init((struct bsd_db *) state, options, opt_len,
509                     unit, hdrlen, mru, debug, 1);
510 }
511
512
513 /*
514  * compress a packet
515  *      One change from the BSD compress command is that when the
516  *      code size expands, we do not output a bunch of padding.
517  */
518 int                                     /* new slen */
519 bsd_compress(state, mret, mp, slen, maxolen)
520     void *state;
521     netbuf_t *mret;             /* return compressed netbuf here */
522     netbuf_t mp;                /* from here */
523     int slen;                   /* uncompressed length */
524     int maxolen;                /* max compressed length */
525 {
526     struct bsd_db *db = (struct bsd_db *) state;
527     int hshift = db->hshift;
528     u_int max_ent = db->max_ent;
529     u_int n_bits = db->n_bits;
530     u_int bitno = 32;
531     u_int32_t accm = 0, fcode;
532     struct bsd_dict *dictp;
533     u_char c;
534     int hval, disp, ent, ilen;
535     u_char *rptr, *wptr;
536     u_char *cp_end;
537     int olen;
538     netbuf_t m;
539
540 #define PUTBYTE(v) {                                    \
541     ++olen;                                             \
542     if (wptr) {                                         \
543         *wptr++ = (v);                                  \
544         if (wptr >= cp_end)                             \
545             wptr = NULL;                                \
546     }                                                   \
547 }
548
549 #define OUTPUT(ent) {                                   \
550     bitno -= n_bits;                                    \
551     accm |= ((ent) << bitno);                           \
552     do {                                                \
553         PUTBYTE(accm >> 24);                            \
554         accm <<= 8;                                     \
555         bitno += 8;                                     \
556     } while (bitno <= 24);                              \
557 }
558
559     /*
560      * If the protocol is not in the range we're interested in,
561      * just return without compressing the packet.  If it is,
562      * the protocol becomes the first byte to compress.
563      */
564     rptr = mtod(mp, u_char *);
565     ent = PPP_PROTOCOL(rptr);
566     if (ent < CI_BSD_COMPRESS || ent > 0xf9) {
567         *mret = NULL;
568         return slen;
569     }
570
571     /* Don't generate compressed packets which are larger than
572        the uncompressed packet. */
573     if (maxolen > slen)
574         maxolen = slen;
575
576     /* Allocate one mbuf to start with. (don't forget space for the FCS!) */
577     m = ppp_nb_alloc(maxolen + db->hdrlen + PPP_FCSLEN);
578     *mret = m;
579     if (m != NULL) {
580       if (db->hdrlen > 0)
581         ppp_nb_shrink_top(m, db->hdrlen);
582       nb_shrink_bot(m, PPP_FCSLEN);  /* grown by pppstart() */
583         wptr = mtod(m, u_char *);
584         cp_end = wptr + maxolen;
585     } else
586         wptr = cp_end = NULL;
587
588     /*
589      * Copy the PPP header over, changing the protocol,
590      * and install the 2-byte packet sequence number.
591      */
592     if (wptr) {
593         *wptr++ = PPP_ADDRESS(rptr);    /* assumes the ppp header is */
594         *wptr++ = PPP_CONTROL(rptr);    /* all in one mbuf */
595         *wptr++ = 0;                    /* change the protocol */
596         *wptr++ = PPP_COMP;
597         *wptr++ = db->seqno >> 8;
598         *wptr++ = db->seqno;
599     }
600     ++db->seqno;
601
602     olen = 0;
603     rptr += PPP_HDRLEN;
604     slen = nb_size(mp) - PPP_HDRLEN;
605     ilen = slen + 1;
606     while (slen > 0) {
607         slen--;
608         c = *rptr++;
609         fcode = BSD_KEY(ent, c);
610         hval = BSD_HASH(ent, c, hshift);
611         dictp = &db->dict[hval];
612
613         /* Validate and then check the entry. */
614         if (dictp->codem1 >= max_ent)
615             goto nomatch;
616         if (dictp->f.fcode == fcode) {
617             ent = dictp->codem1+1;
618             continue;   /* found (prefix,suffix) */
619         }
620
621         /* continue probing until a match or invalid entry */
622         disp = (hval == 0) ? 1 : hval;
623         do {
624             hval += disp;
625             if (hval >= db->hsize)
626                 hval -= db->hsize;
627             dictp = &db->dict[hval];
628             if (dictp->codem1 >= max_ent)
629                 goto nomatch;
630         } while (dictp->f.fcode != fcode);
631         ent = dictp->codem1 + 1;        /* finally found (prefix,suffix) */
632         continue;
633
634     nomatch:
635         OUTPUT(ent);            /* output the prefix */
636
637         /* code -> hashtable */
638         if (max_ent < db->maxmaxcode) {
639             struct bsd_dict *dictp2;
640             /* expand code size if needed */
641             if (max_ent >= MAXCODE(n_bits))
642                 db->n_bits = ++n_bits;
643
644             /* Invalidate old hash table entry using
645              * this code, and then take it over.
646              */
647             dictp2 = &db->dict[max_ent+1];
648             if (db->dict[dictp2->cptr].codem1 == max_ent)
649                 db->dict[dictp2->cptr].codem1 = BADCODEM1;
650             dictp2->cptr = hval;
651             dictp->codem1 = max_ent;
652             dictp->f.fcode = fcode;
653
654             db->max_ent = ++max_ent;
655         }
656         ent = c;
657     }
658
659     OUTPUT(ent);                /* output the last code */
660     db->bytes_out += olen;
661     db->in_count += ilen;
662     if (bitno < 32)
663         ++db->bytes_out;        /* count complete bytes */
664
665     if (bsd_check(db))
666         OUTPUT(CLEAR);          /* do not count the CLEAR */
667
668     /*
669      * Pad dribble bits of last code with ones.
670      * Do not emit a completely useless byte of ones.
671      */
672     if (bitno != 32)
673         PUTBYTE((accm | (0xff << (bitno-8))) >> 24);
674
675     /*
676      * Increase code size if we would have without the packet
677      * boundary and as the decompressor will.
678      */
679     if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode)
680         db->n_bits++;
681
682     db->uncomp_bytes += ilen;
683     ++db->uncomp_count;
684     if (olen + PPP_HDRLEN + BSD_OVHD > maxolen || wptr == NULL) {
685         /* throw away the compressed stuff if it is longer than uncompressed */
686         if (*mret != NULL) {
687             nb_free(*mret);
688             *mret = NULL;
689         }
690         ++db->incomp_count;
691         db->incomp_bytes += ilen;
692     } else {
693         nb_shrink_bot(m, nb_size(m) - (wptr - mtod(m, u_char *)));
694         ++db->comp_count;
695         db->comp_bytes += olen + BSD_OVHD;
696     }
697
698     return olen + PPP_HDRLEN + BSD_OVHD;
699 #undef OUTPUT
700 #undef PUTBYTE
701 }
702
703
704 /*
705  * Update the "BSD Compress" dictionary on the receiver for
706  * incompressible data by pretending to compress the incoming data.
707  */
708 static void
709 bsd_incomp(state, dmsg)
710     void *state;
711     netbuf_t dmsg;
712 {
713     struct bsd_db *db = (struct bsd_db *) state;
714     u_int hshift = db->hshift;
715     u_int max_ent = db->max_ent;
716     u_int n_bits = db->n_bits;
717     struct bsd_dict *dictp;
718     u_int32_t fcode;
719     u_char c;
720     u_int32_t hval, disp;
721     int slen, ilen;
722     u_int bitno = 7;
723     u_char *rptr;
724     u_int ent;
725
726     /*
727      * If the protocol is not in the range we're interested in,
728      * just return without looking at the packet.  If it is,
729      * the protocol becomes the first byte to "compress".
730      */
731     rptr = mtod(dmsg, u_char *);
732     ent = PPP_PROTOCOL(rptr);
733     if (ent < CI_BSD_COMPRESS || ent > 0xf9)
734         return;
735
736     db->seqno++;
737     ilen = 1;           /* count the protocol as 1 byte */
738     rptr += PPP_HDRLEN;
739     slen = nb_size(dmsg) - PPP_HDRLEN;
740     ilen += slen;
741
742     do {
743         c = *rptr++;
744         fcode = BSD_KEY(ent, c);
745         hval = BSD_HASH(ent, c, hshift);
746         dictp = &db->dict[hval];
747
748         /* validate and then check the entry */
749         if (dictp->codem1 >= max_ent)
750             goto nomatch;
751         if (dictp->f.fcode == fcode) {
752             ent = dictp->codem1+1;
753             continue;   /* found (prefix,suffix) */
754         }
755
756         /* continue probing until a match or invalid entry */
757         disp = (hval == 0) ? 1 : hval;
758         do {
759             hval += disp;
760             if (hval >= db->hsize)
761                 hval -= db->hsize;
762             dictp = &db->dict[hval];
763             if (dictp->codem1 >= max_ent)
764                 goto nomatch;
765         } while (dictp->f.fcode != fcode);
766         ent = dictp->codem1+1;
767         continue;       /* finally found (prefix,suffix) */
768
769     nomatch:            /* output (count) the prefix */
770         bitno += n_bits;
771
772         /* code -> hashtable */
773         if (max_ent < db->maxmaxcode) {
774             struct bsd_dict *dictp2;
775             /* expand code size if needed */
776             if (max_ent >= MAXCODE(n_bits))
777                 db->n_bits = ++n_bits;
778
779             /* Invalidate previous hash table entry
780              * assigned this code, and then take it over.
781              */
782             dictp2 = &db->dict[max_ent+1];
783             if (db->dict[dictp2->cptr].codem1 == max_ent)
784                 db->dict[dictp2->cptr].codem1 = BADCODEM1;
785             dictp2->cptr = hval;
786             dictp->codem1 = max_ent;
787             dictp->f.fcode = fcode;
788
789             db->max_ent = ++max_ent;
790             db->lens[max_ent] = db->lens[ent]+1;
791         }
792         ent = c;
793     } while (--slen != 0);
794     bitno += n_bits;            /* output (count) the last code */
795     db->bytes_out += bitno/8;
796     db->in_count += ilen;
797     (void)bsd_check(db);
798
799     ++db->incomp_count;
800     db->incomp_bytes += ilen;
801     ++db->uncomp_count;
802     db->uncomp_bytes += ilen;
803
804     /* Increase code size if we would have without the packet
805      * boundary and as the decompressor will.
806      */
807     if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode)
808         db->n_bits++;
809 }
810
811
812 /*
813  * Decompress "BSD Compress".
814  *
815  * Because of patent problems, we return DECOMP_ERROR for errors
816  * found by inspecting the input data and for system problems, but
817  * DECOMP_FATALERROR for any errors which could possibly be said to
818  * be being detected "after" decompression.  For DECOMP_ERROR,
819  * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
820  * infringing a patent of Motorola's if we do, so we take CCP down
821  * instead.
822  *
823  * Given that the frame has the correct sequence number and a good FCS,
824  * errors such as invalid codes in the input most likely indicate a
825  * bug, so we return DECOMP_FATALERROR for them in order to turn off
826  * compression, even though they are detected by inspecting the input.
827  */
828 int
829 bsd_decompress(state, cmp, dmpp)
830     void *state;
831     netbuf_t cmp, *dmpp;
832 {
833     struct bsd_db *db = (struct bsd_db *) state;
834     u_int max_ent = db->max_ent;
835     u_int32_t accm = 0;
836     u_int bitno = 32;           /* 1st valid bit in accm */
837     u_int n_bits = db->n_bits;
838     u_int tgtbitno = 32-n_bits; /* bitno when we have a code */
839     struct bsd_dict *dictp;
840     int explen, seq, len;
841     u_int incode, oldcode, finchar;
842     u_char *p, *rptr, *wptr;
843     netbuf_t dmp, mret;
844     int adrs, ctrl, ilen;
845     int space, codelen, extra, maxilen;
846
847     /*
848      * Save the address/control from the PPP header
849      * and then get the sequence number.
850      */
851     *dmpp = NULL;
852     rptr = mtod(cmp, u_char *);
853     adrs = PPP_ADDRESS(rptr);
854     ctrl = PPP_CONTROL(rptr);
855     rptr += PPP_HDRLEN;
856     len = nb_size(cmp) - PPP_HDRLEN;
857     seq = (rptr[0] << 8) + rptr[1];
858     rptr += BSD_OVHD;
859     len -= BSD_OVHD;
860
861     /*
862      * Check the sequence number and give up if it differs from
863      * the value we're expecting.
864      */
865     if (seq != db->seqno) {
866         IOLogDbg("bsd_decomp%d: bad sequence # %d, expected %d\n",
867                    db->unit, seq, db->seqno - 1);
868         return DECOMP_ERROR;
869     }
870     ++db->seqno;
871
872     /*
873      * Allocate an netbuf large enough for all the data.
874      */
875     maxilen = db->mru + db->hdrlen + PPP_HDRLEN;        /* no FCS */
876     dmp = ppp_nb_alloc(maxilen);                        /* XXX */
877     if (dmp == NULL)
878         return DECOMP_ERROR;
879     if (db->hdrlen > 0)
880         ppp_nb_shrink_top(dmp, db->hdrlen);
881     mret = dmp;
882     wptr = mtod(dmp, u_char *);
883     space = nb_size(dmp) - PPP_HDRLEN + 1;
884
885     /*
886      * Fill in the ppp header, but not the last byte of the protocol
887      * (that comes from the decompressed data).
888      */
889     wptr[0] = adrs;
890     wptr[1] = ctrl;
891     wptr[2] = 0;
892     wptr += PPP_HDRLEN - 1;
893
894     ilen = len;
895     oldcode = CLEAR;
896     explen = 0;
897     while (len > 0) {
898         /*
899          * Accumulate bytes until we have a complete code.
900          * Then get the next code, relying on the 32-bit,
901          * unsigned accm to mask the result.
902          */
903         bitno -= 8;
904         accm |= *rptr++ << bitno;
905         --len;
906         if (tgtbitno < bitno)
907             continue;
908         incode = accm >> tgtbitno;
909         accm <<= n_bits;
910         bitno += n_bits;
911
912         if (incode == CLEAR) {
913             /*
914              * The dictionary must only be cleared at
915              * the end of a packet.  But there could be an
916              * empty mbuf at the end.
917              */
918             if (len > 0) {
919                 nb_free(mret);
920                 IOLogDbg("bsd_decomp%d: bad CLEAR\n", db->unit);
921                 return DECOMP_FATALERROR;       /* probably a bug */
922             }
923             bsd_clear(db);
924             explen = ilen = 0;
925             break;
926         }
927
928         if (incode > max_ent + 2 || incode > db->maxmaxcode
929             || incode > max_ent && oldcode == CLEAR) {
930             nb_free(mret);
931             IOLogDbg("bsd_decomp%d: bad code 0x%x oldcode=0x%x max_ent=0x%x explen=%d seqno=%d\n",
932                      db->unit, incode, oldcode, max_ent, explen, db->seqno);
933             return DECOMP_FATALERROR;   /* probably a bug */
934         }
935
936         /* Special case for KwKwK string. */
937         if (incode > max_ent) {
938             finchar = oldcode;
939             extra = 1;
940         } else {
941             finchar = incode;
942             extra = 0;
943         }
944
945         codelen = db->lens[finchar];
946         explen += codelen + extra;
947         if (explen > db->mru + 1) {
948             nb_free(mret);
949             IOLogDbg("bsd_decomp%d: ran out of mru\n  len=%d, finchar=0x%x, codelen=%d, explen=%d\n",
950                        db->unit, len, finchar, codelen, explen);
951             return DECOMP_FATALERROR;
952         }
953
954         /*
955          * If we have no space left, then we've overflowed...
956          */
957         if ((space -= codelen + extra) < 0) {
958             IOLog("bsd_decompress%d: no space left in netbuf (need %d bytes)\n",
959                   db->unit, (codelen + extra) - space);
960             nb_free(mret);
961             return DECOMP_ERROR;
962         }
963
964         /*
965          * Decode this code and install it in the decompressed buffer.
966          */
967         p = (wptr += codelen);
968         while (finchar > LAST) {
969             dictp = &db->dict[db->dict[finchar].cptr];
970 #ifdef DEBUG
971             if (--codelen <= 0 || dictp->codem1 != finchar-1)
972                 goto bad;
973 #endif
974             *--p = dictp->f.hs.suffix;
975             finchar = dictp->f.hs.prefix;
976         }
977         *--p = finchar;
978
979 #ifdef DEBUG
980         if (--codelen != 0)
981             IOLog("bsd_decomp%d: short by %d after code 0x%x, max_ent=0x%x\n",
982                    db->unit, codelen, incode, max_ent);
983 #endif
984
985         if (extra)              /* the KwKwK case again */
986             *wptr++ = finchar;
987
988         /*
989          * If not first code in a packet, and
990          * if not out of code space, then allocate a new code.
991          *
992          * Keep the hash table correct so it can be used
993          * with uncompressed packets.
994          */
995         if (oldcode != CLEAR && max_ent < db->maxmaxcode) {
996             struct bsd_dict *dictp2;
997             u_int32_t fcode;
998             u_int32_t hval, disp;
999
1000             fcode = BSD_KEY(oldcode,finchar);
1001             hval = BSD_HASH(oldcode,finchar,db->hshift);
1002             dictp = &db->dict[hval];
1003
1004             /* look for a free hash table entry */
1005             if (dictp->codem1 < max_ent) {
1006                 disp = (hval == 0) ? 1 : hval;
1007                 do {
1008                     hval += disp;
1009                     if (hval >= db->hsize)
1010                         hval -= db->hsize;
1011                     dictp = &db->dict[hval];
1012                 } while (dictp->codem1 < max_ent);
1013             }
1014
1015             /*
1016              * Invalidate previous hash table entry
1017              * assigned this code, and then take it over
1018              */
1019             dictp2 = &db->dict[max_ent+1];
1020             if (db->dict[dictp2->cptr].codem1 == max_ent) {
1021                 db->dict[dictp2->cptr].codem1 = BADCODEM1;
1022             }
1023             dictp2->cptr = hval;
1024             dictp->codem1 = max_ent;
1025             dictp->f.fcode = fcode;
1026
1027             db->max_ent = ++max_ent;
1028             db->lens[max_ent] = db->lens[oldcode]+1;
1029
1030             /* Expand code size if needed. */
1031             if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode) {
1032                 db->n_bits = ++n_bits;
1033                 tgtbitno = 32-n_bits;
1034             }
1035         }
1036         oldcode = incode;
1037     }
1038     nb_shrink_bot(dmp, nb_size(dmp) - (wptr - mtod(dmp, u_char *)));
1039
1040     /*
1041      * Keep the checkpoint right so that incompressible packets
1042      * clear the dictionary at the right times.
1043      */
1044     db->bytes_out += ilen;
1045     db->in_count += explen;
1046     if (bsd_check(db)) {
1047         IOLogDbg("bsd_decomp%d: peer should have cleared dictionary\n",
1048                db->unit);
1049     }
1050
1051     ++db->comp_count;
1052     db->comp_bytes += ilen + BSD_OVHD;
1053     ++db->uncomp_count;
1054     db->uncomp_bytes += explen;
1055
1056     *dmpp = mret;
1057     return DECOMP_OK;
1058
1059 #ifdef DEBUG
1060  bad:
1061     if (codelen <= 0) {
1062         IOLog("bsd_decomp%d: fell off end of chain 0x%x at 0x%x by 0x%x, max_ent=0x%x\n",
1063               db->unit, incode, finchar, db->dict[finchar].cptr, max_ent);
1064     } else if (dictp->codem1 != finchar-1) {
1065         IOLog("bsd_decomp%d: bad code chain 0x%x finchar=0x%x oldcode=0x%x cptr=0x%x codem1=0x%x\n",
1066               db->unit, incode, finchar, oldcode, db->dict[finchar].cptr,
1067               dictp->codem1);
1068     }
1069     nb_free(mret);
1070     return DECOMP_FATALERROR;
1071 #endif /* DEBUG */
1072 }
1073 #endif /* DO_BSD_COMPRESS */