qemu-devel
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]