--- 20090623-ifaddr.diff	2009-06-23 11:55:20.000000000 +0100
+++ 20090623a-ifaddr.diff	2009-06-23 19:31:01.000000000 +0100
@@ -82,50 +82,7 @@
  	struct in_ifinfo *ii;
  	struct in_aliasreq *ifra = (struct in_aliasreq *)data;
  	struct sockaddr_in oldaddr;
-@@ -307,6 +306,42 @@
- 		break;
- 	}
- 
-+	switch (cmd) {
-+	case SIOCAIFADDR:
-+		printf("SIOCAIFADDR %s\n", ifp->if_xname);
-+		break;
-+	case SIOCSIFADDR:
-+		printf("SIOCSIFADDR %s\n", ifp->if_xname);
-+		break;
-+	case SIOCSIFBRDADDR:
-+		printf("SIOCSIFBRDADDR %s\n", ifp->if_xname);
-+		break;
-+	case SIOCSIFNETMASK:
-+		printf("SIOCSIFNETMASK %s\n", ifp->if_xname);
-+		break;
-+	case SIOCSIFDSTADDR:
-+		printf("SIOCSIFDSTADDR %s\n", ifp->if_xname);
-+		break;
-+	case SIOCDIFADDR:
-+		printf("SIOCDIFADDR %s\n", ifp->if_xname);
-+		break;
-+	case SIOCGIFADDR:
-+		printf("SIOCGIFADDR %s\n", ifp->if_xname);
-+		break;
-+	case SIOCGIFNETMASK:
-+		printf("SIOCGIFNETMASK %s\n", ifp->if_xname);
-+		break;
-+	case SIOCGIFDSTADDR:
-+		printf("SIOCGIFDSTADDR %s\n", ifp->if_xname);
-+		break;
-+	case SIOCGIFBRDADDR:
-+		printf("SIOCGIFBRDADDR %s\n", ifp->if_xname);
-+		break;
-+	default:
-+		printf("cmd %lu %s\n", cmd, ifp->if_xname);
-+		break;
-+	}
-+
- 	/*
- 	 * Find address for this interface, if it exists.
- 	 *
-@@ -323,8 +358,10 @@
+@@ -323,8 +322,10 @@
  			break;
  		}
  	}
@@ -137,7 +94,7 @@
  		TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
  			iap = ifatoia(ifa);
  			if (iap->ia_addr.sin_family == AF_INET) {
-@@ -336,6 +373,9 @@
+@@ -336,6 +337,9 @@
  				break;
  			}
  		}
@@ -147,7 +104,7 @@
  	}
  	if (ia == NULL)
  		iaIsFirst = 1;
-@@ -345,23 +385,29 @@
+@@ -345,23 +349,29 @@
  	case SIOCAIFADDR:
  	case SIOCDIFADDR:
  		if (ifra->ifra_addr.sin_family == AF_INET) {
@@ -179,7 +136,7 @@
  		}
  		/* FALLTHROUGH */
  	case SIOCSIFADDR:
-@@ -373,7 +419,7 @@
+@@ -373,7 +383,7 @@
  				    M_ZERO);
  			if (ia == NULL) {
  				error = ENOBUFS;
@@ -188,7 +145,7 @@
  			}
  
  			ifa = &ia->ia_ifa;
-@@ -390,7 +436,11 @@
+@@ -390,7 +400,11 @@
  			}
  			ia->ia_ifp = ifp;
  
@@ -200,7 +157,7 @@
  			s = splnet();
  			TAILQ_INSERT_TAIL(&V_in_ifaddrhead, ia, ia_link);
  			splx(s);
-@@ -405,64 +455,53 @@
+@@ -405,64 +419,53 @@
  	case SIOCGIFBRDADDR:
  		if (ia == NULL) {
  			error = EADDRNOTAVAIL;
@@ -276,7 +233,7 @@
  			}
  		}
  		if (ia->ia_flags & IFA_ROUTE) {
-@@ -472,23 +511,17 @@
+@@ -472,23 +475,17 @@
  					(struct sockaddr *)&ia->ia_dstaddr;
  			rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
  		}
@@ -303,7 +260,7 @@
  		error = in_ifinit(ifp, ia,
  		    (struct sockaddr_in *) &ifr->ifr_addr, 1);
  		if (error != 0 && iaIsNew)
