diff options
Diffstat (limited to 'net/ipv4/igmp.c')
-rw-r--r-- | net/ipv4/igmp.c | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 111eb678cbac..e21ebe759907 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c | |||
@@ -1724,6 +1724,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct | |||
1724 | struct in_device *in_dev = NULL; | 1724 | struct in_device *in_dev = NULL; |
1725 | struct inet_sock *inet = inet_sk(sk); | 1725 | struct inet_sock *inet = inet_sk(sk); |
1726 | struct ip_sf_socklist *psl; | 1726 | struct ip_sf_socklist *psl; |
1727 | int leavegroup = 0; | ||
1727 | int i, j, rv; | 1728 | int i, j, rv; |
1728 | 1729 | ||
1729 | if (!MULTICAST(addr)) | 1730 | if (!MULTICAST(addr)) |
@@ -1775,6 +1776,12 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct | |||
1775 | if (rv) /* source not found */ | 1776 | if (rv) /* source not found */ |
1776 | goto done; | 1777 | goto done; |
1777 | 1778 | ||
1779 | /* special case - (INCLUDE, empty) == LEAVE_GROUP */ | ||
1780 | if (psl->sl_count == 1 && omode == MCAST_INCLUDE) { | ||
1781 | leavegroup = 1; | ||
1782 | goto done; | ||
1783 | } | ||
1784 | |||
1778 | /* update the interface filter */ | 1785 | /* update the interface filter */ |
1779 | ip_mc_del_src(in_dev, &mreqs->imr_multiaddr, omode, 1, | 1786 | ip_mc_del_src(in_dev, &mreqs->imr_multiaddr, omode, 1, |
1780 | &mreqs->imr_sourceaddr, 1); | 1787 | &mreqs->imr_sourceaddr, 1); |
@@ -1831,6 +1838,8 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct | |||
1831 | &mreqs->imr_sourceaddr, 1); | 1838 | &mreqs->imr_sourceaddr, 1); |
1832 | done: | 1839 | done: |
1833 | rtnl_shunlock(); | 1840 | rtnl_shunlock(); |
1841 | if (leavegroup) | ||
1842 | return ip_mc_leave_group(sk, &imr); | ||
1834 | return err; | 1843 | return err; |
1835 | } | 1844 | } |
1836 | 1845 | ||