tests/sys/netinet/Makefile

tests/sys/netinet/fibs.sh
	Replace fibs:udp_dontroute with fibs:src_addr_selection_by_subnet.
	The original test was poorly written; it was actually testing
	kern/167947 instead of the desired kern/187553.  The root cause of the
	bug is that ifa_ifwithnet did not have a fib argument.  The new test
	more directly targets that behavior.

tests/sys/netinet/udp_dontroute.c
	Delete the auxilliary binary used by the old test

PR:		kern/187553
MFC after:	3 weeks
Sponsored by:	Spectra Logic Corporation
This commit is contained in:
Alan Somers 2014-03-25 15:03:08 +00:00
parent b83788ff87
commit 55a76bf7ff
3 changed files with 38 additions and 107 deletions

View File

@ -1,12 +1,7 @@
# $FreeBSD$
TESTSDIR= ${TESTSBASE}/sys/netinet
BINDIR= ${TESTSDIR}
ATF_TESTS_SH+= fibs_test
PROG= udp_dontroute
SRCS= udp_dontroute.c
NO_MAN=
WARNS?= 6
.include <bsd.test.mk>

View File

@ -255,45 +255,66 @@ subnet_route_with_multiple_fibs_on_same_subnet_cleanup()
cleanup_tap
}
# Test that source address selection works correctly for UDP packets with
# SO_DONTROUTE set that are sent on non-default FIBs.
# Regression test for kern/187553 "Source address selection for UDP packets
# with SO_DONTROUTE uses the default FIB". The original complaint was that a
# UDP packet with SO_DONTROUTE set would select a source address from an
# interface on the default FIB instead of the process FIB.
# This bug was discovered with "setfib 1 netperf -t UDP_STREAM -H some_host"
# Regression test for kern/187553
atf_test_case udp_dontroute cleanup
udp_dontroute_head()
# The root cause was that ifa_ifwithnet() did not have a fib argument. It
# would return an address from an interface on any FIB that had a subnet route
# for the destination. If more than one were available, it would choose the
# most specific. The root cause is most easily tested by creating two
# interfaces with overlapping subnet routes, adding a default route to the
# interface with the less specific subnet route, and looking up a host that
# requires the default route using the FIB of the interface with the less
# specific subnet route. "route get" should provide a route that uses the
# interface on the chosen FIB. However, absent the patch for this bug it will
# instead use the other interface.
atf_test_case src_addr_selection_by_subnet cleanup
src_addr_selection_by_subnet_head()
{
atf_set "descr" "Source address selection for UDP packets with SO_DONTROUTE on non-default FIBs works"
atf_set "require.user" "root"
atf_set "require.config" "fibs"
}
udp_dontroute_body()
src_addr_selection_by_subnet_body()
{
atf_expect_fail "kern/187553 Source address selection for UDP packets with SO_DONTROUTE uses the default FIB"
# Configure the TAP interface to use an RFC5737 nonrouteable address
# and a non-default fib
ADDR="192.0.2.2"
ADDR0="192.0.2.2"
ADDR1="192.0.2.3"
GATEWAY0="192.0.2.1"
TARGET="192.0.2.128"
SUBNET="192.0.2.0"
MASK="24"
# Use a different IP on the same subnet as the target
TARGET="192.0.2.100"
MASK0="25"
MASK1="26"
# 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
get_fibs 2
# Configure a TAP interface
setup_tap ${FIB0} ${ADDR} ${MASK}
setup_tap ${FIB0} ${ADDR0} ${MASK0}
TAP0=${TAP}
setup_tap ${FIB1} ${ADDR1} ${MASK1}
TAP1=${TAP}
# Send a UDP packet with SO_DONTROUTE. In the failure case, it will
# return ENETUNREACH
SRCDIR=`atf_get_srcdir`
atf_check -o ignore setfib ${FIB0} ${SRCDIR}/udp_dontroute ${TARGET}
# Add a gateway to the interface with the less specific subnet route
setfib ${FIB0} route add default ${GATEWAY0}
# Lookup a route
echo "Looking up route to ${TARGET} with fib ${FIB0}"
echo "Expected behavior is to use interface ${TAP0}"
atf_check -o match:"interface:.${TAP0}" setfib ${FIB0} route -n get ${TARGET}
}
udp_dontroute_cleanup()
src_addr_selection_by_subnet_cleanup()
{
cleanup_tap
}
@ -305,7 +326,7 @@ atf_init_test_cases()
atf_add_test_case loopback_and_network_routes_on_nondefault_fib
atf_add_test_case default_route_with_multiple_fibs_on_same_subnet
atf_add_test_case subnet_route_with_multiple_fibs_on_same_subnet
atf_add_test_case udp_dontroute
atf_add_test_case src_addr_selection_by_subnet
}
# Looks up one or more fibs from the configuration data and validates them.

View File

@ -1,85 +0,0 @@
/*
* Copyright (c) 2014 Spectra Logic Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* Authors: Alan Somers (Spectra Logic Corporation)
*
* $FreeBSD$
*/
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
* Sends a single UDP packet to the provided address, with SO_DONTROUTE set
* I couldn't find a way to do this with builtin utilities like nc(1)
*/
int main(int argc, char **argv)
{
struct sockaddr_in dst;
int s;
int opt;
int ret;
const char* buf = "Hello, World!";
if (argc != 2) {
fprintf(stderr, "Usage: %s ip_address\n", argv[0]);
exit(2);
}
s = socket(PF_INET, SOCK_DGRAM, 0);
if (s < 0)
err(errno, "socket");
opt = 1;
ret = setsockopt(s, SOL_SOCKET, SO_DONTROUTE, &opt, sizeof(opt));
if (ret == -1)
err(errno, "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);
}
ret = sendto(s, buf, strlen(buf), 0, (struct sockaddr*)&dst,
dst.sin_len);
if (ret == -1)
err(errno, "sendto");
return (0);
}