Module Name:    src
Committed By:   roy
Date:           Sun Sep  1 18:54:38 UTC 2019

Modified Files:
        src/sys/net: rtsock.c
        src/sys/netinet6: nd6.c nd6_nbr.c

Log Message:
inet6: Send RTM_MISS when we fail to resolve an address.

Takes the same approach as when adding a new address - we no longer
announce the new lladdr right away but we announce the result.
This will either be RTM_ADD or RTM_MISS.
RTM_DELETE is only sent if we have a lladdr assigned OR gc'ed.

This results in less messages via route(4) and tells us when a new
lladdr has been added (RTM_ADD), changed (RTM_CHANGE), deleted (RTM_DELETED)
or has failed to been resolved (RTM_MISS). The latter case can be
interpreted as unreachable.


To generate a diff of this commit:
cvs rdiff -u -r1.251 -r1.252 src/sys/net/rtsock.c
cvs rdiff -u -r1.261 -r1.262 src/sys/netinet6/nd6.c
cvs rdiff -u -r1.171 -r1.172 src/sys/netinet6/nd6_nbr.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/net/rtsock.c
diff -u src/sys/net/rtsock.c:1.251 src/sys/net/rtsock.c:1.252
--- src/sys/net/rtsock.c:1.251	Thu Aug 22 21:14:45 2019
+++ src/sys/net/rtsock.c	Sun Sep  1 18:54:38 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: rtsock.c,v 1.251 2019/08/22 21:14:45 roy Exp $	*/
+/*	$NetBSD: rtsock.c,v 1.252 2019/09/01 18:54:38 roy Exp $	*/
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.251 2019/08/22 21:14:45 roy Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.252 2019/09/01 18:54:38 roy Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -152,21 +152,21 @@ rt_clonedmsg(int type, const struct sock
 	/* Mimic flags exactly */
 #define RTF_LLINFO	0x400
 #define RTF_CLONED	0x2000
-	int flags = RTF_HOST | RTF_DONE | RTF_LLINFO | RTF_CLONED;
+	int flags = RTF_DONE;
 	union {
 		struct sockaddr sa;
 		struct sockaddr_storage ss;
 		struct sockaddr_dl sdl;
 	} u;
-	uint8_t namelen = strlen(ifp->if_xname);
-	uint8_t addrlen = ifp->if_addrlen;
 
-	if (type != RTM_DELETE)
+	if (type != RTM_MISS)
+		flags |= RTF_HOST | RTF_CLONED | RTF_LLINFO;
+	if (type == RTM_ADD || type == RTM_CHANGE)
 		flags |= RTF_UP;
 	memset(&info, 0, sizeof(info));
 	info.rti_info[RTAX_DST] = dst;
 	sockaddr_dl_init(&u.sdl, sizeof(u.ss), ifp->if_index, ifp->if_type,
-	    NULL, namelen, lladdr, addrlen);
+	    NULL, 0, lladdr, ifp->if_addrlen);
 	info.rti_info[RTAX_GATEWAY] = &u.sa;
 
 	rt_missmsg(type, &info, flags, 0);

Index: src/sys/netinet6/nd6.c
diff -u src/sys/netinet6/nd6.c:1.261 src/sys/netinet6/nd6.c:1.262
--- src/sys/netinet6/nd6.c:1.261	Sat Aug 31 01:49:45 2019
+++ src/sys/netinet6/nd6.c	Sun Sep  1 18:54:38 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: nd6.c,v 1.261 2019/08/31 01:49:45 roy Exp $	*/
+/*	$NetBSD: nd6.c,v 1.262 2019/09/01 18:54:38 roy Exp $	*/
 /*	$KAME: nd6.c,v 1.279 2002/06/08 11:16:51 itojun Exp $	*/
 
 /*
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.261 2019/08/31 01:49:45 roy Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.262 2019/09/01 18:54:38 roy Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_net_mpsafe.h"
@@ -461,6 +461,8 @@ nd6_llinfo_timer(void *arg)
 	struct nd_ifinfo *ndi = NULL;
 	bool send_ns = false;
 	const struct in6_addr *daddr6 = NULL;
+	const struct in6_addr *taddr6 = &ln->r_l3addr.addr6;
+	struct sockaddr_in6 sin6;
 
 	SOFTNET_KERNEL_LOCK_UNLESS_NET_MPSAFE();
 
@@ -472,7 +474,6 @@ nd6_llinfo_timer(void *arg)
 		goto out;
 	}
 
-
 	ifp = ln->lle_tbl->llt_ifp;
 	KASSERT(ifp != NULL);
 
@@ -483,29 +484,33 @@ nd6_llinfo_timer(void *arg)
 		if (ln->ln_asked < nd6_mmaxtries) {
 			ln->ln_asked++;
 			send_ns = true;
-		} else {
-			struct mbuf *m = ln->ln_hold;
-			if (m) {
-				struct mbuf *m0;
+			break;
+		}
 
-				/*
-				 * assuming every packet in ln_hold has
-				 * the same IP header
-				 */
-				m0 = m->m_nextpkt;
-				m->m_nextpkt = NULL;
-				ln->ln_hold = m0;
-				clear_llinfo_pqueue(ln);
- 			}
-			LLE_REMREF(ln);
-			nd6_free(ln, 0);
-			ln = NULL;
-			if (m != NULL) {
-				icmp6_error2(m, ICMP6_DST_UNREACH,
-				    ICMP6_DST_UNREACH_ADDR, 0, ifp);
-			}
+		if (ln->ln_hold) {
+			struct mbuf *m = ln->ln_hold, *m0;
+
+			/*
+			 * assuming every packet in ln_hold has
+			 * the same IP header
+			 */
+			m0 = m->m_nextpkt;
+			m->m_nextpkt = NULL;
+			ln->ln_hold = m0;
+			clear_llinfo_pqueue(ln);
+
+			icmp6_error2(m, ICMP6_DST_UNREACH,
+			    ICMP6_DST_UNREACH_ADDR, 0, ifp);
 		}
