Commit b212c322 authored by Al Viro's avatar Al Viro

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: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent fcfa0b09
...@@ -1322,8 +1322,27 @@ int compat_ip_setsockopt(struct sock *sk, int level, int optname, ...@@ -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, ...@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment