]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tests/sys/netinet/fibs_test.sh
Merge in changes from ^/vendor/NetBSD/tests/dist@r313245
[FreeBSD/FreeBSD.git] / tests / sys / netinet / fibs_test.sh
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
48 atf_test_case arpresolve_checks_interface_fib cleanup
49 arpresolve_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 }
56 arpresolve_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 }
99 arpresolve_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
112 atf_test_case loopback_and_network_routes_on_nondefault_fib cleanup
113 loopback_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
120 loopback_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
164 loopback_and_network_routes_on_nondefault_fib_cleanup()
165 {
166         cleanup_tap
167 }
168
169 atf_test_case loopback_and_network_routes_on_nondefault_fib_inet6 cleanup
170 loopback_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
177 loopback_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
222 loopback_and_network_routes_on_nondefault_fib_inet6_cleanup()
223 {
224         cleanup_tap
225 }
226
227
228 # Regression test for kern/187552
229 atf_test_case default_route_with_multiple_fibs_on_same_subnet cleanup
230 default_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
237 default_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
271 default_route_with_multiple_fibs_on_same_subnet_cleanup()
272 {
273         cleanup_tap
274 }
275
276 atf_test_case default_route_with_multiple_fibs_on_same_subnet_inet6 cleanup
277 default_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
284 default_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
318 default_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.
328 atf_test_case same_ip_multiple_ifaces_fib0 cleanup
329 same_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 }
335 same_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 }
358 same_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.
371 atf_test_case same_ip_multiple_ifaces cleanup
372 same_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 }
378 same_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 }
407 same_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
417 atf_test_case same_ip_multiple_ifaces_inet6 cleanup
418 same_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 }
424 same_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 }
454 same_ip_multiple_ifaces_inet6_cleanup()
455 {
456         cleanup_tap
457 }
458
459 # Regression test for kern/187550
460 atf_test_case subnet_route_with_multiple_fibs_on_same_subnet cleanup
461 subnet_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
468 subnet_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
492 subnet_route_with_multiple_fibs_on_same_subnet_cleanup()
493 {
494         cleanup_tap
495 }
496
497 atf_test_case subnet_route_with_multiple_fibs_on_same_subnet_inet6 cleanup
498 subnet_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
505 subnet_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
529 subnet_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.
547 atf_test_case udp_dontroute cleanup
548 udp_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
555 udp_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
593 udp_dontroute_cleanup()
594 {
595         cleanup_tap
596 }
597
598
599 atf_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
618 get_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
637 get_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
660 setup_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
671 cleanup_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 }