-@@ -502,12 +535,13 @@
+@@ -502,12 +499,13 @@
  			}
  			EVENTHANDLER_INVOKE(ifaddr_event, ifp);
  		}
@@ -319,7 +276,7 @@
  
  	case SIOCAIFADDR:
  		maskIsNew = 0;
-@@ -521,12 +555,6 @@
+@@ -521,12 +519,6 @@
  					       ia->ia_addr.sin_addr.s_addr)
  				hostIsNew = 0;
  		}
@@ -332,7 +289,7 @@
  		if (ifra->ifra_mask.sin_len) {
  			in_ifscrub(ifp, ia);
  			ia->ia_sockmask = ifra->ifra_mask;
-@@ -545,7 +573,7 @@
+@@ -545,7 +537,7 @@
  		    (hostIsNew || maskIsNew))
  			error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
  		if (error != 0 && iaIsNew)
@@ -341,7 +298,7 @@
  
  		if ((ifp->if_flags & IFF_BROADCAST) &&
  		    (ifra->ifra_broadaddr.sin_family == AF_INET))
-@@ -559,15 +587,10 @@
+@@ -559,15 +551,10 @@
  			}
  			EVENTHANDLER_INVOKE(ifaddr_event, ifp);
  		}
@@ -358,7 +315,7 @@
  		 * in_ifscrub kills the interface route.
  		 */
  		in_ifscrub(ifp, ia);
-@@ -587,25 +610,25 @@
+@@ -587,25 +574,25 @@
  		panic("in_control: unsupported ioctl");
  	}
  
@@ -391,7 +348,7 @@
  			ii = ((struct in_ifinfo *)ifp->if_afdata[AF_INET]);
  			IN_MULTI_LOCK();
  			if (ii->ii_allhosts) {
-@@ -614,16 +637,14 @@
+@@ -614,16 +601,14 @@
  				ii->ii_allhosts = NULL;
  			}
  			IN_MULTI_UNLOCK();
@@ -977,41 +934,7 @@
  	IFNET_RUNLOCK();
  	return (ifa);
  }
-@@ -1427,6 +1430,8 @@
- 
- 	mtx_init(&ifa->ifa_mtx, "ifaddr", NULL, MTX_DEF);
- 	refcount_init(&ifa->ifa_refcnt, 1);
-+	printf("ifa_init %p\n", ifa);
-+	kdb_backtrace();
- }
- 
- void
-@@ -1434,6 +1439,8 @@
- {
- 
- 	refcount_acquire(&ifa->ifa_refcnt);
-+	printf("ifa_ref %p (now %u)\n", ifa, ifa->ifa_refcnt);
-+	kdb_backtrace();
- }
- 
- void
-@@ -1441,8 +1448,15 @@
- {
- 
- 	if (refcount_release(&ifa->ifa_refcnt)) {
-+		printf("ifa_free %p (now %u, will free)\n", ifa,
-+		    ifa->ifa_refcnt);
-+		kdb_backtrace();
- 		mtx_destroy(&ifa->ifa_mtx);
- 		free(ifa, M_IFADDR);
-+	} else {
-+		printf("ifa_free %p (now %u, won't free)\n", ifa,
-+		    ifa->ifa_refcnt);
-+		kdb_backtrace();
- 	}
- }
- 
-@@ -1467,7 +1481,7 @@
+@@ -1467,7 +1470,7 @@
   */
  /*ARGSUSED*/
  static struct ifaddr *
@@ -1020,7 +943,7 @@
  {
  	INIT_VNET_NET(curvnet);
  	struct ifnet *ifp;
-@@ -1480,6 +1494,8 @@
+@@ -1480,6 +1483,8 @@
  			if (ifa->ifa_addr->sa_family != addr->sa_family)
  				continue;
  			if (sa_equal(addr, ifa->ifa_addr)) {
@@ -1029,7 +952,7 @@
  				IF_ADDR_UNLOCK(ifp);
  				goto done;
  			}
-@@ -1488,6 +1504,8 @@
+@@ -1488,6 +1493,8 @@
  			    ifa->ifa_broadaddr &&
  			    ifa->ifa_broadaddr->sa_len != 0 &&
  			    sa_equal(ifa->ifa_broadaddr, addr)) {
@@ -1038,7 +961,7 @@
  				IF_ADDR_UNLOCK(ifp);
  				goto done;
  			}
