mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-11-07 04:36:52 -10:00
netinet6: Check the hop limit after pfil in ip6_tryforward()
ip6_tryforward() sends time exceeded for an expiring packet before the
inbound pfil hooks have seen it, whereas ip_tryforward() and
ip6_forward(), which ip6_input() calls after the hooks, check it
afterwards. On the fast path the router therefore answers packets the
firewall blocks inbound, and pf never handles the expiry itself: a
nat64 (af-to) packet with hop limit 1 gets a time exceeded error from
the router, which a "block" ruleset then drops on the way out, instead
of the one pf_translate_af() sends with the untranslated addresses.
Check the hop limit after the inbound hooks.
Reviewed by: kp
Fixes: 5a1842a2 ("Add ip6_tryforward() - a run to completion ...")
MFC after: 1 week
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D61034
This commit is contained in:
2 files changed
+62
-13
No files matched your search
+13
-13
@@ -145,19 +145,6 @@ ip6_tryforward(struct mbuf *m)
|
||||
m->m_pkthdr.len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Hop limit.
|
||||
*/
|
||||
#ifdef IPSTEALTH
|
||||
if (!V_ip6stealth)
|
||||
#endif
|
||||
if (ip6->ip6_hlim <= IPV6_HLIMDEC) {
|
||||
icmp6_error(m, ICMP6_TIME_EXCEEDED,
|
||||
ICMP6_TIME_EXCEED_TRANSIT, 0);
|
||||
m = NULL;
|
||||
goto dropin;
|
||||
}
|
||||
|
||||
bzero(&dst, sizeof(dst));
|
||||
dst.sin6_family = AF_INET6;
|
||||
dst.sin6_len = sizeof(dst);
|
||||
@@ -197,6 +184,19 @@ ip6_tryforward(struct mbuf *m)
|
||||
dst.sin6_addr = ip6->ip6_dst;
|
||||
}
|
||||
passin:
|
||||
/*
|
||||
* Hop limit, checked after the inbound hooks as on the other
|
||||
* forwarding paths: a packet they drop gets no time exceeded error.
|
||||
*/
|
||||
#ifdef IPSTEALTH
|
||||
if (!V_ip6stealth)
|
||||
#endif
|
||||
if (ip6->ip6_hlim <= IPV6_HLIMDEC) {
|
||||
icmp6_error(m, ICMP6_TIME_EXCEEDED,
|
||||
ICMP6_TIME_EXCEED_TRANSIT, 0);
|
||||
m = NULL;
|
||||
goto dropin;
|
||||
}
|
||||
/*
|
||||
* Find route to destination.
|
||||
*/
|
||||
|
||||
@@ -163,8 +163,57 @@ v6_cleanup()
|
||||
pft_cleanup
|
||||
}
|
||||
|
||||
atf_test_case "v6_hlim" "cleanup"
|
||||
v6_hlim_head()
|
||||
{
|
||||
atf_set descr 'Test that packets pf blocks get no time exceeded error'
|
||||
atf_set require.user root
|
||||
}
|
||||
|
||||
v6_hlim_body()
|
||||
{
|
||||
pft_init
|
||||
|
||||
epair_send=$(vnet_mkepair)
|
||||
epair_recv=$(vnet_mkepair)
|
||||
|
||||
ifconfig ${epair_send}a inet6 2001:db8:42::1/64 up no_dad -ifdisabled
|
||||
ifconfig ${epair_recv}a up
|
||||
|
||||
vnet_mkjail alcatraz ${epair_send}b ${epair_recv}b
|
||||
|
||||
jexec alcatraz ifconfig ${epair_send}b inet6 2001:db8:42::2/64 up no_dad
|
||||
jexec alcatraz ifconfig ${epair_recv}b inet6 2001:db8:43::2/64 up no_dad
|
||||
jexec alcatraz sysctl net.inet6.ip6.forwarding=1
|
||||
jexec alcatraz ndp -s 2001:db8:43::3 00:01:02:03:04:05
|
||||
route add -6 2001:db8:43::/64 2001:db8:42::2
|
||||
|
||||
jexec alcatraz pfctl -e
|
||||
pft_set_rules alcatraz \
|
||||
"block in inet6 proto icmp6 icmp6-type echoreq"
|
||||
|
||||
for redirect in 0 1; do
|
||||
jexec alcatraz sysctl net.inet6.ip6.redirect=${redirect}
|
||||
atf_check -s exit:2 -o ignore \
|
||||
ping -6 -c 1 -m 1 -W 1 2001:db8:43::3
|
||||
atf_check -o match:"[[:space:]]0 time exceed transit" \
|
||||
jexec alcatraz netstat -s -p icmp6
|
||||
done
|
||||
|
||||
pft_set_rules alcatraz "pass"
|
||||
atf_check -s exit:2 -o ignore ping -6 -c 1 -m 1 -W 1 2001:db8:43::3
|
||||
atf_check -o match:"[[:space:]]1 time exceed transit" \
|
||||
jexec alcatraz netstat -s -p icmp6
|
||||
}
|
||||
|
||||
v6_hlim_cleanup()
|
||||
{
|
||||
pft_cleanup
|
||||
}
|
||||
|
||||
atf_init_test_cases()
|
||||
{
|
||||
atf_add_test_case "v4"
|
||||
atf_add_test_case "v6"
|
||||
atf_add_test_case "v6_hlim"
|
||||
}
|
||||
Reference in new issue
Block a user