Index: sys/net/if.c =================================================================== --- sys/net/if.c +++ sys/net/if.c @@ -425,12 +425,12 @@ ifaddr_byindex(u_short idx) { struct ifnet *ifp; - struct ifaddr *ifa = NULL; + struct ifaddr *ifa; IFNET_RLOCK_NOSLEEP(); ifp = ifnet_byindex_locked(idx); - if (ifp != NULL && (ifa = ifp->if_addr) != NULL) - ifa_ref(ifa); + if (ifp == NULL || (ifa = ifp->if_addr) == NULL || ifa_ref(ifa) == 0) + ifa = NULL; /* failure */ IFNET_RUNLOCK_NOSLEEP(); return (ifa); } @@ -969,7 +969,7 @@ while (1) { NET_EPOCH_ENTER(); CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { - if (ifa->ifa_addr->sa_family != AF_LINK) + if (ifa->ifa_addr->sa_family != AF_LINK && ifa_ref(ifa) != 0) break; } NET_EPOCH_EXIT(); @@ -987,20 +987,22 @@ ifr.ifra_broadaddr = *ifa->ifa_dstaddr; if (in_control(NULL, SIOCDIFADDR, (caddr_t)&ifr, ifp, NULL) == 0) - continue; + goto skip; } #endif /* INET */ #ifdef INET6 if (ifa->ifa_addr->sa_family == AF_INET6) { in6_purgeaddr(ifa); /* ifp_addrhead is already updated */ - continue; + goto skip; } #endif /* INET6 */ IF_ADDR_WLOCK(ifp); CK_STAILQ_REMOVE(&ifp->if_addrhead, ifa, ifaddr, ifa_link); IF_ADDR_WUNLOCK(ifp); ifa_free(ifa); +skip: + ifa_free(ifa); } } @@ -1834,11 +1836,11 @@ return (NULL); } -void +int ifa_ref(struct ifaddr *ifa) { - refcount_acquire(&ifa->ifa_refcnt); + return (refcount_acquire_if_not_zero(&ifa->ifa_refcnt)); } static void @@ -2205,12 +2207,9 @@ return; NET_EPOCH_ENTER(); ifa = ifaof_ifpforaddr(dst, ifp); - if (ifa) { + if (ifa != NULL && ifa_ref(ifa) != 0) { oifa = rt->rt_ifa; - if (oifa != ifa) { - ifa_free(oifa); - ifa_ref(ifa); - } + ifa_free(oifa); rt->rt_ifa = ifa; if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) ifa->ifa_rtrequest(cmd, rt, info); Index: sys/net/if_spppsubr.c =================================================================== --- sys/net/if_spppsubr.c +++ sys/net/if_spppsubr.c @@ -4882,10 +4882,8 @@ CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family == AF_INET) { si = (struct sockaddr_in *)ifa->ifa_addr; - if (si != NULL) { - ifa_ref(ifa); + if (si != NULL && ifa_ref(ifa) != 0) break; - } } } if_addr_runlock(ifp); @@ -4999,8 +4997,9 @@ CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family == AF_INET6) { sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; - if (sin6 && IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { - ifa_ref(ifa); + if (sin6 != NULL && + IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && + ifa_ref(ifa) != 0) { break; } } Index: sys/net/if_var.h =================================================================== --- sys/net/if_var.h +++ sys/net/if_var.h @@ -548,7 +548,7 @@ struct ifaddr * ifa_alloc(size_t size, int flags); void ifa_free(struct ifaddr *ifa); -void ifa_ref(struct ifaddr *ifa); +int ifa_ref(struct ifaddr *ifa) __result_use_check; /* * Multicast address structure. This is analogous to the ifaddr Index: sys/net/route.c =================================================================== --- sys/net/route.c +++ sys/net/route.c @@ -652,19 +652,22 @@ RTFREE_LOCKED(rt); flags |= RTF_DYNAMIC; - bzero((caddr_t)&info, sizeof(info)); - info.rti_info[RTAX_DST] = dst; - info.rti_info[RTAX_GATEWAY] = gateway; - info.rti_info[RTAX_NETMASK] = netmask; - ifa_ref(ifa); - info.rti_ifa = ifa; - info.rti_flags = flags; - error = rtrequest1_fib(RTM_ADD, &info, &rt, fibnum); - if (rt != NULL) { - RT_LOCK(rt); - flags = rt->rt_flags; + + if (ifa_ref(ifa) != 0) { + bzero((caddr_t)&info, sizeof(info)); + info.rti_info[RTAX_DST] = dst; + info.rti_info[RTAX_GATEWAY] = gateway; + info.rti_info[RTAX_NETMASK] = netmask; + info.rti_ifa = ifa; + info.rti_flags = flags; + error = rtrequest1_fib(RTM_ADD, &info, &rt, fibnum); + if (rt != NULL) { + RT_LOCK(rt); + flags = rt->rt_flags; + } + } else { + error = ENXIO; } - stat = &V_rtstat.rts_dynamic; } else { @@ -903,7 +906,8 @@ info->rti_flags = rt->rt_flags; info->rti_ifp = rt->rt_ifp; info->rti_ifa = rt->rt_ifa; - ifa_ref(info->rti_ifa); + if (ifa_ref(info->rti_ifa) == 0) + return (ENXIO); if (flags & NHR_REF) { /* Do 'traditional' refcouting */ if_ref(info->rti_ifp); @@ -1313,7 +1317,8 @@ if (needref && info->rti_ifa != NULL) { if (info->rti_ifp == NULL) info->rti_ifp = info->rti_ifa->ifa_ifp; - ifa_ref(info->rti_ifa); + if (ifa_ref(info->rti_ifa) == 0) + error = ENXIO; } else error = ENETUNREACH; NET_EPOCH_EXIT(); @@ -1627,7 +1632,11 @@ * examine the ifa and ifa->ifa_ifp if it so desires. */ ifa = info->rti_ifa; - ifa_ref(ifa); + if (ifa_ref(ifa) == 0) { + R_Free(rt_key(rt)); + uma_zfree(V_rtzone, rt); + return (ENXIO); + } rt->rt_ifa = ifa; rt->rt_ifp = ifa->ifa_ifp; rt->rt_weight = 1; @@ -1805,7 +1814,11 @@ } if (info->rti_ifa != NULL && info->rti_ifa != rt->rt_ifa) { - ifa_ref(info->rti_ifa); + if (ifa_ref(info->rti_ifa) == 0) { + error = ENXIO; + free_ifa = 0; + goto bad; + } rt->rt_ifa = info->rti_ifa; rt->rt_ifp = info->rti_ifp; } @@ -1970,6 +1983,8 @@ } if (dst->sa_len == 0) return(EINVAL); + if (ifa_ref(ifa) == 0) + return (ENXIO); switch (dst->sa_family) { case AF_INET6: case AF_INET: @@ -2063,7 +2078,8 @@ * Do the actual request */ bzero((caddr_t)&info, sizeof(info)); - ifa_ref(ifa); + if (ifa_ref(ifa) == 0) + panic("Cannot get reference on ifa\n"); info.rti_ifa = ifa; info.rti_flags = flags | (ifa->ifa_flags & ~IFA_RTSELF) | RTF_PINNED; @@ -2095,7 +2111,8 @@ if (memcmp(rt->rt_ifa->ifa_addr, ifa->ifa_addr, ifa->ifa_addr->sa_len)) { ifa_free(rt->rt_ifa); - ifa_ref(ifa); + if (ifa_ref(ifa) == 0) + panic("Cannot get reference on ifa\n"); rt->rt_ifp = ifa->ifa_ifp; rt->rt_ifa = ifa; } @@ -2150,6 +2167,7 @@ error = a_failure; } } + ifa_free(ifa); return (error); } Index: sys/netinet/if_ether.c =================================================================== --- sys/netinet/if_ether.c +++ sys/netinet/if_ether.c @@ -843,8 +843,8 @@ ia->ia_ifp == ifp) && itaddr.s_addr == ia->ia_addr.sin_addr.s_addr && (ia->ia_ifa.ifa_carp == NULL || - (*carp_iamatch_p)(&ia->ia_ifa, &enaddr))) { - ifa_ref(&ia->ia_ifa); + (*carp_iamatch_p)(&ia->ia_ifa, &enaddr)) && + ifa_ref(&ia->ia_ifa) != 0) { IN_IFADDR_RUNLOCK(&in_ifa_tracker); goto match; } @@ -852,8 +852,8 @@ LIST_FOREACH(ia, INADDR_HASH(isaddr.s_addr), ia_hash) if (((bridged && ia->ia_ifp->if_bridge == ifp->if_bridge) || ia->ia_ifp == ifp) && - isaddr.s_addr == ia->ia_addr.sin_addr.s_addr) { - ifa_ref(&ia->ia_ifa); + isaddr.s_addr == ia->ia_addr.sin_addr.s_addr && + ifa_ref(&ia->ia_ifa) != 0) { IN_IFADDR_RUNLOCK(&in_ifa_tracker); goto match; } @@ -870,8 +870,8 @@ */ if (is_bridge) { LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash) { - if (BDG_MEMBER_MATCHES_ARP(itaddr.s_addr, ifp, ia)) { - ifa_ref(&ia->ia_ifa); + if (BDG_MEMBER_MATCHES_ARP(itaddr.s_addr, ifp, ia) && + ifa_ref(&ia->ia_ifa) != 0) { ifp = ia->ia_ifp; IN_IFADDR_RUNLOCK(&in_ifa_tracker); goto match; @@ -889,9 +889,9 @@ CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) if (ifa->ifa_addr->sa_family == AF_INET && (ifa->ifa_carp == NULL || - (*carp_iamatch_p)(ifa, &enaddr))) { + (*carp_iamatch_p)(ifa, &enaddr)) && + ifa_ref(ifa) != 0) { ia = ifatoia(ifa); - ifa_ref(ifa); IF_ADDR_RUNLOCK(ifp); goto match; } @@ -901,11 +901,11 @@ * If bridging, fall back to using any inet address. */ IN_IFADDR_RLOCK(&in_ifa_tracker); - if (!bridged || (ia = CK_STAILQ_FIRST(&V_in_ifaddrhead)) == NULL) { + if (!bridged || (ia = CK_STAILQ_FIRST(&V_in_ifaddrhead)) == NULL || + ifa_ref(&ia->ia_ifa) == 0) { IN_IFADDR_RUNLOCK(&in_ifa_tracker); goto drop; } - ifa_ref(&ia->ia_ifa); IN_IFADDR_RUNLOCK(&in_ifa_tracker); match: if (!enaddr) @@ -1399,9 +1399,10 @@ IF_ADDR_WLOCK(ia->ia_ifa.ifa_ifp); ia->ia_garp_count = 0; - if (callout_reset(&ia->ia_garp_timer, (1 << ia->ia_garp_count) * hz, - garp_rexmit, ia) == 0) { - ifa_ref(ifa); + if (ifa_ref(ifa) != 0 && + callout_reset(&ia->ia_garp_timer, (1 << ia->ia_garp_count) * hz, + garp_rexmit, ia) != 0) { + ifa_free(ifa); } IF_ADDR_WUNLOCK(ia->ia_ifa.ifa_ifp); } Index: sys/netinet/in.c =================================================================== --- sys/netinet/in.c +++ sys/netinet/in.c @@ -170,8 +170,8 @@ IN_IFADDR_RLOCK(&in_ifa_tracker); LIST_FOREACH(it, INADDR_HASH(in), ia_hash) { - if (it != ia && IA_SIN(it)->sin_addr.s_addr == in) { - ifa_ref(&it->ia_ifa); + if (it != ia && IA_SIN(it)->sin_addr.s_addr == in && + ifa_ref(&it->ia_ifa) != 0) { IN_IFADDR_RUNLOCK(&in_ifa_tracker); return (it); } @@ -458,11 +458,12 @@ CK_STAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link); IF_ADDR_WUNLOCK(ifp); - ifa_ref(ifa); /* in_ifaddrhead */ - IN_IFADDR_WLOCK(); - CK_STAILQ_INSERT_TAIL(&V_in_ifaddrhead, ia, ia_link); - LIST_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr), ia, ia_hash); - IN_IFADDR_WUNLOCK(); + if (ifa_ref(ifa) != 0) { + IN_IFADDR_WLOCK(); + CK_STAILQ_INSERT_TAIL(&V_in_ifaddrhead, ia, ia_link); + LIST_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr), ia, ia_hash); + IN_IFADDR_WUNLOCK(); + } /* * Give the interface a chance to initialize @@ -865,8 +866,8 @@ * the route itself to it. Make sure that routing daemons * get a heads-up. */ - if ((ia->ia_flags & IFA_ROUTE) == 0) { - ifa_ref(&ia->ia_ifa); + if ((ia->ia_flags & IFA_ROUTE) == 0 && + ifa_ref(&ia->ia_ifa) != 0) { IN_IFADDR_RUNLOCK(&in_ifa_tracker); error = rtinit(&(target->ia_ifa), (int)RTM_DELETE, rtinitflags(target)); Index: sys/netinet/ip_carp.c =================================================================== --- sys/netinet/ip_carp.c +++ sys/netinet/ip_carp.c @@ -669,8 +669,8 @@ error = ELOOP; } ifa = error ? NULL : match; - if (ifa != NULL) - ifa_ref(ifa); + if (ifa != NULL && ifa_ref(ifa) == 0) + ifa = NULL; IF_ADDR_RUNLOCK(ifp); if (ifa == NULL) { @@ -891,8 +891,8 @@ best = ifa; } IF_ADDR_RUNLOCK(ifp); - if (best != NULL) - ifa_ref(best); + if (best != NULL && ifa_ref(best) == 0) + best = NULL; return (best); } @@ -1176,10 +1176,10 @@ continue; if (!IN6_ARE_ADDR_EQUAL(taddr, IFA_IN6(ifa))) continue; - if (ifa->ifa_carp && ifa->ifa_carp->sc_state != MASTER) + if ((ifa->ifa_carp && ifa->ifa_carp->sc_state != MASTER) || + ifa_ref(ifa) == 0) { ifa = NULL; - else - ifa_ref(ifa); + } break; } IF_ADDR_RUNLOCK(ifp); @@ -1890,6 +1890,9 @@ KASSERT(ifa->ifa_carp == NULL, ("%s: ifa %p attached", __func__, ifa)); + if (ifa_ref(ifa) == 0) + return (ENXIO); + switch (ifa->ifa_addr->sa_family) { #ifdef INET case AF_INET: @@ -1899,28 +1902,28 @@ #endif break; default: - return (EPROTOTYPE); + error = EPROTOTYPE; + goto err; } sx_xlock(&carp_sx); if (ifp->if_carp == NULL) { - sx_xunlock(&carp_sx); - return (ENOPROTOOPT); + error = ENOPROTOOPT; + goto err_unlock; } IFNET_FOREACH_CARP(ifp, sc) if (sc->sc_vhid == vhid) break; if (sc == NULL) { - sx_xunlock(&carp_sx); - return (ENOENT); + error = ENOENT; + goto err_unlock; } error = carp_multicast_setup(cif, ifa->ifa_addr->sa_family); if (error) { CIF_FREE(cif); - sx_xunlock(&carp_sx); - return (error); + goto err_unlock; } index = sc->sc_naddrs + sc->sc_naddrs6 + 1; @@ -1942,8 +1945,6 @@ #endif } - ifa_ref(ifa); - CARP_LOCK(sc); sc->sc_ifas[index - 1] = ifa; ifa->ifa_carp = sc; @@ -1954,6 +1955,12 @@ sx_xunlock(&carp_sx); return (0); + +err_unlock: + sx_xunlock(&carp_sx); +err: + ifa_free(ifa); + return (error); } void Index: sys/netinet/raw_ip.c =================================================================== --- sys/netinet/raw_ip.c +++ sys/netinet/raw_ip.c @@ -758,8 +758,8 @@ IN_IFADDR_RLOCK(&in_ifa_tracker); CK_STAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) { if (ia->ia_ifa.ifa_addr == sa - && (ia->ia_flags & IFA_ROUTE)) { - ifa_ref(&ia->ia_ifa); + && (ia->ia_flags & IFA_ROUTE) && + ifa_ref(&ia->ia_ifa) != 0) { IN_IFADDR_RUNLOCK(&in_ifa_tracker); /* * in_scrubprefix() kills the interface route. @@ -786,11 +786,11 @@ if (ia->ia_ifa.ifa_addr == sa) break; } - if (ia == NULL || (ia->ia_flags & IFA_ROUTE)) { + if (ia == NULL || (ia->ia_flags & IFA_ROUTE) || + ifa_ref(&ia->ia_ifa) == 0) { IN_IFADDR_RUNLOCK(&in_ifa_tracker); return; } - ifa_ref(&ia->ia_ifa); IN_IFADDR_RUNLOCK(&in_ifa_tracker); flags = RTF_UP; ifp = ia->ia_ifa.ifa_ifp; Index: sys/netinet6/in6.c =================================================================== --- sys/netinet6/in6.c +++ sys/netinet6/in6.c @@ -1118,17 +1118,17 @@ } ia->ia_ifp = ifp; - ifa_ref(&ia->ia_ifa); /* if_addrhead */ - IF_ADDR_WLOCK(ifp); - CK_STAILQ_INSERT_TAIL(&ifp->if_addrhead, &ia->ia_ifa, ifa_link); - IF_ADDR_WUNLOCK(ifp); - - ifa_ref(&ia->ia_ifa); /* in6_ifaddrhead */ - IN6_IFADDR_WLOCK(); - CK_STAILQ_INSERT_TAIL(&V_in6_ifaddrhead, ia, ia_link); - CK_LIST_INSERT_HEAD(IN6ADDR_HASH(&ia->ia_addr.sin6_addr), ia, ia6_hash); - IN6_IFADDR_WUNLOCK(); - + if (ifa_ref(&ia->ia_ifa) != 0) { + IF_ADDR_WLOCK(ifp); + CK_STAILQ_INSERT_TAIL(&ifp->if_addrhead, &ia->ia_ifa, ifa_link); + IF_ADDR_WUNLOCK(ifp); + } + if (ifa_ref(&ia->ia_ifa) != 0) { + IN6_IFADDR_WLOCK(); + CK_STAILQ_INSERT_TAIL(&V_in6_ifaddrhead, ia, ia_link); + CK_LIST_INSERT_HEAD(IN6ADDR_HASH(&ia->ia_addr.sin6_addr), ia, ia6_hash); + IN6_IFADDR_WUNLOCK(); + } return (ia); } @@ -1457,11 +1457,11 @@ WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "Invoking IPv6 network device address event may sleep"); - ifa_ref(&ia->ia_ifa); - EVENTHANDLER_INVOKE(ifaddr_event_ext, ifp, &ia->ia_ifa, - IFADDR_EVENT_ADD); - ifa_free(&ia->ia_ifa); - + if (ifa_ref(&ia->ia_ifa) != 0) { + EVENTHANDLER_INVOKE(ifaddr_event_ext, ifp, &ia->ia_ifa, + IFADDR_EVENT_ADD); + ifa_free(&ia->ia_ifa); + } return (error); } @@ -1480,10 +1480,8 @@ continue; if (IN6_IS_ADDR_LINKLOCAL(IFA_IN6(ifa))) { if ((((struct in6_ifaddr *)ifa)->ia6_flags & - ignoreflags) != 0) - continue; - ifa_ref(ifa); - break; + ignoreflags) == 0 && ifa_ref(ifa) != 0) + break; } } IF_ADDR_RUNLOCK(ifp); @@ -1508,8 +1506,8 @@ if (zoneid != 0 && zoneid != ia->ia_addr.sin6_scope_id) continue; - ifa_ref(&ia->ia_ifa); - break; + if (ifa_ref(&ia->ia_ifa) != 0) + break; } } IN6_IFADDR_RUNLOCK(&in6_ifa_tracker); @@ -1529,10 +1527,9 @@ CK_STAILQ_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))) { - ifa_ref(ifa); + if (IN6_ARE_ADDR_EQUAL(addr, IFA_IN6(ifa)) && + ifa_ref(ifa) != 0) break; - } } IF_ADDR_RUNLOCK(ifp); @@ -1864,8 +1861,7 @@ besta = (struct in6_ifaddr *)ifa; } } - if (besta) { - ifa_ref(&besta->ia_ifa); + if (besta && ifa_ref(&besta->ia_ifa) != 0) { IF_ADDR_RUNLOCK(ifp); return (besta); } @@ -1884,21 +1880,18 @@ dep[1] = (struct in6_ifaddr *)ifa; continue; } - - if (ifa != NULL) - ifa_ref(ifa); + if (ifa_ref(ifa) == 0) + continue; IF_ADDR_RUNLOCK(ifp); return (struct in6_ifaddr *)ifa; } /* use the last-resort values, that are, deprecated addresses */ - if (dep[0]) { - ifa_ref((struct ifaddr *)dep[0]); + if (dep[0] && ifa_ref((struct ifaddr *)dep[0]) != 0) { IF_ADDR_RUNLOCK(ifp); return dep[0]; } - if (dep[1]) { - ifa_ref((struct ifaddr *)dep[1]); + if (dep[1] && ifa_ref((struct ifaddr *)dep[1]) != 0) { IF_ADDR_RUNLOCK(ifp); return dep[1]; } Index: sys/netinet6/nd6.c =================================================================== --- sys/netinet6/nd6.c +++ sys/netinet6/nd6.c @@ -1106,8 +1106,9 @@ if (!IFA6_IS_DEPRECATED(it6)) public_ifa6 = it6; } - if (public_ifa6 != NULL) - ifa_ref(&public_ifa6->ia_ifa); + if (public_ifa6 != NULL && + ifa_ref(&public_ifa6->ia_ifa) == 0) + public_ifa6 = NULL; IF_ADDR_RUNLOCK(ifp); if (public_ifa6 != NULL) { Index: sys/netinet6/nd6_nbr.c =================================================================== --- sys/netinet6/nd6_nbr.c +++ sys/netinet6/nd6_nbr.c @@ -1261,12 +1261,16 @@ return; } + if (ifa_ref(ifa) == 0) + return; /* Network address has been freed */ + dp = malloc(sizeof(*dp), M_IP6NDP, M_NOWAIT | M_ZERO); if (dp == NULL) { log(LOG_ERR, "nd6_dad_start: memory allocation failed for " "%s(%s)\n", ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr), ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???"); + ifa_free(ifa); return; } callout_init(&dp->dad_timer_ch, 0); @@ -1283,7 +1287,6 @@ * (re)initialization. */ dp->dad_ifa = ifa; - ifa_ref(dp->dad_ifa); dp->dad_count = V_ip6_dad_count; dp->dad_ns_icount = dp->dad_na_icount = 0; dp->dad_ns_ocount = dp->dad_ns_tcount = 0; Index: sys/netinet6/nd6_rtr.c =================================================================== --- sys/netinet6/nd6_rtr.c +++ sys/netinet6/nd6_rtr.c @@ -480,7 +480,8 @@ IF_ADDR_RLOCK(ifp); ifa = CK_STAILQ_FIRST(&ifp->if_addrhead); info.rti_info[RTAX_IFP] = ifa->ifa_addr; - ifa_ref(ifa); + if (ifa_ref(ifa) == 0) + ifa = NULL; IF_ADDR_RUNLOCK(ifp); info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr; } else @@ -1909,8 +1910,8 @@ /* XXX: freebsd does not have ifa_ifwithaf */ IF_ADDR_RLOCK(ifp); CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { - if (ifa->ifa_addr->sa_family == AF_INET6) { - ifa_ref(ifa); + if (ifa->ifa_addr->sa_family == AF_INET6 && + ifa_ref(ifa) != 0) { break; } }