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

📄 ipcomp.c

📁 This a good VPN source
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * IPCOMP zlib interface code. * Copyright (C) 2000  Svenning Soerensen <svenning@post5.tele.dk> * Copyright (C) 2000, 2001  Richard Guy Briggs <rgb@conscoop.ottawa.on.ca> *  * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>. *  * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * for more details. */char ipcomp_c_version[] = "RCSID $Id: ipcomp.c,v 1.37 2004/07/10 19:11:18 mcr Exp $";/* SSS */#include <linux/config.h>#include <linux/version.h>#define __NO_VERSION__#include <linux/module.h>#include <linux/kernel.h> /* printk() */#include "openswan/ipsec_param.h"#ifdef MALLOC_SLAB# include <linux/slab.h> /* kmalloc() */#else /* MALLOC_SLAB */# include <linux/malloc.h> /* kmalloc() */#endif /* MALLOC_SLAB */#include <linux/errno.h>  /* error codes */#include <linux/types.h>#include <linux/netdevice.h>#include <linux/ip.h>#include <linux/skbuff.h>#include <linux/netdevice.h>   /* struct device, and other headers */#include <linux/etherdevice.h> /* eth_type_trans */#include <linux/ip.h>          /* struct iphdr */#include <linux/skbuff.h>#include <openswan.h>#ifdef NET_21# include <net/dst.h># include <asm/uaccess.h># include <linux/in6.h># define proto_priv cb#endif /* NET21 */#include <asm/checksum.h>#include <net/ip.h>#include "openswan/radij.h"#include "openswan/ipsec_encap.h"#include "openswan/ipsec_sa.h"#include "openswan/ipsec_xform.h"#include "openswan/ipsec_tunnel.h"#include "openswan/ipsec_rcv.h" /* sysctl_ipsec_inbound_policy_check */#include "openswan/ipcomp.h"#include "zlib/zlib.h"#include "zlib/zutil.h"#include <pfkeyv2.h> /* SADB_X_CALG_DEFLATE */#ifdef CONFIG_KLIPS_DEBUGint sysctl_ipsec_debug_ipcomp = 0;#endif /* CONFIG_KLIPS_DEBUG */staticstruct sk_buff *skb_copy_ipcomp(struct sk_buff *skb, int data_growth, int gfp_mask);staticvoidpf my_zcalloc(voidpf opaque, uInt items, uInt size){	return (voidpf) kmalloc(items*size, GFP_ATOMIC);}staticvoid my_zfree(voidpf opaque, voidpf address){	kfree(address);}struct sk_buff *skb_compress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags){	struct iphdr *iph;	unsigned int iphlen, pyldsz, cpyldsz;	unsigned char *buffer;	z_stream zs;	int zresult;		KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,		    "klips_debug:skb_compress: .\n");	if(skb == NULL) {		KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,			    "klips_debug:skb_compress: "			    "passed in NULL skb, returning ERROR.\n");		if(flags != NULL) {			*flags |= IPCOMP_PARMERROR;		}		return skb;	}	if(ips == NULL) {		KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,			    "klips_debug:skb_compress: "			    "passed in NULL ipsec_sa needed for cpi, returning ERROR.\n");		if(flags) {			*flags |= IPCOMP_PARMERROR;		}		return skb;	}	if (flags == NULL) {		KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,			    "klips_debug:skb_compress: "			    "passed in NULL flags, returning ERROR.\n");		ipsec_kfree_skb(skb);		return NULL;	}	#ifdef NET_21	iph = skb->nh.iph;#else /* NET_21 */	iph = skb->ip_hdr;#endif /* NET_21 */	switch (iph->protocol) {	case IPPROTO_COMP:	case IPPROTO_AH:	case IPPROTO_ESP:		KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,			    "klips_debug:skb_compress: "			    "skipping compression of packet with ip protocol %d.\n",			    iph->protocol);		*flags |= IPCOMP_UNCOMPRESSABLE;		return skb;	}		/* Don't compress packets already fragmented */	if (iph->frag_off & __constant_htons(IP_MF | IP_OFFSET)) {		KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,			    "klips_debug:skb_compress: "			    "skipping compression of fragmented packet.\n");		*flags |= IPCOMP_UNCOMPRESSABLE;		return skb;	}		iphlen = iph->ihl << 2;	pyldsz = ntohs(iph->tot_len) - iphlen;	/* Don't compress less than 90 bytes (rfc 2394) */	if (pyldsz < 90) {		KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,			    "klips_debug:skb_compress: "			    "skipping compression of tiny packet, len=%d.\n",			    pyldsz);		*flags |= IPCOMP_UNCOMPRESSABLE;		return skb;	}		/* Adaptive decision */	if (ips->ips_comp_adapt_skip) {		KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,			    "klips_debug:skb_compress: "			    "skipping compression: ips_comp_adapt_skip=%d.\n",			    ips->ips_comp_adapt_skip);		ips->ips_comp_adapt_skip--;		*flags |= IPCOMP_UNCOMPRESSABLE;		return skb;	}	zs.zalloc = my_zcalloc;	zs.zfree = my_zfree;	zs.opaque = 0;		/* We want to use deflateInit2 because we don't want the adler	   header. */	zresult = deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -11,			       DEF_MEM_LEVEL,  Z_DEFAULT_STRATEGY);	if (zresult != Z_OK) {		KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,			    "klips_error:skb_compress: "			    "deflateInit2() returned error %d (%s), "			    "skipping compression.\n",			    zresult,			    zs.msg ? zs.msg : zError(zresult));		*flags |= IPCOMP_COMPRESSIONERROR;		return skb;	}		/* Max output size. Result should be max this size.	 * Implementation specific tweak:	 * If it's not at least 32 bytes and 6.25% smaller than	 * the original packet, it's probably not worth wasting	 * the receiver's CPU cycles decompressing it.	 * Your mileage may vary.	 */	cpyldsz = pyldsz - sizeof(struct ipcomphdr) - (pyldsz <= 512 ? 32 : pyldsz >> 4);	buffer = kmalloc(cpyldsz, GFP_ATOMIC);	if (!buffer) {		KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,			    "klips_error:skb_compress: "			    "unable to kmalloc(%d, GFP_ATOMIC), "			    "skipping compression.\n",			    cpyldsz);		*flags |= IPCOMP_COMPRESSIONERROR;		deflateEnd(&zs);		return skb;	}	#ifdef CONFIG_KLIPS_DEBUG	if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) {		__u8 *c;		int i;		c = (__u8*)iph + iphlen;		for(i = 0; i < pyldsz; i++, c++) {			if(!(i % 16)) {				printk(KERN_INFO "skb_compress:   before:");			}			printk("%02x ", *c);			if(!((i + 1) % 16)) {				printk("\n");			}		}		if(i % 16) {			printk("\n");		}	}#endif /* CONFIG_KLIPS_DEBUG */	zs.next_in = (char *) iph + iphlen; /* start of payload */	zs.avail_in = pyldsz;	zs.next_out = buffer;     /* start of compressed payload */	zs.avail_out = cpyldsz;		/* Finish compression in one step */	zresult = deflate(&zs, Z_FINISH);	/* Free all dynamically allocated buffers */	deflateEnd(&zs);	if (zresult != Z_STREAM_END) {		*flags |= IPCOMP_UNCOMPRESSABLE;		kfree(buffer);		/* Adjust adaptive counters */		if (++(ips->ips_comp_adapt_tries) == IPCOMP_ADAPT_INITIAL_TRIES) {			KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,				    "klips_debug:skb_compress: "				    "first %d packets didn't compress, "				    "skipping next %d\n",				    IPCOMP_ADAPT_INITIAL_TRIES,				    IPCOMP_ADAPT_INITIAL_SKIP);			ips->ips_comp_adapt_skip = IPCOMP_ADAPT_INITIAL_SKIP;		}		else if (ips->ips_comp_adapt_tries == IPCOMP_ADAPT_INITIAL_TRIES + IPCOMP_ADAPT_SUBSEQ_TRIES) {			KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,				    "klips_debug:skb_compress: "				    "next %d packets didn't compress, "				    "skipping next %d\n",				    IPCOMP_ADAPT_SUBSEQ_TRIES,				    IPCOMP_ADAPT_SUBSEQ_SKIP);			ips->ips_comp_adapt_skip = IPCOMP_ADAPT_SUBSEQ_SKIP;			ips->ips_comp_adapt_tries = IPCOMP_ADAPT_INITIAL_TRIES;		}		return skb;	}		/* resulting compressed size */	cpyldsz -= zs.avail_out;		/* Insert IPCOMP header */	((struct ipcomphdr*) ((char*) iph + iphlen))->ipcomp_nh = iph->protocol;	((struct ipcomphdr*) ((char*) iph + iphlen))->ipcomp_flags = 0;	/* use the bottom 16 bits of the spi for the cpi.  The top 16 bits are	   for internal reference only. */	((struct ipcomphdr*) (((char*)iph) + iphlen))->ipcomp_cpi = htons((__u16)(ntohl(ips->ips_said.spi) & 0x0000ffff));	KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,		    "klips_debug:skb_compress: "		    "spi=%08x, spi&0xffff=%04x, cpi=%04x, payload size: raw=%d, comp=%d.\n",		    ntohl(ips->ips_said.spi),		    ntohl(ips->ips_said.spi) & 0x0000ffff,		    ntohs(((struct ipcomphdr*)(((char*)iph)+iphlen))->ipcomp_cpi),		    pyldsz,		    cpyldsz);		/* Update IP header */	iph->protocol = IPPROTO_COMP;	iph->tot_len = htons(iphlen + sizeof(struct ipcomphdr) + cpyldsz);#if 1 /* XXX checksum is done by ipsec_tunnel ? */	iph->check = 0;	iph->check = ip_fast_csum((char *) iph, iph->ihl);#endif		/* Copy compressed payload */	memcpy((char *) iph + iphlen + sizeof(struct ipcomphdr),	       buffer,	       cpyldsz);	kfree(buffer);		/* Update skb length/tail by "unputting" the shrinkage */	skb_put(skb,		cpyldsz + sizeof(struct ipcomphdr) - pyldsz);	#ifdef CONFIG_KLIPS_DEBUG	if(sysctl_ipsec_debug_ipcomp && sysctl_ipsec_debug_verbose) {		__u8 *c;		int i;				c = (__u8*)iph + iphlen + sizeof(struct ipcomphdr);		for(i = 0; i < cpyldsz; i++, c++) {			if(!(i % 16)) {				printk(KERN_INFO "skb_compress:   result:");			}			printk("%02x ", *c);			if(!((i + 1) % 16)) {				printk("\n");			}		}		if(i % 16) {			printk("\n");		}	}#endif /* CONFIG_KLIPS_DEBUG */		ips->ips_comp_adapt_skip = 0;	ips->ips_comp_adapt_tries = 0;		return skb;}struct sk_buff *skb_decompress(struct sk_buff *skb, struct ipsec_sa *ips, unsigned int *flags){	struct sk_buff *nskb = NULL;	/* original ip header */	struct iphdr *oiph, *iph;	unsigned int iphlen, pyldsz, cpyldsz;	z_stream zs;	int zresult;	KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,		    "klips_debug:skb_decompress: .\n");	if(!skb) {		KLIPS_PRINT(sysctl_ipsec_debug_ipcomp,			    "klips_error:skb_decompress: "			    "passed in NULL skb, returning ERROR.\n");		if (flags) *flags |= IPCOMP_PARMERROR;		return skb;	}	if(!ips && sysctl_ipsec_inbound_policy_check) {

⌨️ 快捷键说明

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