handle the group_source_req options directly
Native ->setsockopt() handling of these options (MCAST_..._SOURCE_GROUP
and MCAST_{,UN}BLOCK_SOURCE) consists of copyin + call of a helper that
does the actual work. The only change needed for ->compat_setsockopt()
is a slightly different copyin - the helpers can be reused as-is.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
@@ -1322,8 +1322,27 @@ int compat_ip_setsockopt(struct sock *sk, int level, int optname,
|
|||||||
case MCAST_LEAVE_SOURCE_GROUP:
|
case MCAST_LEAVE_SOURCE_GROUP:
|
||||||
case MCAST_BLOCK_SOURCE:
|
case MCAST_BLOCK_SOURCE:
|
||||||
case MCAST_UNBLOCK_SOURCE:
|
case MCAST_UNBLOCK_SOURCE:
|
||||||
return compat_mc_setsockopt(sk, level, optname, optval, optlen,
|
{
|
||||||
ip_setsockopt);
|
struct compat_group_source_req __user *gsr32 = (void __user *)optval;
|
||||||
|
struct group_source_req greqs;
|
||||||
|
|
||||||
|
if (optlen != sizeof(struct compat_group_source_req))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (get_user(greqs.gsr_interface, &gsr32->gsr_interface) ||
|
||||||
|
copy_from_user(&greqs.gsr_group, &gsr32->gsr_group,
|
||||||
|
sizeof(greqs.gsr_group)) ||
|
||||||
|
copy_from_user(&greqs.gsr_source, &gsr32->gsr_source,
|
||||||
|
sizeof(greqs.gsr_source)))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
rtnl_lock();
|
||||||
|
lock_sock(sk);
|
||||||
|
err = do_mcast_group_source(sk, optname, &greqs);
|
||||||
|
release_sock(sk);
|
||||||
|
rtnl_unlock();
|
||||||
|
return err;
|
||||||
|
}
|
||||||
case MCAST_MSFILTER:
|
case MCAST_MSFILTER:
|
||||||
{
|
{
|
||||||
const int size0 = offsetof(struct compat_group_filter, gf_slist);
|
const int size0 = offsetof(struct compat_group_filter, gf_slist);
|
||||||
|
|||||||
@@ -1015,8 +1015,27 @@ int compat_ipv6_setsockopt(struct sock *sk, int level, int optname,
|
|||||||
case MCAST_LEAVE_SOURCE_GROUP:
|
case MCAST_LEAVE_SOURCE_GROUP:
|
||||||
case MCAST_BLOCK_SOURCE:
|
case MCAST_BLOCK_SOURCE:
|
||||||
case MCAST_UNBLOCK_SOURCE:
|
case MCAST_UNBLOCK_SOURCE:
|
||||||
return compat_mc_setsockopt(sk, level, optname, optval, optlen,
|
{
|
||||||
ipv6_setsockopt);
|
struct compat_group_source_req __user *gsr32 = (void __user *)optval;
|
||||||
|
struct group_source_req greqs;
|
||||||
|
|
||||||
|
if (optlen < sizeof(struct compat_group_source_req))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (get_user(greqs.gsr_interface, &gsr32->gsr_interface) ||
|
||||||
|
copy_from_user(&greqs.gsr_group, &gsr32->gsr_group,
|
||||||
|
sizeof(greqs.gsr_group)) ||
|
||||||
|
copy_from_user(&greqs.gsr_source, &gsr32->gsr_source,
|
||||||
|
sizeof(greqs.gsr_source)))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
rtnl_lock();
|
||||||
|
lock_sock(sk);
|
||||||
|
err = do_ipv6_mcast_group_source(sk, optname, &greqs);
|
||||||
|
release_sock(sk);
|
||||||
|
rtnl_unlock();
|
||||||
|
return err;
|
||||||
|
}
|
||||||
case MCAST_MSFILTER:
|
case MCAST_MSFILTER:
|
||||||
{
|
{
|
||||||
const int size0 = offsetof(struct compat_group_filter, gf_slist);
|
const int size0 = offsetof(struct compat_group_filter, gf_slist);
|
||||||
|
|||||||
Reference in New Issue
Block a user