root/drivers/net/bsd_comp.c

/* [previous][next][first][last][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_free
  6. bsd_alloc
  7. bsd_comp_alloc
  8. bsd_decomp_alloc
  9. bsd_init
  10. bsd_comp_init
  11. bsd_decomp_init
  12. lens_ptr
  13. dict_ptr
  14. bsd_compress
  15. bsd_incomp
  16. bsd_decompress
  17. init_module
  18. cleanup_module

   1 /* Because this code is derived from the 4.3BSD compress source:
   2  *
   3  * Copyright (c) 1985, 1986 The Regents of the University of California.
   4  * All rights reserved.
   5  *
   6  * This code is derived from software contributed to Berkeley by
   7  * James A. Woods, derived from original work by Spencer Thomas
   8  * and Joseph Orost.
   9  *
  10  * Redistribution and use in source and binary forms, with or without
  11  * modification, are permitted provided that the following conditions
  12  * are met:
  13  * 1. Redistributions of source code must retain the above copyright
  14  *    notice, this list of conditions and the following disclaimer.
  15  * 2. Redistributions in binary form must reproduce the above copyright
  16  *    notice, this list of conditions and the following disclaimer in the
  17  *    documentation and/or other materials provided with the distribution.
  18  * 3. All advertising materials mentioning features or use of this software
  19  *    must display the following acknowledgement:
  20  *      This product includes software developed by the University of
  21  *      California, Berkeley and its contributors.
  22  * 4. 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 contigious buffers on Linux-derived systems.
  41  *
  42  *  ==FILEVERSION 4==
  43  *
  44  *  NOTE TO MAINTAINERS:
  45  *     If you modify this file at all, increment the number above.
  46  *     bsd_comp.c is shipped with a PPP distribution as well as with
  47  *     the kernel; if everyone increases the FILEVERSION number above,
  48  *     then scripts can do the right thing when deciding whether to
  49  *     install a new bsd_comp.c file. Don't change the format of that
  50  *     line otherwise, so the installation script can recognize it.
  51  *
  52  * $Id: bsd_comp.c,v 1.1 1994/12/08 01:59:58 paulus Exp $
  53  */
  54 
  55 #ifndef MODULE
  56 #error This file must be compiled as a module.
  57 #endif
  58 
  59 #include <linux/module.h>
  60 
  61 #include <endian.h>
  62 #include <linux/kernel.h>
  63 #include <linux/sched.h>
  64 #include <linux/types.h>
  65 #include <linux/fcntl.h>
  66 #include <linux/interrupt.h>
  67 #include <linux/ptrace.h>
  68 #include <linux/ioport.h>
  69 #include <linux/in.h>
  70 #include <linux/malloc.h>
  71 #include <linux/tty.h>
  72 #include <linux/errno.h>
  73 #include <linux/sched.h>        /* to get the struct task_struct */
  74 #include <linux/string.h>       /* used in new tty drivers */
  75 #include <linux/signal.h>       /* used in new tty drivers */
  76 
  77 #include <asm/system.h>
  78 #include <asm/bitops.h>
  79 #include <asm/segment.h>
  80 
  81 #include <net/if.h>
  82 
  83 #include <linux/if_ether.h>
  84 #include <linux/netdevice.h>
  85 #include <linux/skbuff.h>
  86 #include <linux/inet.h>
  87 #include <linux/ioctl.h>
  88 
  89 #include <linux/ppp_defs.h>
  90 
  91 #ifdef NEW_SKBUFF
  92 #include <linux/netprotocol.h>
  93 #endif
  94 
  95 #include <netinet/ip.h>
  96 #include <netinet/tcp.h>
  97 #include <net/if_arp.h>
  98 
  99 #undef   PACKETPTR
 100 #define  PACKETPTR 1
 101 #include <linux/ppp-comp.h>
 102 #undef   PACKETPTR
 103 
 104 /*
 105  * PPP "BSD compress" compression
 106  *  The differences between this compression and the classic BSD LZW
 107  *  source are obvious from the requirement that the classic code worked
 108  *  with files while this handles arbitrarily long streams that
 109  *  are broken into packets.  They are:
 110  *
 111  *      When the code size expands, a block of junk is not emitted by
 112  *          the compressor and not expected by the decompressor.
 113  *
 114  *      New codes are not necessarily assigned every time an old
 115  *          code is output by the compressor.  This is because a packet
 116  *          end forces a code to be emitted, but does not imply that a
 117  *          new sequence has been seen.
 118  *
 119  *      The compression ratio is checked at the first end of a packet
 120  *          after the appropriate gap.  Besides simplifying and speeding
 121  *          things up, this makes it more likely that the transmitter
 122  *          and receiver will agree when the dictionary is cleared when
 123  *          compression is not going well.
 124  */
 125 
 126 /*
 127  * Macros to extract protocol version and number of bits
 128  * from the third byte of the BSD Compress CCP configuration option.
 129  */
 130 
 131 #define BSD_VERSION(x)  ((x) >> 5)
 132 #define BSD_NBITS(x)    ((x) & 0x1F)
 133 
 134 #define BSD_CURRENT_VERSION     1
 135 
 136 /*
 137  * A dictionary for doing BSD compress.
 138  */
 139 
 140 struct bsd_dict {
 141     union {                             /* hash value */
 142         unsigned long   fcode;
 143         struct {
 144 #ifndef BIG_ENDIAN_BITFIELD /* Little endian order */
 145             unsigned short      prefix; /* preceding code */
 146             unsigned char       suffix; /* last character of new code */
 147             unsigned char       pad;
 148 #else /* Big endian order */
 149             unsigned char       pad;
 150             unsigned char       suffix; /* last character of new code */
 151             unsigned short      prefix; /* preceding code */
 152 #endif
 153         } hs;
 154     } f;
 155     unsigned short codem1;              /* output of hash table -1 */
 156     unsigned short cptr;                /* map code to hash table entry */
 157 };
 158 
 159 struct bsd_db {
 160     int     totlen;                     /* length of this structure */
 161     unsigned int   hsize;               /* size of the hash table */
 162     unsigned char  hshift;              /* used in hash function */
 163     unsigned char  n_bits;              /* current bits/code */
 164     unsigned char  maxbits;             /* maximum bits/code */
 165     unsigned char  debug;               /* non-zero if debug desired */
 166     unsigned char  unit;                /* ppp unit number */
 167     unsigned short seqno;               /* sequence # of next packet */
 168     unsigned int   mru;                 /* size of receive (decompress) bufr */
 169     unsigned int   maxmaxcode;          /* largest valid code */
 170     unsigned int   max_ent;             /* largest code in use */
 171     unsigned int   in_count;            /* uncompressed bytes, aged */
 172     unsigned int   bytes_out;           /* compressed bytes, aged */
 173     unsigned int   ratio;               /* recent compression ratio */
 174     unsigned int   checkpoint;          /* when to next check the ratio */
 175     unsigned int   clear_count;         /* times dictionary cleared */
 176     unsigned int   incomp_count;        /* incompressible packets */
 177     unsigned int   incomp_bytes;        /* incompressible bytes */
 178     unsigned int   uncomp_count;        /* uncompressed packets */
 179     unsigned int   uncomp_bytes;        /* uncompressed bytes */
 180     unsigned int   comp_count;          /* compressed packets */
 181     unsigned int   comp_bytes;          /* compressed bytes */
 182     unsigned short  *lens;              /* array of lengths of codes */
 183     struct bsd_dict *dict;              /* dictionary */
 184 };
 185 
 186 #define BSD_OVHD        2               /* BSD compress overhead/packet */
 187 #define MIN_BSD_BITS    9
 188 #define BSD_INIT_BITS   MIN_BSD_BITS
 189 #define MAX_BSD_BITS    15
 190 
 191 static void     bsd_free (void *state);
 192 static void     *bsd_alloc(unsigned char *options, int opt_len, int decomp);
 193 static void     *bsd_comp_alloc (unsigned char *options, int opt_len);
 194 static void     *bsd_decomp_alloc (unsigned char *options, int opt_len);
 195 
 196 static int      bsd_init        (void *db, unsigned char *options,
 197                                  int opt_len, int unit, int debug, int decomp);
 198 static int      bsd_comp_init   (void *state, unsigned char *options,
 199                                  int opt_len, int unit, int opthdr, int debug);
 200 static int      bsd_decomp_init (void *state, unsigned char *options,
 201                                  int opt_len, int unit, int opthdr, int mru,
 202                                  int debug);
 203 
 204 static void     bsd_reset (void *state);
 205 static void     bsd_comp_stats (void *state, struct compstat *stats);
 206 
 207 static int      bsd_compress (void *state, unsigned char *rptr,
 208                               unsigned char *obuf, int isize, int osize);
 209 static void     bsd_incomp (void *state, unsigned char *ibuf, int icnt);
 210 
 211 static int      bsd_decompress (void *state, unsigned char *ibuf, int isize,
 212                                 unsigned char *obuf, int osize);
 213 
 214 /* These are in ppp.c */
 215 extern int  ppp_register_compressor   (struct compressor *cp);
 216 extern void ppp_unregister_compressor (struct compressor *cp);
 217 
 218 /*
 219  * the next two codes should not be changed lightly, as they must not
 220  * lie within the contiguous general code space.
 221  */
 222 #define CLEAR   256                     /* table clear output code */
 223 #define FIRST   257                     /* first free entry */
 224 #define LAST    255
 225 
 226 #define MAXCODE(b)      ((1 << (b)) - 1)
 227 #define BADCODEM1       MAXCODE(MAX_BSD_BITS);
 228 
 229 #define BSD_HASH(prefix,suffix,hshift) ((((unsigned long)(suffix))<<(hshift)) \
 230                                          ^ (unsigned long)(prefix))
 231 #define BSD_KEY(prefix,suffix)          ((((unsigned long)(suffix)) << 16) \
 232                                          + (unsigned long)(prefix))
 233 
 234 #define CHECK_GAP       10000           /* Ratio check interval */
 235 
 236 #define RATIO_SCALE_LOG 8
 237 #define RATIO_SCALE     (1<<RATIO_SCALE_LOG)
 238 #define RATIO_MAX       (0x7fffffff>>RATIO_SCALE_LOG)
 239 
 240 /*
 241  * clear the dictionary
 242  */
 243 
 244 static void
 245 bsd_clear(struct bsd_db *db)
     /* [previous][next][first][last][top][bottom][index][help] */
 246 {
 247     db->clear_count++;
 248     db->max_ent      = FIRST-1;
 249     db->n_bits       = BSD_INIT_BITS;
 250     db->bytes_out    = 0;
 251     db->in_count     = 0;
 252     db->incomp_count = 0;
 253     db->ratio        = 0;
 254     db->checkpoint   = CHECK_GAP;
 255 }
 256 
 257 /*
 258  * If the dictionary is full, then see if it is time to reset it.
 259  *
 260  * Compute the compression ratio using fixed-point arithmetic
 261  * with 8 fractional bits.
 262  *
 263  * Since we have an infinite stream instead of a single file,
 264  * watch only the local compression ratio.
 265  *
 266  * Since both peers must reset the dictionary at the same time even in
 267  * the absence of CLEAR codes (while packets are incompressible), they
 268  * must compute the same ratio.
 269  */
 270 
 271 static int bsd_check (struct bsd_db *db)        /* 1=output CLEAR */
     /* [previous][next][first][last][top][bottom][index][help] */
 272   {
 273     unsigned int new_ratio;
 274 
 275     if (db->in_count >= db->checkpoint)
 276       {
 277         /* age the ratio by limiting the size of the counts */
 278         if (db->in_count >= RATIO_MAX || db->bytes_out >= RATIO_MAX)
 279           {
 280             db->in_count  -= (db->in_count  >> 2);
 281             db->bytes_out -= (db->bytes_out >> 2);
 282           }
 283         
 284         db->checkpoint = db->in_count + CHECK_GAP;
 285         
 286         if (db->max_ent >= db->maxmaxcode)
 287           {
 288             /* Reset the dictionary only if the ratio is worse,
 289              * or if it looks as if it has been poisoned
 290              * by incompressible data.
 291              *
 292              * This does not overflow, because
 293              *  db->in_count <= RATIO_MAX.
 294              */
 295 
 296             new_ratio = db->in_count << RATIO_SCALE_LOG;
 297             if (db->bytes_out != 0)
 298               {
 299                 new_ratio /= db->bytes_out;
 300               }
 301             
 302             if (new_ratio < db->ratio || new_ratio < 1 * RATIO_SCALE)
 303               {
 304                 bsd_clear (db);
 305                 return 1;
 306               }
 307             db->ratio = new_ratio;
 308           }
 309       }
 310     return 0;
 311   }
 312 
 313 /*
 314  * Return statistics.
 315  */
 316 
 317 static void bsd_comp_stats (void *state, struct compstat *stats)
     /* [previous][next][first][last][top][bottom][index][help] */
 318   {
 319     struct bsd_db *db = (struct bsd_db *) state;
 320     
 321     stats->unc_bytes    = db->uncomp_bytes;
 322     stats->unc_packets  = db->uncomp_count;
 323     stats->comp_bytes   = db->comp_bytes;
 324     stats->comp_packets = db->comp_count;
 325     stats->inc_bytes    = db->incomp_bytes;
 326     stats->inc_packets  = db->incomp_count;
 327     stats->in_count     = db->in_count;
 328     stats->bytes_out    = db->bytes_out;
 329   }
 330 
 331 /*
 332  * Reset state, as on a CCP ResetReq.
 333  */
 334 
 335 static void bsd_reset (void *state)
     /* [previous][next][first][last][top][bottom][index][help] */
 336   {
 337     struct bsd_db *db = (struct bsd_db *) state;
 338 
 339     bsd_clear(db);
 340 
 341     db->seqno       = 0;
 342     db->clear_count = 0;
 343   }
 344 
 345 /*
 346  * Release the compression structure
 347  */
 348 
 349 static void bsd_free (void *state)
     /* [previous][next][first][last][top][bottom][index][help] */
 350   {
 351     struct bsd_db *db = (struct bsd_db *) state;
 352     
 353     if (db)
 354       {
 355 /*
 356  * Release the dictionary
 357  */
 358         if (db->dict)
 359           {
 360             vfree (db->dict);
 361             db->dict = NULL;
 362           }
 363 /*
 364  * Release the string buffer
 365  */
 366         if (db->lens)
 367           {
 368             vfree (db->lens);
 369             db->lens = NULL;
 370           }
 371 /*
 372  * Finally release the structure itself.
 373  */
 374         kfree (db);
 375         MOD_DEC_USE_COUNT;
 376       }
 377   }
 378 
 379 /*
 380  * Allocate space for a (de) compressor.
 381  */
 382 
 383 static void *bsd_alloc (unsigned char *options, int opt_len, int decomp)
     /* [previous][next][first][last][top][bottom][index][help] */
 384   {
 385     int bits;
 386     unsigned int hsize, hshift, maxmaxcode;
 387     struct bsd_db *db;
 388 
 389     if (opt_len != 3 || options[0] != CI_BSD_COMPRESS || options[1] != 3
 390         || BSD_VERSION(options[2]) != BSD_CURRENT_VERSION)
 391       {
 392         return NULL;
 393       }
 394 
 395     bits = BSD_NBITS(options[2]);
 396 
 397     switch (bits)
 398       {
 399     case 9:                     /* needs 82152 for both directions */
 400     case 10:                    /* needs 84144 */
 401     case 11:                    /* needs 88240 */
 402     case 12:                    /* needs 96432 */
 403         hsize = 5003;
 404         hshift = 4;
 405         break;
 406     case 13:                    /* needs 176784 */
 407         hsize = 9001;
 408         hshift = 5;
 409         break;
 410     case 14:                    /* needs 353744 */
 411         hsize = 18013;
 412         hshift = 6;
 413         break;
 414     case 15:                    /* needs 691440 */
 415         hsize = 35023;
 416         hshift = 7;
 417         break;
 418     case 16:                    /* needs 1366160--far too much, */
 419         /* hsize = 69001; */    /* and 69001 is too big for cptr */
 420         /* hshift = 8; */       /* in struct bsd_db */
 421         /* break; */
 422     default:
 423         return NULL;
 424       }
 425 /*
 426  * Allocate the main control structure for this instance.
 427  */
 428     maxmaxcode = MAXCODE(bits);
 429     db         = (struct bsd_db *) kmalloc (sizeof (struct bsd_db),
 430                                             GFP_KERNEL);
 431     if (!db)
 432       {
 433         return NULL;
 434       }
 435 
 436     memset (db, 0, sizeof(struct bsd_db));
 437 /*
 438  * Allocate space for the dictionary. This may be more than one page in
 439  * length.
 440  */
 441     db->dict = (struct bsd_dict *) vmalloc (hsize *
 442                                             sizeof (struct bsd_dict));
 443     if (!db->dict)
 444       {
 445         bsd_free (db);
 446         return NULL;
 447       }
 448 
 449     MOD_INC_USE_COUNT;
 450 /*
 451  * If this is the compression buffer then there is no length data.
 452  */
 453     if (!decomp)
 454       {
 455         db->lens = NULL;
 456       }
 457 /*
 458  * For decompression, the length information is needed as well.
 459  */
 460     else
 461       {
 462         db->lens = (unsigned short *) vmalloc ((maxmaxcode + 1) *
 463                                                sizeof (db->lens[0]));
 464         if (!db->lens)
 465           {
 466             bsd_free (db);
 467             return (NULL);
 468           }
 469       }
 470 /*
 471  * Initialize the data information for the compression code
 472  */
 473     db->totlen     = sizeof (struct bsd_db)   +
 474                     (sizeof (struct bsd_dict) * hsize);
 475 
 476     db->hsize      = hsize;
 477     db->hshift     = hshift;
 478     db->maxmaxcode = maxmaxcode;
 479     db->maxbits    = bits;
 480 
 481     return (void *) db;
 482   }
 483 
 484 static void *bsd_comp_alloc (unsigned char *options, int opt_len)
     /* [previous][next][first][last][top][bottom][index][help] */
 485   {
 486     return bsd_alloc (options, opt_len, 0);
 487   }
 488 
 489 static void *bsd_decomp_alloc (unsigned char *options, int opt_len)
     /* [previous][next][first][last][top][bottom][index][help] */
 490   {
 491     return bsd_alloc (options, opt_len, 1);
 492   }
 493 
 494 /*
 495  * Initialize the database.
 496  */
 497 
 498 static int bsd_init (void *state, unsigned char *options,
     /* [previous][next][first][last][top][bottom][index][help] */
 499                      int opt_len, int unit, int debug, int decomp)
 500   {
 501     struct bsd_db *db = state;
 502     int indx;
 503     
 504     if ((opt_len != 3) || (options[0] != CI_BSD_COMPRESS) || (options[1] != 3)
 505         || (BSD_VERSION(options[2]) != BSD_CURRENT_VERSION)
 506         || (BSD_NBITS(options[2]) != db->maxbits)
 507         || (decomp && db->lens == NULL))
 508       {
 509         return 0;
 510       }
 511 
 512     if (decomp)
 513       {
 514         indx = LAST;
 515         do
 516           {
 517             db->lens[indx] = 1;
 518           }
 519         while (indx-- > 0);
 520       }
 521 
 522     indx = db->hsize;
 523     while (indx-- != 0)
 524       {
 525         db->dict[indx].codem1 = BADCODEM1;
 526         db->dict[indx].cptr   = 0;
 527       }
 528 
 529     db->unit = unit;
 530     db->mru  = 0;
 531 #ifndef DEBUG
 532     if (debug)
 533 #endif
 534       db->debug = 1;
 535     
 536     bsd_reset(db);
 537     
 538     return 1;
 539   }
 540 
 541 static int bsd_comp_init (void *state, unsigned char *options,
     /* [previous][next][first][last][top][bottom][index][help] */
 542                           int opt_len, int unit, int opthdr, int debug)
 543   {
 544     return bsd_init (state, options, opt_len, unit, debug, 0);
 545   }
 546 
 547 static int bsd_decomp_init (void *state, unsigned char *options,
     /* [previous][next][first][last][top][bottom][index][help] */
 548                             int opt_len, int unit, int opthdr, int mru,
 549                             int debug)
 550   {
 551     return bsd_init (state, options, opt_len, unit, debug, 1);
 552   }
 553 
 554 /*
 555  * Obtain pointers to the various structures in the compression tables
 556  */
 557 
 558 #define dict_ptrx(p,idx) &(p->dict[idx])
 559 #define lens_ptrx(p,idx) &(p->lens[idx])
 560 
 561 #ifdef DEBUG
 562 static unsigned short *lens_ptr(struct bsd_db *db, int idx)
     /* [previous][next][first][last][top][bottom][index][help] */
 563   {
 564     if ((unsigned int) idx > (unsigned int) db->maxmaxcode)
 565       {
 566         printk ("<9>ppp: lens_ptr(%d) > max\n", idx);
 567         idx = 0;
 568       }
 569     return lens_ptrx (db, idx);
 570   }
 571 
 572 static struct bsd_dict *dict_ptr(struct bsd_db *db, int idx)
     /* [previous][next][first][last][top][bottom][index][help] */
 573   {
 574     if ((unsigned int) idx >= (unsigned int) db->hsize)
 575       {
 576         printk ("<9>ppp: dict_ptr(%d) > max\n", idx);
 577         idx = 0;
 578       }
 579     return dict_ptrx (db, idx);
 580   }
 581 
 582 #else
 583 #define lens_ptr(db,idx) lens_ptrx(db,idx)
 584 #define dict_ptr(db,idx) dict_ptrx(db,idx)
 585 #endif
 586 
 587 /*
 588  * compress a packet
 589  *
 590  *      The result of this function is the size of the compressed
 591  *      packet. A zero is returned if the packet was not compressed
 592  *      for some reason, such as the size being larger than uncompressed.
 593  *
 594  *      One change from the BSD compress command is that when the
 595  *      code size expands, we do not output a bunch of padding.
 596  */
 597 
 598 static int bsd_compress (void *state, unsigned char *rptr, unsigned char *obuf,
     /* [previous][next][first][last][top][bottom][index][help] */
 599                          int isize, int osize)
 600   {
 601     struct bsd_db *db;
 602     int hshift;
 603     unsigned int max_ent;
 604     unsigned int n_bits;
 605     unsigned int bitno;
 606     unsigned long accm;
 607     int ent;
 608     unsigned long fcode;
 609     struct bsd_dict *dictp;
 610     unsigned char c;
 611     int hval;
 612     int disp;
 613     int ilen;
 614     int mxcode;
 615     unsigned char *wptr;
 616     int olen;
 617 
 618 #define PUTBYTE(v)                      \
 619   {                                     \
 620     ++olen;                             \
 621     if (wptr)                           \
 622       {                                 \
 623         *wptr++ = (unsigned char) (v);  \
 624         if (olen >= osize)              \
 625           {                             \
 626             wptr = NULL;                \
 627           }                             \
 628       }                                 \
 629   }
 630 
 631 #define OUTPUT(ent)                     \
 632   {                                     \
 633     bitno -= n_bits;                    \
 634     accm |= ((ent) << bitno);           \
 635     do                                  \
 636       {                                 \
 637         PUTBYTE(accm >> 24);            \
 638         accm <<= 8;                     \
 639         bitno += 8;                     \
 640       }                                 \
 641     while (bitno <= 24);                \
 642   }
 643 
 644   /*
 645    * If the protocol is not in the range we're interested in,
 646    * just return without compressing the packet.  If it is,
 647    * the protocol becomes the first byte to compress.
 648    */
 649 
 650     ent = PPP_PROTOCOL(rptr);
 651     if (ent < 0x21 || ent > 0xf9)
 652       {
 653         return 0;
 654       }
 655 
 656     db      = (struct bsd_db *) state;
 657     hshift  = db->hshift;
 658     max_ent = db->max_ent;
 659     n_bits  = db->n_bits;
 660     bitno   = 32;
 661     accm    = 0;
 662     mxcode  = MAXCODE (n_bits);
 663 
 664     /* Initialize the output pointers */
 665     wptr  = obuf;
 666     olen  = PPP_HDRLEN + BSD_OVHD;
 667 
 668     if (osize > isize)
 669       {
 670         osize = isize;
 671       }
 672 
 673     /* This is the PPP header information */
 674     if (wptr)
 675       {
 676         *wptr++ = PPP_ADDRESS(rptr);
 677         *wptr++ = PPP_CONTROL(rptr);
 678         *wptr++ = 0;
 679         *wptr++ = PPP_COMP;
 680         *wptr++ = db->seqno >> 8;
 681         *wptr++ = db->seqno;
 682       }
 683 
 684     /* Skip the input header */
 685     rptr  += PPP_HDRLEN;
 686     isize -= PPP_HDRLEN;
 687     ilen   = ++isize; /* This is off by one, but that is what is in draft! */
 688 
 689     while (--ilen > 0)
 690       {
 691         c     = *rptr++;
 692         fcode = BSD_KEY  (ent, c);
 693         hval  = BSD_HASH (ent, c, hshift);
 694         dictp = dict_ptr (db, hval);
 695         
 696         /* Validate and then check the entry. */
 697         if (dictp->codem1 >= max_ent)
 698           {
 699             goto nomatch;
 700           }
 701 
 702         if (dictp->f.fcode == fcode)
 703           {
 704             ent = dictp->codem1 + 1;
 705             continue;   /* found (prefix,suffix) */
 706           }
 707         
 708         /* continue probing until a match or invalid entry */
 709         disp = (hval == 0) ? 1 : hval;
 710 
 711         do
 712           {
 713             hval += disp;
 714             if (hval >= db->hsize)
 715               {
 716                 hval -= db->hsize;
 717               }
 718             dictp = dict_ptr (db, hval);
 719             if (dictp->codem1 >= max_ent)
 720               {
 721                 goto nomatch;
 722               }
 723           }
 724         while (dictp->f.fcode != fcode);
 725 
 726         ent = dictp->codem1 + 1;        /* finally found (prefix,suffix) */
 727         continue;
 728         
 729 nomatch:
 730         OUTPUT(ent);            /* output the prefix */
 731         
 732         /* code -> hashtable */
 733         if (max_ent < db->maxmaxcode)
 734           {
 735             struct bsd_dict *dictp2;
 736             struct bsd_dict *dictp3;
 737             int    indx;
 738 
 739             /* expand code size if needed */
 740             if (max_ent >= mxcode)
 741               {
 742                 db->n_bits = ++n_bits;
 743                 mxcode     = MAXCODE (n_bits);
 744               }
 745             
 746             /* Invalidate old hash table entry using
 747              * this code, and then take it over.
 748              */
 749 
 750             dictp2 = dict_ptr (db, max_ent + 1);
 751             indx   = dictp2->cptr;
 752             dictp3 = dict_ptr (db, indx);
 753 
 754             if (dictp3->codem1 == max_ent)
 755               {
 756                 dictp3->codem1 = BADCODEM1;
 757               }
 758 
 759             dictp2->cptr   = hval;
 760             dictp->codem1  = max_ent;
 761             dictp->f.fcode = fcode;
 762             db->max_ent    = ++max_ent;
 763 
 764             if (db->lens)
 765               {
 766                 unsigned short *len1 = lens_ptr (db, max_ent);
 767                 unsigned short *len2 = lens_ptr (db, ent);
 768                 *len1 = *len2 + 1;
 769               }
 770           }
 771         ent = c;
 772       }
 773     
 774     OUTPUT(ent);                /* output the last code */
 775 
 776     db->bytes_out    += olen;   /* Do not count bytes from here */
 777     db->uncomp_bytes += isize;
 778     db->in_count     += isize;
 779     ++db->uncomp_count;
 780     ++db->seqno;
 781 
 782     if (bitno < 32)
 783       {
 784         ++db->bytes_out; /* must be set before calling bsd_check */
 785       }
 786 
 787     /*
 788      * Generate the clear command if needed
 789      */
 790 
 791     if (bsd_check(db))
 792       {
 793         OUTPUT (CLEAR);
 794       }
 795     
 796     /*
 797      * Pad dribble bits of last code with ones.
 798      * Do not emit a completely useless byte of ones.
 799      */
 800 
 801     if (bitno != 32)
 802       {
 803         PUTBYTE((accm | (0xff << (bitno-8))) >> 24);
 804       }
 805     
 806     /*
 807      * Increase code size if we would have without the packet
 808      * boundary because the decompressor will do so.
 809      */
 810 
 811     if (max_ent >= mxcode && max_ent < db->maxmaxcode)
 812       {
 813         db->n_bits++;
 814       }
 815 
 816     /* If output length is too large then this is an incomplete frame. */
 817     if (wptr == NULL)
 818       {
 819         ++db->incomp_count;
 820         db->incomp_bytes += isize;
 821         olen              = 0;
 822       }
 823     else /* Count the number of compressed frames */
 824       {
 825         ++db->comp_count;
 826         db->comp_bytes += olen;
 827       }
 828 
 829     /* Return the resulting output length */
 830     return olen;
 831 #undef OUTPUT
 832 #undef PUTBYTE
 833   }
 834 
 835 /*
 836  * Update the "BSD Compress" dictionary on the receiver for
 837  * incompressible data by pretending to compress the incoming data.
 838  */
 839 
 840 static void bsd_incomp (void *state, unsigned char *ibuf, int icnt)
     /* [previous][next][first][last][top][bottom][index][help] */
 841   {
 842     (void) bsd_compress (state, ibuf, (char *) 0, icnt, 0);
 843   }
 844 
 845 /*
 846  * Decompress "BSD Compress".
 847  *
 848  * Because of patent problems, we return DECOMP_ERROR for errors
 849  * found by inspecting the input data and for system problems, but
 850  * DECOMP_FATALERROR for any errors which could possibly be said to
 851  * be being detected "after" decompression.  For DECOMP_ERROR,
 852  * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
 853  * infringing a patent of Motorola's if we do, so we take CCP down
 854  * instead.
 855  *
 856  * Given that the frame has the correct sequence number and a good FCS,
 857  * errors such as invalid codes in the input most likely indicate a
 858  * bug, so we return DECOMP_FATALERROR for them in order to turn off
 859  * compression, even though they are detected by inspecting the input.
 860  */
 861 
 862 static int bsd_decompress (void *state, unsigned char *ibuf, int isize,
     /* [previous][next][first][last][top][bottom][index][help] */
 863                            unsigned char *obuf, int osize)
 864   {
 865     struct bsd_db *db;
 866     unsigned int max_ent;
 867     unsigned long accm;
 868     unsigned int bitno;         /* 1st valid bit in accm */
 869     unsigned int n_bits;
 870     unsigned int tgtbitno;      /* bitno when we have a code */
 871     struct bsd_dict *dictp;
 872     int explen;
 873     int seq;
 874     unsigned int incode;
 875     unsigned int oldcode;
 876     unsigned int finchar;
 877     unsigned char *p;
 878     unsigned char *wptr;
 879     int adrs;
 880     int ctrl;
 881     int ilen;
 882     int codelen;
 883     int extra;
 884 
 885     db       = (struct bsd_db *) state;
 886     max_ent  = db->max_ent;
 887     accm     = 0;
 888     bitno    = 32;              /* 1st valid bit in accm */
 889     n_bits   = db->n_bits;
 890     tgtbitno = 32 - n_bits;     /* bitno when we have a code */
 891     
 892     /*
 893      * Save the address/control from the PPP header
 894      * and then get the sequence number.
 895      */
 896 
 897     adrs  = PPP_ADDRESS (ibuf);
 898     ctrl  = PPP_CONTROL (ibuf);
 899 
 900     seq   = (ibuf[4] << 8) + ibuf[5];
 901 
 902     ibuf += (PPP_HDRLEN + 2);
 903     ilen  = isize - (PPP_HDRLEN + 2);
 904     
 905     /*
 906      * Check the sequence number and give up if it differs from
 907      * the value we're expecting.
 908      */
 909 
 910     if (seq != db->seqno)
 911       {
 912         if (db->debug)
 913           {
 914             printk("bsd_decomp%d: bad sequence # %d, expected %d\n",
 915                    db->unit, seq, db->seqno - 1);
 916           }
 917         return DECOMP_ERROR;
 918       }
 919 
 920     ++db->seqno;
 921     db->bytes_out += ilen;
 922 
 923     /*
 924      * Fill in the ppp header, but not the last byte of the protocol
 925      * (that comes from the decompressed data).
 926      */
 927 
 928     wptr    = obuf;
 929     *wptr++ = adrs;
 930     *wptr++ = ctrl;
 931     *wptr++ = 0;
 932     
 933     oldcode = CLEAR;
 934     explen  = 3;
 935 
 936     /*
 937      * Keep the checkpoint correctly so that incompressible packets
 938      * clear the dictionary at the proper times.
 939      */
 940 
 941     for (;;)
 942       {
 943         if (ilen-- <= 0)
 944           {
 945             db->in_count += (explen - 3); /* don't count the header */
 946             break;
 947           }
 948 
 949         /*
 950          * Accumulate bytes until we have a complete code.
 951          * Then get the next code, relying on the 32-bit,
 952          * unsigned accm to mask the result.
 953          */
 954 
 955         bitno -= 8;
 956         accm  |= *ibuf++ << bitno;
 957         if (tgtbitno < bitno)
 958           {
 959             continue;
 960           }
 961 
 962         incode = accm >> tgtbitno;
 963         accm <<= n_bits;
 964         bitno += n_bits;
 965 
 966         /*
 967          * The dictionary must only be cleared at the end of a packet.
 968          */
 969         
 970         if (incode == CLEAR)
 971           {
 972             if (ilen > 0)
 973               {
 974                 if (db->debug)
 975                   {
 976                     printk("bsd_decomp%d: bad CLEAR\n", db->unit);
 977                   }
 978                 return DECOMP_FATALERROR;       /* probably a bug */
 979               }
 980             
 981             bsd_clear(db);
 982             break;
 983           }
 984 
 985         if ((incode > max_ent + 2) || (incode > db->maxmaxcode)
 986             || (incode > max_ent && oldcode == CLEAR))
 987           {
 988             if (db->debug)
 989               {
 990                 printk("bsd_decomp%d: bad code 0x%x oldcode=0x%x ",
 991                        db->unit, incode, oldcode);
 992                 printk("max_ent=0x%x explen=%d seqno=%d\n",
 993                        max_ent, explen, db->seqno);
 994               }
 995             return DECOMP_FATALERROR;   /* probably a bug */
 996           }
 997         
 998         /* Special case for KwKwK string. */
 999         if (incode > max_ent)
1000           {
1001             finchar = oldcode;
1002             extra   = 1;
1003           }
1004         else
1005           {
1006             finchar = incode;
1007             extra   = 0;
1008           }
1009         
1010         codelen = *(lens_ptr (db, finchar));
1011         explen += codelen + extra;
1012         if (explen > osize)
1013           {
1014             if (db->debug)
1015               {
1016                 printk("bsd_decomp%d: ran out of mru\n", db->unit);
1017 #ifdef DEBUG
1018                 printk("  len=%d, finchar=0x%x, codelen=%d, explen=%d\n",
1019                        ilen, finchar, codelen, explen);
1020 #endif
1021               }
1022             return DECOMP_FATALERROR;
1023           }
1024         
1025         /*
1026          * Decode this code and install it in the decompressed buffer.
1027          */
1028 
1029         wptr += codelen;
1030         p     = wptr;
1031         while (finchar > LAST)
1032           {
1033             struct bsd_dict *dictp2 = dict_ptr (db, finchar);
1034             
1035             dictp = dict_ptr (db, dictp2->cptr);
1036 #ifdef DEBUG
1037             if (--codelen <= 0 || dictp->codem1 != finchar-1)
1038               {
1039                 if (codelen <= 0)
1040                   {
1041                     printk("bsd_decomp%d: fell off end of chain ", db->unit);
1042                     printk("0x%x at 0x%x by 0x%x, max_ent=0x%x\n",
1043                            incode, finchar, dictp2->cptr, max_ent);
1044                   }
1045                 else
1046                   {
1047                     if (dictp->codem1 != finchar-1)
1048                       {
1049                         printk("bsd_decomp%d: bad code chain 0x%x "
1050                                "finchar=0x%x ",
1051                                db->unit, incode, finchar);
1052 
1053                         printk("oldcode=0x%x cptr=0x%x codem1=0x%x\n",
1054                                oldcode, dictp2->cptr, dictp->codem1);
1055                       }
1056                   }
1057                 return DECOMP_FATALERROR;
1058               }
1059 #endif
1060             *--p    = dictp->f.hs.suffix;
1061             finchar = dictp->f.hs.prefix;
1062           }
1063         *--p = finchar;
1064         
1065 #ifdef DEBUG
1066         if (--codelen != 0)
1067           {
1068             printk("bsd_decomp%d: short by %d after code 0x%x, max_ent=0x%x\n",
1069                    db->unit, codelen, incode, max_ent);
1070           }
1071 #endif
1072         
1073         if (extra)              /* the KwKwK case again */
1074           {
1075             *wptr++ = finchar;
1076           }
1077         
1078         /*
1079          * If not first code in a packet, and
1080          * if not out of code space, then allocate a new code.
1081          *
1082          * Keep the hash table correct so it can be used
1083          * with uncompressed packets.
1084          */
1085 
1086         if (oldcode != CLEAR && max_ent < db->maxmaxcode)
1087           {
1088             struct bsd_dict *dictp2, *dictp3;
1089             unsigned short  *lens1,  *lens2;
1090             unsigned long fcode;
1091             int hval, disp, indx;
1092             
1093             fcode = BSD_KEY(oldcode,finchar);
1094             hval  = BSD_HASH(oldcode,finchar,db->hshift);
1095             dictp = dict_ptr (db, hval);
1096             
1097             /* look for a free hash table entry */
1098             if (dictp->codem1 < max_ent)
1099               {
1100                 disp = (hval == 0) ? 1 : hval;
1101                 do
1102                   {
1103                     hval += disp;
1104                     if (hval >= db->hsize)
1105                       {
1106                         hval -= db->hsize;
1107                       }
1108                     dictp = dict_ptr (db, hval);
1109                   }
1110                 while (dictp->codem1 < max_ent);
1111               }
1112             
1113             /*
1114              * Invalidate previous hash table entry
1115              * assigned this code, and then take it over
1116              */
1117 
1118             dictp2 = dict_ptr (db, max_ent + 1);
1119             indx   = dictp2->cptr;
1120             dictp3 = dict_ptr (db, indx);
1121 
1122             if (dictp3->codem1 == max_ent)
1123               {
1124                 dictp3->codem1 = BADCODEM1;
1125               }
1126 
1127             dictp2->cptr   = hval;
1128             dictp->codem1  = max_ent;
1129             dictp->f.fcode = fcode;
1130             db->max_ent    = ++max_ent;
1131 
1132             /* Update the length of this string. */
1133             lens1  = lens_ptr (db, max_ent);
1134             lens2  = lens_ptr (db, oldcode);
1135             *lens1 = *lens2 + 1;
1136             
1137             /* Expand code size if needed. */
1138             if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode)
1139               {
1140                 db->n_bits = ++n_bits;
1141                 tgtbitno   = 32-n_bits;
1142               }
1143           }
1144         oldcode = incode;
1145       }
1146 
1147     ++db->comp_count;
1148     ++db->uncomp_count;
1149     db->comp_bytes   += isize - BSD_OVHD - PPP_HDRLEN;
1150     db->uncomp_bytes += explen;
1151 
1152     if (bsd_check(db))
1153       {
1154         if (db->debug)
1155           {
1156             printk("bsd_decomp%d: peer should have cleared dictionary on %d\n",
1157                    db->unit, db->seqno - 1);
1158           }
1159       }
1160     return explen;
1161   }
1162      
1163 /*************************************************************
1164  * Table of addresses for the BSD compression module
1165  *************************************************************/
1166 
1167 static struct compressor ppp_bsd_compress = {
1168     CI_BSD_COMPRESS,            /* compress_proto */
1169     bsd_comp_alloc,             /* comp_alloc */
1170     bsd_free,                   /* comp_free */
1171     bsd_comp_init,              /* comp_init */
1172     bsd_reset,                  /* comp_reset */
1173     bsd_compress,               /* compress */
1174     bsd_comp_stats,             /* comp_stat */
1175     bsd_decomp_alloc,           /* decomp_alloc */
1176     bsd_free,                   /* decomp_free */
1177     bsd_decomp_init,            /* decomp_init */
1178     bsd_reset,                  /* decomp_reset */
1179     bsd_decompress,             /* decompress */
1180     bsd_incomp,                 /* incomp */
1181     bsd_comp_stats              /* decomp_stat */
1182 };
1183 
1184 /*************************************************************
1185  * Module support routines
1186  *************************************************************/
1187 
1188 int
1189 init_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1190 {
1191         int answer = ppp_register_compressor (&ppp_bsd_compress);
1192         if (answer == 0)
1193                 printk (KERN_INFO "PPP BSD Compression module registered\n");
1194         return answer;
1195 }
1196 
1197 void
1198 cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1199 {
1200         ppp_unregister_compressor (&ppp_bsd_compress);
1201 }

/* [previous][next][first][last][top][bottom][index][help] */