Page MenuHomeFreeBSD

D17599.id49313.diff
No OneTemporary

D17599.id49313.diff

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);
}
@@ -964,12 +964,17 @@
void
if_purgeaddrs(struct ifnet *ifp)
{
- struct ifaddr *ifa, *next;
+ struct ifaddr *ifa;
+top:;
NET_EPOCH_ENTER();
- CK_STAILQ_FOREACH_SAFE(ifa, &ifp->if_addrhead, ifa_link, next) {
- if (ifa->ifa_addr->sa_family == AF_LINK)
- continue;
+ CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+ if (ifa->ifa_addr->sa_family != AF_LINK && ifa_ref(ifa) != 0)
+ break;
+ }
+ NET_EPOCH_EXIT();
+
+ if (ifa != NULL) {
#ifdef INET
/* XXX: Ugly!! ad hoc just for INET */
if (ifa->ifa_addr->sa_family == AF_INET) {
@@ -981,22 +986,24 @@
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);
+ goto top;
}
- NET_EPOCH_EXIT();
}
/*
@@ -1829,11 +1836,11 @@
return (NULL);
}
-void
+bool
ifa_ref(struct ifaddr *ifa)
{
- refcount_acquire(&ifa->ifa_refcnt);
+ return (refcount_acquire_if_not_zero(&ifa->ifa_refcnt));
}
static void
@@ -2200,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_var.h
===================================================================
--- sys/net/if_var.h
+++ sys/net/if_var.h
@@ -543,7 +543,7 @@
struct ifaddr * ifa_alloc(size_t size, int flags);
void ifa_free(struct ifaddr *ifa);
-void ifa_ref(struct ifaddr *ifa);
+bool ifa_ref(struct ifaddr *ifa) __result_use_check;
/*
* Multicast address structure. This is analogous to the ifaddr
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
@@ -859,8 +860,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
@@ -1117,17 +1117,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);
}
@@ -1476,10 +1476,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);
@@ -1504,8 +1502,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);
@@ -1525,10 +1523,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);
@@ -1860,8 +1857,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);
}
@@ -1880,21 +1876,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;
}
}

File Metadata

Mime Type
text/plain
Expires
Tue, Mar 24, 7:34 AM (5 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30236822
Default Alt Text
D17599.id49313.diff (13 KB)

Event Timeline