Since rev. 1.94 of netinet/in.c, the netinet layer frees all its

multicast memberships, when interface is detached. Thus, when
an underlying interface is detached, we do not need to free
our multicast memberships.

Reviewed by:	bms
This commit is contained in:
Gleb Smirnoff 2007-02-02 09:39:09 +00:00
parent d59fd7af69
commit fbfdcf8735

View File

@ -219,6 +219,7 @@ static void carp_sc_state_locked(struct carp_softc *);
static void carp_send_na(struct carp_softc *);
static int carp_set_addr6(struct carp_softc *, struct sockaddr_in6 *);
static int carp_del_addr6(struct carp_softc *, struct sockaddr_in6 *);
static void carp_multicast6_cleanup(struct carp_softc *);
#endif
static LIST_HEAD(, carp_softc) carpif_list;
@ -423,6 +424,16 @@ carp_clone_destroy(struct ifnet *ifp)
free(sc, M_CARP);
}
/*
* This function can be called on CARP interface destroy path,
* and in case of the removal of the underlying interface as
* well. We differentiate these two cases. In the latter case
* we do not cleanup our multicast memberships, since they
* are already freed. Also, in the latter case we do not
* release the lock on return, because the function will be
* called once more, for another CARP instance on the same
* interface.
*/
static void
carpdetach(struct carp_softc *sc, int unlock)
{
@ -443,7 +454,11 @@ carpdetach(struct carp_softc *sc, int unlock)
carp_set_state(sc, INIT);
SC2IFP(sc)->if_flags &= ~IFF_UP;
carp_setrun(sc, 0);
carp_multicast_cleanup(sc);
if (unlock)
carp_multicast_cleanup(sc);
#ifdef INET6
carp_multicast6_cleanup(sc);
#endif
if (sc->sc_carpdev != NULL) {
cif = (struct carp_if *)sc->sc_carpdev->if_carp;
@ -1369,13 +1384,10 @@ carp_setrun(struct carp_softc *sc, sa_family_t af)
}
}
void
static void
carp_multicast_cleanup(struct carp_softc *sc)
{
struct ip_moptions *imo = &sc->sc_imo;
#ifdef INET6
struct ip6_moptions *im6o = &sc->sc_im6o;
#endif
u_int16_t n = imo->imo_num_memberships;
/* Clean up our own multicast memberships */
@ -1387,8 +1399,14 @@ carp_multicast_cleanup(struct carp_softc *sc)
}
imo->imo_num_memberships = 0;
imo->imo_multicast_ifp = NULL;
}
#ifdef INET6
static void
carp_multicast6_cleanup(struct carp_softc *sc)
{
struct ip6_moptions *im6o = &sc->sc_im6o;
while (!LIST_EMPTY(&im6o->im6o_memberships)) {
struct in6_multi_mship *imm =
LIST_FIRST(&im6o->im6o_memberships);
@ -1397,8 +1415,8 @@ carp_multicast_cleanup(struct carp_softc *sc)
in6_leavegroup(imm);
}
im6o->im6o_multicast_ifp = NULL;
#endif
}
#endif
static int
carp_set_addr(struct carp_softc *sc, struct sockaddr_in *sin)