Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add the socket system call shims.

Includes accept, bind, connect, getpeername, getsockopt, setsockopt,
listen, recvfrom, recmsg, sendmsg, sendto, socket, and socketpair.
  • Loading branch information...
commit c322e2d6688393af11e96c73e37ade48551eefaf 1 parent 3f304df
Stacey Son authored
66 work/qemu-1.2.0/bsd-user/socket.h
View
@@ -0,0 +1,66 @@
+/*
+ * Target socket definitions.
+ */
+
+/*
+ * Types
+ */
+#define TARGET_SOCK_STREAM 1 /* stream socket */
+#define TARGET_SOCK_DGRAM 2 /* datagram socket */
+#define TARGET_SOCK_RAW 3 /* raw-protocol interface */
+#define TARGET_SOCK_RDM 4 /* reliably-delivered message */
+#define TARGET_SOCK_SEQPACKET 5 /* sequenced packet stream */
+
+
+/*
+ * Option flags per-socket.
+ */
+
+#define TARGET_SO_DEBUG 0x0001 /* turn on debugging info recording */
+#define TARGET_SO_ACCEPTCONN 0x0002 /* socket has had listen() */
+#define TARGET_SO_REUSEADDR 0x0004 /* allow local address reuse */
+#define TARGET_SO_KEEPALIVE 0x0008 /* keep connections alive */
+#define TARGET_SO_DONTROUTE 0x0010 /* just use interface addresses */
+#define TARGET_SO_BROADCAST 0x0020 /* permit sending of broadcast msgs */
+#define TARGET_SO_USELOOPBACK 0x0040 /* bypass hardware when possible */
+#define TARGET_SO_LINGER 0x0080 /* linger on close if data present */
+#define TARGET_SO_OOBINLINE 0x0100 /* leave received OOB data in line */
+#define TARGET_SO_REUSEPORT 0x0200 /* allow local address & port reuse */
+#define TARGET_SO_TIMESTAMP 0x0400 /* timestamp received dgram traffic */
+#define TARGET_SO_NOSIGPIPE 0x0800 /* no SIGPIPE from EPIPE */
+#define TARGET_SO_ACCEPTFILTER 0x1000 /* there is an accept filter */
+#define TARGET_SO_BINTIME 0x2000 /* timestamp received dgram traffic */
+#define TARGET_SO_NO_OFFLOAD 0x4000 /* socket cannot be offloaded */
+#define TARGET_SO_NO_DDP 0x8000 /* disable direct data placement */
+
+/*
+ * Additional options, not kept in so_options.
+ */
+#define TARGET_SO_SNDBUF 0x1001 /* send buffer size */
+#define TARGET_SO_RCVBUF 0x1002 /* receive buffer size */
+#define TARGET_SO_SNDLOWAT 0x1003 /* send low-water mark */
+#define TARGET_SO_RCVLOWAT 0x1004 /* receive low-water mark */
+#define TARGET_SO_SNDTIMEO 0x1005 /* send timeout */
+#define TARGET_SO_RCVTIMEO 0x1006 /* receive timeout */
+#define TARGET_SO_ERROR 0x1007 /* get error status and clear */
+#define TARGET_SO_TYPE 0x1008 /* get socket type */
+#define TARGET_SO_LABEL 0x1009 /* socket's MAC label */
+#define TARGET_SO_PEERLABEL 0x1010 /* socket's peer's MAC label */
+#define TARGET_SO_LISTENQLIMIT 0x1011 /* socket's backlog limit */
+#define TARGET_SO_LISTENQLEN 0x1012 /* socket's complete queue length */
+#define TARGET_SO_LISTENINCQLEN 0x1013 /* socket's incomplete queue length */
+#define TARGET_SO_SETFIB 0x1014 /* use this FIB to route */
+#define TARGET_SO_USER_COOKIE 0x1015 /* user cookie (dummynet etc.) */
+#define TARGET_SO_PROTOCOL 0x1016 /* get socket protocol (Linux name) */
+
+/* alias for SO_PROTOCOL (SunOS name) */
+#define TARGET_SO_PROTOTYPE TARGET_SO_PROTOCOL
+
+/*
+ * Level number for (get/set)sockopt() to apply to socket itself.
+ */
+#define TARGET_SOL_SOCKET 0xffff /* options for socket level */
+
+#ifndef CMSG_ALIGN
+#define CMSG_ALIGN(len) ( ((len)+sizeof(long)-1) & ~(sizeof(long)-1) )
+#endif
752 work/qemu-1.2.0/bsd-user/syscall.c
View
@@ -36,8 +36,12 @@
#include <sys/event.h>
#include <sys/mount.h>
#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/un.h>
#include <utime.h>
+#include <netinet/in.h>
+
#include "qemu.h"
#include "qemu-common.h"
@@ -340,6 +344,179 @@ static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
return 0;
}
+static inline 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)
+ return -TARGET_EFAULT;
+
+ sa_family = tswap16(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 (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;
+ unlock_user(target_saddr, target_addr, 0);
+
+ return (0);
+}
+
+static inline 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)
+ return (-TARGET_EFAULT);
+ memcpy(target_saddr, addr, len);
+ target_saddr->sa_family = tswap16(addr->sa_family);
+ unlock_user(target_saddr, target_addr, len);
+
+ return (0);
+}
+
+static inline abi_long
+target_to_host_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)
+ 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);
+}
+
+static inline abi_long
+host_to_target_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)
+ 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_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);
+ 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);
+}
+
static inline rlim_t
target_to_host_rlim(abi_ulong target_rlim)
{
@@ -676,6 +853,287 @@ unimplemented(int num)
return (-TARGET_ENOSYS);
}
+/* do_bind() must return target values and target errnos. */
+static abi_long
+do_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 (ret)
+ return (ret);
+
+ return get_errno(bind(sockfd, addr, addrlen));
+}
+
+/* do_connect() must return target values and target errnos. */
+static abi_long
+do_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 (ret)
+ return (ret);
+
+ return (get_errno(connect(sockfd, addr, addrlen)));
+}
+
+/* do_sendrecvmsg() must return target values and target errnos. */
+static abi_long
+do_sendrecvmsg(int fd, abi_ulong target_msg, int flags, int send)
+{
+ abi_long ret, len;
+ struct target_msghdr *msgp;
+ struct msghdr msg;
+ int count;
+ struct iovec *vec;
+ abi_ulong target_vec;
+
+ if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE, msgp,
+ target_msg, send ? 1 : 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 (ret) {
+ unlock_user_struct(msgp, target_msg, send ? 0 : 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(send ? VERIFY_READ : VERIFY_WRITE, vec, target_vec, count,
+ send);
+ msg.msg_iovlen = count;
+ msg.msg_iov = vec;
+
+ if (send) {
+ ret = target_to_host_cmsg(&msg, msgp);
+ if (0 == ret)
+ ret = get_errno(sendmsg(fd, &msg, flags));
+ } else {
+ ret = get_errno(recvmsg(fd, &msg, flags));
+ if (!is_error(ret)) {
+ len = ret;
+ ret = host_to_target_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 (ret)
+ goto out;
+ }
+ }
+ ret = len;
+ }
+ }
+out:
+ unlock_iovec(vec, target_vec, count, !send);
+ unlock_user_struct(msgp, target_msg, send ? 0 : 1);
+ return (ret);
+}
+
+/* do_accept() must return target values and target errnos. */
+static abi_long
+do_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);
+}
+
+/* do_getpeername() must return target values and target errnos. */
+static abi_long
+do_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);
+}
+
+/* do_getsockname() must return target values and target errnos. */
+static abi_long
+do_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);
+}
+
+/* do_socketpair() must return target values and target errnos. */
+static abi_long
+do_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);
+}
+
+/* do_sendto() must return target values and target errnos. */
+static abi_long
+do_sendto(int fd, abi_ulong msg, size_t len, int flags, abi_ulong target_addr,
+ socklen_t addrlen)
+{
+ void *addr;
+ 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) {
+ addr = alloca(addrlen);
+ ret = target_to_host_sockaddr(addr, target_addr, addrlen);
+ if (ret) {
+ unlock_user(host_msg, msg, 0);
+ return (ret);
+ }
+ ret = get_errno(sendto(fd, host_msg, len, flags, addr,
+ addrlen));
+ } else {
+ ret = get_errno(send(fd, host_msg, len, flags));
+ }
+ unlock_user(host_msg, msg, 0);
+ return (ret);
+}
+
+/* do_recvfrom() must return target values and target errnos. */
+static abi_long
+do_recvfrom(int fd, abi_ulong msg, size_t len, int flags, abi_ulong target_addr,
+ abi_ulong target_addrlen)
+{
+ socklen_t addrlen;
+ void *addr;
+ 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;
+ }
+ addr = alloca(addrlen);
+ ret = get_errno(recvfrom(fd, host_msg, len, flags, addr,
+ &addrlen));
+ } else {
+ addr = 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, addr, 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);
+}
+
/* do_freebsd_select() must return target values and target errnos. */
static abi_long
do_freebsd_select(int n, abi_ulong rfd_addr, abi_ulong wfd_addr,
@@ -722,6 +1180,230 @@ do_freebsd_select(int n, abi_ulong rfd_addr, abi_ulong wfd_addr,
return (ret);
}
+/* do_getsockopt() must return target values and target errnos. */
+static abi_long
+do_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;
+
+ default:
+unimplemented:
+ gemu_log("getsockopt level=%d optname=%d not yet supported\n",
+ level, optname);
+ ret = -TARGET_EOPNOTSUPP;
+ break;
+ }
+ return (ret);
+}
+
+/* do_setsockopt() must return target values and target errnos. */
+static abi_long
+do_setsockopt(int sockfd, int level, int optname, abi_ulong optval_addr,
+ socklen_t optlen)
+{
+ abi_long ret;
+
+ switch(level) {
+ 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;
+
+ case TARGET_SO_USER_COOKIE:
+ optname = SO_USER_COOKIE;
+ break;
+
+ default:
+ goto unimplemented;
+ }
+ break;
+
+ default:
+unimplemented:
+ gemu_log("Unsupported setsockopt level=%d optname=%d\n",
+ level, optname);
+ ret = -TARGET_ENOPROTOOPT;
+ }
+
+ return (ret);
+}
+
/* do_syscall() should always have a single exit point at the end so
that actions, such as logging of syscall results, can be performed.
All errnos that do_syscall() returns must be -TARGET_<errcode>. */
@@ -1821,6 +2503,62 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
}
break;
+ case TARGET_FREEBSD_NR_accept:
+ ret = do_accept(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_bind:
+ ret = do_bind(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_connect:
+ ret = do_connect(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_getpeername:
+ ret = do_getpeername(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_getsockname:
+ ret = do_getsockname(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_getsockopt:
+ ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5);
+ break;
+
+ case TARGET_FREEBSD_NR_setsockopt:
+ ret = do_setsockopt(arg1, arg2, arg3, arg4, arg5);
+ break;
+
+ case TARGET_FREEBSD_NR_listen:
+ ret = get_errno(listen(arg1, arg2));
+ break;
+
+ case TARGET_FREEBSD_NR_recvfrom:
+ ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
+ break;
+
+ case TARGET_FREEBSD_NR_recvmsg:
+ ret = do_sendrecvmsg(arg1, arg2, arg3, 0);
+ break;
+
+ case TARGET_FREEBSD_NR_sendmsg:
+ ret = do_sendrecvmsg(arg1, arg2, arg3, 1);
+ break;
+
+ case TARGET_FREEBSD_NR_sendto:
+ ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
+ break;
+
+ case TARGET_FREEBSD_NR_socket:
+ ret = get_errno(socket(arg1, arg2, arg3));
+ break;
+
+ case TARGET_FREEBSD_NR_socketpair:
+ ret = do_socketpair(arg1, arg2, arg3, arg4);
+ break;
+
case TARGET_FREEBSD_NR_kill:
case TARGET_FREEBSD_NR_sigaction:
case TARGET_FREEBSD_NR_sigprocmask:
@@ -1837,20 +2575,6 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
case TARGET_FREEBSD_NR_getpriority:
case TARGET_FREEBSD_NR_setpriority:
- case TARGET_FREEBSD_NR_accept:
- case TARGET_FREEBSD_NR_bind:
- case TARGET_FREEBSD_NR_connect:
- case TARGET_FREEBSD_NR_getpeername:
- case TARGET_FREEBSD_NR_getsockname:
- case TARGET_FREEBSD_NR_getsockopt:
- /* case TARGET_FREEBSD_NR_listen: */
- case TARGET_FREEBSD_NR_recvfrom:
- case TARGET_FREEBSD_NR_recvmsg:
- case TARGET_FREEBSD_NR_sendmsg:
- case TARGET_FREEBSD_NR_sendto:
- /* case TARGET_FREEBSD_NR_socket: */
- case TARGET_FREEBSD_NR_socketpair:
-
case TARGET_FREEBSD_NR_swapon:
case TARGET_FREEBSD_NR_swapoff:
54 work/qemu-1.2.0/bsd-user/syscall_defs.h
View
@@ -178,6 +178,7 @@ struct target_rlimit {
#define TARGET_O_ASYNC 0x00000040
#define TARGET_O_DIRECT 0x00010000
+#include "socket.h"
#include "errno_defs.h"
#include "freebsd/syscall_nr.h"
@@ -198,6 +199,59 @@ struct target_iovec {
abi_long iov_len; /* Number of bytes */
};
+struct target_msghdr {
+ abi_long msg_name; /* Socket name */
+ int msg_namelen; /* Length of name */
+ abi_long msg_iov; /* Data blocks */
+ abi_long msg_iovlen; /* Number of blocks */
+ abi_long msg_control; /* Per protocol magic
+ (eg BSD file descriptor passing) */
+ abi_long msg_controllen; /* Length of cmsg list */
+ int msg_flags; /* flags on received message */
+};
+
+struct target_cmsghdr {
+ abi_long cmsg_len;
+ int cmsg_level;
+ int cmsg_type;
+};
+
+#define TARGET_CMSG_DATA(cmsg) \
+ ((unsigned char *) ((struct target_cmsghdr *) (cmsg) + 1))
+#define TARGET_CMSG_NXTHDR(mhdr, cmsg) __target_cmsg_nxthdr (mhdr, cmsg)
+#define TARGET_CMSG_ALIGN(len) (((len) + sizeof (abi_long) - 1) \
+ & (size_t) ~(sizeof (abi_long) - 1))
+#define TARGET_CMSG_SPACE(len) (TARGET_CMSG_ALIGN (len) \
+ + TARGET_CMSG_ALIGN (sizeof (struct target_cmsghdr)))
+#define TARGET_CMSG_LEN(len) \
+ (TARGET_CMSG_ALIGN (sizeof (struct target_cmsghdr)) + (len))
+
+static __inline__ struct target_cmsghdr *
+__target_cmsg_nxthdr (struct target_msghdr *__mhdr,
+ struct target_cmsghdr *__cmsg)
+{
+ struct target_cmsghdr *__ptr;
+
+ __ptr = (struct target_cmsghdr *)((unsigned char *) __cmsg +
+ TARGET_CMSG_ALIGN (tswapal(__cmsg->cmsg_len)));
+ if ((unsigned long)((char *)(__ptr+1) -
+ (char *)(size_t)tswapal(__mhdr->msg_control)) >
+ tswapal(__mhdr->msg_controllen))
+ /* No more entries. */
+ return ((struct target_cmsghdr *)0);
+ return (__cmsg);
+}
+
+struct target_sockaddr {
+ uint16_t sa_family;
+ uint8_t sa_data[14];
+};
+
+struct target_in_addr {
+ uint32_t s_addr; /* big endian */
+};
+
+
struct target_timeval {
abi_long tv_sec;
abi_long tv_usec;
Please sign in to comment.
Something went wrong with that request. Please try again.