diff options
Diffstat (limited to 'net/ipv4/igmp.c')
-rw-r--r-- | net/ipv4/igmp.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index e21ebe759907..dbbfa09de4e8 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c | |||
@@ -1748,12 +1748,16 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct | |||
1748 | && pmc->multi.imr_ifindex == imr.imr_ifindex) | 1748 | && pmc->multi.imr_ifindex == imr.imr_ifindex) |
1749 | break; | 1749 | break; |
1750 | } | 1750 | } |
1751 | if (!pmc) /* must have a prior join */ | 1751 | if (!pmc) { /* must have a prior join */ |
1752 | err = -EINVAL; | ||
1752 | goto done; | 1753 | goto done; |
1754 | } | ||
1753 | /* if a source filter was set, must be the same mode as before */ | 1755 | /* if a source filter was set, must be the same mode as before */ |
1754 | if (pmc->sflist) { | 1756 | if (pmc->sflist) { |
1755 | if (pmc->sfmode != omode) | 1757 | if (pmc->sfmode != omode) { |
1758 | err = -EINVAL; | ||
1756 | goto done; | 1759 | goto done; |
1760 | } | ||
1757 | } else if (pmc->sfmode != omode) { | 1761 | } else if (pmc->sfmode != omode) { |
1758 | /* allow mode switches for empty-set filters */ | 1762 | /* allow mode switches for empty-set filters */ |
1759 | ip_mc_add_src(in_dev, &mreqs->imr_multiaddr, omode, 0, NULL, 0); | 1763 | ip_mc_add_src(in_dev, &mreqs->imr_multiaddr, omode, 0, NULL, 0); |
@@ -1765,7 +1769,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct | |||
1765 | psl = pmc->sflist; | 1769 | psl = pmc->sflist; |
1766 | if (!add) { | 1770 | if (!add) { |
1767 | if (!psl) | 1771 | if (!psl) |
1768 | goto done; | 1772 | goto done; /* err = -EADDRNOTAVAIL */ |
1769 | rv = !0; | 1773 | rv = !0; |
1770 | for (i=0; i<psl->sl_count; i++) { | 1774 | for (i=0; i<psl->sl_count; i++) { |
1771 | rv = memcmp(&psl->sl_addr[i], &mreqs->imr_sourceaddr, | 1775 | rv = memcmp(&psl->sl_addr[i], &mreqs->imr_sourceaddr, |
@@ -1774,7 +1778,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct | |||
1774 | break; | 1778 | break; |
1775 | } | 1779 | } |
1776 | if (rv) /* source not found */ | 1780 | if (rv) /* source not found */ |
1777 | goto done; | 1781 | goto done; /* err = -EADDRNOTAVAIL */ |
1778 | 1782 | ||
1779 | /* special case - (INCLUDE, empty) == LEAVE_GROUP */ | 1783 | /* special case - (INCLUDE, empty) == LEAVE_GROUP */ |
1780 | if (psl->sl_count == 1 && omode == MCAST_INCLUDE) { | 1784 | if (psl->sl_count == 1 && omode == MCAST_INCLUDE) { |
@@ -1870,15 +1874,16 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex) | |||
1870 | err = -ENODEV; | 1874 | err = -ENODEV; |
1871 | goto done; | 1875 | goto done; |
1872 | } | 1876 | } |
1873 | err = -EADDRNOTAVAIL; | ||
1874 | 1877 | ||
1875 | for (pmc=inet->mc_list; pmc; pmc=pmc->next) { | 1878 | for (pmc=inet->mc_list; pmc; pmc=pmc->next) { |
1876 | if (pmc->multi.imr_multiaddr.s_addr == msf->imsf_multiaddr && | 1879 | if (pmc->multi.imr_multiaddr.s_addr == msf->imsf_multiaddr && |
1877 | pmc->multi.imr_ifindex == imr.imr_ifindex) | 1880 | pmc->multi.imr_ifindex == imr.imr_ifindex) |
1878 | break; | 1881 | break; |
1879 | } | 1882 | } |
1880 | if (!pmc) /* must have a prior join */ | 1883 | if (!pmc) { /* must have a prior join */ |
1884 | err = -EINVAL; | ||
1881 | goto done; | 1885 | goto done; |
1886 | } | ||
1882 | if (msf->imsf_numsrc) { | 1887 | if (msf->imsf_numsrc) { |
1883 | newpsl = (struct ip_sf_socklist *)sock_kmalloc(sk, | 1888 | newpsl = (struct ip_sf_socklist *)sock_kmalloc(sk, |
1884 | IP_SFLSIZE(msf->imsf_numsrc), GFP_KERNEL); | 1889 | IP_SFLSIZE(msf->imsf_numsrc), GFP_KERNEL); |
@@ -1907,6 +1912,7 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex) | |||
1907 | 0, NULL, 0); | 1912 | 0, NULL, 0); |
1908 | pmc->sflist = newpsl; | 1913 | pmc->sflist = newpsl; |
1909 | pmc->sfmode = msf->imsf_fmode; | 1914 | pmc->sfmode = msf->imsf_fmode; |
1915 | err = 0; | ||
1910 | done: | 1916 | done: |
1911 | rtnl_shunlock(); | 1917 | rtnl_shunlock(); |
1912 | return err; | 1918 | return err; |