summaryrefslogtreecommitdiffstats
path: root/sys/netinet/ip_carp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet/ip_carp.c')
-rw-r--r--sys/netinet/ip_carp.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c
index edeec2a..8c7bd0c 100644
--- a/sys/netinet/ip_carp.c
+++ b/sys/netinet/ip_carp.c
@@ -1500,6 +1500,7 @@ carp_set_addr(struct carp_softc *sc, struct sockaddr_in *sin)
/* we have to do it by hands to check we won't match on us */
ia_if = NULL; own = 0;
+ IN_IFADDR_RLOCK();
TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
/* and, yeah, we need a multicast-capable iface too */
if (ia->ia_ifp != SC2IFP(sc) &&
@@ -1513,20 +1514,30 @@ carp_set_addr(struct carp_softc *sc, struct sockaddr_in *sin)
}
}
- if (!ia_if)
+ if (!ia_if) {
+ IN_IFADDR_RUNLOCK();
return (EADDRNOTAVAIL);
+ }
ia = ia_if;
+ ifa_ref(&ia->ia_ifa);
+ IN_IFADDR_RUNLOCK();
+
ifp = ia->ia_ifp;
if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0 ||
- (imo->imo_multicast_ifp && imo->imo_multicast_ifp != ifp))
+ (imo->imo_multicast_ifp && imo->imo_multicast_ifp != ifp)) {
+ ifa_free(&ia->ia_ifa);
return (EADDRNOTAVAIL);
+ }
if (imo->imo_num_memberships == 0) {
addr.s_addr = htonl(INADDR_CARP_GROUP);
- if ((imo->imo_membership[0] = in_addmulti(&addr, ifp)) == NULL)
+ if ((imo->imo_membership[0] = in_addmulti(&addr, ifp)) ==
+ NULL) {
+ ifa_free(&ia->ia_ifa);
return (ENOBUFS);
+ }
imo->imo_num_memberships++;
imo->imo_multicast_ifp = ifp;
imo->imo_multicast_ttl = CARP_DFLTTL;
@@ -1601,11 +1612,13 @@ carp_set_addr(struct carp_softc *sc, struct sockaddr_in *sin)
carp_setrun(sc, 0);
CARP_UNLOCK(cif);
+ ifa_free(&ia->ia_ifa); /* XXXRW: should hold reference for softc. */
return (0);
cleanup:
in_delmulti(imo->imo_membership[--imo->imo_num_memberships]);
+ ifa_free(&ia->ia_ifa);
return (error);
}
OpenPOWER on IntegriCloud