1# 2# Copyright (c) 2014 Spectra Logic Corporation 3# All rights reserved. 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions 7# are met: 8# 1. Redistributions of source code must retain the above copyright 9# notice, this list of conditions, and the following disclaimer, 10# without modification. 11# 2. Redistributions in binary form must reproduce at minimum a disclaimer 12# substantially similar to the "NO WARRANTY" disclaimer below 13# ("Disclaimer") and any redistribution must be conditioned upon 14# including a substantially similar Disclaimer requirement for further 15# binary redistribution. 16# 17# NO WARRANTY 18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 21# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22# HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28# POSSIBILITY OF SUCH DAMAGES. 29# 30# Authors: Alan Somers (Spectra Logic Corporation) 31# 32 33# arpresolve should check the interface fib for routes to a target when 34# creating an ARP table entry. This is a regression for kern/167947, where 35# arpresolve only checked the default route. 36# 37# Outline: 38# Create two connected epair(4) interfaces 39# Use nping (from security/nmap) to send an ICMP echo request from one 40# interface to the other, spoofing the source IP. The source IP must be 41# spoofed, or else it will already have an entry in the arp table. 42# Check whether an arp entry exists for the spoofed IP 43atf_test_case arpresolve_checks_interface_fib cleanup 44arpresolve_checks_interface_fib_head() 45{ 46 atf_set "descr" "arpresolve should check the interface fib, not the default fib, for routes" 47 atf_set "require.user" "root" 48 atf_set "require.progs" "nping" 49} 50arpresolve_checks_interface_fib_body() 51{ 52 # Configure the TAP interfaces to use a RFC5737 nonrouteable addresses 53 # and a non-default fib 54 ADDR0="192.0.2.2" 55 ADDR1="192.0.2.3" 56 SUBNET="192.0.2.0" 57 # Due to bug TBD (regressed by multiple_fibs_on_same_subnet) we need 58 # diffferent subnet masks, or FIB1 won't have a subnet route. 59 MASK0="24" 60 MASK1="25" 61 # Spoof a MAC that is reserved per RFC7042 62 SPOOF_ADDR="192.0.2.4" 63 SPOOF_MAC="00:00:5E:00:53:00" 64 65 # Check system configuration 66 if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then 67 atf_skip "This test requires net.add_addr_allfibs=0" 68 fi 69 get_fibs 2 70 71 # Configure epair interfaces 72 get_epair 73 setup_iface "$EPAIRA" "$FIB0" inet ${ADDR0} ${MASK0} 74 setup_iface "$EPAIRB" "$FIB1" inet ${ADDR1} ${MASK1} 75 76 # Send an ICMP echo request with a spoofed source IP 77 setfib "$FIB0" nping -c 1 -e ${EPAIRA} -S ${SPOOF_ADDR} \ 78 --source-mac ${SPOOF_MAC} --icmp --icmp-type "echo-request" \ 79 --icmp-code 0 --icmp-id 0xdead --icmp-seq 1 --data 0xbeef \ 80 ${ADDR1} 81 # For informational and debugging purposes only, look for the 82 # characteristic error message 83 dmesg | grep "llinfo.*${SPOOF_ADDR}" 84 # Check that the ARP entry exists 85 atf_check -o match:"${SPOOF_ADDR}.*expires" setfib "$FIB1" arp ${SPOOF_ADDR} 86} 87arpresolve_checks_interface_fib_cleanup() 88{ 89 cleanup_ifaces 90} 91 92 93# Regression test for kern/187549 94atf_test_case loopback_and_network_routes_on_nondefault_fib cleanup 95loopback_and_network_routes_on_nondefault_fib_head() 96{ 97 atf_set "descr" "When creating and deleting loopback IPv4 routes, use the interface's fib" 98 atf_set "require.user" "root" 99} 100 101loopback_and_network_routes_on_nondefault_fib_body() 102{ 103 # Configure the TAP interface to use an RFC5737 nonrouteable address 104 # and a non-default fib 105 ADDR="192.0.2.2" 106 SUBNET="192.0.2.0" 107 MASK="24" 108 109 # Check system configuration 110 if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then 111 atf_skip "This test requires net.add_addr_allfibs=0" 112 fi 113 get_fibs 1 114 115 # Configure a TAP interface 116 setup_tap ${FIB0} inet ${ADDR} ${MASK} 117 118 # Check whether the host route exists in only the correct FIB 119 setfib ${FIB0} netstat -rn -f inet | grep -q "^${ADDR}.*UHS.*lo0" 120 if [ 0 -ne $? ]; then 121 setfib ${FIB0} netstat -rn -f inet 122 atf_fail "Host route did not appear in the correct FIB" 123 fi 124 setfib 0 netstat -rn -f inet | grep -q "^${ADDR}.*UHS.*lo0" 125 if [ 0 -eq $? ]; then 126 setfib 0 netstat -rn -f inet 127 atf_fail "Host route appeared in the wrong FIB" 128 fi 129 130 # Check whether the network route exists in only the correct FIB 131 setfib ${FIB0} netstat -rn -f inet | \ 132 grep -q "^${SUBNET}/${MASK}.*${TAPD}" 133 if [ 0 -ne $? ]; then 134 setfib ${FIB0} netstat -rn -f inet 135 atf_fail "Network route did not appear in the correct FIB" 136 fi 137 setfib 0 netstat -rn -f inet | \ 138 grep -q "^${SUBNET}/${MASK}.*${TAPD}" 139 if [ 0 -eq $? ]; then 140 setfib 0 netstat -rn -f inet 141 atf_fail "Network route appeared in the wrong FIB" 142 fi 143} 144 145loopback_and_network_routes_on_nondefault_fib_cleanup() 146{ 147 cleanup_ifaces 148} 149 150atf_test_case loopback_and_network_routes_on_nondefault_fib_inet6 cleanup 151loopback_and_network_routes_on_nondefault_fib_inet6_head() 152{ 153 atf_set "descr" "When creating and deleting loopback IPv6 routes, use the interface's fib" 154 atf_set "require.user" "root" 155} 156 157loopback_and_network_routes_on_nondefault_fib_inet6_body() 158{ 159 # Configure the TAP interface to use a nonrouteable RFC3849 160 # address and a non-default fib 161 ADDR="2001:db8::2" 162 SUBNET="2001:db8::" 163 MASK="64" 164 165 # Check system configuration 166 if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then 167 atf_skip "This test requires net.add_addr_allfibs=0" 168 fi 169 get_fibs 1 170 171 # Configure a TAP interface 172 setup_tap ${FIB0} inet6 ${ADDR} ${MASK} 173 174 # Check whether the host route exists in only the correct FIB 175 setfib ${FIB0} netstat -rn -f inet6 | grep -q "^${ADDR}.*UHS.*lo0" 176 if [ 0 -ne $? ]; then 177 setfib ${FIB0} netstat -rn -f inet6 178 atf_fail "Host route did not appear in the correct FIB" 179 fi 180 setfib 0 netstat -rn -f inet6 | grep -q "^${ADDR}.*UHS.*lo0" 181 if [ 0 -eq $? ]; then 182 setfib 0 netstat -rn -f inet6 183 atf_fail "Host route appeared in the wrong FIB" 184 fi 185 186 # Check whether the network route exists in only the correct FIB 187 setfib ${FIB0} netstat -rn -f inet6 | \ 188 grep -q "^${SUBNET}/${MASK}.*${TAPD}" 189 if [ 0 -ne $? ]; then 190 setfib ${FIB0} netstat -rn -f inet6 191 atf_fail "Network route did not appear in the correct FIB" 192 fi 193 setfib 0 netstat -rn -f inet6 | \ 194 grep -q "^${SUBNET}/${MASK}.*${TAPD}" 195 if [ 0 -eq $? ]; then 196 setfib 0 netstat -rn -f inet6 197 atf_fail "Network route appeared in the wrong FIB" 198 fi 199} 200 201loopback_and_network_routes_on_nondefault_fib_inet6_cleanup() 202{ 203 cleanup_ifaces 204} 205 206 207# Regression test for kern/187552 208atf_test_case default_route_with_multiple_fibs_on_same_subnet cleanup 209default_route_with_multiple_fibs_on_same_subnet_head() 210{ 211 atf_set "descr" "Multiple interfaces on the same subnet but with different fibs can both have default IPv4 routes" 212 atf_set "require.user" "root" 213} 214 215default_route_with_multiple_fibs_on_same_subnet_body() 216{ 217 # Configure the TAP interfaces to use a RFC5737 nonrouteable addresses 218 # and a non-default fib 219 ADDR0="192.0.2.2" 220 ADDR1="192.0.2.3" 221 GATEWAY="192.0.2.1" 222 SUBNET="192.0.2.0" 223 MASK="24" 224 225 # Check system configuration 226 if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then 227 atf_skip "This test requires net.add_addr_allfibs=0" 228 fi 229 get_fibs 2 230 231 # Configure TAP interfaces 232 setup_tap "$FIB0" inet ${ADDR0} ${MASK} 233 TAP0=$TAP 234 setup_tap "$FIB1" inet ${ADDR1} ${MASK} 235 TAP1=$TAP 236 237 # Attempt to add default routes 238 setfib ${FIB0} route add default ${GATEWAY} 239 setfib ${FIB1} route add default ${GATEWAY} 240 241 # Verify that the default route exists for both fibs, with their 242 # respective interfaces. 243 atf_check -o match:"^default.*${TAP0}$" \ 244 setfib ${FIB0} netstat -rn -f inet 245 atf_check -o match:"^default.*${TAP1}$" \ 246 setfib ${FIB1} netstat -rn -f inet 247} 248 249default_route_with_multiple_fibs_on_same_subnet_cleanup() 250{ 251 cleanup_ifaces 252} 253 254atf_test_case default_route_with_multiple_fibs_on_same_subnet_inet6 cleanup 255default_route_with_multiple_fibs_on_same_subnet_inet6_head() 256{ 257 atf_set "descr" "Multiple interfaces on the same subnet but with different fibs can both have default IPv6 routes" 258 atf_set "require.user" "root" 259} 260 261default_route_with_multiple_fibs_on_same_subnet_inet6_body() 262{ 263 # Configure the TAP interfaces to use nonrouteable RFC3849 264 # addresses and non-default FIBs 265 ADDR0="2001:db8::2" 266 ADDR1="2001:db8::3" 267 GATEWAY="2001:db8::1" 268 SUBNET="2001:db8::" 269 MASK="64" 270 271 # Check system configuration 272 if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then 273 atf_skip "This test requires net.add_addr_allfibs=0" 274 fi 275 get_fibs 2 276 277 # Configure TAP interfaces 278 setup_tap "$FIB0" inet6 ${ADDR0} ${MASK} 279 TAP0=$TAP 280 setup_tap "$FIB1" inet6 ${ADDR1} ${MASK} 281 TAP1=$TAP 282 283 # Attempt to add default routes 284 setfib ${FIB0} route -6 add default ${GATEWAY} 285 setfib ${FIB1} route -6 add default ${GATEWAY} 286 287 # Verify that the default route exists for both fibs, with their 288 # respective interfaces. 289 atf_check -o match:"^default.*${TAP0}$" \ 290 setfib ${FIB0} netstat -rn -f inet6 291 atf_check -o match:"^default.*${TAP1}$" \ 292 setfib ${FIB1} netstat -rn -f inet6 293} 294 295default_route_with_multiple_fibs_on_same_subnet_inet6_cleanup() 296{ 297 cleanup_ifaces 298} 299 300 301# Regression test for PR kern/189089 302# Create two tap interfaces and assign them both the same IP address but with 303# different netmasks, and both on the default FIB. Then remove one's IP 304# address. Hopefully the machine won't panic. 305atf_test_case same_ip_multiple_ifaces_fib0 cleanup 306same_ip_multiple_ifaces_fib0_head() 307{ 308 atf_set "descr" "Can remove an IPv4 alias from an interface when the same IPv4 is also assigned to another interface." 309 atf_set "require.user" "root" 310} 311same_ip_multiple_ifaces_fib0_body() 312{ 313 ADDR="192.0.2.2" 314 MASK0="24" 315 MASK1="32" 316 317 # Unlike most of the tests in this file, this is applicable regardless 318 # of net.add_addr_allfibs 319 320 # Setup the interfaces, then remove one alias. It should not panic. 321 setup_tap 0 inet ${ADDR} ${MASK0} 322 TAP0=${TAP} 323 setup_tap 0 inet ${ADDR} ${MASK1} 324 TAP1=${TAP} 325 ifconfig ${TAP1} -alias ${ADDR} 326 327 # Do it again, in the opposite order. It should not panic. 328 setup_tap 0 inet ${ADDR} ${MASK0} 329 TAP0=${TAP} 330 setup_tap 0 inet ${ADDR} ${MASK1} 331 TAP1=${TAP} 332 ifconfig ${TAP0} -alias ${ADDR} 333} 334same_ip_multiple_ifaces_fib0_cleanup() 335{ 336 cleanup_ifaces 337} 338 339# Regression test for PR kern/189088 340# Test that removing an IP address works even if the same IP is assigned to a 341# different interface, on a different FIB. Tests the same code that whose 342# panic was regressed by same_ip_multiple_ifaces_fib0. 343# Create two tap interfaces and assign them both the same IP address but with 344# different netmasks, and on different FIBs. Then remove one's IP 345# address. Hopefully the machine won't panic. Also, the IP's hostroute should 346# dissappear from the correct fib. 347atf_test_case same_ip_multiple_ifaces cleanup 348same_ip_multiple_ifaces_head() 349{ 350 atf_set "descr" "Can remove an IPv4 alias from an interface when the same address is also assigned to another interface, on non-default FIBs." 351 atf_set "require.user" "root" 352} 353same_ip_multiple_ifaces_body() 354{ 355 atf_expect_fail "kern/189088 Assigning the same IP to multiple interfaces in different FIBs creates a host route for only one" 356 ADDR="192.0.2.2" 357 MASK0="24" 358 MASK1="32" 359 360 # Unlike most of the tests in this file, this is applicable regardless 361 # of net.add_addr_allfibs 362 get_fibs 2 363 364 # Setup the interfaces, then remove one alias. It should not panic. 365 setup_tap ${FIB0} inet ${ADDR} ${MASK0} 366 TAP0=${TAP} 367 setup_tap ${FIB1} inet ${ADDR} ${MASK1} 368 TAP1=${TAP} 369 ifconfig ${TAP1} -alias ${ADDR} 370 atf_check -o not-match:"^${ADDR}[[:space:]]" \ 371 setfib ${FIB1} netstat -rn -f inet 372 373 # Do it again, in the opposite order. It should not panic. 374 setup_tap ${FIB0} inet ${ADDR} ${MASK0} 375 TAP0=${TAP} 376 setup_tap ${FIB1} inet ${ADDR} ${MASK1} 377 TAP1=${TAP} 378 ifconfig ${TAP0} -alias ${ADDR} 379 atf_check -o not-match:"^${ADDR}[[:space:]]" \ 380 setfib ${FIB0} netstat -rn -f inet 381} 382same_ip_multiple_ifaces_cleanup() 383{ 384 # Due to PR kern/189088, we must destroy the interfaces in LIFO order 385 # in order for the routes to be correctly cleaned up. 386 for TAPD in `tail -r "ifaces_to_cleanup"`; do 387 echo ifconfig ${TAPD} destroy 388 ifconfig ${TAPD} destroy 389 done 390} 391 392atf_test_case same_ip_multiple_ifaces_inet6 cleanup 393same_ip_multiple_ifaces_inet6_head() 394{ 395 atf_set "descr" "Can remove an IPv6 alias from an interface when the same address is also assigned to another interface, on non-default FIBs." 396 atf_set "require.user" "root" 397} 398same_ip_multiple_ifaces_inet6_body() 399{ 400 ADDR="2001:db8::2" 401 MASK0="64" 402 MASK1="128" 403 404 # Unlike most of the tests in this file, this is applicable regardless 405 # of net.add_addr_allfibs 406 get_fibs 2 407 408 # Setup the interfaces, then remove one alias. It should not panic. 409 setup_tap ${FIB0} inet6 ${ADDR} ${MASK0} 410 TAP0=${TAP} 411 setup_tap ${FIB1} inet6 ${ADDR} ${MASK1} 412 TAP1=${TAP} 413 atf_check -s exit:0 ifconfig ${TAP1} inet6 ${ADDR} -alias 414 atf_check -o not-match:"^${ADDR}[[:space:]]" \ 415 setfib ${FIB1} netstat -rn -f inet6 416 ifconfig ${TAP1} destroy 417 ifconfig ${TAP0} destroy 418 419 # Do it again, in the opposite order. It should not panic. 420 setup_tap ${FIB0} inet6 ${ADDR} ${MASK0} 421 TAP0=${TAP} 422 setup_tap ${FIB1} inet6 ${ADDR} ${MASK1} 423 TAP1=${TAP} 424 atf_check -s exit:0 ifconfig ${TAP0} inet6 ${ADDR} -alias 425 atf_check -o not-match:"^${ADDR}[[:space:]]" \ 426 setfib ${FIB0} netstat -rn -f inet6 427} 428same_ip_multiple_ifaces_inet6_cleanup() 429{ 430 cleanup_ifaces 431} 432 433atf_test_case slaac_on_nondefault_fib6 cleanup 434slaac_on_nondefault_fib6_head() 435{ 436 atf_set "descr" "SLAAC correctly installs routes on non-default FIBs" 437 atf_set "require.user" "root" 438 atf_set "require.config" "allow_sysctl_side_effects" 439} 440slaac_on_nondefault_fib6_body() 441{ 442 # Configure the epair interfaces to use nonrouteable RFC3849 443 # addresses and non-default FIBs 444 PREFIX="2001:db8:$(printf "%x" `jot -r 1 0 65535`):$(printf "%x" `jot -r 1 0 65535`)" 445 ADDR="$PREFIX::2" 446 GATEWAY="$PREFIX::1" 447 SUBNET="$PREFIX:" 448 MASK="64" 449 450 # Check system configuration 451 if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then 452 atf_skip "This test requires net.add_addr_allfibs=0" 453 fi 454 get_fibs 2 455 456 sysctl -n "net.inet6.ip6.rfc6204w3" >> "rfc6204w3.state" 457 sysctl -n "net.inet6.ip6.forwarding" >> "forwarding.state" 458 # Enable forwarding so the kernel will send RAs 459 sysctl net.inet6.ip6.forwarding=1 460 # Enable RFC6204W3 mode so the kernel will enable default router 461 # selection while also forwarding packets 462 sysctl net.inet6.ip6.rfc6204w3=1 463 464 # Configure epair interfaces 465 get_epair 466 setup_iface "$EPAIRA" "$FIB0" inet6 ${ADDR} ${MASK} 467 echo setfib $FIB1 ifconfig "$EPAIRB" inet6 -ifdisabled accept_rtadv fib $FIB1 up 468 setfib $FIB1 ifconfig "$EPAIRB" inet6 -ifdisabled accept_rtadv fib $FIB1 up 469 rtadvd -p rtadvd.pid -C rtadvd.sock -c /dev/null "$EPAIRA" 470 rtsol "$EPAIRB" 471 472 # Check SLAAC address 473 atf_check -o match:"inet6 ${SUBNET}.*prefixlen ${MASK}.*autoconf" \ 474 ifconfig "$EPAIRB" 475 # Check local route 476 atf_check -o match:"${SUBNET}.*\<UHS\>.*lo0" \ 477 netstat -rnf inet6 -F $FIB1 478 # Check subnet route 479 atf_check -o match:"${SUBNET}:/${MASK}.*\<U\>.*$EPAIRB" \ 480 netstat -rnf inet6 -F $FIB1 481 # Check default route 482 atf_check -o match:"default.*\<UG\>.*$EPAIRB" \ 483 netstat -rnf inet6 -F $FIB1 484 485 # Check that none of the above routes appeared on other routes 486 for fib in $( seq 0 $(($(sysctl -n net.fibs) - 1))); do 487 if [ "$fib" = "$FIB1" -o "$fib" = "$FIB0" ]; then 488 continue 489 fi 490 atf_check -o not-match:"${SUBNET}.*\<UHS\>.*lo0" \ 491 netstat -rnf inet6 -F $fib 492 atf_check -o not-match:"${SUBNET}:/${MASK}.*\<U\>.*$EPAIRB" \ 493 netstat -rnf inet6 -F $fib 494 atf_check -o not-match:"default.*\<UG\>.*$EPAIRB" \ 495 netstat -rnf inet6 -F $fib 496 done 497} 498slaac_on_nondefault_fib6_cleanup() 499{ 500 if [ -f "rtadvd.pid" ]; then 501 # rtadvd can take a long time to shutdown. Use SIGKILL to kill 502 # it right away. The downside to using SIGKILL is that it 503 # won't send final RAs to all interfaces, but we don't care 504 # because we're about to destroy its interface anyway. 505 pkill -kill -F rtadvd.pid 506 rm -f rtadvd.pid 507 fi 508 cleanup_ifaces 509 if [ -f "forwarding.state" ] ; then 510 sysctl "net.inet6.ip6.forwarding"=`cat "forwarding.state"` 511 rm "forwarding.state" 512 fi 513 if [ -f "rfc6204w3.state" ] ; then 514 sysctl "net.inet6.ip6.rfc6204w3"=`cat "rfc6204w3.state"` 515 rm "rfc6204w3.state" 516 fi 517} 518 519# Regression test for kern/187550 520atf_test_case subnet_route_with_multiple_fibs_on_same_subnet cleanup 521subnet_route_with_multiple_fibs_on_same_subnet_head() 522{ 523 atf_set "descr" "Multiple FIBs can have IPv4 subnet routes for the same subnet" 524 atf_set "require.user" "root" 525} 526 527subnet_route_with_multiple_fibs_on_same_subnet_body() 528{ 529 # Configure the TAP interfaces to use a RFC5737 nonrouteable addresses 530 # and a non-default fib 531 ADDR0="192.0.2.2" 532 ADDR1="192.0.2.3" 533 SUBNET="192.0.2.0" 534 MASK="24" 535 536 # Check system configuration 537 if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then 538 atf_skip "This test requires net.add_addr_allfibs=0" 539 fi 540 get_fibs 2 541 542 # Configure TAP interfaces 543 setup_tap "$FIB0" inet ${ADDR0} ${MASK} 544 setup_tap "$FIB1" inet ${ADDR1} ${MASK} 545 546 # Check that a subnet route exists on both fibs 547 atf_check -o ignore setfib "$FIB0" route get $ADDR1 548 atf_check -o ignore setfib "$FIB1" route get $ADDR0 549} 550 551subnet_route_with_multiple_fibs_on_same_subnet_cleanup() 552{ 553 cleanup_ifaces 554} 555 556atf_test_case subnet_route_with_multiple_fibs_on_same_subnet_inet6 cleanup 557subnet_route_with_multiple_fibs_on_same_subnet_inet6_head() 558{ 559 atf_set "descr" "Multiple FIBs can have IPv6 subnet routes for the same subnet" 560 atf_set "require.user" "root" 561} 562 563subnet_route_with_multiple_fibs_on_same_subnet_inet6_body() 564{ 565 # Configure the TAP interfaces to use a RFC3849 nonrouteable addresses 566 # and a non-default fib 567 ADDR0="2001:db8::2" 568 ADDR1="2001:db8::3" 569 SUBNET="2001:db8::" 570 MASK="64" 571 572 # Check system configuration 573 if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then 574 atf_skip "This test requires net.add_addr_allfibs=0" 575 fi 576 get_fibs 2 577 578 # Configure TAP interfaces 579 setup_tap "$FIB0" inet6 ${ADDR0} ${MASK} 580 setup_tap "$FIB1" inet6 ${ADDR1} ${MASK} 581 582 # Check that a subnet route exists on both fibs 583 atf_check -o ignore setfib "$FIB0" route -6 get $ADDR1 584 atf_check -o ignore setfib "$FIB1" route -6 get $ADDR0 585} 586 587subnet_route_with_multiple_fibs_on_same_subnet_inet6_cleanup() 588{ 589 cleanup_ifaces 590} 591 592# Test that source address selection works correctly for UDP packets with 593# SO_DONTROUTE set that are sent on non-default FIBs. 594# This bug was discovered with "setfib 1 netperf -t UDP_STREAM -H some_host" 595# Regression test for kern/187553 596# 597# The root cause was that ifa_ifwithnet() did not have a fib argument. It 598# would return an address from an interface on any FIB that had a subnet route 599# for the destination. If more than one were available, it would choose the 600# most specific. This is most easily tested by creating a FIB without a 601# default route, then trying to send a UDP packet with SO_DONTROUTE set to an 602# address which is not routable on that FIB. Absent the fix for this bug, 603# in_pcbladdr would choose an interface on any FIB with a default route. With 604# the fix, you will get EUNREACH or ENETUNREACH. 605atf_test_case udp_dontroute cleanup 606udp_dontroute_head() 607{ 608 atf_set "descr" "Source address selection for UDP packets with SO_DONTROUTE on non-default FIBs works" 609 atf_set "require.user" "root" 610} 611 612udp_dontroute_body() 613{ 614 # Configure the TAP interface to use an RFC5737 nonrouteable address 615 # and a non-default fib 616 ADDR0="192.0.2.2" 617 ADDR1="192.0.2.3" 618 SUBNET="192.0.2.0" 619 MASK="24" 620 # Use a different IP on the same subnet as the target 621 TARGET="192.0.2.100" 622 SRCDIR=`atf_get_srcdir` 623 624 # Check system configuration 625 if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then 626 atf_skip "This test requires net.add_addr_allfibs=0" 627 fi 628 get_fibs 2 629 630 # Configure the TAP interfaces 631 setup_tap ${FIB0} inet ${ADDR0} ${MASK} 632 TARGET_TAP=${TAP} 633 setup_tap ${FIB1} inet ${ADDR1} ${MASK} 634 635 # Send a UDP packet with SO_DONTROUTE. In the failure case, it will 636 # return ENETUNREACH, or send the packet to the wrong tap 637 atf_check -o ignore setfib ${FIB0} \ 638 ${SRCDIR}/udp_dontroute ${TARGET} /dev/${TARGET_TAP} 639 cleanup_ifaces 640 641 # Repeat, but this time target the other tap 642 setup_tap ${FIB0} inet ${ADDR0} ${MASK} 643 setup_tap ${FIB1} inet ${ADDR1} ${MASK} 644 TARGET_TAP=${TAP} 645 646 atf_check -o ignore setfib ${FIB1} \ 647 ${SRCDIR}/udp_dontroute ${TARGET} /dev/${TARGET_TAP} 648} 649 650udp_dontroute_cleanup() 651{ 652 cleanup_ifaces 653} 654 655atf_test_case udp_dontroute6 cleanup 656udp_dontroute6_head() 657{ 658 atf_set "descr" "Source address selection for UDP IPv6 packets with SO_DONTROUTE on non-default FIBs works" 659 atf_set "require.user" "root" 660} 661 662udp_dontroute6_body() 663{ 664 if [ "$(atf_config_get ci false)" = "true" ]; then 665 atf_skip "https://bugs.freebsd.org/244172" 666 fi 667 # Configure the TAP interface to use an RFC3849 nonrouteable address 668 # and a non-default fib 669 ADDR0="2001:db8::2" 670 ADDR1="2001:db8::3" 671 SUBNET="2001:db8::" 672 MASK="64" 673 # Use a different IP on the same subnet as the target 674 TARGET="2001:db8::100" 675 SRCDIR=`atf_get_srcdir` 676 677 # Check system configuration 678 if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then 679 atf_skip "This test requires net.add_addr_allfibs=0" 680 fi 681 get_fibs 2 682 683 # Configure the TAP interfaces. Use no_dad so the addresses will be 684 # ready right away and won't be marked as tentative until DAD 685 # completes. 686 setup_tap ${FIB0} inet6 ${ADDR0} ${MASK} no_dad 687 TARGET_TAP=${TAP} 688 setup_tap ${FIB1} inet6 ${ADDR1} ${MASK} no_dad 689 690 # Send a UDP packet with SO_DONTROUTE. In the failure case, it will 691 # return ENETUNREACH, or send the packet to the wrong tap 692 atf_check -o ignore setfib ${FIB0} \ 693 ${SRCDIR}/udp_dontroute -6 ${TARGET} /dev/${TARGET_TAP} 694 cleanup_ifaces 695 696 # Repeat, but this time target the other tap 697 setup_tap ${FIB0} inet6 ${ADDR0} ${MASK} no_dad 698 setup_tap ${FIB1} inet6 ${ADDR1} ${MASK} no_dad 699 TARGET_TAP=${TAP} 700 701 atf_check -o ignore setfib ${FIB1} \ 702 ${SRCDIR}/udp_dontroute -6 ${TARGET} /dev/${TARGET_TAP} 703} 704 705udp_dontroute6_cleanup() 706{ 707 cleanup_ifaces 708} 709 710 711atf_init_test_cases() 712{ 713 atf_add_test_case arpresolve_checks_interface_fib 714 atf_add_test_case loopback_and_network_routes_on_nondefault_fib 715 atf_add_test_case loopback_and_network_routes_on_nondefault_fib_inet6 716 atf_add_test_case default_route_with_multiple_fibs_on_same_subnet 717 atf_add_test_case default_route_with_multiple_fibs_on_same_subnet_inet6 718 atf_add_test_case same_ip_multiple_ifaces_fib0 719 atf_add_test_case same_ip_multiple_ifaces 720 atf_add_test_case same_ip_multiple_ifaces_inet6 721 atf_add_test_case slaac_on_nondefault_fib6 722 atf_add_test_case subnet_route_with_multiple_fibs_on_same_subnet 723 atf_add_test_case subnet_route_with_multiple_fibs_on_same_subnet_inet6 724 atf_add_test_case udp_dontroute 725 atf_add_test_case udp_dontroute6 726} 727 728# Looks up one or more fibs from the configuration data and validates them. 729# Returns the results in the env varilables FIB0, FIB1, etc. 730 731# parameter numfibs The number of fibs to lookup 732get_fibs() 733{ 734 NUMFIBS=$1 735 net_fibs=`sysctl -n net.fibs` 736 if [ $net_fibs -lt $(($NUMFIBS + 1)) ]; then 737 atf_check -o ignore sysctl net.fibs=$(($NUMFIBS + 1)) 738 net_fibs=`sysctl -n net.fibs` 739 fi 740 i=0 741 while [ $i -lt "$NUMFIBS" ]; do 742 eval FIB${i}=$(($i + 1)) 743 i=$(( $i + 1 )) 744 done 745} 746 747# Creates a new pair of connected epair(4) interface, registers them for 748# cleanup, and returns their namen via the environment variables EPAIRA and 749# EPAIRB 750get_epair() 751{ 752 local EPAIRD 753 754 if (which pfctl && pfctl -s info | grep -q 'Status: Enabled') || 755 [ `sysctl -n net.inet.ip.fw.enable` = "1" ] || 756 (which ipf && ipf -V); then 757 atf_skip "firewalls interfere with this test" 758 fi 759 760 if EPAIRD=`ifconfig epair create`; then 761 # Record the epair device so we can clean it up later 762 echo ${EPAIRD} >> "ifaces_to_cleanup" 763 EPAIRA=${EPAIRD} 764 EPAIRB=${EPAIRD%a}b 765 else 766 atf_skip "Could not create epair(4) interfaces" 767 fi 768} 769 770# Creates a new tap(4) interface, registers it for cleanup, and returns the 771# name via the environment variable TAP 772get_tap() 773{ 774 local TAPD 775 776 if TAPD=`ifconfig tap create`; then 777 # Record the TAP device so we can clean it up later 778 echo ${TAPD} >> "ifaces_to_cleanup" 779 TAP=${TAPD} 780 else 781 atf_skip "Could not create a tap(4) interface" 782 fi 783} 784 785# Configure an ethernet interface 786# parameters: 787# Interface name 788# fib 789# Protocol (inet or inet6) 790# IP address 791# Netmask in number of bits (eg 24 or 8) 792# Extra flags 793# Return: None 794setup_iface() 795{ 796 local IFACE=$1 797 local FIB=$2 798 local PROTO=$3 799 local ADDR=$4 800 local MASK=$5 801 local FLAGS=$6 802 atf_check setfib ${FIB} ifconfig $IFACE ${PROTO} ${ADDR}/${MASK} fib $FIB $FLAGS 803} 804 805# Create a tap(4) interface, configure it, and register it for cleanup. 806# parameters: 807# fib 808# Protocol (inet or inet6) 809# IP address 810# Netmask in number of bits (eg 24 or 8) 811# Extra flags 812# Return: the tap interface name as the env variable TAP 813setup_tap() 814{ 815 get_tap 816 setup_iface "$TAP" "$@" 817} 818 819cleanup_ifaces() 820{ 821 if [ -f ifaces_to_cleanup ]; then 822 for iface in $(cat ifaces_to_cleanup); do 823 echo ifconfig "${iface}" destroy 824 ifconfig "${iface}" destroy 2>/dev/null || true 825 done 826 rm -f ifaces_to_cleanup 827 fi 828} 829