Rewrite to declare most dual-kernel calls with macros. This helps
with adding new calls and makes all existing fd-accepting hijacked calls dual-kernel. It would be better to autogenerate the code from syscalls.master, but this is easier for now.
This commit is contained in:
parent
984da15cb1
commit
9d0409a087
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: hijack.c,v 1.16 2011/01/19 11:27:01 pooka Exp $ */
|
||||
/* $NetBSD: hijack.c,v 1.17 2011/01/25 12:18:33 pooka Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011 Antti Kantee. All Rights Reserved.
|
||||
|
@ -26,7 +26,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: hijack.c,v 1.16 2011/01/19 11:27:01 pooka Exp $");
|
||||
__RCSID("$NetBSD: hijack.c,v 1.17 2011/01/25 12:18:33 pooka Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
|
@ -53,160 +53,81 @@ __RCSID("$NetBSD: hijack.c,v 1.16 2011/01/19 11:27:01 pooka Exp $");
|
|||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
enum { RUMPCALL_SOCKET, RUMPCALL_ACCEPT, RUMPCALL_BIND, RUMPCALL_CONNECT,
|
||||
RUMPCALL_GETPEERNAME, RUMPCALL_GETSOCKNAME, RUMPCALL_LISTEN,
|
||||
RUMPCALL_RECVFROM, RUMPCALL_RECVMSG,
|
||||
RUMPCALL_SENDTO, RUMPCALL_SENDMSG,
|
||||
RUMPCALL_GETSOCKOPT, RUMPCALL_SETSOCKOPT,
|
||||
RUMPCALL_SHUTDOWN,
|
||||
RUMPCALL_READ, RUMPCALL_READV,
|
||||
RUMPCALL_WRITE, RUMPCALL_WRITEV,
|
||||
RUMPCALL_IOCTL, RUMPCALL_FCNTL,
|
||||
RUMPCALL_CLOSE,
|
||||
RUMPCALL_POLLTS,
|
||||
RUMPCALL__NUM
|
||||
enum dualcall {
|
||||
DUALCALL_WRITE, DUALCALL_WRITEV,
|
||||
DUALCALL_IOCTL, DUALCALL_FCNTL,
|
||||
DUALCALL_SOCKET, DUALCALL_ACCEPT, DUALCALL_BIND, DUALCALL_CONNECT,
|
||||
DUALCALL_GETPEERNAME, DUALCALL_GETSOCKNAME, DUALCALL_LISTEN,
|
||||
DUALCALL_RECVFROM, DUALCALL_RECVMSG,
|
||||
DUALCALL_SENDTO, DUALCALL_SENDMSG,
|
||||
DUALCALL_GETSOCKOPT, DUALCALL_SETSOCKOPT,
|
||||
DUALCALL_SHUTDOWN,
|
||||
DUALCALL_READ, DUALCALL_READV,
|
||||
DUALCALL_DUP2, DUALCALL_CLOSE,
|
||||
DUALCALL_POLLTS,
|
||||
DUALCALL__NUM
|
||||
};
|
||||
|
||||
#define RSYS_STRING(a) __STRING(a)
|
||||
#define RSYS_NAME(a) RSYS_STRING(__CONCAT(RUMP_SYS_RENAME_,a))
|
||||
|
||||
const char *sysnames[] = {
|
||||
RSYS_NAME(SOCKET),
|
||||
RSYS_NAME(ACCEPT),
|
||||
RSYS_NAME(BIND),
|
||||
RSYS_NAME(CONNECT),
|
||||
RSYS_NAME(GETPEERNAME),
|
||||
RSYS_NAME(GETSOCKNAME),
|
||||
RSYS_NAME(LISTEN),
|
||||
RSYS_NAME(RECVFROM),
|
||||
RSYS_NAME(RECVMSG),
|
||||
RSYS_NAME(SENDTO),
|
||||
RSYS_NAME(SENDMSG),
|
||||
RSYS_NAME(GETSOCKOPT),
|
||||
RSYS_NAME(SETSOCKOPT),
|
||||
RSYS_NAME(SHUTDOWN),
|
||||
RSYS_NAME(READ),
|
||||
RSYS_NAME(READV),
|
||||
RSYS_NAME(WRITE),
|
||||
RSYS_NAME(WRITEV),
|
||||
RSYS_NAME(IOCTL),
|
||||
RSYS_NAME(FCNTL),
|
||||
RSYS_NAME(CLOSE),
|
||||
RSYS_NAME(POLLTS),
|
||||
};
|
||||
|
||||
static int (*host_socket)(int, int, int);
|
||||
static int (*host_connect)(int, const struct sockaddr *, socklen_t);
|
||||
static int (*host_bind)(int, const struct sockaddr *, socklen_t);
|
||||
static int (*host_listen)(int, int);
|
||||
static int (*host_accept)(int, struct sockaddr *, socklen_t *);
|
||||
static int (*host_getpeername)(int, struct sockaddr *, socklen_t *);
|
||||
static int (*host_getsockname)(int, struct sockaddr *, socklen_t *);
|
||||
static int (*host_setsockopt)(int, int, int, const void *, socklen_t);
|
||||
|
||||
static ssize_t (*host_read)(int, void *, size_t);
|
||||
static ssize_t (*host_readv)(int, const struct iovec *, int);
|
||||
static ssize_t (*host_write)(int, const void *, size_t);
|
||||
static ssize_t (*host_writev)(int, const struct iovec *, int);
|
||||
static int (*host_ioctl)(int, unsigned long, ...);
|
||||
static int (*host_fcntl)(int, int, ...);
|
||||
static int (*host_close)(int);
|
||||
static int (*host_pollts)(struct pollfd *, nfds_t,
|
||||
const struct timespec *, const sigset_t *);
|
||||
static pid_t (*host_fork)(void);
|
||||
static int (*host_dup2)(int, int);
|
||||
static int (*host_shutdown)(int, int);
|
||||
/* XXX */
|
||||
static void *host_sendto;
|
||||
static void *host_recvfrom;
|
||||
|
||||
static void *rumpcalls[RUMPCALL__NUM];
|
||||
|
||||
/*
|
||||
* Would be nice to get this automatically in sync with libc.
|
||||
* Also, this does not work for compat-using binaries!
|
||||
*/
|
||||
|
||||
#if !__NetBSD_Prereq__(5,99,7)
|
||||
#define SELECT select
|
||||
#define POLLTS pollts
|
||||
#define POLL poll
|
||||
#define LIBCSELECT select
|
||||
#define LIBCPOLLTS pollts
|
||||
#define LIBCPOLL poll
|
||||
#else
|
||||
#define SELECT __select50
|
||||
#define POLLTS __pollts50
|
||||
#define POLL __poll50
|
||||
#define LIBCSELECT __select50
|
||||
#define LIBCPOLLTS __pollts50
|
||||
#define LIBCPOLL __poll50
|
||||
#endif
|
||||
|
||||
int SELECT(int, fd_set *, fd_set *, fd_set *, struct timeval *);
|
||||
int POLLTS(struct pollfd *, nfds_t, const struct timespec *, const sigset_t *);
|
||||
int POLL(struct pollfd *, nfds_t, int);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is called from librumpclient in case of LD_PRELOAD.
|
||||
* It ensures correct RTLD_NEXT.
|
||||
*/
|
||||
static void *
|
||||
hijackdlsym(void *handle, const char *symbol)
|
||||
{
|
||||
#define S(a) __STRING(a)
|
||||
struct sysnames {
|
||||
enum dualcall scm_callnum;
|
||||
const char *scm_hostname;
|
||||
const char *scm_rumpname;
|
||||
} syscnames[] = {
|
||||
{ DUALCALL_SOCKET, "__socket30", RSYS_NAME(SOCKET) },
|
||||
{ DUALCALL_ACCEPT, "accept", RSYS_NAME(ACCEPT) },
|
||||
{ DUALCALL_BIND, "bind", RSYS_NAME(BIND) },
|
||||
{ DUALCALL_CONNECT, "connect", RSYS_NAME(CONNECT) },
|
||||
{ DUALCALL_GETPEERNAME, "getpeername", RSYS_NAME(GETPEERNAME) },
|
||||
{ DUALCALL_GETSOCKNAME, "getsockname", RSYS_NAME(GETSOCKNAME) },
|
||||
{ DUALCALL_LISTEN, "listen", RSYS_NAME(LISTEN) },
|
||||
{ DUALCALL_RECVFROM, "recvfrom", RSYS_NAME(RECVFROM) },
|
||||
{ DUALCALL_RECVMSG, "recvmsg", RSYS_NAME(RECVMSG) },
|
||||
{ DUALCALL_SENDTO, "sendto", RSYS_NAME(SENDTO) },
|
||||
{ DUALCALL_SENDMSG, "sendmsg", RSYS_NAME(SENDMSG) },
|
||||
{ DUALCALL_GETSOCKOPT, "getsockopt", RSYS_NAME(GETSOCKOPT) },
|
||||
{ DUALCALL_SETSOCKOPT, "setsockopt", RSYS_NAME(SETSOCKOPT) },
|
||||
{ DUALCALL_SHUTDOWN, "shutdown", RSYS_NAME(SHUTDOWN) },
|
||||
{ DUALCALL_READ, "read", RSYS_NAME(READ) },
|
||||
{ DUALCALL_READV, "readv", RSYS_NAME(READV) },
|
||||
{ DUALCALL_WRITE, "write", RSYS_NAME(WRITE) },
|
||||
{ DUALCALL_WRITEV, "writev", RSYS_NAME(WRITEV) },
|
||||
{ DUALCALL_IOCTL, "ioctl", RSYS_NAME(IOCTL) },
|
||||
{ DUALCALL_FCNTL, "fcntl", RSYS_NAME(FCNTL) },
|
||||
{ DUALCALL_DUP2, "dup2", RSYS_NAME(DUP2) },
|
||||
{ DUALCALL_CLOSE, "close", RSYS_NAME(CLOSE) },
|
||||
{ DUALCALL_POLLTS, S(LIBCPOLLTS), RSYS_NAME(POLLTS) },
|
||||
};
|
||||
#undef S
|
||||
|
||||
return dlsym(handle, symbol);
|
||||
}
|
||||
struct bothsys {
|
||||
void *bs_host;
|
||||
void *bs_rump;
|
||||
} syscalls[DUALCALL__NUM];
|
||||
#define GETSYSCALL(which, name) syscalls[DUALCALL_##name].bs_##which
|
||||
|
||||
/* low calorie sockets? */
|
||||
static bool hostlocalsockets = true;
|
||||
|
||||
static void __attribute__((constructor))
|
||||
rcinit(void)
|
||||
{
|
||||
int (*rumpcinit)(void);
|
||||
void **rumpcdlsym;
|
||||
void *hand;
|
||||
int i;
|
||||
|
||||
hand = dlopen("librumpclient.so", RTLD_LAZY|RTLD_GLOBAL);
|
||||
if (!hand)
|
||||
err(1, "cannot open librumpclient.so");
|
||||
rumpcinit = dlsym(hand, "rumpclient_init");
|
||||
_DIAGASSERT(rumpcinit);
|
||||
|
||||
rumpcdlsym = dlsym(hand, "rumpclient_dlsym");
|
||||
*rumpcdlsym = hijackdlsym;
|
||||
|
||||
host_socket = dlsym(RTLD_NEXT, "__socket30");
|
||||
host_listen = dlsym(RTLD_NEXT, "listen");
|
||||
host_connect = dlsym(RTLD_NEXT, "connect");
|
||||
host_bind = dlsym(RTLD_NEXT, "bind");
|
||||
host_accept = dlsym(RTLD_NEXT, "accept");
|
||||
host_getpeername = dlsym(RTLD_NEXT, "getpeername");
|
||||
host_getsockname = dlsym(RTLD_NEXT, "getsockname");
|
||||
host_setsockopt = dlsym(RTLD_NEXT, "setsockopt");
|
||||
|
||||
host_read = dlsym(RTLD_NEXT, "read");
|
||||
host_readv = dlsym(RTLD_NEXT, "readv");
|
||||
host_write = dlsym(RTLD_NEXT, "write");
|
||||
host_writev = dlsym(RTLD_NEXT, "writev");
|
||||
host_ioctl = dlsym(RTLD_NEXT, "ioctl");
|
||||
host_fcntl = dlsym(RTLD_NEXT, "fcntl");
|
||||
host_close = dlsym(RTLD_NEXT, "close");
|
||||
host_pollts = dlsym(RTLD_NEXT, "pollts");
|
||||
host_fork = dlsym(RTLD_NEXT, "fork");
|
||||
host_dup2 = dlsym(RTLD_NEXT, "dup2");
|
||||
host_shutdown = dlsym(RTLD_NEXT, "shutdown");
|
||||
host_sendto = dlsym(RTLD_NEXT, "sendto");
|
||||
host_recvfrom = dlsym(RTLD_NEXT, "recvfrom");
|
||||
|
||||
for (i = 0; i < RUMPCALL__NUM; i++) {
|
||||
rumpcalls[i] = dlsym(hand, sysnames[i]);
|
||||
if (!rumpcalls[i]) {
|
||||
fprintf(stderr, "rumphijack: cannot find symbol: %s\n",
|
||||
sysnames[i]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (rumpcinit() == -1)
|
||||
err(1, "rumpclient init");
|
||||
}
|
||||
pid_t (*host_fork)(void);
|
||||
|
||||
static unsigned dup2mask;
|
||||
#define ISDUP2D(fd) (1<<(fd) & dup2mask)
|
||||
|
@ -231,6 +152,84 @@ mydprintf(const char *fmt, ...)
|
|||
#define DPRINTF(x)
|
||||
#endif
|
||||
|
||||
#define FDCALL(type, name, rcname, args, proto, vars) \
|
||||
type name args \
|
||||
{ \
|
||||
type (*fun) proto; \
|
||||
\
|
||||
if (fd_isrump(fd)) { \
|
||||
fun = syscalls[rcname].bs_rump; \
|
||||
fd = fd_host2rump(fd); \
|
||||
} else { \
|
||||
fun = syscalls[rcname].bs_host; \
|
||||
} \
|
||||
\
|
||||
return fun vars; \
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called from librumpclient in case of LD_PRELOAD.
|
||||
* It ensures correct RTLD_NEXT.
|
||||
*/
|
||||
static void *
|
||||
hijackdlsym(void *handle, const char *symbol)
|
||||
{
|
||||
|
||||
return dlsym(handle, symbol);
|
||||
}
|
||||
|
||||
/* low calorie sockets? */
|
||||
static bool hostlocalsockets = true;
|
||||
|
||||
static void __attribute__((constructor))
|
||||
rcinit(void)
|
||||
{
|
||||
int (*rumpcinit)(void);
|
||||
void **rumpcdlsym;
|
||||
void *hand;
|
||||
int i, j;
|
||||
|
||||
hand = dlopen("librumpclient.so", RTLD_LAZY|RTLD_GLOBAL);
|
||||
if (!hand)
|
||||
err(1, "cannot open librumpclient.so");
|
||||
rumpcinit = dlsym(hand, "rumpclient_init");
|
||||
_DIAGASSERT(rumpcinit);
|
||||
|
||||
rumpcdlsym = dlsym(hand, "rumpclient_dlsym");
|
||||
*rumpcdlsym = hijackdlsym;
|
||||
host_fork = dlsym(RTLD_NEXT, "fork");
|
||||
|
||||
/*
|
||||
* In theory cannot print anything during lookups because
|
||||
* we might not have the call vector set up. so, the errx()
|
||||
* is a bit of a strech, but it might work.
|
||||
*/
|
||||
|
||||
for (i = 0; i < DUALCALL__NUM; i++) {
|
||||
/* build runtime O(1) access */
|
||||
for (j = 0; j < __arraycount(syscnames); j++) {
|
||||
if (syscnames[j].scm_callnum == i)
|
||||
break;
|
||||
}
|
||||
|
||||
if (j == __arraycount(syscnames))
|
||||
errx(1, "rumphijack error: syscall pos %d missing", i);
|
||||
|
||||
syscalls[i].bs_host = dlsym(hand,syscnames[j].scm_hostname);
|
||||
if (syscalls[i].bs_host == NULL)
|
||||
errx(1, "hostcall %s not found missing",
|
||||
syscnames[j].scm_hostname);
|
||||
|
||||
syscalls[i].bs_rump = dlsym(hand,syscnames[j].scm_rumpname);
|
||||
if (syscalls[i].bs_rump == NULL)
|
||||
errx(1, "rumpcall %s not found missing",
|
||||
syscnames[j].scm_rumpname);
|
||||
}
|
||||
|
||||
if (rumpcinit() == -1)
|
||||
err(1, "rumpclient init");
|
||||
}
|
||||
|
||||
/* XXX: need runtime selection. low for now due to FD_SETSIZE */
|
||||
#define HIJACK_FDOFF 128
|
||||
#define HIJACK_SELECT 128 /* XXX */
|
||||
|
@ -271,17 +270,17 @@ int __socket30(int, int, int);
|
|||
int
|
||||
__socket30(int domain, int type, int protocol)
|
||||
{
|
||||
int (*rc_socket)(int, int, int);
|
||||
int (*op_socket)(int, int, int);
|
||||
int fd;
|
||||
bool dohost;
|
||||
|
||||
dohost = hostlocalsockets && (domain == AF_LOCAL);
|
||||
|
||||
if (dohost)
|
||||
rc_socket = host_socket;
|
||||
op_socket = GETSYSCALL(host, SOCKET);
|
||||
else
|
||||
rc_socket = rumpcalls[RUMPCALL_SOCKET];
|
||||
fd = rc_socket(domain, type, protocol);
|
||||
op_socket = GETSYSCALL(rump, SOCKET);
|
||||
fd = op_socket(domain, type, protocol);
|
||||
|
||||
if (!dohost)
|
||||
fd = fd_rump2host(fd);
|
||||
|
@ -293,7 +292,7 @@ __socket30(int domain, int type, int protocol)
|
|||
int
|
||||
accept(int s, struct sockaddr *addr, socklen_t *addrlen)
|
||||
{
|
||||
int (*rc_accept)(int, struct sockaddr *, socklen_t *);
|
||||
int (*op_accept)(int, struct sockaddr *, socklen_t *);
|
||||
int fd;
|
||||
bool isrump;
|
||||
|
||||
|
@ -301,12 +300,12 @@ accept(int s, struct sockaddr *addr, socklen_t *addrlen)
|
|||
|
||||
DPRINTF(("accept -> %d", s));
|
||||
if (isrump) {
|
||||
rc_accept = rumpcalls[RUMPCALL_ACCEPT];
|
||||
op_accept = GETSYSCALL(rump, ACCEPT);
|
||||
s = fd_host2rump(s);
|
||||
} else {
|
||||
rc_accept = host_accept;
|
||||
op_accept = GETSYSCALL(host, ACCEPT);
|
||||
}
|
||||
fd = rc_accept(s, addr, addrlen);
|
||||
fd = op_accept(s, addr, addrlen);
|
||||
if (fd != -1 && isrump)
|
||||
fd = fd_rump2host(fd);
|
||||
|
||||
|
@ -315,195 +314,67 @@ accept(int s, struct sockaddr *addr, socklen_t *addrlen)
|
|||
return fd;
|
||||
}
|
||||
|
||||
/*
|
||||
* ioctl and fcntl are varargs calls and need special treatment
|
||||
*/
|
||||
int
|
||||
bind(int s, const struct sockaddr *name, socklen_t namelen)
|
||||
ioctl(int fd, unsigned long cmd, ...)
|
||||
{
|
||||
int (*rc_bind)(int, const struct sockaddr *, socklen_t);
|
||||
int (*op_ioctl)(int, unsigned long cmd, ...);
|
||||
va_list ap;
|
||||
int rv;
|
||||
|
||||
DPRINTF(("bind -> %d\n", s));
|
||||
if (fd_isrump(s)) {
|
||||
rc_bind = rumpcalls[RUMPCALL_BIND];
|
||||
s = fd_host2rump(s);
|
||||
DPRINTF(("ioctl -> %d\n", fd));
|
||||
if (fd_isrump(fd)) {
|
||||
fd = fd_host2rump(fd);
|
||||
op_ioctl = GETSYSCALL(rump, IOCTL);
|
||||
} else {
|
||||
rc_bind = host_bind;
|
||||
op_ioctl = GETSYSCALL(host, IOCTL);
|
||||
}
|
||||
return rc_bind(s, name, namelen);
|
||||
|
||||
va_start(ap, cmd);
|
||||
rv = op_ioctl(fd, cmd, va_arg(ap, void *));
|
||||
va_end(ap);
|
||||
return rv;
|
||||
}
|
||||
|
||||
int
|
||||
connect(int s, const struct sockaddr *name, socklen_t namelen)
|
||||
fcntl(int fd, int cmd, ...)
|
||||
{
|
||||
int (*rc_connect)(int, const struct sockaddr *, socklen_t);
|
||||
int (*op_fcntl)(int, int, ...);
|
||||
va_list ap;
|
||||
int rv;
|
||||
|
||||
DPRINTF(("connect -> %d\n", s));
|
||||
if (fd_isrump(s)) {
|
||||
rc_connect = rumpcalls[RUMPCALL_CONNECT];
|
||||
s = fd_host2rump(s);
|
||||
DPRINTF(("fcntl -> %d\n", fd));
|
||||
if (fd_isrump(fd)) {
|
||||
fd = fd_host2rump(fd);
|
||||
op_fcntl = GETSYSCALL(rump, FCNTL);
|
||||
} else {
|
||||
rc_connect = host_connect;
|
||||
op_fcntl = GETSYSCALL(host, FCNTL);
|
||||
}
|
||||
|
||||
return rc_connect(s, name, namelen);
|
||||
}
|
||||
|
||||
int
|
||||
getpeername(int s, struct sockaddr *name, socklen_t *namelen)
|
||||
{
|
||||
int (*rc_getpeername)(int, struct sockaddr *, socklen_t *);
|
||||
|
||||
DPRINTF(("getpeername -> %d\n", s));
|
||||
if (fd_isrump(s)) {
|
||||
rc_getpeername = rumpcalls[RUMPCALL_GETPEERNAME];
|
||||
s = fd_host2rump(s);
|
||||
} else {
|
||||
rc_getpeername = host_getpeername;
|
||||
}
|
||||
return rc_getpeername(s, name, namelen);
|
||||
}
|
||||
|
||||
int
|
||||
getsockname(int s, struct sockaddr *name, socklen_t *namelen)
|
||||
{
|
||||
int (*rc_getsockname)(int, struct sockaddr *, socklen_t *);
|
||||
|
||||
DPRINTF(("getsockname -> %d\n", s));
|
||||
if (fd_isrump(s)) {
|
||||
rc_getsockname = rumpcalls[RUMPCALL_GETSOCKNAME];
|
||||
s = fd_host2rump(s);
|
||||
} else {
|
||||
rc_getsockname = host_getsockname;
|
||||
}
|
||||
return rc_getsockname(s, name, namelen);
|
||||
}
|
||||
|
||||
int
|
||||
listen(int s, int backlog)
|
||||
{
|
||||
int (*rc_listen)(int, int);
|
||||
|
||||
DPRINTF(("listen -> %d\n", s));
|
||||
if (fd_isrump(s)) {
|
||||
rc_listen = rumpcalls[RUMPCALL_LISTEN];
|
||||
s = fd_host2rump(s);
|
||||
} else {
|
||||
rc_listen = host_listen;
|
||||
}
|
||||
return rc_listen(s, backlog);
|
||||
va_start(ap, cmd);
|
||||
rv = op_fcntl(fd, cmd, va_arg(ap, void *));
|
||||
va_end(ap);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* write cannot issue a standard debug printf due to recursion
|
||||
*/
|
||||
ssize_t
|
||||
recv(int s, void *buf, size_t len, int flags)
|
||||
write(int fd, const void *buf, size_t blen)
|
||||
{
|
||||
ssize_t (*op_write)(int, const void *, size_t);
|
||||
|
||||
return recvfrom(s, buf, len, flags, NULL, NULL);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from,
|
||||
socklen_t *fromlen)
|
||||
{
|
||||
int (*rc_recvfrom)(int, void *, size_t, int,
|
||||
struct sockaddr *, socklen_t *);
|
||||
|
||||
DPRINTF(("recvfrom\n"));
|
||||
if (fd_isrump(s)) {
|
||||
rc_recvfrom = rumpcalls[RUMPCALL_RECVFROM];
|
||||
s = fd_host2rump(s);
|
||||
if (fd_isrump(fd)) {
|
||||
fd = fd_host2rump(fd);
|
||||
op_write = GETSYSCALL(rump, WRITE);
|
||||
} else {
|
||||
rc_recvfrom = host_recvfrom;
|
||||
op_write = GETSYSCALL(host, WRITE);
|
||||
}
|
||||
|
||||
return rc_recvfrom(s, buf, len, flags, from, fromlen);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
recvmsg(int s, struct msghdr *msg, int flags)
|
||||
{
|
||||
int (*rc_recvmsg)(int, struct msghdr *, int);
|
||||
|
||||
DPRINTF(("recvmsg\n"));
|
||||
assertfd(s);
|
||||
rc_recvmsg = rumpcalls[RUMPCALL_RECVMSG];
|
||||
return rc_recvmsg(fd_host2rump(s), msg, flags);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
send(int s, const void *buf, size_t len, int flags)
|
||||
{
|
||||
|
||||
return sendto(s, buf, len, flags, NULL, 0);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
sendto(int s, const void *buf, size_t len, int flags,
|
||||
const struct sockaddr *to, socklen_t tolen)
|
||||
{
|
||||
int (*rc_sendto)(int, const void *, size_t, int,
|
||||
const struct sockaddr *, socklen_t);
|
||||
|
||||
if (s == -1)
|
||||
return len;
|
||||
DPRINTF(("sendto\n"));
|
||||
|
||||
if (fd_isrump(s)) {
|
||||
rc_sendto = rumpcalls[RUMPCALL_SENDTO];
|
||||
s = fd_host2rump(s);
|
||||
} else {
|
||||
rc_sendto = host_sendto;
|
||||
}
|
||||
return rc_sendto(s, buf, len, flags, to, tolen);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
sendmsg(int s, const struct msghdr *msg, int flags)
|
||||
{
|
||||
int (*rc_sendmsg)(int, const struct msghdr *, int);
|
||||
|
||||
DPRINTF(("sendmsg\n"));
|
||||
assertfd(s);
|
||||
rc_sendmsg = rumpcalls[RUMPCALL_SENDTO];
|
||||
return rc_sendmsg(fd_host2rump(s), msg, flags);
|
||||
}
|
||||
|
||||
int
|
||||
getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
|
||||
{
|
||||
int (*rc_getsockopt)(int, int, int, void *, socklen_t *);
|
||||
|
||||
DPRINTF(("getsockopt -> %d\n", s));
|
||||
assertfd(s);
|
||||
rc_getsockopt = rumpcalls[RUMPCALL_GETSOCKOPT];
|
||||
return rc_getsockopt(fd_host2rump(s), level, optname, optval, optlen);
|
||||
}
|
||||
|
||||
int
|
||||
setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
|
||||
{
|
||||
int (*rc_setsockopt)(int, int, int, const void *, socklen_t);
|
||||
|
||||
DPRINTF(("setsockopt -> %d\n", s));
|
||||
if (fd_isrump(s)) {
|
||||
rc_setsockopt = rumpcalls[RUMPCALL_SETSOCKOPT];
|
||||
s = fd_host2rump(s);
|
||||
} else {
|
||||
rc_setsockopt = host_setsockopt;
|
||||
}
|
||||
return rc_setsockopt(s, level, optname, optval, optlen);
|
||||
}
|
||||
|
||||
int
|
||||
shutdown(int s, int how)
|
||||
{
|
||||
int (*rc_shutdown)(int, int);
|
||||
|
||||
DPRINTF(("shutdown -> %d\n", s));
|
||||
if (fd_isrump(s)) {
|
||||
rc_shutdown = rumpcalls[RUMPCALL_SHUTDOWN];
|
||||
s = fd_host2rump(s);
|
||||
} else {
|
||||
rc_shutdown = host_shutdown;
|
||||
}
|
||||
return rc_shutdown(s, how);
|
||||
return op_write(fd, buf, blen);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -512,12 +383,11 @@ shutdown(int s, int how)
|
|||
* not >= fdoff is an error.
|
||||
*
|
||||
* Note: cannot rump2host newd, because it is often hardcoded.
|
||||
*
|
||||
* XXX: should disable debug prints after stdout/stderr are dup2'd
|
||||
*/
|
||||
int
|
||||
dup2(int oldd, int newd)
|
||||
{
|
||||
int (*host_dup2)(int, int);
|
||||
int rv;
|
||||
|
||||
DPRINTF(("dup2 -> %d (o) -> %d (n)\n", oldd, newd));
|
||||
|
@ -530,6 +400,7 @@ dup2(int oldd, int newd)
|
|||
if (rv != -1)
|
||||
dup2mask |= 1<<newd;
|
||||
} else {
|
||||
host_dup2 = syscalls[DUALCALL_DUP2].bs_host;
|
||||
rv = host_dup2(oldd, newd);
|
||||
}
|
||||
|
||||
|
@ -541,7 +412,6 @@ dup2(int oldd, int newd)
|
|||
* the file descriptors of the forked parent in the child, but
|
||||
* prevent double use of connection fd.
|
||||
*/
|
||||
|
||||
pid_t
|
||||
fork()
|
||||
{
|
||||
|
@ -570,134 +440,10 @@ fork()
|
|||
}
|
||||
|
||||
/*
|
||||
* Hybrids
|
||||
* select is done by calling poll.
|
||||
*/
|
||||
|
||||
ssize_t
|
||||
read(int fd, void *buf, size_t len)
|
||||
{
|
||||
ssize_t (*op_read)(int, void *, size_t);
|
||||
ssize_t n;
|
||||
|
||||
DPRINTF(("read %d\n", fd));
|
||||
if (fd_isrump(fd)) {
|
||||
fd = fd_host2rump(fd);
|
||||
op_read = rumpcalls[RUMPCALL_READ];
|
||||
} else {
|
||||
op_read = host_read;
|
||||
}
|
||||
|
||||
n = op_read(fd, buf, len);
|
||||
return n;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
readv(int fd, const struct iovec *iov, int iovcnt)
|
||||
{
|
||||
ssize_t (*op_readv)(int, const struct iovec *, int);
|
||||
|
||||
DPRINTF(("readv %d\n", fd));
|
||||
if (fd_isrump(fd)) {
|
||||
fd = fd_host2rump(fd);
|
||||
op_readv = rumpcalls[RUMPCALL_READV];
|
||||
} else {
|
||||
op_readv = host_readv;
|
||||
}
|
||||
|
||||
return op_readv(fd, iov, iovcnt);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
write(int fd, const void *buf, size_t len)
|
||||
{
|
||||
ssize_t (*op_write)(int, const void *, size_t);
|
||||
|
||||
if (fd_isrump(fd)) {
|
||||
fd = fd_host2rump(fd);
|
||||
op_write = rumpcalls[RUMPCALL_WRITE];
|
||||
} else {
|
||||
op_write = host_write;
|
||||
}
|
||||
|
||||
return op_write(fd, buf, len);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
writev(int fd, const struct iovec *iov, int iovcnt)
|
||||
{
|
||||
ssize_t (*op_writev)(int, const struct iovec *, int);
|
||||
|
||||
DPRINTF(("writev %d\n", fd));
|
||||
if (fd_isrump(fd)) {
|
||||
fd = fd_host2rump(fd);
|
||||
op_writev = rumpcalls[RUMPCALL_WRITEV];
|
||||
} else {
|
||||
op_writev = host_writev;
|
||||
}
|
||||
|
||||
return op_writev(fd, iov, iovcnt);
|
||||
}
|
||||
|
||||
int
|
||||
ioctl(int fd, unsigned long cmd, ...)
|
||||
{
|
||||
int (*op_ioctl)(int, unsigned long cmd, ...);
|
||||
va_list ap;
|
||||
int rv;
|
||||
|
||||
DPRINTF(("ioctl\n"));
|
||||
if (fd_isrump(fd)) {
|
||||
fd = fd_host2rump(fd);
|
||||
op_ioctl = rumpcalls[RUMPCALL_IOCTL];
|
||||
} else {
|
||||
op_ioctl = host_ioctl;
|
||||
}
|
||||
|
||||
va_start(ap, cmd);
|
||||
rv = op_ioctl(fd, cmd, va_arg(ap, void *));
|
||||
va_end(ap);
|
||||
return rv;
|
||||
}
|
||||
|
||||
int
|
||||
fcntl(int fd, int cmd, ...)
|
||||
{
|
||||
int (*op_fcntl)(int, int, ...);
|
||||
va_list ap;
|
||||
int rv;
|
||||
|
||||
DPRINTF(("fcntl\n"));
|
||||
if (fd_isrump(fd)) {
|
||||
fd = fd_host2rump(fd);
|
||||
op_fcntl = rumpcalls[RUMPCALL_FCNTL];
|
||||
} else {
|
||||
op_fcntl = host_fcntl;
|
||||
}
|
||||
|
||||
va_start(ap, cmd);
|
||||
rv = op_fcntl(fd, cmd, va_arg(ap, void *));
|
||||
va_end(ap);
|
||||
return rv;
|
||||
}
|
||||
|
||||
int
|
||||
close(int fd)
|
||||
{
|
||||
int (*op_close)(int);
|
||||
|
||||
DPRINTF(("close %d\n", fd));
|
||||
if (fd_isrump(fd)) {
|
||||
fd = fd_host2rump(fd);
|
||||
op_close = rumpcalls[RUMPCALL_CLOSE];
|
||||
} else {
|
||||
op_close = host_close;
|
||||
}
|
||||
|
||||
return op_close(fd);
|
||||
}
|
||||
|
||||
int
|
||||
SELECT(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
||||
LIBCSELECT(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
||||
struct timeval *timeout)
|
||||
{
|
||||
struct pollfd *pfds;
|
||||
|
@ -710,7 +456,7 @@ SELECT(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
|||
/*
|
||||
* Well, first we must scan the fds to figure out how many
|
||||
* fds there really are. This is because up to and including
|
||||
* nb5 poll() silently refuses nfds > process_open_fds.
|
||||
* nb5 poll() silently refuses nfds > process_maxopen_fds.
|
||||
* Seems to be fixed in current, thank the maker.
|
||||
* god damn cluster...bomb.
|
||||
*/
|
||||
|
@ -847,10 +593,13 @@ struct pollarg {
|
|||
static void *
|
||||
hostpoll(void *arg)
|
||||
{
|
||||
int (*op_pollts)(struct pollfd *, nfds_t, const struct timespec *,
|
||||
const sigset_t *);
|
||||
struct pollarg *parg = arg;
|
||||
intptr_t rv;
|
||||
|
||||
rv = host_pollts(parg->pfds, parg->nfds, parg->ts, parg->sigmask);
|
||||
op_pollts = syscalls[DUALCALL_POLLTS].bs_host;
|
||||
rv = op_pollts(parg->pfds, parg->nfds, parg->ts, parg->sigmask);
|
||||
if (rv == -1)
|
||||
parg->errnum = errno;
|
||||
rump_sys_write(parg->pipefd, &rv, sizeof(rv));
|
||||
|
@ -859,11 +608,12 @@ hostpoll(void *arg)
|
|||
}
|
||||
|
||||
int
|
||||
POLLTS(struct pollfd *fds, nfds_t nfds, const struct timespec *ts,
|
||||
LIBCPOLLTS(struct pollfd *fds, nfds_t nfds, const struct timespec *ts,
|
||||
const sigset_t *sigmask)
|
||||
{
|
||||
int (*op_pollts)(struct pollfd *, nfds_t, const struct timespec *,
|
||||
const sigset_t *);
|
||||
int (*host_close)(int);
|
||||
int hostcall = 0, rumpcall = 0;
|
||||
pthread_t pt;
|
||||
nfds_t i;
|
||||
|
@ -941,7 +691,7 @@ POLLTS(struct pollfd *fds, nfds_t nfds, const struct timespec *ts,
|
|||
parg.pipefd = rpipe[1];
|
||||
pthread_create(&pt, NULL, hostpoll, &parg);
|
||||
|
||||
op_pollts = rumpcalls[RUMPCALL_POLLTS];
|
||||
op_pollts = syscalls[DUALCALL_POLLTS].bs_rump;
|
||||
lrv = op_pollts(pfd_rump, nfds+1, ts, NULL);
|
||||
sverrno = errno;
|
||||
write(hpipe[1], &rv, sizeof(rv));
|
||||
|
@ -968,6 +718,7 @@ POLLTS(struct pollfd *fds, nfds_t nfds, const struct timespec *ts,
|
|||
}
|
||||
|
||||
out:
|
||||
host_close = syscalls[DUALCALL_CLOSE].bs_host;
|
||||
if (rpipe[0] != -1)
|
||||
rump_sys_close(rpipe[0]);
|
||||
if (rpipe[1] != -1)
|
||||
|
@ -981,9 +732,9 @@ POLLTS(struct pollfd *fds, nfds_t nfds, const struct timespec *ts,
|
|||
errno = sverrno;
|
||||
} else {
|
||||
if (hostcall) {
|
||||
op_pollts = host_pollts;
|
||||
op_pollts = syscalls[DUALCALL_POLLTS].bs_host;
|
||||
} else {
|
||||
op_pollts = rumpcalls[RUMPCALL_POLLTS];
|
||||
op_pollts = syscalls[DUALCALL_POLLTS].bs_rump;
|
||||
adjustpoll(fds, nfds, fd_host2rump);
|
||||
}
|
||||
|
||||
|
@ -996,7 +747,7 @@ POLLTS(struct pollfd *fds, nfds_t nfds, const struct timespec *ts,
|
|||
}
|
||||
|
||||
int
|
||||
POLL(struct pollfd *fds, nfds_t nfds, int timeout)
|
||||
LIBCPOLL(struct pollfd *fds, nfds_t nfds, int timeout)
|
||||
{
|
||||
struct timespec ts;
|
||||
struct timespec *tsp = NULL;
|
||||
|
@ -1015,14 +766,107 @@ int
|
|||
kqueue(void)
|
||||
{
|
||||
|
||||
fprintf(stderr, "kqueue unsupported");
|
||||
abort();
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
kevent(int kq, const struct kevent *changelist, size_t nchanges,
|
||||
struct kevent *eventlist, size_t nevents,
|
||||
const struct timespec *timeout)
|
||||
{
|
||||
|
||||
fprintf(stderr, "kqueue unsupported");
|
||||
abort();
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Rest are std type calls.
|
||||
*/
|
||||
|
||||
FDCALL(int, bind, DUALCALL_BIND, \
|
||||
(int fd, const struct sockaddr *name, socklen_t namelen), \
|
||||
(int, const struct sockaddr *, socklen_t), \
|
||||
(fd, name, namelen))
|
||||
|
||||
FDCALL(int, connect, DUALCALL_CONNECT, \
|
||||
(int fd, const struct sockaddr *name, socklen_t namelen), \
|
||||
(int, const struct sockaddr *, socklen_t), \
|
||||
(fd, name, namelen))
|
||||
|
||||
FDCALL(int, getpeername, DUALCALL_GETPEERNAME, \
|
||||
(int fd, struct sockaddr *name, socklen_t *namelen), \
|
||||
(int, struct sockaddr *, socklen_t *), \
|
||||
(fd, name, namelen))
|
||||
|
||||
FDCALL(int, getsockname, DUALCALL_GETSOCKNAME, \
|
||||
(int fd, struct sockaddr *name, socklen_t *namelen), \
|
||||
(int, struct sockaddr *, socklen_t *), \
|
||||
(fd, name, namelen))
|
||||
|
||||
FDCALL(int, listen, DUALCALL_LISTEN, \
|
||||
(int fd, int backlog), \
|
||||
(int, int), \
|
||||
(fd, backlog))
|
||||
|
||||
FDCALL(ssize_t, recvfrom, DUALCALL_RECVFROM, \
|
||||
(int fd, void *buf, size_t len, int flags, \
|
||||
struct sockaddr *from, socklen_t *fromlen), \
|
||||
(int, void *, size_t, int, struct sockaddr *, socklen_t *), \
|
||||
(fd, buf, len, flags, from, fromlen))
|
||||
|
||||
FDCALL(ssize_t, sendto, DUALCALL_SENDTO, \
|
||||
(int fd, const void *buf, size_t len, int flags, \
|
||||
const struct sockaddr *to, socklen_t tolen), \
|
||||
(int, const void *, size_t, int, \
|
||||
const struct sockaddr *, socklen_t), \
|
||||
(fd, buf, len, flags, to, tolen))
|
||||
|
||||
FDCALL(ssize_t, recvmsg, DUALCALL_RECVMSG, \
|
||||
(int fd, struct msghdr *msg, int flags), \
|
||||
(int, struct msghdr *, int), \
|
||||
(fd, msg, flags))
|
||||
|
||||
FDCALL(ssize_t, sendmsg, DUALCALL_SENDMSG, \
|
||||
(int fd, const struct msghdr *msg, int flags), \
|
||||
(int, const struct msghdr *, int), \
|
||||
(fd, msg, flags))
|
||||
|
||||
FDCALL(int, getsockopt, DUALCALL_GETSOCKOPT, \
|
||||
(int fd, int level, int optn, void *optval, socklen_t *optlen), \
|
||||
(int, int, int, void *, socklen_t *), \
|
||||
(fd, level, optn, optval, optlen))
|
||||
|
||||
FDCALL(int, setsockopt, DUALCALL_SETSOCKOPT, \
|
||||
(int fd, int level, int optn, \
|
||||
const void *optval, socklen_t optlen), \
|
||||
(int, int, int, const void *, socklen_t), \
|
||||
(fd, level, optn, optval, optlen))
|
||||
|
||||
FDCALL(int, shutdown, DUALCALL_SHUTDOWN, \
|
||||
(int fd, int how), \
|
||||
(int, int), \
|
||||
(fd, how))
|
||||
|
||||
FDCALL(ssize_t, read, DUALCALL_READ, \
|
||||
(int fd, void *buf, size_t buflen), \
|
||||
(int, void *, size_t), \
|
||||
(fd, buf, buflen))
|
||||
|
||||
FDCALL(ssize_t, readv, DUALCALL_READV, \
|
||||
(int fd, const struct iovec *iov, int iovcnt), \
|
||||
(int, const struct iovec *, int), \
|
||||
(fd, iov, iovcnt))
|
||||
|
||||
FDCALL(ssize_t, writev, DUALCALL_WRITEV, \
|
||||
(int fd, const struct iovec *iov, int iovcnt), \
|
||||
(int, const struct iovec *, int), \
|
||||
(fd, iov, iovcnt))
|
||||
|
||||
FDCALL(int, close, DUALCALL_CLOSE, \
|
||||
(int fd), \
|
||||
(int), \
|
||||
(fd))
|
||||
|
|
Loading…
Reference in New Issue