summaryrefslogtreecommitdiff
path: root/sys/compat/linux/common/linux_socket.c
diff options
context:
space:
mode:
authornjoly <njoly@NetBSD.org>2014-05-23 12:28:51 +0000
committernjoly <njoly@NetBSD.org>2014-05-23 12:28:51 +0000
commit87e37f003e8bb2c720be590f34ec9c25453d581c (patch)
tree6320327104a635c774d9b2009fb260c16c985bc5 /sys/compat/linux/common/linux_socket.c
parentf5ea10296d1df45e9615e2dda33096e6f09c6623 (diff)
Add a funtion that translate socket type value from Linux to NetBSD.
Use it for socket and socketpair syscalls.
Diffstat (limited to 'sys/compat/linux/common/linux_socket.c')
-rw-r--r--sys/compat/linux/common/linux_socket.c67
1 files changed, 31 insertions, 36 deletions
diff --git a/sys/compat/linux/common/linux_socket.c b/sys/compat/linux/common/linux_socket.c
index a1bb924a1a4..d358c585aa7 100644
--- a/sys/compat/linux/common/linux_socket.c
+++ b/sys/compat/linux/common/linux_socket.c
@@ -1,4 +1,4 @@
-/* $NetBSD: linux_socket.c,v 1.118 2014/05/17 21:26:20 rmind Exp $ */
+/* $NetBSD: linux_socket.c,v 1.119 2014/05/23 12:28:51 njoly Exp $ */
/*-
* Copyright (c) 1995, 1998, 2008 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_socket.c,v 1.118 2014/05/17 21:26:20 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_socket.c,v 1.119 2014/05/23 12:28:51 njoly Exp $");
#if defined(_KERNEL_OPT)
#include "opt_inet.h"
@@ -70,7 +70,6 @@ __KERNEL_RCSID(0, "$NetBSD: linux_socket.c,v 1.118 2014/05/17 21:26:20 rmind Exp
#include <sys/kauth.h>
#include <sys/syscallargs.h>
#include <sys/ktrace.h>
-#include <sys/fcntl.h>
#include <lib/libkern/libkern.h>
@@ -111,6 +110,7 @@ __KERNEL_RCSID(0, "$NetBSD: linux_socket.c,v 1.118 2014/05/17 21:26:20 rmind Exp
static int linux_to_bsd_domain(int);
static int bsd_to_linux_domain(int);
+static int linux_to_bsd_type(int);
int linux_to_bsd_sopt_level(int);
int linux_to_bsd_so_sockopt(int);
int linux_to_bsd_ip_sockopt(int);
@@ -238,6 +238,27 @@ bsd_to_linux_domain(int bdom)
}
static int
+linux_to_bsd_type(int ltype)
+{
+ int type, flags;
+
+ /* Real types are identical between Linux and NetBSD */
+ type = ltype & LINUX_SOCK_TYPE_MASK;
+
+ /* But flags are not .. */
+ flags = ltype & ~LINUX_SOCK_TYPE_MASK;
+ if (flags & ~(LINUX_SOCK_CLOEXEC|LINUX_SOCK_NONBLOCK))
+ return -1;
+
+ if (flags & LINUX_SOCK_CLOEXEC)
+ type |= SOCK_CLOEXEC;
+ if (flags & LINUX_SOCK_NONBLOCK)
+ type |= SOCK_NONBLOCK;
+
+ return type;
+}
+
+static int
linux_to_bsd_msg_flags(int lflag)
{
int i, lfl, bfl;
@@ -300,16 +321,16 @@ linux_sys_socket(struct lwp *l, const struct linux_sys_socket_args *uap, registe
syscallarg(int) protocol;
} */
struct sys___socket30_args bsa;
- struct sys_fcntl_args fsa;
- register_t fretval[2];
- int error, flags;
+ int error;
SCARG(&bsa, protocol) = SCARG(uap, protocol);
- SCARG(&bsa, type) = SCARG(uap, type) & LINUX_SOCK_TYPE_MASK;
SCARG(&bsa, domain) = linux_to_bsd_domain(SCARG(uap, domain));
if (SCARG(&bsa, domain) == -1)
return EINVAL;
+ SCARG(&bsa, type) = linux_to_bsd_type(SCARG(uap, type));
+ if (SCARG(&bsa, type) == -1)
+ return EINVAL;
/*
* Apparently linux uses this to talk to ISDN sockets. If we fail
* now programs seems to handle it, but if we don't we are going
@@ -317,36 +338,8 @@ linux_sys_socket(struct lwp *l, const struct linux_sys_socket_args *uap, registe
*/
if (SCARG(&bsa, domain) == AF_ROUTE && SCARG(&bsa, type) == SOCK_RAW)
return ENOTSUP;
- flags = SCARG(uap, type) & ~LINUX_SOCK_TYPE_MASK;
- if (flags & ~(LINUX_SOCK_CLOEXEC | LINUX_SOCK_NONBLOCK))
- return EINVAL;
error = sys___socket30(l, &bsa, retval);
- /*
- * Linux overloads the "type" parameter to include some
- * fcntl flags to be set on the file descriptor.
- * Process those if creating the socket succeeded.
- */
-
- if (!error && flags & LINUX_SOCK_CLOEXEC) {
- SCARG(&fsa, fd) = *retval;
- SCARG(&fsa, cmd) = F_SETFD;
- SCARG(&fsa, arg) = (void *)(uintptr_t)FD_CLOEXEC;
- (void) sys_fcntl(l, &fsa, fretval);
- }
- if (!error && flags & LINUX_SOCK_NONBLOCK) {
- SCARG(&fsa, fd) = *retval;
- SCARG(&fsa, cmd) = F_SETFL;
- SCARG(&fsa, arg) = (void *)(uintptr_t)O_NONBLOCK;
- error = sys_fcntl(l, &fsa, fretval);
- if (error) {
- struct sys_close_args csa;
-
- SCARG(&csa, fd) = *retval;
- (void) sys_close(l, &csa, fretval);
- }
- }
-
#ifdef INET6
/*
* Linux AF_INET6 socket has IPV6_V6ONLY setsockopt set to 0 by
@@ -385,7 +378,9 @@ linux_sys_socketpair(struct lwp *l, const struct linux_sys_socketpair_args *uap,
SCARG(&bsa, domain) = linux_to_bsd_domain(SCARG(uap, domain));
if (SCARG(&bsa, domain) == -1)
return EINVAL;
- SCARG(&bsa, type) = SCARG(uap, type);
+ SCARG(&bsa, type) = linux_to_bsd_type(SCARG(uap, type));
+ if (SCARG(&bsa, type) == -1)
+ return EINVAL;
SCARG(&bsa, protocol) = SCARG(uap, protocol);
SCARG(&bsa, rsv) = SCARG(uap, rsv);