Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 10 Jan 2017 16:30:56 +0000 (UTC)
From:      "Andrey V. Elsukov" <ae@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r311878 - in stable/11/sys: netinet netinet6
Message-ID:  <201701101630.v0AGUuT7064674@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ae
Date: Tue Jan 10 16:30:56 2017
New Revision: 311878
URL: https://svnweb.freebsd.org/changeset/base/311878

Log:
  MFC r310258:
    ip[6]_tryforward does inbound and outbound packet firewall processing.
    This can lead to change of mbuf pointer (packet filter could do m_pullup(),
    NAT, etc). Also in case of change of destination address, tryforward can
    decide that packet should be handled by local system. In this case modified
    mbuf can be returned to the ip[6]_input(). To handle this correctly, check
    M_FASTFWD_OURS flag after return from ip[6]_tryforward. And if it is present,
    update variables that depend from mbuf pointer and skip another inbound
    firewall processing.

Modified:
  stable/11/sys/netinet/ip_input.c
  stable/11/sys/netinet6/ip6_input.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/netinet/ip_input.c
==============================================================================
--- stable/11/sys/netinet/ip_input.c	Tue Jan 10 16:25:39 2017	(r311877)
+++ stable/11/sys/netinet/ip_input.c	Tue Jan 10 16:30:56 2017	(r311878)
@@ -550,24 +550,35 @@ tooshort:
 			m_adj(m, ip_len - m->m_pkthdr.len);
 	}
 
-	/* Try to forward the packet, but if we fail continue */
+	/*
+	 * Try to forward the packet, but if we fail continue.
+	 * ip_tryforward() does inbound and outbound packet firewall
+	 * processing. If firewall has decided that destination becomes
+	 * our local address, it sets M_FASTFWD_OURS flag. In this
+	 * case skip another inbound firewall processing and update
+	 * ip pointer.
+	 */
+	if (V_ipforwarding != 0
 #ifdef IPSEC
-	/* For now we do not handle IPSEC in tryforward. */
-	if (!key_havesp(IPSEC_DIR_INBOUND) && !key_havesp(IPSEC_DIR_OUTBOUND) &&
-	    (V_ipforwarding == 1))
-		if (ip_tryforward(m) == NULL)
+	    && !key_havesp(IPSEC_DIR_INBOUND)
+	    && !key_havesp(IPSEC_DIR_OUTBOUND)
+#endif
+	   ) {
+		if ((m = ip_tryforward(m)) == NULL)
 			return;
+		if (m->m_flags & M_FASTFWD_OURS) {
+			m->m_flags &= ~M_FASTFWD_OURS;
+			ip = mtod(m, struct ip *);
+			goto ours;
+		}
+	}
+#ifdef IPSEC
 	/*
 	 * Bypass packet filtering for packets previously handled by IPsec.
 	 */
 	if (ip_ipsec_filtertunnel(m))
 		goto passin;
-#else
-	if (V_ipforwarding == 1)
-		if (ip_tryforward(m) == NULL)
-			return;
-#endif /* IPSEC */
-
+#endif
 	/*
 	 * Run through list of hooks for input packets.
 	 *

Modified: stable/11/sys/netinet6/ip6_input.c
==============================================================================
--- stable/11/sys/netinet6/ip6_input.c	Tue Jan 10 16:25:39 2017	(r311877)
+++ stable/11/sys/netinet6/ip6_input.c	Tue Jan 10 16:30:56 2017	(r311878)
@@ -731,23 +731,36 @@ ip6_input(struct mbuf *m)
 		goto bad;
 	}
 #endif
-	/* Try to forward the packet, but if we fail continue */
+	/*
+	 * Try to forward the packet, but if we fail continue.
+	 * ip6_tryforward() does inbound and outbound packet firewall
+	 * processing. If firewall has decided that destination becomes
+	 * our local address, it sets M_FASTFWD_OURS flag. In this
+	 * case skip another inbound firewall processing and update
+	 * ip6 pointer.
+	 */
+	if (V_ip6_forwarding != 0
 #ifdef IPSEC
-	if (V_ip6_forwarding != 0 && !key_havesp(IPSEC_DIR_INBOUND) &&
-	    !key_havesp(IPSEC_DIR_OUTBOUND))
-		if (ip6_tryforward(m) == NULL)
+	    && !key_havesp(IPSEC_DIR_INBOUND)
+	    && !key_havesp(IPSEC_DIR_OUTBOUND)
+#endif
+	    ) {
+		if ((m = ip6_tryforward(m)) == NULL)
 			return;
+		if (m->m_flags & M_FASTFWD_OURS) {
+			m->m_flags &= ~M_FASTFWD_OURS;
+			ours = 1;
+			ip6 = mtod(m, struct ip6_hdr *);
+			goto hbhcheck;
+		}
+	}
+#ifdef IPSEC
 	/*
 	 * Bypass packet filtering for packets previously handled by IPsec.
 	 */
 	if (ip6_ipsec_filtertunnel(m))
 		goto passin;
-#else
-	if (V_ip6_forwarding != 0)
-		if (ip6_tryforward(m) == NULL)
-			return;
-#endif /* IPSEC */
-
+#endif
 	/*
 	 * Run through list of hooks for input packets.
 	 *
@@ -755,12 +768,12 @@ ip6_input(struct mbuf *m)
 	 *     (e.g. by NAT rewriting).  When this happens,
 	 *     tell ip6_forward to do the right thing.
 	 */
-	odst = ip6->ip6_dst;
 
 	/* Jump over all PFIL processing if hooks are not active. */
 	if (!PFIL_HOOKED(&V_inet6_pfil_hook))
 		goto passin;
 
+	odst = ip6->ip6_dst;
 	if (pfil_run_hooks(&V_inet6_pfil_hook, &m,
 	    m->m_pkthdr.rcvif, PFIL_IN, NULL))
 		return;



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