2 # SPDX-License-Identifier: BSD-2-Clause
4 # Copyright (c) 2017 Kristof Provost <kp@FreeBSD.org>
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
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.
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
27 . $(atf_get_srcdir)/utils.subr
29 common_dir=$(atf_get_srcdir)/../common
31 atf_test_case "too_many_fragments" "cleanup"
33 too_many_fragments_head()
35 atf_set descr 'IPv4 fragment limitation test'
36 atf_set require.user root
39 too_many_fragments_body()
44 vnet_mkjail alcatraz ${epair}a
46 ifconfig ${epair}b inet 192.0.2.1/24 up
47 jexec alcatraz ifconfig ${epair}a 192.0.2.2/24 up
49 ifconfig ${epair}b mtu 200
50 jexec alcatraz ifconfig ${epair}a mtu 200
52 jexec alcatraz pfctl -e
53 pft_set_rules alcatraz \
54 "set reassemble yes" \
57 # So we know pf is limiting things
58 jexec alcatraz sysctl net.inet.ip.maxfragsperpacket=1024
61 atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2
63 # We can ping with < 64 fragments
64 atf_check -s exit:0 -o ignore ping -c 1 -s 800 192.0.2.2
66 # Too many fragments should fail
67 atf_check -s exit:2 -o ignore ping -c 1 -s 20000 192.0.2.2
70 too_many_fragments_cleanup()
75 atf_test_case "v6" "cleanup"
78 atf_set descr 'IPv6 fragmentation test'
79 atf_set require.user root
80 atf_set require.progs scapy
87 epair_send=$(vnet_mkepair)
88 epair_link=$(vnet_mkepair)
90 vnet_mkjail alcatraz ${epair_send}b ${epair_link}a
91 vnet_mkjail singsing ${epair_link}b
93 ifconfig ${epair_send}a inet6 2001:db8:42::1/64 no_dad up
95 jexec alcatraz ifconfig ${epair_send}b inet6 2001:db8:42::2/64 no_dad up
96 jexec alcatraz ifconfig ${epair_link}a inet6 2001:db8:43::2/64 no_dad up
97 jexec alcatraz sysctl net.inet6.ip6.forwarding=1
99 jexec singsing ifconfig ${epair_link}b inet6 2001:db8:43::3/64 no_dad up
100 jexec singsing route add -6 2001:db8:42::/64 2001:db8:43::2
101 route add -6 2001:db8:43::/64 2001:db8:42::2
103 jexec alcatraz ifconfig ${epair_send}b inet6 -ifdisabled
104 jexec alcatraz ifconfig ${epair_link}a inet6 -ifdisabled
105 jexec singsing ifconfig ${epair_link}b inet6 -ifdisabled
106 ifconfig ${epair_send}a inet6 -ifdisabled
108 ifconfig ${epair_send}a
109 jexec alcatraz ifconfig ${epair_send}b
110 lladdr=$(jexec alcatraz ifconfig ${epair_send}b | awk '/ scopeid / { print($2); }' | cut -f 1 -d %)
112 jexec alcatraz pfctl -e
113 pft_set_rules alcatraz \
114 "set reassemble yes" \
117 "pass in inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv }" \
118 "pass in inet6 proto icmp6 icmp6-type { echoreq, echorep }" \
122 atf_check -s exit:0 -o ignore \
123 ping -6 -c 1 2001:db8:42::2
125 atf_check -s exit:0 -o ignore \
126 ping -6 -c 1 -s 4500 2001:db8:42::2
128 atf_check -s exit:0 -o ignore\
129 ping -6 -c 1 -b 70000 -s 65000 2001:db8:42::2
131 # Force an NDP lookup
132 ping -6 -c 1 ${lladdr}%${epair_send}a
134 atf_check -s exit:0 -o ignore\
135 ping -6 -c 1 -b 70000 -s 65000 ${lladdr}%${epair_send}a
138 atf_check -s exit:0 -o ignore \
139 ping -6 -c 1 2001:db8:43::3
141 atf_check -s exit:0 -o ignore \
142 ping -6 -c 1 -s 4500 2001:db8:43::3
144 atf_check -s exit:0 -o ignore\
145 ping -6 -c 1 -b 70000 -s 65000 2001:db8:43::3
147 $(atf_get_srcdir)/CVE-2019-5597.py \
158 atf_test_case "mtu_diff" "cleanup"
161 atf_set descr 'Test reassembly across different MTUs, PR #255432'
162 atf_set require.user root
169 epair_small=$(vnet_mkepair)
170 epair_large=$(vnet_mkepair)
172 vnet_mkjail first ${epair_small}b ${epair_large}a
173 vnet_mkjail second ${epair_large}b
175 ifconfig ${epair_small}a 192.0.2.1/25 up
176 jexec first ifconfig ${epair_small}b 192.0.2.2/25 up
178 jexec first sysctl net.inet.ip.forwarding=1
179 jexec first ifconfig ${epair_large}a 192.0.2.130/25 up
180 jexec first ifconfig ${epair_large}a mtu 9000
181 jexec second ifconfig ${epair_large}b 192.0.2.131/25 up
182 jexec second ifconfig ${epair_large}b mtu 9000
183 jexec second route add default 192.0.2.130
185 route add 192.0.2.128/25 192.0.2.2
188 pft_set_rules first \
189 "set reassemble yes" \
193 atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2
194 atf_check -s exit:0 -o ignore ping -c 1 192.0.2.130
195 atf_check -s exit:0 -o ignore ping -c 1 192.0.2.131
197 # Large packet that'll get reassembled and sent out in one on the large
199 atf_check -s exit:0 -o ignore ping -c 1 -s 8000 192.0.2.131
213 epair=$(vnet_mkepair)
214 vnet_mkjail alcatraz ${epair}a
216 ifconfig ${epair}b inet 192.0.2.1/24 up
217 jexec alcatraz ifconfig ${epair}a 192.0.2.2/24 up
219 jexec alcatraz pfctl -e
220 pft_set_rules alcatraz \
221 "set reassemble yes" \
225 atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2
227 atf_check -s exit:0 -o ignore $(atf_get_srcdir)/frag-${1}.py \
229 --fromaddr 192.0.2.1 \
234 atf_test_case "overreplace" "cleanup"
237 atf_set descr 'ping fragment that overlaps fragment at index boundary and replace it'
238 atf_set require.user root
239 atf_set require.progs scapy
244 frag_common overreplace
247 overreplace_cleanup()
252 atf_test_case "overindex" "cleanup"
255 atf_set descr 'ping fragment that overlaps the first fragment at index boundary'
256 atf_set require.user root
257 atf_set require.progs scapy
262 frag_common overindex
270 atf_test_case "overlimit" "cleanup"
273 atf_set descr 'ping fragment at index boundary that cannot be requeued'
274 atf_set require.user root
275 atf_set require.progs scapy
280 frag_common overlimit
288 atf_test_case "reassemble" "cleanup"
291 atf_set descr 'Test reassembly'
292 atf_set require.user root
299 epair=$(vnet_mkepair)
300 vnet_mkjail alcatraz ${epair}a
302 ifconfig ${epair}b inet 192.0.2.1/24 up
303 jexec alcatraz ifconfig ${epair}a 192.0.2.2/24 up
306 atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2
308 jexec alcatraz pfctl -e
309 pft_set_rules alcatraz \
312 "pass in inet proto icmp all icmp-type echoreq"
314 # Single fragment passes
315 atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2
317 # But a fragmented ping does not
318 atf_check -s exit:2 -o ignore ping -c 1 -s 2000 192.0.2.2
320 pft_set_rules alcatraz \
321 "set reassemble yes" \
324 "pass in inet proto icmp all icmp-type echoreq"
326 # Both single packet & fragmented pass when we scrub
327 atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2
328 atf_check -s exit:0 -o ignore ping -c 1 -s 2000 192.0.2.2
336 atf_test_case "no_df" "cleanup"
339 atf_set descr 'Test removing of DF flag'
340 atf_set require.user root
345 setup_router_server_ipv4
347 ifconfig ${epair_tester}a mtu 9000
348 jexec router ifconfig ${epair_tester}b mtu 9000
349 jexec router ifconfig ${epair_server}a mtu 1500
350 jexec server ifconfig ${epair_server}b mtu 1500
353 ping_server_check_reply exit:0 --ping-type=icmp
355 pft_set_rules router \
356 "set reassemble no" \
359 "pass in inet proto icmp all icmp-type echoreq"
361 # Ping with normal, fragmentable packets.
362 ping_server_check_reply exit:1 --ping-type=icmp --send-length=2000
364 pft_set_rules router \
365 "set reassemble yes" \
368 "pass in inet proto icmp all icmp-type echoreq"
370 # Ping with normal, fragmentable packets.
371 ping_server_check_reply exit:0 --ping-type=icmp --send-length=2000
373 # Ping with non-fragmentable packets.
374 ping_server_check_reply exit:1 --ping-type=icmp --send-length=2000 --send-flags DF
376 pft_set_rules router \
377 "set reassemble yes no-df" \
380 "pass in inet proto icmp all icmp-type echoreq"
382 # Ping with non-fragmentable packets again.
383 # This time pf will strip the DF flag.
384 ping_server_check_reply exit:0 --ping-type=icmp --send-length=2000 --send-flags DF
391 atf_test_case "no_df" "cleanup"
394 atf_set descr 'Test removing of DF flag'
395 atf_set require.user root
400 setup_router_server_ipv4
402 # Tester can send long packets which will get fragmented by the router.
403 # Replies from server will come in fragments which might get
404 # reassembled resulting in a long reply packet sent back to tester.
405 ifconfig ${epair_tester}a mtu 9000
406 jexec router ifconfig ${epair_tester}b mtu 9000
407 jexec router ifconfig ${epair_server}a mtu 1500
408 jexec server ifconfig ${epair_server}b mtu 1500
411 ping_server_check_reply exit:0 --ping-type=icmp
413 # Enable packet reassembly with clearing of the no-df flag.
414 pft_set_rules router \
415 "scrub all fragment reassemble no-df" \
417 "pass inet proto icmp all icmp-type echoreq"
418 # Ping with non-fragmentable packets.
419 # pf will strip the DF flag resulting in fragmentation and packets
420 # getting properly forwarded.
421 ping_server_check_reply exit:0 --ping-type=icmp --send-length=2000 --send-flags DF
428 atf_test_case "reassemble_slowpath" "cleanup"
429 reassemble_slowpath_head()
431 atf_set descr 'Test reassembly on the slow path'
432 atf_set require.user root
435 reassemble_slowpath_body()
437 if ! sysctl -q kern.features.ipsec >/dev/null ; then
438 atf_skip "This test requires ipsec"
441 setup_router_server_ipv4
443 # Now define an ipsec policy so we end up taking the slow path.
444 # We don't actually need the traffic to go through ipsec, we just don't
445 # want to go through ip_tryforward().
448 spdadd 203.0.113.1/32 203.0.113.2/32 any -P out ipsec esp/transport//require;
449 add 203.0.113.1 203.0.113.2 esp 0x1001 -E aes-gcm-16 \"12345678901234567890\";" \
450 | jexec router setkey -c
453 ping_server_check_reply exit:0 --ping-type=icmp
455 # Enable packet reassembly with clearing of the no-df flag.
456 pft_set_rules router \
457 "scrub in on ${epair_tester}b fragment no reassemble" \
458 "scrub on ${epair_server}a fragment reassemble" \
461 # Ensure that the packet makes it through the slow path
462 atf_check -s exit:0 -o ignore \
463 ping -c 1 -s 2000 198.51.100.2
466 reassemble_slowpath_cleanup()
471 atf_init_test_cases()
473 atf_add_test_case "too_many_fragments"
474 atf_add_test_case "v6"
475 atf_add_test_case "mtu_diff"
476 atf_add_test_case "overreplace"
477 atf_add_test_case "overindex"
478 atf_add_test_case "overlimit"
479 atf_add_test_case "reassemble"
480 atf_add_test_case "no_df"
481 atf_add_test_case "reassemble_slowpath"