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