Module Name: src
Committed By: stacktic
Date: Sat Jun 1 10:09:05 UTC 2013
Modified Files:
src/sys/rump/net/lib/libsockin: rumpcomp_user.c
Log Message:
Translate function parameters between the hypervisor and rump kernel
To generate a diff of this commit:
cvs rdiff -u -r1.5 -r1.6 src/sys/rump/net/lib/libsockin/rumpcomp_user.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/rump/net/lib/libsockin/rumpcomp_user.c
diff -u src/sys/rump/net/lib/libsockin/rumpcomp_user.c:1.5 src/sys/rump/net/lib/libsockin/rumpcomp_user.c:1.6
--- src/sys/rump/net/lib/libsockin/rumpcomp_user.c:1.5 Tue Apr 30 12:39:21 2013
+++ src/sys/rump/net/lib/libsockin/rumpcomp_user.c Sat Jun 1 10:09:05 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: rumpcomp_user.c,v 1.5 2013/04/30 12:39:21 pooka Exp $ */
+/* $NetBSD: rumpcomp_user.c,v 1.6 2013/06/01 10:09:05 stacktic Exp $ */
/*
* Copyright (c) 2008 Antti Kantee. All Rights Reserved.
@@ -32,18 +32,388 @@
#include <errno.h>
#include <poll.h>
+#include <stdint.h>
+
#include <rump/rumpuser_component.h>
+#include <rump/rumpdefs.h>
#include "rumpcomp_user.h"
#define seterror(_v_) if ((_v_) == -1) rv = errno; else rv = 0;
+#ifndef __arraycount
+#define __arraycount(a) (sizeof(a) / sizeof(*a))
+#endif
+
+#ifndef __UNCONST
+#define __UNCONST(a) ((void*)(const void*)a)
+#endif
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+
+static int translate_so_sockopt(int);
+static int translate_ip_sockopt(int);
+static int translate_tcp_sockopt(int);
+static int translate_domain(int);
+
+#define translate(_a_) case RUMP_##_a_: return _a_
+static int
+translate_so_sockopt(int lopt)
+{
+
+ switch (lopt) {
+ translate(SO_DEBUG);
+#ifndef SO_REUSEPORT
+ case RUMP_SO_REUSEPORT: return SO_REUSEADDR;
+#else
+ translate(SO_REUSEPORT);
+#endif
+ translate(SO_TYPE);
+ translate(SO_ERROR);
+ translate(SO_DONTROUTE);
+ translate(SO_BROADCAST);
+ translate(SO_SNDBUF);
+ translate(SO_RCVBUF);
+ translate(SO_KEEPALIVE);
+ translate(SO_OOBINLINE);
+ translate(SO_LINGER);
+ default: return -1;
+ }
+}
+
+static int
+translate_ip_sockopt(int lopt)
+{
+
+ switch (lopt) {
+ translate(IP_TOS);
+ translate(IP_TTL);
+ translate(IP_HDRINCL);
+ translate(IP_MULTICAST_TTL);
+ translate(IP_MULTICAST_LOOP);
+ translate(IP_MULTICAST_IF);
+ translate(IP_ADD_MEMBERSHIP);
+ translate(IP_DROP_MEMBERSHIP);
+ default: return -1;
+ }
+}
+
+static int
+translate_tcp_sockopt(int lopt)
+{
+
+ switch (lopt) {
+ translate(TCP_NODELAY);
+ translate(TCP_MAXSEG);
+ default: return -1;
+ }
+}
+
+static int
+translate_domain(int domain)
+{
+
+ switch (domain) {
+ translate(AF_UNIX);
+ translate(AF_INET);
+ translate(AF_SNA);
+ translate(AF_DECnet);
+ translate(AF_APPLETALK);
+ translate(AF_IPX);
+ translate(AF_INET6);
+ translate(AF_ISDN);
+ translate(AF_BLUETOOTH);
+ translate(AF_ROUTE);
+ default: return AF_UNSPEC;
+ }
+}
+
+#undef translate
+#define translate_back(_a_) case _a_: return RUMP_##_a_
+static int translate_domain_back(int);
+static int
+translate_domain_back(int domain)
+{
+
+ switch (domain) {
+ translate_back(AF_UNIX);
+ translate_back(AF_INET);
+ translate_back(AF_SNA);
+ translate_back(AF_DECnet);
+ translate_back(AF_APPLETALK);
+ translate_back(AF_IPX);
+ translate_back(AF_INET6);
+ translate_back(AF_ISDN);
+ translate_back(AF_BLUETOOTH);
+ translate_back(AF_ROUTE);
+ default: return RUMP_AF_UNSPEC;
+ }
+}
+
+#undef translate_back
+
+static void
+translate_sockopt(int *levelp, int *namep)
+{
+ int level, name;
+
+ level = *levelp;
+ name = *namep;
+
+ switch (level) {
+ case RUMP_SOL_SOCKET:
+ level = SOL_SOCKET;
+ name = translate_so_sockopt(name);
+ break;
+ case RUMP_IPPROTO_IP:
+#ifdef SOL_IP
+ level = SOL_IP;
+#else
+ level = IPPROTO_IP;
+#endif
+ name = translate_ip_sockopt(name);
+ break;
+ case RUMP_IPPROTO_TCP:
+#ifdef SOL_TCP
+ level = SOL_TCP;
+#else
+ level = IPPROTO_TCP;
+#endif
+ name = translate_tcp_sockopt(name);
+ break;
+ case RUMP_IPPROTO_UDP:
+#ifdef SOL_UDP
+ level = SOL_UDP;
+#else
+ level = IPPROTO_UDP;
+#endif
+ name = -1;
+ break;
+ default:
+ level = -1;
+ }
+ *levelp = level;
+ *namep = name;
+}
+
+#ifndef __NetBSD__
+static const struct {
+ int bfl;
+ int lfl;
+} bsd_to_native_msg_flags_[] = {
+ {RUMP_MSG_OOB, MSG_OOB},
+ {RUMP_MSG_PEEK, MSG_PEEK},
+ {RUMP_MSG_DONTROUTE, MSG_DONTROUTE},
+ {RUMP_MSG_EOR, MSG_EOR},
+ {RUMP_MSG_TRUNC, MSG_TRUNC},
+ {RUMP_MSG_CTRUNC, MSG_CTRUNC},
+ {RUMP_MSG_WAITALL, MSG_WAITALL},
+ {RUMP_MSG_DONTWAIT, MSG_DONTWAIT},
+ {RUMP_MSG_NOSIGNAL, MSG_NOSIGNAL},
+};
+
+static int native_to_bsd_msg_flags(int);
+
+static int
+native_to_bsd_msg_flags(int lflag)
+{
+ unsigned int i;
+ int bfl, lfl;
+ int bflag = 0;
+
+ if (lflag == 0)
+ return (0);
+
+ for(i = 0; i < __arraycount(bsd_to_native_msg_flags_); i++) {
+ bfl = bsd_to_native_msg_flags_[i].bfl;
+ lfl = bsd_to_native_msg_flags_[i].lfl;
+
+ if (lflag & lfl) {
+ lflag ^= lfl;
+ bflag |= bfl;
+ }
+ }
+ if (lflag != 0)
+ return (-1);
+
+ return (bflag);
+}
+
+static int
+bsd_to_native_msg_flags(int bflag)
+{
+ unsigned int i;
+ int lflag = 0;
+
+ if (bflag == 0)
+ return (0);
+
+ for(i = 0; i < __arraycount(bsd_to_native_msg_flags_); i++) {
+ if (bflag & bsd_to_native_msg_flags_[i].bfl)
+ lflag |= bsd_to_native_msg_flags_[i].lfl;
+ }
+
+ return (lflag);
+}
+#endif
+
+struct rump_sockaddr {
+ __uint8_t sa_len; /* total length */
+ __uint8_t sa_family; /* address family */
+ char sa_data[14]; /* actually longer; address value */
+};
+
+struct rump_msghdr {
+ void *msg_name; /* optional address */
+ uint32_t msg_namelen; /* size of address */
+ struct iovec *msg_iov; /* scatter/gather array */
+ int msg_iovlen; /* # elements in msg_iov */
+ void *msg_control; /* ancillary data, see below */
+ uint32_t msg_controllen; /* ancillary data buffer len */
+ int msg_flags; /* flags on received message */
+};
+
+static struct sockaddr *translate_sockaddr(const struct sockaddr *,
+ uint32_t);
+static void translate_sockaddr_back(const struct sockaddr *,
+ struct rump_sockaddr *, uint32_t len);
+static struct msghdr *translate_msghdr(const struct rump_msghdr *, int *);
+static void translate_msghdr_back(const struct msghdr *, struct rump_msghdr *);
+
+#if defined(__NetBSD__)
+static struct sockaddr *
+translate_sockaddr(const struct sockaddr *addr, uint32_t len)
+{
+
+ return (struct sockaddr *)__UNCONST(addr);
+}
+
+static void
+translate_sockaddr_back(const struct sockaddr *laddr,
+ struct rump_sockaddr *baddr, uint32_t len)
+{
+
+ return;
+}
+
+static struct msghdr *
+translate_msghdr(const struct rump_msghdr *bmsg, int *flags)
+{
+
+ return (struct msghdr *)__UNCONST(bmsg);
+}
+
+static void
+translate_msghdr_back(const struct msghdr *lmsg, struct rump_msghdr *bmsg)
+{
+
+ return;
+}
+
+#else
+static struct sockaddr *
+translate_sockaddr(const struct sockaddr *addr, uint32_t len)
+{
+ struct sockaddr *laddr;
+ const struct rump_sockaddr *baddr;
+
+ baddr = (const struct rump_sockaddr *)addr;
+ laddr = malloc(len);
+ if (laddr == NULL)
+ return NULL;
+ memcpy(laddr, baddr, len);
+ laddr->sa_family = translate_domain(baddr->sa_family);
+ /* No sa_len for Linux and SunOS */
+#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__)
+ laddr->sa_len = len;
+#endif
+ return laddr;
+}
+
+static void
+translate_sockaddr_back(const struct sockaddr *laddr,
+ struct rump_sockaddr *baddr,
+ uint32_t len)
+{
+
+ if (baddr != NULL) {
+ memcpy(baddr, laddr, len);
+ baddr->sa_family = translate_domain_back(laddr->sa_family);
+ baddr->sa_len = len;
+ }
+ free(__UNCONST(laddr));
+}
+
+static struct msghdr *
+translate_msghdr(const struct rump_msghdr *bmsg, int *flags)
+{
+ struct msghdr *rv;
+
+ *flags = bsd_to_native_msg_flags(*flags);
+ if (*flags < 0)
+ *flags = 0;
+
+ rv = malloc(sizeof(*rv));
+ rv->msg_namelen = bmsg->msg_namelen;
+ rv->msg_iov = bmsg->msg_iov;
+ rv->msg_iovlen = bmsg->msg_iovlen;
+ rv->msg_control = bmsg->msg_control;
+ rv->msg_controllen = bmsg->msg_controllen;
+ rv->msg_flags = 0;
+
+ if (bmsg->msg_name != NULL) {
+ rv->msg_name = translate_sockaddr(bmsg->msg_name,
+ bmsg->msg_namelen);
+ if (rv->msg_name == NULL) {
+ free(rv);
+ return NULL;
+ }
+ } else
+ rv->msg_name = NULL;
+ return rv;
+}
+
+static void
+translate_msghdr_back(const struct msghdr *lmsg, struct rump_msghdr *bmsg)
+{
+
+ if (bmsg == NULL) {
+ if (lmsg->msg_name != NULL)
+ free(lmsg->msg_name);
+ free(__UNCONST(lmsg));
+ return;
+ }
+ bmsg->msg_namelen = lmsg->msg_namelen;
+ bmsg->msg_iov = lmsg->msg_iov;
+ bmsg->msg_iovlen = lmsg->msg_iovlen;
+ bmsg->msg_control = lmsg->msg_control;
+ bmsg->msg_controllen = lmsg->msg_controllen;
+ bmsg->msg_flags = native_to_bsd_msg_flags(lmsg->msg_flags);
+
+ if (lmsg->msg_name != NULL)
+ translate_sockaddr_back(lmsg->msg_name, bmsg->msg_name,
+ bmsg->msg_namelen);
+ else
+ bmsg->msg_name = NULL;
+
+ free(__UNCONST(lmsg));
+}
+#endif
+
int
rumpcomp_sockin_socket(int domain, int type, int proto, int *s)
{
void *cookie;
int rv;
+ domain = translate_domain(domain);
+
cookie = rumpuser_component_unschedule();
*s = socket(domain, type, proto);
seterror(*s);
@@ -59,12 +429,16 @@ rumpcomp_sockin_sendmsg(int s, const str
ssize_t nn;
int rv;
+ msg = translate_msghdr((struct rump_msghdr *)msg, &flags);
+
cookie = rumpuser_component_unschedule();
nn = sendmsg(s, msg, flags);
seterror(nn);
*snd = (size_t)nn;
rumpuser_component_schedule(cookie);
+ translate_msghdr_back(msg, NULL);
+
return rumpuser_component_errtrans(rv);
}
@@ -74,6 +448,10 @@ rumpcomp_sockin_recvmsg(int s, struct ms
void *cookie;
ssize_t nn;
int rv;
+ struct rump_msghdr *saveptr;
+
+ saveptr = (struct rump_msghdr *)msg;
+ msg = translate_msghdr(saveptr, &flags);
cookie = rumpuser_component_unschedule();
nn = recvmsg(s, msg, flags);
@@ -81,6 +459,8 @@ rumpcomp_sockin_recvmsg(int s, struct ms
*rcv = (size_t)nn;
rumpuser_component_schedule(cookie);
+ translate_msghdr_back(msg, saveptr);
+
return rumpuser_component_errtrans(rv);
}
@@ -90,11 +470,15 @@ rumpcomp_sockin_connect(int s, const str
void *cookie;
int rv;
+ name = translate_sockaddr(name, len);
+
cookie = rumpuser_component_unschedule();
rv = connect(s, name, (socklen_t)len);
seterror(rv);
rumpuser_component_schedule(cookie);
+ translate_sockaddr_back(name, NULL, len);
+
return rumpuser_component_errtrans(rv);
}
@@ -104,11 +488,15 @@ rumpcomp_sockin_bind(int s, const struct
void *cookie;
int rv;
+ name = translate_sockaddr(name, len);
+
cookie = rumpuser_component_unschedule();
rv = bind(s, name, (socklen_t)len);
seterror(rv);
rumpuser_component_schedule(cookie);
+ translate_sockaddr_back(name, NULL, len);
+
return rumpuser_component_errtrans(rv);
}
@@ -117,12 +505,18 @@ rumpcomp_sockin_accept(int s, struct soc
{
void *cookie;
int rv;
+ struct rump_sockaddr *saveptr;
+
+ saveptr = (struct rump_sockaddr *)name;
+ name = translate_sockaddr(name, *lenp);
cookie = rumpuser_component_unschedule();
*s2 = accept(s, name, (socklen_t *)lenp);
seterror(*s2);
rumpuser_component_schedule(cookie);
+ translate_sockaddr_back(name, saveptr, *lenp);
+
return rumpuser_component_errtrans(rv);
}
@@ -146,12 +540,19 @@ rumpcomp_sockin_getname(int s, struct so
{
socklen_t slen = *lenp;
int rv;
+ struct rump_sockaddr *saveptr;
+
+ saveptr = (struct rump_sockaddr *)so;
+ so = translate_sockaddr(so, *lenp);
if (which == RUMPCOMP_SOCKIN_SOCKNAME)
rv = getsockname(s, so, &slen);
else
rv = getpeername(s, so, &slen);
+
seterror(rv);
+ translate_sockaddr_back(so, saveptr, *lenp);
+
*lenp = slen;
return rumpuser_component_errtrans(rv);
@@ -164,7 +565,17 @@ rumpcomp_sockin_setsockopt(int s, int le
socklen_t slen = dlen;
int rv;
- rv = setsockopt(s, level, name, data, slen);
+ translate_sockopt(&level, &name);
+ if (level == -1 || name == -1) {
+#ifdef SETSOCKOPT_STRICT
+ errno = EINVAL;
+ rv = -1;
+#else
+ rv = 0;
+#endif
+ } else
+ rv = setsockopt(s, level, name, data, slen);
+
seterror(rv);
return rumpuser_component_errtrans(rv);