[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 13/18] bsd-user: add support for socket related syst
From: |
Stacey Son |
Subject: |
[Qemu-devel] [PATCH 13/18] bsd-user: add support for socket related system calls |
Date: |
Wed, 16 Oct 2013 09:37:07 -0500 |
This change adds support or stubs for socket related system calls including
accept(2), bind(2), connect(2), getpeername(2), getsockname(2), getsockopt(2),
setsockopt(2), listen(2), recvfrom(2), recvmsg(2), sendmsg(2), sendto(2),
socket(2), socketpair(2), shutdown(2), setfib(2), sctp_peeloff(2),
sctp_generic_sendmsg(2), sctp_generic_recvmsg(2), sendfile(2), and
freebsd4_sendfile(2).
Signed-off-by: Stacey Son <address@hidden>
---
bsd-user/Makefile.objs | 4 +-
bsd-user/bsd-socket.c | 108 +++++++++
bsd-user/bsd-socket.h | 266 ++++++++++++++++++++
bsd-user/freebsd/os-socket.c | 149 ++++++++++++
bsd-user/freebsd/os-socket.h | 548 ++++++++++++++++++++++++++++++++++++++++++
bsd-user/freebsd/qemu-os.h | 6 +
bsd-user/netbsd/os-socket.c | 1 +
bsd-user/netbsd/os-socket.h | 98 ++++++++
bsd-user/openbsd/os-socket.c | 1 +
bsd-user/openbsd/os-socket.h | 98 ++++++++
bsd-user/qemu-bsd.h | 8 +
bsd-user/syscall.c | 93 +++++++
12 files changed, 1378 insertions(+), 2 deletions(-)
create mode 100644 bsd-user/bsd-socket.c
create mode 100644 bsd-user/bsd-socket.h
create mode 100644 bsd-user/freebsd/os-socket.c
create mode 100644 bsd-user/freebsd/os-socket.h
create mode 100644 bsd-user/netbsd/os-socket.c
create mode 100644 bsd-user/netbsd/os-socket.h
create mode 100644 bsd-user/openbsd/os-socket.c
create mode 100644 bsd-user/openbsd/os-socket.h
diff --git a/bsd-user/Makefile.objs b/bsd-user/Makefile.objs
index 1a33a6d..9869837 100644
--- a/bsd-user/Makefile.objs
+++ b/bsd-user/Makefile.objs
@@ -1,6 +1,6 @@
obj-y = main.o bsdload.o elfload.o mmap.o signal.o strace.o syscall.o \
- uaccess.o bsd-mem.o bsd-proc.o \
+ uaccess.o bsd-mem.o bsd-proc.o bsd-socket.o \
$(HOST_ABI_DIR)/os-proc.o \
- $(HOST_ABI_DIR)/os-stat.o \
+ $(HOST_ABI_DIR)/os-socket.o $(HOST_ABI_DIR)/os-stat.o \
$(HOST_ABI_DIR)/os-sys.o \
$(HOST_ABI_DIR)/os-time.o
$(TARGET_ABI_DIR)/target_arch_cpu.o
diff --git a/bsd-user/bsd-socket.c b/bsd-user/bsd-socket.c
new file mode 100644
index 0000000..c1a3b49
--- /dev/null
+++ b/bsd-user/bsd-socket.c
@@ -0,0 +1,108 @@
+/*
+ * BSD socket system call related helpers
+ *
+ * Copyright (c) 2013 Stacey D. Son
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+
+#include "qemu.h"
+#include "qemu-bsd.h"
+
+/*
+ * socket conversion
+ */
+abi_long target_to_host_sockaddr(struct sockaddr *addr, abi_ulong target_addr,
+ socklen_t len)
+{
+ const socklen_t unix_maxlen = sizeof(struct sockaddr_un);
+ sa_family_t sa_family;
+ struct target_sockaddr *target_saddr;
+
+ target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
+ if (target_saddr == 0) {
+ return -TARGET_EFAULT;
+ }
+
+ sa_family = target_saddr->sa_family;
+
+ /*
+ * Oops. The caller might send a incomplete sun_path; sun_path
+ * must be terminated by \0 (see the manual page), but unfortunately
+ * it is quite common to specify sockaddr_un length as
+ * "strlen(x->sun_path)" while it should be "strlen(...) + 1". We will
+ * fix that here if needed.
+ */
+ if (target_saddr->sa_family == AF_UNIX) {
+ if (len < unix_maxlen && len > 0) {
+ char *cp = (char *)target_saddr;
+
+ if (cp[len-1] && !cp[len]) {
+ len++;
+ }
+ }
+ if (len > unix_maxlen) {
+ len = unix_maxlen;
+ }
+ }
+
+ memcpy(addr, target_saddr, len);
+ addr->sa_family = sa_family; /* type uint8_t */
+ addr->sa_len = target_saddr->sa_len; /* type uint8_t */
+ unlock_user(target_saddr, target_addr, 0);
+
+ return 0;
+}
+
+abi_long host_to_target_sockaddr(abi_ulong target_addr, struct sockaddr *addr,
+ socklen_t len)
+{
+ struct target_sockaddr *target_saddr;
+
+ target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
+ if (target_saddr == 0) {
+ return -TARGET_EFAULT;
+ }
+ memcpy(target_saddr, addr, len);
+ target_saddr->sa_family = addr->sa_family; /* type uint8_t */
+ target_saddr->sa_len = addr->sa_len; /* type uint8_t */
+ unlock_user(target_saddr, target_addr, len);
+
+ return 0;
+}
+
+abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn, abi_ulong target_addr,
+ socklen_t len)
+{
+ struct target_ip_mreqn *target_smreqn;
+
+ target_smreqn = lock_user(VERIFY_READ, target_addr, len, 1);
+ if (target_smreqn == 0) {
+ return -TARGET_EFAULT;
+ }
+ mreqn->imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr;
+ mreqn->imr_address.s_addr = target_smreqn->imr_address.s_addr;
+ if (len == sizeof(struct target_ip_mreqn)) {
+ mreqn->imr_ifindex = tswapal(target_smreqn->imr_ifindex);
+ }
+ unlock_user(target_smreqn, target_addr, 0);
+
+ return 0;
+}
+
diff --git a/bsd-user/bsd-socket.h b/bsd-user/bsd-socket.h
new file mode 100644
index 0000000..f5d1ac8
--- /dev/null
+++ b/bsd-user/bsd-socket.h
@@ -0,0 +1,266 @@
+/*
+ * socket related system call shims
+ *
+ * Copyright (c) 2013 Stacey D. Son
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __BSD_SOCKET_H_
+#define __BSD_SOCKET_H_
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+
+#include "qemu-bsd.h"
+
+/* bind(2) */
+static inline abi_long do_bsd_bind(int sockfd, abi_ulong target_addr,
+ socklen_t addrlen)
+{
+ abi_long ret;
+ void *addr;
+
+ if ((int)addrlen < 0) {
+ return -TARGET_EINVAL;
+ }
+
+ addr = alloca(addrlen + 1);
+ ret = target_to_host_sockaddr(addr, target_addr, addrlen);
+ if (is_error(ret)) {
+ return ret;
+ }
+
+ return get_errno(bind(sockfd, addr, addrlen));
+}
+
+/* connect(2) */
+static inline abi_long do_bsd_connect(int sockfd, abi_ulong target_addr,
+ socklen_t addrlen)
+{
+ abi_long ret;
+ void *addr;
+
+ if ((int)addrlen < 0) {
+ return -TARGET_EINVAL;
+ }
+ addr = alloca(addrlen);
+
+ ret = target_to_host_sockaddr(addr, target_addr, addrlen);
+
+ if (is_error(ret)) {
+ return ret;
+ }
+
+ return get_errno(connect(sockfd, addr, addrlen));
+}
+
+/* accept(2) */
+static inline abi_long do_bsd_accept(int fd, abi_ulong target_addr,
+ abi_ulong target_addrlen_addr)
+{
+ socklen_t addrlen;
+ void *addr;
+ abi_long ret;
+
+ if (target_addr == 0) {
+ return get_errno(accept(fd, NULL, NULL));
+ }
+ /* return EINVAL if addrlen pointer is invalid */
+ if (get_user_u32(addrlen, target_addrlen_addr)) {
+ return -TARGET_EINVAL;
+ }
+ if ((int)addrlen < 0) {
+ return -TARGET_EINVAL;
+ }
+ if (!access_ok(VERIFY_WRITE, target_addr, addrlen)) {
+ return -TARGET_EINVAL;
+ }
+ addr = alloca(addrlen);
+
+ ret = get_errno(accept(fd, addr, &addrlen));
+ if (!is_error(ret)) {
+ host_to_target_sockaddr(target_addr, addr, addrlen);
+ if (put_user_u32(addrlen, target_addrlen_addr)) {
+ ret = -TARGET_EFAULT;
+ }
+ }
+ return ret;
+}
+
+/* getpeername(2) */
+static inline abi_long do_bsd_getpeername(int fd, abi_ulong target_addr,
+ abi_ulong target_addrlen_addr)
+{
+ socklen_t addrlen;
+ void *addr;
+ abi_long ret;
+
+ if (get_user_u32(addrlen, target_addrlen_addr)) {
+ return -TARGET_EFAULT;
+ }
+ if ((int)addrlen < 0) {
+ return -TARGET_EINVAL;
+ }
+ if (!access_ok(VERIFY_WRITE, target_addr, addrlen)) {
+ return -TARGET_EFAULT;
+ }
+ addr = alloca(addrlen);
+ ret = get_errno(getpeername(fd, addr, &addrlen));
+ if (!is_error(ret)) {
+ host_to_target_sockaddr(target_addr, addr, addrlen);
+ if (put_user_u32(addrlen, target_addrlen_addr)) {
+ ret = -TARGET_EFAULT;
+ }
+ }
+ return ret;
+}
+
+/* getsockname(2) */
+static inline abi_long do_bsd_getsockname(int fd, abi_ulong target_addr,
+ abi_ulong target_addrlen_addr)
+{
+ socklen_t addrlen;
+ void *addr;
+ abi_long ret;
+
+ if (get_user_u32(addrlen, target_addrlen_addr)) {
+ return -TARGET_EFAULT;
+ }
+ if ((int)addrlen < 0) {
+ return -TARGET_EINVAL;
+ }
+ if (!access_ok(VERIFY_WRITE, target_addr, addrlen)) {
+ return -TARGET_EFAULT;
+ }
+ addr = alloca(addrlen);
+
+ ret = get_errno(getsockname(fd, addr, &addrlen));
+ if (!is_error(ret)) {
+ host_to_target_sockaddr(target_addr, addr, addrlen);
+ if (put_user_u32(addrlen, target_addrlen_addr)) {
+ ret = -TARGET_EFAULT;
+ }
+ }
+ return ret;
+}
+
+/* socketpair(2) */
+static inline abi_long do_bsd_socketpair(int domain, int type, int protocol,
+ abi_ulong target_tab_addr)
+{
+ int tab[2];
+ abi_long ret;
+
+ ret = get_errno(socketpair(domain, type, protocol, tab));
+ if (!is_error(ret)) {
+ if (put_user_s32(tab[0], target_tab_addr) ||
+ put_user_s32(tab[1], target_tab_addr + sizeof(tab[0]))) {
+ ret = -TARGET_EFAULT;
+ }
+ }
+ return ret;
+}
+
+/* sendto(2) */
+static inline abi_long do_bsd_sendto(int fd, abi_ulong msg, size_t len,
+ int flags, abi_ulong target_addr, socklen_t addrlen)
+{
+ struct sockaddr *saddr;
+ void *host_msg;
+ abi_long ret;
+
+ if ((int)addrlen < 0) {
+ return -TARGET_EINVAL;
+ }
+ host_msg = lock_user(VERIFY_READ, msg, len, 1);
+ if (!host_msg) {
+ return -TARGET_EFAULT;
+ }
+ if (target_addr) {
+ saddr = alloca(addrlen);
+ ret = target_to_host_sockaddr(saddr, target_addr, addrlen);
+ if (is_error(ret)) {
+ unlock_user(host_msg, msg, 0);
+ return ret;
+ }
+ ret = get_errno(sendto(fd, host_msg, len, flags, saddr, addrlen));
+ } else {
+ ret = get_errno(send(fd, host_msg, len, flags));
+ }
+ unlock_user(host_msg, msg, 0);
+ return ret;
+}
+
+/* recvfrom(2) */
+static inline abi_long do_bsd_recvfrom(int fd, abi_ulong msg, size_t len,
+ int flags, abi_ulong target_addr, abi_ulong target_addrlen)
+{
+ socklen_t addrlen;
+ struct sockaddr *saddr;
+ void *host_msg;
+ abi_long ret;
+
+ host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
+ if (!host_msg) {
+ return -TARGET_EFAULT;
+ }
+ if (target_addr) {
+ if (get_user_u32(addrlen, target_addrlen)) {
+ ret = -TARGET_EFAULT;
+ goto fail;
+ }
+ if ((int)addrlen < 0) {
+ ret = -TARGET_EINVAL;
+ goto fail;
+ }
+ saddr = alloca(addrlen);
+ ret = get_errno(recvfrom(fd, host_msg, len, flags, saddr, &addrlen));
+ } else {
+ saddr = NULL; /* To keep compiler quiet. */
+ ret = get_errno(qemu_recv(fd, host_msg, len, flags));
+ }
+ if (!is_error(ret)) {
+ if (target_addr) {
+ host_to_target_sockaddr(target_addr, saddr, addrlen);
+ if (put_user_u32(addrlen, target_addrlen)) {
+ ret = -TARGET_EFAULT;
+ goto fail;
+ }
+ }
+ unlock_user(host_msg, msg, len);
+ } else {
+fail:
+ unlock_user(host_msg, msg, 0);
+ }
+ return ret;
+}
+
+/* socket(2) */
+static inline abi_long do_bsd_socket(abi_long domain, abi_long type,
+ abi_long protocol)
+{
+
+ return get_errno(socket(domain, type, protocol));
+}
+
+/* shutdown(2) */
+static inline abi_long do_bsd_shutdown(abi_long s, abi_long how)
+{
+
+ return get_errno(shutdown(s, how));
+}
+
+#endif /* !__BSD_SOCKET_H_ */
diff --git a/bsd-user/freebsd/os-socket.c b/bsd-user/freebsd/os-socket.c
new file mode 100644
index 0000000..949af28
--- /dev/null
+++ b/bsd-user/freebsd/os-socket.c
@@ -0,0 +1,149 @@
+/*
+ * FreeBSD socket related system call helpers
+ *
+ * Copyright (c) 2013 Stacey D. Son
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include "qemu.h"
+#include "qemu-os.h"
+
+abi_long t2h_freebsd_cmsg(struct msghdr *msgh,
+ struct target_msghdr *target_msgh)
+{
+ struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
+ abi_long msg_controllen;
+ abi_ulong target_cmsg_addr;
+ struct target_cmsghdr *target_cmsg;
+ socklen_t space = 0;
+
+
+ msg_controllen = tswapal(target_msgh->msg_controllen);
+ if (msg_controllen < sizeof(struct target_cmsghdr)) {
+ goto the_end;
+ }
+ target_cmsg_addr = tswapal(target_msgh->msg_control);
+ target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
+ if (target_cmsg == 0) {
+ return -TARGET_EFAULT;
+ }
+ while (cmsg && target_cmsg) {
+ void *data = CMSG_DATA(cmsg);
+ void *target_data = TARGET_CMSG_DATA(target_cmsg);
+ int len = tswapal(target_cmsg->cmsg_len) -
+ TARGET_CMSG_ALIGN(sizeof(struct target_cmsghdr));
+ space += CMSG_SPACE(len);
+ if (space > msgh->msg_controllen) {
+ space -= CMSG_SPACE(len);
+ gemu_log("Host cmsg overflow\n");
+ break;
+ }
+ cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
+ cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
+ cmsg->cmsg_len = 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(data, target_data, len);
+ } else {
+ int *fd = (int *)data;
+ int *target_fd = (int *)target_data;
+ int i, numfds = len / sizeof(int);
+
+ for (i = 0; i < numfds; i++) {
+ fd[i] = tswap32(target_fd[i]);
+ }
+ }
+ cmsg = CMSG_NXTHDR(msgh, cmsg);
+ target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
+ }
+ unlock_user(target_cmsg, target_cmsg_addr, 0);
+
+the_end:
+ msgh->msg_controllen = space;
+ return 0;
+}
+
+abi_long h2t_freebsd_cmsg(struct target_msghdr *target_msgh,
+ struct msghdr *msgh)
+{
+ struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
+ abi_long msg_controllen;
+ abi_ulong target_cmsg_addr;
+ struct target_cmsghdr *target_cmsg;
+ socklen_t space = 0;
+
+ msg_controllen = tswapal(target_msgh->msg_controllen);
+ if (msg_controllen < sizeof(struct target_cmsghdr)) {
+ goto the_end;
+ }
+ target_cmsg_addr = tswapal(target_msgh->msg_control);
+ target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr,
+ msg_controllen, 0);
+ if (target_cmsg == 0) {
+ return -TARGET_EFAULT;
+ }
+ while (cmsg && target_cmsg) {
+ void *data = CMSG_DATA(cmsg);
+ void *target_data = TARGET_CMSG_DATA(target_cmsg);
+ int len = cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr));
+
+ space += TARGET_CMSG_SPACE(len);
+ if (space > msg_controllen) {
+ space -= TARGET_CMSG_SPACE(len);
+ gemu_log("Target cmsg overflow\n");
+ break;
+ }
+ target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
+ 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)) {
+ 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_freebsd_timeval *target_tv =
+ (struct target_freebsd_timeval *)target_data;
+ __put_user(tv->tv_sec, &target_tv->tv_sec);
+ __put_user(tv->tv_usec, &target_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);
+ target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
+ }
+ unlock_user(target_cmsg, target_cmsg_addr, space);
+
+the_end:
+ target_msgh->msg_controllen = tswapal(space);
+ return 0;
+}
+
diff --git a/bsd-user/freebsd/os-socket.h b/bsd-user/freebsd/os-socket.h
new file mode 100644
index 0000000..9339ffb
--- /dev/null
+++ b/bsd-user/freebsd/os-socket.h
@@ -0,0 +1,548 @@
+/*
+ * FreeBSD socket related system call shims
+ *
+ * Copyright (c) 2013 Stacey D. Son
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __FREEBSD_SOCKET_H_
+#define __FREEBSD_SOCKET_H_
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+
+#include "qemu-os.h"
+
+/* sendmsg(2) */
+static inline abi_long do_freebsd_sendmsg(int fd, abi_ulong target_msg,
+ int flags)
+{
+ abi_long ret;
+ struct target_msghdr *msgp;
+ struct msghdr msg;
+ int count;
+ struct iovec *vec;
+ abi_ulong target_vec;
+
+ if (!lock_user_struct(VERIFY_READ, msgp, target_msg, 1)) {
+ return -TARGET_EFAULT;
+ }
+ if (msgp->msg_name) {
+ msg.msg_namelen = tswap32(msgp->msg_namelen);
+ msg.msg_name = alloca(msg.msg_namelen);
+ ret = target_to_host_sockaddr(msg.msg_name,
+ tswapal(msgp->msg_name), msg.msg_namelen);
+
+ if (is_error(ret)) {
+ unlock_user_struct(msgp, target_msg, 0);
+ return ret;
+ }
+ } else {
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ }
+ msg.msg_controllen = 2 * tswapal(msgp->msg_controllen);
+ msg.msg_control = alloca(msg.msg_controllen);
+ msg.msg_flags = tswap32(msgp->msg_flags);
+
+ count = tswapal(msgp->msg_iovlen);
+ vec = alloca(count * sizeof(struct iovec));
+ target_vec = tswapal(msgp->msg_iov);
+ lock_iovec(VERIFY_READ, vec, target_vec, count, 1);
+ msg.msg_iovlen = count;
+ msg.msg_iov = vec;
+
+ ret = t2h_freebsd_cmsg(&msg, msgp);
+ if (!is_error(ret)) {
+ ret = get_errno(sendmsg(fd, &msg, flags));
+ }
+ unlock_iovec(vec, target_vec, count, 0);
+ unlock_user_struct(msgp, target_msg, 0);
+ return ret;
+}
+
+/* recvmsg(2) */
+static inline abi_long do_freebsd_recvmsg(int fd, abi_ulong target_msg,
+ int flags)
+{
+ abi_long ret, len;
+ struct target_msghdr *msgp;
+ struct msghdr msg;
+ int count;
+ struct iovec *vec;
+ abi_ulong target_vec;
+
+ if (!lock_user_struct(VERIFY_WRITE, msgp, target_msg, 0)) {
+ return -TARGET_EFAULT;
+ }
+ if (msgp->msg_name) {
+ msg.msg_namelen = tswap32(msgp->msg_namelen);
+ msg.msg_name = alloca(msg.msg_namelen);
+ ret = target_to_host_sockaddr(msg.msg_name,
+ tswapal(msgp->msg_name), msg.msg_namelen);
+
+ if (is_error(ret)) {
+ unlock_user_struct(msgp, target_msg, 1);
+ return ret;
+ }
+ } else {
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ }
+ msg.msg_controllen = 2 * tswapal(msgp->msg_controllen);
+ msg.msg_control = alloca(msg.msg_controllen);
+ msg.msg_flags = tswap32(msgp->msg_flags);
+
+ count = tswapal(msgp->msg_iovlen);
+ vec = alloca(count * sizeof(struct iovec));
+ target_vec = tswapal(msgp->msg_iov);
+ lock_iovec(VERIFY_WRITE, vec, target_vec, count, 0);
+ msg.msg_iovlen = count;
+ msg.msg_iov = vec;
+
+ ret = get_errno(recvmsg(fd, &msg, flags));
+ if (!is_error(ret)) {
+ len = ret;
+ ret = h2t_freebsd_cmsg(msgp, &msg);
+ 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 (is_error(ret)) {
+ goto out;
+ }
+ }
+ }
+ ret = len;
+ }
+out:
+ unlock_iovec(vec, target_vec, count, 1);
+ unlock_user_struct(msgp, target_msg, 1);
+ return ret;
+}
+
+/* setsockopt(2) */
+static inline abi_long do_bsd_setsockopt(int sockfd, int level, int optname,
+ abi_ulong optval_addr, socklen_t optlen)
+{
+ abi_long ret;
+ int val;
+ struct ip_mreqn *ip_mreq;
+
+ switch (level) {
+ case IPPROTO_TCP:
+ /* TCP options all take an 'int' 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;
+
+ case IPPROTO_IP:
+ switch (optname) {
+ case IP_HDRINCL:/* int; header is included with data */
+ case IP_TOS: /* int; IP type of service and preced. */
+ case IP_TTL: /* int; IP time to live */
+ case IP_RECVOPTS: /* bool; receive all IP opts w/dgram */
+ case IP_RECVRETOPTS: /* bool; receive IP opts for response */
+ case IP_RECVDSTADDR: /* bool; receive IP dst addr w/dgram */
+ case IP_MULTICAST_IF:/* u_char; set/get IP multicast i/f */
+ case IP_MULTICAST_TTL:/* u_char; set/get IP multicast ttl */
+ case IP_MULTICAST_LOOP:/*u_char;set/get IP multicast loopback */
+ case IP_PORTRANGE: /* int; range to choose for unspec port */
+ case IP_RECVIF: /* bool; receive reception if w/dgram */
+ case IP_IPSEC_POLICY: /* int; set/get security policy */
+ case IP_FAITH: /* bool; accept FAITH'ed connections */
+ case IP_RECVTTL: /* bool; receive reception TTL w/dgram */
+ val = 0;
+ if (optlen >= sizeof(uint32_t)) {
+ if (get_user_u32(val, optval_addr)) {
+ return -TARGET_EFAULT;
+ }
+ } else if (optlen >= 1) {
+ if (get_user_u8(val, optval_addr)) {
+ return -TARGET_EFAULT;
+ }
+ }
+ ret = get_errno(setsockopt(sockfd, level, optname, &val,
+ sizeof(val)));
+ break;
+
+ case IP_ADD_MEMBERSHIP: /*ip_mreq; add an IP group membership */
+ case IP_DROP_MEMBERSHIP:/*ip_mreq; drop an IP group membership*/
+ if (optlen < sizeof(struct target_ip_mreq) ||
+ optlen > sizeof(struct target_ip_mreqn)) {
+ return -TARGET_EINVAL;
+ }
+ ip_mreq = (struct ip_mreqn *) alloca(optlen);
+ target_to_host_ip_mreq(ip_mreq, optval_addr, optlen);
+ ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq,
+ optlen));
+ break;
+
+ default:
+ goto unimplemented;
+ }
+ break;
+
+ case TARGET_SOL_SOCKET:
+ switch (optname) {
+ /* Options with 'int' argument. */
+ case TARGET_SO_DEBUG:
+ optname = SO_DEBUG;
+ break;
+
+ case TARGET_SO_REUSEADDR:
+ optname = SO_REUSEADDR;
+ break;
+
+ case TARGET_SO_REUSEPORT:
+ optname = SO_REUSEADDR;
+ break;
+
+ case TARGET_SO_KEEPALIVE:
+ optname = SO_KEEPALIVE;
+ break;
+
+ case TARGET_SO_DONTROUTE:
+ optname = SO_DONTROUTE;
+ break;
+
+ case TARGET_SO_LINGER:
+ optname = SO_LINGER;
+ break;
+
+ case TARGET_SO_BROADCAST:
+ optname = SO_BROADCAST;
+ break;
+
+ case TARGET_SO_OOBINLINE:
+ optname = SO_OOBINLINE;
+ break;
+
+ case TARGET_SO_SNDBUF:
+ optname = SO_SNDBUF;
+ break;
+
+ case TARGET_SO_RCVBUF:
+ optname = SO_RCVBUF;
+ break;
+
+ case TARGET_SO_SNDLOWAT:
+ optname = SO_RCVLOWAT;
+ break;
+
+ case TARGET_SO_RCVLOWAT:
+ optname = SO_RCVLOWAT;
+ break;
+
+ case TARGET_SO_SNDTIMEO:
+ optname = SO_SNDTIMEO;
+ break;
+
+ case TARGET_SO_RCVTIMEO:
+ optname = SO_RCVTIMEO;
+ break;
+
+ case TARGET_SO_ACCEPTFILTER:
+ goto unimplemented;
+
+ case TARGET_SO_NOSIGPIPE:
+ optname = SO_NOSIGPIPE;
+ break;
+
+ case TARGET_SO_TIMESTAMP:
+ optname = SO_TIMESTAMP;
+ break;
+
+ case TARGET_SO_BINTIME:
+ optname = SO_BINTIME;
+ break;
+
+ case TARGET_SO_ERROR:
+ optname = SO_ERROR;
+ break;
+
+ case TARGET_SO_SETFIB:
+ optname = SO_ERROR;
+ break;
+
+#ifdef SO_USER_COOKIE
+ case TARGET_SO_USER_COOKIE:
+ optname = SO_USER_COOKIE;
+ break;
+#endif
+ default:
+ goto unimplemented;
+ }
+ if (optlen < sizeof(uint32_t)) {
+ return -TARGET_EINVAL;
+ }
+ if (get_user_u32(val, optval_addr)) {
+ return -TARGET_EFAULT;
+ }
+ ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val,
+ sizeof(val)));
+ break;
+ default:
+unimplemented:
+ gemu_log("Unsupported setsockopt level=%d optname=%d\n",
+ level, optname);
+ ret = -TARGET_ENOPROTOOPT;
+ }
+
+ return ret;
+}
+
+/* getsockopt(2) */
+static inline abi_long do_bsd_getsockopt(int sockfd, int level, int optname,
+ abi_ulong optval_addr, abi_ulong optlen)
+{
+ abi_long ret;
+ int len, val;
+ socklen_t lv;
+
+ switch (level) {
+ case TARGET_SOL_SOCKET:
+ level = SOL_SOCKET;
+ switch (optname) {
+
+ /* These don't just return a single integer */
+ case TARGET_SO_LINGER:
+ case TARGET_SO_RCVTIMEO:
+ case TARGET_SO_SNDTIMEO:
+ case TARGET_SO_ACCEPTFILTER:
+ goto unimplemented;
+
+ /* Options with 'int' argument. */
+ case TARGET_SO_DEBUG:
+ optname = SO_DEBUG;
+ goto int_case;
+
+ case TARGET_SO_REUSEADDR:
+ optname = SO_REUSEADDR;
+ goto int_case;
+
+ case TARGET_SO_REUSEPORT:
+ optname = SO_REUSEPORT;
+ goto int_case;
+
+ case TARGET_SO_TYPE:
+ optname = SO_TYPE;
+ goto int_case;
+
+ case TARGET_SO_ERROR:
+ optname = SO_ERROR;
+ goto int_case;
+
+ case TARGET_SO_DONTROUTE:
+ optname = SO_DONTROUTE;
+ goto int_case;
+
+ case TARGET_SO_BROADCAST:
+ optname = SO_BROADCAST;
+ goto int_case;
+
+ case TARGET_SO_SNDBUF:
+ optname = SO_SNDBUF;
+ goto int_case;
+
+ case TARGET_SO_RCVBUF:
+ optname = SO_RCVBUF;
+ goto int_case;
+
+ case TARGET_SO_KEEPALIVE:
+ optname = SO_KEEPALIVE;
+ goto int_case;
+
+ case TARGET_SO_OOBINLINE:
+ optname = SO_OOBINLINE;
+ goto int_case;
+
+ case TARGET_SO_TIMESTAMP:
+ optname = SO_TIMESTAMP;
+ goto int_case;
+
+ case TARGET_SO_RCVLOWAT:
+ optname = SO_RCVLOWAT;
+ goto int_case;
+
+ case TARGET_SO_LISTENINCQLEN:
+ optname = SO_LISTENINCQLEN;
+ goto int_case;
+
+ default:
+int_case:
+ if (get_user_u32(len, optlen)) {
+ return -TARGET_EFAULT;
+ }
+ if (len < 0) {
+ return -TARGET_EINVAL;
+ }
+ lv = sizeof(lv);
+ ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
+ if (ret < 0) {
+ return ret;
+ }
+ if (len > lv) {
+ len = lv;
+ }
+ if (len == 4) {
+ if (put_user_u32(val, optval_addr)) {
+ return -TARGET_EFAULT;
+ }
+ } else {
+ if (put_user_u8(val, optval_addr)) {
+ return -TARGET_EFAULT;
+ }
+ }
+ if (put_user_u32(len, optlen)) {
+ return -TARGET_EFAULT;
+ }
+ break;
+
+ }
+ break;
+
+ case IPPROTO_TCP:
+ /* TCP options all take an 'int' value. */
+ goto int_case;
+
+ case IPPROTO_IP:
+ switch (optname) {
+ case IP_HDRINCL:
+ case IP_TOS:
+ case IP_TTL:
+ case IP_RECVOPTS:
+ case IP_RECVRETOPTS:
+ case IP_RECVDSTADDR:
+
+ case IP_RETOPTS:
+#if defined(__FreeBSD_version) && __FreeBSD_version > 900000 &&
defined(IP_RECVTOS)
+ case IP_RECVTOS:
+#endif
+ case IP_MULTICAST_TTL:
+ case IP_MULTICAST_LOOP:
+ case IP_PORTRANGE:
+ case IP_IPSEC_POLICY:
+ case IP_FAITH:
+ case IP_ONESBCAST:
+ case IP_BINDANY:
+ if (get_user_u32(len, optlen)) {
+ return -TARGET_EFAULT;
+ }
+ if (len < 0) {
+ return -TARGET_EINVAL;
+ }
+ lv = sizeof(lv);
+ ret = get_errno(getsockopt(sockfd, level, optname,
+ &val, &lv));
+ if (ret < 0) {
+ return ret;
+ }
+ if (len < sizeof(int) && len > 0 && val >= 0 &&
+ val < 255) {
+ len = 1;
+ if (put_user_u32(len, optlen) ||
+ put_user_u8(val, optval_addr)) {
+ return -TARGET_EFAULT;
+ }
+ } else {
+ if (len > sizeof(int)) {
+ len = sizeof(int);
+ }
+ if (put_user_u32(len, optlen) ||
+ put_user_u32(val, optval_addr)) {
+ return -TARGET_EFAULT;
+ }
+ }
+ break;
+
+ default:
+ goto unimplemented;
+ }
+ break;
+
+ default:
+unimplemented:
+ gemu_log("getsockopt level=%d optname=%d not yet supported\n",
+ level, optname);
+ ret = -TARGET_EOPNOTSUPP;
+ break;
+ }
+ return ret;
+}
+
+/* setfib(2) */
+static inline abi_long do_freebsd_setfib(abi_long fib)
+{
+
+ return get_errno(setfib(fib));
+}
+
+/* sctp_peeloff(2) */
+static inline abi_long do_freebsd_sctp_peeloff(abi_long s, abi_ulong id)
+{
+
+ qemu_log("qemu: Unsupported syscall sctp_peeloff()\n");
+ return -TARGET_ENOSYS;
+}
+
+/* sctp_generic_sendmsg(2) */
+static inline abi_long do_freebsd_sctp_generic_sendmsg(abi_long s,
+ abi_ulong target_msg, abi_long msglen, abi_ulong target_to,
+ abi_ulong len, abi_ulong target_sinfo, abi_long flags)
+{
+
+ qemu_log("qemu: Unsupported syscall sctp_generic_sendmsg()\n");
+ return -TARGET_ENOSYS;
+}
+
+/* sctp_generic_recvmsg(2) */
+static inline abi_long do_freebsd_sctp_generic_recvmsg(abi_long s,
+ abi_ulong target_iov, abi_long iovlen, abi_ulong target_from,
+ abi_ulong fromlen, abi_ulong target_sinfo, abi_ulong target_msgflags)
+{
+
+ qemu_log("qemu: Unsupported syscall sctp_generic_recvmsg()\n");
+ return -TARGET_ENOSYS;
+}
+
+/* freebsd4_sendfile(2) */
+static inline abi_long do_freebsd_freebsd4_sendfile(abi_long fd, abi_long s,
+ abi_ulong arg3, abi_ulong arg4, abi_ulong nbytes, abi_ulong
target_hdtr,
+ abi_ulong target_sbytes, abi_long flags)
+{
+
+ qemu_log("qemu: Unsupported syscall freebsd4_sendfile()\n");
+ return -TARGET_ENOSYS;
+}
+
+/* sendfile(2) */
+static inline abi_long do_freebsd_sendfile(abi_long fd, abi_long s,
+ abi_ulong arg3, abi_ulong arg4, abi_ulong nbytes, abi_ulong
target_hdtr,
+ abi_ulong target_sbytes, abi_long flags)
+{
+
+ qemu_log("qemu: Unsupported syscall sendfile()\n");
+ return -TARGET_ENOSYS;
+}
+
+#endif /* !__FREEBSD_SOCKET_H_ */
diff --git a/bsd-user/freebsd/qemu-os.h b/bsd-user/freebsd/qemu-os.h
index e915246..90d8eb4 100644
--- a/bsd-user/freebsd/qemu-os.h
+++ b/bsd-user/freebsd/qemu-os.h
@@ -50,6 +50,12 @@ abi_ulong copy_from_user_fdset_ptr(fd_set *fds, fd_set
**fds_ptr,
abi_long copy_to_user_fdset(abi_ulong target_fds_addr, const fd_set *fds,
int n);
+/* os-socket.c */
+abi_long t2h_freebsd_cmsg(struct msghdr *msgh,
+ struct target_msghdr *target_msgh);
+abi_long h2t_freebsd_cmsg(struct target_msghdr *target_msgh,
+ struct msghdr *msgh);
+
/* os-stat.c */
abi_long h2t_freebsd_stat(abi_ulong target_addr, struct stat *host_st);
abi_long h2t_freebsd_nstat(abi_ulong target_addr, struct stat *host_st);
diff --git a/bsd-user/netbsd/os-socket.c b/bsd-user/netbsd/os-socket.c
new file mode 100644
index 0000000..d983c34
--- /dev/null
+++ b/bsd-user/netbsd/os-socket.c
@@ -0,0 +1 @@
+/* XXX NetBSD socket related helpers */
diff --git a/bsd-user/netbsd/os-socket.h b/bsd-user/netbsd/os-socket.h
new file mode 100644
index 0000000..a49c41d
--- /dev/null
+++ b/bsd-user/netbsd/os-socket.h
@@ -0,0 +1,98 @@
+/*
+ * NetBSD socket related system call shims
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __NETBSD_SOCKET_H_
+#define __NETBSD_SOCKET_H_
+
+/*
+ * XXX To support FreeBSD binaries on NetBSD these syscalls will need
+ * to be emulated.
+ */
+
+/* sendmsg(2) */
+static inline abi_long do_freebsd_sendmsg(int fd, abi_ulong target_msg,
+ int flags)
+{
+
+ qemu_log("qemu: Unsupported syscall sendmsg()\n");
+ return -TARGET_ENOSYS;
+}
+
+/* recvmsg(2) */
+static inline abi_long do_freebsd_recvmsg(int fd, abi_ulong target_msg,
+ int flags)
+{
+
+ qemu_log("qemu: Unsupported syscall recvmsg()\n");
+ return -TARGET_ENOSYS;
+}
+
+/* setsockopt(2) */
+static inline abi_long do_bsd_setsockopt(int sockfd, int level, int optname,
+ abi_ulong optval_addr, socklen_t optlen)
+{
+
+ qemu_log("qemu: Unsupported syscall setsockopt()\n");
+ return -TARGET_ENOSYS;
+}
+
+/* getsockopt(2) */
+static inline abi_long do_bsd_getsockopt(int sockfd, int level, int optname,
+ abi_ulong optval_addr, abi_ulong optlen)
+{
+
+ qemu_log("qemu: Unsupported syscall getsockopt()\n");
+ return -TARGET_ENOSYS;
+}
+
+/* setfib(2) */
+static inline abi_long do_freebsd_setfib(abi_long fib)
+{
+
+ qemu_log("qemu: Unsupported syscall setfib()\n");
+ return -TARGET_ENOSYS;
+}
+
+/* sctp_peeloff(2) */
+static inline abi_long do_freebsd_sctp_peeloff(abi_long s, abi_ulong id)
+{
+
+ qemu_log("qemu: Unsupported syscall sctp_peeloff()\n");
+ return -TARGET_ENOSYS;
+}
+
+/* sctp_generic_sendmsg(2) */
+static inline abi_long do_freebsd_sctp_generic_sendmsg(abi_long s,
+ abi_ulong target_msg, abi_long msglen, abi_ulong target_to,
+ abi_ulong len, abi_ulong target_sinfo, abi_long flags)
+{
+
+ qemu_log("qemu: Unsupported syscall sctp_generic_sendmsg()\n");
+ return -TARGET_ENOSYS;
+}
+
+/* sctp_generic_recvmsg(2) */
+static inline abi_long do_freebsd_sctp_generic_recvmsg(abi_long s,
+ abi_ulong target_iov, abi_long iovlen, abi_ulong target_from,
+ abi_ulong fromlen, abi_ulong target_sinfo, abi_ulong target_msgflags)
+{
+
+ qemu_log("qemu: Unsupported syscall sctp_generic_recvmsg()\n");
+ return -TARGET_ENOSYS;
+}
+
+#endif /* !__NETBSD_SOCKET_H_ */
diff --git a/bsd-user/openbsd/os-socket.c b/bsd-user/openbsd/os-socket.c
new file mode 100644
index 0000000..183002d
--- /dev/null
+++ b/bsd-user/openbsd/os-socket.c
@@ -0,0 +1 @@
+/* XXX OpenBSD socket related helpers */
diff --git a/bsd-user/openbsd/os-socket.h b/bsd-user/openbsd/os-socket.h
new file mode 100644
index 0000000..b8b1e99
--- /dev/null
+++ b/bsd-user/openbsd/os-socket.h
@@ -0,0 +1,98 @@
+/*
+ * OpenBSD socket related system call shims
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __OPENBSD_SOCKET_H_
+#define __OPENBSD_SOCKET_H_
+
+/*
+ * XXX To support FreeBSD binaries on OpenBSD these syscalls will need
+ * to be emulated.
+ */
+
+/* sendmsg(2) */
+static inline abi_long do_freebsd_sendmsg(int fd, abi_ulong target_msg,
+ int flags)
+{
+
+ qemu_log("qemu: Unsupported syscall sendmsg()\n");
+ return -TARGET_ENOSYS;
+}
+
+/* recvmsg(2) */
+static inline abi_long do_freebsd_recvmsg(int fd, abi_ulong target_msg,
+ int flags)
+{
+
+ qemu_log("qemu: Unsupported syscall recvmsg()\n");
+ return -TARGET_ENOSYS;
+}
+
+/* setsockopt(2) */
+static inline abi_long do_bsd_setsockopt(int sockfd, int level, int optname,
+ abi_ulong optval_addr, socklen_t optlen)
+{
+
+ qemu_log("qemu: Unsupported syscall setsockopt()\n");
+ return -TARGET_ENOSYS;
+}
+
+/* getsockopt(2) */
+static inline abi_long do_bsd_getsockopt(int sockfd, int level, int optname,
+ abi_ulong optval_addr, abi_ulong optlen)
+{
+
+ qemu_log("qemu: Unsupported syscall getsockopt()\n");
+ return -TARGET_ENOSYS;
+}
+
+/* setfib(2) */
+static inline abi_long do_freebsd_setfib(abi_long fib)
+{
+
+ qemu_log("qemu: Unsupported syscall setfib()\n");
+ return -TARGET_ENOSYS;
+}
+
+/* sctp_peeloff(2) */
+static inline abi_long do_freebsd_sctp_peeloff(abi_long s, abi_ulong id)
+{
+
+ qemu_log("qemu: Unsupported syscall sctp_peeloff()\n");
+ return -TARGET_ENOSYS;
+}
+
+/* sctp_generic_sendmsg(2) */
+static inline abi_long do_freebsd_sctp_generic_sendmsg(abi_long s,
+ abi_ulong target_msg, abi_long msglen, abi_ulong target_to,
+ abi_ulong len, abi_ulong target_sinfo, abi_long flags)
+{
+
+ qemu_log("qemu: Unsupported syscall sctp_generic_sendmsg()\n");
+ return -TARGET_ENOSYS;
+}
+
+/* sctp_generic_recvmsg(2) */
+static inline abi_long do_freebsd_sctp_generic_recvmsg(abi_long s,
+ abi_ulong target_iov, abi_long iovlen, abi_ulong target_from,
+ abi_ulong fromlen, abi_ulong target_sinfo, abi_ulong target_msgflags)
+{
+
+ qemu_log("qemu: Unsupported syscall sctp_generic_recvmsg()\n");
+ return -TARGET_ENOSYS;
+}
+
+#endif /* !__OPENBSD_SOCKET_H_ */
diff --git a/bsd-user/qemu-bsd.h b/bsd-user/qemu-bsd.h
index f562aad..09b99ef 100644
--- a/bsd-user/qemu-bsd.h
+++ b/bsd-user/qemu-bsd.h
@@ -50,4 +50,12 @@ abi_long host_to_target_rusage(abi_ulong target_addr,
const struct rusage *rusage);
int host_to_target_waitstatus(int status);
+/* bsd-socket.c */
+abi_long target_to_host_sockaddr(struct sockaddr *addr, abi_ulong target_addr,
+ socklen_t len);
+abi_long host_to_target_sockaddr(abi_ulong target_addr, struct sockaddr *addr,
+ socklen_t len);
+abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn, abi_ulong target_addr,
+ socklen_t len);
+
#endif /* !_QEMU_BSD_H_ */
diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c
index e3967fa..286c71e 100644
--- a/bsd-user/syscall.c
+++ b/bsd-user/syscall.c
@@ -39,11 +39,13 @@ static int host_to_target_errno(int err);
#include "bsd-mem.h"
#include "bsd-proc.h"
#include "bsd-signal.h"
+#include "bsd-socket.h"
/* *BSD dependent syscall shims */
#include "os-time.h"
#include "os-proc.h"
#include "os-signal.h"
+#include "os-socket.h"
#include "os-stat.h"
/* #define DEBUG */
@@ -1017,6 +1019,97 @@ abi_long do_freebsd_syscall(void *cpu_env, int num,
abi_long arg1,
break;
/*
+ * socket related system calls
+ */
+ case TARGET_FREEBSD_NR_accept: /* accept(2) */
+ ret = do_bsd_accept(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_bind: /* bind(2) */
+ ret = do_bsd_bind(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_connect: /* connect(2) */
+ ret = do_bsd_connect(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_getpeername: /* getpeername(2) */
+ ret = do_bsd_getpeername(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_getsockname: /* getsockname(2) */
+ ret = do_bsd_getsockname(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_getsockopt: /* getsockopt(2) */
+ ret = do_bsd_getsockopt(arg1, arg2, arg3, arg4, arg5);
+ break;
+
+ case TARGET_FREEBSD_NR_setsockopt: /* setsockopt(2) */
+ ret = do_bsd_setsockopt(arg1, arg2, arg3, arg4, arg5);
+ break;
+
+ case TARGET_FREEBSD_NR_listen: /* listen(2) */
+ ret = get_errno(listen(arg1, arg2));
+ break;
+
+ case TARGET_FREEBSD_NR_recvfrom: /* recvfrom(2) */
+ ret = do_bsd_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
+ break;
+
+ case TARGET_FREEBSD_NR_recvmsg: /* recvmsg(2) */
+ ret = do_freebsd_recvmsg(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_sendmsg: /* sendmsg(2) */
+ ret = do_freebsd_sendmsg(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_sendto: /* sendto(2) */
+ ret = do_bsd_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
+ break;
+
+ case TARGET_FREEBSD_NR_socket: /* socket(2) */
+ ret = do_bsd_socket(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_socketpair: /* socketpair(2) */
+ ret = do_bsd_socketpair(arg1, arg2, arg3, arg4);
+ break;
+
+ case TARGET_FREEBSD_NR_shutdown: /* shutdown(2) */
+ ret = do_bsd_shutdown(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_setfib: /* setfib(2) */
+ ret = do_freebsd_setfib(arg1);
+ break;
+
+ case TARGET_FREEBSD_NR_sctp_peeloff: /* sctp_peeloff(2) */
+ ret = do_freebsd_sctp_peeloff(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_sctp_generic_sendmsg: /* sctp_generic_sendmsg(2) */
+ ret = do_freebsd_sctp_generic_sendmsg(arg1, arg2, arg2, arg4, arg5,
+ arg6, arg7);
+ break;
+
+ case TARGET_FREEBSD_NR_sctp_generic_recvmsg: /* sctp_generic_recvmsg(2) */
+ ret = do_freebsd_sctp_generic_recvmsg(arg1, arg2, arg2, arg4, arg5,
+ arg6, arg7);
+ break;
+
+ case TARGET_FREEBSD_NR_sendfile: /* sendfile(2) */
+ ret = do_freebsd_sendfile(arg1, arg2, arg2, arg4, arg5, arg6, arg7,
+ arg8);
+ break;
+
+ case TARGET_FREEBSD_NR_freebsd4_sendfile: /* freebsd4_sendfile(2) */
+ ret = do_freebsd_freebsd4_sendfile(arg1, arg2, arg2, arg4, arg5,
+ arg6, arg7, arg8);
+ break;
+
+ /*
* sys{ctl, arch, call}
*/
case TARGET_FREEBSD_NR___sysctl: /* sysctl(3) */
--
1.7.8
- [Qemu-devel] [PATCH 05/18] bsd-user: move target arch and host OS dependent code out of syscall.c, (continued)
- [Qemu-devel] [PATCH 05/18] bsd-user: move target arch and host OS dependent code out of syscall.c, Stacey Son, 2013/10/16
- [Qemu-devel] [PATCH 09/18] bsd-user: add support for freebsd process related system calls, Stacey Son, 2013/10/16
- [Qemu-devel] [PATCH 10/18] bsd-user: add support for file system related system calls, Stacey Son, 2013/10/16
- [Qemu-devel] [PATCH 04/18] bsd-user: move target arch and host OS dependent code out of main.c, Stacey Son, 2013/10/16
- [Qemu-devel] [PATCH 11/18] bsd-user: add support for stat, directory, and file control related system calls, Stacey Son, 2013/10/16
- [Qemu-devel] [PATCH 08/18] bsd-user: move target arch and host OS dependent code out of elfload.c, Stacey Son, 2013/10/16
- [Qemu-devel] [PATCH 12/18] bsd-user: add support for memory management related system calls, Stacey Son, 2013/10/16
- [Qemu-devel] [PATCH 07/18] bsd-user: add support for freebsd signal related system calls, Stacey Son, 2013/10/16
- [Qemu-devel] [PATCH 13/18] bsd-user: add support for socket related system calls,
Stacey Son <=
- [Qemu-devel] [PATCH 15/18] bsd-user: add support for the ioctl system call, Stacey Son, 2013/10/16
- [Qemu-devel] [PATCH 14/18] bsd-user: add support for thread related system calls, Stacey Son, 2013/10/16
- [Qemu-devel] [PATCH 17/18] bsd-user: add support for miscellaneous system calls, Stacey Son, 2013/10/16
- [Qemu-devel] [PATCH 16/18] bsd-user: add support for extended attribute and ACL related syscalls, Stacey Son, 2013/10/16
- [Qemu-devel] [PATCH 18/18] bsd-user: add arm, mips and mips64 options to configure target-list, Stacey Son, 2013/10/16
- Re: [Qemu-devel] [PATCH 00/18] bsd-user: Add system call and mips/armsupport.., Alex Bennée, 2013/10/16