tree bbab5de7093cec897f617649dd123946b579c4b7
parent 8cdaaa15da58806ac3c75d96c40aef9e31445a25
author David L Stevens <[EMAIL PROTECTED]> Sat, 09 Jul 2005 07:45:16 -0700
committer David S. Miller <[EMAIL PROTECTED]> Sat, 09 Jul 2005 07:45:16 -0700

[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 <[EMAIL PROTECTED]>
Signed-off-by: David S. Miller <[EMAIL PROTECTED]>

 net/ipv4/igmp.c  |   18 ++++++++++++------
 net/ipv6/mcast.c |   18 ++++++++++++------
 2 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -1748,12 +1748,16 @@ int ip_mc_source(int add, int omode, str
                    && pmc->multi.imr_ifindex == imr.imr_ifindex)
                        break;
        }
-       if (!pmc)               /* must have a prior join */
+       if (!pmc) {             /* must have a prior join */
+               err = -EINVAL;
                goto done;
+       }
        /* if a source filter was set, must be the same mode as before */
        if (pmc->sflist) {
-               if (pmc->sfmode != omode)
+               if (pmc->sfmode != omode) {
+                       err = -EINVAL;
                        goto done;
+               }
        } else if (pmc->sfmode != omode) {
                /* allow mode switches for empty-set filters */
                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, str
        psl = pmc->sflist;
        if (!add) {
                if (!psl)
-                       goto done;
+                       goto done;      /* err = -EADDRNOTAVAIL */
                rv = !0;
                for (i=0; i<psl->sl_count; i++) {
                        rv = memcmp(&psl->sl_addr[i], &mreqs->imr_sourceaddr,
@@ -1774,7 +1778,7 @@ int ip_mc_source(int add, int omode, str
                                break;
                }
                if (rv)         /* source not found */
-                       goto done;
+                       goto done;      /* err = -EADDRNOTAVAIL */
 
                /* special case - (INCLUDE, empty) == LEAVE_GROUP */
                if (psl->sl_count == 1 && omode == MCAST_INCLUDE) {
@@ -1870,15 +1874,16 @@ int ip_mc_msfilter(struct sock *sk, stru
                err = -ENODEV;
                goto done;
        }
-       err = -EADDRNOTAVAIL;
 
        for (pmc=inet->mc_list; pmc; pmc=pmc->next) {
                if (pmc->multi.imr_multiaddr.s_addr == msf->imsf_multiaddr &&
                    pmc->multi.imr_ifindex == imr.imr_ifindex)
                        break;
        }
-       if (!pmc)               /* must have a prior join */
+       if (!pmc) {             /* must have a prior join */
+               err = -EINVAL;
                goto done;
+       }
        if (msf->imsf_numsrc) {
                newpsl = (struct ip_sf_socklist *)sock_kmalloc(sk,
                                IP_SFLSIZE(msf->imsf_numsrc), GFP_KERNEL);
@@ -1907,6 +1912,7 @@ int ip_mc_msfilter(struct sock *sk, stru
                        0, NULL, 0);
        pmc->sflist = newpsl;
        pmc->sfmode = msf->imsf_fmode;
+       err = 0;
 done:
        rtnl_shunlock();
        return err;
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -386,12 +386,16 @@ int ip6_mc_source(int add, int omode, st
                if (ipv6_addr_equal(&pmc->addr, group))
                        break;
        }
-       if (!pmc)               /* must have a prior join */
+       if (!pmc) {             /* must have a prior join */
+               err = -EINVAL;
                goto done;
+       }
        /* if a source filter was set, must be the same mode as before */
        if (pmc->sflist) {
-               if (pmc->sfmode != omode)
+               if (pmc->sfmode != omode) {
+                       err = -EINVAL;
                        goto done;
+               }
        } else if (pmc->sfmode != omode) {
                /* allow mode switches for empty-set filters */
                ip6_mc_add_src(idev, group, omode, 0, NULL, 0);
@@ -402,7 +406,7 @@ int ip6_mc_source(int add, int omode, st
        psl = pmc->sflist;
        if (!add) {
                if (!psl)
-                       goto done;
+                       goto done;      /* err = -EADDRNOTAVAIL */
                rv = !0;
                for (i=0; i<psl->sl_count; i++) {
                        rv = memcmp(&psl->sl_addr[i], source,
@@ -411,7 +415,7 @@ int ip6_mc_source(int add, int omode, st
                                break;
                }
                if (rv)         /* source not found */
-                       goto done;
+                       goto done;      /* err = -EADDRNOTAVAIL */
 
                /* special case - (INCLUDE, empty) == LEAVE_GROUP */
                if (psl->sl_count == 1 && omode == MCAST_INCLUDE) {
@@ -503,7 +507,6 @@ int ip6_mc_msfilter(struct sock *sk, str
        if (!idev)
                return -ENODEV;
        dev = idev->dev;
-       err = -EADDRNOTAVAIL;
 
        for (pmc=inet6->ipv6_mc_list; pmc; pmc=pmc->next) {
                if (pmc->ifindex != gsf->gf_interface)
@@ -511,8 +514,10 @@ int ip6_mc_msfilter(struct sock *sk, str
                if (ipv6_addr_equal(&pmc->addr, group))
                        break;
        }
-       if (!pmc)               /* must have a prior join */
+       if (!pmc) {             /* must have a prior join */
+               err = -EINVAL;
                goto done;
+       }
        if (gsf->gf_numsrc) {
                newpsl = (struct ip6_sf_socklist *)sock_kmalloc(sk,
                                IP6_SFLSIZE(gsf->gf_numsrc), GFP_ATOMIC);
@@ -544,6 +549,7 @@ int ip6_mc_msfilter(struct sock *sk, str
                (void) ip6_mc_del_src(idev, group, pmc->sfmode, 0, NULL, 0);
        pmc->sflist = newpsl;
        pmc->sfmode = gsf->gf_fmode;
+       err = 0;
 done:
        read_unlock_bh(&idev->lock);
        in6_dev_put(idev);
-
To unsubscribe from this list: send the line "unsubscribe bk-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to