Module Name:    src
Committed By:   roy
Date:           Fri Nov 24 14:03:25 UTC 2017

Modified Files:
        src/sys/netinet: ip_input.c
        src/sys/netinet6: in6_src.c ip6_input.c ip6_output.c

Log Message:
Allow local communication over DETACHED addresses.
Allow binding to DETACHED or TENTATIVE addresses as we deny
sending upstream from them anyway.
Prefer non DETACHED or TENTATIVE addresses.


To generate a diff of this commit:
cvs rdiff -u -r1.362 -r1.363 src/sys/netinet/ip_input.c
cvs rdiff -u -r1.82 -r1.83 src/sys/netinet6/in6_src.c
cvs rdiff -u -r1.183 -r1.184 src/sys/netinet6/ip6_input.c
cvs rdiff -u -r1.193 -r1.194 src/sys/netinet6/ip6_output.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/netinet/ip_input.c
diff -u src/sys/netinet/ip_input.c:1.362 src/sys/netinet/ip_input.c:1.363
--- src/sys/netinet/ip_input.c:1.362	Fri Nov 17 07:37:12 2017
+++ src/sys/netinet/ip_input.c	Fri Nov 24 14:03:25 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: ip_input.c,v 1.362 2017/11/17 07:37:12 ozaki-r Exp $	*/
+/*	$NetBSD: ip_input.c,v 1.363 2017/11/24 14:03:25 roy Exp $	*/
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -91,7 +91,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.362 2017/11/17 07:37:12 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.363 2017/11/24 14:03:25 roy Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -371,11 +371,14 @@ ip_match_our_address(struct ifnet *ifp, 
 				continue;
 			if (checkif && ia->ia_ifp != ifp)
 				continue;
-			if ((ia->ia_ifp->if_flags & IFF_UP) != 0 &&
-			    (ia->ia4_flags & IN_IFF_DETACHED) == 0)
-				break;
-			else
+			if ((ia->ia_ifp->if_flags & IFF_UP) == 0) {
 				(*downmatch)++;
+				continue;
+			}
+			if (ia->ia4_flags & IN_IFF_DETACHED &&
+			    (ifp->if_flags & IFF_LOOPBACK) == 0)
+				continue;
+			break;
 		}
 	}
 
