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

📄 ppp_mppe.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	int proto;	struct scatterlist sg_in[1], sg_out[1];	/*	 * Check that the protocol is in the range we handle.	 */	proto = PPP_PROTOCOL(ibuf);	if (proto < 0x0021 || proto > 0x00fa)		return 0;	/* Make sure we have enough room to generate an encrypted packet. */	if (osize < isize + MPPE_OVHD + 2) {		/* Drop the packet if we should encrypt it, but can't. */		printk(KERN_DEBUG "mppe_compress[%d]: osize too small! "		       "(have: %d need: %d)\n", state->unit,		       osize, osize + MPPE_OVHD + 2);		return -1;	}	osize = isize + MPPE_OVHD + 2;	/*	 * Copy over the PPP header and set control bits.	 */	obuf[0] = PPP_ADDRESS(ibuf);	obuf[1] = PPP_CONTROL(ibuf);	obuf[2] = PPP_COMP >> 8;	/* isize + MPPE_OVHD + 1 */	obuf[3] = PPP_COMP;	/* isize + MPPE_OVHD + 2 */	obuf += PPP_HDRLEN;	state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE;	if (state->debug >= 7)		printk(KERN_DEBUG "mppe_compress[%d]: ccount %d\n", state->unit,		       state->ccount);	obuf[0] = state->ccount >> 8;	obuf[1] = state->ccount & 0xff;	if (!state->stateful ||	/* stateless mode     */	    ((state->ccount & 0xff) == 0xff) ||	/* "flag" packet      */	    (state->bits & MPPE_BIT_FLUSHED)) {	/* CCP Reset-Request  */		/* We must rekey */		if (state->debug && state->stateful)			printk(KERN_DEBUG "mppe_compress[%d]: rekeying\n",			       state->unit);		mppe_rekey(state, 0);		state->bits |= MPPE_BIT_FLUSHED;	}	obuf[0] |= state->bits;	state->bits &= ~MPPE_BIT_FLUSHED;	/* reset for next xmit */	obuf += MPPE_OVHD;	ibuf += 2;		/* skip to proto field */	isize -= 2;	/* Encrypt packet */	sg_init_table(sg_in, 1);	sg_init_table(sg_out, 1);	setup_sg(sg_in, ibuf, isize);	setup_sg(sg_out, obuf, osize);	if (crypto_blkcipher_encrypt(&desc, sg_out, sg_in, isize) != 0) {		printk(KERN_DEBUG "crypto_cypher_encrypt failed\n");		return -1;	}	state->stats.unc_bytes += isize;	state->stats.unc_packets++;	state->stats.comp_bytes += osize;	state->stats.comp_packets++;	return osize;}/* * Since every frame grows by MPPE_OVHD + 2 bytes, this is always going * to look bad ... and the longer the link is up the worse it will get. */static void mppe_comp_stats(void *arg, struct compstat *stats){	struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg;	*stats = state->stats;}static intmppe_decomp_init(void *arg, unsigned char *options, int optlen, int unit,		 int hdrlen, int mru, int debug){	/* ARGSUSED */	return mppe_init(arg, options, optlen, unit, debug, "mppe_decomp_init");}/* * We received a CCP Reset-Ack.  Just ignore it. */static void mppe_decomp_reset(void *arg){	/* ARGSUSED */	return;}/* * Decompress (decrypt) an MPPE packet. */static intmppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf,		int osize){	struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg;	struct blkcipher_desc desc = { .tfm = state->arc4 };	unsigned ccount;	int flushed = MPPE_BITS(ibuf) & MPPE_BIT_FLUSHED;	int sanity = 0;	struct scatterlist sg_in[1], sg_out[1];	if (isize <= PPP_HDRLEN + MPPE_OVHD) {		if (state->debug)			printk(KERN_DEBUG			       "mppe_decompress[%d]: short pkt (%d)\n",			       state->unit, isize);		return DECOMP_ERROR;	}	/*	 * Make sure we have enough room to decrypt the packet.	 * Note that for our test we only subtract 1 byte whereas in	 * mppe_compress() we added 2 bytes (+MPPE_OVHD);	 * this is to account for possible PFC.	 */	if (osize < isize - MPPE_OVHD - 1) {		printk(KERN_DEBUG "mppe_decompress[%d]: osize too small! "		       "(have: %d need: %d)\n", state->unit,		       osize, isize - MPPE_OVHD - 1);		return DECOMP_ERROR;	}	osize = isize - MPPE_OVHD - 2;	/* assume no PFC */	ccount = MPPE_CCOUNT(ibuf);	if (state->debug >= 7)		printk(KERN_DEBUG "mppe_decompress[%d]: ccount %d\n",		       state->unit, ccount);	/* sanity checks -- terminate with extreme prejudice */	if (!(MPPE_BITS(ibuf) & MPPE_BIT_ENCRYPTED)) {		printk(KERN_DEBUG		       "mppe_decompress[%d]: ENCRYPTED bit not set!\n",		       state->unit);		state->sanity_errors += 100;		sanity = 1;	}	if (!state->stateful && !flushed) {		printk(KERN_DEBUG "mppe_decompress[%d]: FLUSHED bit not set in "		       "stateless mode!\n", state->unit);		state->sanity_errors += 100;		sanity = 1;	}	if (state->stateful && ((ccount & 0xff) == 0xff) && !flushed) {		printk(KERN_DEBUG "mppe_decompress[%d]: FLUSHED bit not set on "		       "flag packet!\n", state->unit);		state->sanity_errors += 100;		sanity = 1;	}	if (sanity) {		if (state->sanity_errors < SANITY_MAX)			return DECOMP_ERROR;		else			/*			 * Take LCP down if the peer is sending too many bogons.			 * We don't want to do this for a single or just a few			 * instances since it could just be due to packet corruption.			 */			return DECOMP_FATALERROR;	}	/*	 * Check the coherency count.	 */	if (!state->stateful) {		/* RFC 3078, sec 8.1.  Rekey for every packet. */		while (state->ccount != ccount) {			mppe_rekey(state, 0);			state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE;		}	} else {		/* RFC 3078, sec 8.2. */		if (!state->discard) {			/* normal state */			state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE;			if (ccount != state->ccount) {				/*				 * (ccount > state->ccount)				 * Packet loss detected, enter the discard state.				 * Signal the peer to rekey (by sending a CCP Reset-Request).				 */				state->discard = 1;				return DECOMP_ERROR;			}		} else {			/* discard state */			if (!flushed) {				/* ccp.c will be silent (no additional CCP Reset-Requests). */				return DECOMP_ERROR;			} else {				/* Rekey for every missed "flag" packet. */				while ((ccount & ~0xff) !=				       (state->ccount & ~0xff)) {					mppe_rekey(state, 0);					state->ccount =					    (state->ccount +					     256) % MPPE_CCOUNT_SPACE;				}				/* reset */				state->discard = 0;				state->ccount = ccount;				/*				 * Another problem with RFC 3078 here.  It implies that the				 * peer need not send a Reset-Ack packet.  But RFC 1962				 * requires it.  Hopefully, M$ does send a Reset-Ack; even				 * though it isn't required for MPPE synchronization, it is				 * required to reset CCP state.				 */			}		}		if (flushed)			mppe_rekey(state, 0);	}	/*	 * Fill in the first part of the PPP header.  The protocol field	 * comes from the decrypted data.	 */	obuf[0] = PPP_ADDRESS(ibuf);	/* +1 */	obuf[1] = PPP_CONTROL(ibuf);	/* +1 */	obuf += 2;	ibuf += PPP_HDRLEN + MPPE_OVHD;	isize -= PPP_HDRLEN + MPPE_OVHD;	/* -6 */	/* net osize: isize-4 */	/*	 * Decrypt the first byte in order to check if it is	 * a compressed or uncompressed protocol field.	 */	sg_init_table(sg_in, 1);	sg_init_table(sg_out, 1);	setup_sg(sg_in, ibuf, 1);	setup_sg(sg_out, obuf, 1);	if (crypto_blkcipher_decrypt(&desc, sg_out, sg_in, 1) != 0) {		printk(KERN_DEBUG "crypto_cypher_decrypt failed\n");		return DECOMP_ERROR;	}	/*	 * Do PFC decompression.	 * This would be nicer if we were given the actual sk_buff	 * instead of a char *.	 */	if ((obuf[0] & 0x01) != 0) {		obuf[1] = obuf[0];		obuf[0] = 0;		obuf++;		osize++;	}	/* And finally, decrypt the rest of the packet. */	setup_sg(sg_in, ibuf + 1, isize - 1);	setup_sg(sg_out, obuf + 1, osize - 1);	if (crypto_blkcipher_decrypt(&desc, sg_out, sg_in, isize - 1)) {		printk(KERN_DEBUG "crypto_cypher_decrypt failed\n");		return DECOMP_ERROR;	}	state->stats.unc_bytes += osize;	state->stats.unc_packets++;	state->stats.comp_bytes += isize;	state->stats.comp_packets++;	/* good packet credit */	state->sanity_errors >>= 1;	return osize;}/* * Incompressible data has arrived (this should never happen!). * We should probably drop the link if the protocol is in the range * of what should be encrypted.  At the least, we should drop this * packet.  (How to do this?) */static void mppe_incomp(void *arg, unsigned char *ibuf, int icnt){	struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg;	if (state->debug &&	    (PPP_PROTOCOL(ibuf) >= 0x0021 && PPP_PROTOCOL(ibuf) <= 0x00fa))		printk(KERN_DEBUG		       "mppe_incomp[%d]: incompressible (unencrypted) data! "		       "(proto %04x)\n", state->unit, PPP_PROTOCOL(ibuf));	state->stats.inc_bytes += icnt;	state->stats.inc_packets++;	state->stats.unc_bytes += icnt;	state->stats.unc_packets++;}/************************************************************* * Module interface table *************************************************************//* * Procedures exported to if_ppp.c. */static struct compressor ppp_mppe = {	.compress_proto = CI_MPPE,	.comp_alloc     = mppe_alloc,	.comp_free      = mppe_free,	.comp_init      = mppe_comp_init,	.comp_reset     = mppe_comp_reset,	.compress       = mppe_compress,	.comp_stat      = mppe_comp_stats,	.decomp_alloc   = mppe_alloc,	.decomp_free    = mppe_free,	.decomp_init    = mppe_decomp_init,	.decomp_reset   = mppe_decomp_reset,	.decompress     = mppe_decompress,	.incomp         = mppe_incomp,	.decomp_stat    = mppe_comp_stats,	.owner          = THIS_MODULE,	.comp_extra     = MPPE_PAD,};/* * ppp_mppe_init() * * Prior to allowing load, try to load the arc4 and sha1 crypto * libraries.  The actual use will be allocated later, but * this way the module will fail to insmod if they aren't available. */static int __init ppp_mppe_init(void){	int answer;	if (!(crypto_has_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC) &&	      crypto_has_hash("sha1", 0, CRYPTO_ALG_ASYNC)))		return -ENODEV;	sha_pad = kmalloc(sizeof(struct sha_pad), GFP_KERNEL);	if (!sha_pad)		return -ENOMEM;	sha_pad_init(sha_pad);	answer = ppp_register_compressor(&ppp_mppe);	if (answer == 0)		printk(KERN_INFO "PPP MPPE Compression module registered\n");	else		kfree(sha_pad);	return answer;}static void __exit ppp_mppe_cleanup(void){	ppp_unregister_compressor(&ppp_mppe);	kfree(sha_pad);}module_init(ppp_mppe_init);module_exit(ppp_mppe_cleanup);

⌨️ 快捷键说明

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