xref: /freebsd/tests/sys/netinet/fibs_test.sh (revision 93a065e7496dfbfbd0a5b0208ef763f37ea975c7)
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$
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" inet ${ADDR0} ${MASK0}
79	TAP0=$TAP
80	setup_tap "$FIB1" inet ${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	if [ -f processes_to_kill ]; then
102		for pid in $(cat processes_to_kill); do
103			kill "${pid}"
104		done
105		rm -f processes_to_kill
106	fi
107	cleanup_tap
108}
109
110
111# Regression test for kern/187549
112atf_test_case loopback_and_network_routes_on_nondefault_fib cleanup
113loopback_and_network_routes_on_nondefault_fib_head()
114{
115	atf_set "descr" "When creating and deleting loopback IPv4 routes, use the interface's fib"
116	atf_set "require.user" "root"
117	atf_set "require.config" "fibs"
118}
119
120loopback_and_network_routes_on_nondefault_fib_body()
121{
122	# Configure the TAP interface to use an RFC5737 nonrouteable address
123	# and a non-default fib
124	ADDR="192.0.2.2"
125	SUBNET="192.0.2.0"
126	MASK="24"
127
128	# Check system configuration
129	if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then
130		atf_skip "This test requires net.add_addr_allfibs=0"
131	fi
132	get_fibs 1
133
134	# Configure a TAP interface
135	setup_tap ${FIB0} inet ${ADDR} ${MASK}
136
137	# Check whether the host route exists in only the correct FIB
138	setfib ${FIB0} netstat -rn -f inet | grep -q "^${ADDR}.*UHS.*lo0"
139	if [ 0 -ne $? ]; then
140		setfib ${FIB0} netstat -rn -f inet
141		atf_fail "Host route did not appear in the correct FIB"
142	fi
143	setfib 0 netstat -rn -f inet | grep -q "^${ADDR}.*UHS.*lo0"
144	if [ 0 -eq $? ]; then
145		setfib 0 netstat -rn -f inet
146		atf_fail "Host route appeared in the wrong FIB"
147	fi
148
149	# Check whether the network route exists in only the correct FIB
150	setfib ${FIB0} netstat -rn -f inet | \
151		grep -q "^${SUBNET}/${MASK}.*${TAPD}"
152	if [ 0 -ne $? ]; then
153		setfib ${FIB0} netstat -rn -f inet
154		atf_fail "Network route did not appear in the correct FIB"
155	fi
156	setfib 0 netstat -rn -f inet | \
157		grep -q "^${SUBNET}/${MASK}.*${TAPD}"
158	if [ 0 -eq $? ]; then
159		setfib 0 netstat -rn -f inet
160		atf_fail "Network route appeared in the wrong FIB"
161	fi
162}
163
164loopback_and_network_routes_on_nondefault_fib_cleanup()
165{
166	cleanup_tap
167}
168
169atf_test_case loopback_and_network_routes_on_nondefault_fib_inet6 cleanup
170loopback_and_network_routes_on_nondefault_fib_inet6_head()
171{
172	atf_set "descr" "When creating and deleting loopback IPv6 routes, use the interface's fib"
173	atf_set "require.user" "root"
174	atf_set "require.config" "fibs"
175}
176
177loopback_and_network_routes_on_nondefault_fib_inet6_body()
178{
179	atf_expect_fail "PR196361 IPv6 network routes don't respect net.add_addr_allfibs=0"
180	# Configure the TAP interface to use a nonrouteable RFC3849
181	# address and a non-default fib
182	ADDR="2001:db8::2"
183	SUBNET="2001:db8::"
184	MASK="64"
185
186	# Check system configuration
187	if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then
188		atf_skip "This test requires net.add_addr_allfibs=0"
189	fi
190	get_fibs 1
191
192	# Configure a TAP interface
193	setup_tap ${FIB0} inet6 ${ADDR} ${MASK}
194
195	# Check whether the host route exists in only the correct FIB
196	setfib ${FIB0} netstat -rn -f inet6 | grep -q "^${ADDR}.*UHS.*lo0"
197	if [ 0 -ne $? ]; then
198		setfib ${FIB0} netstat -rn -f inet6
199		atf_fail "Host route did not appear in the correct FIB"
200	fi
201	setfib 0 netstat -rn -f inet6 | grep -q "^${ADDR}.*UHS.*lo0"
202	if [ 0 -eq $? ]; then
203		setfib 0 netstat -rn -f inet6
204		atf_fail "Host route appeared in the wrong FIB"
205	fi
206
207	# Check whether the network route exists in only the correct FIB
208	setfib ${FIB0} netstat -rn -f inet6 | \
209		grep -q "^${SUBNET}/${MASK}.*${TAPD}"
210	if [ 0 -ne $? ]; then
211		setfib ${FIB0} netstat -rn -f inet6
212		atf_fail "Network route did not appear in the correct FIB"
213	fi
214	setfib 0 netstat -rn -f inet6 | \
215		grep -q "^${SUBNET}/${MASK}.*${TAPD}"
216	if [ 0 -eq $? ]; then
217		setfib 0 netstat -rn -f inet6
218		atf_fail "Network route appeared in the wrong FIB"
219	fi
220}
221
222loopback_and_network_routes_on_nondefault_fib_inet6_cleanup()
223{
224	cleanup_tap
225}
226
227
228# Regression test for kern/187552
229atf_test_case default_route_with_multiple_fibs_on_same_subnet cleanup
230default_route_with_multiple_fibs_on_same_subnet_head()
231{
232	atf_set "descr" "Multiple interfaces on the same subnet but with different fibs can both have default IPv4 routes"
233	atf_set "require.user" "root"
234	atf_set "require.config" "fibs"
235}
236
237default_route_with_multiple_fibs_on_same_subnet_body()
238{
239	# Configure the TAP interfaces to use a RFC5737 nonrouteable addresses
240	# and a non-default fib
241	ADDR0="192.0.2.2"
242	ADDR1="192.0.2.3"
243	GATEWAY="192.0.2.1"
244	SUBNET="192.0.2.0"
245	MASK="24"
246
247	# Check system configuration
248	if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then
249		atf_skip "This test requires net.add_addr_allfibs=0"
250	fi
251	get_fibs 2
252
253	# Configure TAP interfaces
254	setup_tap "$FIB0" inet ${ADDR0} ${MASK}
255	TAP0=$TAP
256	setup_tap "$FIB1" inet ${ADDR1} ${MASK}
257	TAP1=$TAP
258
259	# Attempt to add default routes
260	setfib ${FIB0} route add default ${GATEWAY}
261	setfib ${FIB1} route add default ${GATEWAY}
262
263	# Verify that the default route exists for both fibs, with their
264	# respective interfaces.
265	atf_check -o match:"^default.*${TAP0}$" \
266		setfib ${FIB0} netstat -rn -f inet
267	atf_check -o match:"^default.*${TAP1}$" \
268		setfib ${FIB1} netstat -rn -f inet
269}
270
271default_route_with_multiple_fibs_on_same_subnet_cleanup()
272{
273	cleanup_tap
274}
275
276atf_test_case default_route_with_multiple_fibs_on_same_subnet_inet6 cleanup
277default_route_with_multiple_fibs_on_same_subnet_inet6_head()
278{
279	atf_set "descr" "Multiple interfaces on the same subnet but with different fibs can both have default IPv6 routes"
280	atf_set "require.user" "root"
281	atf_set "require.config" "fibs"
282}
283
284default_route_with_multiple_fibs_on_same_subnet_inet6_body()
285{
286	# Configure the TAP interfaces to use nonrouteable RFC3849
287	# addresses and non-default FIBs
288	ADDR0="2001:db8::2"
289	ADDR1="2001:db8::3"
290	GATEWAY="2001:db8::1"
291	SUBNET="2001:db8::"
292	MASK="64"
293
294	# Check system configuration
295	if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then
296		atf_skip "This test requires net.add_addr_allfibs=0"
297	fi
298	get_fibs 2
299
300	# Configure TAP interfaces
301	setup_tap "$FIB0" inet6 ${ADDR0} ${MASK}
302	TAP0=$TAP
303	setup_tap "$FIB1" inet6 ${ADDR1} ${MASK}
304	TAP1=$TAP
305
306	# Attempt to add default routes
307	setfib ${FIB0} route -6 add default ${GATEWAY}
308	setfib ${FIB1} route -6 add default ${GATEWAY}
309
310	# Verify that the default route exists for both fibs, with their
311	# respective interfaces.
312	atf_check -o match:"^default.*${TAP0}$" \
313		setfib ${FIB0} netstat -rn -f inet6
314	atf_check -o match:"^default.*${TAP1}$" \
315		setfib ${FIB1} netstat -rn -f inet6
316}
317
318default_route_with_multiple_fibs_on_same_subnet_inet6_cleanup()
319{
320	cleanup_tap
321}
322
323
324# Regression test for PR kern/189089
325# Create two tap interfaces and assign them both the same IP address but with
326# different netmasks, and both on the default FIB.  Then remove one's IP
327# address.  Hopefully the machine won't panic.
328atf_test_case same_ip_multiple_ifaces_fib0 cleanup
329same_ip_multiple_ifaces_fib0_head()
330{
331	atf_set "descr" "Can remove an IPv4 alias from an interface when the same IPv4 is also assigned to another interface."
332	atf_set "require.user" "root"
333	atf_set "require.config" "fibs"
334}
335same_ip_multiple_ifaces_fib0_body()
336{
337	ADDR="192.0.2.2"
338	MASK0="24"
339	MASK1="32"
340
341	# Unlike most of the tests in this file, this is applicable regardless
342	# of net.add_addr_allfibs
343
344	# Setup the interfaces, then remove one alias.  It should not panic.
345	setup_tap 0 inet ${ADDR} ${MASK0}
346	TAP0=${TAP}
347	setup_tap 0 inet ${ADDR} ${MASK1}
348	TAP1=${TAP}
349	ifconfig ${TAP1} -alias ${ADDR}
350
351	# Do it again, in the opposite order.  It should not panic.
352	setup_tap 0 inet ${ADDR} ${MASK0}
353	TAP0=${TAP}
354	setup_tap 0 inet ${ADDR} ${MASK1}
355	TAP1=${TAP}
356	ifconfig ${TAP0} -alias ${ADDR}
357}
358same_ip_multiple_ifaces_fib0_cleanup()
359{
360	cleanup_tap
361}
362
363# Regression test for PR kern/189088
364# Test that removing an IP address works even if the same IP is assigned to a
365# different interface, on a different FIB.  Tests the same code that whose
366# panic was regressed by same_ip_multiple_ifaces_fib0.
367# Create two tap interfaces and assign them both the same IP address but with
368# different netmasks, and on different FIBs.  Then remove one's IP
369# address.  Hopefully the machine won't panic.  Also, the IP's hostroute should
370# dissappear from the correct fib.
371atf_test_case same_ip_multiple_ifaces cleanup
372same_ip_multiple_ifaces_head()
373{
374	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."
375	atf_set "require.user" "root"
376	atf_set "require.config" "fibs"
377}
378same_ip_multiple_ifaces_body()
379{
380	atf_expect_fail "kern/189088 Assigning the same IP to multiple interfaces in different FIBs creates a host route for only one"
381	ADDR="192.0.2.2"
382	MASK0="24"
383	MASK1="32"
384
385	# Unlike most of the tests in this file, this is applicable regardless
386	# of net.add_addr_allfibs
387	get_fibs 2
388
389	# Setup the interfaces, then remove one alias.  It should not panic.
390	setup_tap ${FIB0} inet ${ADDR} ${MASK0}
391	TAP0=${TAP}
392	setup_tap ${FIB1} inet ${ADDR} ${MASK1}
393	TAP1=${TAP}
394	ifconfig ${TAP1} -alias ${ADDR}
395	atf_check -o not-match:"^${ADDR}[[:space:]]" \
396		setfib ${FIB1} netstat -rn -f inet
397
398	# Do it again, in the opposite order.  It should not panic.
399	setup_tap ${FIB0} inet ${ADDR} ${MASK0}
400	TAP0=${TAP}
401	setup_tap ${FIB1} inet ${ADDR} ${MASK1}
402	TAP1=${TAP}
403	ifconfig ${TAP0} -alias ${ADDR}
404	atf_check -o not-match:"^${ADDR}[[:space:]]" \
405		setfib ${FIB0} netstat -rn -f inet
406}
407same_ip_multiple_ifaces_cleanup()
408{
409	# Due to PR kern/189088, we must destroy the interfaces in LIFO order
410	# in order for the routes to be correctly cleaned up.
411	for TAPD in `tail -r "tap_devices_to_cleanup"`; do
412		echo ifconfig ${TAPD} destroy
413		ifconfig ${TAPD} destroy
414	done
415}
416
417atf_test_case same_ip_multiple_ifaces_inet6 cleanup
418same_ip_multiple_ifaces_inet6_head()
419{
420	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."
421	atf_set "require.user" "root"
422	atf_set "require.config" "fibs"
423}
424same_ip_multiple_ifaces_inet6_body()
425{
426	ADDR="2001:db8::2"
427	MASK0="64"
428	MASK1="128"
429
430	# Unlike most of the tests in this file, this is applicable regardless
431	# of net.add_addr_allfibs
432	get_fibs 2
433
434	# Setup the interfaces, then remove one alias.  It should not panic.
435	setup_tap ${FIB0} inet6 ${ADDR} ${MASK0}
436	TAP0=${TAP}
437	setup_tap ${FIB1} inet6 ${ADDR} ${MASK1}
438	TAP1=${TAP}
439	atf_check -s exit:0 ifconfig ${TAP1} inet6 ${ADDR} -alias
440	atf_check -o not-match:"^${ADDR}[[:space:]]" \
441		setfib ${FIB1} netstat -rn -f inet6
442	ifconfig ${TAP1} destroy
443	ifconfig ${TAP0} destroy
444
445	# Do it again, in the opposite order.  It should not panic.
446	setup_tap ${FIB0} inet6 ${ADDR} ${MASK0}
447	TAP0=${TAP}
448	setup_tap ${FIB1} inet6 ${ADDR} ${MASK1}
449	TAP1=${TAP}
450	atf_check -s exit:0 ifconfig ${TAP0} inet6 ${ADDR} -alias
451	atf_check -o not-match:"^${ADDR}[[:space:]]" \
452		setfib ${FIB0} netstat -rn -f inet6
453}
454same_ip_multiple_ifaces_inet6_cleanup()
455{
456	cleanup_tap
457}
458
459# Regression test for kern/187550
460atf_test_case subnet_route_with_multiple_fibs_on_same_subnet cleanup
461subnet_route_with_multiple_fibs_on_same_subnet_head()
462{
463	atf_set "descr" "Multiple FIBs can have IPv4 subnet routes for the same subnet"
464	atf_set "require.user" "root"
465	atf_set "require.config" "fibs"
466}
467
468subnet_route_with_multiple_fibs_on_same_subnet_body()
469{
470	# Configure the TAP interfaces to use a RFC5737 nonrouteable addresses
471	# and a non-default fib
472	ADDR0="192.0.2.2"
473	ADDR1="192.0.2.3"
474	SUBNET="192.0.2.0"
475	MASK="24"
476
477	# Check system configuration
478	if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then
479		atf_skip "This test requires net.add_addr_allfibs=0"
480	fi
481	get_fibs 2
482
483	# Configure TAP interfaces
484	setup_tap "$FIB0" inet ${ADDR0} ${MASK}
485	setup_tap "$FIB1" inet ${ADDR1} ${MASK}
486
487	# Check that a subnet route exists on both fibs
488	atf_check -o ignore setfib "$FIB0" route get $ADDR1
489	atf_check -o ignore setfib "$FIB1" route get $ADDR0
490}
491
492subnet_route_with_multiple_fibs_on_same_subnet_cleanup()
493{
494	cleanup_tap
495}
496
497atf_test_case subnet_route_with_multiple_fibs_on_same_subnet_inet6 cleanup
498subnet_route_with_multiple_fibs_on_same_subnet_inet6_head()
499{
500	atf_set "descr" "Multiple FIBs can have IPv6 subnet routes for the same subnet"
501	atf_set "require.user" "root"
502	atf_set "require.config" "fibs"
503}
504
505subnet_route_with_multiple_fibs_on_same_subnet_inet6_body()
506{
507	# Configure the TAP interfaces to use a RFC3849 nonrouteable addresses
508	# and a non-default fib
509	ADDR0="2001:db8::2"
510	ADDR1="2001:db8::3"
511	SUBNET="2001:db8::"
512	MASK="64"
513
514	# Check system configuration
515	if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then
516		atf_skip "This test requires net.add_addr_allfibs=0"
517	fi
518	get_fibs 2
519
520	# Configure TAP interfaces
521	setup_tap "$FIB0" inet6 ${ADDR0} ${MASK}
522	setup_tap "$FIB1" inet6 ${ADDR1} ${MASK}
523
524	# Check that a subnet route exists on both fibs
525	atf_check -o ignore setfib "$FIB0" route -6 get $ADDR1
526	atf_check -o ignore setfib "$FIB1" route -6 get $ADDR0
527}
528
529subnet_route_with_multiple_fibs_on_same_subnet_inet6_cleanup()
530{
531	cleanup_tap
532}
533
534# Test that source address selection works correctly for UDP packets with
535# SO_DONTROUTE set that are sent on non-default FIBs.
536# This bug was discovered with "setfib 1 netperf -t UDP_STREAM -H some_host"
537# Regression test for kern/187553
538#
539# The root cause was that ifa_ifwithnet() did not have a fib argument.  It
540# would return an address from an interface on any FIB that had a subnet route
541# for the destination.  If more than one were available, it would choose the
542# most specific.  This is most easily tested by creating a FIB without a
543# default route, then trying to send a UDP packet with SO_DONTROUTE set to an
544# address which is not routable on that FIB.  Absent the fix for this bug,
545# in_pcbladdr would choose an interface on any FIB with a default route.  With
546# the fix, you will get EUNREACH or ENETUNREACH.
547atf_test_case udp_dontroute cleanup
548udp_dontroute_head()
549{
550	atf_set "descr" "Source address selection for UDP packets with SO_DONTROUTE on non-default FIBs works"
551	atf_set "require.user" "root"
552	atf_set "require.config" "fibs"
553}
554
555udp_dontroute_body()
556{
557	# Configure the TAP interface to use an RFC5737 nonrouteable address
558	# and a non-default fib
559	ADDR0="192.0.2.2"
560	ADDR1="192.0.2.3"
561	SUBNET="192.0.2.0"
562	MASK="24"
563	# Use a different IP on the same subnet as the target
564	TARGET="192.0.2.100"
565	SRCDIR=`atf_get_srcdir`
566
567	# Check system configuration
568	if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then
569		atf_skip "This test requires net.add_addr_allfibs=0"
570	fi
571	get_fibs 2
572
573	# Configure the TAP interfaces
574	setup_tap ${FIB0} inet ${ADDR0} ${MASK}
575	TARGET_TAP=${TAP}
576	setup_tap ${FIB1} inet ${ADDR1} ${MASK}
577
578	# Send a UDP packet with SO_DONTROUTE.  In the failure case, it will
579	# return ENETUNREACH, or send the packet to the wrong tap
580	atf_check -o ignore setfib ${FIB0} \
581		${SRCDIR}/udp_dontroute ${TARGET} /dev/${TARGET_TAP}
582	cleanup_tap
583
584	# Repeat, but this time target the other tap
585	setup_tap ${FIB0} inet ${ADDR0} ${MASK}
586	setup_tap ${FIB1} inet ${ADDR1} ${MASK}
587	TARGET_TAP=${TAP}
588
589	atf_check -o ignore setfib ${FIB1} \
590		${SRCDIR}/udp_dontroute ${TARGET} /dev/${TARGET_TAP}
591}
592
593udp_dontroute_cleanup()
594{
595	cleanup_tap
596}
597
598
599atf_init_test_cases()
600{
601	atf_add_test_case arpresolve_checks_interface_fib
602	atf_add_test_case loopback_and_network_routes_on_nondefault_fib
603	atf_add_test_case loopback_and_network_routes_on_nondefault_fib_inet6
604	atf_add_test_case default_route_with_multiple_fibs_on_same_subnet
605	atf_add_test_case default_route_with_multiple_fibs_on_same_subnet_inet6
606	atf_add_test_case same_ip_multiple_ifaces_fib0
607	atf_add_test_case same_ip_multiple_ifaces
608	atf_add_test_case same_ip_multiple_ifaces_inet6
609	atf_add_test_case subnet_route_with_multiple_fibs_on_same_subnet
610	atf_add_test_case subnet_route_with_multiple_fibs_on_same_subnet_inet6
611	atf_add_test_case udp_dontroute
612}
613
614# Looks up one or more fibs from the configuration data and validates them.
615# Returns the results in the env varilables FIB0, FIB1, etc.
616
617# parameter numfibs	The number of fibs to lookup
618get_fibs()
619{
620	NUMFIBS=$1
621	net_fibs=`sysctl -n net.fibs`
622	i=0
623	while [ $i -lt "$NUMFIBS" ]; do
624		fib=`atf_config_get "fibs" | \
625			awk -v i=$(( i + 1 )) '{print $i}'`
626		echo "fib is ${fib}"
627		eval FIB${i}=${fib}
628		if [ "$fib" -ge "$net_fibs" ]; then
629			atf_skip "The ${i}th configured fib is ${fib}, which is not less than net.fibs, which is ${net_fibs}"
630		fi
631		i=$(( $i + 1 ))
632	done
633}
634
635# Creates a new tap(4) interface, registers it for cleanup, and returns the
636# name via the environment variable TAP
637get_tap()
638{
639	local TAPN=0
640	while ! ifconfig tap${TAPN} create > /dev/null 2>&1; do
641		if [ "$TAPN" -ge 8 ]; then
642			atf_skip "Could not create a tap(4) interface"
643		else
644			TAPN=$(($TAPN + 1))
645		fi
646	done
647	local TAPD=tap${TAPN}
648	# Record the TAP device so we can clean it up later
649	echo ${TAPD} >> "tap_devices_to_cleanup"
650	TAP=${TAPD}
651}
652
653# Create a tap(4) interface, configure it, and register it for cleanup.
654# parameters:
655# fib
656# Protocol (inet or inet6)
657# IP address
658# Netmask in number of bits (eg 24 or 8)
659# Return: the tap interface name as the env variable TAP
660setup_tap()
661{
662	local FIB=$1
663	local PROTO=$2
664	local ADDR=$3
665	local MASK=$4
666	get_tap
667	echo setfib ${FIB} ifconfig $TAP ${PROTO} ${ADDR}/${MASK} fib $FIB
668	setfib ${FIB} ifconfig $TAP ${PROTO} ${ADDR}/${MASK} fib $FIB
669}
670
671cleanup_tap()
672{
673	if [ -f tap_devices_to_cleanup ]; then
674		for tap_device in $(cat tap_devices_to_cleanup); do
675			echo ifconfig "${tap_device}" destroy
676			ifconfig "${tap_device}" destroy 2>/dev/null || true
677		done
678		rm -f tap_devices_to_cleanup
679	fi
680}
681