git: 8c73c0f1230d - main - netinet6: Set PFIL_FWD in ip6_tryforward()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 30 Oct 2026 17:34:16 UTC
The branch main has been updated by rcm:
URL: https://cgit.FreeBSD.org/src/commit/?id=8c73c0f1230dde0a65474b1ae9a94f27f6568bda
commit 8c73c0f1230dde0a65474b1ae9a94f27f6568bda
Author: R. Christian McDonald <rcm@FreeBSD.org>
AuthorDate: 2026-10-30 17:31:37 +0000
Commit: R. Christian McDonald <rcm@FreeBSD.org>
CommitDate: 2026-10-30 17:31:37 +0000
netinet6: Set PFIL_FWD in ip6_tryforward()
ip6_forward() has run the outbound hooks with pfil_mbuf_fwd() since
b52b61c0b6b1, and ip_tryforward() since 1f4c3887e3fa, but
ip6_tryforward() still calls pfil_mbuf_out(). pf therefore handles a
packet on the IPv6 fast path as locally generated: it skips the
packet-too-big error it sends with the untranslated addresses, and
pf_refragment6() sends reassembled packets out through ip6_output()
instead of ip6_forward(), so their fragments leave with the hop limit
not decremented.
Use pfil_mbuf_fwd() in ip6_tryforward() as well. The new
fragmentation_pass:v6_refrag_hlim test sends a packet that pf
reassembles and refragments through the fast path, and checks that its
fragments leave with the hop limit decremented once; before this change
they leave with it unchanged.
Reviewed by: kp
Fixes: b52b61c0 ("pf: distinguish forwarding and output cases for ...")
MFC after: 1 week
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D61033
---
sys/netinet6/ip6_fastfwd.c | 2 +-
tests/sys/netpfil/pf/fragmentation_pass.sh | 55 ++++++++++++++++++++++++++++++
2 files changed, 56 insertions(+), 1 deletion(-)
diff --git a/sys/netinet6/ip6_fastfwd.c b/sys/netinet6/ip6_fastfwd.c
index 8a288eb19891..f6d6df4c7b96 100644
--- a/sys/netinet6/ip6_fastfwd.c
+++ b/sys/netinet6/ip6_fastfwd.c
@@ -218,7 +218,7 @@ passin:
/*
* Outgoing packet firewall processing.
*/
- if (pfil_mbuf_out(V_inet6_pfil_head, &m, nh->nh_ifp,
+ if (pfil_mbuf_fwd(V_inet6_pfil_head, &m, nh->nh_ifp,
NULL) != PFIL_PASS)
goto dropout;
diff --git a/tests/sys/netpfil/pf/fragmentation_pass.sh b/tests/sys/netpfil/pf/fragmentation_pass.sh
index c749aac793ee..d5310d6eeb58 100644
--- a/tests/sys/netpfil/pf/fragmentation_pass.sh
+++ b/tests/sys/netpfil/pf/fragmentation_pass.sh
@@ -155,6 +155,60 @@ v6_cleanup()
pft_cleanup
}
+# refrag_hlim REDIRECT: with net.inet6.ip6.redirect at REDIRECT on the router
+# (0: ip6_tryforward(), 1: ip6_forward()), a forwarded packet that pf
+# reassembles and refragments loses one hop: the echo reply comes back
+# through alcatraz in fragments, with the hop limit singsing sent minus one.
+refrag_hlim()
+{
+ jexec alcatraz sysctl net.inet6.ip6.redirect=$1
+ atf_check -o match:"icmp_seq=0 hlim=63 " \
+ ping -6 -c 1 -m 64 -s 4500 2001:db8:43::3
+}
+
+atf_test_case "v6_refrag_hlim" "cleanup"
+v6_refrag_hlim_head()
+{
+ atf_set descr 'Refragmented forwarded IPv6 loses one hop'
+ atf_set require.user root
+}
+
+v6_refrag_hlim_body()
+{
+ pft_init
+
+ epair_send=$(vnet_mkepair)
+ epair_link=$(vnet_mkepair)
+
+ vnet_mkjail alcatraz ${epair_send}b ${epair_link}a
+ vnet_mkjail singsing ${epair_link}b
+
+ ifconfig ${epair_send}a inet6 2001:db8:42::1/64 no_dad up
+
+ jexec alcatraz ifconfig ${epair_send}b inet6 2001:db8:42::2/64 no_dad up
+ jexec alcatraz ifconfig ${epair_link}a inet6 2001:db8:43::2/64 no_dad up
+ jexec alcatraz sysctl net.inet6.ip6.forwarding=1
+
+ jexec singsing ifconfig ${epair_link}b inet6 2001:db8:43::3/64 no_dad up
+ jexec singsing route add -6 2001:db8:42::/64 2001:db8:43::2
+ route add -6 2001:db8:43::/64 2001:db8:42::2
+
+ jexec alcatraz pfctl -e
+ pft_set_rules alcatraz \
+ "set reassemble yes" \
+ "pass"
+
+ atf_check -o ignore ping -6 -c 1 2001:db8:43::3
+
+ # The fast path: pf must refragment through ip6_forward().
+ refrag_hlim 0
+}
+
+v6_refrag_hlim_cleanup()
+{
+ pft_cleanup
+}
+
atf_test_case "v6_route_to" "cleanup"
v6_route_to_head()
{
@@ -718,6 +772,7 @@ atf_init_test_cases()
{
atf_add_test_case "too_many_fragments"
atf_add_test_case "v6"
+ atf_add_test_case "v6_refrag_hlim"
atf_add_test_case "v6_route_to"
atf_add_test_case "mtu_diff"
atf_add_test_case "overreplace"