xref: /freebsd/tests/sys/netpfil/pf/mbuf.sh (revision 7899f917b1c0ea178f1d2be0cfb452086d079d23)
1#
2# SPDX-License-Identifier: BSD-2-Clause
3#
4# Copyright (c) 2024 Igor Ostapenko <pm@igoro.pro>
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9# 1. Redistributions of source code must retain the above copyright
10#    notice, this list of conditions and the following disclaimer.
11# 2. Redistributions in binary form must reproduce the above copyright
12#    notice, this list of conditions and the following disclaimer in the
13#    documentation and/or other materials provided with the distribution.
14#
15# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25# SUCH DAMAGE.
26
27. $(atf_get_srcdir)/utils.subr
28
29dummymbuf_init()
30{
31	if ! kldstat -q -m dummymbuf; then
32		atf_skip "This test requires dummymbuf"
33	fi
34}
35
36atf_test_case "inet_in_mbuf_len" "cleanup"
37inet_in_mbuf_len_head()
38{
39	atf_set descr 'Test that pf can handle inbound with the first mbuf with m_len < sizeof(struct ip)'
40	atf_set require.user root
41}
42inet_in_mbuf_len_body()
43{
44	pft_init
45	dummymbuf_init
46
47	epair=$(vnet_mkepair)
48	ifconfig ${epair}a 192.0.2.1/24 up
49
50	# Set up a simple jail with one interface
51	vnet_mkjail alcatraz ${epair}b
52	jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up
53
54	# Sanity check
55	atf_check -s exit:0 -o ignore ping -c1 192.0.2.2
56
57	# Should be denied
58	jexec alcatraz pfctl -e
59	pft_set_rules alcatraz \
60		"block"
61	atf_check -s not-exit:0 -o ignore ping -c1 -t1 192.0.2.2
62
63	# Should be allowed by from/to addresses
64	pft_set_rules alcatraz \
65		"block" \
66		"pass in from 192.0.2.1 to 192.0.2.2"
67	atf_check -s exit:0 -o ignore ping -c1 192.0.2.2
68
69	# Should still work for m_len=0
70	jexec alcatraz pfilctl link -i dummymbuf:inet inet
71	jexec alcatraz sysctl net.dummymbuf.rules="inet in ${epair}b pull-head 0;"
72	atf_check_equal "0" "$(jexec alcatraz sysctl -n net.dummymbuf.hits)"
73	atf_check -s exit:0 -o ignore ping -c1 192.0.2.2
74	atf_check_equal "1" "$(jexec alcatraz sysctl -n net.dummymbuf.hits)"
75
76	# m_len=1
77	jexec alcatraz sysctl net.dummymbuf.rules="inet in ${epair}b pull-head 1;"
78	jexec alcatraz sysctl net.dummymbuf.hits=0
79	atf_check -s exit:0 -o ignore ping -c1 192.0.2.2
80	atf_check_equal "1" "$(jexec alcatraz sysctl -n net.dummymbuf.hits)"
81
82	# m_len=19
83	# provided IPv4 basic header is 20 bytes long, it should impact the dst addr
84	jexec alcatraz sysctl net.dummymbuf.rules="inet in ${epair}b pull-head 19;"
85	jexec alcatraz sysctl net.dummymbuf.hits=0
86	atf_check -s exit:0 -o ignore ping -c1 192.0.2.2
87	atf_check_equal "1" "$(jexec alcatraz sysctl -n net.dummymbuf.hits)"
88}
89inet_in_mbuf_len_cleanup()
90{
91	pft_cleanup
92}
93
94atf_test_case "inet6_in_mbuf_len" "cleanup"
95inet6_in_mbuf_len_head()
96{
97	atf_set descr 'Test that pf can handle inbound with the first mbuf with m_len < sizeof(struct ip6_hdr)'
98	atf_set require.user root
99}
100inet6_in_mbuf_len_body()
101{
102	pft_init
103	dummymbuf_init
104
105	epair=$(vnet_mkepair)
106	ifconfig ${epair}a inet6 2001:db8::1/64 up no_dad
107
108	# Set up a simple jail with one interface
109	vnet_mkjail alcatraz ${epair}b
110	jexec alcatraz ifconfig ${epair}b inet6 2001:db8::2/64 up no_dad
111
112	# Sanity check
113	atf_check -s exit:0 -o ignore ping -c1 2001:db8::2
114
115	# Should be denied
116	jexec alcatraz pfctl -e
117	pft_set_rules alcatraz \
118		"block" \
119		"pass quick inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv }"
120	atf_check -s not-exit:0 -o ignore ping -c1 -t1 2001:db8::2
121
122	# Should be allowed by from/to addresses
123	pft_set_rules alcatraz \
124		"block" \
125		"pass quick inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv }" \
126		"pass in inet6 from 2001:db8::1 to 2001:db8::2"
127	atf_check -s exit:0 -o ignore ping -c1 2001:db8::2
128
129	# Should still work for m_len=0
130	jexec alcatraz pfilctl link -i dummymbuf:inet6 inet6
131	jexec alcatraz sysctl net.dummymbuf.rules="inet6 in ${epair}b pull-head 0;"
132	atf_check_equal "0" "$(jexec alcatraz sysctl -n net.dummymbuf.hits)"
133	atf_check -s exit:0 -o ignore ping -c1 2001:db8::2
134	atf_check_equal "1" "$(jexec alcatraz sysctl -n net.dummymbuf.hits)"
135
136	# m_len=1
137	jexec alcatraz sysctl net.dummymbuf.rules="inet6 in ${epair}b pull-head 1;"
138	jexec alcatraz sysctl net.dummymbuf.hits=0
139	atf_check -s exit:0 -o ignore ping -c1 2001:db8::2
140	atf_check_equal "1" "$(jexec alcatraz sysctl -n net.dummymbuf.hits)"
141
142	# m_len=39
143	# provided IPv6 basic header is 40 bytes long, it should impact the dst addr
144	jexec alcatraz sysctl net.dummymbuf.rules="inet6 in ${epair}b pull-head 39;"
145	jexec alcatraz sysctl net.dummymbuf.hits=0
146	atf_check -s exit:0 -o ignore ping -c1 2001:db8::2
147	atf_check_equal "1" "$(jexec alcatraz sysctl -n net.dummymbuf.hits)"
148}
149inet6_in_mbuf_len_cleanup()
150{
151	pft_cleanup
152}
153
154atf_test_case "ethernet_in_mbuf_len" "cleanup"
155ethernet_in_mbuf_len_head()
156{
157	atf_set descr 'Test that pf can handle inbound with the first mbuf with m_len < sizeof(struct ether_header)'
158	atf_set require.user root
159}
160ethernet_in_mbuf_len_body()
161{
162	pft_init
163	dummymbuf_init
164
165	epair=$(vnet_mkepair)
166	epair_a_mac=$(ifconfig ${epair}a ether | awk '/ether/ { print $2; }')
167	ifconfig ${epair}a 192.0.2.1/24 up
168
169	# Set up a simple jail with one interface
170	vnet_mkjail alcatraz ${epair}b
171	jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up
172	epair_b_mac=$(jexec alcatraz ifconfig ${epair}b ether | awk '/ether/ { print $2; }')
173
174	# Sanity check
175	atf_check -s exit:0 -o ignore ping -c1 192.0.2.2
176
177	# Should be denied
178	jexec alcatraz pfctl -e
179	pft_set_rules alcatraz \
180		"ether block" \
181		"pass"
182	atf_check -s not-exit:0 -o ignore ping -c1 -t1 192.0.2.2
183
184	# Should be allowed by from/to addresses
185	echo $epair_a_mac
186	echo $epair_b_mac
187	pft_set_rules alcatraz \
188		"ether block" \
189		"ether pass in  from ${epair_a_mac} to ${epair_b_mac}" \
190		"ether pass out from ${epair_b_mac} to ${epair_a_mac}" \
191		"pass"
192	atf_check -s exit:0 -o ignore ping -c1 192.0.2.2
193
194	# Should still work for m_len=0
195	jexec alcatraz pfilctl link -i dummymbuf:ethernet ethernet
196	jexec alcatraz sysctl net.dummymbuf.rules="ethernet in ${epair}b pull-head 0;"
197	atf_check_equal "0" "$(jexec alcatraz sysctl -n net.dummymbuf.hits)"
198	atf_check -s exit:0 -o ignore ping -c1 192.0.2.2
199	atf_check_equal "1" "$(jexec alcatraz sysctl -n net.dummymbuf.hits)"
200
201	# m_len=1
202	jexec alcatraz sysctl net.dummymbuf.rules="ethernet in ${epair}b pull-head 1;"
203	jexec alcatraz sysctl net.dummymbuf.hits=0
204	atf_check -s exit:0 -o ignore ping -c1 192.0.2.2
205	atf_check_equal "1" "$(jexec alcatraz sysctl -n net.dummymbuf.hits)"
206
207	# m_len=11
208	# for the simplest L2 Ethernet frame it should impact src field
209	jexec alcatraz sysctl net.dummymbuf.rules="ethernet in ${epair}b pull-head 11;"
210	jexec alcatraz sysctl net.dummymbuf.hits=0
211	atf_check -s exit:0 -o ignore ping -c1 192.0.2.2
212	atf_check_equal "1" "$(jexec alcatraz sysctl -n net.dummymbuf.hits)"
213
214	# m_len=13
215	# provided L2 Ethernet simplest header is 14 bytes long, it should impact ethertype field
216	jexec alcatraz sysctl net.dummymbuf.rules="ethernet in ${epair}b pull-head 13;"
217	jexec alcatraz sysctl net.dummymbuf.hits=0
218	atf_check -s exit:0 -o ignore ping -c1 192.0.2.2
219	atf_check_equal "1" "$(jexec alcatraz sysctl -n net.dummymbuf.hits)"
220}
221ethernet_in_mbuf_len_cleanup()
222{
223	pft_cleanup
224}
225
226atf_init_test_cases()
227{
228	atf_add_test_case "inet_in_mbuf_len"
229	atf_add_test_case "inet6_in_mbuf_len"
230	atf_add_test_case "ethernet_in_mbuf_len"
231}
232