xref: /freebsd-src/tests/sys/netpfil/pf/utils.subr (revision 65b20771713c7ec4d46fb5af4a16353209658d79)
11d6f5f21SKristof Provost# Utility functions
21d6f5f21SKristof Provost##
34d846d26SWarner Losh# SPDX-License-Identifier: BSD-2-Clause
465d553b0SKristof Provost#
565d553b0SKristof Provost# Copyright (c) 2017 Kristof Provost <kp@FreeBSD.org>
638e2d5dbSKristof Provost# Copyright (c) 2023 Kajetan Staszkiewicz <vegeta@tuxpowered.net>
765d553b0SKristof Provost#
865d553b0SKristof Provost# Redistribution and use in source and binary forms, with or without
965d553b0SKristof Provost# modification, are permitted provided that the following conditions
1065d553b0SKristof Provost# are met:
1165d553b0SKristof Provost# 1. Redistributions of source code must retain the above copyright
1265d553b0SKristof Provost#    notice, this list of conditions and the following disclaimer.
1365d553b0SKristof Provost# 2. Redistributions in binary form must reproduce the above copyright
1465d553b0SKristof Provost#    notice, this list of conditions and the following disclaimer in the
1565d553b0SKristof Provost#    documentation and/or other materials provided with the distribution.
1665d553b0SKristof Provost#
1765d553b0SKristof Provost# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1865d553b0SKristof Provost# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1965d553b0SKristof Provost# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2065d553b0SKristof Provost# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2165d553b0SKristof Provost# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2265d553b0SKristof Provost# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2365d553b0SKristof Provost# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2465d553b0SKristof Provost# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2565d553b0SKristof Provost# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2665d553b0SKristof Provost# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2765d553b0SKristof Provost# SUCH DAMAGE.
281d6f5f21SKristof Provost
2906aac31aSKristof Provost. $(atf_get_srcdir)/../../common/vnet.subr
3038e2d5dbSKristof Provostcommon_dir=$(atf_get_srcdir)/../common
3106aac31aSKristof Provost
324826406bSKristof Provostpft_onerror()
334826406bSKristof Provost{
344826406bSKristof Provost	status=$?
354826406bSKristof Provost
364826406bSKristof Provost	echo "Debug log."
374826406bSKristof Provost	echo "=========="
384826406bSKristof Provost	echo "Test exit status: $?"
394826406bSKristof Provost	echo
404826406bSKristof Provost
414826406bSKristof Provost	if [ -f created_jails.lst ]; then
424826406bSKristof Provost		for jailname in `cat created_jails.lst`
434826406bSKristof Provost		do
444826406bSKristof Provost			echo "Jail ${jailname}"
454826406bSKristof Provost			echo "----------------"
464826406bSKristof Provost			jexec ${jailname} ifconfig
474826406bSKristof Provost			jexec ${jailname} netstat -rn
484826406bSKristof Provost			jexec ${jailname} pfctl -sa -v
494826406bSKristof Provost		done
504826406bSKristof Provost	fi
514826406bSKristof Provost
524826406bSKristof Provost	echo "Created interfaces:"
534826406bSKristof Provost	echo "-------------------"
544826406bSKristof Provost	cat created_interfaces.lst
554826406bSKristof Provost
564826406bSKristof Provost	echo "Host interfaces:"
574826406bSKristof Provost	echo "----------------"
584826406bSKristof Provost	ifconfig
594826406bSKristof Provost}
604826406bSKristof Provost
611d6f5f21SKristof Provostpft_init()
621d6f5f21SKristof Provost{
6334478b73SKristof Provost	if [ "$1" == "debug" ]
6434478b73SKristof Provost	then
654826406bSKristof Provost		trap pft_onerror EXIT
6634478b73SKristof Provost	fi
674826406bSKristof Provost
6806aac31aSKristof Provost	vnet_init
6906aac31aSKristof Provost
701d6f5f21SKristof Provost	if [ ! -c /dev/pf ]; then
711d6f5f21SKristof Provost		atf_skip "This test requires pf"
721d6f5f21SKristof Provost	fi
731d6f5f21SKristof Provost}
741d6f5f21SKristof Provost
756ab3ac5aSKristof Provostpfsynct_init()
766ab3ac5aSKristof Provost{
776ab3ac5aSKristof Provost	pft_init
786ab3ac5aSKristof Provost
796ab3ac5aSKristof Provost	if ! kldstat -q -m pfsync; then
806ab3ac5aSKristof Provost		atf_skip "This test requires pfsync"
816ab3ac5aSKristof Provost	fi
826ab3ac5aSKristof Provost}
836ab3ac5aSKristof Provost
8450816111SKristof Provostpflog_init()
8550816111SKristof Provost{
86ae8d5881SKristof Provost	pft_init
87ae8d5881SKristof Provost
8850816111SKristof Provost	if ! kldstat -q -m pflog; then
8950816111SKristof Provost		atf_skip "This test requires pflog"
9050816111SKristof Provost	fi
9150816111SKristof Provost}
9250816111SKristof Provost
93fb0c7468SKristof Provostpflow_init()
94fb0c7468SKristof Provost{
95fb0c7468SKristof Provost	pft_init
96fb0c7468SKristof Provost
97fb0c7468SKristof Provost	if ! kldstat -q -m pflow; then
98fb0c7468SKristof Provost		atf_skip "This test requires pflow"
99fb0c7468SKristof Provost	fi
100fb0c7468SKristof Provost}
101fb0c7468SKristof Provost
1021977d9a3SKristof Provostdummynet_init()
1031977d9a3SKristof Provost{
1041977d9a3SKristof Provost	pft_init
1051977d9a3SKristof Provost
1061977d9a3SKristof Provost	if ! kldstat -q -m dummynet; then
1071977d9a3SKristof Provost		atf_skip "This test requires dummynet"
1081977d9a3SKristof Provost	fi
1091977d9a3SKristof Provost}
1101977d9a3SKristof Provost
111ba22aeacSKristof Provostpft_set_rules()
112ba22aeacSKristof Provost{
113ba22aeacSKristof Provost	jname=$1
114ba22aeacSKristof Provost	shift
115ba22aeacSKristof Provost
116b9dee1ffSKristof Provost	if [ $jname == "noflush" ];
117b9dee1ffSKristof Provost	then
118b9dee1ffSKristof Provost		jname=$1
119b9dee1ffSKristof Provost		shift
120b9dee1ffSKristof Provost	else
121ba22aeacSKristof Provost		# Flush all states, rules, fragments, ...
122ba22aeacSKristof Provost		jexec ${jname} pfctl -F all
123b9dee1ffSKristof Provost	fi
124ba22aeacSKristof Provost
125ba22aeacSKristof Provost	while [ $# -gt 0 ]; do
126ba22aeacSKristof Provost		printf "$1\n"
127ba22aeacSKristof Provost		shift
128ba22aeacSKristof Provost	done | jexec ${jname} pfctl -f -
129b20ff7b9SKristof Provost	if [ $? -ne 0 ];
130b20ff7b9SKristof Provost	then
131b20ff7b9SKristof Provost		atf_fail "Failed to set PF rules in ${jname}"
132b20ff7b9SKristof Provost	fi
133ba22aeacSKristof Provost}
134ba22aeacSKristof Provost
1351d6f5f21SKristof Provostpft_cleanup()
1361d6f5f21SKristof Provost{
13706aac31aSKristof Provost	vnet_cleanup
1381d6f5f21SKristof Provost}
1396ab3ac5aSKristof Provost
1406ab3ac5aSKristof Provostpfsynct_cleanup()
1416ab3ac5aSKristof Provost{
1426ab3ac5aSKristof Provost	pft_cleanup
1436ab3ac5aSKristof Provost}
14416b38333SKristof Provost
14516b38333SKristof Provostis_altq_supported()
14616b38333SKristof Provost{
14716b38333SKristof Provost	sysctl -q kern.features.altq >/dev/null || \
14816b38333SKristof Provost	    atf_skip "Test requires ALTQ"
14916b38333SKristof Provost
15016b38333SKristof Provost	while [ -n "$1" ]
15116b38333SKristof Provost	do
15216b38333SKristof Provost		sysctl -q kern.features.altq.${1} >/dev/null || \
15316b38333SKristof Provost		    atf_skip "Test required ALTQ_${1}"
15416b38333SKristof Provost		shift
15516b38333SKristof Provost	done
15616b38333SKristof Provost}
15716b38333SKristof Provost
15816b38333SKristof Provostaltq_init()
15916b38333SKristof Provost{
16016b38333SKristof Provost	pft_init
16116b38333SKristof Provost	is_altq_supported
16216b38333SKristof Provost}
16316b38333SKristof Provost
16416b38333SKristof Provostaltq_cleanup()
16516b38333SKristof Provost{
16616b38333SKristof Provost	pft_cleanup
16716b38333SKristof Provost}
16838e2d5dbSKristof Provost
16938e2d5dbSKristof Provost# Create a bare router jail.
17038e2d5dbSKristof Provost# This function lacks target configuration.
17138e2d5dbSKristof Provostsetup_router_ipv4()
17238e2d5dbSKristof Provost{
17338e2d5dbSKristof Provost	pft_init
17438e2d5dbSKristof Provost
17538e2d5dbSKristof Provost	epair_tester=$(vnet_mkepair)
17638e2d5dbSKristof Provost	epair_server=$(vnet_mkepair)
17738e2d5dbSKristof Provost
17838e2d5dbSKristof Provost	net_tester=192.0.2.0/24
17938e2d5dbSKristof Provost	net_tester_mask=24
18038e2d5dbSKristof Provost	net_tester_host_router=192.0.2.1
18138e2d5dbSKristof Provost	net_tester_host_tester=192.0.2.2
18238e2d5dbSKristof Provost
18338e2d5dbSKristof Provost	net_server=198.51.100.0/24
18438e2d5dbSKristof Provost	net_server_mask=24
18538e2d5dbSKristof Provost	net_server_host_router=198.51.100.1
18638e2d5dbSKristof Provost	net_server_host_server=198.51.100.2
18738e2d5dbSKristof Provost
18838e2d5dbSKristof Provost	vnet_mkjail router ${epair_tester}b ${epair_server}a
18938e2d5dbSKristof Provost
19038e2d5dbSKristof Provost	ifconfig ${epair_tester}a ${net_tester_host_tester}/${net_tester_mask} up
19138e2d5dbSKristof Provost	route add -net ${net_server} ${net_tester_host_router}
19238e2d5dbSKristof Provost
19338e2d5dbSKristof Provost	jexec router ifconfig ${epair_tester}b ${net_tester_host_router}/${net_tester_mask} up
19438e2d5dbSKristof Provost	jexec router sysctl net.inet.ip.forwarding=1
19538e2d5dbSKristof Provost	jexec router ifconfig ${epair_server}a ${net_server_host_router}/${net_server_mask} up
19638e2d5dbSKristof Provost
19738e2d5dbSKristof Provost	jexec router pfctl -e
19838e2d5dbSKristof Provost}
19938e2d5dbSKristof Provost
20038e2d5dbSKristof Provost# Create a router jail.
20138e2d5dbSKristof Provost# The target for tests does not exist but a static ARP entry does
20238e2d5dbSKristof Provost# so packets to it can be properly routed.
20338e2d5dbSKristof Provostsetup_router_dummy_ipv4()
20438e2d5dbSKristof Provost{
20538e2d5dbSKristof Provost	setup_router_ipv4
20638e2d5dbSKristof Provost	jexec router arp -s ${net_server_host_server} 00:01:02:03:04:05
20738e2d5dbSKristof Provost	ifconfig ${epair_server}b up
20838e2d5dbSKristof Provost}
20938e2d5dbSKristof Provost
21038e2d5dbSKristof Provost# Create a router and a server jail.
21138e2d5dbSKristof Provost# The server is capable of responding to pings from the tester.
21238e2d5dbSKristof Provostsetup_router_server_ipv4()
21338e2d5dbSKristof Provost{
21438e2d5dbSKristof Provost	setup_router_ipv4
21538e2d5dbSKristof Provost	vnet_mkjail server ${epair_server}b
21638e2d5dbSKristof Provost	jexec server ifconfig ${epair_server}b ${net_server_host_server}/${net_server_mask} up
21738e2d5dbSKristof Provost	jexec server route add -net ${net_tester} ${net_server_host_router}
2186ffd4aebSKajetan Staszkiewicz	inetd_conf=$(mktemp)
2196ffd4aebSKajetan Staszkiewicz	echo "discard stream tcp nowait root internal" > $inetd_conf
220c17a0f62SKristof Provost	jexec server inetd -p ${PWD}/inetd.pid $inetd_conf
22138e2d5dbSKristof Provost}
22238e2d5dbSKristof Provost
22338e2d5dbSKristof Provost# Create a bare router jail.
22438e2d5dbSKristof Provost# This function lacks target configuration.
22538e2d5dbSKristof Provostsetup_router_ipv6()
22638e2d5dbSKristof Provost{
22738e2d5dbSKristof Provost	pft_init
22838e2d5dbSKristof Provost
22938e2d5dbSKristof Provost	epair_tester=$(vnet_mkepair)
23038e2d5dbSKristof Provost	epair_server=$(vnet_mkepair)
23138e2d5dbSKristof Provost
23238e2d5dbSKristof Provost	net_tester=2001:db8:42::/64
23338e2d5dbSKristof Provost	net_tester_mask=64
23438e2d5dbSKristof Provost	net_tester_host_router=2001:db8:42::1
23538e2d5dbSKristof Provost	net_tester_host_tester=2001:db8:42::2
23638e2d5dbSKristof Provost
23738e2d5dbSKristof Provost	net_server=2001:db8:43::/64
23838e2d5dbSKristof Provost	net_server_mask=64
23938e2d5dbSKristof Provost	net_server_host_router=2001:db8:43::1
24038e2d5dbSKristof Provost	net_server_host_server=2001:db8:43::2
24138e2d5dbSKristof Provost
24238e2d5dbSKristof Provost	vnet_mkjail router ${epair_tester}b ${epair_server}a
24338e2d5dbSKristof Provost
24438e2d5dbSKristof Provost	ifconfig ${epair_tester}a inet6 ${net_tester_host_tester}/${net_tester_mask}up no_dad
24538e2d5dbSKristof Provost	route add -6 ${net_server} ${net_tester_host_router}
24638e2d5dbSKristof Provost
24738e2d5dbSKristof Provost	jexec router ifconfig ${epair_tester}b inet6 ${net_tester_host_router}/${net_tester_mask} up no_dad
24838e2d5dbSKristof Provost	jexec router sysctl net.inet6.ip6.forwarding=1
24938e2d5dbSKristof Provost	jexec router ifconfig ${epair_server}a inet6 ${net_server_host_router}/${net_server_mask} up no_dad
25038e2d5dbSKristof Provost
25138e2d5dbSKristof Provost	jexec router pfctl -e
25238e2d5dbSKristof Provost}
25338e2d5dbSKristof Provost
25438e2d5dbSKristof Provost# Create a router jail.
25538e2d5dbSKristof Provost# The target for tests does not exist but a static NDP entry does
25638e2d5dbSKristof Provost# so packets to it can be properly routed.
25738e2d5dbSKristof Provostsetup_router_dummy_ipv6()
25838e2d5dbSKristof Provost{
25938e2d5dbSKristof Provost	setup_router_ipv6
26038e2d5dbSKristof Provost	jexec router ndp -s ${net_server_host_server} 00:01:02:03:04:05
26138e2d5dbSKristof Provost	ifconfig ${epair_server}b up
26238e2d5dbSKristof Provost}
26338e2d5dbSKristof Provost
26438e2d5dbSKristof Provost# Create a router and a server jail.
26538e2d5dbSKristof Provost# The server is capable of responding to pings from tester.
26638e2d5dbSKristof Provostsetup_router_server_ipv6()
26738e2d5dbSKristof Provost{
26838e2d5dbSKristof Provost	setup_router_ipv6
26938e2d5dbSKristof Provost	vnet_mkjail server ${epair_server}b
27038e2d5dbSKristof Provost	jexec server ifconfig ${epair_server}b inet6 ${net_server_host_server}/${net_server_mask} up no_dad
27138e2d5dbSKristof Provost	jexec server route add -6 ${net_tester} ${net_server_host_router}
2726ffd4aebSKajetan Staszkiewicz	inetd_conf=$(mktemp)
2736ffd4aebSKajetan Staszkiewicz	echo "discard stream tcp6 nowait root internal" > $inetd_conf
274c17a0f62SKristof Provost	jexec server inetd -p ${PWD}/inetd.pid $inetd_conf
27538e2d5dbSKristof Provost}
27638e2d5dbSKristof Provost
27738e2d5dbSKristof Provost# Ping the dummy static NDP target.
27838e2d5dbSKristof Provost# Check for pings being forwarded through the router towards the target.
27938e2d5dbSKristof Provostping_dummy_check_request()
28038e2d5dbSKristof Provost{
28138e2d5dbSKristof Provost	exit_condition=$1
28238e2d5dbSKristof Provost	shift
28338e2d5dbSKristof Provost	params=$@
28438e2d5dbSKristof Provost	atf_check -s ${exit_condition} ${common_dir}/pft_ping.py \
28538e2d5dbSKristof Provost	    --sendif ${epair_tester}a \
28638e2d5dbSKristof Provost	    --to ${net_server_host_server} \
28738e2d5dbSKristof Provost	    --recvif ${epair_server}b \
28838e2d5dbSKristof Provost	$params
28938e2d5dbSKristof Provost}
29038e2d5dbSKristof Provost
29138e2d5dbSKristof Provost# Ping the server jail.
29238e2d5dbSKristof Provost# Check for responses coming back throught the router back to the tester.
29338e2d5dbSKristof Provostping_server_check_reply()
29438e2d5dbSKristof Provost{
29538e2d5dbSKristof Provost	exit_condition=$1
29638e2d5dbSKristof Provost	shift
29738e2d5dbSKristof Provost	params=$@
29838e2d5dbSKristof Provost	atf_check -s ${exit_condition} ${common_dir}/pft_ping.py \
29938e2d5dbSKristof Provost	    --sendif ${epair_tester}a \
30038e2d5dbSKristof Provost	    --to ${net_server_host_server} \
30138e2d5dbSKristof Provost	    --replyif ${epair_tester}a \
30238e2d5dbSKristof Provost	$params
30338e2d5dbSKristof Provost}
304*65b20771SKajetan Staszkiewicz
305*65b20771SKajetan Staszkiewicznormalize_pfctl_s()
306*65b20771SKajetan Staszkiewicz{
307*65b20771SKajetan Staszkiewicz	# `pfctl -s[rsS]` output is divided into sections. Each rule, state or
308*65b20771SKajetan Staszkiewicz	# source node starts with the beginning of a line and next lines with leading
309*65b20771SKajetan Staszkiewicz	# spaces are various parameters of said rule, state or source node.
310*65b20771SKajetan Staszkiewicz	# Convert it into a single line per entry, and remove multiple spaces,
311*65b20771SKajetan Staszkiewicz	# so that regular expressions for matching them in tests can be simpler.
312*65b20771SKajetan Staszkiewicz	awk '{ if ($0 ~ /^[^ ]/ && NR > 1) print(""); gsub(/ +/, " ", $0); printf("%s", $0); } END {print("");}'
313*65b20771SKajetan Staszkiewicz}
314