summaryrefslogtreecommitdiffstats
path: root/sys/compat/linux
diff options
context:
space:
mode:
authordchagin <dchagin@FreeBSD.org>2015-05-24 18:06:12 +0000
committerdchagin <dchagin@FreeBSD.org>2015-05-24 18:06:12 +0000
commit796d34d09cdb59afca2d3e36ab48eb6eb39bf7aa (patch)
treed124e4abef30ce748305efcb8a80f34775fdda6e /sys/compat/linux
parent21f92dba1febd740cbf14bff364b46101e3287e8 (diff)
downloadFreeBSD-src-796d34d09cdb59afca2d3e36ab48eb6eb39bf7aa.zip
FreeBSD-src-796d34d09cdb59afca2d3e36ab48eb6eb39bf7aa.tar.gz
Since FreeBSD supports SOCK_CLOEXEC & SOCK_NONBLOCK options
remove its emulation via fcntl call from Linuxulator.
Diffstat (limited to 'sys/compat/linux')
-rw-r--r--sys/compat/linux/linux_socket.c94
1 files changed, 25 insertions, 69 deletions
diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c
index 30c0486..7e9f751 100644
--- a/sys/compat/linux/linux_socket.c
+++ b/sys/compat/linux/linux_socket.c
@@ -80,6 +80,7 @@ static int linux_sendmsg_common(struct thread *, l_int, struct l_msghdr *,
l_uint);
static int linux_recvmsg_common(struct thread *, l_int, struct l_msghdr *,
l_uint, struct msghdr *);
+static int linux_set_socket_flags(int, int *);
/*
* Reads a linux sockaddr and does any necessary translation.
@@ -534,20 +535,15 @@ bsd_to_linux_msghdr(const struct msghdr *bhdr, struct l_msghdr *lhdr)
}
static int
-linux_set_socket_flags(struct thread *td, int s, int flags)
+linux_set_socket_flags(int lflags, int *flags)
{
- int error;
- if (flags & LINUX_SOCK_NONBLOCK) {
- error = kern_fcntl(td, s, F_SETFL, O_NONBLOCK);
- if (error)
- return (error);
- }
- if (flags & LINUX_SOCK_CLOEXEC) {
- error = kern_fcntl(td, s, F_SETFD, FD_CLOEXEC);
- if (error)
- return (error);
- }
+ if (lflags & ~(LINUX_SOCK_CLOEXEC | LINUX_SOCK_NONBLOCK))
+ return (EINVAL);
+ if (lflags & LINUX_SOCK_NONBLOCK)
+ *flags |= SOCK_NONBLOCK;
+ if (lflags & LINUX_SOCK_CLOEXEC)
+ *flags |= SOCK_CLOEXEC;
return (0);
}
@@ -649,15 +645,16 @@ linux_socket(struct thread *td, struct linux_socket_args *args)
int type;
int protocol;
} */ bsd_args;
- int retval_socket, socket_flags;
+ int retval_socket;
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);
+ retval_socket = linux_set_socket_flags(args->type & ~LINUX_SOCK_TYPE_MASK,
+ &bsd_args.type);
+ if (retval_socket != 0)
+ return (retval_socket);
bsd_args.domain = linux_to_bsd_domain(args->domain);
if (bsd_args.domain == -1)
return (EAFNOSUPPORT);
@@ -666,13 +663,6 @@ linux_socket(struct thread *td, struct linux_socket_args *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) {
@@ -701,7 +691,6 @@ linux_socket(struct thread *td, struct linux_socket_args *args)
}
#endif
-out:
return (retval_socket);
}
@@ -784,43 +773,30 @@ static int
linux_accept_common(struct thread *td, int s, l_uintptr_t addr,
l_uintptr_t namelen, int flags)
{
- struct accept_args /* {
+ struct accept4_args /* {
int s;
struct sockaddr * __restrict name;
socklen_t * __restrict anamelen;
+ int flags;
} */ bsd_args;
int error;
- if (flags & ~(LINUX_SOCK_CLOEXEC | LINUX_SOCK_NONBLOCK))
- return (EINVAL);
-
bsd_args.s = s;
/* XXX: */
bsd_args.name = (struct sockaddr * __restrict)PTRIN(addr);
bsd_args.anamelen = PTRIN(namelen);/* XXX */
- error = sys_accept(td, &bsd_args);
+ error = linux_set_socket_flags(flags, &bsd_args.flags);
+ if (error != 0)
+ return (error);
+ error = sys_accept4(td, &bsd_args);
bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.name);
if (error) {
if (error == EFAULT && namelen != sizeof(struct sockaddr_in))
return (EINVAL);
return (error);
}
-
- /*
- * linux appears not to copy flags from the parent socket to the
- * accepted one, so we must clear the flags in the new descriptor
- * and apply the requested flags.
- */
- error = kern_fcntl(td, td->td_retval[0], F_SETFL, 0);
- if (error)
- goto out;
- error = linux_set_socket_flags(td, td->td_retval[0], flags);
- if (error)
- goto out;
if (addr)
error = linux_sa_put(PTRIN(addr));
-
-out:
if (error) {
(void)kern_close(td, td->td_retval[0]);
td->td_retval[0] = 0;
@@ -900,20 +876,18 @@ linux_socketpair(struct thread *td, struct linux_socketpair_args *args)
int protocol;
int *rsv;
} */ bsd_args;
- int error, socket_flags;
- int sv[2];
+ int error;
bsd_args.domain = linux_to_bsd_domain(args->domain);
if (bsd_args.domain != PF_LOCAL)
return (EAFNOSUPPORT);
-
- 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);
-
+ error = linux_set_socket_flags(args->type & ~LINUX_SOCK_TYPE_MASK,
+ &bsd_args.type);
+ if (error != 0)
+ return (error);
if (args->protocol != 0 && args->protocol != PF_UNIX)
/*
@@ -926,25 +900,7 @@ linux_socketpair(struct thread *td, struct linux_socketpair_args *args)
else
bsd_args.protocol = 0;
bsd_args.rsv = (int *)PTRIN(args->rsv);
- error = kern_socketpair(td, bsd_args.domain, bsd_args.type,
- bsd_args.protocol, sv);
- if (error)
- return (error);
- error = linux_set_socket_flags(td, sv[0], socket_flags);
- if (error)
- goto out;
- error = linux_set_socket_flags(td, sv[1], socket_flags);
- if (error)
- goto out;
-
- error = copyout(sv, bsd_args.rsv, 2 * sizeof(int));
-
-out:
- if (error) {
- (void)kern_close(td, sv[0]);
- (void)kern_close(td, sv[1]);
- }
- return (error);
+ return (sys_socketpair(td, &bsd_args));
}
#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
OpenPOWER on IntegriCloud