fibs_test.sh revision 263779
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# $FreeBSD: head/tests/sys/netinet/fibs_test.sh 263779 2014-03-26 22:46:03Z asomers $ 33 34# All of the tests in this file requires the test-suite config variable "fibs" 35# to be defined to a space-delimited list of FIBs that may be used for testing. 36 37# arpresolve should check the interface fib for routes to a target when 38# creating an ARP table entry. This is a regression for kern/167947, where 39# arpresolve only checked the default route. 40# 41# Outline: 42# Create two tap(4) interfaces 43# Simulate a crossover cable between them by using net/socat 44# Use nping (from security/nmap) to send an ICMP echo request from one 45# interface to the other, spoofing the source IP. The source IP must be 46# spoofed, or else it will already have an entry in the arp table. 47# Check whether an arp entry exists for the spoofed IP 48atf_test_case arpresolve_checks_interface_fib cleanup 49arpresolve_checks_interface_fib_head() 50{ 51 atf_set "descr" "arpresolve should check the interface fib, not the default fib, for routes" 52 atf_set "require.user" "root" 53 atf_set "require.config" "fibs" 54 atf_set "require.progs" "socat nping" 55} 56arpresolve_checks_interface_fib_body() 57{ 58 # Configure the TAP interfaces to use a RFC5737 nonrouteable addresses 59 # and a non-default fib 60 ADDR0="192.0.2.2" 61 ADDR1="192.0.2.3" 62 SUBNET="192.0.2.0" 63 # Due to bug TBD (regressed by multiple_fibs_on_same_subnet) we need 64 # diffferent subnet masks, or FIB1 won't have a subnet route. 65 MASK0="24" 66 MASK1="25" 67 # Spoof a MAC that is reserved per RFC7042 68 SPOOF_ADDR="192.0.2.4" 69 SPOOF_MAC="00:00:5E:00:53:00" 70 71 # Check system configuration 72 if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then 73 atf_skip "This test requires net.add_addr_allfibs=0" 74 fi 75 get_fibs 2 76 77 # Configure TAP interfaces 78 setup_tap "$FIB0" ${ADDR0} ${MASK0} 79 TAP0=$TAP 80 setup_tap "$FIB1" ${ADDR1} ${MASK1} 81 TAP1=$TAP 82 83 # Simulate a crossover cable 84 socat /dev/${TAP0} /dev/${TAP1} & 85 SOCAT_PID=$! 86 echo ${SOCAT_PID} >> "processes_to_kill" 87 88 # Send an ICMP echo request with a spoofed source IP 89 setfib 2 nping -c 1 -e ${TAP0} -S ${SPOOF_ADDR} \ 90 --source-mac ${SPOOF_MAC} --icmp --icmp-type "echo-request" \ 91 --icmp-code 0 --icmp-id 0xdead --icmp-seq 1 --data 0xbeef \ 92 ${ADDR1} 93 # For informational and debugging purposes only, look for the 94 # characteristic error message 95 dmesg | grep "llinfo.*${SPOOF_ADDR}" 96 # Check that the ARP entry exists 97 atf_check -o match:"${SPOOF_ADDR}.*expires" setfib 3 arp ${SPOOF_ADDR} 98} 99arpresolve_checks_interface_fib_cleanup() 100{ 101 for PID in `cat "processes_to_kill"`; do 102 kill $PID 103 done 104 cleanup_tap 105} 106 107 108# Regression test for kern/187549 109atf_test_case loopback_and_network_routes_on_nondefault_fib cleanup 110loopback_and_network_routes_on_nondefault_fib_head() 111{ 112 atf_set "descr" "When creating and deleting loopback routes, use the interface's fib" 113 atf_set "require.user" "root" 114 atf_set "require.config" "fibs" 115} 116 117loopback_and_network_routes_on_nondefault_fib_body() 118{ 119 atf_expect_fail "kern/187549 Host and network routes for a new interface appear in the wrong FIB" 120 # Configure the TAP interface to use an RFC5737 nonrouteable address 121 # and a non-default fib 122 ADDR="192.0.2.2" 123 SUBNET="192.0.2.0" 124 MASK="24" 125 126 # Check system configuration 127 if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then 128 atf_skip "This test requires net.add_addr_allfibs=0" 129 fi 130 get_fibs 1 131 132 # Configure a TAP interface 133 setup_tap ${FIB0} ${ADDR} ${MASK} 134 135 # Check whether the host route exists in only the correct FIB 136 setfib ${FIB0} netstat -rn -f inet | grep -q "^${ADDR}.*UHS.*lo0" 137 if [ 0 -ne $? ]; then 138 setfib ${FIB0} netstat -rn -f inet 139 atf_fail "Host route did not appear in the correct FIB" 140 fi 141 setfib 0 netstat -rn -f inet | grep -q "^${ADDR}.*UHS.*lo0" 142 if [ 0 -eq $? ]; then 143 setfib 0 netstat -rn -f inet 144 atf_fail "Host route appeared in the wrong FIB" 145 fi 146 147 # Check whether the network route exists in only the correct FIB 148 setfib ${FIB0} netstat -rn -f inet | \ 149 grep -q "^${SUBNET}/${MASK}.*${TAPD}" 150 if [ 0 -ne $? ]; then 151 setfib ${FIB0} netstat -rn -f inet 152 atf_fail "Network route did not appear in the correct FIB" 153 fi 154 setfib 0 netstat -rn -f inet | \ 155 grep -q "^${SUBNET}/${MASK}.*${TAPD}" 156 if [ 0 -eq $? ]; then 157 setfib ${FIB0} netstat -rn -f inet 158 atf_fail "Network route appeared in the wrong FIB" 159 fi 160} 161 162loopback_and_network_routes_on_nondefault_fib_cleanup() 163{ 164 cleanup_tap 165} 166 167 168# Regression test for kern/187552 169atf_test_case default_route_with_multiple_fibs_on_same_subnet cleanup 170default_route_with_multiple_fibs_on_same_subnet_head() 171{ 172 atf_set "descr" "Multiple interfaces on the same subnet but with different fibs can both have default routes" 173 atf_set "require.user" "root" 174 atf_set "require.config" "fibs" 175} 176 177default_route_with_multiple_fibs_on_same_subnet_body() 178{ 179 atf_expect_fail "kern/187552 default route uses the wrong interface when multiple interfaces have the same subnet but different fibs" 180 # Configure the TAP interfaces to use a RFC5737 nonrouteable addresses 181 # and a non-default fib 182 ADDR0="192.0.2.2" 183 ADDR1="192.0.2.3" 184 GATEWAY="192.0.2.1" 185 SUBNET="192.0.2.0" 186 MASK="24" 187 188 # Check system configuration 189 if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then 190 atf_skip "This test requires net.add_addr_allfibs=0" 191 fi 192 get_fibs 2 193 194 # Configure TAP interfaces 195 setup_tap "$FIB0" ${ADDR0} ${MASK} 196 TAP0=$TAP 197 setup_tap "$FIB1" ${ADDR1} ${MASK} 198 TAP1=$TAP 199 200 # Attempt to add default routes 201 setfib ${FIB0} route add default ${GATEWAY} 202 setfib ${FIB1} route add default ${GATEWAY} 203 204 # Verify that the default route exists for both fibs, with their 205 # respective interfaces. 206 atf_check -o match:"^default.*${TAP0}$" \ 207 setfib ${FIB0} netstat -rn -f inet 208 atf_check -o match:"^default.*${TAP1}$" \ 209 setfib ${FIB1} netstat -rn -f inet 210} 211 212default_route_with_multiple_fibs_on_same_subnet_cleanup() 213{ 214 cleanup_tap 215} 216 217 218# Regression test for kern/187550 219atf_test_case subnet_route_with_multiple_fibs_on_same_subnet cleanup 220subnet_route_with_multiple_fibs_on_same_subnet_head() 221{ 222 atf_set "descr" "Multiple FIBs can have subnet routes for the same subnet" 223 atf_set "require.user" "root" 224 atf_set "require.config" "fibs" 225} 226 227subnet_route_with_multiple_fibs_on_same_subnet_body() 228{ 229 atf_expect_fail "kern/187550 Multiple interfaces on different FIBs but the same subnet don't all have a subnet route" 230 # Configure the TAP interfaces to use a RFC5737 nonrouteable addresses 231 # and a non-default fib 232 ADDR0="192.0.2.2" 233 ADDR1="192.0.2.3" 234 SUBNET="192.0.2.0" 235 MASK="24" 236 237 # Check system configuration 238 if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then 239 atf_skip "This test requires net.add_addr_allfibs=0" 240 fi 241 get_fibs 2 242 243 # Configure TAP interfaces 244 setup_tap "$FIB0" ${ADDR0} ${MASK} 245 setup_tap "$FIB1" ${ADDR1} ${MASK} 246 247 # Check that a subnet route exists on both fibs 248 atf_check -o ignore setfib "$FIB0" route get $ADDR1 249 atf_check -o ignore setfib "$FIB1" route get $ADDR0 250} 251 252subnet_route_with_multiple_fibs_on_same_subnet_cleanup() 253{ 254 cleanup_tap 255} 256 257# Regression test for kern/187553 "Source address selection for UDP packets 258# with SO_DONTROUTE uses the default FIB". The original complaint was that a 259# UDP packet with SO_DONTROUTE set would select a source address from an 260# interface on the default FIB instead of the process FIB. 261# This bug was discovered with "setfib 1 netperf -t UDP_STREAM -H some_host" 262# Regression test for kern/187553 263 264# The root cause was that ifa_ifwithnet() did not have a fib argument. It 265# would return an address from an interface on any FIB that had a subnet route 266# for the destination. If more than one were available, it would choose the 267# most specific. The root cause is most easily tested by creating two 268# interfaces with overlapping subnet routes, adding a default route to the 269# interface with the less specific subnet route, and looking up a host that 270# requires the default route using the FIB of the interface with the less 271# specific subnet route. "route get" should provide a route that uses the 272# interface on the chosen FIB. However, absent the patch for this bug it will 273# instead use the other interface. 274atf_test_case src_addr_selection_by_subnet cleanup 275src_addr_selection_by_subnet_head() 276{ 277 atf_set "descr" "Source address selection for UDP packets with SO_DONTROUTE on non-default FIBs works" 278 atf_set "require.user" "root" 279 atf_set "require.config" "fibs" 280} 281 282src_addr_selection_by_subnet_body() 283{ 284 atf_expect_fail "kern/187553 Source address selection for UDP packets with SO_DONTROUTE uses the default FIB" 285 # Configure the TAP interface to use an RFC5737 nonrouteable address 286 # and a non-default fib 287 ADDR0="192.0.2.2" 288 ADDR1="192.0.2.3" 289 GATEWAY0="192.0.2.1" 290 TARGET="192.0.2.128" 291 SUBNET="192.0.2.0" 292 MASK0="25" 293 MASK1="26" 294 295 # Check system configuration 296 if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then 297 atf_skip "This test requires net.add_addr_allfibs=0" 298 fi 299 get_fibs 2 300 301 # Configure a TAP interface 302 setup_tap ${FIB0} ${ADDR0} ${MASK0} 303 TAP0=${TAP} 304 setup_tap ${FIB1} ${ADDR1} ${MASK1} 305 TAP1=${TAP} 306 307 # Add a gateway to the interface with the less specific subnet route 308 setfib ${FIB0} route add default ${GATEWAY0} 309 310 # Lookup a route 311 echo "Looking up route to ${TARGET} with fib ${FIB0}" 312 echo "Expected behavior is to use interface ${TAP0}" 313 atf_check -o match:"interface:.${TAP0}" setfib ${FIB0} route -n get ${TARGET} 314} 315 316src_addr_selection_by_subnet_cleanup() 317{ 318 cleanup_tap 319} 320 321 322atf_init_test_cases() 323{ 324 atf_add_test_case arpresolve_checks_interface_fib 325 atf_add_test_case loopback_and_network_routes_on_nondefault_fib 326 atf_add_test_case default_route_with_multiple_fibs_on_same_subnet 327 atf_add_test_case subnet_route_with_multiple_fibs_on_same_subnet 328 atf_add_test_case src_addr_selection_by_subnet 329} 330 331# Looks up one or more fibs from the configuration data and validates them. 332# Returns the results in the env varilables FIB0, FIB1, etc. 333 334# parameter numfibs The number of fibs to lookup 335get_fibs() 336{ 337 NUMFIBS=$1 338 net_fibs=`sysctl -n net.fibs` 339 i=0 340 while [ $i -lt "$NUMFIBS" ]; do 341 fib=`atf_config_get "fibs" | \ 342 awk -v i=$(( i + 1 )) '{print $i}'` 343 echo "fib is ${fib}" 344 eval FIB${i}=${fib} 345 if [ "$fib" -ge "$net_fibs" ]; then 346 atf_skip "The ${i}th configured fib is ${fib}, which is not less than net.fibs, which is ${net_fibs}" 347 fi 348 i=$(( $i + 1 )) 349 done 350} 351 352# Creates a new tap(4) interface, registers it for cleanup, and returns the 353# name via the environment variable TAP 354get_tap() 355{ 356 local TAPN=0 357 while ! ifconfig tap${TAPN} create > /dev/null 2>&1; do 358 if [ "$TAPN" -ge 8 ]; then 359 atf_skip "Could not create a tap(4) interface" 360 else 361 TAPN=$(($TAPN + 1)) 362 fi 363 done 364 local TAPD=tap${TAPN} 365 # Record the TAP device so we can clean it up later 366 echo ${TAPD} >> "tap_devices_to_cleanup" 367 TAP=${TAPD} 368} 369 370# Create a tap(4) interface, configure it, and register it for cleanup. 371# parameters: 372# fib 373# IP address 374# Netmask in number of bits (eg 24 or 8) 375# Return: the tap interface name as the env variable TAP 376setup_tap() 377{ 378 local FIB=$1 379 local ADDR=$2 380 local MASK=$3 381 get_tap 382 echo setfib ${FIB} ifconfig $TAP ${ADDR}/${MASK} fib $FIB 383 setfib ${FIB} ifconfig $TAP ${ADDR}/${MASK} fib $FIB 384} 385 386cleanup_tap() 387{ 388 for TAPD in `cat "tap_devices_to_cleanup"`; do 389 ifconfig ${TAPD} destroy 390 done 391} 392