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