1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-10-19 02:29:40 +00:00

pf: fix dummynet + route-to

Ensure that we pick the correct dummynet pipe (i.e. forward vs. reverse
direction) when applying route-to.

We mark the processing as outbound so that dummynet will re-inject in
the correct phase of processing after it's done with the packet, but
that will cause us to pick the wrong pipe number. Reverse them so that
the incorrect decision ends up picking the correct pipe.

Sponsored by:	Rubicon Communications, LLC ("Netgate")
Differential Revision:	https://reviews.freebsd.org/D44366
This commit is contained in:
Kristof Provost 2024-03-12 13:29:08 +01:00
parent 0ea0c02655
commit c6f1116357
2 changed files with 84 additions and 7 deletions

View File

@ -7240,6 +7240,7 @@ pf_route(struct mbuf **m, struct pf_krule *r, struct ifnet *oifp,
struct pf_ksrc_node *sn = NULL;
int error = 0;
uint16_t ip_len, ip_off;
uint16_t tmp;
int r_rt, r_dir;
KASSERT(m && *m && r && oifp, ("%s: invalid parameters", __func__));
@ -7381,11 +7382,26 @@ pf_route(struct mbuf **m, struct pf_krule *r, struct ifnet *oifp,
m0->m_pkthdr.csum_flags &= ~CSUM_SCTP;
}
/*
* Make sure dummynet gets the correct direction, in case it needs to
* re-inject later.
*/
pd->dir = PF_OUT;
if (pd->dir == PF_IN) {
/*
* Make sure dummynet gets the correct direction, in case it needs to
* re-inject later.
*/
pd->dir = PF_OUT;
/*
* The following processing is actually the rest of the inbound processing, even
* though we've marked it as outbound (so we don't look through dummynet) and it
* happens after the outbound processing (pf_test(PF_OUT) above).
* Swap the dummynet pipe numbers, because it's going to come to the wrong
* conclusion about what direction it's processing, and we can't fix it or it
* will re-inject incorrectly. Swapping the pipe numbers means that its incorrect
* decision will pick the right pipe, and everything will mostly work as expected.
*/
tmp = pd->act.dnrpipe;
pd->act.dnrpipe = pd->act.dnpipe;
pd->act.dnpipe = tmp;
}
/*
* If small enough for interface, or the interface will take

View File

@ -345,7 +345,7 @@ dummynet_body()
# The ping request will pass, but take 1.2 seconds
# So this works:
atf_check -s exit:0 -o ignore ping -c 1 192.0.2.1
atf_check -s exit:0 -o ignore ping -c 1 -t 2 192.0.2.1
# But this times out:
atf_check -s exit:2 -o ignore ping -c 1 -t 1 192.0.2.1
@ -355,7 +355,7 @@ dummynet_body()
# The ping request will pass, but take 1.2 seconds
# So this works:
atf_check -s exit:0 -o ignore ping -c 1 192.0.2.1
atf_check -s exit:0 -o ignore ping -c 1 -t 2 192.0.2.1
# But this times out:
atf_check -s exit:2 -o ignore ping -c 1 -t 1 192.0.2.1
}
@ -365,6 +365,66 @@ dummynet_cleanup()
pft_cleanup
}
atf_test_case "dummynet_in" "cleanup"
dummynet_in_head()
{
atf_set descr 'Thest that dummynet works as expected on pass in route-to packets'
atf_set require.user root
}
dummynet_in_body()
{
dummynet_init
epair_srv=$(vnet_mkepair)
epair_gw=$(vnet_mkepair)
vnet_mkjail srv ${epair_srv}a
jexec srv ifconfig ${epair_srv}a 192.0.2.1/24 up
jexec srv route add default 192.0.2.2
vnet_mkjail gw ${epair_srv}b ${epair_gw}a
jexec gw ifconfig ${epair_srv}b 192.0.2.2/24 up
jexec gw ifconfig ${epair_gw}a 198.51.100.1/24 up
jexec gw sysctl net.inet.ip.forwarding=1
ifconfig ${epair_gw}b 198.51.100.2/24 up
route add -net 192.0.2.0/24 198.51.100.1
# Sanity check
atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.1
jexec gw dnctl pipe 1 config delay 1200
pft_set_rules gw \
"pass in route-to (${epair_srv}b 192.0.2.1) to 192.0.2.1 dnpipe 1"
jexec gw pfctl -e
# The ping request will pass, but take 1.2 seconds
# So this works:
echo "Expect 1.2 s"
ping -c 1 192.0.2.1
atf_check -s exit:0 -o ignore ping -c 1 -t 2 192.0.2.1
# But this times out:
atf_check -s exit:2 -o ignore ping -c 1 -t 1 192.0.2.1
# return path dummynet
pft_set_rules gw \
"pass in route-to (${epair_srv}b 192.0.2.1) to 192.0.2.1 dnpipe (0, 1)"
# The ping request will pass, but take 1.2 seconds
# So this works:
echo "Expect 1.2 s"
ping -c 1 192.0.2.1
atf_check -s exit:0 -o ignore ping -c 1 -t 2 192.0.2.1
# But this times out:
atf_check -s exit:2 -o ignore ping -c 1 -t 1 192.0.2.1
}
dummynet_in_cleanup()
{
pft_cleanup
}
atf_test_case "ifbound" "cleanup"
ifbound_head()
{
@ -675,6 +735,7 @@ atf_init_test_cases()
atf_add_test_case "multiwanlocal"
atf_add_test_case "icmp_nat"
atf_add_test_case "dummynet"
atf_add_test_case "dummynet_in"
atf_add_test_case "ifbound"
atf_add_test_case "ifbound_v6"
atf_add_test_case "ifbound_reply_to"