-@@ -1504,14 +1522,14 @@
+@@ -1504,14 +1511,14 @@
  ifa_ifwithaddr(struct sockaddr *addr)
  {
  
@@ -1055,7 +978,7 @@
  }
  
  /*
-@@ -1535,6 +1553,7 @@
+@@ -1535,6 +1542,7 @@
  			    ifa->ifa_broadaddr &&
  			    ifa->ifa_broadaddr->sa_len != 0 &&
  			    sa_equal(ifa->ifa_broadaddr, addr)) {
@@ -1063,7 +986,7 @@
  				IF_ADDR_UNLOCK(ifp);
  				goto done;
  			}
-@@ -1568,6 +1587,7 @@
+@@ -1568,6 +1576,7 @@
  				continue;
  			if (ifa->ifa_dstaddr != NULL &&
  			    sa_equal(addr, ifa->ifa_dstaddr)) {
@@ -1071,7 +994,7 @@
  				IF_ADDR_UNLOCK(ifp);
  				goto done;
  			}
-@@ -1590,7 +1610,7 @@
+@@ -1590,7 +1599,7 @@
  	INIT_VNET_NET(curvnet);
  	struct ifnet *ifp;
  	struct ifaddr *ifa;
@@ -1080,7 +1003,7 @@
  	u_int af = addr->sa_family;
  	char *addr_data = addr->sa_data, *cplim;
  
-@@ -1605,8 +1625,10 @@
+@@ -1605,8 +1614,10 @@
  	}
  
  	/*
@@ -1093,7 +1016,7 @@
  	 */
  	IFNET_RLOCK();
  	TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
-@@ -1627,6 +1649,7 @@
+@@ -1627,6 +1638,7 @@
  				 */
  				if (ifa->ifa_dstaddr != NULL &&
  				    sa_equal(addr, ifa->ifa_dstaddr)) {
@@ -1101,7 +1024,7 @@
  					IF_ADDR_UNLOCK(ifp);
  					goto done;
  				}
-@@ -1637,6 +1660,7 @@
+@@ -1637,6 +1649,7 @@
  				 */
  				if (ifa->ifa_claim_addr) {
  					if ((*ifa->ifa_claim_addr)(ifa, addr)) {
@@ -1109,7 +1032,7 @@
  						IF_ADDR_UNLOCK(ifp);
  						goto done;
  					}
-@@ -1667,17 +1691,24 @@
+@@ -1667,17 +1680,24 @@
  				 * before continuing to search
  				 * for an even better one.
  				 */
@@ -1136,7 +1059,7 @@
  	return (ifa);
  }
  
-@@ -1691,7 +1722,7 @@
+@@ -1691,7 +1711,7 @@
  	struct ifaddr *ifa;
  	char *cp, *cp2, *cp3;
  	char *cplim;
@@ -1145,7 +1068,7 @@
  	u_int af = addr->sa_family;
  
  	if (af >= AF_MAX)
-@@ -1700,7 +1731,7 @@
+@@ -1700,7 +1720,7 @@
  	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
  		if (ifa->ifa_addr->sa_family != af)
  			continue;
@@ -1154,7 +1077,7 @@
  			ifa_maybe = ifa;
  		if (ifa->ifa_netmask == 0) {
  			if (sa_equal(addr, ifa->ifa_addr) ||
-@@ -1726,6 +1757,8 @@
+@@ -1726,6 +1746,8 @@
  	}
  	ifa = ifa_maybe;
  done:
@@ -1163,7 +1086,7 @@
  	IF_ADDR_UNLOCK(ifp);
  	return (ifa);
  }
-@@ -1752,7 +1785,6 @@
+@@ -1752,7 +1774,6 @@
  		return;
  	ifa = ifaof_ifpforaddr(dst, ifp);
  	if (ifa) {
@@ -1318,7 +1241,15 @@
 ===================================================================
 --- netinet6/in6_ifattach.c	(revision 194622)
 +++ netinet6/in6_ifattach.c	(working copy)
-@@ -513,6 +513,7 @@
+@@ -253,6 +253,7 @@
+ 	return -1;
+ 
+ found:
++	IF_ADDR_LOCK_ASSERT(ifp);
+ 	addr = LLADDR(sdl);
+ 	addrlen = sdl->sdl_alen;
+ 
+@@ -513,6 +514,7 @@
  		/* NOTREACHED */
  	}
  #endif
