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

📄 isdn_bsdcomp.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
	struct bsd_dict *dictp;	unsigned char c;	int hval,disp,ilen,mxcode;	unsigned char *rptr = skb_in->data;	int isize = skb_in->len;#define OUTPUT(ent)			\  {					\    bitno -= n_bits;			\    accm |= ((ent) << bitno);		\    do	{				\        if(skb_out && skb_tailroom(skb_out) > 0) 	\      		*(skb_put(skb_out,1)) = (unsigned char) (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.	 */	printk(KERN_DEBUG "bsd_compress called with %x\n",proto);		ent = proto;	if (proto < 0x21 || proto > 0xf9 || !(proto & 0x1) )		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);		/* This is the PPP header information */	if(skb_out && skb_tailroom(skb_out) >= 2) {		char *v = skb_put(skb_out,2);		/* we only push our own data on the header,		  AC,PC and protos is pushed by caller  */		v[0] = db->seqno >> 8;		v[1] = db->seqno;	}	ilen   = ++isize; /* This is off by one, but that is what is in draft! */	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->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->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->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 */	if(skb_out)		db->bytes_out    += skb_out->len; /* Do not count bytes from here */	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 && skb_out && skb_tailroom(skb_out) > 0) 		*(skb_put(skb_out,1)) = (unsigned char) ((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 incompressible frame. */	if (!skb_out || (skb_out && skb_out->len >= skb_in->len) ) {		++db->incomp_count;		db->incomp_bytes += isize;		return 0;	}	/* Count the number of compressed frames */	++db->comp_count;	db->comp_bytes += skb_out->len;	return skb_out->len;#undef OUTPUT}/* * Update the "BSD Compress" dictionary on the receiver for * incompressible data by pretending to compress the incoming data. */static void bsd_incomp (void *state, struct sk_buff *skb_in,int proto){	bsd_compress (state, skb_in, NULL, proto);}/* * Decompress "BSD Compress". */static int bsd_decompress (void *state, struct sk_buff *skb_in, struct sk_buff *skb_out,			   struct isdn_ppp_resetparams *rsparm){	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 seq;	unsigned int incode;	unsigned int oldcode;	unsigned int finchar;	unsigned char *p,*ibuf;	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 */	printk(KERN_DEBUG "bsd_decompress called\n");	if(!skb_in || !skb_out) {		printk(KERN_ERR "bsd_decompress called with NULL parameter\n");		return DECOMP_ERROR;	}    	/*	 * Get the sequence number.	 */	if( (p = skb_pull(skb_in,2)) == NULL) {		return DECOMP_ERROR;	}	p-=2;	seq   = (p[0] << 8) + p[1];	ilen  = skb_in->len;	ibuf = skb_in->data;	/*	 * Check the sequence number and give up if it differs from	 * the value we're expecting.	 */	if (seq != db->seqno) {		if (db->debug) {			printk(KERN_DEBUG "bsd_decomp%d: bad sequence # %d, expected %d\n",				db->unit, seq, db->seqno - 1);		}		return DECOMP_ERROR;	}	++db->seqno;	db->bytes_out += ilen;	if(skb_tailroom(skb_out) > 0)		*(skb_put(skb_out,1)) = 0;	else		return DECOMP_ERR_NOMEM;    	oldcode = CLEAR;	/*	 * Keep the checkpoint correctly so that incompressible packets	 * clear the dictionary at the proper times.	 */	for (;;) {		if (ilen-- <= 0) {			db->in_count += (skb_out->len - 1); /* 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(KERN_DEBUG "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(KERN_DEBUG "bsd_decomp%d: bad code 0x%x oldcode=0x%x ",					db->unit, incode, oldcode);				printk(KERN_DEBUG "max_ent=0x%x skb->Len=%d seqno=%d\n",					max_ent, skb_out->len, 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));		if( skb_tailroom(skb_out) < codelen + extra) {			if (db->debug) {				printk(KERN_DEBUG "bsd_decomp%d: ran out of mru\n", db->unit);#ifdef DEBUG				printk(KERN_DEBUG "  len=%d, finchar=0x%x, codelen=%d,skblen=%d\n",					ilen, finchar, codelen, skb_out->len);#endif			}			return DECOMP_FATALERROR;		}		/*		 * Decode this code and install it in the decompressed buffer.		 */		p     = skb_put(skb_out,codelen);		p += codelen;		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(KERN_ERR "bsd_decomp%d: fell off end of chain ", db->unit);					printk(KERN_ERR "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(KERN_ERR "bsd_decomp%d: bad code chain 0x%x finchar=0x%x ",db->unit, incode, finchar);						printk(KERN_ERR "oldcode=0x%x cptr=0x%x codem1=0x%x\n", oldcode, dictp2->cptr, dictp->codem1);					}				}				return DECOMP_FATALERROR;			}#endif			{				u32 fcode = dictp->fcode;				*--p    = (fcode >> 16) & 0xff;				finchar = fcode & 0xffff;			}		}		*--p = finchar;	#ifdef DEBUG		if (--codelen != 0)			printk(KERN_ERR "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 */			*(skb_put(skb_out,1)) = 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;			u16  *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->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   += skb_in->len - BSD_OVHD;	db->uncomp_bytes += skb_out->len;	if (bsd_check(db)) {		if (db->debug)			printk(KERN_DEBUG "bsd_decomp%d: peer should have cleared dictionary on %d\n",				db->unit, db->seqno - 1);	}	return skb_out->len;}/************************************************************* * Table of addresses for the BSD compression module *************************************************************/static struct isdn_ppp_compressor ippp_bsd_compress = {	.owner          = THIS_MODULE,	.num            = CI_BSD_COMPRESS,	.alloc          = bsd_alloc,	.free           = bsd_free,	.init           = bsd_init,	.reset          = bsd_reset,	.compress       = bsd_compress,	.decompress     = bsd_decompress,	.incomp         = bsd_incomp,	.stat           = bsd_stats,};/************************************************************* * Module support routines *************************************************************/static int __init isdn_bsdcomp_init(void){	int answer = isdn_ppp_register_compressor (&ippp_bsd_compress);	if (answer == 0)		printk (KERN_INFO "PPP BSD Compression module registered\n");	return answer;}static void __exit isdn_bsdcomp_exit(void){	isdn_ppp_unregister_compressor (&ippp_bsd_compress);}module_init(isdn_bsdcomp_init);module_exit(isdn_bsdcomp_exit);

⌨️ 快捷键说明

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