diff options
| author | David L Stevens <dlstevens@us.ibm.com> | 2005-07-08 20:45:16 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2005-07-08 20:45:16 -0400 |
| commit | 917f2f105ea4bbba8604e3ed55233eebda7afe6a (patch) | |
| tree | bbab5de7093cec897f617649dd123946b579c4b7 /net | |
| parent | 8cdaaa15da58806ac3c75d96c40aef9e31445a25 (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>
Diffstat (limited to 'net')
| -rw-r--r-- | net/ipv4/igmp.c | 18 | ||||
| -rw-r--r-- | net/ipv6/mcast.c | 18 |
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; | ||
| 1910 | done: | 1916 | done: |
| 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; | ||
| 547 | done: | 553 | done: |
| 548 | read_unlock_bh(&idev->lock); | 554 | read_unlock_bh(&idev->lock); |
| 549 | in6_dev_put(idev); | 555 | in6_dev_put(idev); |
