svn commit: r356093 - in stable/12/sys: modules/ipfw_nat64 netpfil/ipfw/nat64

Andrey V. Elsukov ae at FreeBSD.org
Thu Dec 26 18:05:39 UTC 2019


Author: ae
Date: Thu Dec 26 18:05:38 2019
New Revision: 356093
URL: https://svnweb.freebsd.org/changeset/base/356093

Log:
  MFC r355650:
    Follow RFC 4443 p2.2 and always use own addresses for reflected ICMPv6
    datagrams.
  
    Previously destination address from original datagram was used. That
    looked confusing, especially in the traceroute6 output.
    Also honor IPSTEALTH kernel option and do TTL/HLIM decrementing only
    when stealth mode is disabled.
  
    Reported by:	Marco van Tol <marco at tols org>
    Sponsored by:	Yandex LLC
    Differential Revision:	https://reviews.freebsd.org/D22631

Modified:
  stable/12/sys/modules/ipfw_nat64/Makefile
  stable/12/sys/netpfil/ipfw/nat64/nat64_translate.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/modules/ipfw_nat64/Makefile
==============================================================================
--- stable/12/sys/modules/ipfw_nat64/Makefile	Thu Dec 26 17:25:51 2019	(r356092)
+++ stable/12/sys/modules/ipfw_nat64/Makefile	Thu Dec 26 18:05:38 2019	(r356093)
@@ -7,6 +7,7 @@ SRCS=	ip_fw_nat64.c nat64_translate.c
 SRCS+=	nat64clat.c nat64clat_control.c
 SRCS+=	nat64lsn.c nat64lsn_control.c
 SRCS+=	nat64stl.c nat64stl_control.c
+SRCS+=	opt_ipstealth.h
 
 CFLAGS+= -I${SRCTOP}/sys/contrib/ck/include
 

Modified: stable/12/sys/netpfil/ipfw/nat64/nat64_translate.c
==============================================================================
--- stable/12/sys/netpfil/ipfw/nat64/nat64_translate.c	Thu Dec 26 17:25:51 2019	(r356092)
+++ stable/12/sys/netpfil/ipfw/nat64/nat64_translate.c	Thu Dec 26 18:05:38 2019	(r356093)
@@ -29,6 +29,8 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include "opt_ipstealth.h"
+
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/counter.h>
@@ -101,14 +103,39 @@ static const struct nat64_methods nat64_direct = {
 	.output = nat64_direct_output,
 	.output_one = nat64_direct_output_one
 };
-VNET_DEFINE_STATIC(const struct nat64_methods *, nat64out) = &nat64_netisr;
-#define	V_nat64out	VNET(nat64out)
 
+/* These variables should be initialized explicitly on module loading */
+VNET_DEFINE_STATIC(const struct nat64_methods *, nat64out);
+VNET_DEFINE_STATIC(const int *, nat64ipstealth);
+VNET_DEFINE_STATIC(const int *, nat64ip6stealth);
+#define	V_nat64out		VNET(nat64out)
+#define	V_nat64ipstealth	VNET(nat64ipstealth)
+#define	V_nat64ip6stealth	VNET(nat64ip6stealth)
+
+static const int stealth_on = 1;
+#ifndef IPSTEALTH
+static const int stealth_off = 0;
+#endif
+
 void
 nat64_set_output_method(int direct)
 {
 
-	V_nat64out = direct != 0 ? &nat64_direct: &nat64_netisr;
+	if (direct != 0) {
+		V_nat64out = &nat64_direct;
+#ifdef IPSTEALTH
+		/* Honor corresponding variables, if IPSTEALTH is defined */
+		V_nat64ipstealth = &V_ipstealth;
+		V_nat64ip6stealth = &V_ip6stealth;
+#else
+		/* otherwise we need to decrement HLIM/TTL for direct case */
+		V_nat64ipstealth = V_nat64ip6stealth = &stealth_off;
+#endif
+	} else {
+		V_nat64out = &nat64_netisr;
+		/* Leave TTL/HLIM decrementing to forwarding code */
+		V_nat64ipstealth = V_nat64ip6stealth = &stealth_on;
+	}
 }
 
 int
