Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 10 Jan 2016 11:59:56 +0000 (UTC)
From:      "Alexander V. Chernikov" <melifaro@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r293632 - head/sys/netinet6
Message-ID:  <201601101159.u0ABxuGp088030@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: melifaro
Date: Sun Jan 10 11:59:55 2016
New Revision: 293632
URL: https://svnweb.freebsd.org/changeset/base/293632

Log:
  Do not hold ifaddr reference for the whole icmp6_reflect() exec time.
  
  Copy source address, calculate hlim and release refcount instead.

Modified:
  head/sys/netinet6/icmp6.c

Modified: head/sys/netinet6/icmp6.c
==============================================================================
--- head/sys/netinet6/icmp6.c	Sun Jan 10 08:41:01 2016	(r293631)
+++ head/sys/netinet6/icmp6.c	Sun Jan 10 11:59:55 2016	(r293632)
@@ -2114,13 +2114,13 @@ icmp6_rip6_input(struct mbuf **mp, int o
 void
 icmp6_reflect(struct mbuf *m, size_t off)
 {
-	struct in6_addr src, *srcp = NULL;
+	struct in6_addr src6, *srcp;
 	struct ip6_hdr *ip6;
 	struct icmp6_hdr *icmp6;
 	struct in6_ifaddr *ia = NULL;
 	struct ifnet *outif = NULL;
 	int plen;
-	int type, code;
+	int type, code, hlim;
 
 	/* too short to reflect */
 	if (off < sizeof(struct ip6_hdr)) {
@@ -2166,6 +2166,8 @@ icmp6_reflect(struct mbuf *m, size_t off
 	icmp6 = (struct icmp6_hdr *)(ip6 + 1);
 	type = icmp6->icmp6_type; /* keep type for statistics */
 	code = icmp6->icmp6_code; /* ditto. */
+	hlim = 0;
+	srcp = NULL;
 
 	/*
 	 * If the incoming packet was addressed directly to us (i.e. unicast),
@@ -2177,8 +2179,18 @@ icmp6_reflect(struct mbuf *m, size_t off
 	if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
 		ia = in6ifa_ifwithaddr(&ip6->ip6_dst, 0 /* XXX */);
 		if (ia != NULL && !(ia->ia6_flags &
-		    (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY)))
-			srcp = &ia->ia_addr.sin6_addr;
+		    (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY))) {
+			src6 = ia->ia_addr.sin6_addr;
+			srcp = &src6;
+
+			if (m->m_pkthdr.rcvif != NULL) {
+				/* XXX: This may not be the outgoing interface */
+				hlim = ND_IFINFO(m->m_pkthdr.rcvif)->chlim;
+			} else
+				hlim = V_ip6_defhlim;
+		}
+		if (ia != NULL)
+			ifa_free(&ia->ia_ifa);
 	}
 
 	if (srcp == NULL) {
@@ -2195,16 +2207,16 @@ icmp6_reflect(struct mbuf *m, size_t off
 		sin6.sin6_len = sizeof(sin6);
 		sin6.sin6_addr = ip6->ip6_dst; /* zone ID should be embedded */
 
-		e = in6_selectsrc(&sin6, NULL, NULL, NULL, &outif, &src);
+		e = in6_selectsrc(&sin6, NULL, NULL, NULL, &outif, &src6);
 		if (e) {
 			char ip6buf[INET6_ADDRSTRLEN];
 			nd6log((LOG_DEBUG,
 			    "icmp6_reflect: source can't be determined: "
 			    "dst=%s, error=%d\n",
-			    ip6_sprintf(ip6buf, &sin6.sin6_addr), e));
+			    ip6_sprintf(ip6buf, &ip6->ip6_dst), e));
 			goto bad;
 		}
-		srcp = &src;
+		srcp = &src6;
 	}
 	/*
 	 * ip6_input() drops a packet if its src is multicast.
@@ -2218,11 +2230,8 @@ icmp6_reflect(struct mbuf *m, size_t off
 	ip6->ip6_nxt = IPPROTO_ICMPV6;
 	if (outif)
 		ip6->ip6_hlim = ND_IFINFO(outif)->chlim;
-	else if (m->m_pkthdr.rcvif) {
-		/* XXX: This may not be the outgoing interface */
-		ip6->ip6_hlim = ND_IFINFO(m->m_pkthdr.rcvif)->chlim;
-	} else
-		ip6->ip6_hlim = V_ip6_defhlim;
+	else
+		ip6->ip6_hlim = hlim;
 
 	icmp6->icmp6_cksum = 0;
 	icmp6->icmp6_cksum = in6_cksum(m, IPPROTO_ICMPV6,
@@ -2238,13 +2247,9 @@ icmp6_reflect(struct mbuf *m, size_t off
 	if (outif)
 		icmp6_ifoutstat_inc(outif, type, code);
 
-	if (ia != NULL)
-		ifa_free(&ia->ia_ifa);
 	return;
 
  bad:
-	if (ia != NULL)
-		ifa_free(&ia->ia_ifa);
 	m_freem(m);
 	return;
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201601101159.u0ABxuGp088030>