View | Details | Raw Unified | Return to bug 233535 | Differences between
and this patch

Collapse All | Expand All

(-)sys/netinet6/in6_ifattach.c (-1 / +8 lines)
Lines 872-878 Link Here
872
		    ifma->ifma_protospec == NULL)
872
		    ifma->ifma_protospec == NULL)
873
			continue;
873
			continue;
874
		inm = (struct in6_multi *)ifma->ifma_protospec;
874
		inm = (struct in6_multi *)ifma->ifma_protospec;
875
		in6m_disconnect(inm);
875
		in6m_disconnect_locked(&purgeinms, inm);
876
		in6m_rele_locked(&purgeinms, inm);
876
		in6m_rele_locked(&purgeinms, inm);
877
		if (__predict_false(ifma6_restart)) {
877
		if (__predict_false(ifma6_restart)) {
878
			ifma6_restart = false;
878
			ifma6_restart = false;
Lines 884-889 Link Here
884
	IN6_MULTI_LIST_UNLOCK();
884
	IN6_MULTI_LIST_UNLOCK();
885
	IN6_MULTI_UNLOCK();
885
	IN6_MULTI_UNLOCK();
886
	in6m_release_list_deferred(&purgeinms);
886
	in6m_release_list_deferred(&purgeinms);
887
888
	/*
889
	 * Make sure all multicast deletions invoking if_ioctl() are
890
	 * completed before returning. Else we risk accessing a freed
891
	 * ifnet structure pointer.
892
	 */
893
	in6m_release_wait();
887
}
894
}
888
895
889
void
896
void
(-)sys/netinet6/in6_mcast.c (-7 / +23 lines)
Lines 585-592 Link Here
585
}
585
}
586
586
587
void
587
void
588
in6m_disconnect(struct in6_multi *inm)
588
in6m_release_wait(void)
589
{
589
{
590
	/* wait for all jobs to complete */
591
	gtaskqueue_drain_all(free_gtask.gt_taskqueue);
592
}
593
594
void
595
in6m_disconnect_locked(struct in6_multi_head *inmh, struct in6_multi *inm)
596
{
590
	struct ifnet *ifp;
597
	struct ifnet *ifp;
591
	struct ifaddr *ifa;
598
	struct ifaddr *ifa;
592
	struct in6_ifaddr *ifa6;
599
	struct in6_ifaddr *ifa6;
Lines 593-602 Link Here
593
	struct in6_multi_mship *imm, *imm_tmp;
600
	struct in6_multi_mship *imm, *imm_tmp;
594
	struct ifmultiaddr *ifma, *ll_ifma;
601
	struct ifmultiaddr *ifma, *ll_ifma;
595
602
603
	IN6_MULTI_LIST_LOCK_ASSERT();
604
596
	ifp = inm->in6m_ifp;
605
	ifp = inm->in6m_ifp;
606
	if (ifp == NULL)
607
		return;		/* already called */
597
608
598
	if (ifp == NULL)
599
		return;
600
	inm->in6m_ifp = NULL;
609
	inm->in6m_ifp = NULL;
601
	IF_ADDR_WLOCK_ASSERT(ifp);
610
	IF_ADDR_WLOCK_ASSERT(ifp);
602
	ifma = inm->in6m_ifma;
611
	ifma = inm->in6m_ifma;
Lines 633-638 Link Here
633
			if (inm == imm->i6mm_maddr) {
642
			if (inm == imm->i6mm_maddr) {
634
				LIST_REMOVE(imm, i6mm_chain);
643
				LIST_REMOVE(imm, i6mm_chain);
635
				free(imm, M_IP6MADDR);
644
				free(imm, M_IP6MADDR);
645
				in6m_rele_locked(inmh, inm);
636
			}
646
			}
637
		}
647
		}
638
	}
648
	}
Lines 1324-1330 Link Here
1324
				break;
1334
				break;
1325
			}
1335
			}
1326
		}
1336
		}
1327
		in6m_disconnect(inm);
1337
		in6m_disconnect_locked(NULL, inm);
