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

📄 ipsec_xmit.c

📁 This a good VPN source
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * IPSEC Transmit code. * Copyright (C) 1996, 1997  John Ioannidis. * Copyright (C) 1998-2003   Richard Guy Briggs. * Copyright (C) 2004        Michael Richardson <mcr@xelerance.com> *  * 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_xmit_c_version[] = "RCSID $Id: ipsec_xmit.c,v 1.10 2004/09/13 17:55:21 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 <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/tcp.h>         /* struct tcphdr */#include <linux/udp.h>         /* struct udphdr */#include <linux/skbuff.h>#include <openswan.h>#ifdef NET_21# define MSS_HACK_		/* experimental */# include <asm/uaccess.h># include <linux/in6.h># include <net/dst.h># define proto_priv cb#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>#ifdef MSS_HACK# include <net/tcp.h>		/* TCP options */#endif	/* MSS_HACK */#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_xmit.h"#include "openswan/ipsec_sa.h"#include "openswan/ipsec_tunnel.h"#include "openswan/ipsec_ipe4.h"#include "openswan/ipsec_ah.h"#include "openswan/ipsec_esp.h"#ifdef CONFIG_KLIPS_IPCOMP#include "openswan/ipcomp.h"#endif /* CONFIG_KLIPS_IPCOMP */#include <pfkeyv2.h>#include <pfkey.h>#include "openswan/ipsec_proto.h"#include "openswan/ipsec_alg.h"/*  * Stupid kernel API differences in APIs. Not only do some * kernels not have ip_select_ident, but some have differing APIs, * and SuSE has one with one parameter, but no way of checking to * see what is really what. */#ifdef SUSE_LINUX_2_4_19_IS_STUPID#define KLIPS_IP_SELECT_IDENT(iph, skb) ip_select_ident(iph)#else/* simplest case, nothing */#if !defined(IP_SELECT_IDENT)#define KLIPS_IP_SELECT_IDENT(iph, skb)  do { iph->id = htons(ip_id_count++); } while(0)#endif/* kernels > 2.3.37-ish */#if defined(IP_SELECT_IDENT) && !defined(IP_SELECT_IDENT_NEW)#define KLIPS_IP_SELECT_IDENT(iph, skb) ip_select_ident(iph, skb->dst)#endif/* kernels > 2.4.2 */#if defined(IP_SELECT_IDENT) && defined(IP_SELECT_IDENT_NEW)#define KLIPS_IP_SELECT_IDENT(iph, skb) ip_select_ident(iph, skb->dst, NULL)#endif#endif /* SUSE_LINUX_2_4_19_IS_STUPID */static __u32 zeroes[64];#ifdef CONFIG_KLIPS_DEBUGint sysctl_ipsec_debug_verbose = 0;#endif /* CONFIG_KLIPS_DEBUG */int ipsec_xmit_trap_count = 0;int ipsec_xmit_trap_sendcount = 0;int sysctl_ipsec_icmp = 0;int sysctl_ipsec_tos = 0;#ifdef CONFIG_KLIPS_DEBUG_DEBUG_NO_STATIC voiddmp(char *s, caddr_t bb, int len){	int i;	unsigned char *b = bb;  	if (debug_tunnel) {		printk(KERN_INFO "klips_debug:ipsec_tunnel_:dmp: "		       "at %s, len=%d:",		       s,		       len);		for (i=0; i < len; i++) {			if(!(i%16)){				printk("\nklips_debug:  ");			}			printk(" %02x", *b++);		}		printk("\n");	}}#else /* CONFIG_KLIPS_DEBUG */#define dmp(_x, _y, _z) #endif /* CONFIG_KLIPS_DEBUG */#ifndef SKB_COPY_EXPAND/* *	This is mostly skbuff.c:skb_copy(). */struct sk_buff *skb_copy_expand(struct sk_buff *skb, int headroom, int tailroom, int priority){	struct sk_buff *n;	unsigned long offset;	/*	 *	Do sanity checking	 */	if((headroom < 0) || (tailroom < 0) || ((headroom+tailroom) < 0)) {		printk(KERN_WARNING		       "klips_error:skb_copy_expand: "		       "Illegal negative head,tailroom %d,%d\n",		       headroom,		       tailroom);		return NULL;	}	/*	 *	Allocate the copy buffer	 */	 #ifndef NET_21	IS_SKB(skb);#endif /* !NET_21 */	n=alloc_skb(skb->end - skb->head + headroom + tailroom, priority);	KLIPS_PRINT(debug_tunnel & DB_TN_CROUT,		    "klips_debug:skb_copy_expand: "		    "allocating %d bytes, head=0p%p data=0p%p tail=0p%p end=0p%p end-head=%d tail-data=%d\n",		    skb->end - skb->head + headroom + tailroom,		    skb->head,		    skb->data,		    skb->tail,		    skb->end,		    skb->end - skb->head,		    skb->tail - skb->data);	if(n==NULL)		return NULL;	/*	 *	Shift between the two data areas in bytes	 */	 	/* Set the data pointer */	skb_reserve(n,skb->data-skb->head+headroom);	/* Set the tail pointer and length */	if(skb_tailroom(n) < skb->len) {		printk(KERN_WARNING "klips_error:skb_copy_expand: "		       "tried to skb_put %ld, %d available.  This should never happen, please report.\n",		       (unsigned long int)skb->len,		       skb_tailroom(n));		ipsec_kfree_skb(n);		return NULL;	}	skb_put(n,skb->len);	offset=n->head + headroom - skb->head;	/* Copy the bytes */	memcpy(n->head + headroom, skb->head,skb->end-skb->head);#ifdef NET_21	n->csum=skb->csum;	n->priority=skb->priority;	n->dst=dst_clone(skb->dst);	if(skb->nh.raw)		n->nh.raw=skb->nh.raw+offset;#ifndef NETDEV_23	n->is_clone=0;#endif /* NETDEV_23 */	atomic_set(&n->users, 1);	n->destructor = NULL;	n->security=skb->security;#else /* NET_21 */	n->link3=NULL;	n->when=skb->when;	if(skb->ip_hdr)	        n->ip_hdr=(struct iphdr *)(((char *)skb->ip_hdr)+offset);	n->saddr=skb->saddr;	n->daddr=skb->daddr;	n->raddr=skb->raddr;	n->seq=skb->seq;	n->end_seq=skb->end_seq;	n->ack_seq=skb->ack_seq;	n->acked=skb->acked;	n->free=1;	n->arp=skb->arp;	n->tries=0;	n->lock=0;	n->users=0;#endif /* NET_21 */	n->protocol=skb->protocol;	n->list=NULL;	n->sk=NULL;	n->dev=skb->dev;	if(skb->h.raw)		n->h.raw=skb->h.raw+offset;	if(skb->mac.raw) 		n->mac.raw=skb->mac.raw+offset;	memcpy(n->proto_priv, skb->proto_priv, sizeof(skb->proto_priv));#ifndef NETDEV_23	n->used=skb->used;#endif /* !NETDEV_23 */	n->pkt_type=skb->pkt_type;	n->stamp=skb->stamp;	#ifndef NET_21	IS_SKB(n);#endif /* !NET_21 */	return n;}#endif /* !SKB_COPY_EXPAND */#ifdef CONFIG_KLIPS_DEBUGvoidipsec_print_ip(struct iphdr *ip){	char buf[ADDRTOA_BUF];	printk(KERN_INFO "klips_debug:   IP:");	printk(" ihl:%d", ip->ihl << 2);	printk(" ver:%d", ip->version);	printk(" tos:%d", ip->tos);	printk(" tlen:%d", ntohs(ip->tot_len));	printk(" id:%d", ntohs(ip->id));	printk(" %s%s%sfrag_off:%d",               ip->frag_off & __constant_htons(IP_CE) ? "CE " : "",               ip->frag_off & __constant_htons(IP_DF) ? "DF " : "",               ip->frag_off & __constant_htons(IP_MF) ? "MF " : "",               (ntohs(ip->frag_off) & IP_OFFSET) << 3);	printk(" ttl:%d", ip->ttl);	printk(" proto:%d", ip->protocol);	if(ip->protocol == IPPROTO_UDP)		printk(" (UDP)");	if(ip->protocol == IPPROTO_TCP)		printk(" (TCP)");	if(ip->protocol == IPPROTO_ICMP)		printk(" (ICMP)");	printk(" chk:%d", ntohs(ip->check));	addrtoa(*((struct in_addr*)(&ip->saddr)), 0, buf, sizeof(buf));	printk(" saddr:%s", buf);	if(ip->protocol == IPPROTO_UDP)		printk(":%d",		       ntohs(((struct udphdr*)((caddr_t)ip + (ip->ihl << 2)))->source));	if(ip->protocol == IPPROTO_TCP)		printk(":%d",		       ntohs(((struct tcphdr*)((caddr_t)ip + (ip->ihl << 2)))->source));	addrtoa(*((struct in_addr*)(&ip->daddr)), 0, buf, sizeof(buf));	printk(" daddr:%s", buf);	if(ip->protocol == IPPROTO_UDP)		printk(":%d",		       ntohs(((struct udphdr*)((caddr_t)ip + (ip->ihl << 2)))->dest));	if(ip->protocol == IPPROTO_TCP)		printk(":%d",		       ntohs(((struct tcphdr*)((caddr_t)ip + (ip->ihl << 2)))->dest));	if(ip->protocol == IPPROTO_ICMP)		printk(" type:code=%d:%d",		       ((struct icmphdr*)((caddr_t)ip + (ip->ihl << 2)))->type,		       ((struct icmphdr*)((caddr_t)ip + (ip->ihl << 2)))->code);	printk("\n");	if(sysctl_ipsec_debug_verbose) {		__u8 *c;		int i;				c = ((__u8*)ip) + ip->ihl*4;		for(i = 0; i < ntohs(ip->tot_len) - ip->ihl*4; i++ /*, c++*/) {			if(!(i % 16)) {				printk(KERN_INFO				       "klips_debug:   @%03x:",				       i);			}			printk(" %02x", /***/c[i]);			if(!((i + 1) % 16)) {				printk("\n");			}		}		if(i % 16) {			printk("\n");		}	}}#endif /* CONFIG_KLIPS_DEBUG */#ifdef MSS_HACK/* * Issues: *  1) Fragments arriving in the tunnel should probably be rejected. *  2) How does this affect syncookies, mss_cache, dst cache ? *  3) Path MTU discovery handling needs to be reviewed.  For example, *     if we receive an ICMP 'packet too big' message from an intermediate  *     router specifying it's next hop MTU, our stack may process this and *     adjust the MSS without taking our AH/ESP overheads into account. */ /* * Recaclulate checksum using differences between changed datum,  * borrowed from netfilter. */DEBUG_NO_STATIC u_int16_t ipsec_fast_csum(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck){	u_int32_t diffs[] = { oldvalinv, newval };	return csum_fold(csum_partial((char *)diffs, sizeof(diffs),	oldcheck^0xFFFF));}/* * Determine effective MSS. * * Note that we assume that there is always an MSS option for our own * SYN segments, which is mentioned in tcp_syn_build_options(), kernel 2.2.x. * This could change, and we should probably parse TCP options instead. * */DEBUG_NO_STATIC u_int8_tipsec_adjust_mss(struct sk_buff *skb, struct tcphdr *tcph, u_int16_t mtu){	u_int16_t oldmss, newmss;	u_int32_t *mssp;	struct sock *sk = skb->sk;		newmss = tcp_sync_mss(sk, mtu);	printk(KERN_INFO "klips: setting mss to %u\n", newmss);	mssp = (u_int32_t *)tcph + sizeof(struct tcphdr) / sizeof(u_int32_t);	oldmss = ntohl(*mssp) & 0x0000FFFF;	*mssp = htonl((TCPOPT_MSS << 24) | (TCPOLEN_MSS << 16) | newmss);	tcph->check = ipsec_fast_csum(htons(~oldmss), 	                              htons(newmss), tcph->check);	return 1;}#endif	/* MSS_HACK */                                                        /* * Sanity checks */enum ipsec_xmit_valueipsec_xmit_sanity_check_dev(struct ipsec_xmit_state *ixs){	if (ixs->dev == NULL) {		KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,			    "klips_error:ipsec_xmit_sanity_check_dev: "			    "No device associated with skb!\n" );		return IPSEC_XMIT_NODEV;	}	ixs->prv = ixs->dev->priv;	if (ixs->prv == NULL) {		KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,			    "klips_error:ipsec_xmit_sanity_check_dev: "			    "Device has no private structure!\n" );		return 	IPSEC_XMIT_NOPRIVDEV;	}	ixs->physdev = ixs->prv->dev;	if (ixs->physdev == NULL) {		KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,			    "klips_error:ipsec_xmit_sanity_check_dev: "			    "Device is not attached to physical device!\n" );		return IPSEC_XMIT_NOPHYSDEV;	}	ixs->physmtu = ixs->physdev->mtu;	ixs->stats = (struct net_device_stats *) &(ixs->prv->mystats);	return IPSEC_XMIT_OK;}enum ipsec_xmit_valueipsec_xmit_sanity_check_skb(struct ipsec_xmit_state *ixs){	/*	 *	Return if there is nothing to do.  (Does this ever happen?) XXX	 */	if (ixs->skb == NULL) {		KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,			    "klips_error:ipsec_xmit_sanity_check_skb: "			    "Nothing to do!\n" );		return IPSEC_XMIT_NOSKB;	}#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(ixs->skb)) {		if#ifdef SKB_COW_NEW	       (skb_cow(ixs->skb, skb_headroom(ixs->skb)) != 0)#else /* SKB_COW_NEW */	       ((ixs->skb = skb_cow(ixs->skb, skb_headroom(ixs->skb))) == NULL)#endif /* SKB_COW_NEW */		{			KLIPS_PRINT(debug_tunnel & DB_TN_XMIT,				    "klips_error:ipsec_xmit_sanity_check_skb: "				    "skb_cow failed to allocate buffer, dropping.\n" );			ixs->stats->tx_dropped++;			return IPSEC_XMIT_ERRSKBALLOC;		}	}#endif /* NET_21 */#ifdef NET_21	ixs->iph = ixs->skb->nh.iph;#else /* NET_21 */	ixs->iph = ixs->skb->ip_hdr;#endif /* NET_21 */	/* sanity check for IP version as we can't handle IPv6 right now */

⌨️ 快捷键说明

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