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

📄 ipsec_tunnel.c

📁 This a good VPN source
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * IPSEC Tunneling code. Heavily based on drivers/net/new_tunnel.c * Copyright (C) 1996, 1997  John Ioannidis. * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003  Richard Guy Briggs. *  * 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 ipsec_tunnel_c_version[] = "RCSID $Id: ipsec_tunnel.c,v 1.227 2004/12/10 21:16:08 ken Exp $";#define __NO_VERSION__#include <linux/module.h>#include <linux/config.h>	/* for CONFIG_IP_FORWARD */#include <linux/version.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>  /* size_t */#include <linux/interrupt.h> /* mark_bh */#include <net/tcp.h>#include <net/udp.h>#include <linux/skbuff.h>#include <linux/netdevice.h>   /* struct device, struct net_device_stats, dev_queue_xmit() 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 <asm/uaccess.h># include <linux/in6.h># define ip_chk_addr inet_addr_type# define IS_MYADDR RTN_LOCAL# include <net/dst.h># undef dev_kfree_skb# define dev_kfree_skb(a,b) kfree_skb(a)# define PHYSDEV_TYPE#endif /* NET_21 */#include <asm/checksum.h>#include <net/icmp.h>		/* icmp_send() */#include <net/ip.h>#ifdef NETDEV_23# include <linux/netfilter_ipv4.h>#endif /* NETDEV_23 */#include <linux/if_arp.h>#include "openswan/ipsec_kversion.h"#include "openswan/radij.h"#include "openswan/ipsec_life.h"#include "openswan/ipsec_xform.h"#include "openswan/ipsec_eroute.h"#include "openswan/ipsec_encap.h"#include "openswan/ipsec_radij.h"#include "openswan/ipsec_sa.h"#include "openswan/ipsec_tunnel.h"#include "openswan/ipsec_xmit.h"#include "openswan/ipsec_ipe4.h"#include "openswan/ipsec_ah.h"#include "openswan/ipsec_esp.h"#include "openswan/ipsec_kern24.h"#include <pfkeyv2.h>#include <pfkey.h>#include "openswan/ipsec_proto.h"#ifdef CONFIG_KLIPS_NAT_TRAVERSAL#include <linux/udp.h>#endifstatic __u32 zeroes[64];#ifdef CONFIG_KLIPS_DEBUGint debug_tunnel = 0;#endif /* CONFIG_KLIPS_DEBUG */DEBUG_NO_STATIC intipsec_tunnel_open(struct net_device *dev){	struct ipsecpriv *prv = dev->priv;		/*	 * Can't open until attached.	 */	KLIPS_PRINT(debug_tunnel & DB_TN_INIT,		    "klips_debug:ipsec_tunnel_open: "		    "dev = %s, prv->dev = %s\n",		    dev->name, prv->dev?prv->dev->name:"NONE");	if (prv->dev == NULL)		return -ENODEV;		KLIPS_INC_USE;	return 0;}DEBUG_NO_STATIC intipsec_tunnel_close(struct net_device *dev){	KLIPS_DEC_USE;	return 0;}#ifdef NETDEV_23static inline int ipsec_tunnel_xmit2(struct sk_buff *skb){#ifdef NETDEV_25	/* 2.6 kernels */	return dst_output(skb);#else	return ip_send(skb);#endif}#endif /* NETDEV_23 */enum ipsec_xmit_valueipsec_tunnel_strip_hard_header(struct ipsec_xmit_state *ixs){	/* ixs->physdev->hard_header_len is unreliable and should not be used */        ixs->hard_header_len = (unsigned char *)(ixs->iph) - ixs->skb->data;	if(ixs->hard_header_len < 0) {		KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,			    "klips_error:ipsec_xmit_strip_hard_header: "			    "Negative hard_header_len (%d)?!\n", ixs->hard_header_len);		ixs->stats->tx_dropped++;		return IPSEC_XMIT_BADHHLEN;	}	/* while ixs->physdev->hard_header_len is unreliable and	 * should not be trusted, it accurate and required for ATM, GRE and	 * some other interfaces to work. Thanks to Willy Tarreau 	 * <willy@w.ods.org>.	 */	if(ixs->hard_header_len == 0) { /* no hard header present */		ixs->hard_header_stripped = 1;		ixs->hard_header_len = ixs->physdev->hard_header_len;	}#ifdef CONFIG_KLIPS_DEBUG	if (debug_tunnel & DB_TN_XMIT) {		int i;		char c;				printk(KERN_INFO "klips_debug:ipsec_xmit_strip_hard_header: "		       ">>> skb->len=%ld hard_header_len:%d",		       (unsigned long int)ixs->skb->len, ixs->hard_header_len);		c = ' ';		for (i=0; i < ixs->hard_header_len; i++) {			printk("%c%02x", c, ixs->skb->data[i]);			c = ':';		}		printk(" \n");	}#endif /* CONFIG_KLIPS_DEBUG */	KLIPS_IP_PRINT(debug_tunnel & DB_TN_XMIT, ixs->iph);	KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,		    "klips_debug:ipsec_xmit_strip_hard_header: "		    "Original head,tailroom: %d,%d\n",		    skb_headroom(ixs->skb), skb_tailroom(ixs->skb));	return IPSEC_XMIT_OK;}enum ipsec_xmit_valueipsec_tunnel_SAlookup(struct ipsec_xmit_state *ixs){	unsigned int bypass;	bypass = FALSE;	/*	 * First things first -- look us up in the erouting tables.	 */	ixs->matcher.sen_len = sizeof (struct sockaddr_encap);	ixs->matcher.sen_family = AF_ENCAP;	ixs->matcher.sen_type = SENT_IP4;	ixs->matcher.sen_ip_src.s_addr = ixs->iph->saddr;	ixs->matcher.sen_ip_dst.s_addr = ixs->iph->daddr;	ixs->matcher.sen_proto = ixs->iph->protocol;	ipsec_extract_ports(ixs->iph, &ixs->matcher);	/*	 * 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);		ixs->eroute = ipsec_findroute(&ixs->matcher);	if(ixs->iph->protocol == IPPROTO_UDP) {		struct udphdr *t = NULL;		KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,			    "klips_debug:udp port check: "			    "fragoff: %d len: %d>%ld \n",			    ntohs(ixs->iph->frag_off) & IP_OFFSET,			    (ixs->skb->len - ixs->hard_header_len),                            (unsigned long int) ((ixs->iph->ihl << 2) + sizeof(struct udphdr)));				if((ntohs(ixs->iph->frag_off) & IP_OFFSET) == 0 &&		   ((ixs->skb->len - ixs->hard_header_len) >=		    ((ixs->iph->ihl << 2) + sizeof(struct udphdr))))		{			t =((struct udphdr*)((caddr_t)ixs->iph+(ixs->iph->ihl<<2)));			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,				    "klips_debug:udp port in packet: "				    "port %d -> %d\n",				    ntohs(t->source), ntohs(t->dest));		}		ixs->sport=0; ixs->dport=0;		if(ixs->skb->sk) {#ifdef NET_26			struct udp_sock *us;						us = (struct udp_sock *)ixs->skb->sk;			ixs->sport = ntohs(us->inet.sport);			ixs->dport = ntohs(us->inet.dport);#else			ixs->sport = ntohs(ixs->skb->sk->sport);			ixs->dport = ntohs(ixs->skb->sk->dport);#endif		} 		if(t != NULL) {			if(ixs->sport == 0) {				ixs->sport = ntohs(t->source);			}			if(ixs->dport == 0) {				ixs->dport = ntohs(t->dest);			}		}	}	/*	 * practically identical to above, but let's be careful about	 * tcp vs udp headers	 */	if(ixs->iph->protocol == IPPROTO_TCP) {		struct tcphdr *t = NULL;		if((ntohs(ixs->iph->frag_off) & IP_OFFSET) == 0 &&		   ((ixs->skb->len - ixs->hard_header_len) >=		    ((ixs->iph->ihl << 2) + sizeof(struct tcphdr)))) {			t =((struct tcphdr*)((caddr_t)ixs->iph+(ixs->iph->ihl<<2)));		}		ixs->sport=0; ixs->dport=0;		if(ixs->skb->sk) {#ifdef NET_26			struct tcp_tw_bucket *tw;						tw = (struct tcp_tw_bucket *)ixs->skb->sk;			ixs->sport = ntohs(tw->tw_sport);			ixs->dport = ntohs(tw->tw_dport);#else			ixs->sport = ntohs(ixs->skb->sk->sport);			ixs->dport = ntohs(ixs->skb->sk->dport);#endif		} 		if(t != NULL) {			if(ixs->sport == 0) {				ixs->sport = ntohs(t->source);			}			if(ixs->dport == 0) {				ixs->dport = ntohs(t->dest);			}		}	}		/* default to a %drop eroute */	ixs->outgoing_said.proto = IPPROTO_INT;	ixs->outgoing_said.spi = htonl(SPI_DROP);	ixs->outgoing_said.dst.u.v4.sin_addr.s_addr = INADDR_ANY;	KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,		    "klips_debug:ipsec_xmit_SAlookup: "		    "checking for local udp/500 IKE packet "		    "saddr=%x, er=0p%p, daddr=%x, er_dst=%x, proto=%d sport=%d dport=%d\n",		    ntohl((unsigned int)ixs->iph->saddr),		    ixs->eroute,		    ntohl((unsigned int)ixs->iph->daddr),		    ixs->eroute ? ntohl((unsigned int)ixs->eroute->er_said.dst.u.v4.sin_addr.s_addr) : 0,		    ixs->iph->protocol,		    ixs->sport,		    ixs->dport); 	/*	 * 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)ixs->iph->saddr) == IS_MYADDR	    && (ixs->eroute==NULL		|| ixs->iph->daddr == ixs->eroute->er_said.dst.u.v4.sin_addr.s_addr		|| INADDR_ANY == ixs->eroute->er_said.dst.u.v4.sin_addr.s_addr)	    && (ixs->iph->protocol == IPPROTO_UDP && ixs->sport == 500)) {		/* Whatever the eroute, this is an IKE message 		 * from us (i.e. not being forwarded).		 * Furthermore, if there is a tunnel eroute,		 * the destination is the peer for this eroute.		 * So %pass the packet: modify the default %drop.		 */		ixs->outgoing_said.spi = htonl(SPI_PASS);		if(!(ixs->skb->sk) && ((ntohs(ixs->iph->frag_off) & IP_MF) != 0)) {			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,				    "klips_debug:ipsec_xmit_SAlookup: "				    "local UDP/500 (probably IKE) passthrough: base fragment, rest of fragments will probably get filtered.\n");		}		bypass = TRUE;	}#ifdef KLIPS_EXCEPT_DNS53	/*	 *	 * if we are udp/53 or tcp/53, also let it through a %trap or %hold,	 * since it is DNS, but *also* follow the %trap.	 * 	 * we do not do this for tunnels, only %trap's and %hold's.	 *	 */	if (ip_chk_addr((unsigned long)ixs->iph->saddr) == IS_MYADDR	    && (ixs->eroute==NULL		|| ixs->iph->daddr == ixs->eroute->er_said.dst.u.v4.sin_addr.s_addr		|| INADDR_ANY == ixs->eroute->er_said.dst.u.v4.sin_addr.s_addr)	    && ((ixs->iph->protocol == IPPROTO_UDP		 || ixs->iph->protocol == IPPROTO_TCP)		&& ixs->dport == 53)) {				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,			    "klips_debug:ipsec_xmit_SAlookup: "			    "possible DNS packet\n");		if(ixs->eroute)		{			if(ixs->eroute->er_said.spi == htonl(SPI_TRAP)			   || ixs->eroute->er_said.spi == htonl(SPI_HOLD))			{				ixs->outgoing_said.spi = htonl(SPI_PASSTRAP);				bypass = TRUE;			}		}		else		{			ixs->outgoing_said.spi = htonl(SPI_PASSTRAP);			bypass = TRUE;		}						KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,			    "klips_debug:ipsec_xmit_SAlookup: "			    "bypass = %d\n", bypass);		if(bypass		   && !(ixs->skb->sk)		   && ((ntohs(ixs->iph->frag_off) & IP_MF) != 0))		{			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,				    "klips_debug:ipsec_xmit_SAlookup: "				    "local port 53 (probably DNS) passthrough:"				    "base fragment, rest of fragments will "				    "probably get filtered.\n");		}	}#endif	if (bypass==FALSE && ixs->eroute) {		ixs->eroute->er_count++;		ixs->eroute->er_lasttime = jiffies/HZ;		if(ixs->eroute->er_said.proto==IPPROTO_INT		   && ixs->eroute->er_said.spi==htonl(SPI_HOLD))		{			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,				    "klips_debug:ipsec_xmit_SAlookup: "				    "shunt SA of HOLD: skb stored in HOLD.\n");			if(ixs->eroute->er_last != NULL) {				kfree_skb(ixs->eroute->er_last);			}			ixs->eroute->er_last = ixs->skb;			ixs->skb = NULL;			ixs->stats->tx_dropped++;			spin_unlock(&eroute_lock);			return IPSEC_XMIT_STOLEN;		}		ixs->outgoing_said = ixs->eroute->er_said;		ixs->eroute_pid = ixs->eroute->er_pid;		/* Copy of the ident for the TRAP/TRAPSUBNET eroutes */		if(ixs->outgoing_said.proto==IPPROTO_INT		   && (ixs->outgoing_said.spi==htonl(SPI_TRAP)		       || (ixs->outgoing_said.spi==htonl(SPI_TRAPSUBNET)))) {			int len;						ixs->ips.ips_ident_s.type = ixs->eroute->er_ident_s.type;			ixs->ips.ips_ident_s.id = ixs->eroute->er_ident_s.id;			ixs->ips.ips_ident_s.len = ixs->eroute->er_ident_s.len;			if (ixs->ips.ips_ident_s.len)			{				len = ixs->ips.ips_ident_s.len * IPSEC_PFKEYv2_ALIGN - sizeof(struct sadb_ident);				KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,					    "klips_debug:ipsec_xmit_SAlookup: "					    "allocating %d bytes for ident_s shunt SA of HOLD: skb stored in HOLD.\n",					    len);				if ((ixs->ips.ips_ident_s.data = kmalloc(len, GFP_ATOMIC)) == NULL) {					printk(KERN_WARNING "klips_debug:ipsec_xmit_SAlookup: "					       "Failed, tried to allocate %d bytes for source ident.\n", 					       len);					ixs->stats->tx_dropped++;					spin_unlock(&eroute_lock);					return IPSEC_XMIT_ERRMEMALLOC;				}				memcpy(ixs->ips.ips_ident_s.data, ixs->eroute->er_ident_s.data, len);			}			ixs->ips.ips_ident_d.type = ixs->eroute->er_ident_d.type;			ixs->ips.ips_ident_d.id = ixs->eroute->er_ident_d.id;			ixs->ips.ips_ident_d.len = ixs->eroute->er_ident_d.len;			if (ixs->ips.ips_ident_d.len)

⌨️ 快捷键说明

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