summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/netinet/in.c33
-rw-r--r--sys/netinet/in_var.h2
2 files changed, 33 insertions, 2 deletions
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);
}
diff --git a/sys/netinet/in_var.h b/sys/netinet/in_var.h
index da728a6..7d22844 100644
--- a/sys/netinet/in_var.h
+++ b/sys/netinet/in_var.h
@@ -247,6 +247,8 @@ do { \
struct route;
struct in_multi *in_addmulti(struct in_addr *, struct ifnet *);
void in_delmulti(struct in_multi *);
+void in_delmulti_locked(struct in_multi *);
+void in_delmulti_ifp(struct ifnet *ifp);
int in_control(struct socket *, u_long, caddr_t, struct ifnet *,
struct thread *);
void in_rtqdrain(void);
OpenPOWER on IntegriCloud