+
+		sockaddr_in6_init(&sin6, taddr6, 0, 0, 0);
+		rt_clonedmsg(RTM_MISS, sin6tosa(&sin6), NULL, ifp);
+
+		LLE_REMREF(ln);
+		nd6_free(ln, 0);
+		ln = NULL;
 		break;
+
 	case ND6_LLINFO_REACHABLE:
 		if (!ND6_LLINFO_PERMANENT(ln)) {
 			ln->ln_state = ND6_LLINFO_STALE;
@@ -550,7 +555,6 @@ nd6_llinfo_timer(void *arg)
 
 	if (send_ns) {
 		struct in6_addr src, *psrc;
-		const struct in6_addr *taddr6 = &ln->r_l3addr.addr6;
 
 		nd6_llinfo_settimer(ln, ndi->retrans * hz / 1000);
 		psrc = nd6_llinfo_get_holdsrc(ln, &src);
@@ -1191,8 +1195,6 @@ nd6_free(struct llentry *ln, int gc)
 {
 	struct ifnet *ifp;
 	struct in6_addr *in6;
-	struct sockaddr_in6 sin6;
-	const char *lladdr;
 
 	KASSERT(ln != NULL);
 	LLE_WLOCK_ASSERT(ln);
@@ -1282,9 +1284,15 @@ nd6_free(struct llentry *ln, int gc)
 		LLE_WLOCK(ln);
 	}
 
-	sockaddr_in6_init(&sin6, in6, 0, 0, 0);
-	lladdr = ln->la_flags & LLE_VALID ? (const char *)&ln->ll_addr : NULL;
-	rt_clonedmsg(RTM_DELETE, sin6tosa(&sin6), lladdr, ifp);
+	if (ln->la_flags & LLE_VALID || gc) {
+		struct sockaddr_in6 sin6;
+		const char *lladdr;
+
+		sockaddr_in6_init(&sin6, in6, 0, 0, 0);
+		lladdr = ln->la_flags & LLE_VALID ?
+		    (const char *)&ln->ll_addr : NULL;
+		rt_clonedmsg(RTM_DELETE, sin6tosa(&sin6), lladdr, ifp);
+	}
 
 	/*
 	 * Save to unlock. We still hold an extra reference and will not
@@ -2218,7 +2226,7 @@ nd6_cache_lladdr(
 		break;
 	}
 
-	if (do_update) {
+	if (do_update && lladdr != NULL) {
 		struct sockaddr_in6 sin6;
 
 		sockaddr_in6_init(&sin6, from, 0, 0, 0);
@@ -2334,7 +2342,6 @@ nd6_resolve(struct ifnet *ifp, const str
 	/* Slow path */
 	ln = nd6_lookup(&dst->sin6_addr, ifp, true);
 	if (ln == NULL && nd6_is_addr_neighbor(dst, ifp))  {
-		struct sockaddr_in6 sin6;
 		/*
 		 * Since nd6_is_addr_neighbor() internally calls nd6_lookup(),
 		 * the condition below is not very efficient.  But we believe
@@ -2350,11 +2357,6 @@ nd6_resolve(struct ifnet *ifp, const str
 			m_freem(m);
 			return ENOBUFS;
 		}
-
-		sockaddr_in6_init(&sin6, &ln->r_l3addr.addr6, 0, 0, 0);
-		if (rt != NULL)
-			rt_clonedmsg(RTM_ADD, sin6tosa(&sin6), NULL, ifp);
-
 		created = true;
 	}
 
@@ -2439,12 +2441,9 @@ nd6_resolve(struct ifnet *ifp, const str
 		nd6_llinfo_settimer(ln, ND_IFINFO(ifp)->retrans * hz / 1000);
 		psrc = nd6_llinfo_get_holdsrc(ln, &src);
 		LLE_WUNLOCK(ln);
-		ln = NULL;
 		nd6_ns_output(ifp, NULL, &dst->sin6_addr, psrc, NULL);
-	} else {
-		/* We did the lookup so we need to do the unlock here. */
+	} else
 		LLE_WUNLOCK(ln);
-	}
 
 	if (created)
 		nd6_gc_neighbors(LLTABLE6(ifp), &dst->sin6_addr);

Index: src/sys/netinet6/nd6_nbr.c
diff -u src/sys/netinet6/nd6_nbr.c:1.171 src/sys/netinet6/nd6_nbr.c:1.172
--- src/sys/netinet6/nd6_nbr.c:1.171	Fri Aug 30 08:40:25 2019
+++ src/sys/netinet6/nd6_nbr.c	Sun Sep  1 18:54:38 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: nd6_nbr.c,v 1.171 2019/08/30 08:40:25 roy Exp $	*/
+/*	$NetBSD: nd6_nbr.c,v 1.172 2019/09/01 18:54:38 roy Exp $	*/
 /*	$KAME: nd6_nbr.c,v 1.61 2001/02/10 16:06:14 jinmei Exp $	*/
 
 /*
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nd6_nbr.c,v 1.171 2019/08/30 08:40:25 roy Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nd6_nbr.c,v 1.172 2019/09/01 18:54:38 roy Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -605,13 +605,13 @@ nd6_na_input(struct mbuf *m, int off, in
 	int is_router;
 	int is_solicited;
 	int is_override;
+	int rt_cmd;
 	char *lladdr = NULL;
 	int lladdrlen = 0;
 	struct ifaddr *ifa;
 	struct llentry *ln = NULL;
 	union nd_opts ndopts;
 	struct sockaddr_in6 ssin6;
-	bool rt_announce;
 	bool checklink = false;
 	struct psref psref;
 	struct psref psref_ia;
@@ -735,7 +735,7 @@ nd6_na_input(struct mbuf *m, int off, in
 	if (ln == NULL)
 		goto freeit;
 
-	rt_announce = false;
+	rt_cmd = 0;
 	if (ln->ln_state == ND6_LLINFO_INCOMPLETE) {
 		/*
 		 * If the link-layer has address, and no lladdr option came,
@@ -749,7 +749,7 @@ nd6_na_input(struct mbuf *m, int off, in
 		 */
 		memcpy(&ln->ll_addr, lladdr, ifp->if_addrlen);
 		ln->la_flags |= LLE_VALID;
-		rt_announce = true;
+		rt_cmd = RTM_ADD;
 		if (is_solicited) {
 			ln->ln_state = ND6_LLINFO_REACHABLE;
 			ln->ln_byhint = 0;
@@ -780,12 +780,14 @@ nd6_na_input(struct mbuf *m, int off, in
 		else {
 			if (ln->la_flags & LLE_VALID) {
 				if (memcmp(lladdr, &ln->ll_addr, ifp->if_addrlen))
-					llchange = rt_announce = true;
+					llchange = true;
 				else
 					llchange = false;
 			} else
-				llchange = rt_announce = true;
+				llchange = true;
 		}
+		if (llchange)
+			rt_cmd = RTM_CHANGE;
 
 		/*
 		 * This is VERY complex.  Look at it with care.
@@ -882,11 +884,11 @@ nd6_na_input(struct mbuf *m, int off, in
 	ln->ln_asked = 0;
 	nd6_llinfo_release_pkts(ln, ifp);
 
-	if (rt_announce) {
+	if (rt_cmd != 0) {
 		struct sockaddr_in6 sin6;
 
 		sockaddr_in6_init(&sin6, &ln->r_l3addr.addr6, 0, 0, 0);
-		rt_clonedmsg(RTM_CHANGE, sin6tosa(&sin6),
+		rt_clonedmsg(rt_cmd, sin6tosa(&sin6),
 		    (char *)&ln->ll_addr, ln->lle_tbl->llt_ifp);
 	}
 

Reply via email to