@@ -486,8 +513,7 @@ nat64_init_ip4hdr(const struct ip6_hdr *ip6, const str
 	ip->ip_tos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
 	ip->ip_len = htons(sizeof(*ip) + plen);
 	ip->ip_ttl = ip6->ip6_hlim;
-	/* Forwarding code will decrement TTL for netisr based output. */
-	if (V_nat64out == &nat64_direct)
+	if (*V_nat64ip6stealth == 0)
 		ip->ip_ttl -= IPV6_HLIMDEC;
 	ip->ip_sum = 0;
 	ip->ip_p = (proto == IPPROTO_ICMPV6) ? IPPROTO_ICMP: proto;
@@ -623,18 +649,18 @@ nat64_icmp6_reflect(struct mbuf *m, uint8_t type, uint
 	struct icmp6_hdr *icmp6;
 	struct ip6_hdr *ip6, *oip6;
 	struct mbuf *n;
-	int len, plen;
+	int len, plen, proto;
 
 	len = 0;
-	plen = nat64_getlasthdr(m, &len);
-	if (plen < 0) {
+	proto = nat64_getlasthdr(m, &len);
+	if (proto < 0) {
 		DPRINTF(DP_DROPS, "mbuf isn't contigious");
 		goto freeit;
 	}
 	/*
 	 * Do not send ICMPv6 in reply to ICMPv6 errors.
 	 */
-	if (plen == IPPROTO_ICMPV6) {
+	if (proto == IPPROTO_ICMPV6) {
 		if (m->m_len < len + sizeof(*icmp6)) {
 			DPRINTF(DP_DROPS, "mbuf isn't contigious");
 			goto freeit;
@@ -646,6 +672,21 @@ nat64_icmp6_reflect(struct mbuf *m, uint8_t type, uint
 			    "ICMPv6 errors");
 			goto freeit;
 		}
+		/*
+		 * If there are extra headers between IPv6 and ICMPv6,
+		 * strip off them.
+		 */
+		if (len > sizeof(struct ip6_hdr)) {
+			/*
+			 * NOTE: ipfw_chk already did m_pullup() and it is
+			 * expected that data is contigious from the start
+			 * of IPv6 header up to the end of ICMPv6 header.
+			 */
+			bcopy(mtod(m, caddr_t),
+			    mtodo(m, len - sizeof(struct ip6_hdr)),
+			    sizeof(struct ip6_hdr));
+			m_adj(m, len - sizeof(struct ip6_hdr));
+		}
 	}
 	/*
 	if (icmp6_ratelimit(&ip6->ip6_src, type, code))
@@ -687,7 +728,19 @@ nat64_icmp6_reflect(struct mbuf *m, uint8_t type, uint
 
 	n->m_len = n->m_pkthdr.len = sizeof(struct ip6_hdr) + plen;
 	oip6 = mtod(n, struct ip6_hdr *);
-	oip6->ip6_src = ip6->ip6_dst;
+	/*
+	 * Make IPv6 source address selection for reflected datagram.
+	 * nat64_check_ip6() doesn't allow scoped addresses, therefore
+	 * we use zero scopeid.
+	 */
+	if (in6_selectsrc_addr(M_GETFIB(n), &ip6->ip6_src, 0,
+	    n->m_pkthdr.rcvif, &oip6->ip6_src, NULL) != 0) {
+		/*
+		 * Failed to find proper source address, drop the packet.
+		 */
+		m_freem(n);
+		goto freeit;
+	}
 	oip6->ip6_dst = ip6->ip6_src;
 	oip6->ip6_nxt = IPPROTO_ICMPV6;
 	oip6->ip6_flow = 0;
@@ -1182,7 +1235,7 @@ nat64_do_handle_ip4(struct mbuf *m, struct in6_addr *s
 
 	ip = mtod(m, struct ip*);
 
-	if (ip->ip_ttl <= IPTTLDEC) {
+	if (*V_nat64ipstealth == 0 && ip->ip_ttl <= IPTTLDEC) {
 		nat64_icmp_reflect(m, ICMP_TIMXCEED,
 		    ICMP_TIMXCEED_INTRANS, 0, &cfg->stats, logdata);
 		return (NAT64RETURN);
@@ -1229,8 +1282,7 @@ nat64_do_handle_ip4(struct mbuf *m, struct in6_addr *s
 	ip6.ip6_flow = htonl(ip->ip_tos << 20);
 	ip6.ip6_vfc |= IPV6_VERSION;
 	ip6.ip6_hlim = ip->ip_ttl;
-	/* Forwarding code will decrement TTL for netisr based output. */
-	if (V_nat64out == &nat64_direct)
+	if (*V_nat64ipstealth == 0)
 		ip6.ip6_hlim -= IPTTLDEC;
 	ip6.ip6_plen = htons(plen);
 	ip6.ip6_nxt = (proto == IPPROTO_ICMP) ? IPPROTO_ICMPV6: proto;
@@ -1533,7 +1585,7 @@ nat64_do_handle_ip6(struct mbuf *m, uint32_t aaddr, ui
 		return (NAT64MFREE);
 	}
 
-	if (ip6->ip6_hlim <= IPV6_HLIMDEC) {
+	if (*V_nat64ip6stealth == 0 && ip6->ip6_hlim <= IPV6_HLIMDEC) {
 		nat64_icmp6_reflect(m, ICMP6_TIME_EXCEEDED,
 		    ICMP6_TIME_EXCEED_TRANSIT, 0, &cfg->stats, logdata);
 		return (NAT64RETURN);


More information about the svn-src-all mailing list