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 # After commit 361a8395f0b0e6f254fd138798232529679d99f6 it became 324 # an error to assign the same interface address twice. 325 atf_expect_fail "The test results in an ifconfig error and thus spuriously fails" 326 setup_tap 0 inet ${ADDR} ${MASK1} 327 TAP1=${TAP} 328 ifconfig ${TAP1} -alias ${ADDR} 329 330 # Do it again, in the opposite order. It should not panic. 331 setup_tap 0 inet ${ADDR} ${MASK0} 332 TAP0=${TAP} 333 setup_tap 0 inet ${ADDR} ${MASK1} 334 TAP1=${TAP} 335 ifconfig ${TAP0} -alias ${ADDR} 336} 337same_ip_multiple_ifaces_fib0_cleanup() 338{ 339 cleanup_ifaces 340} 341 342# Regression test for PR kern/189088 343# Test that removing an IP address works even if the same IP is assigned to a 344# different interface, on a different FIB. Tests the same code that whose 345# panic was regressed by same_ip_multiple_ifaces_fib0. 346# Create two tap interfaces and assign them both the same IP address but with 347# different netmasks, and on different FIBs. Then remove one's IP 348# address. Hopefully the machine won't panic. Also, the IP's hostroute should 349# dissappear from the correct fib. 350atf_test_case same_ip_multiple_ifaces cleanup 351same_ip_multiple_ifaces_head() 352{ 353 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." 354 atf_set "require.user" "root" 355} 356same_ip_multiple_ifaces_body() 357{ 358 ADDR="192.0.2.2" 359 MASK0="24" 360 MASK1="32" 361 362 # Unlike most of the tests in this file, this is applicable regardless 363 # of net.add_addr_allfibs 364 get_fibs 4 365 366 # Setup the interfaces, then remove one alias. It should not panic. 367 setup_tap ${FIB0} inet ${ADDR} ${MASK0} 368 TAP0=${TAP} 369 setup_tap ${FIB1} inet ${ADDR} ${MASK1} 370 TAP1=${TAP} 371 ifconfig ${TAP1} -alias ${ADDR} 372 atf_check -o not-match:"^${ADDR}[[:space:]]" \ 373 setfib ${FIB1} netstat -rn -f inet 374 375 # Do it again, in the opposite order. It should not panic. 376 setup_tap ${FIB2} inet ${ADDR} ${MASK0} 377 TAP0=${TAP} 378 setup_tap ${FIB3} inet ${ADDR} ${MASK1} 379 TAP1=${TAP} 380 ifconfig ${TAP0} -alias ${ADDR} 381 atf_check -o not-match:"^${ADDR}[[:space:]]" \ 382 setfib ${FIB2} netstat -rn -f inet 383} 384same_ip_multiple_ifaces_cleanup() 385{ 386 # Due to PR kern/189088, we must destroy the interfaces in LIFO order 387 # in order for the routes to be correctly cleaned up. 388 for TAPD in `tail -r "ifaces_to_cleanup"`; do 389 echo ifconfig ${TAPD} destroy 390 ifconfig ${TAPD} destroy 391 done 392} 393 394atf_test_case same_ip_multiple_ifaces_inet6 cleanup 395same_ip_multiple_ifaces_inet6_head() 396{ 397 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." 398 atf_set "require.user" "root" 399} 400same_ip_multiple_ifaces_inet6_body() 401{ 402 ADDR="2001:db8::2" 403 MASK0="64" 404 MASK1="128" 405 406 # Unlike most of the tests in this file, this is applicable regardless 407 # of net.add_addr_allfibs 408 get_fibs 2 409 410 # Setup the interfaces, then remove one alias. It should not panic. 411 setup_tap ${FIB0} inet6 ${ADDR} ${MASK0} 412 TAP0=${TAP} 413 setup_tap ${FIB1} inet6 ${ADDR} ${MASK1} 414 TAP1=${TAP} 415 atf_check -s exit:0 ifconfig ${TAP1} inet6 ${ADDR} -alias 416 atf_check -o not-match:"^${ADDR}[[:space:]]" \ 417 setfib ${FIB1} netstat -rn -f inet6 418 ifconfig ${TAP1} destroy 419 ifconfig ${TAP0} destroy 420 421 # Do it again, in the opposite order. It should not panic. 422 setup_tap ${FIB0} inet6 ${ADDR} ${MASK0} 423 TAP0=${TAP} 424 setup_tap ${FIB1} inet6 ${ADDR} ${MASK1} 425 TAP1=${TAP} 426 atf_check -s exit:0 ifconfig ${TAP0} inet6 ${ADDR} -alias 427 atf_check -o not-match:"^${ADDR}[[:space:]]" \ 428 setfib ${FIB0} netstat -rn -f inet6 429} 430same_ip_multiple_ifaces_inet6_cleanup() 431{ 432 cleanup_ifaces 433} 434 435atf_test_case slaac_on_nondefault_fib6 cleanup 436slaac_on_nondefault_fib6_head() 437{ 438 atf_set "descr" "SLAAC correctly installs routes on non-default FIBs" 439 atf_set "require.user" "root" 440 atf_set "require.config" "allow_sysctl_side_effects" 441} 442slaac_on_nondefault_fib6_body() 443{ 444 # Configure the epair interfaces to use nonrouteable RFC3849 445 # addresses and non-default FIBs 446 PREFIX="2001:db8:$(printf "%x" `jot -r 1 0 65535`):$(printf "%x" `jot -r 1 0 65535`)" 447 ADDR="$PREFIX::2" 448 GATEWAY="$PREFIX::1" 449 SUBNET="$PREFIX:" 450 MASK="64" 451 452 # Check system configuration 453 if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then 454 atf_skip "This test requires net.add_addr_allfibs=0" 455 fi 456 get_fibs 2 457 458 sysctl -n "net.inet6.ip6.rfc6204w3" >> "rfc6204w3.state" 459 sysctl -n "net.inet6.ip6.forwarding" >> "forwarding.state" 460 # Enable forwarding so the kernel will send RAs 461 sysctl net.inet6.ip6.forwarding=1 462 # Enable RFC6204W3 mode so the kernel will enable default router 463 # selection while also forwarding packets 464 sysctl net.inet6.ip6.rfc6204w3=1 465 466 # Configure epair interfaces 467 get_epair 468 setup_iface "$EPAIRA" "$FIB0" inet6 ${ADDR} ${MASK} 469 echo setfib $FIB1 ifconfig "$EPAIRB" inet6 -ifdisabled accept_rtadv fib $FIB1 up 470 setfib $FIB1 ifconfig "$EPAIRB" inet6 -ifdisabled accept_rtadv fib $FIB1 up 471 rtadvd -p rtadvd.pid -C rtadvd.sock -c /dev/null "$EPAIRA" 472 rtsol "$EPAIRB" 473 474 # Check SLAAC address 475 atf_check -o match:"inet6 ${SUBNET}.*prefixlen ${MASK}.*autoconf" \ 476 ifconfig "$EPAIRB" 477 # Check local route 478 atf_check -o match:"${SUBNET}.*\<UHS\>.*lo0" \ 479 netstat -rnf inet6 -F $FIB1 480 # Check subnet route 481 atf_check -o match:"${SUBNET}:/${MASK}.*\<U\>.*$EPAIRB" \ 482 netstat -rnf inet6 -F $FIB1 483 # Check default route 484 atf_check -o match:"default.*\<UG\>.*$EPAIRB" \ 485 netstat -rnf inet6 -F $FIB1 486 487 # Check that none of the above routes appeared on other routes 488 for fib in $( seq 0 $(($(sysctl -n net.fibs) - 1))); do 489 if [ "$fib" = "$FIB1" -o "$fib" = "$FIB0" ]; then 490 continue 491 fi 492 atf_check -o not-match:"${SUBNET}.*\<UHS\>.*lo0" \ 493 netstat -rnf inet6 -F $fib 494 atf_check -o not-match:"${SUBNET}:/${MASK}.*\<U\>.*$EPAIRB" \ 495 netstat -rnf inet6 -F $fib 496 atf_check -o not-match:"default.*\<UG\>.*$EPAIRB" \ 497 netstat -rnf inet6 -F $fib 498 done 499} 500slaac_on_nondefault_fib6_cleanup() 501{ 502 if [ -f "rtadvd.pid" ]; then 503 # rtadvd can take a long time to shutdown. Use SIGKILL to kill 504 # it right away. The downside to using SIGKILL is that it 505 # won't send final RAs to all interfaces, but we don't care 506 # because we're about to destroy its interface anyway. 507 pkill -kill -F rtadvd.pid 508 rm -f rtadvd.pid 509 fi 510 cleanup_ifaces 511 if [ -f "forwarding.state" ] ; then 512 sysctl "net.inet6.ip6.forwarding"=`cat "forwarding.state"` 513 rm "forwarding.state" 514 fi 515 if [ -f "rfc6204w3.state" ] ; then 516 sysctl "net.inet6.ip6.rfc6204w3"=`cat "rfc6204w3.state"` 517 rm "rfc6204w3.state" 518 fi 519} 520 521# Regression test for kern/187550 522atf_test_case subnet_route_with_multiple_fibs_on_same_subnet cleanup 523subnet_route_with_multiple_fibs_on_same_subnet_head() 524{ 525 atf_set "descr" "Multiple FIBs can have IPv4 subnet routes for the same subnet" 526 atf_set "require.user" "root" 527} 528 529subnet_route_with_multiple_fibs_on_same_subnet_body() 530{ 531 # Configure the TAP interfaces to use a RFC5737 nonrouteable addresses 532 # and a non-default fib 533 ADDR0="192.0.2.2" 534 ADDR1="192.0.2.3" 535 SUBNET="192.0.2.0" 536 MASK="24" 537 538 # Check system configuration 539 if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then 540 atf_skip "This test requires net.add_addr_allfibs=0" 541 fi 542 get_fibs 2 543 544 # Configure TAP interfaces 545 setup_tap "$FIB0" inet ${ADDR0} ${MASK} 546 setup_tap "$FIB1" inet ${ADDR1} ${MASK} 547 548 # Check that a subnet route exists on both fibs 549 atf_check -o ignore setfib "$FIB0" route get $ADDR1 550 atf_check -o ignore setfib "$FIB1" route get $ADDR0 551} 552 553subnet_route_with_multiple_fibs_on_same_subnet_cleanup() 554{ 555 cleanup_ifaces 556} 557 558atf_test_case subnet_route_with_multiple_fibs_on_same_subnet_inet6 cleanup 559subnet_route_with_multiple_fibs_on_same_subnet_inet6_head() 560{ 561 atf_set "descr" "Multiple FIBs can have IPv6 subnet routes for the same subnet" 562 atf_set "require.user" "root" 563} 564 565subnet_route_with_multiple_fibs_on_same_subnet_inet6_body() 566{ 567 # Configure the TAP interfaces to use a RFC3849 nonrouteable addresses 568 # and a non-default fib 569 ADDR0="2001:db8::2" 570 ADDR1="2001:db8::3" 571 SUBNET="2001:db8::" 572 MASK="64" 573 574 # Check system configuration 575 if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then 576 atf_skip "This test requires net.add_addr_allfibs=0" 577 fi 578 get_fibs 2 579 580 # Configure TAP interfaces 581 setup_tap "$FIB0" inet6 ${ADDR0} ${MASK} 582 setup_tap "$FIB1" inet6 ${ADDR1} ${MASK} 583 584 # Check that a subnet route exists on both fibs 585 atf_check -o ignore setfib "$FIB0" route -6 get $ADDR1 586 atf_check -o ignore setfib "$FIB1" route -6 get $ADDR0 587} 588 589subnet_route_with_multiple_fibs_on_same_subnet_inet6_cleanup() 590{ 591 cleanup_ifaces 592} 593 594# Test that source address selection works correctly for UDP packets with 595# SO_DONTROUTE set that are sent on non-default FIBs. 596# This bug was discovered with "setfib 1 netperf -t UDP_STREAM -H some_host" 597# Regression test for kern/187553 598# 599# The root cause was that ifa_ifwithnet() did not have a fib argument. It 600# would return an address from an interface on any FIB that had a subnet route 601# for the destination. If more than one were available, it would choose the 602# most specific. This is most easily tested by creating a FIB without a 603# default route, then trying to send a UDP packet with SO_DONTROUTE set to an 604# address which is not routable on that FIB. Absent the fix for this bug, 605# in_pcbladdr would choose an interface on any FIB with a default route. With 606# the fix, you will get EUNREACH or ENETUNREACH. 607atf_test_case udp_dontroute cleanup 608udp_dontroute_head() 609{ 610 atf_set "descr" "Source address selection for UDP packets with SO_DONTROUTE on non-default FIBs works" 611 atf_set "require.user" "root" 612} 613 614udp_dontroute_body() 615{ 616 # Configure the TAP interface to use an RFC5737 nonrouteable address 617 # and a non-default fib 618 ADDR0="192.0.2.2" 619 ADDR1="192.0.2.3" 620 SUBNET="192.0.2.0" 621 MASK="24" 622 # Use a different IP on the same subnet as the target 623 TARGET="192.0.2.100" 624 SRCDIR=`atf_get_srcdir` 625 626 # Check system configuration 627 if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then 628 atf_skip "This test requires net.add_addr_allfibs=0" 629 fi 630 get_fibs 2 631 632 # Configure the TAP interfaces 633 setup_tap ${FIB0} inet ${ADDR0} ${MASK} 634 TARGET_TAP=${TAP} 635 setup_tap ${FIB1} inet ${ADDR1} ${MASK} 636 637 # Send a UDP packet with SO_DONTROUTE. In the failure case, it will 638 # return ENETUNREACH, or send the packet to the wrong tap 639 atf_check -o ignore setfib ${FIB0} \ 640 ${SRCDIR}/udp_dontroute ${TARGET} /dev/${TARGET_TAP} 641 cleanup_ifaces 642 643 # Repeat, but this time target the other tap 644 setup_tap ${FIB0} inet ${ADDR0} ${MASK} 645 setup_tap ${FIB1} inet ${ADDR1} ${MASK} 646 TARGET_TAP=${TAP} 647 648 atf_check -o ignore setfib ${FIB1} \ 649 ${SRCDIR}/udp_dontroute ${TARGET} /dev/${TARGET_TAP} 650} 651 652udp_dontroute_cleanup() 653{ 654 cleanup_ifaces 655} 656 657atf_test_case udp_dontroute6 cleanup 658udp_dontroute6_head() 659{ 660 atf_set "descr" "Source address selection for UDP IPv6 packets with SO_DONTROUTE on non-default FIBs works" 661 atf_set "require.user" "root" 662} 663 664udp_dontroute6_body() 665{ 666 if [ "$(atf_config_get ci false)" = "true" ]; then 667 atf_skip "https://bugs.freebsd.org/244172" 668 fi 669 # Configure the TAP interface to use an RFC3849 nonrouteable address 670 # and a non-default fib 671 ADDR0="2001:db8::2" 672 ADDR1="2001:db8::3" 673 SUBNET="2001:db8::" 674 MASK="64" 675 # Use a different IP on the same subnet as the target 676 TARGET="2001:db8::100" 677 SRCDIR=`atf_get_srcdir` 678 679 # Check system configuration 680 if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then 681 atf_skip "This test requires net.add_addr_allfibs=0" 682 fi 683 get_fibs 2 684 685 # Configure the TAP interfaces. Use no_dad so the addresses will be 686 # ready right away and won't be marked as tentative until DAD 687 # completes. 688 setup_tap ${FIB0} inet6 ${ADDR0} ${MASK} no_dad 689 TARGET_TAP=${TAP} 690 setup_tap ${FIB1} inet6 ${ADDR1} ${MASK} no_dad 691 692 # Send a UDP packet with SO_DONTROUTE. In the failure case, it will 693 # return ENETUNREACH, or send the packet to the wrong tap 694 atf_check -o ignore setfib ${FIB0} \ 695 ${SRCDIR}/udp_dontroute -6 ${TARGET} /dev/${TARGET_TAP} 696 cleanup_ifaces 697 698 # Repeat, but this time target the other tap 699 setup_tap ${FIB0} inet6 ${ADDR0} ${MASK} no_dad 700 setup_tap ${FIB1} inet6 ${ADDR1} ${MASK} no_dad 701 TARGET_TAP=${TAP} 702 703 atf_check -o ignore setfib ${FIB1} \ 704 ${SRCDIR}/udp_dontroute -6 ${TARGET} /dev/${TARGET_TAP} 705} 706 707udp_dontroute6_cleanup() 708{ 709 cleanup_ifaces 710} 711 712 713atf_init_test_cases() 714{ 715 atf_add_test_case arpresolve_checks_interface_fib 716 atf_add_test_case loopback_and_network_routes_on_nondefault_fib 717 atf_add_test_case loopback_and_network_routes_on_nondefault_fib_inet6 718 atf_add_test_case default_route_with_multiple_fibs_on_same_subnet 719 atf_add_test_case default_route_with_multiple_fibs_on_same_subnet_inet6 720 atf_add_test_case same_ip_multiple_ifaces_fib0 721 atf_add_test_case same_ip_multiple_ifaces 722 atf_add_test_case same_ip_multiple_ifaces_inet6 723 atf_add_test_case slaac_on_nondefault_fib6 724 atf_add_test_case subnet_route_with_multiple_fibs_on_same_subnet 725 atf_add_test_case subnet_route_with_multiple_fibs_on_same_subnet_inet6 726 atf_add_test_case udp_dontroute 727 atf_add_test_case udp_dontroute6 728} 729 730# Looks up one or more fibs from the configuration data and validates them. 731# Returns the results in the env varilables FIB0, FIB1, etc. 732 733# parameter numfibs The number of fibs to lookup 734get_fibs() 735{ 736 NUMFIBS=$1 737 net_fibs=`sysctl -n net.fibs` 738 if [ $net_fibs -lt $(($NUMFIBS + 1)) ]; then 739 atf_check -o ignore sysctl net.fibs=$(($NUMFIBS + 1)) 740 net_fibs=`sysctl -n net.fibs` 741 fi 742 i=0 743 while [ $i -lt "$NUMFIBS" ]; do 744 eval FIB${i}=$(($i + 1)) 745 i=$(( $i + 1 )) 746 done 747} 748 749# Creates a new pair of connected epair(4) interface, registers them for 750# cleanup, and returns their namen via the environment variables EPAIRA and 751# EPAIRB 752get_epair() 753{ 754 local EPAIRD 755 756 if (which pfctl && pfctl -s info | grep -q 'Status: Enabled') || 757 [ `sysctl -n net.inet.ip.fw.enable` = "1" ] || 758 (which ipf && ipf -V); then 759 atf_skip "firewalls interfere with this test" 760 fi 761 762 if EPAIRD=`ifconfig epair create`; then 763 # Record the epair device so we can clean it up later 764 echo ${EPAIRD} >> "ifaces_to_cleanup" 765 EPAIRA=${EPAIRD} 766 EPAIRB=${EPAIRD%a}b 767 else 768 atf_skip "Could not create epair(4) interfaces" 769 fi 770} 771 772# Creates a new tap(4) interface, registers it for cleanup, and returns the 773# name via the environment variable TAP 774get_tap() 775{ 776 local TAPD 777 778 if TAPD=`ifconfig tap create`; then 779 # Record the TAP device so we can clean it up later 780 echo ${TAPD} >> "ifaces_to_cleanup" 781 TAP=${TAPD} 782 else 783 atf_skip "Could not create a tap(4) interface" 784 fi 785} 786 787# Configure an ethernet interface 788# parameters: 789# Interface name 790# fib 791# Protocol (inet or inet6) 792# IP address 793# Netmask in number of bits (eg 24 or 8) 794# Extra flags 795# Return: None 796setup_iface() 797{ 798 local IFACE=$1 799 local FIB=$2 800 local PROTO=$3 801 local ADDR=$4 802 local MASK=$5 803 local FLAGS=$6 804 atf_check setfib ${FIB} ifconfig $IFACE ${PROTO} ${ADDR}/${MASK} fib $FIB $FLAGS 805} 806 807# Create a tap(4) interface, configure it, and register it for cleanup. 808# parameters: 809# fib 810# Protocol (inet or inet6) 811# IP address 812# Netmask in number of bits (eg 24 or 8) 813# Extra flags 814# Return: the tap interface name as the env variable TAP 815setup_tap() 816{ 817 get_tap 818 setup_iface "$TAP" "$@" 819} 820 821cleanup_ifaces() 822{ 823 if [ -f ifaces_to_cleanup ]; then 824 for iface in $(cat ifaces_to_cleanup); do 825 echo ifconfig "${iface}" destroy 826 ifconfig "${iface}" destroy 2>/dev/null || true 827 done 828 rm -f ifaces_to_cleanup 829 fi 830} 831