From nobody Tue Nov 26 14:07:34 2024 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4XyPXk72JWz5fWQn; Tue, 26 Nov 2024 14:07:34 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R10" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4XyPXk6XRKz4Ss9; Tue, 26 Nov 2024 14:07:34 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1732630054; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=RkhEE/M+KLvnD7K70Kt40areEXe3dANS0QEsenpPtHQ=; b=WwLBohOQYbeRgawRhs9TEUDNocw1yZUD3J5iv+ExWT6IdDbksGdNw831acbI9On73EMiSI fwYRWbh23aDjrmTGhlGdHBocBVIcbj/3w5amOhEnJrayieSNO/OwsmB+XUi74AEf+bvQkK k7fKrr0AE5gCx0JtYUH1LqXIhFkWdole8K8Xs+068pZg13RRkwO+Oux86Zsn+fUH+3f6Sl w2NUvQFFpwdJEJN0FvaU0p7GBcFp7jovm6fIzHnKGpetDNzEe3hf2ejyUdowb+xCp8tz6G 6JnqPMvYcD+WK16zwUaxQxF7sf8uTA8SpwQ4/xVdMJKM/Bk6vvYbqVl6BdMrNA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1732630054; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=RkhEE/M+KLvnD7K70Kt40areEXe3dANS0QEsenpPtHQ=; b=Salr0QmVq2ogOZ9681EJjFf65gqYdQaj1u8Z9ZibmkjaINrzKQyKvuHQgLs90KnoeqptKt VbV0JL0n+bOQVk6JcfLCxu4k1IlCghctFbOXUy2wEvsqfxNv7nwxOdjNsv007stcDtHYB8 I0/J+gwUgoCSGxIAQUT1Ul/WJMFyj6Xr/Fjj1K2mi7wxH3I3FtXwAn2p3040/ywaTu1KOy J03POO1hpQwVF2wOzwHWr0ea3PeSxrsBgVH3Bx5ft6xpNw9v78fseMmlWI9EswEFKz1H49 TAuKYjhJb/NHLuCTLN2mkrJ9vreZXWbTQOg9E9t1V/+GVmJNzbjd58G8BREkiw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1732630054; a=rsa-sha256; cv=none; b=PDOo+vtQHBtWSesPcopaDN1OajmJe5ufKXyylssB9vhAQfY4/yW8Uk2m3Zblw9HmnZYa2q dCNBFCOPXo+qe9H/zauvFGlFi5P6gCEK1E6/BilrYvZYCI1Uyb37ypKhiA7va18jty7cpS ExqIBiM5tdlp3DYzxkqDXKAEdXSr4FEGeP3F01K9fFmfpySlC6pnRIRrePtGtTZA4lmv4n rBq0kirBi0XmhqxIvzWUCSiCA6S5hqh8pu1c4U1r5nbDoX4rSkojwtbf+MNjl1uWE5uYFN dGHmXAN3aVkrKS9dbxPgGxF209dy/r3ap4IvPG5KdIc262cqeSxMw0/VtmK9eA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4XyPXk68SSzSQ3; Tue, 26 Nov 2024 14:07:34 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 4AQE7Yun010248; Tue, 26 Nov 2024 14:07:34 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 4AQE7Y6Y010245; Tue, 26 Nov 2024 14:07:34 GMT (envelope-from git) Date: Tue, 26 Nov 2024 14:07:34 GMT Message-Id: <202411261407.4AQE7Y6Y010245@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kristof Provost Subject: git: 56b7685ae328 - main - pf: handle IPv6 fragmentation for route-to List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kp X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 56b7685ae3285aa8c29574f116c6bc2c4fe17cc8 Auto-Submitted: auto-generated The branch main has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=56b7685ae3285aa8c29574f116c6bc2c4fe17cc8 commit 56b7685ae3285aa8c29574f116c6bc2c4fe17cc8 Author: Kristof Provost AuthorDate: 2024-11-26 08:45:13 +0000 Commit: Kristof Provost CommitDate: 2024-11-26 14:06:52 +0000 pf: handle IPv6 fragmentation for route-to If a fragmented IPv6 packet hits a route-to rule we have to first prevent the pf_test(PF_OUT) check in pf_route6() from refragmenting (and calling ip6_output()/ip6_forward()). We then have to refragment in pf_route6() and transmit the packets on the route-to interface. Split pf_refragment6() into two parts, the first to perform the refragmentation, the second to call ip6_output()/ip6_forward() and call the former from pf_route6(). Add a test case for route-to-ing fragmented IPv6 packets to verify this works as expected. Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D47684 --- sys/net/pfvar.h | 5 ++- sys/netpfil/pf/pf.c | 18 ++++++-- sys/netpfil/pf/pf_norm.c | 34 ++++++++++----- tests/sys/netpfil/pf/fragmentation_pass.sh | 70 ++++++++++++++++++++++++++++++ 4 files changed, 112 insertions(+), 15 deletions(-) diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index 0dc5d4363867..e00101ba2b78 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -70,6 +70,8 @@ #ifdef _KERNEL +#define PF_PFIL_NOREFRAGMENT 0x80000000 + #if defined(__arm__) #define PF_WANT_32_TO_64_COUNTER #endif @@ -2372,7 +2374,8 @@ void pf_poolmask(struct pf_addr *, struct pf_addr*, struct pf_addr *, struct pf_addr *, sa_family_t); void pf_addr_inc(struct pf_addr *, sa_family_t); int pf_max_frag_size(struct mbuf *); -int pf_refragment6(struct ifnet *, struct mbuf **, struct m_tag *, bool); +int pf_refragment6(struct ifnet *, struct mbuf **, struct m_tag *, + struct ifnet *, bool); #endif /* INET6 */ int pf_multihome_scan_init(int, int, struct pf_pdesc *); diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c index 5a0cad132340..fdec1cecb350 100644 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -7927,6 +7927,7 @@ pf_route6(struct mbuf **m, struct pf_krule *r, struct ifnet *oifp, struct pf_kstate *s, struct pf_pdesc *pd, struct inpcb *inp) { struct mbuf *m0, *md; + struct m_tag *mtag; struct sockaddr_in6 dst; struct ip6_hdr *ip6; struct pfi_kkif *nkif = NULL; @@ -8053,8 +8054,8 @@ pf_route6(struct mbuf **m, struct pf_krule *r, struct ifnet *oifp, } if (pd->dir == PF_IN) { - if (pf_test(AF_INET6, PF_OUT, PFIL_FWD, ifp, &m0, inp, - &pd->act) != PF_PASS) { + if (pf_test(AF_INET6, PF_OUT, PFIL_FWD | PF_PFIL_NOREFRAGMENT, + ifp, &m0, inp, &pd->act) != PF_PASS) { SDT_PROBE1(pf, ip6, route_to, drop, __LINE__); goto bad; } else if (m0 == NULL) { @@ -8087,6 +8088,14 @@ pf_route6(struct mbuf **m, struct pf_krule *r, struct ifnet *oifp, */ if (IN6_IS_SCOPE_EMBED(&dst.sin6_addr)) dst.sin6_addr.s6_addr16[1] = htons(ifp->if_index); + mtag = m_tag_find(m0, PACKET_TAG_PF_REASSEMBLED, NULL); + if (mtag != NULL) { + int ret; + ret = pf_refragment6(ifp, &m0, mtag, ifp, true); + SDT_PROBE2(pf, ip6, route_to, output, ifp, ret); + goto done; + } + if ((u_long)m0->m_pkthdr.len <= ifp->if_mtu) { md = m0; pf_dummynet_route(pd, s, r, ifp, sintosa(&dst), &md); @@ -9474,14 +9483,15 @@ eat_pkt: if (s) PF_STATE_UNLOCK(s); +out: #ifdef INET6 /* If reassembled packet passed, create new fragments. */ if (af == AF_INET6 && action == PF_PASS && *m0 && dir == PF_OUT && + (! (pflags & PF_PFIL_NOREFRAGMENT)) && (mtag = m_tag_find(pd.m, PACKET_TAG_PF_REASSEMBLED, NULL)) != NULL) - action = pf_refragment6(ifp, m0, mtag, pflags & PFIL_FWD); + action = pf_refragment6(ifp, m0, mtag, NULL, pflags & PFIL_FWD); #endif -out: pf_sctp_multihome_delayed(&pd, kif, s, action); return (action); diff --git a/sys/netpfil/pf/pf_norm.c b/sys/netpfil/pf/pf_norm.c index 8779d599900e..6e19c23d0b73 100644 --- a/sys/netpfil/pf/pf_norm.c +++ b/sys/netpfil/pf/pf_norm.c @@ -42,6 +42,7 @@ #include #include +#include #include #include #include @@ -49,6 +50,8 @@ #include #include #include +#include +#include #include #include #include @@ -958,7 +961,7 @@ pf_max_frag_size(struct mbuf *m) int pf_refragment6(struct ifnet *ifp, struct mbuf **m0, struct m_tag *mtag, - bool forward) + struct ifnet *rt, bool forward) { struct mbuf *m = *m0, *t; struct ip6_hdr *hdr; @@ -1029,16 +1032,27 @@ pf_refragment6(struct ifnet *ifp, struct mbuf **m0, struct m_tag *mtag, m->m_flags |= M_SKIP_FIREWALL; memset(&pd, 0, sizeof(pd)); pd.pf_mtag = pf_find_mtag(m); - if (error == 0) - if (forward) { - MPASS(m->m_pkthdr.rcvif != NULL); - ip6_forward(m, 0); - } else { - (void)ip6_output(m, NULL, NULL, 0, NULL, NULL, - NULL); - } - else + if (error != 0) { m_freem(m); + continue; + } + if (rt != NULL) { + struct sockaddr_in6 dst; + hdr = mtod(m, struct ip6_hdr *); + + bzero(&dst, sizeof(dst)); + dst.sin6_family = AF_INET6; + dst.sin6_len = sizeof(dst); + dst.sin6_addr = hdr->ip6_dst; + + nd6_output_ifp(rt, rt, m, &dst, NULL); + } else if (forward) { + MPASS(m->m_pkthdr.rcvif != NULL); + ip6_forward(m, 0); + } else { + (void)ip6_output(m, NULL, NULL, 0, NULL, NULL, + NULL); + } } return (action); diff --git a/tests/sys/netpfil/pf/fragmentation_pass.sh b/tests/sys/netpfil/pf/fragmentation_pass.sh index 2399eb0374bb..68b078d42ddc 100644 --- a/tests/sys/netpfil/pf/fragmentation_pass.sh +++ b/tests/sys/netpfil/pf/fragmentation_pass.sh @@ -155,6 +155,75 @@ v6_cleanup() pft_cleanup } +atf_test_case "v6_route_to" "cleanup" +v6_route_to_head() +{ + atf_set descr 'Test IPv6 reassembly combined with route-to' + atf_set require.user root +} + +v6_route_to_body() +{ + pft_init +} + +v6_route_to_cleanup() +{ + pft_cleanup + + 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 ifconfig ${epair_send}b inet6 -ifdisabled + jexec alcatraz ifconfig ${epair_link}a inet6 -ifdisabled + jexec singsing ifconfig ${epair_link}b inet6 -ifdisabled + ifconfig ${epair_send}a inet6 -ifdisabled + + jexec alcatraz pfctl -e + pft_set_rules alcatraz \ + "set reassemble yes" \ + "pass" \ + "pass in route-to (${epair_link}a 2001:db8:43::3) inet6 proto icmp6 from any to 2001:db8:43::3 keep state" + + # Forwarding test + atf_check -s exit:0 -o ignore \ + ping -6 -c 1 2001:db8:43::3 + + atf_check -s exit:0 -o ignore \ + ping -6 -c 1 -s 4500 2001:db8:43::3 + + atf_check -s exit:0 -o ignore\ + ping -6 -c 1 -b 70000 -s 65000 2001:db8:43::3 + + # Now test this without fragmentation + pft_set_rules alcatraz \ + "set reassemble no" \ + "pass" \ + "pass in route-to (${epair_link}a 2001:db8:43::3) inet6 proto icmp6 from any to 2001:db8:43::3 keep state" + + atf_check -s exit:0 -o ignore \ + ping -6 -c 1 2001:db8:43::3 + + atf_check -s exit:0 -o ignore \ + ping -6 -c 1 -s 4500 2001:db8:43::3 + + atf_check -s exit:0 -o ignore\ + ping -6 -c 1 -b 70000 -s 65000 2001:db8:43::3 +} + atf_test_case "mtu_diff" "cleanup" mtu_diff_head() { @@ -544,6 +613,7 @@ atf_init_test_cases() { atf_add_test_case "too_many_fragments" atf_add_test_case "v6" + atf_add_test_case "v6_route_to" atf_add_test_case "mtu_diff" atf_add_test_case "overreplace" atf_add_test_case "overindex"