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