Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 13 Nov 2014 10:49:00 +0000 (UTC)
From:      "Andrey V. Elsukov" <ae@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r274466 - head/sys/netipsec
Message-ID:  <201411131049.sADAn0pw085327@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ae
Date: Thu Nov 13 10:48:59 2014
New Revision: 274466
URL: https://svnweb.freebsd.org/changeset/base/274466

Log:
  Strip IP header only when we act in tunnel mode.
  
  MFC after:	1 week
  Sponsored by:	Yandex LLC

Modified:
  head/sys/netipsec/ipsec_input.c

Modified: head/sys/netipsec/ipsec_input.c
==============================================================================
--- head/sys/netipsec/ipsec_input.c	Thu Nov 13 10:47:24 2014	(r274465)
+++ head/sys/netipsec/ipsec_input.c	Thu Nov 13 10:48:59 2014	(r274466)
@@ -671,8 +671,8 @@ ipsec6_common_input_cb(struct mbuf *m, s
 	ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
 
 	/* Save protocol */
-	prot = 0;
-	m_copydata(m, protoff, 1, (unsigned char *) &prot);
+	m_copydata(m, protoff, 1, &nxt8);
+	prot = nxt8;
 
 #ifdef DEV_ENC
 	if_inc_counter(encif, IFCOUNTER_IPACKETS, 1);
@@ -684,32 +684,33 @@ ipsec6_common_input_cb(struct mbuf *m, s
 		return (error);
 #endif /* DEV_ENC */
 
-#ifdef INET
-	/* IP-in-IP encapsulation */
-	if (prot == IPPROTO_IPIP) {
-		if (m->m_pkthdr.len - skip < sizeof(struct ip)) {
+	/* IPv6-in-IP encapsulation */
+	if (prot == IPPROTO_IPV6 &&
+	    saidx->mode != IPSEC_MODE_TRANSPORT) {
+		if (m->m_pkthdr.len - skip < sizeof(struct ip6_hdr)) {
 			IPSEC_ISTAT(sproto, hdrops);
 			error = EINVAL;
 			goto bad;
 		}
-		/* ipn will now contain the inner IPv4 header */
-	 	m_striphdr(m, 0, skip);
+		/* ip6n will now contain the inner IPv6 header. */
+		m_striphdr(m, 0, skip);
 		skip = 0;
 #ifdef notyet
 		/*
 		 * Check that the inner source address is the same as
 		 * the proxy address, if available.
 		 */
-		if ((saidx->proxy.sa.sa_family == AF_INET &&
-		    saidx->proxy.sin.sin_addr.s_addr != INADDR_ANY &&
-		    ipn.ip_src.s_addr != saidx->proxy.sin.sin_addr.s_addr) ||
-		    (saidx->proxy.sa.sa_family != AF_INET &&
+		if ((saidx->proxy.sa.sa_family == AF_INET6 &&
+		    !IN6_IS_ADDR_UNSPECIFIED(&saidx->proxy.sin6.sin6_addr) &&
+		    !IN6_ARE_ADDR_EQUAL(&ip6n.ip6_src,
+			&saidx->proxy.sin6.sin6_addr)) ||
+		    (saidx->proxy.sa.sa_family != AF_INET6 &&
 			saidx->proxy.sa.sa_family != 0)) {
 
 			DPRINTF(("%s: inner source address %s doesn't "
 			    "correspond to expected proxy source %s, "
 			    "SA %s/%08lx\n", __func__,
-			    inet_ntoa4(ipn.ip_src),
+			    ip6_sprintf(ip6buf, &ip6n.ip6_src),
 			    ipsec_address(&saidx->proxy),
 			    ipsec_address(&saidx->dst),
 			    (u_long) ntohl(sav->spi)));
@@ -720,33 +721,33 @@ ipsec6_common_input_cb(struct mbuf *m, s
 		}
 #endif /* notyet */
 	}
-#endif /* INET */
-	/* IPv6-in-IP encapsulation */
-	if (prot == IPPROTO_IPV6) {
-		if (m->m_pkthdr.len - skip < sizeof(struct ip6_hdr)) {
+#ifdef INET
+	/* IP-in-IP encapsulation */
+	else if (prot == IPPROTO_IPIP &&
+	    saidx->mode != IPSEC_MODE_TRANSPORT) {
+		if (m->m_pkthdr.len - skip < sizeof(struct ip)) {
 			IPSEC_ISTAT(sproto, hdrops);
 			error = EINVAL;
 			goto bad;
 		}
-		/* ip6n will now contain the inner IPv6 header. */
-		m_striphdr(m, 0, skip);
+		/* ipn will now contain the inner IPv4 header */
+	 	m_striphdr(m, 0, skip);
 		skip = 0;
 #ifdef notyet
 		/*
 		 * Check that the inner source address is the same as
 		 * the proxy address, if available.
 		 */
-		if ((saidx->proxy.sa.sa_family == AF_INET6 &&
-		    !IN6_IS_ADDR_UNSPECIFIED(&saidx->proxy.sin6.sin6_addr) &&
-		    !IN6_ARE_ADDR_EQUAL(&ip6n.ip6_src,
-			&saidx->proxy.sin6.sin6_addr)) ||
-		    (saidx->proxy.sa.sa_family != AF_INET6 &&
+		if ((saidx->proxy.sa.sa_family == AF_INET &&
+		    saidx->proxy.sin.sin_addr.s_addr != INADDR_ANY &&
+		    ipn.ip_src.s_addr != saidx->proxy.sin.sin_addr.s_addr) ||
+		    (saidx->proxy.sa.sa_family != AF_INET &&
 			saidx->proxy.sa.sa_family != 0)) {
 
 			DPRINTF(("%s: inner source address %s doesn't "
 			    "correspond to expected proxy source %s, "
 			    "SA %s/%08lx\n", __func__,
-			    ip6_sprintf(ip6buf, &ip6n.ip6_src),
+			    inet_ntoa4(ipn.ip_src),
 			    ipsec_address(&saidx->proxy),
 			    ipsec_address(&saidx->dst),
 			    (u_long) ntohl(sav->spi)));
@@ -757,6 +758,10 @@ ipsec6_common_input_cb(struct mbuf *m, s
 		}
 #endif /* notyet */
 	}
+#endif /* INET */
+	else {
+		prot = IPPROTO_IPV6; /* for correct BPF processing */
+	}
 
 	/*
 	 * Record what we've done to the packet (under what SA it was
@@ -807,10 +812,6 @@ ipsec6_common_input_cb(struct mbuf *m, s
 	if ((error = ipsec_filter(&m, PFIL_IN, ENC_IN|ENC_AFTER)) != 0)
 		return (error);
 #endif /* DEV_ENC */
-	/* Retrieve new protocol */
-	/* We have stripped the IP6 header from the mbuf, we have to use the backuped proto value instead */
-	nxt8 = prot;
-
 	/*
 	 * See the end of ip6_input for this logic.
 	 * IPPROTO_IPV[46] case will be processed just like other ones



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201411131049.sADAn0pw085327>