xref: /freebsd/tests/sys/netpfil/pf/sctp.sh (revision 2d42aa9d7ba64fe7166f76234a595637f0c212cf)
1# $FreeBSD$
2#
3# SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4#
5# Copyright © 2023 Orange Business Services
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions
9# are met:
10# 1. Redistributions of source code must retain the above copyright
11#    notice, this list of conditions and the following disclaimer.
12# 2. Redistributions in binary form must reproduce the above copyright
13#    notice, this list of conditions and the following disclaimer in the
14#    documentation and/or other materials provided with the distribution.
15#
16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26# SUCH DAMAGE.
27
28. $(atf_get_srcdir)/utils.subr
29
30sctp_init()
31{
32	pft_init
33	if ! kldstat -q -m sctp; then
34		atf_skip "This test requires SCTP"
35	fi
36}
37
38atf_test_case "basic_v4" "cleanup"
39basic_v4_head()
40{
41	atf_set descr 'Basic SCTP connection over IPv4 passthrough'
42	atf_set require.user root
43}
44
45basic_v4_body()
46{
47	sctp_init
48
49	j="sctp:basic_v4"
50	epair=$(vnet_mkepair)
51
52	vnet_mkjail ${j}a ${epair}a
53	vnet_mkjail ${j}b ${epair}b
54
55	jexec ${j}a ifconfig ${epair}a 192.0.2.1/24 up
56	jexec ${j}b ifconfig ${epair}b 192.0.2.2/24 up
57	# Sanity check
58	atf_check -s exit:0 -o ignore \
59	    jexec ${j}a ping -c 1 192.0.2.2
60
61	jexec ${j}a pfctl -e
62	pft_set_rules ${j}a \
63		"block" \
64		"pass in proto sctp to port 1234"
65
66	echo "foo" | jexec ${j}a nc --sctp -N -l 1234 &
67
68	# Wait for the server to start
69	sleep 1
70
71	out=$(jexec ${j}b nc --sctp -N -w 3 192.0.2.1 1234)
72	if [ "$out" != "foo" ]; then
73		atf_fail "SCTP connection failed"
74	fi
75
76	# Now with scrub rules present, so normalization is done
77	pft_set_rules ${j}a \
78		"scrub on ${j}a" \
79		"block" \
80		"pass in proto sctp to port 1234"
81
82	echo "foo" | jexec ${j}a nc --sctp -N -l 1234 &
83	sleep 1
84
85	out=$(jexec ${j}b nc --sctp -N -w 3 192.0.2.1 1234)
86	if [ "$out" != "foo" ]; then
87		atf_fail "SCTP connection failed"
88	fi
89
90	# Now fail with a blocked port
91	echo "foo" | jexec ${j}a nc --sctp -N -l 1235 &
92	sleep 1
93
94	out=$(jexec ${j}b nc --sctp -N -w 3 192.0.2.1 1235)
95	if [ "$out" == "foo" ]; then
96		atf_fail "SCTP port block failed"
97	fi
98
99	# Now fail with a blocked port but passing source port
100	out=$(jexec ${j}b nc --sctp -N -w 3 -p 1234 192.0.2.1 1235)
101	if [ "$out" == "foo" ]; then
102		atf_fail "SCTP port block failed"
103	fi
104}
105
106basic_v4_cleanup()
107{
108	pft_cleanup
109}
110
111atf_test_case "basic_v6" "cleanup"
112basic_v6_head()
113{
114	atf_set descr 'Basic SCTP connection over IPv6'
115	atf_set require.user root
116}
117
118basic_v6_body()
119{
120	sctp_init
121
122	j="sctp:basic_v6"
123	epair=$(vnet_mkepair)
124
125	vnet_mkjail ${j}a ${epair}a
126	vnet_mkjail ${j}b ${epair}b
127
128	jexec ${j}a ifconfig ${epair}a inet6 2001:db8::a/64 up no_dad
129	jexec ${j}b ifconfig ${epair}b inet6 2001:db8::b/64 up no_dad
130
131	# Sanity check
132	atf_check -s exit:0 -o ignore \
133	    jexec ${j}a ping -6 -c 1 2001:db8::b
134
135	jexec ${j}a pfctl -e
136	pft_set_rules ${j}a \
137		"block proto sctp" \
138		"pass in proto sctp to port 1234"
139
140	echo "foo" | jexec ${j}a nc -6 --sctp -N -l 1234 &
141
142	# Wait for the server to start
143	sleep 1
144
145	out=$(jexec ${j}b nc --sctp -N -w 3 2001:db8::a 1234)
146	if [ "$out" != "foo" ]; then
147		atf_fail "SCTP connection failed"
148	fi
149
150	# Now with scrub rules present, so normalization is done
151	pft_set_rules ${j}a \
152		"scrub on ${j}a" \
153		"block proto sctp" \
154		"pass in proto sctp to port 1234"
155
156	echo "foo" | jexec ${j}a nc -6 --sctp -N -l 1234 &
157	sleep 1
158
159	out=$(jexec ${j}b nc --sctp -N -w 3 2001:db8::a 1234)
160	if [ "$out" != "foo" ]; then
161		atf_fail "SCTP connection failed"
162	fi
163
164	# Now fail with a blocked port
165	echo "foo" | jexec ${j}a nc -6 --sctp -N -l 1235 &
166	sleep 1
167
168	out=$(jexec ${j}b nc --sctp -N -w 3 2001:db8::a 1235)
169	if [ "$out" == "foo" ]; then
170		atf_fail "SCTP port block failed"
171	fi
172
173	# Now fail with a blocked port but passing source port
174	out=$(jexec ${j}b nc --sctp -N -w 3 -p 1234 2001:db8::a 1235)
175	if [ "$out" == "foo" ]; then
176		atf_fail "SCTP port block failed"
177	fi
178}
179
180basic_v6_cleanup()
181{
182	pft_cleanup
183}
184
185atf_test_case "abort_v4" "cleanup"
186abort_v4_head()
187{
188	atf_set descr 'Test sending ABORT messages'
189	atf_set require.user root
190}
191
192abort_v4_body()
193{
194	sctp_init
195
196	j="sctp:abort_v4"
197	epair=$(vnet_mkepair)
198
199	vnet_mkjail ${j}a ${epair}a
200	vnet_mkjail ${j}b ${epair}b
201
202	jexec ${j}a ifconfig ${epair}a 192.0.2.1/24 up
203	jexec ${j}b ifconfig ${epair}b 192.0.2.2/24 up
204
205	# Sanity check
206	atf_check -s exit:0 -o ignore \
207	    jexec ${j}a ping -c 1 192.0.2.2
208
209	jexec ${j}a pfctl -e
210	pft_set_rules ${j}a \
211		"block return in proto sctp to port 1234"
212
213	echo "foo" | jexec ${j}a nc --sctp -N -l 1234 &
214
215	# Wait for the server to start
216	sleep 1
217
218	# If we get the abort we'll exit immediately, if we don't timeout will
219	# stop nc.
220	out=$(jexec ${j}b timeout 3 nc --sctp -N 192.0.2.1 1234)
221	if [ $? -eq 124 ]; then
222		atf_fail 'Abort not received'
223	fi
224	if [ "$out" == "foo" ]; then
225		atf_fail "block failed entirely"
226	fi
227
228	# Without 'return' we will time out.
229	pft_set_rules ${j}a \
230		"block in proto sctp to port 1234"
231
232	out=$(jexec ${j}b timeout 3 nc --sctp -N 192.0.2.1 1234)
233	if [ $? -ne 124 ]; then
234		atf_fail 'Abort sent anyway?'
235	fi
236}
237
238abort_v4_cleanup()
239{
240	pft_cleanup
241}
242
243atf_test_case "abort_v6" "cleanup"
244abort_v4_head()
245{
246	atf_set descr 'Test sending ABORT messages over IPv6'
247	atf_set require.user root
248}
249
250abort_v6_body()
251{
252	sctp_init
253
254	j="sctp:abort_v6"
255	epair=$(vnet_mkepair)
256
257	vnet_mkjail ${j}a ${epair}a
258	vnet_mkjail ${j}b ${epair}b
259
260	jexec ${j}a ifconfig ${epair}a inet6 2001:db8::a/64 no_dad
261	jexec ${j}b ifconfig ${epair}b inet6 2001:db8::b/64 no_dad
262
263	# Sanity check
264	atf_check -s exit:0 -o ignore \
265	    jexec ${j}a ping -6 -c 1 2001:db8::b
266
267	jexec ${j}a pfctl -e
268	pft_set_rules ${j}a \
269		"block return in proto sctp to port 1234"
270
271	echo "foo" | jexec ${j}a nc -6 --sctp -N -l 1234 &
272
273	# Wait for the server to start
274	sleep 1
275
276	# If we get the abort we'll exit immediately, if we don't timeout will
277	# stop nc.
278	out=$(jexec ${j}b timeout 3 nc --sctp -N 2001:db8::a 1234)
279	if [ $? -eq 124 ]; then
280		atf_fail 'Abort not received'
281	fi
282	if [ "$out" == "foo" ]; then
283		atf_fail "block failed entirely"
284	fi
285
286	# Without 'return' we will time out.
287	pft_set_rules ${j}a \
288		"block in proto sctp to port 1234"
289
290	out=$(jexec ${j}b timeout 3 nc --sctp -N 2001:db8::a 1234)
291	if [ $? -ne 124 ]; then
292		atf_fail 'Abort sent anyway?'
293	fi
294}
295
296abort_v4_cleanup()
297{
298	pft_cleanup
299}
300
301atf_init_test_cases()
302{
303	atf_add_test_case "basic_v4"
304	atf_add_test_case "basic_v6"
305	atf_add_test_case "abort_v4"
306	atf_add_test_case "abort_v6"
307}
308