1328
		in6m_release_deferred(inm);
1338
		in6m_release_deferred(inm);
1329
		NET_EPOCH_EXIT(et);
1339
		NET_EPOCH_EXIT(et);
1330
	} else {
1340
	} else {
Lines 1413-1420 Link Here
1413
	CTR2(KTR_MLD, "%s: dropping ref on %p", __func__, inm);
1423
	CTR2(KTR_MLD, "%s: dropping ref on %p", __func__, inm);
1414
	if (ifp)
1424
	if (ifp)
1415
		IF_ADDR_WLOCK(ifp);
1425
		IF_ADDR_WLOCK(ifp);
1416
	if (inm->in6m_refcount == 1 && inm->in6m_ifp != NULL)
1426
1417
		in6m_disconnect(inm);
1427
	if (inm->in6m_refcount == 1) {
1428
		/*
1429
		 * When there is only one reference left, the "inm"
1430
		 * cannot be on any membership lists. It is therefore
1431
		 * safe to pass NULL to the "inmh" freelist pointer.
1432
		 */
1433
		in6m_disconnect_locked(NULL, inm);
1434
	}
1418
	in6m_release_deferred(inm);
1435
	in6m_release_deferred(inm);
1419
	if (ifp)
1436
	if (ifp)
1420
		IF_ADDR_WUNLOCK(ifp);
1437
		IF_ADDR_WUNLOCK(ifp);
Lines 2178-2184 Link Here
2178
			IN6_MULTI_UNLOCK();
2195
			IN6_MULTI_UNLOCK();
2179
			goto out_im6o_free;
2196
			goto out_im6o_free;
2180
		}
2197
		}
2181
		in6m_acquire(inm);
2182
		imo->im6o_membership[idx] = inm;
2198
		imo->im6o_membership[idx] = inm;
2183
	} else {
2199
	} else {
2184
		CTR1(KTR_MLD, "%s: merge inm state", __func__);
2200
		CTR1(KTR_MLD, "%s: merge inm state", __func__);
(-)sys/netinet6/in6_var.h (-1 / +3 lines)
Lines 670-677 Link Here
670
	}			in6m_st[2];	/* state at t0, t1 */
670
	}			in6m_st[2];	/* state at t0, t1 */
