svn commit: r281694 - head/sys/netipsec

Andrey V. Elsukov ae at FreeBSD.org
Sat Apr 18 16:51:25 UTC 2015


Author: ae
Date: Sat Apr 18 16:51:24 2015
New Revision: 281694
URL: https://svnweb.freebsd.org/changeset/base/281694

Log:
  Requeue mbuf via netisr when we use IPSec tunnel mode and IPv6.
  
  ipsec6_common_input_cb() uses partial copy of ip6_input() to parse
  headers. But this isn't correct, when we use tunnel mode IPSec.
  
  When we stripped outer IPv6 header from the decrypted packet, it
  can become IPv4 packet and should be handled by ip_input. Also when
  we use tunnel mode IPSec with IPv6 traffic, we should pass decrypted
  packet with inner IPv6 header to ip6_input, it will correctly handle
  it and also can decide to forward it.
  
  The "skip" variable points to offset where payload starts. In tunnel
  mode we reset it to zero after stripping the outer header. So, when
  it is zero, we should requeue mbuf via netisr.
  
  Differential Revision:	https://reviews.freebsd.org/D2306
  Reviewed by:	adrian, gnn
  Sponsored by:	Yandex LLC

Modified:
  head/sys/netipsec/ipsec_input.c

Modified: head/sys/netipsec/ipsec_input.c
==============================================================================
--- head/sys/netipsec/ipsec_input.c	Sat Apr 18 16:46:31 2015	(r281693)
+++ head/sys/netipsec/ipsec_input.c	Sat Apr 18 16:51:24 2015	(r281694)
@@ -627,7 +627,7 @@ ipsec6_common_input_cb(struct mbuf *m, s
 	struct m_tag *mtag;
 	struct tdb_ident *tdbi;
 	struct secasindex *saidx;
-	int nxt;
+	int nxt, isr_prot;
 	u_int8_t nxt8;
 	int error, nest;
 #ifdef notyet
@@ -803,6 +803,35 @@ 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 */
+	if (skip == 0) {
+		/*
+		 * We stripped outer IPv6 header.
+		 * Now we should requeue decrypted packet via netisr.
+		 */
+		switch (prot) {
+#ifdef INET
+		case IPPROTO_IPIP:
+			isr_prot = NETISR_IP;
+			break;
+#endif
+		case IPPROTO_IPV6:
+			isr_prot = NETISR_IPV6;
+			break;
+		default:
+			DPRINTF(("%s: cannot handle inner ip proto %d\n",
+			    __func__, prot));
+			IPSEC_ISTAT(sproto, nopf);
+			error = EPFNOSUPPORT;
+			goto bad;
+		}
+		error = netisr_queue_src(isr_prot, (uintptr_t)sav->spi, m);
+		if (error) {
+			IPSEC_ISTAT(sproto, qfull);
+			DPRINTF(("%s: queue full; proto %u packet dropped\n",
+			    __func__, sproto));
+		}
+		return (error);
+	}
 	/*
 	 * See the end of ip6_input for this logic.
 	 * IPPROTO_IPV[46] case will be processed just like other ones


More information about the svn-src-head mailing list