From b8c88cc5311a2eda826e4748545455fd429c6590 Mon Sep 17 00:00:00 2001 From: bms Date: Thu, 28 Sep 2006 10:04:07 +0000 Subject: The IPv4 code should clean up multicast group state when an interface goes away. Without this change, it leaks in_multi (and often ether_multi state) if many clonable interfaces are created and destroyed in quick succession. The concept of this fix is borrowed from KAME. Detailed information about this behaviour, as well as test cases, are available in the PR. PR: kern/78227 MFC after: 1 week --- sys/netinet/in.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) (limited to 'sys/netinet/in.c') diff --git a/sys/netinet/in.c b/sys/netinet/in.c index 7f23c10..64e1ba1 100644 --- a/sys/netinet/in.c +++ b/sys/netinet/in.c @@ -1025,13 +1025,23 @@ void in_delmulti(inm) register struct in_multi *inm; { - struct ifmultiaddr *ifma; - struct in_multi my_inm; struct ifnet *ifp; ifp = inm->inm_ifp; IFF_LOCKGIANT(ifp); IN_MULTI_LOCK(); + in_delmulti_locked(inm); + IN_MULTI_UNLOCK(); + IFF_UNLOCKGIANT(ifp); +} + +void +in_delmulti_locked(inm) + register struct in_multi *inm; +{ + struct ifmultiaddr *ifma; + struct in_multi my_inm; + ifma = inm->inm_ifma; my_inm.inm_ifp = NULL ; /* don't send the leave msg */ if (ifma->ifma_refcount == 1) { @@ -1050,6 +1060,24 @@ in_delmulti(inm) if_delmulti(ifma->ifma_ifp, ifma->ifma_addr); if (my_inm.inm_ifp != NULL) igmp_leavegroup(&my_inm); +} + +/* + * Delete all multicast address records associated with the ifp. + */ +void +in_delmulti_ifp(ifp) + register struct ifnet *ifp; +{ + struct in_multi *inm; + struct in_multi *oinm; + + IFF_LOCKGIANT(ifp); + IN_MULTI_LOCK(); + LIST_FOREACH_SAFE(inm, &in_multihead, inm_link, oinm) { + if (inm->inm_ifp == ifp) + in_delmulti_locked(inm); + } IN_MULTI_UNLOCK(); IFF_UNLOCKGIANT(ifp); } @@ -1064,4 +1092,5 @@ in_ifdetach(ifp) in_pcbpurgeif0(&ripcbinfo, ifp); in_pcbpurgeif0(&udbinfo, ifp); + in_delmulti_ifp(ifp); } -- cgit v1.1