ppp_deflate.c

来自「linux 内核源代码」· C语言 代码 · 共 656 行 · 第 1/2 页

C
656
字号
{	struct ppp_deflate_state *state;	int w_size;	if (opt_len != CILEN_DEFLATE	    || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)	    || options[1] != CILEN_DEFLATE	    || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL	    || options[3] != DEFLATE_CHK_SEQUENCE)		return NULL;	w_size = DEFLATE_SIZE(options[2]);	if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)		return NULL;	state = kzalloc(sizeof(*state), GFP_KERNEL);	if (state == NULL)		return NULL;	state->w_size         = w_size;	state->strm.next_out  = NULL;	state->strm.workspace = kmalloc(zlib_inflate_workspacesize(),					GFP_KERNEL|__GFP_REPEAT);	if (state->strm.workspace == NULL)		goto out_free;	if (zlib_inflateInit2(&state->strm, -w_size) != Z_OK)		goto out_free;	return (void *) state;out_free:	z_decomp_free(state);	return NULL;}/** *	z_decomp_init - initialize a previously-allocated decompressor. *	@arg:	pointer to the private state for the decompressor *	@options: pointer to the CCP option data describing the *		compression that was negotiated with the peer *	@opt_len: length of the CCP option data at @options *	@unit:	PPP unit number for diagnostic messages *	@hdrlen: ignored (present for backwards compatibility) *	@mru:	maximum length of decompressed packets *	@debug:	debug flag; if non-zero, debug messages are printed. * *	The CCP options described by @options must match the options *	specified when the decompressor was allocated.  The decompressor *	history is reset.  Returns 0 for failure (CCP options don't *	match) or 1 for success. */static int z_decomp_init(void *arg, unsigned char *options, int opt_len,			 int unit, int hdrlen, int mru, int debug){	struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;	if (opt_len < CILEN_DEFLATE	    || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)	    || options[1] != CILEN_DEFLATE	    || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL	    || DEFLATE_SIZE(options[2]) != state->w_size	    || options[3] != DEFLATE_CHK_SEQUENCE)		return 0;	state->seqno = 0;	state->unit  = unit;	state->debug = debug;	state->mru   = mru;	zlib_inflateReset(&state->strm);	return 1;}/** *	z_decomp_reset - reset a previously-allocated decompressor. *	@arg:	pointer to private state for the decompressor. * *	This clears the history for the decompressor and makes it *	ready to receive a new compressed stream. */static void z_decomp_reset(void *arg){	struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;	state->seqno = 0;	zlib_inflateReset(&state->strm);}/** *	z_decompress - decompress a Deflate-compressed packet. *	@arg:	pointer to private state for the decompressor *	@ibuf:	pointer to input (compressed) packet data *	@isize:	length of input packet *	@obuf:	pointer to space for output (decompressed) packet *	@osize:	amount of space available at @obuf * * 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. */int z_decompress(void *arg, unsigned char *ibuf, int isize,		 unsigned char *obuf, int osize){	struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;	int olen, seq, r;	int decode_proto, overflow;	unsigned char overflow_buf[1];	if (isize <= PPP_HDRLEN + DEFLATE_OVHD) {		if (state->debug)			printk(KERN_DEBUG "z_decompress%d: short pkt (%d)\n",			       state->unit, isize);		return DECOMP_ERROR;	}	/* Check the sequence number. */	seq = (ibuf[PPP_HDRLEN] << 8) + ibuf[PPP_HDRLEN+1];	if (seq != (state->seqno & 0xffff)) {		if (state->debug)			printk(KERN_DEBUG "z_decompress%d: bad seq # %d, expected %d\n",			       state->unit, seq, state->seqno & 0xffff);		return DECOMP_ERROR;	}	++state->seqno;	/*	 * Fill in the first part of the PPP header.  The protocol field	 * comes from the decompressed data.	 */	obuf[0] = PPP_ADDRESS(ibuf);	obuf[1] = PPP_CONTROL(ibuf);	obuf[2] = 0;	/*	 * Set up to call inflate.  We set avail_out to 1 initially so we can	 * look at the first byte of the output and decide whether we have	 * a 1-byte or 2-byte protocol field.	 */	state->strm.next_in = ibuf + PPP_HDRLEN + DEFLATE_OVHD;	state->strm.avail_in = isize - (PPP_HDRLEN + DEFLATE_OVHD);	state->strm.next_out = obuf + 3;	state->strm.avail_out = 1;	decode_proto = 1;	overflow = 0;	/*	 * Call inflate, supplying more input or output as needed.	 */	for (;;) {		r = zlib_inflate(&state->strm, Z_PACKET_FLUSH);		if (r != Z_OK) {			if (state->debug)				printk(KERN_DEBUG "z_decompress%d: inflate returned %d (%s)\n",				       state->unit, r, (state->strm.msg? state->strm.msg: ""));			return DECOMP_FATALERROR;		}		if (state->strm.avail_out != 0)			break;		/* all done */		if (decode_proto) {			state->strm.avail_out = osize - PPP_HDRLEN;			if ((obuf[3] & 1) == 0) {				/* 2-byte protocol field */				obuf[2] = obuf[3];				--state->strm.next_out;				++state->strm.avail_out;			}			decode_proto = 0;		} else if (!overflow) {			/*			 * We've filled up the output buffer; the only way to			 * find out whether inflate has any more characters			 * left is to give it another byte of output space.			 */			state->strm.next_out = overflow_buf;			state->strm.avail_out = 1;			overflow = 1;		} else {			if (state->debug)				printk(KERN_DEBUG "z_decompress%d: ran out of mru\n",				       state->unit);			return DECOMP_FATALERROR;		}	}	if (decode_proto) {		if (state->debug)			printk(KERN_DEBUG "z_decompress%d: didn't get proto\n",			       state->unit);		return DECOMP_ERROR;	}	olen = osize + overflow - state->strm.avail_out;	state->stats.unc_bytes += olen;	state->stats.unc_packets++;	state->stats.comp_bytes += isize;	state->stats.comp_packets++;	return olen;}/** *	z_incomp - add incompressible input data to the history. *	@arg:	pointer to private state for the decompressor *	@ibuf:	pointer to input packet data *	@icnt:	length of input data. */static void z_incomp(void *arg, unsigned char *ibuf, int icnt){	struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;	int proto, r;	/*	 * Check that the protocol is one we handle.	 */	proto = PPP_PROTOCOL(ibuf);	if (proto > 0x3fff || proto == 0xfd || proto == 0xfb)		return;	++state->seqno;	/*	 * We start at the either the 1st or 2nd byte of the protocol field,	 * depending on whether the protocol value is compressible.	 */	state->strm.next_in = ibuf + 3;	state->strm.avail_in = icnt - 3;	if (proto > 0xff) {		--state->strm.next_in;		++state->strm.avail_in;	}	r = zlib_inflateIncomp(&state->strm);	if (r != Z_OK) {		/* gak! */		if (state->debug) {			printk(KERN_DEBUG "z_incomp%d: inflateIncomp returned %d (%s)\n",			       state->unit, r, (state->strm.msg? state->strm.msg: ""));		}		return;	}	/*	 * Update stats.	 */	state->stats.inc_bytes += icnt;	state->stats.inc_packets++;	state->stats.unc_bytes += icnt;	state->stats.unc_packets++;}/************************************************************* * Module interface table *************************************************************//* These are in ppp_generic.c */extern int  ppp_register_compressor   (struct compressor *cp);extern void ppp_unregister_compressor (struct compressor *cp);/* * Procedures exported to if_ppp.c. */static struct compressor ppp_deflate = {	.compress_proto =	CI_DEFLATE,	.comp_alloc =		z_comp_alloc,	.comp_free =		z_comp_free,	.comp_init =		z_comp_init,	.comp_reset =		z_comp_reset,	.compress =		z_compress,	.comp_stat =		z_comp_stats,	.decomp_alloc =		z_decomp_alloc,	.decomp_free =		z_decomp_free,	.decomp_init =		z_decomp_init,	.decomp_reset =		z_decomp_reset,	.decompress =		z_decompress,	.incomp =		z_incomp,	.decomp_stat =		z_comp_stats,	.owner =		THIS_MODULE};static struct compressor ppp_deflate_draft = {	.compress_proto =	CI_DEFLATE_DRAFT,	.comp_alloc =		z_comp_alloc,	.comp_free =		z_comp_free,	.comp_init =		z_comp_init,	.comp_reset =		z_comp_reset,	.compress =		z_compress,	.comp_stat =		z_comp_stats,	.decomp_alloc =		z_decomp_alloc,	.decomp_free =		z_decomp_free,	.decomp_init =		z_decomp_init,	.decomp_reset =		z_decomp_reset,	.decompress =		z_decompress,	.incomp =		z_incomp,	.decomp_stat =		z_comp_stats,	.owner =		THIS_MODULE};static int __init deflate_init(void){        int answer = ppp_register_compressor(&ppp_deflate);        if (answer == 0)                printk(KERN_INFO		       "PPP Deflate Compression module registered\n");	ppp_register_compressor(&ppp_deflate_draft);        return answer;}static void __exit deflate_cleanup(void){	ppp_unregister_compressor(&ppp_deflate);	ppp_unregister_compressor(&ppp_deflate_draft);}module_init(deflate_init);module_exit(deflate_cleanup);MODULE_LICENSE("Dual BSD/GPL");MODULE_ALIAS("ppp-compress-" __stringify(CI_DEFLATE));MODULE_ALIAS("ppp-compress-" __stringify(CI_DEFLATE_DRAFT));

⌨️ 快捷键说明

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