Page MenuHomeFreeBSD

D25181.id73788.diff
No OneTemporary

D25181.id73788.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

File Metadata

Mime Type
text/plain
Expires
Wed, Feb 5, 4:09 PM (11 h, 15 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16476916
Default Alt Text
D25181.id73788.diff (5 KB)

Event Timeline