root/net/bsd-comp.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. bsd_clear
  2. bsd_check
  3. bsd_comp_stats
  4. bsd_reset
  5. bsd_alloc
  6. bsd_free
  7. bsd_comp_alloc
  8. bsd_decomp_alloc
  9. bsd_init
  10. bsd_comp_init
  11. bsd_decomp_init
  12. bsd_compress
  13. bsd_incomp
  14. bsd_decompress

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

/* [<][>][^][v][top][bottom][index][help] */