summaryrefslogtreecommitdiffstats
path: root/sys/netinet/ip_carp.c
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2009-04-26 19:05:40 +0000
committerrwatson <rwatson@FreeBSD.org>2009-04-26 19:05:40 +0000
commit81b54c9672a05d5b452c1f848dc3ddfb2b9271ae (patch)
tree88e163122183c9e91ecbfa7ad86871be28e06ecd /sys/netinet/ip_carp.c
parent59019e8516a585542319c3d3a058f97468157f38 (diff)
downloadFreeBSD-src-81b54c9672a05d5b452c1f848dc3ddfb2b9271ae.zip
FreeBSD-src-81b54c9672a05d5b452c1f848dc3ddfb2b9271ae.tar.gz
Acquire IF_ADDR_LOCK() around most iterations over ifp->if_addrhead
(colloquially known as if_addrlist). Currently not acquired around interface address loops that call out to the routing code due to potential lock order issues. MFC after: 3 weeks
Diffstat (limited to 'sys/netinet/ip_carp.c')
-rw-r--r--sys/netinet/ip_carp.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c
index 33b5059..b2922fc 100644
--- a/sys/netinet/ip_carp.c
+++ b/sys/netinet/ip_carp.c
@@ -275,6 +275,7 @@ carp_hmac_prepare(struct carp_softc *sc)
found = 0;
last = cur;
cur.s_addr = 0xffffffff;
+ IF_ADDR_LOCK(SC2IFP(sc));
TAILQ_FOREACH(ifa, &SC2IFP(sc)->if_addrlist, ifa_list) {
in.s_addr = ifatoia(ifa)->ia_addr.sin_addr.s_addr;
if (ifa->ifa_addr->sa_family == AF_INET &&
@@ -284,6 +285,7 @@ carp_hmac_prepare(struct carp_softc *sc)
found++;
}
}
+ IF_ADDR_UNLOCK(SC2IFP(sc));
if (found)
SHA1Update(&sc->sc_sha1, (void *)&cur, sizeof(cur));
} while (found);
@@ -294,6 +296,7 @@ carp_hmac_prepare(struct carp_softc *sc)
found = 0;
last6 = cur6;
memset(&cur6, 0xff, sizeof(cur6));
+ IF_ADDR_LOCK(SC2IFP(sc));
TAILQ_FOREACH(ifa, &SC2IFP(sc)->if_addrlist, ifa_list) {
in6 = ifatoia6(ifa)->ia_addr.sin6_addr;
if (IN6_IS_SCOPE_EMBED(&in6))
@@ -305,6 +308,7 @@ carp_hmac_prepare(struct carp_softc *sc)
found++;
}
}
+ IF_ADDR_UNLOCK(SC2IFP(sc));
if (found)
SHA1Update(&sc->sc_sha1, (void *)&cur6, sizeof(cur6));
} while (found);
@@ -1121,6 +1125,7 @@ carp_addrcount(struct carp_if *cif, struct in_ifaddr *ia, int type)
(SC2IFP(vh)->if_flags & IFF_UP) &&
(SC2IFP(vh)->if_drv_flags & IFF_DRV_RUNNING)) ||
(type == CARP_COUNT_MASTER && vh->sc_state == MASTER)) {
+ IF_ADDR_LOCK(SC2IFP(vh));
TAILQ_FOREACH(ifa, &SC2IFP(vh)->if_addrlist,
ifa_list) {
if (ifa->ifa_addr->sa_family == AF_INET &&
@@ -1128,6 +1133,7 @@ carp_addrcount(struct carp_if *cif, struct in_ifaddr *ia, int type)
ifatoia(ifa)->ia_addr.sin_addr.s_addr)
count++;
}
+ IF_ADDR_UNLOCK(SC2IFP(vh));
}
}
return (count);
@@ -1166,6 +1172,7 @@ carp_iamatch(void *v, struct in_ifaddr *ia,
TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list) {
if ((SC2IFP(vh)->if_flags & IFF_UP) &&
(SC2IFP(vh)->if_drv_flags & IFF_DRV_RUNNING)) {
+ IF_ADDR_LOCK(SC2IFP(vh));
TAILQ_FOREACH(ifa, &SC2IFP(vh)->if_addrlist,
ifa_list) {
if (ifa->ifa_addr->sa_family ==
@@ -1176,9 +1183,11 @@ carp_iamatch(void *v, struct in_ifaddr *ia,
if (vh->sc_state ==
MASTER) {
*enaddr = IF_LLADDR(vh->sc_ifp);
+ IF_ADDR_UNLOCK(SC2IFP(vh));
CARP_UNLOCK(cif);
return (1);
} else {
+ IF_ADDR_UNLOCK(SC2IFP(vh));
CARP_UNLOCK(cif);
return (0);
}
@@ -1186,6 +1195,7 @@ carp_iamatch(void *v, struct in_ifaddr *ia,
count++;
}
}
+ IF_ADDR_UNLOCK(SC2IFP(vh));
}
}
} else {
@@ -1214,16 +1224,19 @@ carp_iamatch6(void *v, struct in6_addr *taddr)
CARP_LOCK(cif);
TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list) {
+ IF_ADDR_LOCK(SC2IFP(vh));
TAILQ_FOREACH(ifa, &SC2IFP(vh)->if_addrlist, ifa_list) {
if (IN6_ARE_ADDR_EQUAL(taddr,
&ifatoia6(ifa)->ia_addr.sin6_addr) &&
(SC2IFP(vh)->if_flags & IFF_UP) &&
(SC2IFP(vh)->if_drv_flags & IFF_DRV_RUNNING) &&
vh->sc_state == MASTER) {
+ IF_ADDR_UNLOCK(SC2IFP(vh));
CARP_UNLOCK(cif);
return (ifa);
}
}
+ IF_ADDR_UNLOCK(SC2IFP(vh));
}
CARP_UNLOCK(cif);
@@ -1240,6 +1253,7 @@ carp_macmatch6(void *v, struct mbuf *m, const struct in6_addr *taddr)
CARP_LOCK(cif);
TAILQ_FOREACH(sc, &cif->vhif_vrs, sc_list) {
+ IF_ADDR_LOCK(SC2IFP(sc));
TAILQ_FOREACH(ifa, &SC2IFP(sc)->if_addrlist, ifa_list) {
if (IN6_ARE_ADDR_EQUAL(taddr,
&ifatoia6(ifa)->ia_addr.sin6_addr) &&
@@ -1250,6 +1264,7 @@ carp_macmatch6(void *v, struct mbuf *m, const struct in6_addr *taddr)
sizeof(struct ifnet *), M_NOWAIT);
if (mtag == NULL) {
/* better a bit than nothing */
+ IF_ADDR_UNLOCK(SC2IFP(sc));
CARP_UNLOCK(cif);
return (IF_LLADDR(sc->sc_ifp));
}
@@ -1257,10 +1272,12 @@ carp_macmatch6(void *v, struct mbuf *m, const struct in6_addr *taddr)
sizeof(struct ifnet *));
m_tag_prepend(m, mtag);
+ IF_ADDR_UNLOCK(SC2IFP(sc));
CARP_UNLOCK(cif);
return (IF_LLADDR(sc->sc_ifp));
}
}
+ IF_ADDR_UNLOCK(SC2IFP(sc));
}
CARP_UNLOCK(cif);
OpenPOWER on IntegriCloud