linux-user: improve target_to_host_sock_type conversion

Previous implementation has failed to take into account different value of
SOCK_NONBLOCK on target and host, and existence of SOCK_CLOEXEC.
The same conversion has to be applied both for do_socket and do_socketpair,
so the code has been isolated in a static inline function.

enum sock_type in linux-user/socket.h has been extended to include
TARGET_SOCK_CLOEXEC and TARGET_SOCK_NONBLOCK, similar to definition in libc.
The patch also includes necessary code style changes (tab to spaces) in the
header file since most of the file has been touched by this change.

Signed-off-by: Petar Jovanovic <petar.jovanovic@imgtec.com>
Message-id: 1372639454-7560-1-git-send-email-petar.jovanovic@rt-rk.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Petar Jovanovic 2013-07-01 02:44:14 +02:00 committed by Riku Voipio
parent 023b0ae33b
commit f651e6ae55
2 changed files with 266 additions and 140 deletions

View file

@ -1,6 +1,6 @@
#if defined(TARGET_MIPS) #if defined(TARGET_MIPS)
// MIPS special values for constants /* MIPS special values for constants */
/* /*
* For setsockopt(2) * For setsockopt(2)
@ -17,10 +17,13 @@
#define TARGET_SO_BROADCAST 0x0020 /* Allow transmission of #define TARGET_SO_BROADCAST 0x0020 /* Allow transmission of
broadcast messages. */ broadcast messages. */
#define TARGET_SO_LINGER 0x0080 /* Block on close of a reliable #define TARGET_SO_LINGER 0x0080 /* Block on close of a reliable
socket to transmit pending data. */ * socket to transmit pending data.
#define TARGET_SO_OOBINLINE 0x0100 /* Receive out-of-band data in-band. */ */
#define TARGET_SO_OOBINLINE 0x0100 /* Receive out-of-band data in-band.
*/
#if 0 #if 0
To add: #define TARGET_SO_REUSEPORT 0x0200 /* Allow local address and port reuse. */ /* To add: Allow local address and port reuse. */
#define TARGET_SO_REUSEPORT 0x0200
#endif #endif
#define TARGET_SO_TYPE 0x1008 /* Compatible name for SO_STYLE. */ #define TARGET_SO_TYPE 0x1008 /* Compatible name for SO_STYLE. */
@ -72,9 +75,16 @@
* @SOCK_RAW - raw socket * @SOCK_RAW - raw socket
* @SOCK_RDM - reliably-delivered message * @SOCK_RDM - reliably-delivered message
* @SOCK_SEQPACKET - sequential packet socket * @SOCK_SEQPACKET - sequential packet socket
* @SOCK_DCCP - Datagram Congestion Control Protocol socket
* @SOCK_PACKET - linux specific way of getting packets at the dev level. * @SOCK_PACKET - linux specific way of getting packets at the dev level.
* For writing rarp and other similar things on the user level. * For writing rarp and other similar things on the user
* level.
* @SOCK_CLOEXEC - sets the close-on-exec (FD_CLOEXEC) flag.
* @SOCK_NONBLOCK - sets the O_NONBLOCK file status flag.
*/ */
#define ARCH_HAS_SOCKET_TYPES 1
enum sock_type { enum sock_type {
TARGET_SOCK_DGRAM = 1, TARGET_SOCK_DGRAM = 1,
TARGET_SOCK_STREAM = 2, TARGET_SOCK_STREAM = 2,
@ -83,9 +93,12 @@
TARGET_SOCK_SEQPACKET = 5, TARGET_SOCK_SEQPACKET = 5,
TARGET_SOCK_DCCP = 6, TARGET_SOCK_DCCP = 6,
TARGET_SOCK_PACKET = 10, TARGET_SOCK_PACKET = 10,
TARGET_SOCK_CLOEXEC = 02000000,
TARGET_SOCK_NONBLOCK = 0200,
}; };
#define TARGET_SOCK_MAX (SOCK_PACKET + 1) #define TARGET_SOCK_MAX (TARGET_SOCK_PACKET + 1)
#define TARGET_SOCK_TYPE_MASK 0xf /* Covers up to TARGET_SOCK_MAX-1. */
#elif defined(TARGET_ALPHA) #elif defined(TARGET_ALPHA)
@ -156,8 +169,81 @@
/* Instruct lower device to use last 4-bytes of skb data as FCS */ /* Instruct lower device to use last 4-bytes of skb data as FCS */
#define TARGET_SO_NOFCS 43 #define TARGET_SO_NOFCS 43
/** sock_type - Socket types
*
* Please notice that for binary compat reasons ALPHA has to
* override the enum sock_type in include/linux/net.h, so
* we define ARCH_HAS_SOCKET_TYPES here.
*
* @SOCK_DGRAM - datagram (conn.less) socket
* @SOCK_STREAM - stream (connection) socket
* @SOCK_RAW - raw socket
* @SOCK_RDM - reliably-delivered message
* @SOCK_SEQPACKET - sequential packet socket
* @SOCK_DCCP - Datagram Congestion Control Protocol socket
* @SOCK_PACKET - linux specific way of getting packets at the dev level.
* For writing rarp and other similar things on the user
* level.
* @SOCK_CLOEXEC - sets the close-on-exec (FD_CLOEXEC) flag.
* @SOCK_NONBLOCK - sets the O_NONBLOCK file status flag.
*/
#define ARCH_HAS_SOCKET_TYPES 1
enum sock_type {
TARGET_SOCK_STREAM = 1,
TARGET_SOCK_DGRAM = 2,
TARGET_SOCK_RAW = 3,
TARGET_SOCK_RDM = 4,
TARGET_SOCK_SEQPACKET = 5,
TARGET_SOCK_DCCP = 6,
TARGET_SOCK_PACKET = 10,
TARGET_SOCK_CLOEXEC = 010000000,
TARGET_SOCK_NONBLOCK = 010000000000,
};
#define TARGET_SOCK_MAX (TARGET_SOCK_PACKET + 1)
#define TARGET_SOCK_TYPE_MASK 0xf /* Covers up to TARGET_SOCK_MAX-1. */
#else #else
#if defined(TARGET_SPARC)
/** sock_type - Socket types
*
* Please notice that for binary compat reasons SPARC has to
* override the enum sock_type in include/linux/net.h, so
* we define ARCH_HAS_SOCKET_TYPES here.
*
* @SOCK_DGRAM - datagram (conn.less) socket
* @SOCK_STREAM - stream (connection) socket
* @SOCK_RAW - raw socket
* @SOCK_RDM - reliably-delivered message
* @SOCK_SEQPACKET - sequential packet socket
* @SOCK_DCCP - Datagram Congestion Control Protocol socket
* @SOCK_PACKET - linux specific way of getting packets at the dev level.
* For writing rarp and other similar things on the user
* level.
* @SOCK_CLOEXEC - sets the close-on-exec (FD_CLOEXEC) flag.
* @SOCK_NONBLOCK - sets the O_NONBLOCK file status flag.
*/
#define ARCH_HAS_SOCKET_TYPES 1
enum sock_type {
TARGET_SOCK_STREAM = 1,
TARGET_SOCK_DGRAM = 2,
TARGET_SOCK_RAW = 3,
TARGET_SOCK_RDM = 4,
TARGET_SOCK_SEQPACKET = 5,
TARGET_SOCK_DCCP = 6,
TARGET_SOCK_PACKET = 10,
TARGET_SOCK_CLOEXEC = 020000000,
TARGET_SOCK_NONBLOCK = 040000,
};
#define TARGET_SOCK_MAX (TARGET_SOCK_PACKET + 1)
#define TARGET_SOCK_TYPE_MASK 0xf /* Covers up to TARGET_SOCK_MAX-1. */
#endif
/* For setsockopt(2) */ /* For setsockopt(2) */
#define TARGET_SOL_SOCKET 1 #define TARGET_SOL_SOCKET 1
@ -214,3 +300,36 @@
#define TARGET_SO_PEERSEC 31 #define TARGET_SO_PEERSEC 31
#endif #endif
#ifndef ARCH_HAS_SOCKET_TYPES
/** sock_type - Socket types - default values
*
*
* @SOCK_STREAM - stream (connection) socket
* @SOCK_DGRAM - datagram (conn.less) socket
* @SOCK_RAW - raw socket
* @SOCK_RDM - reliably-delivered message
* @SOCK_SEQPACKET - sequential packet socket
* @SOCK_DCCP - Datagram Congestion Control Protocol socket
* @SOCK_PACKET - linux specific way of getting packets at the dev level.
* For writing rarp and other similar things on the user
* level.
* @SOCK_CLOEXEC - sets the close-on-exec (FD_CLOEXEC) flag.
* @SOCK_NONBLOCK - sets the O_NONBLOCK file status flag.
*/
enum sock_type {
TARGET_SOCK_STREAM = 1,
TARGET_SOCK_DGRAM = 2,
TARGET_SOCK_RAW = 3,
TARGET_SOCK_RDM = 4,
TARGET_SOCK_SEQPACKET = 5,
TARGET_SOCK_DCCP = 6,
TARGET_SOCK_PACKET = 10,
TARGET_SOCK_CLOEXEC = 02000000,
TARGET_SOCK_NONBLOCK = 04000,
};
#define TARGET_SOCK_MAX (TARGET_SOCK_PACKET + 1)
#define TARGET_SOCK_TYPE_MASK 0xf /* Covers up to TARGET_SOCK_MAX-1. */
#endif

