diff options
| author | Blue Swirl <blauwirbel@gmail.com> | 2012-08-14 19:50:22 +0000 |
|---|---|---|
| committer | Blue Swirl <blauwirbel@gmail.com> | 2012-08-14 19:50:22 +0000 |
| commit | 873359d411eeb380906761e46839a2b705dbcf75 (patch) | |
| tree | 970fbd4452ef9c28a9f039ca71b353c69f706e75 /linux-user/syscall.c | |
| parent | 92fc4b586f8856ee9f2bad31fb6e9acd80fa8319 (diff) | |
| parent | 3a1363acf9648bc26989b01b87c7c3c494df2138 (diff) | |
| download | focaccia-qemu-873359d411eeb380906761e46839a2b705dbcf75.tar.gz focaccia-qemu-873359d411eeb380906761e46839a2b705dbcf75.zip | |
Merge branch 'linux-user.next' of git://git.linaro.org/people/pmaydell/qemu-arm
* 'linux-user.next' of git://git.linaro.org/people/pmaydell/qemu-arm:
linux-user: ARM: Ignore immediate value for svc in thumb mode
linux-user: Use init_guest_space when -R and -B are specified
linux-user: Factor out guest space probing into a function
flatload: fix bss clearing
linux-user: make host_to_target_cmsg support SO_TIMESTAMP cmsg_type
linux-user: make do_setsockopt support SOL_RAW ICMP_FILTER socket option
linux-user: pass sockaddr from host to target
linux-user: Move target_to_host_errno_table[] setup out of ioctl loop
linux-user: Fix SNDCTL_DSP_MAP{IN, OUT}BUF ioctl definitions
linux-user: Fix incorrect TARGET_BLKBSZGET, TARGET_BLKBSZSET
Diffstat (limited to 'linux-user/syscall.c')
| -rw-r--r-- | linux-user/syscall.c | 67 |
1 files changed, 55 insertions, 12 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 3ba3ef5719..41c869bfe0 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -60,6 +60,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base, #include <netinet/ip.h> #include <netinet/tcp.h> #include <linux/wireless.h> +#include <linux/icmp.h> #include "qemu-common.h" #ifdef TARGET_GPROF #include <sys/gmon.h> @@ -1268,7 +1269,6 @@ static inline abi_long host_to_target_sockaddr(abi_ulong target_addr, return 0; } -/* ??? Should this also swap msgh->name? */ static inline abi_long target_to_host_cmsg(struct msghdr *msgh, struct target_msghdr *target_msgh) { @@ -1325,7 +1325,6 @@ static inline abi_long target_to_host_cmsg(struct msghdr *msgh, return 0; } -/* ??? Should this also swap msgh->name? */ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh, struct msghdr *msgh) { @@ -1360,16 +1359,28 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh, target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type); target_cmsg->cmsg_len = tswapal(TARGET_CMSG_LEN(len)); - if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) { - gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type); - memcpy(target_data, data, len); - } else { + if ((cmsg->cmsg_level == TARGET_SOL_SOCKET) && + (cmsg->cmsg_type == SCM_RIGHTS)) { int *fd = (int *)data; int *target_fd = (int *)target_data; int i, numfds = len / sizeof(int); for (i = 0; i < numfds; i++) target_fd[i] = tswap32(fd[i]); + } else if ((cmsg->cmsg_level == TARGET_SOL_SOCKET) && + (cmsg->cmsg_type == SO_TIMESTAMP) && + (len == sizeof(struct timeval))) { + /* copy struct timeval to target */ + struct timeval *tv = (struct timeval *)data; + struct target_timeval *target_tv = + (struct target_timeval *)target_data; + + target_tv->tv_sec = tswapal(tv->tv_sec); + target_tv->tv_usec = tswapal(tv->tv_usec); + } else { + gemu_log("Unsupported ancillary data: %d/%d\n", + cmsg->cmsg_level, cmsg->cmsg_type); + memcpy(target_data, data, len); } cmsg = CMSG_NXTHDR(msgh, cmsg); @@ -1454,6 +1465,25 @@ static abi_long do_setsockopt(int sockfd, int level, int optname, goto unimplemented; } break; + case SOL_RAW: + switch (optname) { + case ICMP_FILTER: + /* struct icmp_filter takes an u32 value */ + if (optlen < sizeof(uint32_t)) { + return -TARGET_EINVAL; + } + + if (get_user_u32(val, optval_addr)) { + return -TARGET_EFAULT; + } + ret = get_errno(setsockopt(sockfd, level, optname, + &val, sizeof(val))); + break; + + default: + goto unimplemented; + } + break; case TARGET_SOL_SOCKET: switch (optname) { /* Options with 'int' argument. */ @@ -1885,10 +1915,22 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg, if (!is_error(ret)) { len = ret; ret = host_to_target_cmsg(msgp, &msg); - if (!is_error(ret)) + if (!is_error(ret)) { + msgp->msg_namelen = tswap32(msg.msg_namelen); + if (msg.msg_name != NULL) { + ret = host_to_target_sockaddr(tswapal(msgp->msg_name), + msg.msg_name, msg.msg_namelen); + if (ret) { + goto out; + } + } + ret = len; + } } } + +out: unlock_iovec(vec, target_vec, count, !send); unlock_user_struct(msgp, target_msg, send ? 0 : 1); return ret; @@ -4606,6 +4648,12 @@ void syscall_init(void) #undef STRUCT #undef STRUCT_SPECIAL + /* Build target_to_host_errno_table[] table from + * host_to_target_errno_table[]. */ + for (i = 0; i < ERRNO_TABLE_SIZE; i++) { + target_to_host_errno_table[host_to_target_errno_table[i]] = i; + } + /* we patch the ioctl size if necessary. We rely on the fact that no ioctl has all the bits at '1' in the size field */ ie = ioctl_entries; @@ -4625,11 +4673,6 @@ void syscall_init(void) (size << TARGET_IOC_SIZESHIFT); } - /* Build target_to_host_errno_table[] table from - * host_to_target_errno_table[]. */ - for (i=0; i < ERRNO_TABLE_SIZE; i++) - target_to_host_errno_table[host_to_target_errno_table[i]] = i; - /* automatic consistency check if same arch */ #if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \ (defined(__x86_64__) && defined(TARGET_X86_64)) |