summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorae <ae@FreeBSD.org>2017-01-10 16:30:56 +0000
committerae <ae@FreeBSD.org>2017-01-10 16:30:56 +0000
commit261f0a64fddb2f9b43520eecfe0fbdcb110dfe03 (patch)
treec62265d527c8c59e423f41298421ad42432e387c
parenta78549d940fbfb7e8367cad1da1c42bd27446430 (diff)
downloadFreeBSD-src-261f0a64fddb2f9b43520eecfe0fbdcb110dfe03.zip
FreeBSD-src-261f0a64fddb2f9b43520eecfe0fbdcb110dfe03.tar.gz
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.
-rw-r--r--sys/netinet/ip_input.c33
-rw-r--r--sys/netinet6/ip6_input.c35
2 files changed, 46 insertions, 22 deletions
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index 3a07ad8..73a155d 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -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.
*
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
index 26d55ba..0a7dae8 100644
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -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;
OpenPOWER on IntegriCloud