Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F110748985
D25181.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D25181.id.diff
View Options
Index: share/man/man4/icmp6.4
===================================================================
--- share/man/man4/icmp6.4
+++ share/man/man4/icmp6.4
@@ -238,6 +238,29 @@
with a pointer to the
.Vt icmp6_filter
structure as the option value.
+.Ss MIB Variables
+The
+.Tn ICMPv6
+protocol implements a number of variables in the
+.Va net.inet6.icmp6
+branch of the
+.Xr sysctl 3
+MIB.
+.Bl -tag -width "icmplim_output"
+.It Va reply_src
+.Pq Vt str
+An interface name used for the ICMPv6 reply source in response to packets
+which are not directly addressed to us.
+By default continue with normal source selection.
+.It Va reply_from_interface
+.Pq Vt boolean
+Use the IP address of the interface the packet came through in for
+responses to packets which are not directly addressed to us.
+If enabled, this rule is processed before all others.
+By default, continue with normal source selection.
+Enabling this option is particularly useful on routers because it
+makes external traceroutes show the actual path a packet has taken
+instead of the possibly different return path.
.Sh SEE ALSO
.Xr getsockopt 2 ,
.Xr recv 2 ,
Index: sys/netinet/icmp6.h
===================================================================
--- sys/netinet/icmp6.h
+++ sys/netinet/icmp6.h
@@ -692,6 +692,8 @@
#define ICMPV6CTL_MAXID 26
#ifdef _KERNEL
+#include <sys/sysctl.h>
+
# ifdef __STDC__
struct nhop_object;
struct rttimer;
@@ -782,6 +784,9 @@
#define ICMP6_NODEINFO_NODEADDROK 0x2
#define ICMP6_NODEINFO_TMPADDROK 0x4
#define ICMP6_NODEINFO_GLOBALOK 0x8
+
+SYSCTL_DECL(_net_inet6_icmp6);
+
#endif /* _KERNEL */
#endif /* not _NETINET_ICMP6_H_ */
Index: sys/netinet6/icmp6.c
===================================================================
--- sys/netinet6/icmp6.c
+++ sys/netinet6/icmp6.c
@@ -129,6 +129,8 @@
VNET_DEFINE_STATIC(int, icmp6errpps_count) = 0;
VNET_DEFINE_STATIC(struct timeval, icmp6errppslim_last);
VNET_DECLARE(int, icmp6_nodeinfo);
+VNET_DEFINE_STATIC(int, icmp6_replyif) = 0;
+VNET_DEFINE_STATIC(char, reply_src6[IFNAMSIZ]);
#define V_ripcbinfo VNET(ripcbinfo)
#define V_ripcb VNET(ripcb)
@@ -136,6 +138,8 @@
#define V_icmp6errpps_count VNET(icmp6errpps_count)
#define V_icmp6errppslim_last VNET(icmp6errppslim_last)
#define V_icmp6_nodeinfo VNET(icmp6_nodeinfo)
+#define V_icmp6_replyif VNET(icmp6_replyif)
+#define V_reply_src6 VNET(reply_src6)
static void icmp6_errcount(int, int);
static int icmp6_rip6_input(struct mbuf **, int);
@@ -152,6 +156,14 @@
struct ifnet *, int);
static int icmp6_notify_error(struct mbuf **, int, int, int);
+SYSCTL_INT(_net_inet6_icmp6, OID_AUTO, reply_from_interface, CTLFLAG_VNET | CTLFLAG_RW,
+ &VNET_NAME(icmp6_replyif), 0,
+ "ICMP6 reply from incoming interface for non-local packets");
+
+SYSCTL_STRING(_net_inet6_icmp6, OID_AUTO, reply_src, CTLFLAG_VNET | CTLFLAG_RW,
+ &VNET_NAME(reply_src6), IFNAMSIZ,
+ "ICMP6 reply source for non-local packets");
+
/*
* Kernel module interface for updating icmp6stat. The argument is an index
* into icmp6stat treated as an array of u_quad_t. While this encodes the
@@ -2125,26 +2137,69 @@
int error;
struct in6_addr dst6;
uint32_t scopeid;
+ struct ifnet *ifp;
+ struct ifaddr *ifa;
+ struct in6_ifaddr *ifa6;
/*
* This case matches to multicasts, our anycast, or unicasts
* that we do not own. Select a source address based on the
* source address of the erroneous packet.
*/
+ ifp = m->m_pkthdr.rcvif;
in6_splitscope(&ip6->ip6_src, &dst6, &scopeid);
- error = in6_selectsrc_addr(M_GETFIB(m), &dst6,
- scopeid, NULL, &src6, &hlim);
- if (error) {
- char ip6buf[INET6_ADDRSTRLEN];
- nd6log((LOG_DEBUG,
- "icmp6_reflect: source can't be determined: "
- "dst=%s, error=%d\n",
- ip6_sprintf(ip6buf, &ip6->ip6_dst), error));
- goto bad;
+ if (V_icmp6_replyif && ifp != NULL) {
+ hlim = in6_selecthlim(NULL, ifp);
+ CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+ ifa6 = (struct in6_ifaddr *)ifa;
+ if (ifa->ifa_addr->sa_family != AF_INET6)
+ continue;
+ if (in6_getscope(&ifa6->ia_addr.sin6_addr) != scopeid)
+ continue;
+ ia = ifatoia6(ifa);
+ srcp = IA6_IN6(ia);
+ break;
+ }
+ } else if (V_reply_src6[0] != '\0' && (ifp = ifunit(V_reply_src6))) {
+ hlim = in6_selecthlim(NULL, ifp);
+ CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+ ifa6 = (struct in6_ifaddr *)ifa;
+ if (ifa->ifa_addr->sa_family != AF_INET6)
+ continue;
+ if (in6_getscope(&ifa6->ia_addr.sin6_addr) != scopeid)
+ continue;
+ ia = ifatoia6(ifa);
+ srcp = IA6_IN6(ia);
+ break;
+ }
+ } else {
+ error = in6_selectsrc_addr(M_GETFIB(m), &dst6,
+ scopeid, NULL, &src6, &hlim);
+
+ if (error) {
+ char ip6buf[INET6_ADDRSTRLEN];
+ nd6log((LOG_DEBUG,
+ "icmp6_reflect: source can't be determined: "
+ "dst=%s, error=%d\n",
+ ip6_sprintf(ip6buf, &ip6->ip6_dst), error));
+ goto bad;
+ }
+ srcp = &src6;
}
- srcp = &src6;
}
+ /*
+ * If address selection above did not give a source address, fail.
+ */
+ if (srcp == NULL) {
+ char ip6buf[INET6_ADDRSTRLEN];
+ nd6log((LOG_DEBUG,
+ "icmp6_reflect: source address is null: "
+ "dst=%s\n",
+ ip6_sprintf(ip6buf, &ip6->ip6_dst)));
+ goto bad;
+ }
+
/*
* ip6_input() drops a packet if its src is multicast.
* So, the src is never multicast.
Index: sys/netinet6/nd6_rtr.c
===================================================================
--- sys/netinet6/nd6_rtr.c
+++ sys/netinet6/nd6_rtr.c
@@ -103,8 +103,6 @@
VNET_DEFINE(int, nd6_ignore_ipv6_only_ra) = 1;
#endif
-SYSCTL_DECL(_net_inet6_icmp6);
-
/* RTPREF_MEDIUM has to be 0! */
#define RTPREF_HIGH 1
#define RTPREF_MEDIUM 0
Index: tests/sys/netinet6/Makefile
===================================================================
--- tests/sys/netinet6/Makefile
+++ tests/sys/netinet6/Makefile
@@ -13,7 +13,8 @@
divert \
forward6 \
output6 \
- lpm6
+ lpm6 \
+ icmp6
TEST_METADATA.output6+= required_programs="python"
${PACKAGE}FILES+= exthdr.py
Index: tests/sys/netinet6/icmp6.sh
===================================================================
--- tests/sys/netinet6/icmp6.sh
+++ tests/sys/netinet6/icmp6.sh
@@ -0,0 +1,106 @@
+#!/usr/bin/env atf-sh
+#-
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2020 Neel Chauhan
+#
+# 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.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE.
+#
+# $FreeBSD$
+#
+
+. $(atf_get_srcdir)/../common/vnet.subr
+
+atf_test_case "icmp6_reply_src_iface" "cleanup"
+icmp6_reply_src_iface_head() {
+
+ atf_set descr 'Test ICMP6 reply src interface sysctl'
+ atf_set require.user root
+}
+
+icmp6_reply_src_iface_body() {
+
+ vnet_init
+
+ ip6a="2001:db8:6666::1"
+ ip6b="2001:db8:6666::2"
+ ip6c="2001:db8:6667::1"
+ ip6d="2001:db8:6667::2"
+ plen=64
+
+ epair1=$(vnet_mkepair)
+ epair2=$(vnet_mkepair)
+ ifconfig ${epair1}a up
+ ifconfig ${epair1}a inet6 ${ip6a}/${plen}
+
+ jname1="jail1"
+ vnet_mkjail ${jname1} ${epair1}b ${epair2}a
+ jexec ${jname1} ifconfig ${epair1}b up
+ jexec ${jname1} ifconfig ${epair1}b inet6 ${ip6b}/${plen}
+
+ jexec ${jname1} ifconfig ${epair2}a up
+ jexec ${jname1} ifconfig ${epair2}a inet6 ${ip6c}/${plen}
+
+ jname2="jail2"
+ vnet_mkjail ${jname2} ${epair2}b
+ jexec ${jname2} ifconfig ${epair2}b up
+ jexec ${jname2} ifconfig ${epair2}b inet6 ${ip6d}/${plen}
+
+ # wait for DAD to complete
+ while [ `ifconfig ${epair1}a inet6 | grep -c tentative` != "0" ]; do
+ sleep 0.1
+ done
+ while [ `jexec ${jname1} ifconfig ${epair1}b inet6 | grep -c tentative` != "0" ]; do
+ sleep 0.1
+ done
+ while [ `jexec ${jname1} ifconfig ${epair2}a inet6 | grep -c tentative` != "0" ]; do
+ sleep 0.1
+ done
+ while [ `jexec ${jname2} ifconfig ${epair2}b inet6 | grep -c tentative` != "0" ]; do
+ sleep 0.1
+ done
+
+
+ jexec ${jname1} sysctl net.inet6.icmp6.reply_src=${epair2}a
+ jexec ${jname1} sysctl net.inet6.ip6.forwarding=1
+
+ route add -6 2001:db8:6667::/${plen} ${ip6b}
+ jexec ${jname2} route add -6 ::/0 ${ip6c}
+
+ # check counters are valid
+ atf_check -o match:${ip6c} -e ignore traceroute6 ${ip6d}
+}
+
+icmp6_reply_src_iface_cleanup() {
+
+ sysctl net.inet6.icmp6.reply_src=
+ vnet_cleanup
+}
+
+atf_init_test_cases()
+{
+
+ atf_add_test_case "icmp6_reply_src_iface"
+}
+
+# end
+
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Feb 23, 2:47 PM (3 h, 55 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16775798
Default Alt Text
D25181.id.diff (9 KB)
Attached To
Mode
D25181: Introduce net.inet6.icmp6.reply_from_interface and net.inet6.icmp6.reply_src sysctls
Attached
Detach File
Event Timeline
Log In to Comment