Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 17 Oct 2013 11:40:08 +0000 (UTC)
From:      "Andrey V. Elsukov" <ae@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r256675 - user/ae/inet6/sys/netinet6
Message-ID:  <201310171140.r9HBe8s2040153@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ae
Date: Thu Oct 17 11:40:08 2013
New Revision: 256675
URL: http://svnweb.freebsd.org/changeset/base/256675

Log:
  Rework icmp6_reflect():
  * sort variables declarations;
  * when incoming packet was addressed directly for us, use interface
    where it is configured as outgoing interface (XXX: is it correct?);
  * otherwise, use SAS Algorithm and keep route information, that it
    returns. Use this route in ip6_output().
  * since we always know outgoing interface, use IPV6_USEROIF flag
    for ip6_output()

Modified:
  user/ae/inet6/sys/netinet6/icmp6.c

Modified: user/ae/inet6/sys/netinet6/icmp6.c
==============================================================================
--- user/ae/inet6/sys/netinet6/icmp6.c	Thu Oct 17 11:33:16 2013	(r256674)
+++ user/ae/inet6/sys/netinet6/icmp6.c	Thu Oct 17 11:40:08 2013	(r256675)
@@ -227,7 +227,6 @@ void
 icmp6_error2(struct mbuf *m, int type, int code, int param,
     struct ifnet *ifp)
 {
-	struct ip6_hdr *ip6;
 
 	if (ifp == NULL)
 		return;
@@ -2119,13 +2118,14 @@ icmp6_rip6_input(struct mbuf **mp, int o
 void
 icmp6_reflect(struct mbuf *m, size_t off)
 {
+	struct route_in6 *ro, ro6;
+	struct in6_addr src, *srcp = NULL;
 	struct ip6_hdr *ip6;
 	struct icmp6_hdr *icmp6;
 	struct in6_ifaddr *ia = NULL;
-	int plen;
-	int type, code;
 	struct ifnet *outif = NULL;
-	struct in6_addr origdst, src, *srcp = NULL;
+	uint32_t zoneid;
+	int type, code, plen, error;
 
 	/* too short to reflect */
 	if (off < sizeof(struct ip6_hdr)) {
@@ -2172,13 +2172,6 @@ icmp6_reflect(struct mbuf *m, size_t off
 	type = icmp6->icmp6_type; /* keep type for statistics */
 	code = icmp6->icmp6_code; /* ditto. */
 
-	origdst = ip6->ip6_dst;
-	/*
-	 * ip6_input() drops a packet if its src is multicast.
-	 * So, the src is never multicast.
-	 */
-	ip6->ip6_dst = ip6->ip6_src;
-
 	/*
 	 * If the incoming packet was addressed directly to us (i.e. unicast),
 	 * use dst as the src for the reply.
@@ -2186,56 +2179,59 @@ icmp6_reflect(struct mbuf *m, size_t off
 	 * (for example) when we encounter an error while forwarding procedure
 	 * destined to a duplicated address of ours.
 	 */
+	zoneid = in6_getscopezone(m->m_pkthdr.rcvif,
+	    in6_addrscope(&ip6->ip6_dst));
 	if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
-		ia = in6ifa_ifwithaddr(&ip6->ip6_dst,
-		    in6_getscopezone(m->m_pkthdr.rcvif,
-		    in6_addrscope(&ip6->ip6_dst)));
+		ia = in6ifa_ifwithaddr(&ip6->ip6_dst, zoneid);
 		if (ia != NULL && !(ia->ia6_flags &
-		    (IN6_IFF_ANYCAST | IN6_IFF_NOTREADY)))
+		    (IN6_IFF_ANYCAST | IN6_IFF_NOTREADY))) {
 			srcp = &ia->ia_addr.sin6_addr;
+			outif = ia->ia_ifp; /* XXX: is it correct? */
+		}
 	}
+	ro = NULL;
 	if (srcp == NULL) {
-		int e;
 		struct sockaddr_in6 sin6;
-		struct route_in6 ro;
 
 		/*
 		 * 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.
 		 */
+		ro = &ro6;
+		bzero(&ro6, sizeof(ro6));
+		outif = m->m_pkthdr.rcvif;
+
 		bzero(&sin6, sizeof(sin6));
 		sin6.sin6_family = AF_INET6;
 		sin6.sin6_len = sizeof(sin6);
-		sin6.sin6_addr = ip6->ip6_dst; /* zone ID should be embedded */
-
-		bzero(&ro, sizeof(ro));
-		e = in6_selectsrc(&sin6, NULL, NULL, &ro, NULL, &outif, &src);
-		if (ro.ro_rt)
-			RTFREE(ro.ro_rt); /* XXX: we could use this */
-		if (e) {
+		sin6.sin6_addr = ip6->ip6_src;
+		sin6.sin6_scope_id = zoneid;
+		error = in6_selectsrc(&sin6, NULL, NULL, ro, NULL,
+		    &outif, &src);
+		if (error != 0) {
 			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, &sin6.sin6_addr), error));
+			RO_RTFREE(ro);
 			goto bad;
 		}
 		srcp = &src;
 	}
-
+	KASSERT(outif != NULL, ("%s: outif is NULL", __func__));
+	/*
+	 * ip6_input() drops a packet if its src is multicast.
+	 * So, the src is never multicast.
+	 */
+	ip6->ip6_dst = ip6->ip6_src;
 	ip6->ip6_src = *srcp;
 	ip6->ip6_flow = 0;
 	ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
 	ip6->ip6_vfc |= IPV6_VERSION;
 	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;
+	ip6->ip6_hlim = ND_IFINFO(outif)->chlim;
 
 	icmp6->icmp6_cksum = 0;
 	icmp6->icmp6_cksum = in6_cksum(m, IPPROTO_ICMPV6,
@@ -2247,12 +2243,12 @@ icmp6_reflect(struct mbuf *m, size_t off
 
 	m->m_flags &= ~(M_BCAST|M_MCAST);
 
-	ip6_output(m, NULL, NULL, 0, NULL, &outif, NULL);
-	if (outif)
-		icmp6_ifoutstat_inc(outif, type, code);
-
+	ip6_output(m, NULL, ro, IPV6_USEROIF, NULL, &outif, NULL);
+	icmp6_ifoutstat_inc(outif, type, code);
 	if (ia != NULL)
 		ifa_free(&ia->ia_ifa);
+	if (ro != NULL)
+		RO_RTFREE(ro);
 	return;
 
  bad:



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