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

📄 ipsec_rcv.c

📁 This a good VPN source
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * receive 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_rcv_c_version[] = "RCSID $Id: ipsec_rcv.c,v 1.156 2004/12/03 21:34:51 mcr Exp $";#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>  /* size_t */#include <linux/interrupt.h> /* mark_bh */#include <linux/netdevice.h>	/* struct device, and other headers */#include <linux/etherdevice.h>	/* eth_type_trans */#include <linux/ip.h>		/* struct iphdr */#include <net/tcp.h>#include <net/udp.h>#include <linux/skbuff.h>#include <openswan.h>#ifdef SPINLOCK# ifdef SPINLOCK_23#  include <linux/spinlock.h> /* *lock* */# else /* SPINLOCK_23 */#  include <asm/spinlock.h> /* *lock* */# endif /* SPINLOCK_23 */#endif /* SPINLOCK */#ifdef NET_21# 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_radij.h"#include "openswan/ipsec_xform.h"#include "openswan/ipsec_tunnel.h"#include "openswan/ipsec_rcv.h"#include "openswan/ipsec_auth.h"#include "openswan/ipsec_esp.h"#ifdef CONFIG_KLIPS_AH#include "openswan/ipsec_ah.h"#endif /* CONFIG_KLIPS_AH */#ifdef CONFIG_KLIPS_IPCOMP#include "openswan/ipsec_ipcomp.h"#endif /* CONFIG_KLIPS_COMP */#include <pfkeyv2.h>#include <pfkey.h>#include "openswan/ipsec_proto.h"#include "openswan/ipsec_alg.h"#include "openswan/ipsec_kern24.h"#ifdef CONFIG_KLIPS_DEBUGint debug_rcv = 0;#endif /* CONFIG_KLIPS_DEBUG */int sysctl_ipsec_inbound_policy_check = 1;#ifdef CONFIG_KLIPS_NAT_TRAVERSAL#include <linux/udp.h>#endif/* This is a private use protocol, and AT&T should be ashamed. They should have * used protocol # 59, which is "no next header" instead of 0xFE. */#ifndef IPPROTO_ATT_HEARTBEAT#define IPPROTO_ATT_HEARTBEAT 0xFE#endif#ifdef CONFIG_KLIPS_DEBUGvoidipsec_dmp(char *s, caddr_t bb, int len){	int i;	unsigned char *b = bb;  		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");}#endif /* CONFIG_KLIPS_DEBUG *//* * Check-replay-window routine, adapted from the original * by J. Hughes, from draft-ietf-ipsec-esp-des-md5-03.txt * *  This is a routine that implements a 64 packet window. This is intend- *  ed on being an implementation sample. */DEBUG_NO_STATIC intipsec_checkreplaywindow(struct ipsec_sa*ipsp, __u32 seq){	__u32 diff;	if (ipsp->ips_replaywin == 0)	/* replay shut off */		return 1;	if (seq == 0)		return 0;		/* first == 0 or wrapped */	/* new larger sequence number */	if (seq > ipsp->ips_replaywin_lastseq) {		return 1;		/* larger is good */	}	diff = ipsp->ips_replaywin_lastseq - seq;	/* too old or wrapped */ /* if wrapped, kill off SA? */	if (diff >= ipsp->ips_replaywin) {		return 0;	}	/* this packet already seen */	if (ipsp->ips_replaywin_bitmap & (1 << diff))		return 0;	return 1;			/* out of order but good */}DEBUG_NO_STATIC intipsec_updatereplaywindow(struct ipsec_sa*ipsp, __u32 seq){	__u32 diff;	if (ipsp->ips_replaywin == 0)	/* replay shut off */		return 1;	if (seq == 0)		return 0;		/* first == 0 or wrapped */	/* new larger sequence number */	if (seq > ipsp->ips_replaywin_lastseq) {		diff = seq - ipsp->ips_replaywin_lastseq;		/* In win, set bit for this pkt */		if (diff < ipsp->ips_replaywin)			ipsp->ips_replaywin_bitmap =				(ipsp->ips_replaywin_bitmap << diff) | 1;		else			/* This packet has way larger seq num */			ipsp->ips_replaywin_bitmap = 1;		if(seq - ipsp->ips_replaywin_lastseq - 1 > ipsp->ips_replaywin_maxdiff) {			ipsp->ips_replaywin_maxdiff = seq - ipsp->ips_replaywin_lastseq - 1;		}		ipsp->ips_replaywin_lastseq = seq;		return 1;		/* larger is good */	}	diff = ipsp->ips_replaywin_lastseq - seq;	/* too old or wrapped */ /* if wrapped, kill off SA? */	if (diff >= ipsp->ips_replaywin) {/*		if(seq < 0.25*max && ipsp->ips_replaywin_lastseq > 0.75*max) {			ipsec_sa_delchain(ipsp);		}*/		return 0;	}	/* this packet already seen */	if (ipsp->ips_replaywin_bitmap & (1 << diff))		return 0;	ipsp->ips_replaywin_bitmap |= (1 << diff);	/* mark as seen */	return 1;			/* out of order but good */}#ifdef CONFIG_KLIPS_AUTH_HMAC_MD5struct auth_alg ipsec_rcv_md5[]={	{osMD5Init, osMD5Update, osMD5Final, AHMD596_ALEN}};#endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */#ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1struct auth_alg ipsec_rcv_sha1[]={	{SHA1Init, SHA1Update, SHA1Final, AHSHA196_ALEN}};#endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */enum ipsec_rcv_valueipsec_rcv_decap_once(struct ipsec_rcv_state *irs, struct xform_functions *proto_funcs){	int iphlen;	unsigned char *dat;	__u8 proto;	struct in_addr ipsaddr;	struct in_addr ipdaddr;	int replay = 0;	/* replay value in AH or ESP packet */	struct ipsec_sa* ipsnext = NULL;	/* next SA towards inside of packet */	struct ipsec_sa *newipsp;	struct iphdr *ipp;	struct sk_buff *skb;#ifdef CONFIG_KLIPS_ALG	struct ipsec_alg_auth *ixt_a=NULL;#endif /* CONFIG_KLIPS_ALG */	skb = irs->skb;	irs->len = skb->len;	dat = skb->data;	ipp = irs->ipp;	proto = ipp->protocol;	ipsaddr.s_addr = ipp->saddr;	addrtoa(ipsaddr, 0, irs->ipsaddr_txt, sizeof(irs->ipsaddr_txt));	ipdaddr.s_addr = ipp->daddr;	addrtoa(ipdaddr, 0, irs->ipdaddr_txt, sizeof(irs->ipdaddr_txt));	iphlen = ipp->ihl << 2;	irs->iphlen=iphlen;	ipp->check = 0;			/* we know the sum is good */		KLIPS_PRINT(debug_rcv,		    "klips_debug:ipsec_rcv_decap_once: "		    "decap (%d) from %s -> %s\n",		    proto, irs->ipsaddr_txt, irs->ipdaddr_txt);	/*	 * Find tunnel control block and (indirectly) call the	 * appropriate tranform routine. The resulting sk_buf	 * is a valid IP packet ready to go through input processing.	 */	irs->said.dst.u.v4.sin_addr.s_addr = ipp->daddr;	irs->said.dst.u.v4.sin_family = AF_INET;	if(proto_funcs->rcv_checks) {		enum ipsec_rcv_value retval =		  (*proto_funcs->rcv_checks)(irs, skb);		if(retval < 0) {			return retval;		}	}	irs->said.proto = proto;	irs->sa_len = satot(&irs->said, 0, irs->sa, sizeof(irs->sa));	if(irs->sa_len == 0) {		strcpy(irs->sa, "(error)");	}	newipsp = ipsec_sa_getbyid(&irs->said);	if (newipsp == NULL) {		KLIPS_PRINT(debug_rcv,			    "klips_debug:ipsec_rcv: "			    "no ipsec_sa for SA:%s: incoming packet with no SA dropped\n",			    irs->sa_len ? irs->sa : " (error)");		if(irs->stats) {			irs->stats->rx_dropped++;		}		return IPSEC_RCV_SAIDNOTFOUND;	}	/* MCR - XXX this is bizarre. ipsec_sa_getbyid returned it, having incremented the refcount,	 * why in the world would we decrement it here?	 ipsec_sa_put(irs->ipsp);*/ /* incomplete */	/* If it is in larval state, drop the packet, we cannot process yet. */	if(newipsp->ips_state == SADB_SASTATE_LARVAL) {		KLIPS_PRINT(debug_rcv,			    "klips_debug:ipsec_rcv: "			    "ipsec_sa in larval state, cannot be used yet, dropping packet.\n");		if(irs->stats) {			irs->stats->rx_dropped++;		}		ipsec_sa_put(newipsp);		return IPSEC_RCV_SAIDNOTLIVE;	}	if(newipsp->ips_state == SADB_SASTATE_DEAD) {		KLIPS_PRINT(debug_rcv,			    "klips_debug:ipsec_rcv: "			    "ipsec_sa in dead state, cannot be used any more, dropping packet.\n");		if(irs->stats) {			irs->stats->rx_dropped++;		}		ipsec_sa_put(newipsp);		return IPSEC_RCV_SAIDNOTLIVE;	}	if(sysctl_ipsec_inbound_policy_check) {		if(irs->ipp->saddr != ((struct sockaddr_in*)(newipsp->ips_addr_s))->sin_addr.s_addr) {			KLIPS_PRINT(debug_rcv,				    "klips_debug:ipsec_rcv: "				    "SA:%s, src=%s of pkt does not agree with expected SA source address policy.\n",				    irs->sa_len ? irs->sa : " (error)",				    irs->ipsaddr_txt);			if(irs->stats) {				irs->stats->rx_dropped++;			}			ipsec_sa_put(newipsp);			return IPSEC_RCV_FAILEDINBOUND;		}		KLIPS_PRINT(debug_rcv,			    "klips_debug:ipsec_rcv: "			    "SA:%s, src=%s of pkt agrees with expected SA source address policy.\n",			    irs->sa_len ? irs->sa : " (error)",			    irs->ipsaddr_txt);		/*		 * at this point, we have looked up a new SA, and we want to make sure that if this		 * isn't the first SA in the list, that the previous SA actually points at this one.		 */		if(irs->ipsp) {			if(irs->ipsp->ips_inext != newipsp) {				KLIPS_PRINT(debug_rcv,					    "klips_debug:ipsec_rcv: "					    "unexpected SA:%s: does not agree with ips->inext policy, dropped\n",					    irs->sa_len ? irs->sa : " (error)");				if(irs->stats) {					irs->stats->rx_dropped++;				}				ipsec_sa_put(newipsp);				return IPSEC_RCV_FAILEDINBOUND;			}			KLIPS_PRINT(debug_rcv,				    "klips_debug:ipsec_rcv: "				    "SA:%s grouping from previous SA is OK.\n",				    irs->sa_len ? irs->sa : " (error)");		} else {			KLIPS_PRINT(debug_rcv,				    "klips_debug:ipsec_rcv: "				    "SA:%s First SA in group.\n",				    irs->sa_len ? irs->sa : " (error)");		}		/*		 * previously, at this point, we checked if the back pointer from the new SA that		 * we just found matched the back pointer. But, we won't do this check anymore,		 * because we want to be able to nest SAs		 */#ifdef CONFIG_KLIPS_NAT_TRAVERSAL		KLIPS_PRINT(debug_rcv,			"klips_debug:ipsec_rcv: "			"natt_type=%u tdbp->ips_natt_type=%u : %s\n",			irs->natt_type, newipsp->ips_natt_type,			(irs->natt_type==newipsp->ips_natt_type)?"ok":"bad");		if (irs->natt_type != newipsp->ips_natt_type) {			KLIPS_PRINT(debug_rcv,				    "klips_debug:ipsec_rcv: "				    "SA:%s does not agree with expected NAT-T policy.\n",				    irs->sa_len ? irs->sa : " (error)");			if(irs->stats) {				irs->stats->rx_dropped++;			}			ipsec_sa_put(newipsp);			return IPSEC_RCV_FAILEDINBOUND;		}#endif		 	}	/* okay, SA checks out, so free any previous SA, and record a new one */	if(irs->ipsp) {		ipsec_sa_put(irs->ipsp);	}	irs->ipsp=newipsp;	/* note that the outer code will free the irs->ipsp if there is an error */	/* now check the lifetimes */	if(ipsec_lifetime_check(&irs->ipsp->ips_life.ipl_bytes,   "bytes",				irs->sa, ipsec_life_countbased, ipsec_incoming,				irs->ipsp) == ipsec_life_harddied ||	   ipsec_lifetime_check(&irs->ipsp->ips_life.ipl_addtime, "addtime",				irs->sa, ipsec_life_timebased,  ipsec_incoming,				irs->ipsp) == ipsec_life_harddied ||	   ipsec_lifetime_check(&irs->ipsp->ips_life.ipl_addtime, "usetime",				irs->sa, ipsec_life_timebased,  ipsec_incoming,				irs->ipsp) == ipsec_life_harddied ||

⌨️ 快捷键说明

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