net/ipv4: factor out mcast join/leave setsockopt helpers
Factor out one helper each for setting the native and compat version of the MCAST_MSFILTER option. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
d62c38f6a1
commit
02caad7cc0
@@ -806,6 +806,60 @@ out_free_gsf:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int ip_mcast_join_leave(struct sock *sk, int optname,
|
||||||
|
void __user *optval, int optlen)
|
||||||
|
{
|
||||||
|
struct ip_mreqn mreq = { };
|
||||||
|
struct sockaddr_in *psin;
|
||||||
|
struct group_req greq;
|
||||||
|
|
||||||
|
if (optlen < sizeof(struct group_req))
|
||||||
|
return -EINVAL;
|
||||||
|
if (copy_from_user(&greq, optval, sizeof(greq)))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
psin = (struct sockaddr_in *)&greq.gr_group;
|
||||||
|
if (psin->sin_family != AF_INET)
|
||||||
|
return -EINVAL;
|
||||||
|
mreq.imr_multiaddr = psin->sin_addr;
|
||||||
|
mreq.imr_ifindex = greq.gr_interface;
|
||||||
|
if (optname == MCAST_JOIN_GROUP)
|
||||||
|
return ip_mc_join_group(sk, &mreq);
|
||||||
|
return ip_mc_leave_group(sk, &mreq);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_COMPAT
|
||||||
|
static int compat_ip_mcast_join_leave(struct sock *sk, int optname,
|
||||||
|
void __user *optval, int optlen)
|
||||||
|
{
|
||||||
|
struct compat_group_req greq;
|
||||||
|
struct ip_mreqn mreq = { };
|
||||||
|
struct sockaddr_in *psin;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (optlen < sizeof(struct compat_group_req))
|
||||||
|
return -EINVAL;
|
||||||
|
if (copy_from_user(&greq, optval, sizeof(greq)))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
psin = (struct sockaddr_in *)&greq.gr_group;
|
||||||
|
if (psin->sin_family != AF_INET)
|
||||||
|
return -EINVAL;
|
||||||
|
mreq.imr_multiaddr = psin->sin_addr;
|
||||||
|
mreq.imr_ifindex = greq.gr_interface;
|
||||||
|
|
||||||
|
rtnl_lock();
|
||||||
|
lock_sock(sk);
|
||||||
|
if (optname == MCAST_JOIN_GROUP)
|
||||||
|
err = ip_mc_join_group(sk, &mreq);
|
||||||
|
else
|
||||||
|
err = ip_mc_leave_group(sk, &mreq);
|
||||||
|
release_sock(sk);
|
||||||
|
rtnl_unlock();
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int do_ip_setsockopt(struct sock *sk, int level,
|
static int do_ip_setsockopt(struct sock *sk, int level,
|
||||||
int optname, char __user *optval, unsigned int optlen)
|
int optname, char __user *optval, unsigned int optlen)
|
||||||
{
|
{
|
||||||
@@ -1211,29 +1265,8 @@ static int do_ip_setsockopt(struct sock *sk, int level,
|
|||||||
}
|
}
|
||||||
case MCAST_JOIN_GROUP:
|
case MCAST_JOIN_GROUP:
|
||||||
case MCAST_LEAVE_GROUP:
|
case MCAST_LEAVE_GROUP:
|
||||||
{
|
err = ip_mcast_join_leave(sk, optname, optval, optlen);
|
||||||
struct group_req greq;
|
|
||||||
struct sockaddr_in *psin;
|
|
||||||
struct ip_mreqn mreq;
|
|
||||||
|
|
||||||
if (optlen < sizeof(struct group_req))
|
|
||||||
goto e_inval;
|
|
||||||
err = -EFAULT;
|
|
||||||
if (copy_from_user(&greq, optval, sizeof(greq)))
|
|
||||||
break;
|
|
||||||
psin = (struct sockaddr_in *)&greq.gr_group;
|
|
||||||
if (psin->sin_family != AF_INET)
|
|
||||||
goto e_inval;
|
|
||||||
memset(&mreq, 0, sizeof(mreq));
|
|
||||||
mreq.imr_multiaddr = psin->sin_addr;
|
|
||||||
mreq.imr_ifindex = greq.gr_interface;
|
|
||||||
|
|
||||||
if (optname == MCAST_JOIN_GROUP)
|
|
||||||
err = ip_mc_join_group(sk, &mreq);
|
|
||||||
else
|
|
||||||
err = ip_mc_leave_group(sk, &mreq);
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case MCAST_JOIN_SOURCE_GROUP:
|
case MCAST_JOIN_SOURCE_GROUP:
|
||||||
case MCAST_LEAVE_SOURCE_GROUP:
|
case MCAST_LEAVE_SOURCE_GROUP:
|
||||||
case MCAST_BLOCK_SOURCE:
|
case MCAST_BLOCK_SOURCE:
|
||||||
@@ -1389,37 +1422,7 @@ int compat_ip_setsockopt(struct sock *sk, int level, int optname,
|
|||||||
switch (optname) {
|
switch (optname) {
|
||||||
case MCAST_JOIN_GROUP:
|
case MCAST_JOIN_GROUP:
|
||||||
case MCAST_LEAVE_GROUP:
|
case MCAST_LEAVE_GROUP:
|
||||||
{
|
return compat_ip_mcast_join_leave(sk, optname, optval, optlen);
|
||||||
struct compat_group_req __user *gr32 = (void __user *)optval;
|
|
||||||
struct group_req greq;
|
|
||||||
struct sockaddr_in *psin = (struct sockaddr_in *)&greq.gr_group;
|
|
||||||
struct ip_mreqn mreq;
|
|
||||||
|
|
||||||
if (optlen < sizeof(struct compat_group_req))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (get_user(greq.gr_interface, &gr32->gr_interface) ||
|
|
||||||
copy_from_user(&greq.gr_group, &gr32->gr_group,
|
|
||||||
sizeof(greq.gr_group)))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
if (psin->sin_family != AF_INET)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
memset(&mreq, 0, sizeof(mreq));
|
|
||||||
mreq.imr_multiaddr = psin->sin_addr;
|
|
||||||
mreq.imr_ifindex = greq.gr_interface;
|
|
||||||
|
|
||||||
rtnl_lock();
|
|
||||||
lock_sock(sk);
|
|
||||||
if (optname == MCAST_JOIN_GROUP)
|
|
||||||
err = ip_mc_join_group(sk, &mreq);
|
|
||||||
else
|
|
||||||
err = ip_mc_leave_group(sk, &mreq);
|
|
||||||
release_sock(sk);
|
|
||||||
rtnl_unlock();
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
case MCAST_JOIN_SOURCE_GROUP:
|
case MCAST_JOIN_SOURCE_GROUP:
|
||||||
case MCAST_LEAVE_SOURCE_GROUP:
|
case MCAST_LEAVE_SOURCE_GROUP:
|
||||||
case MCAST_BLOCK_SOURCE:
|
case MCAST_BLOCK_SOURCE:
|
||||||
|
Reference in New Issue
Block a user