This patch:
1) Adds (INCLUDE, empty)/leave-group equivalence to the full-state 
multicast
        source filter APIs (IPv4 and IPv6)
2) Fixes an incorrect errno in the IPv6 leave-group (ENOENT should be
        EADDRNOTAVAIL)
[in-line for viewing, attached for applying]

Signed-off-by: David L Stevens <[EMAIL PROTECTED]>
diff -ruNp linux-2.6.12.1v1mc-3/net/ipv4/igmp.c 
linux-2.6.12.1v1mc-4/net/ipv4/igmp.c
--- linux-2.6.12.1v1mc-3/net/ipv4/igmp.c        2005-07-01 
16:50:06.000000000 -0700
+++ linux-2.6.12.1v1mc-4/net/ipv4/igmp.c        2005-07-05 
15:32:21.000000000 -0700
@@ -1849,13 +1849,14 @@ done:
 
 int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex)
 {
-       int err;
+       int err = 0;
        struct ip_mreqn imr;
        u32 addr = msf->imsf_multiaddr;
        struct ip_mc_socklist *pmc;
        struct in_device *in_dev;
        struct inet_sock *inet = inet_sk(sk);
        struct ip_sf_socklist *newpsl, *psl;
+       int leavegroup = 0;
 
        if (!MULTICAST(addr))
                return -EINVAL;
@@ -1875,6 +1876,12 @@ int ip_mc_msfilter(struct sock *sk, stru
                goto done;
        }
 
+       /* special case - (INCLUDE, empty) == LEAVE_GROUP */
+       if (msf->imsf_fmode == MCAST_INCLUDE && msf->imsf_numsrc == 0) {
+               leavegroup = 1;
+               goto done;
+       }
+
        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)
@@ -1915,6 +1922,8 @@ int ip_mc_msfilter(struct sock *sk, stru
        err = 0;
 done:
        rtnl_shunlock();
+       if (leavegroup)
+               err = ip_mc_leave_group(sk, &imr);
        return err;
 }
 
diff -ruNp linux-2.6.12.1v1mc-3/net/ipv6/mcast.c 
linux-2.6.12.1v1mc-4/net/ipv6/mcast.c
--- linux-2.6.12.1v1mc-3/net/ipv6/mcast.c       2005-07-01 
16:50:48.000000000 -0700
+++ linux-2.6.12.1v1mc-4/net/ipv6/mcast.c       2005-07-05 
15:29:36.000000000 -0700
@@ -271,7 +271,7 @@ int ipv6_sock_mc_drop(struct sock *sk, i
        }
        write_unlock_bh(&ipv6_sk_mc_lock);
 
-       return -ENOENT;
+       return -EADDRNOTAVAIL;
 }
 
 static struct inet6_dev *ip6_mc_find_dev(struct in6_addr *group, int 
ifindex)
@@ -471,6 +471,7 @@ int ip6_mc_msfilter(struct sock *sk, str
        struct inet6_dev *idev;
        struct ipv6_pinfo *inet6 = inet6_sk(sk);
        struct ip6_sf_socklist *newpsl, *psl;
+       int leavegroup = 0;
        int i, err;
 
        group = &((struct sockaddr_in6 *)&gsf->gf_group)->sin6_addr;
@@ -487,6 +488,11 @@ int ip6_mc_msfilter(struct sock *sk, str
                return -ENODEV;
        dev = idev->dev;
 
+       if (gsf->gf_fmode == MCAST_INCLUDE && gsf->gf_numsrc == 0) {
+               leavegroup = 1;
+               goto done;
+       }
+
        for (pmc=inet6->ipv6_mc_list; pmc; pmc=pmc->next) {
                if (pmc->ifindex != gsf->gf_interface)
                        continue;
@@ -533,6 +539,8 @@ done:
        read_unlock_bh(&idev->lock);
        in6_dev_put(idev);
        dev_put(dev);
+       if (leavegroup)
+               err = ipv6_sock_mc_drop(sk, gsf->gf_interface, group);
        return err;
 }
 

Attachment: v1mc-4.patch
Description: Binary data

Reply via email to