Index: sys/netinet6/in6.c
===================================================================
--- sys/netinet6/in6.c	(revision 255235)
+++ sys/netinet6/in6.c	(working copy)
@@ -140,8 +140,9 @@
 #define ia62ifa(ia6)	(&((ia6)->ia_ifa))
 
 void
-in6_ifaddloop(struct ifaddr *ifa)
+in6_ifdoloop(struct ifaddr *ifa, int llflags)
 {
+	int announcing;
 	struct sockaddr_dl gateway;
 	struct sockaddr_in6 mask, addr;
 	struct rtentry rt;
@@ -151,73 +152,63 @@
 
 	ia = ifa2ia6(ifa);
 	ifp = ifa->ifa_ifp;
-	IF_AFDATA_LOCK(ifp);
-	ifa->ifa_rtrequest = NULL;
-
-	/* XXX QL
-	 * we need to report rt_newaddrmsg
-	 */
-	ln = lla_lookup(LLTABLE6(ifp), (LLE_CREATE | LLE_IFADDR |
-	    LLE_EXCLUSIVE), (struct sockaddr *)&ia->ia_addr);
-	IF_AFDATA_UNLOCK(ifp);
-	if (ln != NULL) {
-		ln->la_expire = 0;  /* for IPv6 this means permanent */
-		ln->ln_state = ND6_LLINFO_REACHABLE;
-		/*
-		 * initialize for rtmsg generation
-		 */
+	/* Don't report new tentative addresses to the routing socket */
+	announcing = (llflags & LLE_DELETE ||
+	    ((ia->ia6_flags & IN6_IFF_TENTATIVE) == 0));
+	if (announcing) {
+		memcpy(&addr, &ia->ia_addr, sizeof(ia->ia_addr));
+		memcpy(&mask, &ia->ia_prefixmask, sizeof(ia->ia_prefixmask));
 		bzero(&gateway, sizeof(gateway));
 		gateway.sdl_len = sizeof(gateway);
 		gateway.sdl_family = AF_LINK;
 		gateway.sdl_nlen = 0;
-		gateway.sdl_alen = 6;
-		memcpy(gateway.sdl_data, &ln->ll_addr.mac_aligned,
-		    sizeof(ln->ll_addr));
-		LLE_WUNLOCK(ln);
+		bzero(&rt, sizeof(rt));
+		rt.rt_gateway = (struct sockaddr *)&gateway;
+		rt.rt_flags = RTF_HOST | RTF_STATIC;
+		rt_mask(&rt) = (struct sockaddr *)&mask;
+		rt_key(&rt) = (struct sockaddr *)&addr;
 	}
 
-	bzero(&rt, sizeof(rt));
-	rt.rt_gateway = (struct sockaddr *)&gateway;
-	memcpy(&mask, &ia->ia_prefixmask, sizeof(ia->ia_prefixmask));
-	memcpy(&addr, &ia->ia_addr, sizeof(ia->ia_addr));
-	rt_mask(&rt) = (struct sockaddr *)&mask;
-	rt_key(&rt) = (struct sockaddr *)&addr;
-	rt.rt_flags = RTF_UP | RTF_HOST | RTF_STATIC;
-	rt_newaddrmsg(RTM_ADD, ifa, 0, &rt);
-}
+	if (llflags & LLE_DELETE) {
+		lltable_prefix_free(AF_INET6, (struct sockaddr *)&addr,
+		    (struct sockaddr *)&mask, LLE_STATIC);
+		gateway.sdl_alen = ifp->if_addrlen;
+	} else {
+		llflags |= LLE_IFADDR;
+		IF_AFDATA_LOCK(ifp);
+		if (llflags & LLE_CREATE) {
+			llflags |= LLE_EXCLUSIVE;
+		        ifa->ifa_rtrequest = NULL; // -current use nd6_rtrequest
+		}
+		ln = lla_lookup(LLTABLE6(ifp), llflags,
+		    (struct sockaddr *)&ia->ia_addr);
+		IF_AFDATA_UNLOCK(ifp);
+		if (ln != NULL) {
+			if (llflags & LLE_CREATE) {
+				ln->la_expire = 0;  /* permanent */
+				ln->ln_state = ND6_LLINFO_REACHABLE;
+			}
+			if (announcing) {
+				gateway.sdl_alen = 6;
+				memcpy(gateway.sdl_data,
+				    &ln->ll_addr.mac_aligned,
+				    sizeof(ln->ll_addr));
+			}
+			if (llflags & LLE_EXCLUSIVE)
+				LLE_WUNLOCK(ln);
+			else
+				LLE_RUNLOCK(ln);
+		}
+	}
 
-void
-in6_ifremloop(struct ifaddr *ifa)
-{
-	struct sockaddr_dl gateway;
-	struct sockaddr_in6 mask, addr;
-	struct rtentry rt0;
-	struct in6_ifaddr *ia;
-	struct ifnet *ifp;
-
-	ia = ifa2ia6(ifa);
-	ifp = ifa->ifa_ifp;
-	IF_AFDATA_LOCK(ifp);
-	lla_lookup(LLTABLE6(ifp), (LLE_DELETE | LLE_IFADDR),
-	    (struct sockaddr *)&ia->ia_addr);
-	IF_AFDATA_UNLOCK(ifp);
-
-	/*
-	 * initialize for rtmsg generation
-	 */
-	bzero(&gateway, sizeof(gateway));
-	gateway.sdl_len = sizeof(gateway);
-	gateway.sdl_family = AF_LINK;
-	gateway.sdl_nlen = 0;
-	gateway.sdl_alen = ifp->if_addrlen;
-	bzero(&rt0, sizeof(rt0));
-	rt0.rt_gateway = (struct sockaddr *)&gateway;
-	memcpy(&mask, &ia->ia_prefixmask, sizeof(ia->ia_prefixmask));
-	memcpy(&addr, &ia->ia_addr, sizeof(ia->ia_addr));
-	rt_mask(&rt0) = (struct sockaddr *)&mask;
-	rt_key(&rt0) = (struct sockaddr *)&addr;
-	rt0.rt_flags = RTF_HOST | RTF_STATIC;
-	rt_newaddrmsg(RTM_DELETE, ifa, 0, &rt0);
+	if (announcing) {
+		if (llflags & LLE_DELETE)
+			rt_newaddrmsg(RTM_DELETE, ifa, 0, &rt);
+		else {
+			rt.rt_flags |= RTF_UP;
+			rt_newaddrmsg(RTM_ADD, ifa, 0, &rt);
+		}
+	}
 }
 
 int
@@ -1021,10 +1012,6 @@
 	} else
 		ia->ia6_lifetime.ia6t_preferred = 0;
 
