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

📄 ipsec_tunnel.c

📁 网上下到的一个很详细介绍VPN基础知识的资料
💻 C
📖 第 1 页 / 共 5 页
字号:
 *	This function assumes it is being called from dev_queue_xmit() *	and that skb is filled properly by that function. */intipsec_tunnel_start_xmit(struct sk_buff *skb, struct device *dev){	struct ipsecpriv *prv;		/* Our device' private space */	struct sk_buff *oskb = NULL;	/* Original skb pointer */	struct net_device_stats *stats;	/* This device's statistics */	struct iphdr  *iph;		/* Our new IP header */	__u32   newdst;			/* The other SG's IP address */	__u32	orgdst;			/* Original IP destination address */	__u32	orgedst;		/* 1st SG's IP address */	__u32   newsrc;			/* The new source SG's IP address */	__u32	orgsrc;			/* Original IP source address */	__u32	innersrc;		/* Innermost IP source address */	int	iphlen;			/* IP header length */	int	pyldsz;			/* upper protocol payload size */	int	headroom;	int	tailroom;	int     max_headroom = 0;	/* The extra header space needed */	int	max_tailroom = 0;	/* The extra stuffing needed */	int     ll_headroom;		/* The extra link layer hard_header space needed */	int     tot_headroom = 0;	/* The total header space needed */	int	tot_tailroom = 0;	/* The totalstuffing needed */	__u8	*saved_header = NULL;	/* saved copy of the hard header */	int i;	struct sockaddr_encap matcher;	/* eroute search key */	struct eroute *er;	struct tdb *tdbp, *tdbq;	/* Tunnel Descriptor Block pointers */	char sa[SATOA_BUF];	size_t sa_len;	int hard_header_stripped = 0;	/* has the hard header been removed yet? */	int hard_header_len = 0;	struct device *physdev;/*	struct device *virtdev; */	short physmtu;	short mtudiff;#ifdef NET_21	struct rtable *rt = NULL;#endif /* NET_21 */	struct sa_id outgoing_said;#ifdef NET_21	int pass = 0;#endif /* NET_21 */	int error = 0;	uint32_t eroute_pid = 0;	/*	 *	Return if there is nothing to do.  (Does this ever happen?) XXX	 */	if (skb == NULL) {		KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,			    "klips_error:ipsec_tunnel_start_xmit: "			    "Nothing to do!\n" );		goto cleanup;	}	if (dev == NULL) {		KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,			    "klips_error:ipsec_tunnel_start_xmit: "			    "No device associated with skb!\n" );		goto cleanup;	}	prv = dev->priv;	if (prv == NULL) {		KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,			    "klips_error:ipsec_tunnel_start_xmit: "			    "Device has no private structure!\n" );		goto cleanup;	}	physdev = prv->dev;	if (physdev == NULL) {		KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,			    "klips_error:ipsec_tunnel_start_xmit: "			    "Device is not attached to physical device!\n" );		goto cleanup;	}	physmtu = physdev->mtu;	stats = (struct net_device_stats *) &(prv->mystats);#ifdef NET_21	/* if skb was cloned (most likely due to a packet sniffer such as	   tcpdump being momentarily attached to the interface), make	   a copy of our own to modify */	if(skb_cloned(skb)) {		if#ifdef SKB_COW_NEW	       (skb_cow(skb, skb_headroom(skb)) != 0)#else /* SKB_COW_NEW */	       ((skb = skb_cow(skb, skb_headroom(skb))) == NULL)#endif /* SKB_COW_NEW */		{			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,				    "klips_error:ipsec_tunnel_start_xmit: "				    "skb_cow failed to allocate buffer, dropping.\n" );			stats->tx_dropped++;			goto cleanup;		}	}#endif /* NET_21 */#ifdef NET_21	iph = skb->nh.iph;#else /* NET_21 */	iph = skb->ip_hdr;#endif /* NET_21 */	/* sanity check for IP version as we can't handle IPv6 right now */	if (iph->version != 4) {		KLIPS_PRINT(debug_tunnel,			    "klips_debug:ipsec_tunnel_start_xmit: "			    "found IP Version %d but cannot process other IP versions than v4.\n",			    iph->version); /* XXX */		stats->tx_dropped++;		goto cleanup;	}		/* physdev->hard_header_len is unreliable and should not be used */	hard_header_len = (unsigned char *)iph - skb->data;	if(hard_header_len < 0) {		KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,			    "klips_error:ipsec_tunnel_start_xmit: "			    "Negative hard_header_len (%d)?!\n", hard_header_len);		stats->tx_dropped++;		goto cleanup;	}	if(hard_header_len == 0) { /* no hard header present */		hard_header_stripped = 1;	}#ifdef CONFIG_IPSEC_DEBUG	if (debug_tunnel & DB_TN_XMIT) {		int i;		char c;				printk(KERN_INFO "klips_debug:ipsec_tunnel_start_xmit: "		       ">>> skb->len=%ld hard_header_len:%d",		       (unsigned long int)skb->len, hard_header_len);		c = ' ';		for (i=0; i < hard_header_len; i++) {			printk("%c%02x", c, skb->data[i]);			c = ':';		}		printk(" \n");	}#endif /* CONFIG_IPSEC_DEBUG */	KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, iph);	/*	 * Sanity checks	 */	if ((iph->ihl << 2) != sizeof (struct iphdr)) {		KLIPS_PRINT(debug_tunnel,			    "klips_debug:ipsec_tunnel_start_xmit: "			    "cannot process IP header options yet.  May be mal-formed packet.\n"); /* XXX */		stats->tx_dropped++;		goto cleanup;	}	#ifndef NET_21	/* TTL decrement code (on the way out!) borrowed from ip_forward.c */	if(0) {		unsigned long checksum = iph->check;		iph->ttl--;	/*	 *	Re-compute the IP header checksum.	 *	This is efficient. We know what has happened to the header	 *	and can thus adjust the checksum as Phil Karn does in KA9Q	 *	except we do this in "network byte order".	 */		checksum += htons(0x0100);		/* carry overflow? */		checksum += checksum >> 16;		iph->check = checksum;	}	if (iph->ttl <= 0) {		/* Tell the sender its packet died... */		ICMP_SEND(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0, physdev);		KLIPS_PRINT(debug_tunnel, "klips_debug:ipsec_tunnel_start_xmit: "			    "TTL=0, too many hops!\n");		stats->tx_dropped++;		goto cleanup;	}#endif /* !NET_21 */	/*	 * First things first -- look us up in the erouting tables.	 */	matcher.sen_len = sizeof (struct sockaddr_encap);	matcher.sen_family = AF_ENCAP;	matcher.sen_type = SENT_IP4;	matcher.sen_ip_src.s_addr = iph->saddr;	matcher.sen_ip_dst.s_addr = iph->daddr;	/*	 * The spinlock is to prevent any other process from accessing or deleting	 * the eroute while we are using and updating it.	 */	spin_lock(&eroute_lock);		er = ipsec_findroute(&matcher);	if(er) {		outgoing_said = er->er_said;		eroute_pid = er->er_pid;		er->er_count++;		er->er_lasttime = jiffies/HZ;	}	spin_unlock(&eroute_lock);	/*	 * Quick cheat for now...are we udp/500? If so, let it through	 * without interference since it is most likely an IKE packet.	 */	if((ip_chk_addr((unsigned long)iph->saddr) == IS_MYADDR)	   && ((!er)	       || (iph->daddr == outgoing_said.dst.s_addr)	       || (INADDR_ANY == outgoing_said.dst.s_addr))	   && (iph->protocol == IPPROTO_UDP)	   && (ntohs(((struct udphdr*)((caddr_t)iph + (iph->ihl << 2)))->dest) == 500)) {#ifdef NET_21		pass = 1;#endif /* NET_21 */		KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,			    "klips_debug:ipsec_tunnel_start_xmit: "			    "udp/500 IKE packet, sending unprocessed, "			    "calling dev_queue_xmit\n"); 		goto bypass;	}	KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,		    "klips_debug:ipsec_tunnel_start_xmit: "		    "Original head,tailroom: %d,%d\n",		    skb_headroom(skb), skb_tailroom(skb));	innersrc = iph->saddr;	/* start encapsulation loop here XXX */	do {		struct tdb *tdbprev = NULL;		newdst = orgdst = iph->daddr;		newsrc = orgsrc = iph->saddr;		orgedst = outgoing_said.dst.s_addr;		iphlen = iph->ihl << 2;		pyldsz = ntohs(iph->tot_len) - iphlen;		max_headroom = max_tailroom = 0;				if(er == NULL || (outgoing_said.proto==IPPROTO_INT				  && outgoing_said.spi==htonl(SPI_DROP))) {			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,				    "klips_debug:ipsec_tunnel_start_xmit: "				    "shunt SA of DROP or no eroute: dropping.\n");			stats->tx_dropped++;			goto cleanup;		}				if(outgoing_said.proto==IPPROTO_INT		   && outgoing_said.spi==htonl(SPI_REJECT)) {			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,				    "klips_debug:ipsec_tunnel_start_xmit: "				    "shunt SA of REJECT: notifying when coded... and dropping.\n");			stats->tx_dropped++;			goto cleanup;		}				if(outgoing_said.proto==IPPROTO_INT		   && outgoing_said.spi==htonl(SPI_PASS)) {#ifdef NET_21			pass = 1;#endif /* NET_21 */			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,				    "klips_debug:ipsec_tunnel_start_xmit: "				    "shunt SA of PASS: calling dev_queue_xmit\n");			goto bypass;		}		if(outgoing_said.proto==IPPROTO_INT		   && outgoing_said.spi==htonl(SPI_HOLD)) {			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,				    "klips_debug:ipsec_tunnel_start_xmit: "				    "shunt SA of HOLD: will stash when coded..., dropping for now.\n");			stats->tx_dropped++;			goto cleanup;		}				if(outgoing_said.proto==IPPROTO_INT		   && outgoing_said.spi==htonl(SPI_TRAP)) {			struct tdb tdb;			struct sockaddr_in src, dst;#ifdef CONFIG_IPSEC_DEBUG			char bufsrc[ADDRTOA_BUF], bufdst[ADDRTOA_BUF];#endif /* CONFIG_IPSEC_DEBUG */			struct eroute hold_eroute;			struct sa_id hold_said;						/* Signal all listening KMds with a PF_KEY ACQUIRE */			tdb.tdb_said.proto = iph->protocol;			src.sin_family = AF_INET;			dst.sin_family = AF_INET;			src.sin_addr.s_addr = iph->saddr;			dst.sin_addr.s_addr = iph->daddr;			src.sin_port = 				(iph->protocol == IPPROTO_UDP				 ? ((struct udphdr*) (((caddr_t)iph) + (iph->ihl << 2)))->source				 : (iph->protocol == IPPROTO_TCP				    ? ((struct tcphdr*)((caddr_t)iph + (iph->ihl << 2)))->source				    : 0));			dst.sin_port = 				(iph->protocol == IPPROTO_UDP				 ? ((struct udphdr*) (((caddr_t)iph) + (iph->ihl << 2)))->dest				 : (iph->protocol == IPPROTO_TCP				    ? ((struct tcphdr*)((caddr_t)iph + (iph->ihl << 2)))->dest				    : 0));			for(i = 0;			    i < sizeof(struct sockaddr_in)				    - offsetof(struct sockaddr_in, sin_zero);			    i++) {				src.sin_zero[i] = 0;				dst.sin_zero[i] = 0;			}						tdb.tdb_addr_s = (struct sockaddr*)(&src);			tdb.tdb_addr_d = (struct sockaddr*)(&dst);			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,				    "klips_debug:ipsec_tunnel_start_xmit: "				    "SADB_ACQUIRE sent with src=%s:%d, dst=%s:%d, proto=%d.\n",				    addrtoa(((struct sockaddr_in*)(tdb.tdb_addr_s))->sin_addr, 0, bufsrc, sizeof(bufsrc)) <= ADDRTOA_BUF ? bufsrc : "BAD_ADDR",				    ((struct sockaddr_in*)(tdb.tdb_addr_s))->sin_port,				    addrtoa(((struct sockaddr_in*)(tdb.tdb_addr_d))->sin_addr, 0, bufdst, sizeof(bufdst)) <= ADDRTOA_BUF ? bufdst : "BAD_ADDR",				    ((struct sockaddr_in*)(tdb.tdb_addr_d))->sin_port,				    tdb.tdb_said.proto);			pfkey_acquire(&tdb);			/* install HOLD eroute */			memset((caddr_t)&hold_eroute, 0, sizeof(hold_eroute));			memset((caddr_t)&hold_said, 0, sizeof(hold_said));			hold_said.proto = IPPROTO_INT;			hold_said.spi = htonl(SPI_HOLD);			hold_said.dst.s_addr = 0L;			hold_eroute.er_eaddr.sen_len = sizeof(struct sockaddr_encap);			hold_eroute.er_emask.sen_len = sizeof(struct sockaddr_encap);			hold_eroute.er_eaddr.sen_family = AF_ENCAP;			hold_eroute.er_emask.sen_family = AF_ENCAP;			hold_eroute.er_eaddr.sen_type = SENT_IP4;			hold_eroute.er_emask.sen_type = 255;			hold_eroute.er_eaddr.sen_ip_src.s_addr = iph->saddr;			hold_eroute.er_eaddr.sen_ip_dst.s_addr = iph->daddr;			hold_eroute.er_emask.sen_ip_src.s_addr = INADDR_BROADCAST;			hold_eroute.er_emask.sen_ip_dst.s_addr = INADDR_BROADCAST;						hold_eroute.er_pid = eroute_pid;			hold_eroute.er_count = 0;			hold_eroute.er_lasttime = jiffies/HZ;#ifdef IPSEC_CONFIG_FULL_SELECTOR_LIST			/* These are ficticious.  Don't uncomment these until			   proto, sport and dport exist in the SPDB */			hold_eroute.er_proto = iph->protocol;			hold_eroute.er_src_port = 				(iph->protocol == IPPROTO_UDP				 ? ((struct udphdr*) (((caddr_t)iph) + (iph->ihl << 2)))->source				 : (iph->protocol == IPPROTO_TCP				    ? ((struct tcphdr*)((caddr_t)iph + (iph->ihl << 2)))->source				    : 0));			hold_eroute.er_dst_port = 				(iph->protocol == IPPROTO_UDP				 ? ((struct udphdr*) (((caddr_t)iph) + (iph->ihl << 2)))->dest				 : (iph->protocol == IPPROTO_TCP				    ? ((struct tcphdr*)((caddr_t)iph + (iph->ihl << 2)))->dest				    : 0));#endif /* IPSEC_CONFIG_FULL_SELECTOR_LIST */#ifdef CONFIG_IPSEC_DEBUG			if (debug_pfkey) {				char buf1[64], buf2[64];				subnettoa(hold_eroute.er_eaddr.sen_ip_src,					  hold_eroute.er_emask.sen_ip_src, 0, buf1, sizeof(buf1));				subnettoa(hold_eroute.er_eaddr.sen_ip_dst,					  hold_eroute.er_emask.sen_ip_dst, 0, buf2, sizeof(buf2));				KLIPS_PRINT(debug_pfkey,					    "klips_debug:ipsec_tunnel_start_xmit: "					    "calling breakeroute and makeroute for %s->%s HOLD eroute.\n",					    buf1, buf2);			}#endif /* CONFIG_IPSEC_DEBUG */			if (!(ipsec_breakroute(&(hold_eroute.er_eaddr),						      &(hold_eroute.er_emask)) == EINVAL)) {				KLIPS_PRINT(debug_pfkey,					    "klips_debug:ipsec_tunnel_start_xmit: "					    "breakeroute should have failed.\n");				/* SENDERR(-error); */			} else {				KLIPS_PRINT(debug_pfkey,					    "klips_debug:ipsec_tunnel_start_xmit: "					    "HOLD breakeroute found nothing as expected.\n");			}						if ((error = ipsec_makeroute(&(hold_eroute.er_eaddr),						     &(hold_eroute.er_emask),						     hold_said,						     eroute_pid))) {				KLIPS_PRINT(debug_pfkey,					    "klips_debug:ipsec_tunnel_start_xmit: "					    "HOLD makeroute returned %d, failed.\n", error);				/* SENDERR(-error); */			} else {				KLIPS_PRINT(debug_pfkey,					    "klips_debug:ipsec_tunnel_start_xmit: "					    "HOLD makeroute call successful.\n");			}						goto cleanup;		}				/*		  The spinlock is to prevent any other process from		  accessing or deleting the TDB hash table or any of the		  TDBs while we are using and updating them.		  

⌨️ 快捷键说明

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