Beispiel #1
0
static int
linux_socket(struct linux_socket_args *args, int *res)
{
	struct linux_socket_args linux_args;
	struct sockopt sopt;
	int error, domain, optval;

	error = copyin(args, &linux_args, sizeof(linux_args));
	if (error)
		return (error);

	domain = linux_to_bsd_domain(linux_args.domain);
	if (domain == -1)
		return (EINVAL);

	error = kern_socket(domain, linux_args.type, linux_args.protocol, res);

	/* Copy back the return value from socket() */
	if (error == 0 && linux_args.type == SOCK_RAW &&
	    (linux_args.protocol == IPPROTO_RAW || linux_args.protocol == 0) &&
	    linux_args.domain == AF_INET) {
		/* It's a raw IP socket: set the IP_HDRINCL option. */
		optval = 1;
		sopt.sopt_dir = SOPT_SET;
		sopt.sopt_level = IPPROTO_IP;
		sopt.sopt_name = IP_HDRINCL;
		sopt.sopt_val = &optval;
		sopt.sopt_valsize = sizeof(optval);
		sopt.sopt_td = NULL;

		/* We ignore any error returned by setsockopt() */
		kern_setsockopt(*res, &sopt);
	}

	return (error);
}
Beispiel #2
0
static int
linux_socket(struct thread *td, struct linux_socket_args *args)
{
	struct socket_args /* {
		int domain;
		int type;
		int protocol;
	} */ bsd_args;
	int retval_socket, socket_flags;

	bsd_args.protocol = args->protocol;
	socket_flags = args->type & ~LINUX_SOCK_TYPE_MASK;
	if (socket_flags & ~(LINUX_SOCK_CLOEXEC | LINUX_SOCK_NONBLOCK))
		return (EINVAL);
	bsd_args.type = args->type & LINUX_SOCK_TYPE_MASK;
	if (bsd_args.type < 0 || bsd_args.type > LINUX_SOCK_MAX)
		return (EINVAL);
	bsd_args.domain = linux_to_bsd_domain(args->domain);
	if (bsd_args.domain == -1)
		return (EAFNOSUPPORT);

	retval_socket = socket(td, &bsd_args);
	if (retval_socket)
		return (retval_socket);

	retval_socket = linux_set_socket_flags(td, td->td_retval[0],
	    socket_flags);
	if (retval_socket) {
		(void)kern_close(td, td->td_retval[0]);
		goto out;
	}

	if (bsd_args.type == SOCK_RAW
	    && (bsd_args.protocol == IPPROTO_RAW || bsd_args.protocol == 0)
	    && bsd_args.domain == PF_INET) {
		/* It's a raw IP socket: set the IP_HDRINCL option. */
		int hdrincl;

		hdrincl = 1;
		/* We ignore any error returned by kern_setsockopt() */
		kern_setsockopt(td, td->td_retval[0], IPPROTO_IP, IP_HDRINCL,
		    &hdrincl, UIO_SYSSPACE, sizeof(hdrincl));
	}
#ifdef INET6
	/*
	 * Linux AF_INET6 socket has IPV6_V6ONLY setsockopt set to 0 by default
	 * and some apps depend on this. So, set V6ONLY to 0 for Linux apps.
	 * For simplicity we do this unconditionally of the net.inet6.ip6.v6only
	 * sysctl value.
	 */
	if (bsd_args.domain == PF_INET6) {
		int v6only;

		v6only = 0;
		/* We ignore any error returned by setsockopt() */
		kern_setsockopt(td, td->td_retval[0], IPPROTO_IPV6, IPV6_V6ONLY,
		    &v6only, UIO_SYSSPACE, sizeof(v6only));
	}
#endif

out:
	return (retval_socket);
}