-	/* reset the interface and routing table appropriately. */
-	if ((error = in6_ifinit(ifp, ia, &ifra->ifra_addr, hostIsNew)) != 0)
-		goto unlink;
-
 	/*
 	 * configure address flags.
 	 */
@@ -1050,6 +1037,10 @@
 	if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)
 		ia->ia6_flags |= IN6_IFF_TENTATIVE;
 
+	/* reset the interface and routing table appropriately. */
+	if ((error = in6_ifinit(ifp, ia, &ifra->ifra_addr, hostIsNew)) != 0)
+		goto unlink;
+
 	/*
 	 * We are done if we have simply modified an existing address.
 	 */
@@ -1885,6 +1876,8 @@
 	/* Add ownaddr as loopback rtentry, if necessary (ex. on p2p link). */
 	if (newhost)
 		in6_ifaddloop(&(ia->ia_ifa));
+	else
+		nd6_newaddrmsg(&(ia->ia_ifa));
 
 	return (error);
 }
Index: sys/netinet6/in6_var.h
===================================================================
--- sys/netinet6/in6_var.h	(revision 255235)
+++ sys/netinet6/in6_var.h	(working copy)
@@ -775,8 +775,9 @@
 int	in6_prefix_add_ifid __P((int, struct in6_ifaddr *));
 void	in6_prefix_remove_ifid __P((int, struct in6_ifaddr *));
 void	in6_purgeprefix __P((struct ifnet *));
-void	in6_ifremloop(struct ifaddr *);
-void	in6_ifaddloop(struct ifaddr *);
+void	in6_ifdoloop(struct ifaddr *, int);
+#define	in6_ifaddloop(ifa)	in6_ifdoloop((ifa), LLE_CREATE)
+#define	in6_ifremloop(ifa)	in6_ifdoloop((ifa), LLE_DELETE)
 
 int	in6_is_addr_deprecated __P((struct sockaddr_in6 *));
 struct inpcb;
