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

📄 ipsec_rcv.c

📁 This a good VPN source
💻 C
📖 第 1 页 / 共 5 页
字号:
	   ipsec_lifetime_check(&irs->ipsp->ips_life.ipl_packets, "packets",				irs->sa, ipsec_life_countbased, ipsec_incoming,				irs->ipsp) == ipsec_life_harddied) {		ipsec_sa_delchain(irs->ipsp);		if(irs->stats) {			irs->stats->rx_dropped++;		}				KLIPS_PRINT(debug_rcv,			    "klips_debug:ipsec_rcv_decap_once: "			    "decap (%d) failed lifetime check\n",			    proto);		return IPSEC_RCV_LIFETIMEFAILED;	}#ifdef CONFIG_KLIPS_NAT_TRAVERSAL	if ((irs->natt_type) &&		( (irs->ipp->saddr != (((struct sockaddr_in*)(newipsp->ips_addr_s))->sin_addr.s_addr)) ||		  (irs->natt_sport != newipsp->ips_natt_sport)		)) {		struct sockaddr sipaddr;		/** Advertise NAT-T addr change to pluto **/		sipaddr.sa_family = AF_INET;		((struct sockaddr_in*)&sipaddr)->sin_addr.s_addr = irs->ipp->saddr;		((struct sockaddr_in*)&sipaddr)->sin_port = htons(irs->natt_sport);		pfkey_nat_t_new_mapping(newipsp, &sipaddr, irs->natt_sport);		/**		 * Then allow or block packet depending on		 * sysctl_ipsec_inbound_policy_check.		 *		 * In all cases, pluto will update SA if new mapping is		 * accepted.		 */		if (sysctl_ipsec_inbound_policy_check) {			KLIPS_PRINT(debug_rcv,				"klips_debug:ipsec_rcv: "				"SA:%s, src=%s:%u of pkt does not agree with expected "				"SA source address policy (pluto has been informed).\n",				irs->sa_len ? irs->sa : " (error)",				irs->ipsaddr_txt, irs->natt_sport);			if(irs->stats) {				irs->stats->rx_dropped++;			}			ipsec_sa_put(newipsp);			return IPSEC_RCV_FAILEDINBOUND;		}	}#endif	irs->authfuncs=NULL;	/* authenticate, if required */#ifdef CONFIG_KLIPS_ALG	if ((ixt_a=irs->ipsp->ips_alg_auth)) {		irs->authlen = AHHMAC_HASHLEN;		irs->authfuncs = NULL;		irs->ictx = NULL;		irs->octx = NULL;		irs->ictx_len = 0;		irs->octx_len = 0;		KLIPS_PRINT(debug_rcv,				"klips_debug:ipsec_rcv: "				"authalg=%d authlen=%d\n",				irs->ipsp->ips_authalg, 				irs->authlen);	} else#endif /* CONFIG_KLIPS_ALG */	switch(irs->ipsp->ips_authalg) {#ifdef CONFIG_KLIPS_AUTH_HMAC_MD5	case AH_MD5:		irs->authlen = AHHMAC_HASHLEN;		irs->authfuncs = ipsec_rcv_md5;		irs->ictx = (void *)&((struct md5_ctx*)(irs->ipsp->ips_key_a))->ictx;		irs->octx = (void *)&((struct md5_ctx*)(irs->ipsp->ips_key_a))->octx;		irs->ictx_len = sizeof(((struct md5_ctx*)(irs->ipsp->ips_key_a))->ictx);		irs->octx_len = sizeof(((struct md5_ctx*)(irs->ipsp->ips_key_a))->octx);		break;#endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */#ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1	case AH_SHA:		irs->authlen = AHHMAC_HASHLEN;		irs->authfuncs = ipsec_rcv_sha1;		irs->ictx = (void *)&((struct sha1_ctx*)(irs->ipsp->ips_key_a))->ictx;		irs->octx = (void *)&((struct sha1_ctx*)(irs->ipsp->ips_key_a))->octx;		irs->ictx_len = sizeof(((struct sha1_ctx*)(irs->ipsp->ips_key_a))->ictx);		irs->octx_len = sizeof(((struct sha1_ctx*)(irs->ipsp->ips_key_a))->octx);		break;#endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */	case AH_NONE:		irs->authlen = 0;		irs->authfuncs = NULL;		irs->ictx = NULL;		irs->octx = NULL;		irs->ictx_len = 0;		irs->octx_len = 0;		break;	default:		irs->ipsp->ips_errs.ips_alg_errs += 1;		if(irs->stats) {			irs->stats->rx_errors++;		}		return IPSEC_RCV_BADAUTH;	}	irs->ilen = irs->len - iphlen - irs->authlen;	if(irs->ilen <= 0) {	  KLIPS_PRINT(debug_rcv,		      "klips_debug:ipsec_rcv: "		      "runt %s packet with no data, dropping.\n",		      (proto == IPPROTO_ESP ? "esp" : "ah"));	  if(irs->stats) {	    irs->stats->rx_dropped++;	  }	  return IPSEC_RCV_BADLEN;	}#ifdef CONFIG_KLIPS_ALG	if(irs->authfuncs || ixt_a) {#else	if(irs->authfuncs) {#endif		unsigned char *authenticator = NULL;		if(proto_funcs->rcv_setup_auth) {			enum ipsec_rcv_value retval			    = (*proto_funcs->rcv_setup_auth)(irs, skb,							 &replay,							 &authenticator);			if(retval < 0) {				return retval;			}		}		if(!authenticator) {			irs->ipsp->ips_errs.ips_auth_errs += 1;			if(irs->stats) {				irs->stats->rx_dropped++;			}			return IPSEC_RCV_BADAUTH;		}		if(!ipsec_checkreplaywindow(irs->ipsp, replay)) {			irs->ipsp->ips_errs.ips_replaywin_errs += 1;			KLIPS_PRINT(debug_rcv & DB_RX_REPLAY,				    "klips_debug:ipsec_rcv: "				    "duplicate frame from %s, packet dropped\n",				    irs->ipsaddr_txt);			if(irs->stats) {				irs->stats->rx_dropped++;			}			return IPSEC_RCV_REPLAYFAILED;		}		/*		 * verify authenticator		 */		KLIPS_PRINT(debug_rcv,			    "klips_debug:ipsec_rcv: "			    "encalg = %d, authalg = %d.\n",			    irs->ipsp->ips_encalg,			    irs->ipsp->ips_authalg);		/* calculate authenticator */		if(proto_funcs->rcv_calc_auth == NULL) {			return IPSEC_RCV_BADAUTH;		}		(*proto_funcs->rcv_calc_auth)(irs, skb);		if (memcmp(irs->hash, authenticator, irs->authlen)) {			irs->ipsp->ips_errs.ips_auth_errs += 1;			KLIPS_PRINT(debug_rcv & DB_RX_INAU,				    "klips_debug:ipsec_rcv: "				    "auth failed on incoming packet from %s: hash=%08x%08x%08x auth=%08x%08x%08x, dropped\n",				    irs->ipsaddr_txt,				    ntohl(*(__u32*)&irs->hash[0]),				    ntohl(*(__u32*)&irs->hash[4]),				    ntohl(*(__u32*)&irs->hash[8]),				    ntohl(*(__u32*)authenticator),				    ntohl(*((__u32*)authenticator + 1)),				    ntohl(*((__u32*)authenticator + 2)));			if(irs->stats) {				irs->stats->rx_dropped++;			}			return IPSEC_RCV_AUTHFAILED;		} else {			KLIPS_PRINT(debug_rcv,				    "klips_debug:ipsec_rcv: "				    "authentication successful.\n");		}		/* Crypto hygiene: clear memory used to calculate autheticator.		 * The length varies with the algorithm.		 */		memset(irs->hash, 0, irs->authlen);		/* If the sequence number == 0, expire SA, it had rolled */		if(irs->ipsp->ips_replaywin && !replay /* !irs->ipsp->ips_replaywin_lastseq */) {			ipsec_sa_delchain(irs->ipsp);			KLIPS_PRINT(debug_rcv,				    "klips_debug:ipsec_rcv: "				    "replay window counter rolled, expiring SA.\n");			if(irs->stats) {				irs->stats->rx_dropped++;			}			return IPSEC_RCV_REPLAYROLLED;		}		/* now update the replay counter */		if (!ipsec_updatereplaywindow(irs->ipsp, replay)) {			irs->ipsp->ips_errs.ips_replaywin_errs += 1;			KLIPS_PRINT(debug_rcv & DB_RX_REPLAY,				    "klips_debug:ipsec_rcv: "				    "duplicate frame from %s, packet dropped\n",				    irs->ipsaddr_txt);			if(irs->stats) {				irs->stats->rx_dropped++;			}			return IPSEC_RCV_REPLAYROLLED;		}	}	if(proto_funcs->rcv_decrypt) {		enum ipsec_rcv_value retval =		  (*proto_funcs->rcv_decrypt)(irs);		if(retval != IPSEC_RCV_OK) {			return retval;		}	}	/*	 *	Adjust pointers	 */	skb = irs->skb;	irs->len = skb->len;	dat = skb->data;#ifdef NET_21/*		skb->h.ipiph=(struct iphdr *)skb->data; */	skb->nh.raw = skb->data;	skb->h.raw = skb->nh.raw + (skb->nh.iph->ihl << 2);	memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));#else /* NET_21 */	skb->h.iph=(struct iphdr *)skb->data;	skb->ip_hdr=(struct iphdr *)skb->data;	memset(skb->proto_priv, 0, sizeof(struct options));#endif /* NET_21 */	ipp = (struct iphdr *)dat;	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));	/*	 *	Discard the original ESP/AH header	 */	ipp->protocol = irs->next_header;	ipp->check = 0;	/* NOTE: this will be included in checksum */	ipp->check = ip_fast_csum((unsigned char *)dat, iphlen >> 2);	KLIPS_PRINT(debug_rcv & DB_RX_PKTRX,		    "klips_debug:ipsec_rcv: "		    "after <%s%s%s>, SA:%s:\n",		    IPS_XFORM_NAME(irs->ipsp),		    irs->sa_len ? irs->sa : " (error)");	KLIPS_IP_PRINT(debug_rcv & DB_RX_PKTRX, ipp);	skb->protocol = htons(ETH_P_IP);	skb->ip_summed = 0;	ipsnext = irs->ipsp->ips_inext;	if(sysctl_ipsec_inbound_policy_check) {		if(ipsnext) {			if(				ipp->protocol != IPPROTO_AH				&& ipp->protocol != IPPROTO_ESP#ifdef CONFIG_KLIPS_IPCOMP				&& ipp->protocol != IPPROTO_COMP				&& (ipsnext->ips_said.proto != IPPROTO_COMP				    || ipsnext->ips_inext)#endif /* CONFIG_KLIPS_IPCOMP */				&& ipp->protocol != IPPROTO_IPIP				&& ipp->protocol != IPPROTO_ATT_HEARTBEAT  /* heartbeats to AT&T SIG/GIG */				) {				KLIPS_PRINT(debug_rcv,					    "klips_debug:ipsec_rcv: "					    "packet with incomplete policy dropped, last successful SA:%s.\n",					    irs->sa_len ? irs->sa : " (error)");				if(irs->stats) {					irs->stats->rx_dropped++;				}				return IPSEC_RCV_FAILEDINBOUND;			}			KLIPS_PRINT(debug_rcv,				    "klips_debug:ipsec_rcv: "				    "SA:%s, Another IPSEC header to process.\n",				    irs->sa_len ? irs->sa : " (error)");		} else {			KLIPS_PRINT(debug_rcv,				    "klips_debug:ipsec_rcv: "				    "No ips_inext from this SA:%s.\n",				    irs->sa_len ? irs->sa : " (error)");		}	}#ifdef CONFIG_KLIPS_IPCOMP	/* update ipcomp ratio counters, even if no ipcomp packet is present */	if (ipsnext	    && ipsnext->ips_said.proto == IPPROTO_COMP	    && ipp->protocol != IPPROTO_COMP) {		ipsnext->ips_comp_ratio_cbytes += ntohs(ipp->tot_len);		ipsnext->ips_comp_ratio_dbytes += ntohs(ipp->tot_len);	}#endif /* CONFIG_KLIPS_IPCOMP */	irs->ipsp->ips_life.ipl_bytes.ipl_count += irs->len;	irs->ipsp->ips_life.ipl_bytes.ipl_last   = irs->len;	if(!irs->ipsp->ips_life.ipl_usetime.ipl_count) {		irs->ipsp->ips_life.ipl_usetime.ipl_count = jiffies / HZ;	}	irs->ipsp->ips_life.ipl_usetime.ipl_last = jiffies / HZ;	irs->ipsp->ips_life.ipl_packets.ipl_count += 1;#ifdef CONFIG_NETFILTER	if(proto == IPPROTO_ESP || proto == IPPROTO_AH) {		skb->nfmark = (skb->nfmark & (~(IPsecSAref2NFmark(IPSEC_SA_REF_MASK))))			| IPsecSAref2NFmark(IPsecSA2SAref(irs->ipsp));		KLIPS_PRINT(debug_rcv & DB_RX_PKTRX,			    "klips_debug:ipsec_rcv: "			    "%s SA sets skb->nfmark=0x%x.\n",			    proto == IPPROTO_ESP ? "ESP" : "AH",			    (unsigned)skb->nfmark);	}#endif /* CONFIG_NETFILTER */	return IPSEC_RCV_OK;}intipsec_rcv(struct sk_buff *skb#ifndef PROTO_HANDLER_SINGLE_PARM#ifdef NET_21	  unsigned short xlen#else /* NET_21 */	  struct net_device *dev,	  struct options *opt,	  __u32 daddr_unused,	  unsigned short xlen,	  __u32 saddr,	  int redo,	  struct inet_protocol *protocol#endif /* NET_21 */#endif /* PROTO_HANDLER_SINGLE_PARM */	  ){#ifdef NET_21#ifdef CONFIG_KLIPS_DEBUG	struct net_device *dev = skb->dev;#endif /* CONFIG_KLIPS_DEBUG */#endif /* NET_21 */	unsigned char protoc;	struct iphdr *ipp;	struct ipsec_sa *ipsp = NULL;	struct net_device_stats *stats = NULL;		/* This device's statistics */	struct net_device *ipsecdev = NULL, *prvdev;	struct ipsecpriv *prv;	char name[9];	int i;	struct in_addr ipsaddr;	struct in_addr ipdaddr;	struct ipsec_sa* ipsnext = NULL;	/* next SA towards inside of packet */	struct ipsec_rcv_state irs;	/* Don't unlink in the middle of a turnaround */	KLIPS_INC_USE;	memset(&irs, 0, sizeof(struct ipsec_rcv_state));	if (skb == NULL) {		KLIPS_PRINT(debug_rcv,			    "klips_debug:ipsec_rcv: "			    "NULL skb passed in.\n");		goto rcvleave;	}	if (skb->data == NULL) {		KLIPS_PRINT(debug_rcv,			    "klips_debug:ipsec_rcv: "			    "NULL skb->data passed in, packet is bogus, dropping.\n");		goto rcvleave;	}#ifdef CONFIG_IPSEC_NAT_TRAVERSAL	if (skb->sk && skb->nh.iph && skb->nh.iph->protocol==IPPROTO_UDP) {		/**		 * Packet comes from udp_queue_rcv_skb so it is already defrag,		 * checksum verified, ... (ie safe to use)		 *		 * If the packet is not for us, return -1 and udp_queue_rcv_skb		 * will continue to handle it (do not kfree skb !!).		 */#ifdef NET_26#if 0	  /* at this time, NAT-T is not supported on 2.6. */	  struct udp_sock *us = udp_sk(skb->sk);

⌨️ 快捷键说明

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