Translate function parameters between the hypervisor and rump kernel
This commit is contained in:
parent
6e6b2fc7a4
commit
79e963ee99
|
@ -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 struct msghdr *msg, int flags, size_t *snd)
|
|||
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 msghdr *msg, int flags, size_t *rcv)
|
|||
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 msghdr *msg, int flags, size_t *rcv)
|
|||
*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 struct sockaddr *name, int len)
|
|||
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 sockaddr *name, int len)
|
|||
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 sockaddr *name, int *lenp, int *s2)
|
|||
{
|
||||
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 sockaddr *so, int *lenp,
|
|||
{
|
||||
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 level, int name,
|
|||
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);
|
||||
|
|
Loading…
Reference in New Issue