Page MenuHomeFreeBSD

D14547.id39961.diff
No OneTemporary

D14547.id39961.diff

Index: sys/netinet/in.c
===================================================================
--- sys/netinet/in.c
+++ sys/netinet/in.c
@@ -78,6 +78,8 @@
static void in_socktrim(struct sockaddr_in *);
static void in_purgemaddrs(struct ifnet *);
+static void in_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info);
+
static VNET_DEFINE(int, nosameprefix);
#define V_nosameprefix VNET(nosameprefix)
SYSCTL_INT(_net_inet_ip, OID_AUTO, no_same_prefix, CTLFLAG_VNET | CTLFLAG_RW,
@@ -401,6 +403,7 @@
ifa->ifa_netmask = (struct sockaddr *)&ia->ia_sockmask;
callout_init_rw(&ia->ia_garp_timer, &ifp->if_addr_lock,
CALLOUT_RETURNUNLOCKED);
+ ifa->ifa_rtrequest = in_rtrequest;
ia->ia_ifp = ifp;
ia->ia_addr = *addr;
@@ -1497,3 +1500,56 @@
lltable_free(ii->ii_llt);
free(ii, M_IFADDR);
}
+
+/*
+ * Return true if the route described by info is the local subnet route for
+ * ifa, or false otherwise.
+ */
+static int
+in_is_subnet_route(struct ifaddr *ifa, struct rt_addrinfo *info)
+{
+ struct sockaddr *tmp_sa;
+ struct sockaddr_storage tmp_storage;
+
+ if (info->rti_info[RTAX_DST] == NULL || info->rti_info[RTAX_NETMASK] == NULL)
+ return (0);
+
+ /* First test that the ifaddr falls into the subnet described by the route. */
+ tmp_sa = (struct sockaddr*)&tmp_storage;
+ rt_maskedcopy(ifa->ifa_addr, tmp_sa, ifa->ifa_netmask);
+
+ if (!sa_equal(tmp_sa, info->rti_info[RTAX_DST]))
+ return (0);
+
+ /*
+ * Now test that the subnet mask is the same for the address and
+ * the route. If they are different then the route has a different
+ * prefix size and ifa just happens to fall within that route.
+ *
+ * For some reason ifa->ifa_netmask sa_len field is not
+ * sizeof(struct sockaddr_in). This causes attempts to directly
+ * compare against info->rti_info[RTAX_NETMASK] to incorrectly
+ * fail even if the netmasks are the same. Fix this by making a
+ * copy of ifa->ifa_netmask with the length field correct.
+ */
+ bzero(tmp_sa, sizeof(struct sockaddr_in));
+ memcpy(tmp_sa, ifa->ifa_netmask, ifa->ifa_netmask->sa_len);
+ tmp_sa->sa_len = sizeof(struct sockaddr_in);
+
+ return (sa_equal(info->rti_info[RTAX_NETMASK], tmp_sa));
+}
+
+static void
+in_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info)
+{
+
+ /*
+ * If we are modifying a route to a subnet, we need to migrate the IFA_ROUTE
+ * flag to the new source ifa for the route.
+ */
+ if (req == RTM_DELETE && rt->rt_ifa->ifa_flags & IFA_ROUTE &&
+ info->rti_ifa != NULL && in_is_subnet_route(rt->rt_ifa, info)) {
+ rt->rt_ifa->ifa_flags &= ~IFA_ROUTE;
+ info->rti_ifa->ifa_flags |= IFA_ROUTE;
+ }
+}
Index: tests/sys/netinet/Makefile
===================================================================
--- tests/sys/netinet/Makefile
+++ tests/sys/netinet/Makefile
@@ -1,9 +1,16 @@
# $FreeBSD$
+PACKAGE= tests
+
TESTSDIR= ${TESTSBASE}/sys/netinet
BINDIR= ${TESTSDIR}
-ATF_TESTS_SH= fibs_test
+ATF_TESTS_SH= \
+ fibs_test \
+ route_test \
+
+${PACKAGE}FILES+= \
+ route.subr
PROGS= udp_dontroute tcp_user_cookie
Index: tests/sys/netinet/fibs_test.sh
===================================================================
--- tests/sys/netinet/fibs_test.sh
+++ tests/sys/netinet/fibs_test.sh
@@ -34,6 +34,8 @@
# All of the tests in this file requires the test-suite config variable "fibs"
# to be defined to a space-delimited list of FIBs that may be used for testing.
+. $(atf_get_srcdir)/route.subr
+
# arpresolve should check the interface fib for routes to a target when
# creating an ARP table entry. This is a regression for kern/167947, where
# arpresolve only checked the default route.
@@ -720,7 +722,6 @@
cleanup_ifaces
}
-
atf_init_test_cases()
{
atf_add_test_case arpresolve_checks_interface_fib
@@ -737,109 +738,3 @@
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.
-# Returns the results in the env varilables FIB0, FIB1, etc.
-
-# parameter numfibs The number of fibs to lookup
-get_fibs()
-{
- NUMFIBS=$1
- net_fibs=`sysctl -n net.fibs`
- i=0
- while [ $i -lt "$NUMFIBS" ]; do
- fib=`atf_config_get "fibs" | \
- awk -v i=$(( i + 1 )) '{print $i}'`
- echo "fib is ${fib}"
- eval FIB${i}=${fib}
- if [ "$fib" -ge "$net_fibs" ]; then
- atf_skip "The ${i}th configured fib is ${fib}, which is not less than net.fibs, which is ${net_fibs}"
- fi
- i=$(( $i + 1 ))
- 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 (which pfctl && pfctl -s info | grep -q 'Status: Enabled') ||
- [ `sysctl -n net.inet.ip.fw.enable` = "1" ] ||
- (which ipf && ipf -V); then
- atf_skip "firewalls interfere with this test"
- fi
-
- 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 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()
-{
- get_tap
- setup_iface "$TAP" "$@"
-}
-
-cleanup_ifaces()
-{
- 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 ifaces_to_cleanup
- fi
-}
Index: tests/sys/netinet/route.subr
===================================================================
--- /dev/null
+++ tests/sys/netinet/route.subr
@@ -0,0 +1,138 @@
+#
+# 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$
+
+# Looks up one or more fibs from the configuration data and validates them.
+# Returns the results in the env varilables FIB0, FIB1, etc.
+
+# parameter numfibs The number of fibs to lookup
+get_fibs()
+{
+ NUMFIBS=$1
+ net_fibs=`sysctl -n net.fibs`
+ i=0
+ while [ $i -lt "$NUMFIBS" ]; do
+ fib=`atf_config_get "fibs" | \
+ awk -v i=$(( i + 1 )) '{print $i}'`
+ echo "fib is ${fib}"
+ eval FIB${i}=${fib}
+ if [ "$fib" -ge "$net_fibs" ]; then
+ atf_skip "The ${i}th configured fib is ${fib}, which is not less than net.fibs, which is ${net_fibs}"
+ fi
+ i=$(( $i + 1 ))
+ 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 (which pfctl && pfctl -s info | grep -q 'Status: Enabled') ||
+ [ `sysctl -n net.inet.ip.fw.enable` = "1" ] ||
+ (which ipf && ipf -V); then
+ atf_skip "firewalls interfere with this test"
+ fi
+
+ 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 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()
+{
+ get_tap
+ setup_iface "$TAP" "$@"
+}
+
+cleanup_ifaces()
+{
+ 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 ifaces_to_cleanup
+ fi
+}
Index: tests/sys/netinet/route_test.sh
===================================================================
--- /dev/null
+++ tests/sys/netinet/route_test.sh
@@ -0,0 +1,125 @@
+#
+# Copyright (c) 2014 Dell Inc
+# 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.
+
+# All of the tests in this file requires the test-suite config variable "fibs"
+# to be defined to a space-delimited list of FIBs that may be used for testing.
+
+. $(atf_get_srcdir)/route.subr
+
+# Test that a route can be modified with "route change $SUBNET/$MASK" without
+# needing to also specify the gateway of the route.
+atf_test_case ipv4_change_route_without_dest cleanup
+ipv4_change_route_without_dest_head()
+{
+ atf_set "descr" "Test modifying a route without re-specifying its gateway"
+ atf_set "require.user" "root"
+ atf_set "require.config" "fibs"
+}
+
+ipv4_change_route_without_dest_body()
+{
+ # Configure the TAP interfaces to use a RFC5737 nonrouteable addresses
+ # and a non-default fib
+ SUBNET_PREFIX="192.0.2"
+ SUBNET="${SUBNET_PREFIX}.0"
+ ADDR0="${SUBNET_PREFIX}.1"
+ ADDR1="${SUBNET_PREFIX}.2"
+
+ MASK="24"
+
+ # 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
+
+ setup_tap "$FIB0" inet ${ADDR0} $MASK
+ ifconfig $TAP mtu 9000
+
+ atf_check -s exit:0 -o ignore setfib $FIB0 route change \
+ ${SUBNET}/${MASK} -mtu 8723
+
+ # Just searching for "8723" is awful, but the output of 'route get' is
+ # not amenable to parsing
+ atf_check -o match:8723 setfib $FIB0 route get $ADDR1
+}
+
+ipv4_change_route_without_dest_cleanup()
+{
+ cleanup_ifaces
+}
+
+# Test that a route can be modified with "route change $SUBNET/$MASK" without
+# needing to also specify the gateway of the route.
+atf_test_case ipv6_change_route_without_dest cleanup
+ipv6_change_route_without_dest_head()
+{
+ atf_set "descr" "Test modifying a route without re-specifying its gateway"
+ atf_set "require.user" "root"
+ atf_set "require.config" "fibs"
+}
+
+ipv6_change_route_without_dest_body()
+{
+ # Configure the TAP interfaces to use a RFC5737 nonrouteable addresses
+ # and a non-default fib
+ SUBNET_PREFIX="2001:db8:"
+ SUBNET="${SUBNET_PREFIX}:0"
+ ADDR0="${SUBNET_PREFIX}:1"
+ ADDR1="${SUBNET_PREFIX}:2"
+
+ 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
+
+ setup_tap "$FIB0" inet6 ${ADDR0} $MASK
+ ifconfig $TAP mtu 9000
+
+ atf_check -s exit:0 -o ignore setfib $FIB0 route -6 change \
+ ${SUBNET}/${MASK} -mtu 8723
+
+ # Just searching for "8723" is awful, but the output of 'route get' is
+ # not amenable to parsing
+ atf_check -o match:8723 setfib $FIB0 route -6 get $ADDR1
+}
+
+ipv6_change_route_without_dest_cleanup()
+{
+ cleanup_ifaces
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case ipv4_change_route_without_dest
+ atf_add_test_case ipv6_change_route_without_dest
+}

File Metadata

Mime Type
text/plain
Expires
Thu, Feb 19, 4:33 AM (22 h, 14 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28868324
Default Alt Text
D14547.id39961.diff (14 KB)

Event Timeline