Skip to content

Commit

Permalink
net/ipv4: factor out mcast join/leave setsockopt helpers
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Christoph Hellwig authored and David S. Miller committed Jul 20, 2020
1 parent d62c38f commit 02caad7
Showing 1 changed file with 56 additions and 53 deletions.
109 changes: 56 additions & 53 deletions net/ipv4/ip_sockglue.c
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,60 @@ static int compat_ip_set_mcast_msfilter(struct sock *sk, void __user *optval,
}
#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,
int optname, char __user *optval, unsigned int optlen)
{
Expand Down Expand Up @@ -1211,29 +1265,8 @@ static int do_ip_setsockopt(struct sock *sk, int level,
}
case MCAST_JOIN_GROUP:
case MCAST_LEAVE_GROUP:
{
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);
err = ip_mcast_join_leave(sk, optname, optval, optlen);
break;
}
case MCAST_JOIN_SOURCE_GROUP:
case MCAST_LEAVE_SOURCE_GROUP:
case MCAST_BLOCK_SOURCE:
Expand Down Expand Up @@ -1389,37 +1422,7 @@ int compat_ip_setsockopt(struct sock *sk, int level, int optname,
switch (optname) {
case MCAST_JOIN_GROUP:
case MCAST_LEAVE_GROUP:
{
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;
}
return compat_ip_mcast_join_leave(sk, optname, optval, optlen);
case MCAST_JOIN_SOURCE_GROUP:
case MCAST_LEAVE_SOURCE_GROUP:
case MCAST_BLOCK_SOURCE:
Expand Down

0 comments on commit 02caad7

Please sign in to comment.