[IPV4]: (INCLUDE,empty)/leave-group equivalence for full-state MSF APIs & errno fix
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) Signed-off-by: David L Stevens <dlstevens@us.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
917f2f105e
commit
9951f036fe
2 changed files with 19 additions and 2 deletions
|
@ -1849,13 +1849,14 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
|
||||||
|
|
||||||
int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex)
|
int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex)
|
||||||
{
|
{
|
||||||
int err;
|
int err = 0;
|
||||||
struct ip_mreqn imr;
|
struct ip_mreqn imr;
|
||||||
u32 addr = msf->imsf_multiaddr;
|
u32 addr = msf->imsf_multiaddr;
|
||||||
struct ip_mc_socklist *pmc;
|
struct ip_mc_socklist *pmc;
|
||||||
struct in_device *in_dev;
|
struct in_device *in_dev;
|
||||||
struct inet_sock *inet = inet_sk(sk);
|
struct inet_sock *inet = inet_sk(sk);
|
||||||
struct ip_sf_socklist *newpsl, *psl;
|
struct ip_sf_socklist *newpsl, *psl;
|
||||||
|
int leavegroup = 0;
|
||||||
|
|
||||||
if (!MULTICAST(addr))
|
if (!MULTICAST(addr))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -1875,6 +1876,12 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex)
|
||||||
goto done;
|
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) {
|
for (pmc=inet->mc_list; pmc; pmc=pmc->next) {
|
||||||
if (pmc->multi.imr_multiaddr.s_addr == msf->imsf_multiaddr &&
|
if (pmc->multi.imr_multiaddr.s_addr == msf->imsf_multiaddr &&
|
||||||
pmc->multi.imr_ifindex == imr.imr_ifindex)
|
pmc->multi.imr_ifindex == imr.imr_ifindex)
|
||||||
|
@ -1915,6 +1922,8 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex)
|
||||||
err = 0;
|
err = 0;
|
||||||
done:
|
done:
|
||||||
rtnl_shunlock();
|
rtnl_shunlock();
|
||||||
|
if (leavegroup)
|
||||||
|
err = ip_mc_leave_group(sk, &imr);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -281,7 +281,7 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr)
|
||||||
}
|
}
|
||||||
write_unlock_bh(&ipv6_sk_mc_lock);
|
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)
|
static struct inet6_dev *ip6_mc_find_dev(struct in6_addr *group, int ifindex)
|
||||||
|
@ -492,6 +492,7 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf)
|
||||||
struct inet6_dev *idev;
|
struct inet6_dev *idev;
|
||||||
struct ipv6_pinfo *inet6 = inet6_sk(sk);
|
struct ipv6_pinfo *inet6 = inet6_sk(sk);
|
||||||
struct ip6_sf_socklist *newpsl, *psl;
|
struct ip6_sf_socklist *newpsl, *psl;
|
||||||
|
int leavegroup = 0;
|
||||||
int i, err;
|
int i, err;
|
||||||
|
|
||||||
group = &((struct sockaddr_in6 *)&gsf->gf_group)->sin6_addr;
|
group = &((struct sockaddr_in6 *)&gsf->gf_group)->sin6_addr;
|
||||||
|
@ -508,6 +509,11 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
dev = idev->dev;
|
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) {
|
for (pmc=inet6->ipv6_mc_list; pmc; pmc=pmc->next) {
|
||||||
if (pmc->ifindex != gsf->gf_interface)
|
if (pmc->ifindex != gsf->gf_interface)
|
||||||
continue;
|
continue;
|
||||||
|
@ -554,6 +560,8 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf)
|
||||||
read_unlock_bh(&idev->lock);
|
read_unlock_bh(&idev->lock);
|
||||||
in6_dev_put(idev);
|
in6_dev_put(idev);
|
||||||
dev_put(dev);
|
dev_put(dev);
|
||||||
|
if (leavegroup)
|
||||||
|
err = ipv6_sock_mc_drop(sk, gsf->gf_interface, group);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue