1# $FreeBSD$ 2# 3# SPDX-License-Identifier: BSD-2-Clause-FreeBSD 4# 5# Copyright (c) 2021 Rubicon Communications, LLC (Netgate) 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. $(atf_get_srcdir)/runner.subr 30 31interface_removal_head() 32{ 33 atf_set descr 'Test removing interfaces with dummynet delayed traffic' 34 atf_set require.user root 35} 36 37interface_removal_body() 38{ 39 fw=$1 40 firewall_init $fw 41 dummynet_init $fw 42 43 epair=$(vnet_mkepair) 44 vnet_mkjail alcatraz ${epair}b 45 46 ifconfig ${epair}a 192.0.2.1/24 up 47 jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up 48 49 # Sanity check 50 atf_check -s exit:0 -o ignore ping -i .1 -c 3 -s 1200 192.0.2.2 51 52 jexec alcatraz dnctl pipe 1 config delay 1500 53 54 firewall_config alcatraz ${fw} \ 55 "ipfw" \ 56 "ipfw add 1000 pipe 1 ip from any to any" \ 57 "pf" \ 58 "pass dnpipe 1" 59 60 # single ping succeeds just fine 61 atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2 62 63 # Send traffic that'll still be pending when we remove the interface 64 ping -c 5 -s 1200 192.0.2.2 & 65 sleep 1 # Give ping the chance to start. 66 67 # Remove the interface, but keep the jail around for a bit 68 ifconfig ${epair}a destroy 69 70 sleep 3 71} 72 73interface_removal_cleanup() 74{ 75 firewall_cleanup $1 76} 77 78pipe_head() 79{ 80 atf_set descr 'Basic pipe test' 81 atf_set require.user root 82} 83 84pipe_body() 85{ 86 fw=$1 87 firewall_init $fw 88 dummynet_init $fw 89 90 epair=$(vnet_mkepair) 91 vnet_mkjail alcatraz ${epair}b 92 93 ifconfig ${epair}a 192.0.2.1/24 up 94 jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up 95 96 # Sanity check 97 atf_check -s exit:0 -o ignore ping -i .1 -c 3 -s 1200 192.0.2.2 98 99 jexec alcatraz dnctl pipe 1 config bw 30Byte/s 100 101 firewall_config alcatraz ${fw} \ 102 "ipfw" \ 103 "ipfw add 1000 pipe 1 ip from any to any" \ 104 "pf" \ 105 "pass dnpipe 1" 106 107 # single ping succeeds just fine 108 atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2 109 110 # Saturate the link 111 ping -i .1 -c 5 -s 1200 192.0.2.2 112 113 # We should now be hitting the limits and get this packet dropped. 114 atf_check -s exit:2 -o ignore ping -c 1 -s 1200 192.0.2.2 115} 116 117pipe_cleanup() 118{ 119 firewall_cleanup $1 120} 121 122pipe_v6_head() 123{ 124 atf_set descr 'Basic IPv6 pipe test' 125 atf_set require.user root 126} 127 128pipe_v6_body() 129{ 130 fw=$1 131 firewall_init $fw 132 dummynet_init $fw 133 134 epair=$(vnet_mkepair) 135 vnet_mkjail alcatraz ${epair}b 136 137 ifconfig ${epair}a inet6 2001:db8:42::1/64 up no_dad 138 jexec alcatraz ifconfig ${epair}b inet6 2001:db8:42::2/64 up no_dad 139 140 # Sanity check 141 atf_check -s exit:0 -o ignore ping6 -i .1 -c 3 -s 1200 2001:db8:42::2 142 143 jexec alcatraz dnctl pipe 1 config bw 100Byte/s 144 145 firewall_config alcatraz ${fw} \ 146 "ipfw" \ 147 "ipfw add 1000 pipe 1 ip6 from any to any" \ 148 "pf" \ 149 "pass dnpipe 1" 150 151 # Single ping succeeds 152 atf_check -s exit:0 -o ignore ping6 -c 1 2001:db8:42::2 153 154 # Saturate the link 155 ping6 -i .1 -c 5 -s 1200 2001:db8:42::2 156 157 # We should now be hitting the limit and get this packet dropped. 158 atf_check -s exit:2 -o ignore ping6 -c 1 -s 1200 2001:db8:42::2 159} 160 161pipe_v6_cleanup() 162{ 163 firewall_cleanup $1 164} 165 166queue_head() 167{ 168 atf_set descr 'Basic queue test' 169 atf_set require.user root 170} 171 172queue_body() 173{ 174 fw=$1 175 176 if [ $fw = "ipfw" ] && [ "$(atf_config_get ci false)" = "true" ]; then 177 atf_skip "https://bugs.freebsd.org/264805" 178 fi 179 180 firewall_init $fw 181 dummynet_init $fw 182 183 epair=$(vnet_mkepair) 184 vnet_mkjail alcatraz ${epair}b 185 186 ifconfig ${epair}a 192.0.2.1/24 up 187 jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up 188 jexec alcatraz /usr/sbin/inetd -p inetd-alcatraz.pid \ 189 $(atf_get_srcdir)/../pf/echo_inetd.conf 190 191 # Sanity check 192 atf_check -s exit:0 -o ignore ping -i .1 -c 3 -s 1200 192.0.2.2 193 reply=$(echo "foo" | nc -N 192.0.2.2 7) 194 if [ "$reply" != "foo" ]; 195 then 196 atf_fail "Echo sanity check failed" 197 fi 198 199 jexec alcatraz dnctl pipe 1 config bw 1MByte/s 200 jexec alcatraz dnctl sched 1 config pipe 1 type wf2q+ 201 jexec alcatraz dnctl queue 100 config sched 1 weight 99 mask all 202 jexec alcatraz dnctl queue 200 config sched 1 weight 1 mask all 203 204 firewall_config alcatraz ${fw} \ 205 "ipfw" \ 206 "ipfw add 1000 queue 100 tcp from 192.0.2.2 to any out" \ 207 "ipfw add 1001 queue 200 icmp from 192.0.2.2 to any out" \ 208 "ipfw add 1002 allow ip from any to any" \ 209 "pf" \ 210 "pass in proto tcp dnqueue (0, 100)" \ 211 "pass in proto icmp dnqueue (0, 200)" 212 213 # Single ping succeeds 214 atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2 215 216 # Unsaturated TCP succeeds 217 reply=$(echo "foo" | nc -w 5 -N 192.0.2.2 7) 218 if [ "$reply" != "foo" ]; 219 then 220 atf_fail "Unsaturated echo failed" 221 fi 222 223 # Saturate the link 224 ping -f -s 1300 192.0.2.2 & 225 226 # Allow this to fill the queue 227 sleep 1 228 229 # TCP should still just pass 230 fails=0 231 for i in `seq 1 3` 232 do 233 result=$(dd if=/dev/zero bs=1024 count=2000 | timeout 3 nc -w 5 -N 192.0.2.2 7 | wc -c) 234 if [ $result -ne 2048000 ]; 235 then 236 echo "Failed to prioritise TCP traffic. Got only $result bytes" 237 fails=$(( ${fails} + 1 )) 238 fi 239 done 240 if [ ${fails} -gt 0 ]; 241 then 242 atf_fail "We failed prioritisation ${fails} times" 243 fi 244 245 # This will fail if we reverse the pola^W priority 246 firewall_config alcatraz ${fw} \ 247 "ipfw" \ 248 "ipfw add 1000 queue 200 tcp from 192.0.2.2 to any out" \ 249 "ipfw add 1001 queue 100 icmp from 192.0.2.2 to any out" \ 250 "ipfw add 1002 allow ip from any to any" \ 251 "pf" \ 252 "pass in proto tcp dnqueue (0, 200)" \ 253 "pass in proto icmp dnqueue (0, 100)" 254 255 jexec alcatraz ping -f -s 1300 192.0.2.1 & 256 sleep 1 257 258 fails=0 259 for i in `seq 1 3` 260 do 261 result=$(dd if=/dev/zero bs=1024 count=2000 | timeout 3 nc -w 5 -N 192.0.2.2 7 | wc -c) 262 if [ $result -ne 2048000 ]; 263 then 264 echo "Failed to prioritise TCP traffic. Got only $result bytes" 265 fails=$(( ${fails} + 1 )) 266 fi 267 done 268 if [ ${fails} -lt 3 ]; 269 then 270 atf_fail "We failed reversed prioritisation only ${fails} times." 271 fi 272} 273 274queue_cleanup() 275{ 276 firewall_cleanup $1 277} 278 279queue_v6_head() 280{ 281 atf_set descr 'Basic queue test' 282 atf_set require.user root 283} 284 285queue_v6_body() 286{ 287 fw=$1 288 firewall_init $fw 289 dummynet_init $fw 290 291 epair=$(vnet_mkepair) 292 vnet_mkjail alcatraz ${epair}b 293 294 ifconfig ${epair}a inet6 2001:db8:42::1/64 no_dad up 295 jexec alcatraz ifconfig ${epair}b inet6 2001:db8:42::2 no_dad up 296 jexec alcatraz /usr/sbin/inetd -p inetd-alcatraz.pid \ 297 $(atf_get_srcdir)/../pf/echo_inetd.conf 298 299 # Sanity check 300 atf_check -s exit:0 -o ignore ping6 -i .1 -c 3 -s 1200 2001:db8:42::2 301 reply=$(echo "foo" | nc -N 2001:db8:42::2 7) 302 if [ "$reply" != "foo" ]; 303 then 304 atf_fail "Echo sanity check failed" 305 fi 306 307 jexec alcatraz dnctl pipe 1 config bw 1MByte/s 308 jexec alcatraz dnctl sched 1 config pipe 1 type wf2q+ 309 jexec alcatraz dnctl queue 100 config sched 1 weight 99 mask all 310 jexec alcatraz dnctl queue 200 config sched 1 weight 1 mask all 311 312 firewall_config alcatraz ${fw} \ 313 "ipfw" \ 314 "ipfw add 1001 queue 100 tcp from 2001:db8:42::2 to any out" \ 315 "ipfw add 1000 queue 200 ipv6-icmp from 2001:db8:42::2 to any out" \ 316 "ipfw add 1002 allow ip6 from any to any" \ 317 "pf" \ 318 "pass in proto tcp dnqueue (0, 100)" \ 319 "pass in proto icmp6 dnqueue (0, 200)" 320 321 # Single ping succeeds 322 atf_check -s exit:0 -o ignore ping6 -c 1 2001:db8:42::2 323 324 # Unsaturated TCP succeeds 325 reply=$(echo "foo" | nc -w 5 -N 2001:db8:42::2 7) 326 if [ "$reply" != "foo" ]; 327 then 328 atf_fail "Unsaturated echo failed" 329 fi 330 331 # Saturate the link 332 ping6 -f -s 1200 2001:db8:42::2 & 333 334 # Allow this to fill the queue 335 sleep 1 336 337 # TCP should still just pass 338 fails=0 339 for i in `seq 1 3` 340 do 341 result=$(dd if=/dev/zero bs=1024 count=1000 | timeout 3 nc -w 5 -N 2001:db8:42::2 7 | wc -c) 342 if [ $result -ne 1024000 ]; 343 then 344 echo "Failed to prioritise TCP traffic. Got only $result bytes" 345 fails=$(( ${fails} + 1 )) 346 fi 347 done 348 if [ ${fails} -gt 0 ]; 349 then 350 atf_fail "We failed prioritisation ${fails} times" 351 fi 352 353 # What happens if we prioritise ICMP over TCP? 354 firewall_config alcatraz ${fw} \ 355 "ipfw" \ 356 "ipfw add 1001 queue 200 tcp from 2001:db8:42::2 to any out" \ 357 "ipfw add 1000 queue 100 ipv6-icmp from 2001:db8:42::2 to any out" \ 358 "ipfw add 1002 allow ip6 from any to any" \ 359 "pf" \ 360 "pass in proto tcp dnqueue (0, 200)" \ 361 "pass in proto icmp6 dnqueue (0, 100)" 362 363 fails=0 364 for i in `seq 1 3` 365 do 366 result=$(dd if=/dev/zero bs=1024 count=1000 | timeout 3 nc -w 5 -N 2001:db8:42::2 7 | wc -c) 367 if [ $result -ne 1024000 ]; 368 then 369 echo "Failed to prioritise TCP traffic. Got only $result bytes" 370 fails=$(( ${fails} + 1 )) 371 fi 372 done 373 if [ ${fails} -lt 3 ]; 374 then 375 atf_fail "We failed reversed prioritisation only ${fails} times." 376 fi 377} 378 379queue_v6_cleanup() 380{ 381 firewall_cleanup $1 382} 383 384nat_head() 385{ 386 atf_set descr 'Basic dummynet + NAT test' 387 atf_set require.user root 388} 389 390nat_body() 391{ 392 fw=$1 393 firewall_init $fw 394 dummynet_init $fw 395 nat_init $fw 396 397 epair=$(vnet_mkepair) 398 epair_two=$(vnet_mkepair) 399 400 ifconfig ${epair}a 192.0.2.2/24 up 401 route add -net 198.51.100.0/24 192.0.2.1 402 403 vnet_mkjail gw ${epair}b ${epair_two}a 404 jexec gw ifconfig ${epair}b 192.0.2.1/24 up 405 jexec gw ifconfig ${epair_two}a 198.51.100.1/24 up 406 jexec gw sysctl net.inet.ip.forwarding=1 407 408 vnet_mkjail srv ${epair_two}b 409 jexec srv ifconfig ${epair_two}b 198.51.100.2/24 up 410 411 jexec gw dnctl pipe 1 config bw 300Byte/s 412 413 firewall_config gw $fw \ 414 "pf" \ 415 "nat on ${epair_two}a inet from 192.0.2.0/24 to any -> (${epair_two}a)" \ 416 "pass dnpipe 1" 417 418 # We've deliberately not set a route to 192.0.2.0/24 on srv, so the 419 # only way it can respond to this is if NAT is applied correctly. 420 atf_check -s exit:0 -o ignore ping -c 1 198.51.100.2 421} 422 423nat_cleanup() 424{ 425 firewall_cleanup $1 426} 427 428setup_tests \ 429 interface_removal \ 430 ipfw \ 431 pf \ 432 pipe \ 433 ipfw \ 434 pf \ 435 pipe_v6 \ 436 ipfw \ 437 pf \ 438 queue \ 439 ipfw \ 440 pf \ 441 queue_v6 \ 442 ipfw \ 443 pf \ 444 nat \ 445 pf 446