Index: sys/netinet/igmp.c =================================================================== --- sys/netinet/igmp.c +++ sys/netinet/igmp.c @@ -856,6 +856,7 @@ "process v2 query 0x%08x on ifp %p(%s)", ntohl(igmp->igmp_group.s_addr), ifp, ifp->if_xname); igmp_v2_update_group(inm, timer); + inm_release_deferred(inm); } } @@ -1081,6 +1082,8 @@ out_locked: IGMP_UNLOCK(); + if (inm) + inm_release_deferred(inm); IN_MULTI_LIST_UNLOCK(); return (0); @@ -1296,6 +1299,9 @@ } out_locked: + if (inm) + inm_release_deferred(inm); + IN_MULTI_LIST_UNLOCK(); return (0); @@ -1406,8 +1412,9 @@ break; } } - out_locked: + if (inm) + inm_release_deferred(inm); IN_MULTI_LIST_UNLOCK(); return (0); Index: sys/netinet/in_mcast.c =================================================================== --- sys/netinet/in_mcast.c +++ sys/netinet/in_mcast.c @@ -357,6 +357,8 @@ break; inm = NULL; } + if (inm) + inm_acquire_locked(inm); return (inm); } @@ -564,9 +566,8 @@ * If we already joined this group, just bump the * refcount and return it. */ - KASSERT(inm->inm_refcount >= 1, + KASSERT(inm->inm_refcount > 1, ("%s: bad refcount %d", __func__, inm->inm_refcount)); - inm_acquire_locked(inm); *pinm = inm; } IN_MULTI_LIST_UNLOCK(); @@ -638,7 +639,8 @@ inm->inm_ifp = ifp; inm->inm_igi = ii->ii_igmp; inm->inm_ifma = ifma; - inm->inm_refcount = 1; + /* One reference for the caller and one for the ifp */ + inm->inm_refcount = 2; inm->inm_state = IGMP_NOT_MEMBER; mbufq_init(&inm->inm_scq, IGMP_MAX_STATE_CHANGES); inm->inm_st[0].iss_fmode = MCAST_UNDEFINED; @@ -1314,6 +1316,7 @@ if (error) { CTR2(KTR_IGMPV3, "%s: dropping ref on %p", __func__, inm); + /* drop the callers reference */ inm_release_deferred(inm); } else { *pinm = inm; @@ -2285,7 +2288,6 @@ IN_MULTI_LIST_UNLOCK(); goto out_imo_free; } - inm_acquire(inm); imo->imo_membership[idx] = inm; } else { CTR1(KTR_IGMPV3, "%s: merge inm state", __func__);