Page MenuHomeFreeBSD

D25181.id.diff
No OneTemporary

D25181.id.diff

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

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)

Event Timeline