671
};
671
};
672
672
673
void in6m_disconnect(struct in6_multi *inm);
673
void in6m_disconnect_locked(struct in6_multi_head *inmh, struct in6_multi *inm);
674
extern int ifma6_restart;
674
extern int ifma6_restart;
675
675
/*
676
/*
676
 * Helper function to derive the filter mode on a source entry
677
 * Helper function to derive the filter mode on a source entry
677
 * from its internal counters. Predicates are:
678
 * from its internal counters. Predicates are:
Lines 811-816 Link Here
811
int	in6m_record_source(struct in6_multi *, const struct in6_addr *);
812
int	in6m_record_source(struct in6_multi *, const struct in6_addr *);
812
void	in6m_release_deferred(struct in6_multi *);
813
void	in6m_release_deferred(struct in6_multi *);
813
void	in6m_release_list_deferred(struct in6_multi_head *);
814
void	in6m_release_list_deferred(struct in6_multi_head *);
815
void	in6m_release_wait(void);
814
void	ip6_freemoptions(struct ip6_moptions *);
816
void	ip6_freemoptions(struct ip6_moptions *);
815
int	ip6_getmoptions(struct inpcb *, struct sockopt *);
817
int	ip6_getmoptions(struct inpcb *, struct sockopt *);
816
int	ip6_setmoptions(struct inpcb *, struct sockopt *);
818
int	ip6_setmoptions(struct inpcb *, struct sockopt *);
(-)sys/netinet6/mld6.c (-5 / +13 lines)
Lines 557-563 Link Here
557
				continue;
557
				continue;
558
			inm = (struct in6_multi *)ifma->ifma_protospec;
558
			inm = (struct in6_multi *)ifma->ifma_protospec;
559
			if (inm->in6m_state == MLD_LEAVING_MEMBER) {
559
			if (inm->in6m_state == MLD_LEAVING_MEMBER) {
560
				in6m_disconnect(inm);
560
				in6m_disconnect_locked(&inmh, inm);
561
				in6m_rele_locked(&inmh, inm);
561
				in6m_rele_locked(&inmh, inm);
562
				ifma->ifma_protospec = NULL;
562
				ifma->ifma_protospec = NULL;
563
			}
563
			}
Lines 1488-1495 Link Here
1488
	case MLD_REPORTING_MEMBER:
1488
	case MLD_REPORTING_MEMBER:
1489
		if (report_timer_expired) {
1489
		if (report_timer_expired) {
1490
			inm->in6m_state = MLD_IDLE_MEMBER;
1490
			inm->in6m_state = MLD_IDLE_MEMBER;
1491
			in6m_disconnect(inm);
1491
			in6m_disconnect_locked(inmh, inm);
1492
			in6m_rele_locked(inmh, inm);
1493
		}
1492
		}
1494
		break;
1493
		break;
1495
	case MLD_G_QUERY_PENDING_MEMBER:
1494
	case MLD_G_QUERY_PENDING_MEMBER:
Lines 1613-1619 Link Here
1613
			if (inm->in6m_state == MLD_LEAVING_MEMBER &&
1612
			if (inm->in6m_state == MLD_LEAVING_MEMBER &&
1614
			    inm->in6m_scrv == 0) {
1613
			    inm->in6m_scrv == 0) {
1615
				inm->in6m_state = MLD_NOT_MEMBER;
1614
				inm->in6m_state = MLD_NOT_MEMBER;
1616
				in6m_disconnect(inm);
1615
				in6m_disconnect_locked(inmh, inm);
1617
				in6m_rele_locked(inmh, inm);
1616
				in6m_rele_locked(inmh, inm);
1618
			}
1617
			}
1619
		}
1618
		}
Lines 1704-1710 Link Here
1704
			 * version, we need to release the final
1703
			 * version, we need to release the final
1705
			 * reference held for issuing the INCLUDE {}.
1704
			 * reference held for issuing the INCLUDE {}.
1706
			 */
1705
			 */
1707
			in6m_disconnect(inm);
1706
			in6m_disconnect_locked(&inmh, inm);
1708
			in6m_rele_locked(&inmh, inm);
1707
			in6m_rele_locked(&inmh, inm);
1709
			ifma->ifma_protospec = NULL;
1708
			ifma->ifma_protospec = NULL;
1710
			/* FALLTHROUGH */
1709
			/* FALLTHROUGH */
Lines 1899-1904 Link Here
1899
	error = 0;
1898
	error = 0;
1900
1899
1901
	/*
1900
	/*
1901
	 * Check if the in6_multi has already been disconnected.
1902
	 */
1903
	if (inm->in6m_ifp == NULL) {
1904
	  	CTR1(KTR_MLD, "%s: inm is disconnected", __func__);
1905
		return (0);
1906
	}
1907
1908
	/*
1902
	 * Try to detect if the upper layer just asked us to change state
1909
	 * Try to detect if the upper layer just asked us to change state
1903
	 * for an interface which has now gone away.
1910
	 * for an interface which has now gone away.
1904
	 */
1911
	 */
Lines 2008-2013 Link Here
2008
		if (mli->mli_version == MLD_VERSION_2 &&
2015
		if (mli->mli_version == MLD_VERSION_2 &&
2009
		    inm->in6m_state == MLD_LEAVING_MEMBER) {
2016
		    inm->in6m_state == MLD_LEAVING_MEMBER) {
2010
			inm->in6m_refcount--;
2017
			inm->in6m_refcount--;
2018
			MPASS(inm->in6m_refcount > 0);
2011
		}
2019
		}
2012
		inm->in6m_state = MLD_REPORTING_MEMBER;
2020
		inm->in6m_state = MLD_REPORTING_MEMBER;
2013
2021

Return to bug 233535