Index: sys/netinet6/in6_mcast.c
===================================================================
--- sys/netinet6/in6_mcast.c	(revision 342455)
+++ sys/netinet6/in6_mcast.c	(working copy)
@@ -426,6 +426,7 @@
 		 * If we already joined this group, just bump the
 		 * refcount and return it.
 		 */
+		hptrace(inm, "check");
 		KASSERT(inm->in6m_refcount >= 1,
 		    ("%s: bad refcount %d", __func__, inm->in6m_refcount));
 		in6m_acquire_locked(inm);
@@ -497,6 +498,7 @@
 	inm->in6m_mli = MLD_IFINFO(ifp);
 	inm->in6m_ifma = ifma;
 	inm->in6m_refcount = 1;
+	hptrace(inm, "set");
 	inm->in6m_state = MLD_NOT_MEMBER;
 	mbufq_init(&inm->in6m_scq, MLD_MAX_STATE_CHANGES);
 
@@ -527,6 +529,8 @@
 
 	CTR2(KTR_MLD, "%s: refcount is %d", __func__, inm->in6m_refcount);
 
+	hptrace(inm, "check");
+
 	MPASS(inm->in6m_refcount == 0);
 	CTR2(KTR_MLD, "%s: freeing inm %p", __func__, inm);
 
@@ -632,6 +636,9 @@
 		    i6mm_chain, imm_tmp) {
 			if (inm == imm->i6mm_maddr) {
 				LIST_REMOVE(imm, i6mm_chain);
+				inm->in6m_refcount--;
+				hptrace(inm, "list remove - post dec");
+				MPASS(inm->in6m_refcount > 0);
 				free(imm, M_IP6MADDR);
 			}
 		}
@@ -646,6 +653,7 @@
 	IN6_MULTI_LIST_LOCK_ASSERT();
 	KASSERT(inm->in6m_refcount > 0, ("refcount == %d inm: %p", inm->in6m_refcount, inm));
 	if (--inm->in6m_refcount == 0) {
+		hptrace(inm, "list release - post dec");
 		MPASS(inm->in6m_ifp == NULL);
 		SLIST_INIT(&tmp);
 		inm->in6m_ifma->ifma_protospec = NULL;
@@ -652,6 +660,8 @@
 		MPASS(inm->in6m_ifma->ifma_llifma == NULL);
 		SLIST_INSERT_HEAD(&tmp, inm, in6m_nrele);
 		in6m_release_list_deferred(&tmp);
+	} else {
+		hptrace(inm, "list release - post dec");
 	}
 }
 
@@ -1413,6 +1423,8 @@
 	CTR2(KTR_MLD, "%s: dropping ref on %p", __func__, inm);
 	if (ifp)
 		IF_ADDR_WLOCK(ifp);
+
+	hptrace(inm, "leavegroup check");
 	if (inm->in6m_refcount == 1 && inm->in6m_ifp != NULL)
 		in6m_disconnect(inm);
 	in6m_release_deferred(inm);
Index: sys/netinet6/in6_var.h
===================================================================
--- sys/netinet6/in6_var.h	(revision 342455)
+++ sys/netinet6/in6_var.h	(working copy)
@@ -760,6 +760,15 @@
 	return (inm);
 }
 
+#include <sys/kdb.h>
+
+static inline void
+hptrace(struct in6_multi *inm, const char *msg)
+{
+	printf("%s - inm=%p - in6m_refcount = %d\n", msg, inm, inm->in6m_refcount);
+	kdb_backtrace();
+}
+
 /* Acquire an in6_multi record. */
 static __inline void
 in6m_acquire_locked(struct in6_multi *inm)
@@ -767,6 +776,7 @@
 
 	IN6_MULTI_LIST_LOCK_ASSERT();
 	++inm->in6m_refcount;
+	hptrace(inm, "acquire_locked - post inc");
 }
 
 static __inline void
@@ -784,10 +794,13 @@
 	IN6_MULTI_LIST_LOCK_ASSERT();
 
 	if (--inm->in6m_refcount == 0) {
+		hptrace(inm, "rele_locked - post dec");
 		MPASS(inm->in6m_ifp == NULL);
 		inm->in6m_ifma->ifma_protospec = NULL;
 		MPASS(inm->in6m_ifma->ifma_llifma == NULL);
 		SLIST_INSERT_HEAD(inmh, inm, in6m_nrele);
+	} else {
+		hptrace(inm, "rele_locked - post dec");
 	}
 }
 
Index: sys/netinet6/mld6.c
===================================================================
--- sys/netinet6/mld6.c	(revision 342455)
+++ sys/netinet6/mld6.c	(working copy)
@@ -1895,6 +1895,14 @@
 	error = 0;
 
 	/*
+	 * Check if the in6_multi has already been disconnected.
+	 */
+	if (inm->in6m_ifp == NULL) {
+	  	CTR3(KTR_MLD, "%s: inm is disconnected", __func__);
+		return (0);
+	}
+
+	/*
 	 * Try to detect if the upper layer just asked us to change state
 	 * for an interface which has now gone away.
 	 */
@@ -2004,6 +2012,8 @@
 		if (mli->mli_version == MLD_VERSION_2 &&
 		    inm->in6m_state == MLD_LEAVING_MEMBER) {
 			inm->in6m_refcount--;
+			hptrace(inm, "leaving member - post dec");
+			MPASS(inm->in6m_refcount > 0);
 		}
 		inm->in6m_state = MLD_REPORTING_MEMBER;