@@ -1326,7 +1257,7 @@
  
  	/*
  	 * Make the link-local prefix (fe80::%link/64) as on-link.
-@@ -737,11 +738,15 @@
+@@ -737,11 +739,15 @@
  	 * XXX multiple loopback interface case.
  	 */
  	if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
@@ -1344,7 +1275,7 @@
  	}
  
  	/*
-@@ -755,7 +760,8 @@
+@@ -755,7 +761,8 @@
  			} else {
  				/* failed to assign linklocal address. bark? */
  			}
@@ -1561,6 +1492,15 @@
  			int error;
  			struct sockaddr_in6 dst_sa;
  
+@@ -604,7 +612,7 @@
+ 	char *lladdr = NULL;
+ 	int lladdrlen = 0;
+ 	int checklink = 0;
+-	struct ifaddr *ifa;
++	struct ifaddr *ifa = NULL;
+ 	struct llentry *ln = NULL;
+ 	union nd_opts ndopts;
+ 	struct mbuf *chain = NULL;
 @@ -679,12 +687,14 @@
  	 */
  	if (ifa
@@ -1576,6 +1516,24 @@
  		log(LOG_ERR,
  		    "nd6_na_input: duplicate IP6 address %s\n",
  		    ip6_sprintf(ip6bufs, &taddr6));
+@@ -887,6 +897,8 @@
+ 		if (chain)
+ 			nd6_output_flush(ifp, ifp, chain, &sin6, NULL);
+ 	}
++	if (ifa != NULL)
++		ifa_free(ifa);
+ 	if (checklink)
+ 		pfxlist_onlink_check();
+ 
+@@ -896,6 +908,8 @@
+  bad:
+ 	if (ln != NULL)
+ 		LLE_WUNLOCK(ln);
++	if (ifa != NULL)
++		ifa_free(ifa);
+ 
+ 	ICMP6STAT_INC(icp6s_badna);
+ 	m_freem(m);
 Index: netinet6/in6.c
 ===================================================================
 --- netinet6/in6.c	(revision 194622)
@@ -1649,16 +1607,20 @@
  	case SIOCSIFALIFETIME_IN6:
  	    {
  		struct in6_addrlifetime *lt;
-@@ -394,7 +399,7 @@
+@@ -394,42 +399,47 @@
  		if (td != NULL) {
  			error = priv_check(td, PRIV_NETINET_ALIFETIME6);
  			if (error)
 -				return (error);
 +				goto out;
  		}
- 		if (ia == NULL)
- 			return (EADDRNOTAVAIL);
-@@ -402,34 +407,37 @@
+-		if (ia == NULL)
+-			return (EADDRNOTAVAIL);
++		if (ia == NULL) {
++			error = EADDRNOTAVAIL;
++			goto out;
++		}
+ 		/* sanity for overflow - beware unsigned */
  		lt = &ifr->ifr_ifru.ifru_lifetime;
  		if (lt->ia6t_vltime != ND6_INFINITE_LIFETIME &&
  		    lt->ia6t_vltime + time_second < time_second) {
@@ -1703,7 +1665,7 @@
  		break;
  
  	case SIOCGIFNETMASK_IN6:
-@@ -441,8 +449,10 @@
+@@ -441,8 +451,10 @@
  		break;
  
  	case SIOCGIFSTAT_IN6:
@@ -1716,7 +1678,7 @@
  		bzero(&ifr->ifr_ifru.ifru_stat,
  		    sizeof(ifr->ifr_ifru.ifru_stat));
  		ifr->ifr_ifru.ifru_stat =
-@@ -450,8 +460,10 @@
+@@ -450,8 +462,10 @@
  		break;
  
  	case SIOCGIFSTAT_ICMP6:
@@ -1729,7 +1691,7 @@
  		bzero(&ifr->ifr_ifru.ifru_icmp6stat,
  		    sizeof(ifr->ifr_ifru.ifru_icmp6stat));
  		ifr->ifr_ifru.ifru_icmp6stat =
-@@ -515,7 +527,7 @@
+@@ -515,7 +529,7 @@
  
  	case SIOCAIFADDR_IN6:
  	{
@@ -1738,7 +1700,7 @@
  		struct nd_prefixctl pr0;
  		struct nd_prefix *pr;
  
-@@ -524,7 +536,9 @@
+@@ -524,7 +538,9 @@
  		 * and link it to the list.
  		 */
  		if ((error = in6_update_ifa(ifp, ifra, ia, 0)) != 0)
@@ -1749,7 +1711,7 @@
  		if ((ia = in6ifa_ifpwithaddr(ifp, &ifra->ifra_addr.sin6_addr))
  		    == NULL) {
  			/*
-@@ -578,11 +592,12 @@
+@@ -578,11 +594,12 @@
  			 * interface route.
  			 */
  			if ((error = nd6_prelist_add(&pr0, NULL, &pr)) != 0)
@@ -1764,17 +1726,19 @@
  			}
  		}
  
-@@ -640,12 +655,18 @@
+@@ -640,12 +657,19 @@
  	}
  
  	default:
 -		if (ifp == NULL || ifp->if_ioctl == 0)
 -			return (EOPNOTSUPP);
+-		return ((*ifp->if_ioctl)(ifp, cmd, data));
 +		if (ifp == NULL || ifp->if_ioctl == 0) {
 +			error = EOPNOTSUPP;
 +			goto out;
 +		}
- 		return ((*ifp->if_ioctl)(ifp, cmd, data));
++		error = (*ifp->if_ioctl)(ifp, cmd, data);
++		goto out;
  	}
  
 -	return (0);
