aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid L Stevens <dlstevens@us.ibm.com>2005-07-08 20:45:16 -0400
committerDavid S. Miller <davem@davemloft.net>2005-07-08 20:45:16 -0400
commit917f2f105ea4bbba8604e3ed55233eebda7afe6a (patch)
treebbab5de7093cec897f617649dd123946b579c4b7
parent8cdaaa15da58806ac3c75d96c40aef9e31445a25 (diff)
[IPV4]: multicast API "join" issues
1) In the full-state API when imsf_numsrc == 0 errno should be "0", but returns EADDRNOTAVAIL 2) An illegal filter mode change errno should be EINVAL, but returns EADDRNOTAVAIL 3) Trying to do an any-source option without IP_ADD_MEMBERSHIP errno should be EINVAL, but returns EADDRNOTAVAIL 4) Adds comments for the less obvious error return values Signed-off-by: David L Stevens <dlstevens@us.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/ipv4/igmp.c18
-rw-r--r--net/ipv6/mcast.c18
2 files changed, 24 insertions, 12 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;
1910done: 1916done:
1911 rtnl_shunlock(); 1917 rtnl_shunlock();
1912 return err; 1918 return err;
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 562fcd14fdea..9db4581d0d79 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -386,12 +386,16 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
386 if (ipv6_addr_equal(&pmc->addr, group)) 386 if (ipv6_addr_equal(&pmc->addr, group))
387 break; 387 break;
388 } 388 }
389 if (!pmc) /* must have a prior join */ 389 if (!pmc) { /* must have a prior join */
390 err = -EINVAL;
390 goto done; 391 goto done;
392 }
391 /* if a source filter was set, must be the same mode as before */ 393 /* if a source filter was set, must be the same mode as before */
392 if (pmc->sflist) { 394 if (pmc->sflist) {
393 if (pmc->sfmode != omode) 395 if (pmc->sfmode != omode) {
396 err = -EINVAL;
394 goto done; 397 goto done;
398 }
395 } else if (pmc->sfmode != omode) { 399 } else if (pmc->sfmode != omode) {
396 /* allow mode switches for empty-set filters */ 400 /* allow mode switches for empty-set filters */
397 ip6_mc_add_src(idev, group, omode, 0, NULL, 0); 401 ip6_mc_add_src(idev, group, omode, 0, NULL, 0);
@@ -402,7 +406,7 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
402 psl = pmc->sflist; 406 psl = pmc->sflist;
403 if (!add) { 407 if (!add) {
404 if (!psl) 408 if (!psl)
405 goto done; 409 goto done; /* err = -EADDRNOTAVAIL */
406 rv = !0; 410 rv = !0;
407 for (i=0; i<psl->sl_count; i++) { 411 for (i=0; i<psl->sl_count; i++) {
408 rv = memcmp(&psl->sl_addr[i], source, 412 rv = memcmp(&psl->sl_addr[i], source,
@@ -411,7 +415,7 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
411 break; 415 break;
412 } 416 }
413 if (rv) /* source not found */ 417 if (rv) /* source not found */
414 goto done; 418 goto done; /* err = -EADDRNOTAVAIL */
415 419
416 /* special case - (INCLUDE, empty) == LEAVE_GROUP */ 420 /* special case - (INCLUDE, empty) == LEAVE_GROUP */
417 if (psl->sl_count == 1 && omode == MCAST_INCLUDE) { 421 if (psl->sl_count == 1 && omode == MCAST_INCLUDE) {
@@ -503,7 +507,6 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf)
503 if (!idev) 507 if (!idev)
504 return -ENODEV; 508 return -ENODEV;
505 dev = idev->dev; 509 dev = idev->dev;
506 err = -EADDRNOTAVAIL;
507 510
508 for (pmc=inet6->ipv6_mc_list; pmc; pmc=pmc->next) { 511 for (pmc=inet6->ipv6_mc_list; pmc; pmc=pmc->next) {
509 if (pmc->ifindex != gsf->gf_interface) 512 if (pmc->ifindex != gsf->gf_interface)
@@ -511,8 +514,10 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf)
511 if (ipv6_addr_equal(&pmc->addr, group)) 514 if (ipv6_addr_equal(&pmc->addr, group))
512 break; 515 break;
513 } 516 }
514 if (!pmc) /* must have a prior join */ 517 if (!pmc) { /* must have a prior join */
518 err = -EINVAL;
515 goto done; 519 goto done;
520 }
516 if (gsf->gf_numsrc) { 521 if (gsf->gf_numsrc) {
517 newpsl = (struct ip6_sf_socklist *)sock_kmalloc(sk, 522 newpsl = (struct ip6_sf_socklist *)sock_kmalloc(sk,
518 IP6_SFLSIZE(gsf->gf_numsrc), GFP_ATOMIC); 523 IP6_SFLSIZE(gsf->gf_numsrc), GFP_ATOMIC);
@@ -544,6 +549,7 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf)
544 (void) ip6_mc_del_src(idev, group, pmc->sfmode, 0, NULL, 0); 549 (void) ip6_mc_del_src(idev, group, pmc->sfmode, 0, NULL, 0);
545 pmc->sflist = newpsl; 550 pmc->sflist = newpsl;
546 pmc->sfmode = gsf->gf_fmode; 551 pmc->sfmode = gsf->gf_fmode;
552 err = 0;
547done: 553done:
548 read_unlock_bh(&idev->lock); 554 read_unlock_bh(&idev->lock);
549 in6_dev_put(idev); 555 in6_dev_put(idev);