Commit 94b0db3e authored by David Stevens's avatar David Stevens Committed by David S. Miller

[IPV4]: Fix IGMP device reference counting.


1) Check indev->dead instead of IFF_UP
2) Add missing ip_mc_down() call to ip_mc_destroy_dev().

Based upon a report from Willy Tarreau.
parent f0d4856e
...@@ -1067,7 +1067,7 @@ static void igmp_group_dropped(struct ip_mc_list *im) ...@@ -1067,7 +1067,7 @@ static void igmp_group_dropped(struct ip_mc_list *im)
reporter = im->reporter; reporter = im->reporter;
igmp_stop_timer(im); igmp_stop_timer(im);
if (in_dev->dev->flags & IFF_UP) { if (!in_dev->dead) {
if (IGMP_V1_SEEN(in_dev)) if (IGMP_V1_SEEN(in_dev))
goto done; goto done;
if (IGMP_V2_SEEN(in_dev)) { if (IGMP_V2_SEEN(in_dev)) {
...@@ -1098,6 +1098,8 @@ static void igmp_group_added(struct ip_mc_list *im) ...@@ -1098,6 +1098,8 @@ static void igmp_group_added(struct ip_mc_list *im)
if (im->multiaddr == IGMP_ALL_HOSTS) if (im->multiaddr == IGMP_ALL_HOSTS)
return; return;
if (in_dev->dead)
return;
if (IGMP_V1_SEEN(in_dev) || IGMP_V2_SEEN(in_dev)) { if (IGMP_V1_SEEN(in_dev) || IGMP_V2_SEEN(in_dev)) {
spin_lock_bh(&im->lock); spin_lock_bh(&im->lock);
igmp_start_timer(im, IGMP_Initial_Report_Delay); igmp_start_timer(im, IGMP_Initial_Report_Delay);
...@@ -1171,7 +1173,7 @@ void ip_mc_inc_group(struct in_device *in_dev, u32 addr) ...@@ -1171,7 +1173,7 @@ void ip_mc_inc_group(struct in_device *in_dev, u32 addr)
igmpv3_del_delrec(in_dev, im->multiaddr); igmpv3_del_delrec(in_dev, im->multiaddr);
#endif #endif
igmp_group_added(im); igmp_group_added(im);
if (in_dev->dev->flags & IFF_UP) if (!in_dev->dead)
ip_rt_multicast_event(in_dev); ip_rt_multicast_event(in_dev);
out: out:
return; return;
...@@ -1195,7 +1197,7 @@ void ip_mc_dec_group(struct in_device *in_dev, u32 addr) ...@@ -1195,7 +1197,7 @@ void ip_mc_dec_group(struct in_device *in_dev, u32 addr)
write_unlock_bh(&in_dev->lock); write_unlock_bh(&in_dev->lock);
igmp_group_dropped(i); igmp_group_dropped(i);
if (in_dev->dev->flags & IFF_UP) if (!in_dev->dead)
ip_rt_multicast_event(in_dev); ip_rt_multicast_event(in_dev);
ip_ma_put(i); ip_ma_put(i);
...@@ -1271,6 +1273,9 @@ void ip_mc_destroy_dev(struct in_device *in_dev) ...@@ -1271,6 +1273,9 @@ void ip_mc_destroy_dev(struct in_device *in_dev)
ASSERT_RTNL(); ASSERT_RTNL();
/* Deactivate timers */
ip_mc_down(in_dev);
write_lock_bh(&in_dev->lock); write_lock_bh(&in_dev->lock);
while ((i = in_dev->mc_list) != NULL) { while ((i = in_dev->mc_list) != NULL) {
in_dev->mc_list = i->next; in_dev->mc_list = i->next;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment