Page MenuHomeFreeBSD

D47684.diff
No OneTemporary

D47684.diff

diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
--- 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 @@
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
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -7927,6 +7927,7 @@
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 @@
}
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 @@
*/
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 @@
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
--- a/sys/netpfil/pf/pf_norm.c
+++ b/sys/netpfil/pf/pf_norm.c
@@ -42,6 +42,7 @@
#include <sys/socket.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/vnet.h>
#include <net/pfvar.h>
#include <net/if_pflog.h>
@@ -49,6 +50,8 @@
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_var.h>
+#include <netinet6/in6_var.h>
+#include <netinet6/nd6.h>
#include <netinet6/ip6_var.h>
#include <netinet6/scope6_var.h>
#include <netinet/tcp.h>
@@ -958,7 +961,7 @@
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 @@
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
--- a/tests/sys/netpfil/pf/fragmentation_pass.sh
+++ b/tests/sys/netpfil/pf/fragmentation_pass.sh
@@ -155,6 +155,75 @@
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_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"

File Metadata

Mime Type
text/plain
Expires
Wed, Feb 12, 7:28 AM (18 h, 33 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16607855
Default Alt Text
D47684.diff (6 KB)

Event Timeline