Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F176834469
D61041.1793453499.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
6 KB
Referenced Files
None
Subscribers
None
D61041.1793453499.diff
View Options
diff --git a/sys/netinet6/ip6_fastfwd.c b/sys/netinet6/ip6_fastfwd.c
--- a/sys/netinet6/ip6_fastfwd.c
+++ b/sys/netinet6/ip6_fastfwd.c
@@ -95,11 +95,13 @@
ip6_tryforward(struct mbuf *m)
{
struct sockaddr_in6 dst;
+ struct in6_addr in_src, in_dst; /* as received */
struct in6_addr pfil_dst; /* before the outbound hooks */
struct nhop_object *nh;
struct m_tag *fwd_tag;
struct ip6_hdr *ip6;
struct ifnet *rcvif;
+ struct mbuf *mcopy = NULL;
uint32_t plen;
int error;
@@ -150,6 +152,8 @@
dst.sin6_family = AF_INET6;
dst.sin6_len = sizeof(dst);
dst.sin6_addr = ip6->ip6_dst;
+ in_src = ip6->ip6_src;
+ in_dst = ip6->ip6_dst;
/*
* Incoming packet firewall processing.
@@ -286,6 +290,19 @@
}
}
passout:
+ /*
+ * A packet leaving through the interface it arrived on could have
+ * gone to the next hop directly, so keep a copy to send its source a
+ * redirect. Not when the route came from a redirect, nor when a
+ * packet filter rewrote the addresses or chose the next hop: the
+ * packets must then keep coming through us.
+ */
+ if (nh->nh_ifp == rcvif && V_ip6_sendredirects &&
+ (nh->nh_flags & NHF_REDIRECT) == 0 &&
+ IN6_ARE_ADDR_EQUAL(&dst.sin6_addr, &in_dst) &&
+ IN6_ARE_ADDR_EQUAL(&ip6->ip6_src, &in_src))
+ mcopy = m_copym(m, 0, imin(m->m_pkthdr.len, ICMPV6_PLD_MAXLEN),
+ M_NOWAIT);
/*
* If TCP/UDP header still needs a valid checksum and interface will not
@@ -320,9 +337,15 @@
if (error != 0) {
in6_ifstat_inc(nh->nh_ifp, ifs6_out_discard);
IP6STAT_INC(ip6s_cantforward);
+ if (mcopy != NULL)
+ m_freem(mcopy);
} else {
in6_ifstat_inc(nh->nh_ifp, ifs6_out_forward);
IP6STAT_INC(ip6s_forward);
+ if (mcopy != NULL) {
+ IP6STAT_INC(ip6s_redirectsent);
+ icmp6_redirect_output(mcopy, nh);
+ }
}
return (NULL);
dropin:
@@ -333,5 +356,7 @@
drop:
if (m != NULL)
m_freem(m);
+ if (mcopy != NULL)
+ m_freem(mcopy);
return (NULL);
}
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -668,15 +668,13 @@
}
/*
* Try to forward the packet, but if we fail continue.
- * ip6_tryforward() does not generate redirects, so fall
- * through to normal processing if redirects are required.
* 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 && V_ip6_sendredirects == 0
+ if (V_ip6_forwarding != 0
#if defined(IPSEC) || defined(IPSEC_SUPPORT)
&& (!IPSEC_ENABLED(ipv6) ||
IPSEC_CAPS(ipv6, m, IPSEC_CAP_OPERABLE) == 0)
diff --git a/tests/sys/netinet6/redirect.sh b/tests/sys/netinet6/redirect.sh
--- a/tests/sys/netinet6/redirect.sh
+++ b/tests/sys/netinet6/redirect.sh
@@ -111,10 +111,90 @@
vnet_cleanup
}
+# A host whose default router forwards its packets to a better router on the
+# same link.
+send_redirect_setup()
+{
+ vnet_init
+
+ epair=$(vnet_mkepair)
+ vnet_mkjail host ${epair}a
+ vnet_mkjail rtr ${epair}b
+
+ jexec host ifconfig ${epair}a inet6 2001:db8:1::2/64 up
+ jexec rtr ifconfig ${epair}b inet6 2001:db8:1::1/64 up
+ jexec rtr sysctl net.inet6.ip6.forwarding=1
+
+ while [ `jexec host ifconfig ${epair}a inet6 | grep -c tentative` != "0" ]; do
+ sleep 0.1
+ done
+ while [ `jexec rtr ifconfig ${epair}b inet6 | grep -c tentative` != "0" ]; do
+ sleep 0.1
+ done
+
+ rtr_ll=`jexec rtr ifconfig ${epair}b inet6 | awk '$2~/^fe80:/{print$2}' | awk -F% '{print$1}'`
+ jexec host route add -6 default ${rtr_ll}%${epair}a
+
+ jexec rtr ndp -s fe80::5555%${epair}b 00:00:5e:00:53:55
+ jexec rtr route add -6 -net 2001:db8:2::/64 fe80::5555%${epair}b
+}
+
+atf_test_case "send_redirect" "cleanup"
+send_redirect_head()
+{
+ atf_set descr 'Test that a router sends IPv6 redirects'
+ atf_set require.user root
+}
+
+send_redirect_body()
+{
+ send_redirect_setup
+
+ atf_check -s exit:2 -o ignore jexec host ping -6 -c 1 -W 1 2001:db8:2::1
+ atf_check -o match:"1 redirect sent" jexec rtr netstat -s -p ip6
+
+ atf_check -o match:"gateway: fe80::5555%${epair}a\$" \
+ jexec host route -n get -6 2001:db8:2::1
+ atf_check -o match:'flags: <UP,GATEWAY,HOST,DYNAMIC,DONE>' \
+ jexec host route -n get -6 2001:db8:2::1
+}
+
+send_redirect_cleanup()
+{
+ vnet_cleanup
+}
+
+atf_test_case "send_redirect_disabled" "cleanup"
+send_redirect_disabled_head()
+{
+ atf_set descr 'Test that net.inet6.ip6.redirect=0 stops IPv6 redirects'
+ atf_set require.user root
+}
+
+send_redirect_disabled_body()
+{
+ send_redirect_setup
+ jexec rtr sysctl net.inet6.ip6.redirect=0
+
+ atf_check -s exit:2 -o ignore jexec host ping -6 -c 1 -W 1 2001:db8:2::1
+ atf_check -o match:"1 packet forwarded" \
+ -o match:"0 redirects sent" jexec rtr netstat -s -p ip6
+
+ atf_check -o match:"gateway: ${rtr_ll}%${epair}a\$" \
+ jexec host route -n get -6 2001:db8:2::1
+}
+
+send_redirect_disabled_cleanup()
+{
+ vnet_cleanup
+}
+
atf_init_test_cases()
{
atf_add_test_case "valid_redirect"
+ atf_add_test_case "send_redirect"
+ atf_add_test_case "send_redirect_disabled"
}
# end
diff --git a/tests/sys/netpfil/pf/forward.sh b/tests/sys/netpfil/pf/forward.sh
--- a/tests/sys/netpfil/pf/forward.sh
+++ b/tests/sys/netpfil/pf/forward.sh
@@ -277,10 +277,54 @@
pft_cleanup
}
+atf_test_case "v6_redirect_rewritten" "cleanup"
+v6_redirect_rewritten_head()
+{
+ atf_set descr 'Test that a packet whose destination pf rewrote gets no redirect'
+ atf_set require.user root
+}
+
+v6_redirect_rewritten_body()
+{
+ pft_init
+
+ epair=$(vnet_mkepair)
+
+ # The host sends to 2001:db8:43::3, which the router rewrites to the
+ # host's own link; the router would redirect the host to the real next
+ # hop for the original destination, but the host never sent to it.
+ ifconfig ${epair}a inet6 2001:db8:42::1/64 up no_dad -ifdisabled
+ vnet_mkjail alcatraz ${epair}b
+ jexec alcatraz ifconfig ${epair}b inet6 2001:db8:42::2/64 up no_dad
+ jexec alcatraz sysctl net.inet6.ip6.forwarding=1
+ jexec alcatraz sysctl net.inet6.ip6.redirect=1
+ jexec alcatraz ndp -s 2001:db8:42::3 00:01:02:03:04:05
+ jexec alcatraz ndp -s 2001:db8:43::3 00:01:02:03:04:06
+ jexec alcatraz route add -6 2001:db8:43::/64 2001:db8:42::3
+ route add -6 2001:db8:43::/64 2001:db8:42::2
+
+ jexec alcatraz pfctl -e
+ pft_set_rules alcatraz "pass"
+ atf_check -s exit:2 -o ignore ping -6 -c 1 -W 1 2001:db8:43::3
+ atf_check -o match:"1 redirect sent" jexec alcatraz netstat -s -p ip6
+
+ pft_set_rules alcatraz \
+ "rdr on ${epair}b inet6 to 2001:db8:43::4 -> 2001:db8:43::3" \
+ "pass"
+ atf_check -s exit:2 -o ignore ping -6 -c 1 -W 1 2001:db8:43::4
+ atf_check -o match:"1 redirect sent" jexec alcatraz netstat -s -p ip6
+}
+
+v6_redirect_rewritten_cleanup()
+{
+ pft_cleanup
+}
+
atf_init_test_cases()
{
atf_add_test_case "v4"
atf_add_test_case "v6"
atf_add_test_case "v6_hlim"
atf_add_test_case "v6_hlim_decrement"
+ atf_add_test_case "v6_redirect_rewritten"
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Oct 31, 1:31 PM (11 h, 24 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41264661
Default Alt Text
D61041.1793453499.diff (6 KB)
Attached To
Mode
D61041: netinet6: Send redirects from ip6_tryforward()
Attached
Detach File
Event Timeline