summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/netinet6/mld6.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/netinet6/mld6.c')
-rw-r--r--freebsd/sys/netinet6/mld6.c43
1 files changed, 25 insertions, 18 deletions
diff --git a/freebsd/sys/netinet6/mld6.c b/freebsd/sys/netinet6/mld6.c
index 0c82d5ff..b00f03ef 100644
--- a/freebsd/sys/netinet6/mld6.c
+++ b/freebsd/sys/netinet6/mld6.c
@@ -209,11 +209,11 @@ static MALLOC_DEFINE(M_MLD, "mld", "mld state");
/*
* VIMAGE-wide globals.
*/
-static VNET_DEFINE(struct timeval, mld_gsrdelay) = {10, 0};
-static VNET_DEFINE(LIST_HEAD(, mld_ifsoftc), mli_head);
-static VNET_DEFINE(int, interface_timers_running6);
-static VNET_DEFINE(int, state_change_timers_running6);
-static VNET_DEFINE(int, current_state_timers_running6);
+VNET_DEFINE_STATIC(struct timeval, mld_gsrdelay) = {10, 0};
+VNET_DEFINE_STATIC(LIST_HEAD(, mld_ifsoftc), mli_head);
+VNET_DEFINE_STATIC(int, interface_timers_running6);
+VNET_DEFINE_STATIC(int, state_change_timers_running6);
+VNET_DEFINE_STATIC(int, current_state_timers_running6);
#define V_mld_gsrdelay VNET(mld_gsrdelay)
#define V_mli_head VNET(mli_head)
@@ -559,6 +559,7 @@ mld_ifdetach(struct ifnet *ifp)
continue;
inm = (struct in6_multi *)ifma->ifma_protospec;
if (inm->in6m_state == MLD_LEAVING_MEMBER) {
+ in6m_disconnect(inm);
in6m_rele_locked(&inmh, inm);
ifma->ifma_protospec = NULL;
}
@@ -1485,6 +1486,7 @@ mld_v1_process_group_timer(struct in6_multi_head *inmh, struct in6_multi *inm)
case MLD_REPORTING_MEMBER:
if (report_timer_expired) {
inm->in6m_state = MLD_IDLE_MEMBER;
+ in6m_disconnect(inm);
in6m_rele_locked(inmh, inm);
}
break;
@@ -1609,6 +1611,7 @@ mld_v2_process_group_timers(struct in6_multi_head *inmh,
if (inm->in6m_state == MLD_LEAVING_MEMBER &&
inm->in6m_scrv == 0) {
inm->in6m_state = MLD_NOT_MEMBER;
+ in6m_disconnect(inm);
in6m_rele_locked(inmh, inm);
}
}
@@ -1681,7 +1684,8 @@ mld_v2_cancel_link_timers(struct mld_ifsoftc *mli)
IF_ADDR_WLOCK(ifp);
restart:
CK_STAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link, next) {
- if (ifma->ifma_addr->sa_family != AF_INET6)
+ if (ifma->ifma_addr->sa_family != AF_INET6 ||
+ ifma->ifma_protospec == NULL)
continue;
inm = (struct in6_multi *)ifma->ifma_protospec;
switch (inm->in6m_state) {
@@ -1698,6 +1702,7 @@ mld_v2_cancel_link_timers(struct mld_ifsoftc *mli)
* version, we need to release the final
* reference held for issuing the INCLUDE {}.
*/
+ in6m_disconnect(inm);
in6m_rele_locked(&inmh, inm);
ifma->ifma_protospec = NULL;
/* FALLTHROUGH */
@@ -1795,8 +1800,11 @@ mld_v1_transmit_report(struct in6_multi *in6m, const int type)
IN6_MULTI_LIST_LOCK_ASSERT();
MLD_LOCK_ASSERT();
-
+
ifp = in6m->in6m_ifp;
+ /* in process of being freed */
+ if (ifp == NULL)
+ return (0);
ia = in6ifa_ifpforlinklocal(ifp, IN6_IFF_NOTREADY|IN6_IFF_ANYCAST);
/* ia may be NULL if link-local address is tentative. */
@@ -1894,16 +1902,15 @@ mld_change_state(struct in6_multi *inm, const int delay)
*/
KASSERT(inm->in6m_ifma != NULL, ("%s: no ifma", __func__));
ifp = inm->in6m_ifma->ifma_ifp;
- if (ifp != NULL) {
- /*
- * Sanity check that netinet6's notion of ifp is the
- * same as net's.
- */
- KASSERT(inm->in6m_ifp == ifp, ("%s: bad ifp", __func__));
- }
+ if (ifp == NULL)
+ return (0);
+ /*
+ * Sanity check that netinet6's notion of ifp is the
+ * same as net's.
+ */
+ KASSERT(inm->in6m_ifp == ifp, ("%s: bad ifp", __func__));
MLD_LOCK();
-
mli = MLD_IFINFO(ifp);
KASSERT(mli != NULL, ("%s: no mld_ifsoftc for ifp %p", __func__, ifp));
@@ -1997,9 +2004,9 @@ mld_initial_join(struct in6_multi *inm, struct mld_ifsoftc *mli,
* group around for the final INCLUDE {} enqueue.
*/
if (mli->mli_version == MLD_VERSION_2 &&
- inm->in6m_state == MLD_LEAVING_MEMBER)
- in6m_release_deferred(inm);
-
+ inm->in6m_state == MLD_LEAVING_MEMBER) {
+ inm->in6m_refcount--;
+ }
inm->in6m_state = MLD_REPORTING_MEMBER;
switch (mli->mli_version) {