@@ -392,7 +395,10 @@ ip_match_our_address_broadcast(struct if
 		if (ifa->ifa_addr->sa_family != AF_INET)
 			continue;
 		ia = ifatoia(ifa);
-		if (ia->ia4_flags & (IN_IFF_NOTREADY | IN_IFF_DETACHED))
+		if (ia->ia4_flags & IN_IFF_NOTREADY)
+			continue;
+		if (ia->ia4_flags & IN_IFF_DETACHED &&
+		    (ifp->if_flags & IFF_LOOPBACK) == 0)
 			continue;
 		if (in_hosteq(ip->ip_dst, ia->ia_broadaddr.sin_addr) ||
 		    in_hosteq(ip->ip_dst, ia->ia_netbroadcast) ||

Index: src/sys/netinet6/in6_src.c
diff -u src/sys/netinet6/in6_src.c:1.82 src/sys/netinet6/in6_src.c:1.83
--- src/sys/netinet6/in6_src.c:1.82	Mon Nov 20 09:01:20 2017
+++ src/sys/netinet6/in6_src.c	Fri Nov 24 14:03:25 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: in6_src.c,v 1.82 2017/11/20 09:01:20 ozaki-r Exp $	*/
+/*	$NetBSD: in6_src.c,v 1.83 2017/11/24 14:03:25 roy Exp $	*/
 /*	$KAME: in6_src.c,v 1.159 2005/10/19 01:40:32 t-momose Exp $	*/
 
 /*
@@ -66,7 +66,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in6_src.c,v 1.82 2017/11/20 09:01:20 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6_src.c,v 1.83 2017/11/24 14:03:25 roy Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -217,10 +217,14 @@ in6_select_best_ia(struct sockaddr_in6 *
 		}
 
 		/* avoid unusable addresses */
-		if ((ia->ia6_flags &
-		     (IN6_IFF_NOTREADY | IN6_IFF_ANYCAST | IN6_IFF_DETACHED))) {
-				continue;
-		}
+		if ((ia->ia6_flags & (IN6_IFF_DUPLICATED | IN6_IFF_ANYCAST)))
+			continue;
+		/* Prefer validated addresses */
+		if (!(ia->ia6_flags & (IN6_IFF_TENTATIVE | IN6_IFF_DETACHED)) &&
+		    ia_best != NULL &&
+		    ia_best->ia6_flags & (IN6_IFF_TENTATIVE | IN6_IFF_DETACHED))
+			REPLACE(0);
+
 		if (!ip6_use_deprecated && IFA6_IS_DEPRECATED(ia))
 			continue;
 
@@ -238,7 +242,7 @@ in6_select_best_ia(struct sockaddr_in6 *
 		}
 
 		if (ia_best == NULL)
-			REPLACE(0);
+			REPLACE(1);
 
 		/* Rule 2: Prefer appropriate scope */
 		if (dst_scope < 0)

Index: src/sys/netinet6/ip6_input.c
diff -u src/sys/netinet6/ip6_input.c:1.183 src/sys/netinet6/ip6_input.c:1.184
--- src/sys/netinet6/ip6_input.c:1.183	Fri Nov 17 07:37:12 2017
+++ src/sys/netinet6/ip6_input.c	Fri Nov 24 14:03:25 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: ip6_input.c,v 1.183 2017/11/17 07:37:12 ozaki-r Exp $	*/
+/*	$NetBSD: ip6_input.c,v 1.184 2017/11/24 14:03:25 roy Exp $	*/
 /*	$KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $	*/
 
 /*
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.183 2017/11/17 07:37:12 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.184 2017/11/24 14:03:25 roy Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_gateway.h"
@@ -501,13 +501,33 @@ ip6_input(struct mbuf *m, struct ifnet *
 #endif
 	    rt->rt_ifp->if_type == IFT_LOOP) {
 		struct in6_ifaddr *ia6 = (struct in6_ifaddr *)rt->rt_ifa;
+		int addrok;
+
 		if (ia6->ia6_flags & IN6_IFF_ANYCAST)
 			m->m_flags |= M_ANYCAST6;
 		/*
 		 * packets to a tentative, duplicated, or somehow invalid
 		 * address must not be accepted.
 		 */
-		if (!(ia6->ia6_flags & (IN6_IFF_NOTREADY | IN6_IFF_DETACHED))) {
+		if (ia6->ia6_flags & IN6_IFF_NOTREADY)
+			addrok = 0;
+		else if (ia6->ia6_flags & IN6_IFF_DETACHED &&
+		    !IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src))
+		{
+			/* Allow internal traffic to DETACHED addresses */
+			struct sockaddr_in6 sin6;
+			int s;
+
+			memset(&sin6, 0, sizeof(sin6));
+			sin6.sin6_family = AF_INET6;
+			sin6.sin6_len = sizeof(sin6);
+			sin6.sin6_addr = ip6->ip6_src;
+			s = pserialize_read_enter();
+			addrok = (ifa_ifwithaddr(sin6tosa(&sin6)) != NULL);
+			pserialize_read_exit(s);
+		} else
+			addrok = 0;
+		if (addrok) {
 			/* this address is ready */
 			ours = 1;
 			deliverifp = ia6->ia_ifp;	/* correct? */

Index: src/sys/netinet6/ip6_output.c
diff -u src/sys/netinet6/ip6_output.c:1.193 src/sys/netinet6/ip6_output.c:1.194
--- src/sys/netinet6/ip6_output.c:1.193	Wed Aug  2 01:28:03 2017
+++ src/sys/netinet6/ip6_output.c	Fri Nov 24 14:03:25 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: ip6_output.c,v 1.193 2017/08/02 01:28:03 ozaki-r Exp $	*/
+/*	$NetBSD: ip6_output.c,v 1.194 2017/11/24 14:03:25 roy Exp $	*/
 /*	$KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $	*/
 
 /*
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip6_output.c,v 1.193 2017/08/02 01:28:03 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip6_output.c,v 1.194 2017/11/24 14:03:25 roy Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -134,7 +134,7 @@ static int ip6_insert_jumboopt(struct ip
 static int ip6_splithdr(struct mbuf *, struct ip6_exthdrs *);
 static int ip6_getpmtu(struct rtentry *, struct ifnet *, u_long *, int *);
 static int copypktopts(struct ip6_pktopts *, struct ip6_pktopts *, int);
-static int ip6_ifaddrvalid(const struct in6_addr *);
+static int ip6_ifaddrvalid(const struct in6_addr *, const struct in6_addr *);
 static int ip6_handle_rthdr(struct ip6_rthdr *, struct ip6_hdr *);
 
 #ifdef RFC2292
@@ -605,7 +605,9 @@ ip6_output(
 	/* scope check is done. */
 
 	/* Ensure we only send from a valid address. */
-	if ((error = ip6_ifaddrvalid(&src0)) != 0) {
+	if ((ifp->if_flags & IFF_LOOPBACK) == 0 &&
+	    (error = ip6_ifaddrvalid(&src0, &dst0)) != 0)
+	{
 		char ip6buf[INET6_ADDRSTRLEN];
 		nd6log(LOG_ERR,
 		    "refusing to send from invalid address %s (pid %d)\n",
@@ -3363,27 +3365,31 @@ ip6_optlen(struct in6pcb *in6p)
  * if the packet could be dropped without error (protocol dependent).
  */
 static int
-ip6_ifaddrvalid(const struct in6_addr *addr)
+ip6_ifaddrvalid(const struct in6_addr *src, const struct in6_addr *dst)
 {
 	struct sockaddr_in6 sin6;
 	int s, error;
 	struct ifaddr *ifa;
 	struct in6_ifaddr *ia6;
 
-	if (IN6_IS_ADDR_UNSPECIFIED(addr))
+	if (IN6_IS_ADDR_UNSPECIFIED(src))
 		return 0;
 
 	memset(&sin6, 0, sizeof(sin6));
 	sin6.sin6_family = AF_INET6;
 	sin6.sin6_len = sizeof(sin6);
-	sin6.sin6_addr = *addr;
+	sin6.sin6_addr = *src;
 
 	s = pserialize_read_enter();
 	ifa = ifa_ifwithaddr(sin6tosa(&sin6));
 	if ((ia6 = ifatoia6(ifa)) == NULL ||
 	    ia6->ia6_flags & (IN6_IFF_ANYCAST | IN6_IFF_DUPLICATED))
 		error = -1;
-	else if (ia6->ia6_flags & (IN6_IFF_TENTATIVE | IN6_IFF_DETACHED))
+	else if (ia6->ia6_flags & IN6_IFF_TENTATIVE)
+		error = 1;
+	else if (ia6->ia6_flags & IN6_IFF_DETACHED &&
+	    ifa_ifwithaddr(sin6tosa(&dst)) == NULL)
+		/* Allow internal traffic to DETACHED addresses */
 		error = 1;
 	else
 		error = 0;

Reply via email to