⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bsd_comp.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 2 页
字号:
    int olen;#define PUTBYTE(v)			\  {					\    ++olen;				\    if (wptr)				\      {					\	*wptr++ = (unsigned char) (v);	\	if (olen >= osize)		\	  {				\	    wptr = NULL;		\	  }				\      }					\  }#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;      }    db      = (struct bsd_db *) state;    hshift  = db->hshift;    max_ent = db->max_ent;    n_bits  = db->n_bits;    bitno   = 32;    accm    = 0;    mxcode  = MAXCODE (n_bits);    /* Initialize the output pointers */    wptr  = obuf;    olen  = PPP_HDRLEN + BSD_OVHD;    if (osize > isize)      {	osize = isize;      }    /* This is the PPP header information */    if (wptr)      {	*wptr++ = PPP_ADDRESS(rptr);	*wptr++ = PPP_CONTROL(rptr);	*wptr++ = 0;	*wptr++ = PPP_COMP;	*wptr++ = db->seqno >> 8;	*wptr++ = db->seqno;      }    /* Skip the input header */    rptr  += PPP_HDRLEN;    isize -= PPP_HDRLEN;    ilen   = ++isize;	/* Low byte of protocol is counted as input */    while (--ilen > 0)      {	c     = *rptr++;	fcode = BSD_KEY  (ent, c);	hval  = BSD_HASH (ent, c, hshift);	dictp = dict_ptr (db, hval);		/* Validate and then check the entry. */	if (dictp->codem1 >= max_ent)	  {	    goto nomatch;	  }	if (dictp->f.fcode == fcode)	  {	    ent = dictp->codem1 + 1;	    continue;	/* found (prefix,suffix) */	  }		/* continue probing until a match or invalid entry */	disp = (hval == 0) ? 1 : hval;	do	  {	    hval += disp;	    if (hval >= db->hsize)	      {		hval -= db->hsize;	      }	    dictp = dict_ptr (db, hval);	    if (dictp->codem1 >= max_ent)	      {		goto nomatch;	      }	  }	while (dictp->f.fcode != fcode);	ent = dictp->codem1 + 1;	/* finally found (prefix,suffix) */	continue;	nomatch:	OUTPUT(ent);		/* output the prefix */		/* code -> hashtable */	if (max_ent < db->maxmaxcode)	  {	    struct bsd_dict *dictp2;	    struct bsd_dict *dictp3;	    int    indx;	    /* expand code size if needed */	    if (max_ent >= mxcode)	      {		db->n_bits = ++n_bits;		mxcode     = MAXCODE (n_bits);	      }	    	    /* Invalidate old hash table entry using	     * this code, and then take it over.	     */	    dictp2 = dict_ptr (db, max_ent + 1);	    indx   = dictp2->cptr;	    dictp3 = dict_ptr (db, indx);	    if (dictp3->codem1 == max_ent)	      {		dictp3->codem1 = BADCODEM1;	      }	    dictp2->cptr   = hval;	    dictp->codem1  = max_ent;	    dictp->f.fcode = fcode;	    db->max_ent    = ++max_ent;	    if (db->lens)	      {		unsigned short *len1 = lens_ptr (db, max_ent);		unsigned short *len2 = lens_ptr (db, ent);		*len1 = *len2 + 1;	      }	  }	ent = c;      }        OUTPUT(ent);		/* output the last code */    db->bytes_out    += olen - PPP_HDRLEN - BSD_OVHD;    db->uncomp_bytes += isize;    db->in_count     += isize;    ++db->uncomp_count;    ++db->seqno;    if (bitno < 32)      {	++db->bytes_out; /* must be set before calling bsd_check */      }    /*     * Generate the clear command if needed     */    if (bsd_check(db))      {	OUTPUT (CLEAR);      }        /*     * Pad dribble bits of last code with ones.     * Do not emit a completely useless byte of ones.     */    if (bitno != 32)      {	PUTBYTE((accm | (0xff << (bitno-8))) >> 24);      }        /*     * Increase code size if we would have without the packet     * boundary because the decompressor will do so.     */    if (max_ent >= mxcode && max_ent < db->maxmaxcode)      {	db->n_bits++;      }    /* 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;      }    /* Return the resulting output length */    return olen;#undef OUTPUT#undef PUTBYTE  }/* * Update the "BSD Compress" dictionary on the receiver for * incompressible data by pretending to compress the incoming data. */static void bsd_incomp (void *state, unsigned char *ibuf, int icnt)  {    (void) bsd_compress (state, ibuf, (char *) 0, icnt, 0);  }/* * 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. */static int bsd_decompress (void *state, unsigned char *ibuf, int isize,			   unsigned char *obuf, int osize)  {    struct bsd_db *db;    unsigned int max_ent;    unsigned long accm;    unsigned int bitno;		/* 1st valid bit in accm */    unsigned int n_bits;    unsigned int tgtbitno;	/* bitno when we have a code */    struct bsd_dict *dictp;    int explen;    int seq;    unsigned int incode;    unsigned int oldcode;    unsigned int finchar;    unsigned char *p;    unsigned char *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.     */    adrs  = PPP_ADDRESS (ibuf);    ctrl  = PPP_CONTROL (ibuf);    seq   = (ibuf[4] << 8) + ibuf[5];    ibuf += (PPP_HDRLEN + 2);    ilen  = isize - (PPP_HDRLEN + 2);        /*     * Check the sequence number and give up if it differs from     * the value we're expecting.     */    if (seq != db->seqno)      {	if (db->debug)	  {	    printk("bsd_decomp%d: bad sequence # %d, expected %d\n",		   db->unit, seq, db->seqno - 1);	  }	return DECOMP_ERROR;      }    ++db->seqno;    db->bytes_out += ilen;    /*     * Fill in the ppp header, but not the last byte of the protocol     * (that comes from the decompressed data).     */    wptr    = obuf;    *wptr++ = adrs;    *wptr++ = ctrl;    *wptr++ = 0;        oldcode = CLEAR;    explen  = 3;    /*     * Keep the checkpoint correctly so that incompressible packets     * clear the dictionary at the proper times.     */    for (;;)      {	if (ilen-- <= 0)	  {	    db->in_count += (explen - 3); /* don't count the header */	    break;	  }	/*	 * Accumulate bytes until we have a complete code.	 * Then get the next code, relying on the 32-bit,	 * unsigned accm to mask the result.	 */	bitno -= 8;	accm  |= *ibuf++ << bitno;	if (tgtbitno < bitno)	  {	    continue;	  }	incode = accm >> tgtbitno;	accm <<= n_bits;	bitno += n_bits;	/*	 * The dictionary must only be cleared at the end of a packet.	 */		if (incode == CLEAR)	  {	    if (ilen > 0)	      {		if (db->debug)		  {		    printk("bsd_decomp%d: bad CLEAR\n", db->unit);		  }		return DECOMP_FATALERROR;	/* probably a bug */	      }	    	    bsd_clear(db);	    break;	  }	if ((incode > max_ent + 2) || (incode > db->maxmaxcode)	    || (incode > max_ent && oldcode == CLEAR))	  {	    if (db->debug)	      {		printk("bsd_decomp%d: bad code 0x%x oldcode=0x%x ",		       db->unit, incode, oldcode);		printk("max_ent=0x%x explen=%d seqno=%d\n",		       max_ent, explen, db->seqno);	      }	    return DECOMP_FATALERROR;	/* probably a bug */	  }		/* Special case for KwKwK string. */	if (incode > max_ent)	  {	    finchar = oldcode;	    extra   = 1;	  }	else	  {	    finchar = incode;	    extra   = 0;	  }		codelen = *(lens_ptr (db, finchar));	explen += codelen + extra;	if (explen > osize)	  {	    if (db->debug)	      {		printk("bsd_decomp%d: ran out of mru\n", db->unit);#ifdef DEBUG		printk("  len=%d, finchar=0x%x, codelen=%d, explen=%d\n",		       ilen, finchar, codelen, explen);#endif	      }	    return DECOMP_FATALERROR;	  }		/*	 * Decode this code and install it in the decompressed buffer.	 */	wptr += codelen;	p     = wptr;	while (finchar > LAST)	  {	    struct bsd_dict *dictp2 = dict_ptr (db, finchar);	    	    dictp = dict_ptr (db, dictp2->cptr);#ifdef DEBUG	    if (--codelen <= 0 || dictp->codem1 != finchar-1)	      {		if (codelen <= 0)		  {		    printk("bsd_decomp%d: fell off end of chain ", db->unit);		    printk("0x%x at 0x%x by 0x%x, max_ent=0x%x\n",			   incode, finchar, dictp2->cptr, max_ent);		  }		else		  {		    if (dictp->codem1 != finchar-1)		      {			printk("bsd_decomp%d: bad code chain 0x%x "			       "finchar=0x%x ",			       db->unit, incode, finchar);			printk("oldcode=0x%x cptr=0x%x codem1=0x%x\n",			       oldcode, dictp2->cptr, dictp->codem1);		      }		  }		return DECOMP_FATALERROR;	      }#endif	    *--p    = dictp->f.hs.suffix;	    finchar = dictp->f.hs.prefix;	  }	*--p = finchar;	#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 (oldcode != CLEAR && max_ent < db->maxmaxcode)	  {	    struct bsd_dict *dictp2, *dictp3;	    unsigned short  *lens1,  *lens2;	    unsigned long fcode;	    int hval, disp, indx;	    	    fcode = BSD_KEY(oldcode,finchar);	    hval  = BSD_HASH(oldcode,finchar,db->hshift);	    dictp = dict_ptr (db, hval);	    	    /* look for a free hash table entry */	    if (dictp->codem1 < max_ent)	      {		disp = (hval == 0) ? 1 : hval;		do		  {		    hval += disp;		    if (hval >= db->hsize)		      {			hval -= db->hsize;		      }		    dictp = dict_ptr (db, hval);		  }		while (dictp->codem1 < max_ent);	      }	    	    /*	     * Invalidate previous hash table entry	     * assigned this code, and then take it over	     */	    dictp2 = dict_ptr (db, max_ent + 1);	    indx   = dictp2->cptr;	    dictp3 = dict_ptr (db, indx);	    if (dictp3->codem1 == max_ent)	      {		dictp3->codem1 = BADCODEM1;	      }	    dictp2->cptr   = hval;	    dictp->codem1  = max_ent;	    dictp->f.fcode = fcode;	    db->max_ent    = ++max_ent;	    /* Update the length of this string. */	    lens1  = lens_ptr (db, max_ent);	    lens2  = lens_ptr (db, oldcode);	    *lens1 = *lens2 + 1;	    	    /* Expand code size if needed. */	    if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode)	      {		db->n_bits = ++n_bits;		tgtbitno   = 32-n_bits;	      }	  }	oldcode = incode;      }    ++db->comp_count;    ++db->uncomp_count;    db->comp_bytes   += isize - BSD_OVHD - PPP_HDRLEN;    db->uncomp_bytes += explen;    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 *************************************************************/static struct compressor ppp_bsd_compress = {    CI_BSD_COMPRESS,		/* compress_proto */    bsd_comp_alloc,		/* comp_alloc */    bsd_free,			/* comp_free */    bsd_comp_init,		/* comp_init */    bsd_reset,			/* comp_reset */    bsd_compress,		/* compress */    bsd_comp_stats,		/* comp_stat */    bsd_decomp_alloc,		/* decomp_alloc */    bsd_free,			/* decomp_free */    bsd_decomp_init,		/* decomp_init */    bsd_reset,			/* decomp_reset */    bsd_decompress,		/* decompress */    bsd_incomp,			/* incomp */    bsd_comp_stats		/* decomp_stat */};/************************************************************* * Module support routines *************************************************************/int bsdcomp_init(void){	int answer = ppp_register_compressor(&ppp_bsd_compress);	if (answer == 0)		printk(KERN_INFO "PPP BSD Compression module registered\n");	return answer;}void bsdcomp_cleanup(void){	ppp_unregister_compressor(&ppp_bsd_compress);}module_init(bsdcomp_init);module_exit(bsdcomp_cleanup);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -