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

📄 ipsec_rcv.c

📁 ipsec vpn
💻 C
📖 第 1 页 / 共 5 页
字号:
	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;		struct sockaddr_in *psin = (struct sockaddr_in*)(newipsp->ips_addr_s);		/** 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 [%08x:%u] (notifying pluto of change).\n",				irs->sa_len ? irs->sa : " (error)",				    irs->ipsaddr_txt, irs->natt_sport,				    psin->sin_addr.s_addr,				    newipsp->ips_natt_sport);			if(irs->stats) {				irs->stats->rx_dropped++;			}			ipsec_sa_put(newipsp);			return IPSEC_RCV_FAILEDINBOUND;		}	}#endif#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;	}	/* ilen counts number of bytes in ESP portion */	irs->ilen = ((skb->data + skb->len) - skb->h.raw) - 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;	}	if(irs->authfuncs || ixt_a) {		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;	ipp = irs->ipp = skb->nh.iph;	iphlen = ipp->ihl<<2;	skb->h.raw = skb->nh.raw + iphlen;		/* zero any options that there might be */	memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));	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 *)skb->nh.iph, 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;}/* * core decapsulation loop for all protocols. * * the following things should be setup to enter this function. * * irs->stats  == stats structure (or NULL) * irs->ipp    = IP header. * irs->ipsp   = NULL. * irs->ilen   = 0; * irs->authlen = 0; * irs->authfuncs = NULL; * irs->skb    = skb; * skb->nh.iph = ipp; * skb->h.raw  = start of payload * */int ipsec_rcv_decap(struct ipsec_rcv_state *irs){	struct ipsec_sa *ipsp = NULL;	struct ipsec_sa* ipsnext = NULL;	struct in_addr ipsaddr;	struct in_addr ipdaddr;	struct iphdr *ipp;	struct sk_buff *skb = NULL;	/* begin decapsulating loop here */	/*	  The spinlock is to prevent any other process from	  accessing or deleting the ipsec_sa hash table or any of the	  ipsec_sa s while we are using and updating them.	  This is not optimal, but was relatively straightforward	  at the time.  A better way to do it has been planned for	  more than a year, to lock the hash table and put reference	  counts on each ipsec_sa instead.  This is not likely to happen	  in KLIPS1 unless a volunteer contributes it, but will be	  designed into KLIPS2.	*/	spin_lock(&tdb_lock);	do {	        int decap_stat;		struct xform_functions *proto_funcs;		switch(irs->ipp->protocol) {		case IPPROTO_ESP:		  proto_funcs = esp_xform_funcs;		  break;		  #ifdef CONFIG_KLIPS_AH		case IPPROTO_AH:		  proto_funcs = ah_xform_funcs;		  break;#endif /* !CONFIG_KLIPS_AH */		  #ifdef CONFIG_KLIPS_IPCOMP		case IPPROTO_COMP:		  proto_funcs = ipcomp_xform_funcs;		  break;#endif /* !CONFIG_KLIPS_IPCOMP */		default:		  if(irs->stats) {		    irs->stats->rx_errors++;		  }		  decap_stat = IPSEC_RCV_BADPROTO;		  goto rcvleave;		}	        decap_stat = ipsec_rcv_decap_once(irs, proto_funcs);		if(decap_stat != IPSEC_RCV_OK) {			spin_unlock(&tdb_lock);			KLIPS_PRINT(debug_rcv,				    "klips_debug:ipsec_rcv: decap_once failed: %d\n",				    decap_stat);					goto rcvleave;		}	/* end decapsulation loop here */	} while(   (irs->ipp->protocol == IPPROTO_ESP )		|| (irs->ipp->protocol == IPPROTO_AH  )#ifdef CONFIG_KLIPS_IPCOMP		|| (irs->ipp->protocol == IPPROTO_COMP)#endif /* CONFIG_KLIPS_IPCOMP */		);	/* set up for decap loop */	ipp  =irs->ipp;	ipsp =irs->ipsp;	ipsnext = ipsp->ips_inext;	skb = irs->skb;	/* if there is an IPCOMP, but we don't have an IPPROTO_COMP,	 * then we can just skip it	 */#ifdef CONFIG_KLIPS_IPCOMP	if(ipsnext && ipsnext->ips_said.proto == IPPROTO_COMP) {		ipsp = ipsnext;		ipsnext = ipsp->ips_inext;	}#endif /* CONFIG_KLIPS_IPCOMP */#ifdef CONFIG_IPSEC_NAT_TRAVERSAL	if ((irs->natt_type) && (ipp->protocol != IPPROTO_IPIP)) {	  /**	   * NAT-Traversal and Transport Mode:	   *   we need to correct TCP/UDP checksum	   *	   * If we've got NAT-OA, we can fix checksum without recalculation.	   */	  __u32 natt_oa = ipsp->ips_natt_oa ?	    ((struct sockaddr_in*)(ipsp->ips_natt_oa))->sin_addr.s_addr : 0;	  __u16 pkt_len = skb->tail - (unsigned char *)ipp;	  __u16 data_len = pkt_len - (ipp->ihl << 2);	  	  switch (ipp->protocol) {	  case IPPROTO_TCP:	    if (data_len >= sizeof(struct tcphdr)) {

⌨️ 快捷键说明

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