summaryrefslogtreecommitdiffstats
path: root/sys/netinet/ip_carp.c
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2009-06-25 16:35:28 +0000
committerrwatson <rwatson@FreeBSD.org>2009-06-25 16:35:28 +0000
commitbd6eb7be79d81290efa6dcaa9f492a05b1966344 (patch)
treeff4ff11920651e5f6aaeaa54e259e4f335eec1af /sys/netinet/ip_carp.c
parent07492aedb8a9805aa9b5287012a05ac498d59d7b (diff)
downloadFreeBSD-src-bd6eb7be79d81290efa6dcaa9f492a05b1966344.zip
FreeBSD-src-bd6eb7be79d81290efa6dcaa9f492a05b1966344.tar.gz
Add address list locking for in6_ifaddrhead/ia_link: as with locking
for in_ifaddrhead, we stick with an rwlock for the time being, which we will revisit in the future with a possible move to rmlocks. Some pieces of code require significant further reworking to be safe from all classes of writer-writer races. Reviewed by: bz MFC after: 6 weeks
Diffstat (limited to 'sys/netinet/ip_carp.c')
-rw-r--r--sys/netinet/ip_carp.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c
index 8c7bd0c..152f5e6 100644
--- a/sys/netinet/ip_carp.c
+++ b/sys/netinet/ip_carp.c
@@ -1680,6 +1680,7 @@ carp_set_addr6(struct carp_softc *sc, struct sockaddr_in6 *sin6)
/* we have to do it by hands to check we won't match on us */
ia_if = NULL; own = 0;
+ IN6_IFADDR_RLOCK();
TAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) {
int i;
@@ -1702,14 +1703,20 @@ carp_set_addr6(struct carp_softc *sc, struct sockaddr_in6 *sin6)
}
}
- if (!ia_if)
+ if (!ia_if) {
+ IN6_IFADDR_RUNLOCK();
return (EADDRNOTAVAIL);
+ }
ia = ia_if;
+ ifa_ref(&ia->ia_ifa);
+ IN6_IFADDR_RUNLOCK();
ifp = ia->ia_ifp;
if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0 ||
- (im6o->im6o_multicast_ifp && im6o->im6o_multicast_ifp != ifp))
+ (im6o->im6o_multicast_ifp && im6o->im6o_multicast_ifp != ifp)) {
+ ifa_free(&ia->ia_ifa);
return (EADDRNOTAVAIL);
+ }
if (!sc->sc_naddrs6) {
struct in6_multi *in6m;
@@ -1811,12 +1818,14 @@ carp_set_addr6(struct carp_softc *sc, struct sockaddr_in6 *sin6)
carp_setrun(sc, 0);
CARP_UNLOCK(cif);
+ ifa_free(&ia->ia_ifa); /* XXXRW: should hold reference for softc. */
return (0);
cleanup:
if (!sc->sc_naddrs6)
carp_multicast6_cleanup(sc);
+ ifa_free(&ia->ia_ifa);
return (error);
}
OpenPOWER on IntegriCloud