The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/net/bsd_comp.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: d71d1dc58162fd7c7d0872794bd0723c


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.