@@ -1786,7 +1750,86 @@
  }
  
  /*
-@@ -1481,6 +1502,7 @@
+@@ -811,6 +835,7 @@
+ 		} else
+ 			V_in6_ifaddr = ia;
+ 
++		ifa_ref(&ia->ia_ifa);			/* if_addrhead */
+ 		IF_ADDR_LOCK(ifp);
+ 		TAILQ_INSERT_TAIL(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
+ 		IF_ADDR_UNLOCK(ifp);
+@@ -1085,8 +1110,7 @@
+ 	 * XXX It may be of use, if we can administratively
+ 	 * disable DAD.
+ 	 */
+-	if (hostIsNew && in6if_do_dad(ifp) &&
+-	    ((ifra->ifra_flags & IN6_IFF_NODAD) == 0) &&
++	if (in6if_do_dad(ifp) && ((ifra->ifra_flags & IN6_IFF_NODAD) == 0) &&
+ 	    (ia->ia6_flags & IN6_IFF_TENTATIVE))
+ 	{
+ 		int mindelay, maxdelay;
+@@ -1120,6 +1144,8 @@
+ 		nd6_dad_start((struct ifaddr *)ia, delay);
+ 	}
+ 
++	KASSERT(hostIsNew, ("in6_update_ifa: !hostIsNew"));
++	ifa_free(&ia->ia_ifa);
+ 	return (error);
+ 
+   unlink:
+@@ -1127,11 +1153,15 @@
+ 	 * XXX: if a change of an existing address failed, keep the entry
+ 	 * anyway.
+ 	 */
+-	if (hostIsNew)
++	if (hostIsNew) {
++		ifa_free(&ia->ia_ifa);
+ 		in6_unlink_ifa(ia, ifp);
++	}
+ 	return (error);
+ 
+   cleanup:
++	KASSERT(hostIsNew, ("in6_update_ifa: cleanup: !hostIsNew"));
++	ifa_free(&ia->ia_ifa);
+ 	in6_purgeaddr(&ia->ia_ifa);
+ 	return error;
+ }
+@@ -1155,6 +1185,7 @@
+ 	 * link-local and node-local all-nodes multicast
+ 	 * address routes
+ 	 */
++	IF_ADDR_LOCK(ifp);
+ 	TAILQ_FOREACH_SAFE(ifa0, &ifp->if_addrhead, ifa_link, nifa) {
+ 		if ((ifa0->ifa_addr->sa_family != AF_INET6) ||
+ 		    memcmp(&satosin6(ifa0->ifa_addr)->sin6_addr,
+@@ -1164,6 +1195,9 @@
+ 		else
+ 			break;
+ 	}
++	if (ifa0 != NULL)
++		ifa_ref(ifa0);
++	IF_ADDR_UNLOCK(ifp);
+ 
+ 	/* stop DAD processing */
+ 	nd6_dad_stop(ifa);
+@@ -1331,6 +1365,8 @@
+ 			return;
+ 		ia->ia_flags &= ~IFA_ROUTE;
+ 	}
++	if (ifa0 != NULL)
++		ifa_free(ifa0);
+ 
+ 	in6_unlink_ifa(ia, ifp);
+ }
+@@ -1345,6 +1381,7 @@
+ 	IF_ADDR_LOCK(ifp);
+ 	TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
+ 	IF_ADDR_UNLOCK(ifp);
++	ifa_free(&ia->ia_ifa);			/* if_addrhead */
+ 
+ 	oia = ia;
+ 	if (oia == (ia = V_in6_ifaddr))
+@@ -1481,6 +1518,7 @@
  		struct in6_addr *hostid = NULL;
  		int prefixlen;
  
@@ -1794,7 +1837,7 @@
  		if ((iflr->flags & IFLR_PREFIX) != 0) {
  			struct sockaddr_in6 *sin6;
  
-@@ -1532,6 +1554,8 @@
+@@ -1532,6 +1570,8 @@
  				    hostid->s6_addr32[3];
  			}
  		}
