fibs_test.sh revision 263445
1263445Sasomers#
2263445Sasomers#  Copyright (c) 2014 Spectra Logic Corporation
3263445Sasomers#  All rights reserved.
4263445Sasomers# 
5263445Sasomers#  Redistribution and use in source and binary forms, with or without
6263445Sasomers#  modification, are permitted provided that the following conditions
7263445Sasomers#  are met:
8263445Sasomers#  1. Redistributions of source code must retain the above copyright
9263445Sasomers#     notice, this list of conditions, and the following disclaimer,
10263445Sasomers#     without modification.
11263445Sasomers#  2. Redistributions in binary form must reproduce at minimum a disclaimer
12263445Sasomers#     substantially similar to the "NO WARRANTY" disclaimer below
13263445Sasomers#     ("Disclaimer") and any redistribution must be conditioned upon
14263445Sasomers#     including a substantially similar Disclaimer requirement for further
15263445Sasomers#     binary redistribution.
16263445Sasomers# 
17263445Sasomers#  NO WARRANTY
18263445Sasomers#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19263445Sasomers#  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20263445Sasomers#  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
21263445Sasomers#  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22263445Sasomers#  HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23263445Sasomers#  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24263445Sasomers#  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25263445Sasomers#  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26263445Sasomers#  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27263445Sasomers#  IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28263445Sasomers#  POSSIBILITY OF SUCH DAMAGES.
29263445Sasomers# 
30263445Sasomers#  Authors: Alan Somers         (Spectra Logic Corporation)
31263445Sasomers#
32263445Sasomers# $FreeBSD: head/tests/sys/netinet/fibs_test.sh 263445 2014-03-20 20:39:41Z asomers $
33263445Sasomers
34263445Sasomers# All of the tests in this file requires the test-suite config variable "fibs"
35263445Sasomers# to be defined to a space-delimited list of FIBs that may be used for testing.
36263445Sasomers
37263445Sasomers# arpresolve should check the interface fib for routes to a target when
38263445Sasomers# creating an ARP table entry.  This is a regression for kern/167947, where
39263445Sasomers# arpresolve only checked the default route.
40263445Sasomers#
41263445Sasomers# Outline:
42263445Sasomers# Create two tap(4) interfaces
43263445Sasomers# Simulate a crossover cable between them by using net/socat
44263445Sasomers# Use nping (from security/nmap) to send an ICMP echo request from one
45263445Sasomers# interface to the other, spoofing the source IP.  The source IP must be
46263445Sasomers# spoofed, or else it will already have an entry in the arp table. 
47263445Sasomers# Check whether an arp entry exists for the spoofed IP
48263445Sasomersatf_test_case arpresolve_checks_interface_fib cleanup
49263445Sasomersarpresolve_checks_interface_fib_head()
50263445Sasomers{
51263445Sasomers	atf_set "descr" "arpresolve should check the interface fib, not the default fib, for routes"
52263445Sasomers	atf_set "require.user" "root"
53263445Sasomers	atf_set "require.config" "fibs"
54263445Sasomers	atf_set "require.progs" "socat nping"
55263445Sasomers}
56263445Sasomersarpresolve_checks_interface_fib_body()
57263445Sasomers{
58263445Sasomers	atf_expect_fail "kern/167947 arpresolve checks only the default FIB for the interface route"
59263445Sasomers	# Configure the TAP interfaces to use a RFC5737 nonrouteable addresses
60263445Sasomers	# and a non-default fib
61263445Sasomers	ADDR0="192.0.2.2"
62263445Sasomers	ADDR1="192.0.2.3"
63263445Sasomers	SUBNET="192.0.2.0"
64263445Sasomers	# Due to bug TBD (regressed by multiple_fibs_on_same_subnet) we need
65263445Sasomers	# diffferent subnet masks, or FIB1 won't have a subnet route.
66263445Sasomers	MASK0="24"
67263445Sasomers	MASK1="25"
68263445Sasomers	# Spoof a MAC that is reserved per RFC7042
69263445Sasomers	SPOOF_ADDR="192.0.2.4"
70263445Sasomers	SPOOF_MAC="00:00:5E:00:53:00"
71263445Sasomers
72263445Sasomers	# Check system configuration
73263445Sasomers	if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then
74263445Sasomers		atf_skip "This test requires net.add_addr_allfibs=0"
75263445Sasomers	fi
76263445Sasomers	get_fibs 2
77263445Sasomers
78263445Sasomers	# Configure TAP interfaces
79263445Sasomers	setup_tap "$FIB0" ${ADDR0} ${MASK0}
80263445Sasomers	TAP0=$TAP
81263445Sasomers	setup_tap "$FIB1" ${ADDR1} ${MASK1}
82263445Sasomers	TAP1=$TAP
83263445Sasomers
84263445Sasomers	# Simulate a crossover cable
85263445Sasomers	socat /dev/${TAP0} /dev/${TAP1} &
86263445Sasomers	SOCAT_PID=$!
87263445Sasomers	echo ${SOCAT_PID} >> "processes_to_kill"
88263445Sasomers	
89263445Sasomers	# Send an ICMP echo request with a spoofed source IP
90263445Sasomers	setfib 2 nping -c 1 -e ${TAP0} -S ${SPOOF_ADDR} \
91263445Sasomers		--source-mac ${SPOOF_MAC} --icmp --icmp-type "echo-request" \
92263445Sasomers		--icmp-code 0 --icmp-id 0xdead --icmp-seq 1 --data 0xbeef \
93263445Sasomers		${ADDR1}
94263445Sasomers	# For informational and debugging purposes only, look for the
95263445Sasomers	# characteristic error message
96263445Sasomers	dmesg | grep "llinfo.*${SPOOF_ADDR}"
97263445Sasomers	# Check that the ARP entry exists
98263445Sasomers	atf_check -o match:"${SPOOF_ADDR}.*expires" setfib 3 arp ${SPOOF_ADDR}
99263445Sasomers}
100263445Sasomersarpresolve_checks_interface_fib_cleanup()
101263445Sasomers{
102263445Sasomers	for PID in `cat "processes_to_kill"`; do
103263445Sasomers		kill $PID
104263445Sasomers	done
105263445Sasomers	cleanup_tap
106263445Sasomers}
107263445Sasomers
108263445Sasomers
109263445Sasomers# Regression test for kern/187549
110263445Sasomersatf_test_case loopback_and_network_routes_on_nondefault_fib cleanup
111263445Sasomersloopback_and_network_routes_on_nondefault_fib_head()
112263445Sasomers{
113263445Sasomers	atf_set "descr" "When creating and deleting loopback routes, use the interface's fib"
114263445Sasomers	atf_set "require.user" "root"
115263445Sasomers	atf_set "require.config" "fibs"
116263445Sasomers}
117263445Sasomers
118263445Sasomersloopback_and_network_routes_on_nondefault_fib_body()
119263445Sasomers{
120263445Sasomers	atf_expect_fail "kern/187549 Host and network routes for a new interface appear in the wrong FIB"
121263445Sasomers	# Configure the TAP interface to use an RFC5737 nonrouteable address
122263445Sasomers	# and a non-default fib
123263445Sasomers	ADDR="192.0.2.2"
124263445Sasomers	SUBNET="192.0.2.0"
125263445Sasomers	MASK="24"
126263445Sasomers
127263445Sasomers	# Check system configuration
128263445Sasomers	if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then
129263445Sasomers		atf_skip "This test requires net.add_addr_allfibs=0"
130263445Sasomers	fi
131263445Sasomers	get_fibs 1
132263445Sasomers
133263445Sasomers	# Configure a TAP interface
134263445Sasomers	setup_tap ${FIB0} ${ADDR} ${MASK}
135263445Sasomers
136263445Sasomers	# Check whether the host route exists in only the correct FIB
137263445Sasomers	setfib ${FIB0} netstat -rn -f inet | grep -q "^${ADDR}.*UHS.*lo0"
138263445Sasomers	if [ 0 -ne $? ]; then
139263445Sasomers		setfib ${FIB0} netstat -rn -f inet
140263445Sasomers		atf_fail "Host route did not appear in the correct FIB"
141263445Sasomers	fi
142263445Sasomers	setfib 0 netstat -rn -f inet | grep -q "^${ADDR}.*UHS.*lo0"
143263445Sasomers	if [ 0 -eq $? ]; then
144263445Sasomers		setfib 0 netstat -rn -f inet
145263445Sasomers		atf_fail "Host route appeared in the wrong FIB"
146263445Sasomers	fi
147263445Sasomers
148263445Sasomers	# Check whether the network route exists in only the correct FIB
149263445Sasomers	setfib ${FIB0} netstat -rn -f inet | \
150263445Sasomers		grep -q "^${SUBNET}/${MASK}.*${TAPD}"
151263445Sasomers	if [ 0 -ne $? ]; then
152263445Sasomers		setfib ${FIB0} netstat -rn -f inet
153263445Sasomers		atf_fail "Network route did not appear in the correct FIB"
154263445Sasomers	fi
155263445Sasomers	setfib 0 netstat -rn -f inet | \
156263445Sasomers		grep -q "^${SUBNET}/${MASK}.*${TAPD}"
157263445Sasomers	if [ 0 -eq $? ]; then
158263445Sasomers		setfib ${FIB0} netstat -rn -f inet
159263445Sasomers		atf_fail "Network route appeared in the wrong FIB"
160263445Sasomers	fi
161263445Sasomers}
162263445Sasomers
163263445Sasomersloopback_and_network_routes_on_nondefault_fib_cleanup()
164263445Sasomers{
165263445Sasomers	cleanup_tap
166263445Sasomers}
167263445Sasomers
168263445Sasomers
169263445Sasomers# Regression test for kern/187552
170263445Sasomersatf_test_case default_route_with_multiple_fibs_on_same_subnet cleanup
171263445Sasomersdefault_route_with_multiple_fibs_on_same_subnet_head()
172263445Sasomers{
173263445Sasomers	atf_set "descr" "Multiple interfaces on the same subnet but with different fibs can both have default routes"
174263445Sasomers	atf_set "require.user" "root"
175263445Sasomers	atf_set "require.config" "fibs"
176263445Sasomers}
177263445Sasomers
178263445Sasomersdefault_route_with_multiple_fibs_on_same_subnet_body()
179263445Sasomers{
180263445Sasomers	atf_expect_fail "kern/187552 default route uses the wrong interface when multiple interfaces have the same subnet but different fibs"
181263445Sasomers	# Configure the TAP interfaces to use a RFC5737 nonrouteable addresses
182263445Sasomers	# and a non-default fib
183263445Sasomers	ADDR0="192.0.2.2"
184263445Sasomers	ADDR1="192.0.2.3"
185263445Sasomers	GATEWAY="192.0.2.1"
186263445Sasomers	SUBNET="192.0.2.0"
187263445Sasomers	MASK="24"
188263445Sasomers
189263445Sasomers	# Check system configuration
190263445Sasomers	if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then
191263445Sasomers		atf_skip "This test requires net.add_addr_allfibs=0"
192263445Sasomers	fi
193263445Sasomers	get_fibs 2
194263445Sasomers
195263445Sasomers	# Configure TAP interfaces
196263445Sasomers	setup_tap "$FIB0" ${ADDR0} ${MASK}
197263445Sasomers	TAP0=$TAP
198263445Sasomers	setup_tap "$FIB1" ${ADDR1} ${MASK}
199263445Sasomers	TAP1=$TAP
200263445Sasomers
201263445Sasomers	# Attempt to add default routes
202263445Sasomers	setfib ${FIB0} route add default ${GATEWAY}
203263445Sasomers	setfib ${FIB1} route add default ${GATEWAY}
204263445Sasomers
205263445Sasomers	# Verify that the default route exists for both fibs, with their
206263445Sasomers	# respective interfaces.
207263445Sasomers	atf_check -o match:"^default.*${TAP0}$" \
208263445Sasomers		setfib ${FIB0} netstat -rn -f inet
209263445Sasomers	atf_check -o match:"^default.*${TAP1}$" \
210263445Sasomers		setfib ${FIB1} netstat -rn -f inet
211263445Sasomers}
212263445Sasomers
213263445Sasomersdefault_route_with_multiple_fibs_on_same_subnet_cleanup()
214263445Sasomers{
215263445Sasomers	cleanup_tap
216263445Sasomers}
217263445Sasomers
218263445Sasomers
219263445Sasomers# Regression test for kern/187550
220263445Sasomersatf_test_case subnet_route_with_multiple_fibs_on_same_subnet cleanup
221263445Sasomerssubnet_route_with_multiple_fibs_on_same_subnet_head()
222263445Sasomers{
223263445Sasomers	atf_set "descr" "Multiple FIBs can have subnet routes for the same subnet"
224263445Sasomers	atf_set "require.user" "root"
225263445Sasomers	atf_set "require.config" "fibs"
226263445Sasomers}
227263445Sasomers
228263445Sasomerssubnet_route_with_multiple_fibs_on_same_subnet_body()
229263445Sasomers{
230263445Sasomers	atf_expect_fail "kern/187550 Multiple interfaces on different FIBs but the same subnet don't all have a subnet route"
231263445Sasomers	# Configure the TAP interfaces to use a RFC5737 nonrouteable addresses
232263445Sasomers	# and a non-default fib
233263445Sasomers	ADDR0="192.0.2.2"
234263445Sasomers	ADDR1="192.0.2.3"
235263445Sasomers	SUBNET="192.0.2.0"
236263445Sasomers	MASK="24"
237263445Sasomers
238263445Sasomers	# Check system configuration
239263445Sasomers	if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then
240263445Sasomers		atf_skip "This test requires net.add_addr_allfibs=0"
241263445Sasomers	fi
242263445Sasomers	get_fibs 2
243263445Sasomers
244263445Sasomers	# Configure TAP interfaces
245263445Sasomers	setup_tap "$FIB0" ${ADDR0} ${MASK}
246263445Sasomers	setup_tap "$FIB1" ${ADDR1} ${MASK}
247263445Sasomers
248263445Sasomers	# Check that a subnet route exists on both fibs
249263445Sasomers	atf_check -o ignore setfib "$FIB0" route get $ADDR1
250263445Sasomers	atf_check -o ignore setfib "$FIB1" route get $ADDR0
251263445Sasomers}
252263445Sasomers
253263445Sasomerssubnet_route_with_multiple_fibs_on_same_subnet_cleanup()
254263445Sasomers{
255263445Sasomers	cleanup_tap
256263445Sasomers}
257263445Sasomers
258263445Sasomers# Test that source address selection works correctly for UDP packets with
259263445Sasomers# SO_DONTROUTE set that are sent on non-default FIBs.
260263445Sasomers# This bug was discovered with "setfib 1 netperf -t UDP_STREAM -H some_host"
261263445Sasomers# Regression test for kern/187553
262263445Sasomersatf_test_case udp_dontroute cleanup
263263445Sasomersudp_dontroute_head()
264263445Sasomers{
265263445Sasomers	atf_set "descr" "Source address selection for UDP packets with SO_DONTROUTE on non-default FIBs works"
266263445Sasomers	atf_set "require.user" "root"
267263445Sasomers	atf_set "require.config" "fibs"
268263445Sasomers}
269263445Sasomers
270263445Sasomersudp_dontroute_body()
271263445Sasomers{
272263445Sasomers	atf_expect_fail "kern/187553 Source address selection for UDP packets with SO_DONTROUTE uses the default FIB"
273263445Sasomers	# Configure the TAP interface to use an RFC5737 nonrouteable address
274263445Sasomers	# and a non-default fib
275263445Sasomers	ADDR="192.0.2.2"
276263445Sasomers	SUBNET="192.0.2.0"
277263445Sasomers	MASK="24"
278263445Sasomers	# Use a different IP on the same subnet as the target
279263445Sasomers	TARGET="192.0.2.100"
280263445Sasomers
281263445Sasomers	# Check system configuration
282263445Sasomers	if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then
283263445Sasomers		atf_skip "This test requires net.add_addr_allfibs=0"
284263445Sasomers	fi
285263445Sasomers	get_fibs 1
286263445Sasomers
287263445Sasomers	# Configure a TAP interface
288263445Sasomers	setup_tap ${FIB0} ${ADDR} ${MASK}
289263445Sasomers
290263445Sasomers	# Send a UDP packet with SO_DONTROUTE.  In the failure case, it will
291263445Sasomers	# return ENETUNREACH
292263445Sasomers	SRCDIR=`atf_get_srcdir`
293263445Sasomers	atf_check -o ignore setfib ${FIB0} ${SRCDIR}/udp_dontroute ${TARGET}
294263445Sasomers}
295263445Sasomers
296263445Sasomersudp_dontroute_cleanup()
297263445Sasomers{
298263445Sasomers	cleanup_tap
299263445Sasomers}
300263445Sasomers
301263445Sasomers
302263445Sasomersatf_init_test_cases()
303263445Sasomers{
304263445Sasomers	atf_add_test_case arpresolve_checks_interface_fib
305263445Sasomers	atf_add_test_case loopback_and_network_routes_on_nondefault_fib 
306263445Sasomers	atf_add_test_case default_route_with_multiple_fibs_on_same_subnet 
307263445Sasomers	atf_add_test_case subnet_route_with_multiple_fibs_on_same_subnet 
308263445Sasomers	atf_add_test_case udp_dontroute
309263445Sasomers}
310263445Sasomers
311263445Sasomers# Looks up one or more fibs from the configuration data and validates them.
312263445Sasomers# Returns the results in the env varilables FIB0, FIB1, etc.
313263445Sasomers
314263445Sasomers# parameter numfibs	The number of fibs to lookup
315263445Sasomersget_fibs()
316263445Sasomers{
317263445Sasomers	NUMFIBS=$1
318263445Sasomers	net_fibs=`sysctl -n net.fibs`
319263445Sasomers	i=0
320263445Sasomers	while [ $i -lt "$NUMFIBS" ]; do
321263445Sasomers		fib=`atf_config_get "fibs" | \
322263445Sasomers			awk -v i=$(( i + 1 )) '{print $i}'`
323263445Sasomers		echo "fib is ${fib}"
324263445Sasomers		eval FIB${i}=${fib}
325263445Sasomers		if [ "$fib" -ge "$net_fibs" ]; then
326263445Sasomers			atf_skip "The ${i}th configured fib is ${fib}, which is not less than net.fibs, which is ${net_fibs}"
327263445Sasomers		fi
328263445Sasomers		i=$(( $i + 1 ))
329263445Sasomers	done
330263445Sasomers}
331263445Sasomers
332263445Sasomers# Creates a new tap(4) interface, registers it for cleanup, and returns the
333263445Sasomers# name via the environment variable TAP
334263445Sasomersget_tap()
335263445Sasomers{
336263445Sasomers	local TAPN=0
337263445Sasomers	while ! ifconfig tap${TAPN} create > /dev/null 2>&1; do
338263445Sasomers		if [ "$TAPN" -ge 8 ]; then
339263445Sasomers			atf_skip "Could not create a tap(4) interface"
340263445Sasomers		else
341263445Sasomers			TAPN=$(($TAPN + 1))
342263445Sasomers		fi
343263445Sasomers	done
344263445Sasomers	local TAPD=tap${TAPN}
345263445Sasomers	# Record the TAP device so we can clean it up later
346263445Sasomers	echo ${TAPD} >> "tap_devices_to_cleanup"
347263445Sasomers	TAP=${TAPD}
348263445Sasomers}
349263445Sasomers
350263445Sasomers# Create a tap(4) interface, configure it, and register it for cleanup.
351263445Sasomers# parameters:
352263445Sasomers# fib
353263445Sasomers# IP address
354263445Sasomers# Netmask in number of bits (eg 24 or 8)
355263445Sasomers# Return: the tap interface name as the env variable TAP
356263445Sasomerssetup_tap()
357263445Sasomers{
358263445Sasomers	local FIB=$1
359263445Sasomers	local ADDR=$2
360263445Sasomers	local MASK=$3
361263445Sasomers	get_tap
362263445Sasomers	echo setfib ${FIB} ifconfig $TAP ${ADDR}/${MASK} fib $FIB
363263445Sasomers	setfib ${FIB} ifconfig $TAP ${ADDR}/${MASK} fib $FIB
364263445Sasomers}
365263445Sasomers
366263445Sasomerscleanup_tap()
367263445Sasomers{
368263445Sasomers	for TAPD in `cat "tap_devices_to_cleanup"`; do
369263445Sasomers		ifconfig ${TAPD} destroy
370263445Sasomers	done
371263445Sasomers}
372