tech-net archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Detached address check



On 22/11/2017 12:26, Roy Marples wrote:
On 22/11/2017 11:49, Roy Marples wrote:
That's a fair comment.
I've attached a patch which should fix this for IPv4 at least.

Simpler patch attached.

Now includes IPv6.
ping/ping6 and telnet to ipv4/ipv6 detached addresses works fine.

Let me know if this fixes everything for you please.

Roy
? sys/netinet6/.nd6_nbr.c.swp
Index: sys/netinet/ip_input.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/ip_input.c,v
retrieving revision 1.362
diff -u -p -r1.362 ip_input.c
--- sys/netinet/ip_input.c	17 Nov 2017 07:37:12 -0000	1.362
+++ sys/netinet/ip_input.c	22 Nov 2017 16:23:32 -0000
@@ -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: sys/netinet6/in6_src.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/in6_src.c,v
retrieving revision 1.82
diff -u -p -r1.82 in6_src.c
--- sys/netinet6/in6_src.c	20 Nov 2017 09:01:20 -0000	1.82
+++ sys/netinet6/in6_src.c	22 Nov 2017 16:23:33 -0000
@@ -218,7 +218,7 @@ in6_select_best_ia(struct sockaddr_in6 *
 
 		/* avoid unusable addresses */
 		if ((ia->ia6_flags &
-		     (IN6_IFF_NOTREADY | IN6_IFF_ANYCAST | IN6_IFF_DETACHED))) {
+		     (IN6_IFF_NOTREADY | IN6_IFF_ANYCAST))) {
 				continue;
 		}
 		if (!ip6_use_deprecated && IFA6_IS_DEPRECATED(ia))
Index: sys/netinet6/ip6_input.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/ip6_input.c,v
retrieving revision 1.183
diff -u -p -r1.183 ip6_input.c
--- sys/netinet6/ip6_input.c	17 Nov 2017 07:37:12 -0000	1.183
+++ sys/netinet6/ip6_input.c	22 Nov 2017 16:23:33 -0000
@@ -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: sys/netinet6/ip6_output.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/ip6_output.c,v
retrieving revision 1.193
diff -u -p -r1.193 ip6_output.c
--- sys/netinet6/ip6_output.c	2 Aug 2017 01:28:03 -0000	1.193
+++ sys/netinet6/ip6_output.c	22 Nov 2017 16:23:33 -0000
@@ -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;


Home | Main Index | Thread Index | Old Index