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);

Reply via email to