Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F145302777
D14547.id39961.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
14 KB
Referenced Files
None
Subscribers
None
D14547.id39961.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D14547: Allow IPv4 subnet routes to move to a different ifa
Attached
Detach File
Event Timeline
Log In to Comment