diff options
| author | njoly <njoly@NetBSD.org> | 2014-05-23 12:28:51 +0000 |
|---|---|---|
| committer | njoly <njoly@NetBSD.org> | 2014-05-23 12:28:51 +0000 |
| commit | 87e37f003e8bb2c720be590f34ec9c25453d581c (patch) | |
| tree | 6320327104a635c774d9b2009fb260c16c985bc5 /sys/compat/linux/common/linux_socket.c | |
| parent | f5ea10296d1df45e9615e2dda33096e6f09c6623 (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.c | 67 |
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); |