@@ -1803,7 +1846,7 @@
  
  		ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
  		in6_prefixlen2mask(&ifra.ifra_prefixmask.sin6_addr, prefixlen);
-@@ -1779,6 +1803,7 @@
+@@ -1779,6 +1819,7 @@
  
  /*
   * Find an IPv6 interface link-local address specific to an interface.
@@ -1811,16 +1854,15 @@
   */
  struct in6_ifaddr *
  in6ifa_ifpforlinklocal(struct ifnet *ifp, int ignoreflags)
-@@ -1796,6 +1821,8 @@
+@@ -1793,6 +1834,7 @@
+ 			if ((((struct in6_ifaddr *)ifa)->ia6_flags &
+ 			     ignoreflags) != 0)
+ 				continue;
++			ifa_ref(ifa);
  			break;
  		}
  	}
-+	if (ifa != NULL)
-+		ifa_ref(ifa);
- 	IF_ADDR_UNLOCK(ifp);
- 
- 	return ((struct in6_ifaddr *)ifa);
-@@ -1804,6 +1831,7 @@
+@@ -1804,6 +1846,7 @@
  
  /*
   * find the internet address corresponding to a given interface and address.
@@ -1828,16 +1870,19 @@
   */
  struct in6_ifaddr *
  in6ifa_ifpwithaddr(struct ifnet *ifp, struct in6_addr *addr)
-@@ -1817,6 +1845,8 @@
- 		if (IN6_ARE_ADDR_EQUAL(addr, IFA_IN6(ifa)))
+@@ -1814,8 +1857,10 @@
+ 	TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+ 		if (ifa->ifa_addr->sa_family != AF_INET6)
+ 			continue;
+-		if (IN6_ARE_ADDR_EQUAL(addr, IFA_IN6(ifa)))
++		if (IN6_ARE_ADDR_EQUAL(addr, IFA_IN6(ifa))) {
++			ifa_ref(ifa);
  			break;
++		}
  	}
-+	if (ifa != NULL)
-+		ifa_ref(ifa);
  	IF_ADDR_UNLOCK(ifp);
  
- 	return ((struct in6_ifaddr *)ifa);
-@@ -2049,6 +2079,7 @@
+@@ -2049,6 +2094,7 @@
  		}
  	}
  	if (besta) {
@@ -1845,7 +1890,7 @@
  		IF_ADDR_UNLOCK(ifp);
  		return (besta);
  	}
-@@ -2068,6 +2099,8 @@
+@@ -2068,6 +2114,8 @@
  			continue;
  		}
  
@@ -1854,7 +1899,7 @@
  		IF_ADDR_UNLOCK(ifp);
  		return (struct in6_ifaddr *)ifa;
  	}