View file

@ -1705,31 +1705,36 @@ static void unlock_iovec(struct iovec *vec, abi_ulong target_addr,
free(vec); free(vec);
} }
static inline void target_to_host_sock_type(int *type)
{
int host_type = 0;
int target_type = *type;
switch (target_type & TARGET_SOCK_TYPE_MASK) {
case TARGET_SOCK_DGRAM:
host_type = SOCK_DGRAM;
break;
case TARGET_SOCK_STREAM:
host_type = SOCK_STREAM;
break;
default:
host_type = target_type & TARGET_SOCK_TYPE_MASK;
break;
}
if (target_type & TARGET_SOCK_CLOEXEC) {
host_type |= SOCK_CLOEXEC;
}
if (target_type & TARGET_SOCK_NONBLOCK) {
host_type |= SOCK_NONBLOCK;
}
*type = host_type;
}
/* do_socket() Must return target values and target errnos. */ /* do_socket() Must return target values and target errnos. */
static abi_long do_socket(int domain, int type, int protocol) static abi_long do_socket(int domain, int type, int protocol)
{ {
#if defined(TARGET_MIPS) target_to_host_sock_type(&type);
switch(type) {
case TARGET_SOCK_DGRAM:
type = SOCK_DGRAM;
break;
case TARGET_SOCK_STREAM:
type = SOCK_STREAM;
break;
case TARGET_SOCK_RAW:
type = SOCK_RAW;
break;
case TARGET_SOCK_RDM:
type = SOCK_RDM;
break;
case TARGET_SOCK_SEQPACKET:
type = SOCK_SEQPACKET;
break;
case TARGET_SOCK_PACKET:
type = SOCK_PACKET;
break;
}
#endif
if (domain == PF_NETLINK) if (domain == PF_NETLINK)
return -EAFNOSUPPORT; /* do not NETLINK socket connections possible */ return -EAFNOSUPPORT; /* do not NETLINK socket connections possible */
return get_errno(socket(domain, type, protocol)); return get_errno(socket(domain, type, protocol));
@ -1962,6 +1967,8 @@ static abi_long do_socketpair(int domain, int type, int protocol,
int tab[2]; int tab[2];
abi_long ret; abi_long ret;
target_to_host_sock_type(&type);
ret = get_errno(socketpair(domain, type, protocol, tab)); ret = get_errno(socketpair(domain, type, protocol, tab));
if (!is_error(ret)) { if (!is_error(ret)) {
if (put_user_s32(tab[0], target_tab_addr) if (put_user_s32(tab[0], target_tab_addr)