summaryrefslogtreecommitdiffstats
path: root/tests/sys
diff options
context:
space:
mode:
authorasomers <asomers@FreeBSD.org>2017-04-17 20:13:20 +0000
committerasomers <asomers@FreeBSD.org>2017-04-17 20:13:20 +0000
commit59a524a9111affef7c7c2ce1141781301f3ebca8 (patch)
treed512a7d269c641ea2478ef9e58fa8f71420d84ca /tests/sys
parentcb4bf29da0424be3a232ad99f87e103ace0442f3 (diff)
downloadFreeBSD-src-59a524a9111affef7c7c2ce1141781301f3ebca8.zip
FreeBSD-src-59a524a9111affef7c7c2ce1141781301f3ebca8.tar.gz
MFC r313025, r313395, r314113, r314442, r315458, r315656
r313025: Add tests for multi-fib IPv6 routing PR: 196361 Submitted by: jhujhiti@adjectivism.org Reported by: Jason Healy <jhealy@logn.net> MFC after: 4 weeks Sponsored by: Spectra Logic Corp r313395: Add fibs_test:udp_dontroute6, another IPv6 multi-FIB test PR: 196361 MFC after: 3 weeks Sponsored by: Spectra Logic Corp r314113: Remove tests/sys/netinet/fibs_tests's dependency on net/socat Instead of bridging two tap interfaces with socat, just use an epair pair. MFC after: 3 weeks Sponsored by: Spectra Logic Corp r314442: Add an ATF test for IPv6 SLAAC with multiple fibs Tests that an interface can get a SLAAC address and that it inserts its routes into the correct fib. Does not test anything to do with NDP. PR: 196361 Reviewed by: Erick Turnquist <jhujhiti@adjectivism.org> MFC after: 3 weeks Sponsored by: Spectra Logic Corp Differential Revision: https://reviews.freebsd.org/D9776 r315458: Constrain IPv6 routes to single FIBs when net.add_addr_allfibs=0 sys/netinet6/icmp6.c Use the interface's FIB for source address selection in ICMPv6 error responses. sys/netinet6/in6.c In in6_newaddrmsg, announce arrival of local addresses on the interface's FIB only. In in6_lltable_rtcheck, use a per-fib ND6 cache instead of a single cache. sys/netinet6/in6_src.c In in6_selectsrc, use the caller's fib instead of the default fib. In in6_selectsrc_socket, remove a superfluous check. sys/netinet6/nd6.c In nd6_lle_event, use the interface's fib for routing socket messages. In nd6_is_new_addr_neighbor, check all FIBs when trying to determine whether an address is a neighbor. Also, simplify the code for point to point interfaces. sys/netinet6/nd6.h sys/netinet6/nd6.c sys/netinet6/nd6_rtr.c Make defrouter_select fib-aware, and make all of its callers pass in the interface fib. sys/netinet6/nd6_nbr.c When inputting a Neighbor Solicitation packet, consider the interface fib instead of the default fib for DAD. Output NS and Neighbor Advertisement packets on the correct fib. sys/netinet6/nd6_rtr.c Allow installing the same host route on different interfaces in different FIBs. If rt_add_addr_allfibs=0, only install or delete the prefix route on the interface fib. tests/sys/netinet/fibs_test.sh Clear some expected failures, but add a skip for the newly revealed BUG217871. PR: 196361 Submitted by: Erick Turnquist <jhujhiti@adjectivism.org> Reported by: Jason Healy <jhealy@logn.net> Reviewed by: asomers MFC after: 3 weeks Sponsored by: Spectra Logic Corp Differential Revision: https://reviews.freebsd.org/D9451 r315656: Fix back-to-back runs of sys/netinet/fibs_test;slaac_on_nondefault_fib6 This test was failing if run twice because rtadvd takes too long to die. The rtadvd process from the first run was still running when the second run created its interfaces. The solution is to use SIGKILL during the cleanup instead of SIGTERM so rtadvd will die faster. While I'm here, randomize the addresses used for the test, which makes bugs like this easier to spot, and fix the cleanup order to be the opposite of the setup order PR: 217871 MFC after: 18 days X-MFC-With: 315458 Sponsored by: Spectra Logic Corp
Diffstat (limited to 'tests/sys')
-rwxr-xr-xtests/sys/netinet/fibs_test.sh499
-rw-r--r--tests/sys/netinet/udp_dontroute.c53
2 files changed, 465 insertions, 87 deletions
diff --git a/tests/sys/netinet/fibs_test.sh b/tests/sys/netinet/fibs_test.sh
index 70b53e8..febcbb7 100755
--- a/tests/sys/netinet/fibs_test.sh
+++ b/tests/sys/netinet/fibs_test.sh
@@ -39,8 +39,7 @@
# arpresolve only checked the default route.
#
# Outline:
-# Create two tap(4) interfaces
-# Simulate a crossover cable between them by using net/socat
+# Create two connected epair(4) interfaces
# Use nping (from security/nmap) to send an ICMP echo request from one
# interface to the other, spoofing the source IP. The source IP must be
# spoofed, or else it will already have an entry in the arp table.
@@ -51,7 +50,7 @@ arpresolve_checks_interface_fib_head()
atf_set "descr" "arpresolve should check the interface fib, not the default fib, for routes"
atf_set "require.user" "root"
atf_set "require.config" "fibs"
- atf_set "require.progs" "socat nping"
+ atf_set "require.progs" "nping"
}
arpresolve_checks_interface_fib_body()
{
@@ -74,19 +73,13 @@ arpresolve_checks_interface_fib_body()
fi
get_fibs 2
- # Configure TAP interfaces
- setup_tap "$FIB0" ${ADDR0} ${MASK0}
- TAP0=$TAP
- setup_tap "$FIB1" ${ADDR1} ${MASK1}
- TAP1=$TAP
-
- # Simulate a crossover cable
- socat /dev/${TAP0} /dev/${TAP1} &
- SOCAT_PID=$!
- echo ${SOCAT_PID} >> "processes_to_kill"
+ # Configure epair interfaces
+ get_epair
+ setup_iface "$EPAIRA" "$FIB0" inet ${ADDR0} ${MASK0}
+ setup_iface "$EPAIRB" "$FIB1" inet ${ADDR1} ${MASK1}
# Send an ICMP echo request with a spoofed source IP
- setfib 2 nping -c 1 -e ${TAP0} -S ${SPOOF_ADDR} \
+ setfib "$FIB0" nping -c 1 -e ${EPAIRA} -S ${SPOOF_ADDR} \
--source-mac ${SPOOF_MAC} --icmp --icmp-type "echo-request" \
--icmp-code 0 --icmp-id 0xdead --icmp-seq 1 --data 0xbeef \
${ADDR1}
@@ -94,17 +87,11 @@ arpresolve_checks_interface_fib_body()
# characteristic error message
dmesg | grep "llinfo.*${SPOOF_ADDR}"
# Check that the ARP entry exists
- atf_check -o match:"${SPOOF_ADDR}.*expires" setfib 3 arp ${SPOOF_ADDR}
+ atf_check -o match:"${SPOOF_ADDR}.*expires" setfib "$FIB1" arp ${SPOOF_ADDR}
}
arpresolve_checks_interface_fib_cleanup()
{
- if [ -f processes_to_kill ]; then
- for pid in $(cat processes_to_kill); do
- kill "${pid}"
- done
- rm -f processes_to_kill
- fi
- cleanup_tap
+ cleanup_ifaces
}
@@ -112,7 +99,7 @@ arpresolve_checks_interface_fib_cleanup()
atf_test_case loopback_and_network_routes_on_nondefault_fib cleanup
loopback_and_network_routes_on_nondefault_fib_head()
{
- atf_set "descr" "When creating and deleting loopback routes, use the interface's fib"
+ atf_set "descr" "When creating and deleting loopback IPv4 routes, use the interface's fib"
atf_set "require.user" "root"
atf_set "require.config" "fibs"
}
@@ -132,7 +119,7 @@ loopback_and_network_routes_on_nondefault_fib_body()
get_fibs 1
# Configure a TAP interface
- setup_tap ${FIB0} ${ADDR} ${MASK}
+ setup_tap ${FIB0} inet ${ADDR} ${MASK}
# Check whether the host route exists in only the correct FIB
setfib ${FIB0} netstat -rn -f inet | grep -q "^${ADDR}.*UHS.*lo0"
@@ -156,14 +143,71 @@ loopback_and_network_routes_on_nondefault_fib_body()
setfib 0 netstat -rn -f inet | \
grep -q "^${SUBNET}/${MASK}.*${TAPD}"
if [ 0 -eq $? ]; then
- setfib ${FIB0} netstat -rn -f inet
+ setfib 0 netstat -rn -f inet
atf_fail "Network route appeared in the wrong FIB"
fi
}
loopback_and_network_routes_on_nondefault_fib_cleanup()
{
- cleanup_tap
+ cleanup_ifaces
+}
+
+atf_test_case loopback_and_network_routes_on_nondefault_fib_inet6 cleanup
+loopback_and_network_routes_on_nondefault_fib_inet6_head()
+{
+ atf_set "descr" "When creating and deleting loopback IPv6 routes, use the interface's fib"
+ atf_set "require.user" "root"
+ atf_set "require.config" "fibs"
+}
+
+loopback_and_network_routes_on_nondefault_fib_inet6_body()
+{
+ # Configure the TAP interface to use a nonrouteable RFC3849
+ # address and a non-default fib
+ ADDR="2001:db8::2"
+ SUBNET="2001:db8::"
+ MASK="64"
+
+ # Check system configuration
+ if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then
+ atf_skip "This test requires net.add_addr_allfibs=0"
+ fi
+ get_fibs 1
+
+ # Configure a TAP interface
+ setup_tap ${FIB0} inet6 ${ADDR} ${MASK}
+
+ # Check whether the host route exists in only the correct FIB
+ setfib ${FIB0} netstat -rn -f inet6 | grep -q "^${ADDR}.*UHS.*lo0"
+ if [ 0 -ne $? ]; then
+ setfib ${FIB0} netstat -rn -f inet6
+ atf_fail "Host route did not appear in the correct FIB"
+ fi
+ setfib 0 netstat -rn -f inet6 | grep -q "^${ADDR}.*UHS.*lo0"
+ if [ 0 -eq $? ]; then
+ setfib 0 netstat -rn -f inet6
+ atf_fail "Host route appeared in the wrong FIB"
+ fi
+
+ # Check whether the network route exists in only the correct FIB
+ setfib ${FIB0} netstat -rn -f inet6 | \
+ grep -q "^${SUBNET}/${MASK}.*${TAPD}"
+ if [ 0 -ne $? ]; then
+ setfib ${FIB0} netstat -rn -f inet6
+ atf_fail "Network route did not appear in the correct FIB"
+ fi
+ setfib 0 netstat -rn -f inet6 | \
+ grep -q "^${SUBNET}/${MASK}.*${TAPD}"
+ if [ 0 -eq $? ]; then
+ setfib 0 netstat -rn -f inet6
+ atf_fail "Network route appeared in the wrong FIB"
+ fi
+}
+
+loopback_and_network_routes_on_nondefault_fib_inet6_cleanup()
+{
+ cleanup_ifaces
}
@@ -171,7 +215,7 @@ loopback_and_network_routes_on_nondefault_fib_cleanup()
atf_test_case default_route_with_multiple_fibs_on_same_subnet cleanup
default_route_with_multiple_fibs_on_same_subnet_head()
{
- atf_set "descr" "Multiple interfaces on the same subnet but with different fibs can both have default routes"
+ atf_set "descr" "Multiple interfaces on the same subnet but with different fibs can both have default IPv4 routes"
atf_set "require.user" "root"
atf_set "require.config" "fibs"
}
@@ -193,9 +237,9 @@ default_route_with_multiple_fibs_on_same_subnet_body()
get_fibs 2
# Configure TAP interfaces
- setup_tap "$FIB0" ${ADDR0} ${MASK}
+ setup_tap "$FIB0" inet ${ADDR0} ${MASK}
TAP0=$TAP
- setup_tap "$FIB1" ${ADDR1} ${MASK}
+ setup_tap "$FIB1" inet ${ADDR1} ${MASK}
TAP1=$TAP
# Attempt to add default routes
@@ -212,7 +256,54 @@ default_route_with_multiple_fibs_on_same_subnet_body()
default_route_with_multiple_fibs_on_same_subnet_cleanup()
{
- cleanup_tap
+ cleanup_ifaces
+}
+
+atf_test_case default_route_with_multiple_fibs_on_same_subnet_inet6 cleanup
+default_route_with_multiple_fibs_on_same_subnet_inet6_head()
+{
+ atf_set "descr" "Multiple interfaces on the same subnet but with different fibs can both have default IPv6 routes"
+ atf_set "require.user" "root"
+ atf_set "require.config" "fibs"
+}
+
+default_route_with_multiple_fibs_on_same_subnet_inet6_body()
+{
+ # Configure the TAP interfaces to use nonrouteable RFC3849
+ # addresses and non-default FIBs
+ ADDR0="2001:db8::2"
+ ADDR1="2001:db8::3"
+ GATEWAY="2001:db8::1"
+ SUBNET="2001:db8::"
+ MASK="64"
+
+ # Check system configuration
+ if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then
+ atf_skip "This test requires net.add_addr_allfibs=0"
+ fi
+ get_fibs 2
+
+ # Configure TAP interfaces
+ setup_tap "$FIB0" inet6 ${ADDR0} ${MASK}
+ TAP0=$TAP
+ setup_tap "$FIB1" inet6 ${ADDR1} ${MASK}
+ TAP1=$TAP
+
+ # Attempt to add default routes
+ setfib ${FIB0} route -6 add default ${GATEWAY}
+ setfib ${FIB1} route -6 add default ${GATEWAY}
+
+ # Verify that the default route exists for both fibs, with their
+ # respective interfaces.
+ atf_check -o match:"^default.*${TAP0}$" \
+ setfib ${FIB0} netstat -rn -f inet6
+ atf_check -o match:"^default.*${TAP1}$" \
+ setfib ${FIB1} netstat -rn -f inet6
+}
+
+default_route_with_multiple_fibs_on_same_subnet_inet6_cleanup()
+{
+ cleanup_ifaces
}
@@ -223,7 +314,7 @@ default_route_with_multiple_fibs_on_same_subnet_cleanup()
atf_test_case same_ip_multiple_ifaces_fib0 cleanup
same_ip_multiple_ifaces_fib0_head()
{
- atf_set "descr" "Can remove an IP alias from an interface when the same IP is also assigned to another interface."
+ atf_set "descr" "Can remove an IPv4 alias from an interface when the same IPv4 is also assigned to another interface."
atf_set "require.user" "root"
atf_set "require.config" "fibs"
}
@@ -237,22 +328,22 @@ same_ip_multiple_ifaces_fib0_body()
# of net.add_addr_allfibs
# Setup the interfaces, then remove one alias. It should not panic.
- setup_tap 0 ${ADDR} ${MASK0}
+ setup_tap 0 inet ${ADDR} ${MASK0}
TAP0=${TAP}
- setup_tap 0 ${ADDR} ${MASK1}
+ setup_tap 0 inet ${ADDR} ${MASK1}
TAP1=${TAP}
ifconfig ${TAP1} -alias ${ADDR}
# Do it again, in the opposite order. It should not panic.
- setup_tap 0 ${ADDR} ${MASK0}
+ setup_tap 0 inet ${ADDR} ${MASK0}
TAP0=${TAP}
- setup_tap 0 ${ADDR} ${MASK1}
+ setup_tap 0 inet ${ADDR} ${MASK1}
TAP1=${TAP}
ifconfig ${TAP0} -alias ${ADDR}
}
same_ip_multiple_ifaces_fib0_cleanup()
{
- cleanup_tap
+ cleanup_ifaces
}
# Regression test for PR kern/189088
@@ -266,7 +357,7 @@ same_ip_multiple_ifaces_fib0_cleanup()
atf_test_case same_ip_multiple_ifaces cleanup
same_ip_multiple_ifaces_head()
{
- atf_set "descr" "Can remove an IP alias from an interface when the same IP is also assigned to another interface, on non-default FIBs."
+ 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."
atf_set "require.user" "root"
atf_set "require.config" "fibs"
}
@@ -282,18 +373,18 @@ same_ip_multiple_ifaces_body()
get_fibs 2
# Setup the interfaces, then remove one alias. It should not panic.
- setup_tap ${FIB0} ${ADDR} ${MASK0}
+ setup_tap ${FIB0} inet ${ADDR} ${MASK0}
TAP0=${TAP}
- setup_tap ${FIB1} ${ADDR} ${MASK1}
+ setup_tap ${FIB1} inet ${ADDR} ${MASK1}
TAP1=${TAP}
ifconfig ${TAP1} -alias ${ADDR}
atf_check -o not-match:"^${ADDR}[[:space:]]" \
setfib ${FIB1} netstat -rn -f inet
# Do it again, in the opposite order. It should not panic.
- setup_tap ${FIB0} ${ADDR} ${MASK0}
+ setup_tap ${FIB0} inet ${ADDR} ${MASK0}
TAP0=${TAP}
- setup_tap ${FIB1} ${ADDR} ${MASK1}
+ setup_tap ${FIB1} inet ${ADDR} ${MASK1}
TAP1=${TAP}
ifconfig ${TAP0} -alias ${ADDR}
atf_check -o not-match:"^${ADDR}[[:space:]]" \
@@ -303,16 +394,145 @@ same_ip_multiple_ifaces_cleanup()
{
# Due to PR kern/189088, we must destroy the interfaces in LIFO order
# in order for the routes to be correctly cleaned up.
- for TAPD in `tail -r "tap_devices_to_cleanup"`; do
+ for TAPD in `tail -r "ifaces_to_cleanup"`; do
+ echo ifconfig ${TAPD} destroy
ifconfig ${TAPD} destroy
done
}
+atf_test_case same_ip_multiple_ifaces_inet6 cleanup
+same_ip_multiple_ifaces_inet6_head()
+{
+ 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."
+ atf_set "require.user" "root"
+ atf_set "require.config" "fibs"
+}
+same_ip_multiple_ifaces_inet6_body()
+{
+ ADDR="2001:db8::2"
+ MASK0="64"
+ MASK1="128"
+
+ # Unlike most of the tests in this file, this is applicable regardless
+ # of net.add_addr_allfibs
+ get_fibs 2
+
+ # Setup the interfaces, then remove one alias. It should not panic.
+ setup_tap ${FIB0} inet6 ${ADDR} ${MASK0}
+ TAP0=${TAP}
+ setup_tap ${FIB1} inet6 ${ADDR} ${MASK1}
+ TAP1=${TAP}
+ atf_check -s exit:0 ifconfig ${TAP1} inet6 ${ADDR} -alias
+ atf_check -o not-match:"^${ADDR}[[:space:]]" \
+ setfib ${FIB1} netstat -rn -f inet6
+ ifconfig ${TAP1} destroy
+ ifconfig ${TAP0} destroy
+
+ # Do it again, in the opposite order. It should not panic.
+ setup_tap ${FIB0} inet6 ${ADDR} ${MASK0}
+ TAP0=${TAP}
+ setup_tap ${FIB1} inet6 ${ADDR} ${MASK1}
+ TAP1=${TAP}
+ atf_check -s exit:0 ifconfig ${TAP0} inet6 ${ADDR} -alias
+ atf_check -o not-match:"^${ADDR}[[:space:]]" \
+ setfib ${FIB0} netstat -rn -f inet6
+}
+same_ip_multiple_ifaces_inet6_cleanup()
+{
+ cleanup_ifaces
+}
+
+atf_test_case slaac_on_nondefault_fib6 cleanup
+slaac_on_nondefault_fib6_head()
+{
+ atf_set "descr" "SLAAC correctly installs routes on non-default FIBs"
+ atf_set "require.user" "root"
+ atf_set "require.config" "fibs" "allow_sysctl_side_effects"
+}
+slaac_on_nondefault_fib6_body()
+{
+ # Configure the epair interfaces to use nonrouteable RFC3849
+ # addresses and non-default FIBs
+ PREFIX="2001:db8:$(printf "%x" `jot -r 1 0 65535`):$(printf "%x" `jot -r 1 0 65535`)"
+ ADDR="$PREFIX::2"
+ GATEWAY="$PREFIX::1"
+ SUBNET="$PREFIX:"
+ MASK="64"
+
+ # Check system configuration
+ if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then
+ atf_skip "This test requires net.add_addr_allfibs=0"
+ fi
+ get_fibs 2
+
+ sysctl -n "net.inet6.ip6.rfc6204w3" >> "rfc6204w3.state"
+ sysctl -n "net.inet6.ip6.forwarding" >> "forwarding.state"
+ # Enable forwarding so the kernel will send RAs
+ sysctl net.inet6.ip6.forwarding=1
+ # Enable RFC6204W3 mode so the kernel will enable default router
+ # selection while also forwarding packets
+ sysctl net.inet6.ip6.rfc6204w3=1
+
+ # Configure epair interfaces
+ get_epair
+ setup_iface "$EPAIRA" "$FIB0" inet6 ${ADDR} ${MASK}
+ echo setfib $FIB1 ifconfig "$EPAIRB" inet6 -ifdisabled accept_rtadv fib $FIB1 up
+ setfib $FIB1 ifconfig "$EPAIRB" inet6 -ifdisabled accept_rtadv fib $FIB1 up
+ rtadvd -p rtadvd.pid -C rtadvd.sock -c /dev/null "$EPAIRA"
+ rtsol "$EPAIRB"
+
+ # Check SLAAC address
+ atf_check -o match:"inet6 ${SUBNET}.*prefixlen ${MASK}.*autoconf" \
+ ifconfig "$EPAIRB"
+ # Check local route
+ atf_check -o match:"${SUBNET}.*\<UHS\>.*lo0" \
+ netstat -rnf inet6 -F $FIB1
+ # Check subnet route
+ atf_check -o match:"${SUBNET}:/${MASK}.*\<U\>.*$EPAIRB" \
+ netstat -rnf inet6 -F $FIB1
+ # Check default route
+ atf_check -o match:"default.*\<UG\>.*$EPAIRB" \
+ netstat -rnf inet6 -F $FIB1
+
+ # Check that none of the above routes appeared on other routes
+ for fib in $( seq 0 $(($(sysctl -n net.fibs) - 1))); do
+ if [ "$fib" = "$FIB1" -o "$fib" = "$FIB0" ]; then
+ continue
+ fi
+ atf_check -o not-match:"${SUBNET}.*\<UHS\>.*lo0" \
+ netstat -rnf inet6 -F $fib
+ atf_check -o not-match:"${SUBNET}:/${MASK}.*\<U\>.*$EPAIRB" \
+ netstat -rnf inet6 -F $fib
+ atf_check -o not-match:"default.*\<UG\>.*$EPAIRB" \
+ netstat -rnf inet6 -F $fib
+ done
+}
+slaac_on_nondefault_fib6_cleanup()
+{
+ if [ -f "rtadvd.pid" ]; then
+ # rtadvd can take a long time to shutdown. Use SIGKILL to kill
+ # it right away. The downside to using SIGKILL is that it
+ # won't send final RAs to all interfaces, but we don't care
+ # because we're about to destroy its interface anyway.
+ pkill -kill -F rtadvd.pid
+ rm -f rtadvd.pid
+ fi
+ cleanup_ifaces
+ if [ -f "forwarding.state" ] ; then
+ sysctl "net.inet6.ip6.forwarding"=`cat "forwarding.state"`
+ rm "forwarding.state"
+ fi
+ if [ -f "rfc6204w3.state" ] ; then
+ sysctl "net.inet6.ip6.rfc6204w3"=`cat "rfc6204w3.state"`
+ rm "rfc6204w3.state"
+ fi
+}
+
# Regression test for kern/187550
atf_test_case subnet_route_with_multiple_fibs_on_same_subnet cleanup
subnet_route_with_multiple_fibs_on_same_subnet_head()
{
- atf_set "descr" "Multiple FIBs can have subnet routes for the same subnet"
+ atf_set "descr" "Multiple FIBs can have IPv4 subnet routes for the same subnet"
atf_set "require.user" "root"
atf_set "require.config" "fibs"
}
@@ -333,8 +553,8 @@ subnet_route_with_multiple_fibs_on_same_subnet_body()
get_fibs 2
# Configure TAP interfaces
- setup_tap "$FIB0" ${ADDR0} ${MASK}
- setup_tap "$FIB1" ${ADDR1} ${MASK}
+ setup_tap "$FIB0" inet ${ADDR0} ${MASK}
+ setup_tap "$FIB1" inet ${ADDR1} ${MASK}
# Check that a subnet route exists on both fibs
atf_check -o ignore setfib "$FIB0" route get $ADDR1
@@ -343,7 +563,44 @@ subnet_route_with_multiple_fibs_on_same_subnet_body()
subnet_route_with_multiple_fibs_on_same_subnet_cleanup()
{
- cleanup_tap
+ cleanup_ifaces
+}
+
+atf_test_case subnet_route_with_multiple_fibs_on_same_subnet_inet6 cleanup
+subnet_route_with_multiple_fibs_on_same_subnet_inet6_head()
+{
+ atf_set "descr" "Multiple FIBs can have IPv6 subnet routes for the same subnet"
+ atf_set "require.user" "root"
+ atf_set "require.config" "fibs"
+}
+
+subnet_route_with_multiple_fibs_on_same_subnet_inet6_body()
+{
+ # Configure the TAP interfaces to use a RFC3849 nonrouteable addresses
+ # and a non-default fib
+ ADDR0="2001:db8::2"
+ ADDR1="2001:db8::3"
+ SUBNET="2001:db8::"
+ MASK="64"
+
+ # Check system configuration
+ if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then
+ atf_skip "This test requires net.add_addr_allfibs=0"
+ fi
+ get_fibs 2
+
+ # Configure TAP interfaces
+ setup_tap "$FIB0" inet6 ${ADDR0} ${MASK}
+ setup_tap "$FIB1" inet6 ${ADDR1} ${MASK}
+
+ # Check that a subnet route exists on both fibs
+ atf_check -o ignore setfib "$FIB0" route -6 get $ADDR1
+ atf_check -o ignore setfib "$FIB1" route -6 get $ADDR0
+}
+
+subnet_route_with_multiple_fibs_on_same_subnet_inet6_cleanup()
+{
+ cleanup_ifaces
}
# Test that source address selection works correctly for UDP packets with
@@ -386,19 +643,19 @@ udp_dontroute_body()
get_fibs 2
# Configure the TAP interfaces
- setup_tap ${FIB0} ${ADDR0} ${MASK}
+ setup_tap ${FIB0} inet ${ADDR0} ${MASK}
TARGET_TAP=${TAP}
- setup_tap ${FIB1} ${ADDR1} ${MASK}
+ setup_tap ${FIB1} inet ${ADDR1} ${MASK}
# Send a UDP packet with SO_DONTROUTE. In the failure case, it will
# return ENETUNREACH, or send the packet to the wrong tap
atf_check -o ignore setfib ${FIB0} \
${SRCDIR}/udp_dontroute ${TARGET} /dev/${TARGET_TAP}
- cleanup_tap
+ cleanup_ifaces
# Repeat, but this time target the other tap
- setup_tap ${FIB0} ${ADDR0} ${MASK}
- setup_tap ${FIB1} ${ADDR1} ${MASK}
+ setup_tap ${FIB0} inet ${ADDR0} ${MASK}
+ setup_tap ${FIB1} inet ${ADDR1} ${MASK}
TARGET_TAP=${TAP}
atf_check -o ignore setfib ${FIB1} \
@@ -407,7 +664,60 @@ udp_dontroute_body()
udp_dontroute_cleanup()
{
- cleanup_tap
+ cleanup_ifaces
+}
+
+atf_test_case udp_dontroute6 cleanup
+udp_dontroute6_head()
+{
+ atf_set "descr" "Source address selection for UDP IPv6 packets with SO_DONTROUTE on non-default FIBs works"
+ atf_set "require.user" "root"
+ atf_set "require.config" "fibs"
+}
+
+udp_dontroute6_body()
+{
+ # Configure the TAP interface to use an RFC3849 nonrouteable address
+ # and a non-default fib
+ ADDR0="2001:db8::2"
+ ADDR1="2001:db8::3"
+ SUBNET="2001:db8::"
+ MASK="64"
+ # Use a different IP on the same subnet as the target
+ TARGET="2001:db8::100"
+ SRCDIR=`atf_get_srcdir`
+
+ # Check system configuration
+ if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then
+ atf_skip "This test requires net.add_addr_allfibs=0"
+ fi
+ get_fibs 2
+
+ # Configure the TAP interfaces. Use no_dad so the addresses will be
+ # ready right away and won't be marked as tentative until DAD
+ # completes.
+ setup_tap ${FIB0} inet6 ${ADDR0} ${MASK} no_dad
+ TARGET_TAP=${TAP}
+ setup_tap ${FIB1} inet6 ${ADDR1} ${MASK} no_dad
+
+ # Send a UDP packet with SO_DONTROUTE. In the failure case, it will
+ # return ENETUNREACH, or send the packet to the wrong tap
+ atf_check -o ignore setfib ${FIB0} \
+ ${SRCDIR}/udp_dontroute -6 ${TARGET} /dev/${TARGET_TAP}
+ cleanup_ifaces
+
+ # Repeat, but this time target the other tap
+ setup_tap ${FIB0} inet6 ${ADDR0} ${MASK} no_dad
+ setup_tap ${FIB1} inet6 ${ADDR1} ${MASK} no_dad
+ TARGET_TAP=${TAP}
+
+ atf_check -o ignore setfib ${FIB1} \
+ ${SRCDIR}/udp_dontroute -6 ${TARGET} /dev/${TARGET_TAP}
+}
+
+udp_dontroute6_cleanup()
+{
+ cleanup_ifaces
}
@@ -415,11 +725,17 @@ atf_init_test_cases()
{
atf_add_test_case arpresolve_checks_interface_fib
atf_add_test_case loopback_and_network_routes_on_nondefault_fib
+ atf_add_test_case loopback_and_network_routes_on_nondefault_fib_inet6
atf_add_test_case default_route_with_multiple_fibs_on_same_subnet
+ atf_add_test_case default_route_with_multiple_fibs_on_same_subnet_inet6
atf_add_test_case same_ip_multiple_ifaces_fib0
atf_add_test_case same_ip_multiple_ifaces
+ atf_add_test_case same_ip_multiple_ifaces_inet6
+ atf_add_test_case slaac_on_nondefault_fib6
atf_add_test_case subnet_route_with_multiple_fibs_on_same_subnet
+ atf_add_test_case subnet_route_with_multiple_fibs_on_same_subnet_inet6
atf_add_test_case udp_dontroute
+ atf_add_test_case udp_dontroute6
}
# Looks up one or more fibs from the configuration data and validates them.
@@ -443,46 +759,81 @@ get_fibs()
done
}
+# Creates a new pair of connected epair(4) interface, registers them for
+# cleanup, and returns their namen via the environment variables EPAIRA and
+# EPAIRB
+get_epair()
+{
+ local EPAIRD
+
+ if EPAIRD=`ifconfig epair create`; then
+ # Record the epair device so we can clean it up later
+ echo ${EPAIRD} >> "ifaces_to_cleanup"
+ EPAIRA=${EPAIRD}
+ EPAIRB=${EPAIRD%a}b
+ else
+ atf_skip "Could not create epair(4) interfaces"
+ fi
+}
+
# Creates a new tap(4) interface, registers it for cleanup, and returns the
# name via the environment variable TAP
get_tap()
{
- local TAPN=0
- while ! ifconfig tap${TAPN} create > /dev/null 2>&1; do
- if [ "$TAPN" -ge 8 ]; then
- atf_skip "Could not create a tap(4) interface"
- else
- TAPN=$(($TAPN + 1))
- fi
- done
- local TAPD=tap${TAPN}
- # Record the TAP device so we can clean it up later
- echo ${TAPD} >> "tap_devices_to_cleanup"
- TAP=${TAPD}
+ local TAPD
+
+ if TAPD=`ifconfig tap create`; then
+ # Record the TAP device so we can clean it up later
+ echo ${TAPD} >> "ifaces_to_cleanup"
+ TAP=${TAPD}
+ else
+ atf_skip "Could not create a tap(4) interface"
+ fi
+}
+
+# Configure an ethernet interface
+# parameters:
+# Interface name
+# fib
+# Protocol (inet or inet6)
+# IP address
+# Netmask in number of bits (eg 24 or 8)
+# Extra flags
+# Return: None
+setup_iface()
+{
+ local IFACE=$1
+ local FIB=$2
+ local PROTO=$3
+ local ADDR=$4
+ local MASK=$5
+ local FLAGS=$6
+ echo setfib ${FIB} \
+ ifconfig $IFACE ${PROTO} ${ADDR}/${MASK} fib $FIB $FLAGS
+ setfib ${FIB} ifconfig $IFACE ${PROTO} ${ADDR}/${MASK} fib $FIB $FLAGS
}
# Create a tap(4) interface, configure it, and register it for cleanup.
# parameters:
# fib
+# Protocol (inet or inet6)
# IP address
# Netmask in number of bits (eg 24 or 8)
+# Extra flags
# Return: the tap interface name as the env variable TAP
setup_tap()
{
- local FIB=$1
- local ADDR=$2
- local MASK=$3
get_tap
- echo setfib ${FIB} ifconfig $TAP ${ADDR}/${MASK} fib $FIB
- setfib ${FIB} ifconfig $TAP ${ADDR}/${MASK} fib $FIB
+ setup_iface "$TAP" "$@"
}
-cleanup_tap()
+cleanup_ifaces()
{
- if [ -f tap_devices_to_cleanup ]; then
- for tap_device in $(cat tap_devices_to_cleanup); do
- ifconfig "${tap_device}" destroy
+ if [ -f ifaces_to_cleanup ]; then
+ for iface in $(cat ifaces_to_cleanup); do
+ echo ifconfig "${iface}" destroy
+ ifconfig "${iface}" destroy 2>/dev/null || true
done
- rm -f tap_devices_to_cleanup
+ rm -f ifaces_to_cleanup
fi
}
diff --git a/tests/sys/netinet/udp_dontroute.c b/tests/sys/netinet/udp_dontroute.c
index 79421fd..24e3fc4 100644
--- a/tests/sys/netinet/udp_dontroute.c
+++ b/tests/sys/netinet/udp_dontroute.c
@@ -41,6 +41,7 @@
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
+#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -52,7 +53,7 @@
int
main(int argc, char **argv)
{
- struct sockaddr_in dst;
+ struct sockaddr_storage dst;
int s, t;
int opt;
int ret;
@@ -60,17 +61,33 @@ main(int argc, char **argv)
const char* sendbuf = "Hello, World!";
const size_t buflen = 80;
char recvbuf[buflen];
+ bool v6 = false;
+ const char *addr, *tapdev;
+ const uint16_t port = 46120;
- if (argc != 3) {
- fprintf(stderr, "Usage: %s ip_address tapdev\n", argv[0]);
+ bzero(&dst, sizeof(dst));
+ if (argc < 3 || argc > 4) {
+ fprintf(stderr, "Usage: %s [-6] ip_address tapdev\n", argv[0]);
exit(2);
}
- t = open(argv[2], O_RDWR | O_NONBLOCK);
+ if (strcmp("-6", argv[1]) == 0) {
+ v6 = true;
+ addr = argv[2];
+ tapdev = argv[3];
+ } else {
+ addr = argv[1];
+ tapdev = argv[2];
+ }
+
+ t = open(tapdev, O_RDWR | O_NONBLOCK);
if (t < 0)
err(EXIT_FAILURE, "open");
- s = socket(PF_INET, SOCK_DGRAM, 0);
+ if (v6)
+ s = socket(PF_INET6, SOCK_DGRAM, 0);
+ else
+ s = socket(PF_INET, SOCK_DGRAM, 0);
if (s < 0)
err(EXIT_FAILURE, "socket");
opt = 1;
@@ -79,16 +96,26 @@ main(int argc, char **argv)
if (ret == -1)
err(EXIT_FAILURE, "setsockopt(SO_DONTROUTE)");
- dst.sin_len = sizeof(dst);
- dst.sin_family = AF_INET;
- dst.sin_port = htons(46120);
- dst.sin_addr.s_addr = inet_addr(argv[1]);
- if (dst.sin_addr.s_addr == htonl(INADDR_NONE)) {
- fprintf(stderr, "Invalid address: %s\n", argv[1]);
- exit(2);
+ if (v6) {
+ struct sockaddr_in6 *dst6 = ((struct sockaddr_in6*)&dst);
+
+ dst.ss_len = sizeof(struct sockaddr_in6);
+ dst.ss_family = AF_INET6;
+ dst6->sin6_port = htons(port);
+ ret = inet_pton(AF_INET6, addr, &dst6->sin6_addr);
+ } else {
+ struct sockaddr_in *dst4 = ((struct sockaddr_in*)&dst);
+
+ dst.ss_len = sizeof(struct sockaddr_in);
+ dst.ss_family = AF_INET;
+ dst4->sin_port = htons(port);
+ ret = inet_pton(AF_INET, addr, &dst4->sin_addr);
}
+ if (ret != 1)
+ err(EXIT_FAILURE, "inet_pton returned %d", ret);
+
ret = sendto(s, sendbuf, strlen(sendbuf), 0, (struct sockaddr*)&dst,
- dst.sin_len);
+ dst.ss_len);
if (ret == -1)
err(EXIT_FAILURE, "sendto");
OpenPOWER on IntegriCloud