/* * Update: The Berkeley copyright was changed, and the change * is retroactive to all "true" BSD software (ie everything * from UCB as opposed to other peoples code that just carried * the same license). The new copyright doesn't clash with the * GPL, so the module-only restriction has been removed..
*/
/* Because this code is derived from the 4.3BSD compress source: * * Copyright (c) 1985, 1986 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * James A. Woods, derived from original work by Spencer Thomas * and Joseph Orost. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE.
*/
/* * This version is for use with contiguous buffers on Linux-derived systems. * * ==FILEVERSION 20000226== * * NOTE TO MAINTAINERS: * If you modify this file at all, please set the number above to the * date of the modification as YYMMDD (year month day). * bsd_comp.c is shipped with a PPP distribution as well as with * the kernel; if everyone increases the FILEVERSION number above, * then scripts can do the right thing when deciding whether to * install a new bsd_comp.c file. Don't change the format of that * line otherwise, so the installation script can recognize it. * * From: bsd_comp.c,v 1.3 1994/12/08 01:59:58 paulus Exp
*/
/* * PPP "BSD compress" compression * The differences between this compression and the classic BSD LZW * source are obvious from the requirement that the classic code worked * with files while this handles arbitrarily long streams that * are broken into packets. They are: * * When the code size expands, a block of junk is not emitted by * the compressor and not expected by the decompressor. * * New codes are not necessarily assigned every time an old * code is output by the compressor. This is because a packet * end forces a code to be emitted, but does not imply that a * new sequence has been seen. * * The compression ratio is checked at the first end of a packet * after the appropriate gap. Besides simplifying and speeding * things up, this makes it more likely that the transmitter * and receiver will agree when the dictionary is cleared when * compression is not going well.
*/
/* * Macros to extract protocol version and number of bits * from the third byte of the BSD Compress CCP configuration option.
*/
staticvoid bsd_free (void *state); staticvoid *bsd_alloc(unsignedchar *options, int opt_len, int decomp); staticvoid *bsd_comp_alloc (unsignedchar *options, int opt_len); staticvoid *bsd_decomp_alloc (unsignedchar *options, int opt_len);
staticint bsd_init (void *db, unsignedchar *options, int opt_len, int unit, int debug, int decomp); staticint bsd_comp_init (void *state, unsignedchar *options, int opt_len, int unit, int opthdr, int debug); staticint bsd_decomp_init (void *state, unsignedchar *options, int opt_len, int unit, int opthdr, int mru, int debug);
staticint bsd_compress (void *state, unsignedchar *rptr, unsignedchar *obuf, int isize, int osize); staticvoid bsd_incomp (void *state, unsignedchar *ibuf, int icnt);
staticint bsd_decompress (void *state, unsignedchar *ibuf, int isize, unsignedchar *obuf, int osize);
/* These are in ppp_generic.c */ externint ppp_register_compressor (struct compressor *cp); externvoid ppp_unregister_compressor (struct compressor *cp);
/* * the next two codes should not be changed lightly, as they must not * lie within the contiguous general code space.
*/ #define CLEAR 256 /* table clear output code */ #define FIRST 257 /* first free entry */ #define LAST 255
/* * If the dictionary is full, then see if it is time to reset it. * * Compute the compression ratio using fixed-point arithmetic * with 8 fractional bits. * * Since we have an infinite stream instead of a single file, * watch only the local compression ratio. * * Since both peers must reset the dictionary at the same time even in * the absence of CLEAR codes (while packets are incompressible), they * must compute the same ratio.
*/
if (db->in_count >= db->checkpoint)
{ /* age the ratio by limiting the size of the counts */ if (db->in_count >= RATIO_MAX || db->bytes_out >= RATIO_MAX)
{
db->in_count -= (db->in_count >> 2);
db->bytes_out -= (db->bytes_out >> 2);
}
db->checkpoint = db->in_count + CHECK_GAP;
if (db->max_ent >= db->maxmaxcode)
{ /* Reset the dictionary only if the ratio is worse, * or if it looks as if it has been poisoned * by incompressible data. * * This does not overflow, because * db->in_count <= RATIO_MAX.
*/
switch (bits)
{ case 9: /* needs 82152 for both directions */ case 10: /* needs 84144 */ case 11: /* needs 88240 */ case 12: /* needs 96432 */
hsize = 5003;
hshift = 4; break; case 13: /* needs 176784 */
hsize = 9001;
hshift = 5; break; case 14: /* needs 353744 */
hsize = 18013;
hshift = 6; break; case 15: /* needs 691440 */
hsize = 35023;
hshift = 7; break; case 16: /* needs 1366160--far too much, */ /* hsize = 69001; */ /* and 69001 is too big for cptr */ /* hshift = 8; */ /* in struct bsd_db */ /* break; */ default: return NULL;
} /* * Allocate the main control structure for this instance.
*/
maxmaxcode = MAXCODE(bits);
db = kzalloc(sizeof (struct bsd_db),
GFP_KERNEL); if (!db)
{ return NULL;
}
/* * Allocate space for the dictionary. This may be more than one page in * length.
*/
db->dict = vmalloc(array_size(hsize, sizeof(struct bsd_dict))); if (!db->dict)
{
bsd_free (db); return NULL;
}
/* * If this is the compression buffer then there is no length data.
*/ if (!decomp)
{
db->lens = NULL;
} /* * For decompression, the length information is needed as well.
*/ else
{
db->lens = vmalloc(array_size(sizeof(db->lens[0]), (maxmaxcode + 1))); if (!db->lens)
{
bsd_free (db); return NULL;
}
} /* * Initialize the data information for the compression code
*/
db->totlen = sizeof (struct bsd_db) +
(sizeof (struct bsd_dict) * hsize);
staticint bsd_comp_init (void *state, unsignedchar *options, int opt_len, int unit, int opthdr, int debug)
{ return bsd_init (state, options, opt_len, unit, debug, 0);
}
staticint bsd_decomp_init (void *state, unsignedchar *options, int opt_len, int unit, int opthdr, int mru, int debug)
{ return bsd_init (state, options, opt_len, unit, debug, 1);
}
/* * Obtain pointers to the various structures in the compression tables
*/
/* * compress a packet * * The result of this function is the size of the compressed * packet. A zero is returned if the packet was not compressed * for some reason, such as the size being larger than uncompressed. * * One change from the BSD compress command is that when the * code size expands, we do not output a bunch of padding.
*/
staticint bsd_compress (void *state, unsignedchar *rptr, unsignedchar *obuf, int isize, int osize)
{ struct bsd_db *db; int hshift; unsignedint max_ent; unsignedint n_bits; unsignedint bitno; unsignedlong accm; int ent; unsignedlong fcode; struct bsd_dict *dictp; unsignedchar c; int hval; int disp; int ilen; int mxcode; unsignedchar *wptr; int olen;
#define OUTPUT(ent) \
{ \
bitno -= n_bits; \
accm |= ((ent) << bitno); \ do \
{ \
PUTBYTE(accm >> 24); \
accm <<= 8; \
bitno += 8; \
} \ while (bitno <= 24); \
}
/* * If the protocol is not in the range we're interested in, * just return without compressing the packet. If it is, * the protocol becomes the first byte to compress.
*/
ent = PPP_PROTOCOL(rptr); if (ent < 0x21 || ent > 0xf9)
{ return 0;
}
/* If output length is too large then this is an incomplete frame. */ if (wptr == NULL)
{
++db->incomp_count;
db->incomp_bytes += isize;
olen = 0;
} else/* Count the number of compressed frames */
{
++db->comp_count;
db->comp_bytes += olen;
}
/* * Decompress "BSD Compress". * * Because of patent problems, we return DECOMP_ERROR for errors * found by inspecting the input data and for system problems, but * DECOMP_FATALERROR for any errors which could possibly be said to * be being detected "after" decompression. For DECOMP_ERROR, * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be * infringing a patent of Motorola's if we do, so we take CCP down * instead. * * Given that the frame has the correct sequence number and a good FCS, * errors such as invalid codes in the input most likely indicate a * bug, so we return DECOMP_FATALERROR for them in order to turn off * compression, even though they are detected by inspecting the input.
*/
staticint bsd_decompress (void *state, unsignedchar *ibuf, int isize, unsignedchar *obuf, int osize)
{ struct bsd_db *db; unsignedint max_ent; unsignedlong accm; unsignedint bitno; /* 1st valid bit in accm */ unsignedint n_bits; unsignedint tgtbitno; /* bitno when we have a code */ struct bsd_dict *dictp; int explen; int seq; unsignedint incode; unsignedint oldcode; unsignedint finchar; unsignedchar *p; unsignedchar *wptr; int adrs; int ctrl; int ilen; int codelen; int extra;
db = (struct bsd_db *) state;
max_ent = db->max_ent;
accm = 0;
bitno = 32; /* 1st valid bit in accm */
n_bits = db->n_bits;
tgtbitno = 32 - n_bits; /* bitno when we have a code */
/* * Save the address/control from the PPP header * and then get the sequence number.
*/
#ifdef DEBUG if (--codelen != 0)
{
printk("bsd_decomp%d: short by %d after code 0x%x, max_ent=0x%x\n",
db->unit, codelen, incode, max_ent);
} #endif
if (extra) /* the KwKwK case again */
{
*wptr++ = finchar;
}
/* * If not first code in a packet, and * if not out of code space, then allocate a new code. * * Keep the hash table correct so it can be used * with uncompressed packets.
*/
if (bsd_check(db))
{ if (db->debug)
{
printk("bsd_decomp%d: peer should have cleared dictionary on %d\n",
db->unit, db->seqno - 1);
}
} return explen;
}
/************************************************************* * Table of addresses for the BSD compression module
*************************************************************/
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.