Commit fcfa0b09 authored by Al Viro's avatar Al Viro

ipv6: take handling of group_source_req options into a helper

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 2bbf8c1e
...@@ -136,6 +136,41 @@ static bool setsockopt_needs_rtnl(int optname) ...@@ -136,6 +136,41 @@ static bool setsockopt_needs_rtnl(int optname)
return false; return false;
} }
static int do_ipv6_mcast_group_source(struct sock *sk, int optname,
struct group_source_req *greqs)
{
int omode, add;
if (greqs->gsr_group.ss_family != AF_INET6 ||
greqs->gsr_source.ss_family != AF_INET6)
return -EADDRNOTAVAIL;
if (optname == MCAST_BLOCK_SOURCE) {
omode = MCAST_EXCLUDE;
add = 1;
} else if (optname == MCAST_UNBLOCK_SOURCE) {
omode = MCAST_EXCLUDE;
add = 0;
} else if (optname == MCAST_JOIN_SOURCE_GROUP) {
struct sockaddr_in6 *psin6;
int retv;
psin6 = (struct sockaddr_in6 *)&greqs->gsr_group;
retv = ipv6_sock_mc_join_ssm(sk, greqs->gsr_interface,
&psin6->sin6_addr,
MCAST_INCLUDE);
/* prior join w/ different source is ok */
if (retv && retv != -EADDRINUSE)
return retv;
omode = MCAST_INCLUDE;
add = 1;
} else /* MCAST_LEAVE_SOURCE_GROUP */ {
omode = MCAST_INCLUDE;
add = 0;
}
return ip6_mc_source(add, omode, sk, greqs);
}
static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
char __user *optval, unsigned int optlen) char __user *optval, unsigned int optlen)
{ {
...@@ -715,7 +750,6 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, ...@@ -715,7 +750,6 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
case MCAST_UNBLOCK_SOURCE: case MCAST_UNBLOCK_SOURCE:
{ {
struct group_source_req greqs; struct group_source_req greqs;
int omode, add;
if (optlen < sizeof(struct group_source_req)) if (optlen < sizeof(struct group_source_req))
goto e_inval; goto e_inval;
...@@ -723,34 +757,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, ...@@ -723,34 +757,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
retv = -EFAULT; retv = -EFAULT;
break; break;
} }
if (greqs.gsr_group.ss_family != AF_INET6 || retv = do_ipv6_mcast_group_source(sk, optname, &greqs);
greqs.gsr_source.ss_family != AF_INET6) {
retv = -EADDRNOTAVAIL;
break;
}
if (optname == MCAST_BLOCK_SOURCE) {
omode = MCAST_EXCLUDE;
add = 1;
} else if (optname == MCAST_UNBLOCK_SOURCE) {
omode = MCAST_EXCLUDE;
add = 0;
} else if (optname == MCAST_JOIN_SOURCE_GROUP) {
struct sockaddr_in6 *psin6;
psin6 = (struct sockaddr_in6 *)&greqs.gsr_group;
retv = ipv6_sock_mc_join_ssm(sk, greqs.gsr_interface,
&psin6->sin6_addr,
MCAST_INCLUDE);
/* prior join w/ different source is ok */
if (retv && retv != -EADDRINUSE)
break;
omode = MCAST_INCLUDE;
add = 1;
} else /* MCAST_LEAVE_SOURCE_GROUP */ {
omode = MCAST_INCLUDE;
add = 0;
}
retv = ip6_mc_source(add, omode, sk, &greqs);
break; break;
} }
case MCAST_MSFILTER: case MCAST_MSFILTER:
......
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