Networked X11 clients have the annoying property that they need to

contact the X server.  Since most of the useful cases these days
are local, add a toggle which forwards PF_LOCAL sockets to the host
and all other protocol families to the rump kernel.

This makes an unmodified firefox work with a rump TCP/IP stack.
I'm sure someone will find applications for being able to run
multiple web browser profiles on one OS with each browser having
a different IP address in the same subnet ...
This commit is contained in:
pooka 2011-01-09 19:56:33 +00:00
parent e58abe368a
commit 81131c3a38
1 changed files with 98 additions and 33 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: hijack.c,v 1.6 2011/01/09 14:15:06 pooka Exp $ */
/* $NetBSD: hijack.c,v 1.7 2011/01/09 19:56: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.6 2011/01/09 14:15:06 pooka Exp $");
__RCSID("$NetBSD: hijack.c,v 1.7 2011/01/09 19:56:33 pooka Exp $");
#include <sys/param.h>
#include <sys/types.h>
@ -91,6 +91,15 @@ const char *sysnames[] = {
"__pollts50",
};
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);
@ -116,6 +125,9 @@ hijackdlsym(void *handle, const char *symbol)
return dlsym(handle, symbol);
}
/* low calorie sockets? */
static bool hostlocalsockets = false;
static void __attribute__((constructor))
rcinit(void)
{
@ -133,6 +145,15 @@ rcinit(void)
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");
@ -228,13 +249,21 @@ __socket30(int domain, int type, int protocol)
{
int (*rc_socket)(int, int, int);
int fd;
bool dohost;
rc_socket = rumpcalls[RUMPCALL_SOCKET];
dohost = hostlocalsockets && (domain == AF_LOCAL);
if (dohost)
rc_socket = host_socket;
else
rc_socket = rumpcalls[RUMPCALL_SOCKET];
fd = rc_socket(domain, type, protocol);
DPRINTF(("socket <- %d\n", fd_rump2host(fd)));
if (!dohost)
fd = fd_rump2host(fd);
DPRINTF(("socket <- %d\n", fd));
return fd_rump2host(fd);
return fd;
}
int
@ -242,14 +271,24 @@ accept(int s, struct sockaddr *addr, socklen_t *addrlen)
{
int (*rc_accept)(int, struct sockaddr *, socklen_t *);
int fd;
bool isrump;
isrump = fd_isrump(s);
DPRINTF(("accept -> %d", s));
assertfd(s);
rc_accept = rumpcalls[RUMPCALL_ACCEPT];
fd = rc_accept(fd_host2rump(s), addr, addrlen);
DPRINTF((" <- %d\n", fd_rump2host(fd)));
if (isrump) {
rc_accept = rumpcalls[RUMPCALL_ACCEPT];
s = fd_host2rump(s);
} else {
rc_accept = host_accept;
}
fd = rc_accept(s, addr, addrlen);
if (fd != -1 && isrump)
fd = fd_rump2host(fd);
return fd_rump2host(fd);
DPRINTF((" <- %d\n", fd));
return fd;
}
int
@ -258,10 +297,13 @@ bind(int s, const struct sockaddr *name, socklen_t namelen)
int (*rc_bind)(int, const struct sockaddr *, socklen_t);
DPRINTF(("bind -> %d\n", s));
assertfd(s);
rc_bind = rumpcalls[RUMPCALL_BIND];
return rc_bind(fd_host2rump(s), name, namelen);
if (fd_isrump(s)) {
rc_bind = rumpcalls[RUMPCALL_BIND];
s = fd_host2rump(s);
} else {
rc_bind = host_bind;
}
return rc_bind(s, name, namelen);
}
int
@ -270,10 +312,14 @@ connect(int s, const struct sockaddr *name, socklen_t namelen)
int (*rc_connect)(int, const struct sockaddr *, socklen_t);
DPRINTF(("connect -> %d\n", s));
assertfd(s);
rc_connect = rumpcalls[RUMPCALL_CONNECT];
if (fd_isrump(s)) {
rc_connect = rumpcalls[RUMPCALL_CONNECT];
s = fd_host2rump(s);
} else {
rc_connect = host_connect;
}
return rc_connect(fd_host2rump(s), name, namelen);
return rc_connect(s, name, namelen);
}
int
@ -282,9 +328,13 @@ getpeername(int s, struct sockaddr *name, socklen_t *namelen)
int (*rc_getpeername)(int, struct sockaddr *, socklen_t *);
DPRINTF(("getpeername -> %d\n", s));
assertfd(s);
rc_getpeername = rumpcalls[RUMPCALL_GETPEERNAME];
return rc_getpeername(fd_host2rump(s), name, namelen);
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
@ -293,9 +343,13 @@ getsockname(int s, struct sockaddr *name, socklen_t *namelen)
int (*rc_getsockname)(int, struct sockaddr *, socklen_t *);
DPRINTF(("getsockname -> %d\n", s));
assertfd(s);
rc_getsockname = rumpcalls[RUMPCALL_GETSOCKNAME];
return rc_getsockname(fd_host2rump(s), name, namelen);
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
@ -304,9 +358,13 @@ listen(int s, int backlog)
int (*rc_listen)(int, int);
DPRINTF(("listen -> %d\n", s));
assertfd(s);
rc_listen = rumpcalls[RUMPCALL_LISTEN];
return rc_listen(fd_host2rump(s), backlog);
if (fd_isrump(s)) {
rc_listen = rumpcalls[RUMPCALL_LISTEN];
s = fd_host2rump(s);
} else {
rc_listen = host_listen;
}
return rc_listen(s, backlog);
}
ssize_t
@ -379,7 +437,7 @@ getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
{
int (*rc_getsockopt)(int, int, int, void *, socklen_t *);
DPRINTF(("getsockopt\n"));
DPRINTF(("getsockopt -> %d\n", s));
assertfd(s);
rc_getsockopt = rumpcalls[RUMPCALL_GETSOCKOPT];
return rc_getsockopt(fd_host2rump(s), level, optname, optval, optlen);
@ -390,10 +448,14 @@ 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\n"));
assertfd(s);
rc_setsockopt = rumpcalls[RUMPCALL_SETSOCKOPT];
return rc_setsockopt(fd_host2rump(s), level, optname, optval, optlen);
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
@ -401,7 +463,7 @@ shutdown(int s, int how)
{
int (*rc_shutdown)(int, int);
DPRINTF(("shutdown\n"));
DPRINTF(("shutdown -> %d\n", s));
assertfd(s);
rc_shutdown = rumpcalls[RUMPCALL_SHUTDOWN];
return rc_shutdown(fd_host2rump(s), how);
@ -496,6 +558,7 @@ readv(int fd, const struct iovec *iov, int iovcnt)
{
int (*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];
@ -503,7 +566,6 @@ readv(int fd, const struct iovec *iov, int iovcnt)
op_readv = host_readv;
}
DPRINTF(("readv\n"));
return op_readv(fd, iov, iovcnt);
}
@ -527,6 +589,7 @@ writev(int fd, const struct iovec *iov, int iovcnt)
{
int (*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];
@ -604,6 +667,8 @@ select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
nfds_t i, j, realnfds;
int rv, incr;
DPRINTF(("select\n"));
/*
* Well, first we must scan the fds to figure out how many
* fds there really are. This is because up to and including