Index: sys/netinet6/nd6.c
===================================================================
--- sys/netinet6/nd6.c	(revision 255235)
+++ sys/netinet6/nd6.c	(working copy)
@@ -632,7 +632,10 @@
 		} else if (IFA6_IS_DEPRECATED(ia6)) {
 			int oldflags = ia6->ia6_flags;
 
-			ia6->ia6_flags |= IN6_IFF_DEPRECATED;
+			if ((oldflags & IN6_IFF_DEPRECATED) == 0) {
+				ia6->ia6_flags |= IN6_IFF_DEPRECATED;
+				nd6_newaddrmsg((struct ifaddr *)ia6);
+			}
 
 			/*
 			 * If a temporary address has just become deprecated,
@@ -663,7 +666,10 @@
 			 * A new RA might have made a deprecated address
 			 * preferred.
 			 */
-			ia6->ia6_flags &= ~IN6_IFF_DEPRECATED;
+			if (ia6->ia6_flags & IN6_IFF_DEPRECATED) {
+				ia6->ia6_flags &= ~IN6_IFF_DEPRECATED;
+				nd6_newaddrmsg((struct ifaddr *)ia6);
+			}
 		}
 	}
 
Index: sys/netinet6/nd6.h
===================================================================
--- sys/netinet6/nd6.h	(revision 255235)
+++ sys/netinet6/nd6.h	(working copy)
@@ -428,6 +428,7 @@
 void nd6_ns_output __P((struct ifnet *, const struct in6_addr *,
 	const struct in6_addr *, struct llentry *, int));
 caddr_t nd6_ifptomac __P((struct ifnet *));
+#define nd6_newaddrmsg(ifa)	in6_ifdoloop((ifa), 0)
 void nd6_dad_start __P((struct ifaddr *, int));
 void nd6_dad_stop __P((struct ifaddr *));
 void nd6_dad_duplicated __P((struct ifaddr *));
Index: sys/netinet6/nd6_nbr.c
===================================================================
--- sys/netinet6/nd6_nbr.c	(revision 255235)
+++ sys/netinet6/nd6_nbr.c	(working copy)
@@ -1218,14 +1218,11 @@
 			ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
 		return;
 	}
-	if (ia->ia6_flags & IN6_IFF_ANYCAST) {
+	if (ia->ia6_flags & IN6_IFF_ANYCAST || !V_ip6_dad_count) {
 		ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
+		nd6_newaddrmsg(ifa);
 		return;
 	}
-	if (!V_ip6_dad_count) {
-		ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
-		return;
-	}
 	if (ifa->ifa_ifp == NULL)
 		panic("nd6_dad_start: ifa->ifa_ifp == NULL");
 	if (!(ifa->ifa_ifp->if_flags & IFF_UP)) {
@@ -1383,6 +1380,7 @@
 			 * No duplicate address found.
 			 */
 			ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
+			nd6_newaddrmsg(ifa);
 
 			nd6log((LOG_DEBUG,
 			    "%s: DAD complete for %s - no duplicates found\n",
@@ -1432,6 +1430,9 @@
 	log(LOG_ERR, "%s: manual intervention required\n",
 	    if_name(ifp));
 
+	/* Inform the routing socket that DAD has completed */
+	nd6_newaddrmsg(ifa);
+
 	/*
 	 * If the address is a link-local address formed from an interface
 	 * identifier based on the hardware address which is supposed to be
Index: sys/netinet6/nd6_rtr.c
===================================================================
--- sys/netinet6/nd6_rtr.c	(revision 255235)
+++ sys/netinet6/nd6_rtr.c	(working copy)
@@ -1525,9 +1525,15 @@
 					ifa->ia6_flags &= ~IN6_IFF_DETACHED;
 					ifa->ia6_flags |= IN6_IFF_TENTATIVE;
 					nd6_dad_start((struct ifaddr *)ifa, 0);
+					/* We will notify the routing socket of
+					 * the DAD result, so no need to
+					 * here */
 				}
 			} else {
-				ifa->ia6_flags |= IN6_IFF_DETACHED;
+				if ((ifa->ia6_flags & IN6_IFF_DETACHED) == 0) {
+					ifa->ia6_flags |= IN6_IFF_DETACHED;
+					nd6_newaddrmsg((struct ifaddr *)ifa);
+				}
 			}
 		}
 	}
