diff options
Diffstat (limited to 'tests/sys/netpfil')
| -rw-r--r-- | tests/sys/netpfil/pf/Makefile | 2 | ||||
| -rw-r--r-- | tests/sys/netpfil/pf/anchor.sh | 46 | ||||
| -rw-r--r-- | tests/sys/netpfil/pf/ioctl/validation.c | 58 | ||||
| -rw-r--r-- | tests/sys/netpfil/pf/nat.sh | 47 | ||||
| -rw-r--r-- | tests/sys/netpfil/pf/proxy.sh | 61 | ||||
| -rwxr-xr-x | tests/sys/netpfil/pf/src_track.sh | 74 | ||||
| -rw-r--r-- | tests/sys/netpfil/pf/table.sh | 62 | ||||
| -rw-r--r-- | tests/sys/netpfil/pf/tftpd_inetd.conf | 28 | ||||
| -rw-r--r-- | tests/sys/netpfil/pf/tftpd_proxy_inetd.conf | 27 | 
9 files changed, 399 insertions, 6 deletions
| diff --git a/tests/sys/netpfil/pf/Makefile b/tests/sys/netpfil/pf/Makefile index b363e0b17c76..9416f6abbdf1 100644 --- a/tests/sys/netpfil/pf/Makefile +++ b/tests/sys/netpfil/pf/Makefile @@ -90,6 +90,8 @@ ${PACKAGE}FILES+=	\  			pft_ether.py \  			pft_read_ipfix.py \  			rdr-srcport.py \ +			tftpd_inetd.conf \ +			tftpd_proxy_inetd.conf \  			utils.subr \  			utils.py diff --git a/tests/sys/netpfil/pf/anchor.sh b/tests/sys/netpfil/pf/anchor.sh index 64ca84b34c3d..f321c742788e 100644 --- a/tests/sys/netpfil/pf/anchor.sh +++ b/tests/sys/netpfil/pf/anchor.sh @@ -123,6 +123,51 @@ nested_anchor_cleanup()  	pft_cleanup  } +atf_test_case "deeply_nested" "cleanup" +deeply_nested_head() +{ +	atf_set descr 'Test setting and retrieving deeply nested anchors' +	atf_set require.user root +} + +deeply_nested_body() +{ +	pft_init + +	epair=$(vnet_mkepair) +	vnet_mkjail alcatraz ${epair}a + +	pft_set_rules alcatraz \ +		"anchor \"foo\" { \n\ +			anchor \"bar\" { \n\ +				anchor \"foobar\" { \n\ +					pass on ${epair}a \n\ +				} \n\ +				anchor \"quux\" { \n\ +					pass on ${epair}a \n\ +				} \n\ +			} \n\ +			anchor \"baz\" { \n\ +				pass on ${epair}a \n\ +			} \n\ +			anchor \"qux\" { \n\ +				pass on ${epair}a \n\ +			} \n\ +		}" + +	atf_check -s exit:0 -o \ +	    inline:"  foo\n  foo/bar\n  foo/bar/foobar\n  foo/bar/quux\n  foo/baz\n  foo/qux\n" \ +	    jexec alcatraz pfctl -sA + +	atf_check -s exit:0 -o inline:"  foo/bar/foobar\n  foo/bar/quux\n" \ +	    jexec alcatraz pfctl -a foo/bar -sA +} + +deeply_nested_cleanup() +{ +	pft_cleanup +} +  atf_test_case "wildcard" "cleanup"  wildcard_head()  { @@ -498,6 +543,7 @@ atf_init_test_cases()  	atf_add_test_case "pr183198"  	atf_add_test_case "pr279225"  	atf_add_test_case "nested_anchor" +	atf_add_test_case "deeply_nested"  	atf_add_test_case "wildcard"  	atf_add_test_case "nested_label"  	atf_add_test_case "quick" diff --git a/tests/sys/netpfil/pf/ioctl/validation.c b/tests/sys/netpfil/pf/ioctl/validation.c index 3e03163cc752..bb060e22f3a0 100644 --- a/tests/sys/netpfil/pf/ioctl/validation.c +++ b/tests/sys/netpfil/pf/ioctl/validation.c @@ -194,6 +194,38 @@ ATF_TC_CLEANUP(gettables, tc)  	COMMON_CLEANUP();  } +ATF_TC_WITH_CLEANUP(clrtables); +ATF_TC_HEAD(clrtables, tc) +{ +	atf_tc_set_md_var(tc, "require.user", "root"); +	atf_tc_set_md_var(tc, "require.kmods", "pf"); +} + +ATF_TC_BODY(clrtables, tc) +{ +	struct pfioc_table io; +	struct pfr_table tbl; +	int flags; + +	COMMON_HEAD(); + +	flags = 0; + +	memset(&io, '/', sizeof(io)); +	io.pfrio_flags = flags; +	io.pfrio_buffer = &tbl; +	io.pfrio_esize = 0; +	io.pfrio_size = 1; + +	if (ioctl(dev, DIOCRCLRTABLES, &io) == 0) +		atf_tc_fail("Request with unterminated anchor name succeeded"); +} + +ATF_TC_CLEANUP(clrtables, tc) +{ +	COMMON_CLEANUP(); +} +  ATF_TC_WITH_CLEANUP(gettstats);  ATF_TC_HEAD(gettstats, tc)  { @@ -949,11 +981,36 @@ ATF_TC_CLEANUP(natlook, tc)  	COMMON_CLEANUP();  } +ATF_TC_WITH_CLEANUP(addstate); +ATF_TC_HEAD(addstate, tc) +{ +	atf_tc_set_md_var(tc, "require.user", "root"); +	atf_tc_set_md_var(tc, "require.kmods", "pfsync"); +} + +ATF_TC_BODY(addstate, tc) +{ +	struct pfioc_state st; + +	COMMON_HEAD(); + +	memset(&st, 'a', sizeof(st)); +	st.state.timeout = PFTM_TCP_FIRST_PACKET; + +	ATF_CHECK_ERRNO(EINVAL, ioctl(dev, DIOCADDSTATE, &st) == -1); +} + +ATF_TC_CLEANUP(addstate, tc) +{ +	COMMON_CLEANUP(); +} +  ATF_TP_ADD_TCS(tp)  {  	ATF_TP_ADD_TC(tp, addtables);  	ATF_TP_ADD_TC(tp, deltables);  	ATF_TP_ADD_TC(tp, gettables); +	ATF_TP_ADD_TC(tp, clrtables);  	ATF_TP_ADD_TC(tp, getastats);  	ATF_TP_ADD_TC(tp, gettstats);  	ATF_TP_ADD_TC(tp, clrtstats); @@ -974,6 +1031,7 @@ ATF_TP_ADD_TCS(tp)  	ATF_TP_ADD_TC(tp, rpool_mtx);  	ATF_TP_ADD_TC(tp, rpool_mtx2);  	ATF_TP_ADD_TC(tp, natlook); +	ATF_TP_ADD_TC(tp, addstate);  	return (atf_no_error());  } diff --git a/tests/sys/netpfil/pf/nat.sh b/tests/sys/netpfil/pf/nat.sh index 1ef87cee3598..0824671fa0f1 100644 --- a/tests/sys/netpfil/pf/nat.sh +++ b/tests/sys/netpfil/pf/nat.sh @@ -477,15 +477,49 @@ no_addrs_random_cleanup()  	pft_cleanup  } -atf_test_case "nat_pass" "cleanup" -nat_pass_head() +atf_test_case "nat_pass_in" "cleanup" +nat_pass_in_head()  { -	atf_set descr 'IPv4 NAT on pass rule' +	atf_set descr 'IPv4 NAT on inbound pass rule'  	atf_set require.user root  	atf_set require.progs scapy  } -nat_pass_body() +nat_pass_in_body() +{ +	setup_router_server_ipv4 +	# Delete the route back to make sure that the traffic has been NAT-ed +	jexec server route del -net ${net_tester} ${net_server_host_router} +	# Provide routing back to the NAT address +	jexec server route add 203.0.113.0/24 ${net_server_host_router} +	jexec router route add 203.0.113.0/24 -iface ${epair_tester}b + +	pft_set_rules router \ +		"block" \ +		"pass in  on ${epair_tester}b inet proto tcp nat-to 203.0.113.0 keep state" \ +		"pass out on ${epair_server}a inet proto tcp keep state" + +	ping_server_check_reply exit:0 --ping-type=tcp3way --send-sport=4201 + +	jexec router pfctl -qvvsr +	jexec router pfctl -qvvss +	jexec router ifconfig +	jexec router netstat -rn +} + +nat_pass_in_cleanup() +{ +	pft_cleanup +} + +nat_pass_out_head() +{ +	atf_set descr 'IPv4 NAT on outbound pass rule' +	atf_set require.user root +	atf_set require.progs scapy +} + +nat_pass_out_body()  {  	setup_router_server_ipv4  	# Delete the route back to make sure that the traffic has been NAT-ed @@ -504,7 +538,7 @@ nat_pass_body()  	jexec router netstat -rn  } -nat_pass_cleanup() +nat_pass_out_cleanup()  {  	pft_cleanup  } @@ -874,7 +908,8 @@ atf_init_test_cases()  	atf_add_test_case "no_addrs_random"  	atf_add_test_case "map_e_compat"  	atf_add_test_case "map_e_pass" -	atf_add_test_case "nat_pass" +	atf_add_test_case "nat_pass_in" +	atf_add_test_case "nat_pass_out"  	atf_add_test_case "nat_match"  	atf_add_test_case "binat_compat"  	atf_add_test_case "binat_match" diff --git a/tests/sys/netpfil/pf/proxy.sh b/tests/sys/netpfil/pf/proxy.sh index 78ce25930c04..a07bb259b544 100644 --- a/tests/sys/netpfil/pf/proxy.sh +++ b/tests/sys/netpfil/pf/proxy.sh @@ -88,7 +88,68 @@ ftp_cleanup()  	pft_cleanup  } +atf_test_case "tftp" "cleanup" +tftp_head() +{ +	atf_set descr 'Test tftp-proxy' +	atf_set require.user root +} + +tftp_body() +{ +	pft_init + +	epair_client=$(vnet_mkepair) +	epair_link=$(vnet_mkepair) + +	ifconfig ${epair_client}a 192.0.2.2/24 up +	route add -net 198.51.100.0/24 192.0.2.1 + +	vnet_mkjail fwd ${epair_client}b ${epair_link}a +	jexec fwd ifconfig lo0 127.0.0.1/8 up +	jexec fwd ifconfig ${epair_client}b 192.0.2.1/24 up +	jexec fwd ifconfig ${epair_link}a 198.51.100.1/24 up +	jexec fwd ifconfig lo0 127.0.0.1/8 up +	jexec fwd sysctl net.inet.ip.forwarding=1 + +	vnet_mkjail srv ${epair_link}b +	jexec srv ifconfig ${epair_link}b 198.51.100.2/24 up +	jexec srv route add default 198.51.100.1 + +	# Start tftp server in srv +	jexec srv /usr/sbin/inetd -p ${PWD}/inetd-srv.pid \ +	    $(atf_get_srcdir)/tftpd_inetd.conf + +	jexec fwd /usr/sbin/inetd -p ${PWD}/inetd-fwd.pid \ +	    $(atf_get_srcdir)/tftpd_proxy_inetd.conf + +	jexec fwd pfctl -e +	pft_set_rules fwd \ +		"nat on ${epair_link}a inet from 192.0.2.0/24 to any -> (${epair_link}a)" \ +		"nat-anchor \"tftp-proxy/*\"" \ +		"rdr-anchor \"tftp-proxy/*\"" \ +		"rdr pass on ${epair_client}b proto udp from 192.0.2.0/24 to any port 69 -> 127.0.0.1 port 69" \ +		"anchor \"tftp-proxy/*\"" \ +		"pass out proto udp from 127.0.0.1 to any port 69" + +	# Create a dummy file to download +	echo 'foo' > /tmp/remote.txt +	echo 'get remote.txt local.txt' | tftp 198.51.100.2 + +	# Compare the downloaded file to the original +	if ! diff -q local.txt /tmp/remote.txt; +	then +		atf_fail 'Failed to retrieve file' +	fi +} + +tftp_cleanup() +{ +	pft_cleanup +} +  atf_init_test_cases()  {  	atf_add_test_case "ftp" +	atf_add_test_case "tftp"  } diff --git a/tests/sys/netpfil/pf/src_track.sh b/tests/sys/netpfil/pf/src_track.sh index d86b4ce6c466..1b09030f6174 100755 --- a/tests/sys/netpfil/pf/src_track.sh +++ b/tests/sys/netpfil/pf/src_track.sh @@ -588,6 +588,79 @@ mixed_af_cleanup()  	pft_cleanup  } +atf_test_case "check_valid" "cleanup" +check_valid_head() +{ +	atf_set descr 'Test if source node is invalidated on change in redirection pool' +	atf_set require.user root +	atf_set require.progs python3 scapy +} + +check_valid_body() +{ +	setup_router_server_nat64 + +	# Clients will connect from another network behind the router. +	# This allows for using multiple source addresses. +	jexec router route add -6 ${net_clients_6}::/${net_clients_6_mask} ${net_tester_6_host_tester} + +	jexec server1 ifconfig ${epair_server1}b inet6 ${net_server1_6}::42:1/128 alias +	jexec server1 ifconfig ${epair_server1}b inet6 ${net_server1_6}::42:2/128 alias + +	jexec router pfctl -e +	pft_set_rules router \ +		"set debug loud " \ +		"set state-policy if-bound" \ +		"table <targets> { ${net_server1_6}::42:1 }" \ +		"pass in on ${epair_tester}b \ +			route-to { (${epair_server1}a <targets>) } \ +			sticky-address \ +			proto tcp \ +			keep state" + +	atf_check -s exit:0 ${common_dir}/pft_ping.py \ +		--sendif ${epair_tester}a --replyif ${epair_tester}a \ +		--fromaddr ${net_clients_6}::1 --to ${host_server_6} \ +		--ping-type=tcp3way --send-sport=4201 + +	# A source node is created using the original redirection target +	nodes=$(mktemp) || exit 1 +	jexec router pfctl -qvvsS | normalize_pfctl_s > $nodes +	node_regexp='2001:db8:44::1 -> 2001:db8:4201::42:1 .* states 1,.* route sticky-address' +	grep -qE "${node_regexp}" $nodes || atf_fail "Source node not found for '${node_regexp}'" + +	# Change contents of the redirection table +	echo ${net_server1_6}::42:2 | jexec router pfctl -Tr -t targets -f - + +	atf_check -s exit:0 ${common_dir}/pft_ping.py \ +		--sendif ${epair_tester}a --replyif ${epair_tester}a \ +		--fromaddr ${net_clients_6}::1 --to ${host_server_6} \ +		--ping-type=tcp3way --send-sport=4202 + +	# The original source node was deleted, a new one was created. +	# It has 1 states. +	jexec router pfctl -qvvsS | normalize_pfctl_s > $nodes +	node_regexp='2001:db8:44::1 -> 2001:db8:4201::42:2 .* states 1,.* route sticky-address' +	grep -qE "${node_regexp}" $nodes || atf_fail "Source node not found for '${node_regexp}'" + +	atf_check -s exit:0 ${common_dir}/pft_ping.py \ +		--sendif ${epair_tester}a --replyif ${epair_tester}a \ +		--fromaddr ${net_clients_6}::1 --to ${host_server_6} \ +		--ping-type=tcp3way --send-sport=4203 + +	# Without redirection table change the source node is reused. +	# It has 2 states. +	jexec router pfctl -qvvsS | normalize_pfctl_s > $nodes +	node_regexp='2001:db8:44::1 -> 2001:db8:4201::42:2 .* states 2,.* route sticky-address' +	grep -qE "${node_regexp}" $nodes || atf_fail "Source node not found for '${node_regexp}'" +} + +check_valid_cleanup() +{ +	pft_cleanup +} + +  atf_init_test_cases()  {  	atf_add_test_case "source_track" @@ -598,4 +671,5 @@ atf_init_test_cases()  	atf_add_test_case "sn_types_compat"  	atf_add_test_case "sn_types_pass"  	atf_add_test_case "mixed_af" +	atf_add_test_case "check_valid"  } diff --git a/tests/sys/netpfil/pf/table.sh b/tests/sys/netpfil/pf/table.sh index 69fe12fc9804..6761ce652beb 100644 --- a/tests/sys/netpfil/pf/table.sh +++ b/tests/sys/netpfil/pf/table.sh @@ -747,6 +747,67 @@ in_anchor_cleanup()  	pft_cleanup  } +atf_test_case "replace" "cleanup" +replace_head() +{ +	atf_set descr 'Test table replace command' +	atf_set require.user root +} + +replace_body() +{ +	pft_init +	pwd=$(pwd) + +	epair_send=$(vnet_mkepair) +	ifconfig ${epair_send}a 192.0.2.1/24 up + +	vnet_mkjail alcatraz ${epair_send}b +	jexec alcatraz ifconfig ${epair_send}b 192.0.2.2/24 up +	jexec alcatraz pfctl -e + +	pft_set_rules alcatraz \ +	    "table <foo> counters { 192.0.2.1 }" \ +	    "block all" \ +	    "pass in from <foo> to any" \ +	    "pass out from any to <foo>" \ +	    "set skip on lo" + +	atf_check -s exit:0 -o ignore ping -c 3 192.0.2.2 + +	# Replace the address +	atf_check -s exit:0 -e "match:1 addresses added." -e "match:1 addresses deleted." \ +	    jexec alcatraz pfctl -t foo -T replace 192.0.2.3 +	atf_check -s exit:0 -o "match:192.0.2.3" \ +	    jexec alcatraz pfctl -t foo -T show +	atf_check -s exit:2 -o ignore ping -c 3 192.0.2.2 + +	# Negated address +	atf_check -s exit:0 -e "match:1 addresses changed." \ +	    jexec alcatraz pfctl -t foo -T replace "!192.0.2.3" + +	# Now add 500 addresses +	for i in `seq 1 2`; do +		for j in `seq 1 250`; do +			echo "1.${i}.${j}.1" >> ${pwd}/foo.lst +		done +	done +	atf_check -s exit:0 -e "match:500 addresses added." -e "match:1 addresses deleted." \ +	    jexec alcatraz pfctl -t foo -T replace -f ${pwd}/foo.lst + +	atf_check -s exit:0 -o "not-match:192.0.2.3" \ +	    jexec alcatraz pfctl -t foo -T show + +	# Loading the same list produces no changes. +	atf_check -s exit:0 -e "match:no changes." \ +	    jexec alcatraz pfctl -t foo -T replace -f ${pwd}/foo.lst +} + +replace_cleanup() +{ +	pft_cleanup +} +  atf_init_test_cases()  {  	atf_add_test_case "v4_counters" @@ -765,4 +826,5 @@ atf_init_test_cases()  	atf_add_test_case "large"  	atf_add_test_case "show_recursive"  	atf_add_test_case "in_anchor" +	atf_add_test_case "replace"  } diff --git a/tests/sys/netpfil/pf/tftpd_inetd.conf b/tests/sys/netpfil/pf/tftpd_inetd.conf new file mode 100644 index 000000000000..3554d0a7fb08 --- /dev/null +++ b/tests/sys/netpfil/pf/tftpd_inetd.conf @@ -0,0 +1,28 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2025 Rubicon Communications, LLC (Netgate) +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +#    notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +#    notice, this list of conditions and the following disclaimer in the +#    documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +tftp	dgram	udp	wait	root	/usr/libexec/tftpd	tftpd -l -S -s /tmp +tftp	dgram	udp6	wait	root	/usr/libexec/tftpd	tftpd -l -S -s /tmp diff --git a/tests/sys/netpfil/pf/tftpd_proxy_inetd.conf b/tests/sys/netpfil/pf/tftpd_proxy_inetd.conf new file mode 100644 index 000000000000..aa5f000f3bba --- /dev/null +++ b/tests/sys/netpfil/pf/tftpd_proxy_inetd.conf @@ -0,0 +1,27 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2025 Rubicon Communications, LLC (Netgate) +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +#    notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +#    notice, this list of conditions and the following disclaimer in the +#    documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +tftp	dgram	udp	wait	root	/usr/libexec/tftp-proxy tftp-proxy | 