-@@ -2319,6 +2352,7 @@
+@@ -2319,6 +2367,7 @@
  		/* XXX ifaof_ifpforaddr should take a const param */
  		ifa = ifaof_ifpforaddr(__DECONST(struct sockaddr *, l3addr), ifp);
  		if (ifa != NULL) {
@@ -2012,7 +2057,36 @@
 ===================================================================
 --- netinet6/nd6_rtr.c	(revision 194622)
 +++ netinet6/nd6_rtr.c	(working copy)
-@@ -1307,6 +1307,7 @@
+@@ -435,6 +435,7 @@
+ {
+ 	struct rt_addrinfo info;
+ 	struct ifnet *ifp;
++	struct ifaddr *ifa;
+ 
+ 	bzero((caddr_t)&info, sizeof(info));
+ 	info.rti_info[RTAX_DST] = rt_key(rt);
+@@ -443,13 +444,17 @@
+ 	ifp = rt->rt_ifp;
+ 	if (ifp != NULL) {
+ 		IF_ADDR_LOCK(ifp);
+-		info.rti_info[RTAX_IFP] =
+-		    TAILQ_FIRST(&ifp->if_addrhead)->ifa_addr;
++		ifa = TAILQ_FIRST(&ifp->if_addrhead);
++		info.rti_info[RTAX_IFP] = ifa->ifa_addr;
++		ifa_ref(ifa);
+ 		IF_ADDR_UNLOCK(ifp);
+ 		info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
+-	}
++	} else
++		ifa = NULL;
+ 
+ 	rt_missmsg(cmd, &info, rt->rt_flags, 0);
++	if (ifa != NULL)
++		ifa_free(ifa);
+ }
+ 
+ void
+@@ -1307,6 +1312,7 @@
  					    e));
  				}
  			}
@@ -2020,7 +2094,7 @@
  
  			/*
  			 * A newly added address might affect the status
-@@ -1597,10 +1598,14 @@
+@@ -1597,10 +1603,14 @@
  	    IN6_IFF_NOTREADY | IN6_IFF_ANYCAST);
  	if (ifa == NULL) {
  		/* XXX: freebsd does not have ifa_ifwithaf */
@@ -2035,7 +2109,7 @@
  		/* should we care about ia6_flags? */
  	}
  	if (ifa == NULL) {
-@@ -1661,6 +1666,8 @@
+@@ -1661,6 +1671,8 @@
  		RT_REMREF(rt);
  		RT_UNLOCK(rt);
  	}
@@ -2044,7 +2118,7 @@
  
  	return (error);
  }
-@@ -1802,6 +1809,7 @@
+@@ -1802,6 +1814,7 @@
  	/* prefixlen + ifidlen must be equal to 128 */
  	plen0 = in6_mask2len(&ib->ia_prefixmask.sin6_addr, NULL);
  	if (prefixlen != plen0) {
@@ -2052,7 +2126,7 @@
  		nd6log((LOG_INFO, "in6_ifadd: wrong prefixlen for %s "
  		    "(prefix=%d ifid=%d)\n",
  		    if_name(ifp), prefixlen, 128 - plen0));
-@@ -1834,6 +1842,7 @@
+@@ -1834,6 +1847,7 @@
  	    (ib->ia_addr.sin6_addr.s6_addr32[2] & ~mask.s6_addr32[2]);
  	ifra.ifra_addr.sin6_addr.s6_addr32[3] |=
  	    (ib->ia_addr.sin6_addr.s6_addr32[3] & ~mask.s6_addr32[3]);
@@ -2060,7 +2134,7 @@
  
  	/* new prefix mask. */
  	ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
-@@ -1854,7 +1863,10 @@
+@@ -1854,7 +1868,10 @@
  	 * usually not happen, but we can still see this case, e.g., if we
  	 * have manually configured the exact address to be configured.
  	 */
@@ -2072,7 +2146,7 @@
  		/* this should be rare enough to make an explicit log */
  		log(LOG_INFO, "in6_ifadd: %s is already configured\n",
  		    ip6_sprintf(ip6buf, &ifra.ifra_addr.sin6_addr));
-@@ -1879,8 +1891,12 @@
+@@ -1879,8 +1896,12 @@
  	}
  
  	ia = in6ifa_ifpwithaddr(ifp, &ifra.ifra_addr.sin6_addr);
@@ -2087,7 +2161,7 @@
  }
  
  /*
-@@ -2000,6 +2016,7 @@
+@@ -2000,6 +2021,7 @@
  	}
  	newia->ia6_ndpr = ia0->ia6_ndpr;
  	newia->ia6_ndpr->ndpr_refcnt++;
