Commit fcfa0b09 authored by Al Viro's avatar Al Viro
Browse files

ipv6: take handling of group_source_req options into a helper



Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 2bbf8c1e
Loading
Loading
Loading
Loading
+36 −29
Original line number Diff line number Diff line
@@ -136,6 +136,41 @@ static bool setsockopt_needs_rtnl(int optname)
	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,
		    char __user *optval, unsigned int optlen)
{
@@ -715,7 +750,6 @@ done:
	case MCAST_UNBLOCK_SOURCE:
	{
		struct group_source_req greqs;
		int omode, add;

		if (optlen < sizeof(struct group_source_req))
			goto e_inval;
@@ -723,34 +757,7 @@ done:
			retv = -EFAULT;
			break;
		}
		if (greqs.gsr_group.ss_family != AF_INET6 ||
		    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);
		retv = do_ipv6_mcast_group_source(sk, optname, &greqs);
		break;
	}
	case MCAST_MSFILTER: