Home | History | Annotate | Line # | Download | only in librumphijack
hijack.c revision 1.7
      1  1.7  pooka /*      $NetBSD: hijack.c,v 1.7 2011/01/09 19:56:33 pooka Exp $	*/
      2  1.1  pooka 
      3  1.1  pooka /*-
      4  1.1  pooka  * Copyright (c) 2011 Antti Kantee.  All Rights Reserved.
      5  1.1  pooka  *
      6  1.1  pooka  * Redistribution and use in source and binary forms, with or without
      7  1.1  pooka  * modification, are permitted provided that the following conditions
      8  1.1  pooka  * are met:
      9  1.1  pooka  * 1. Redistributions of source code must retain the above copyright
     10  1.1  pooka  *    notice, this list of conditions and the following disclaimer.
     11  1.1  pooka  * 2. Redistributions in binary form must reproduce the above copyright
     12  1.1  pooka  *    notice, this list of conditions and the following disclaimer in the
     13  1.1  pooka  *    documentation and/or other materials provided with the distribution.
     14  1.1  pooka  *
     15  1.1  pooka  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
     16  1.1  pooka  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     17  1.1  pooka  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     18  1.1  pooka  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     19  1.1  pooka  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     20  1.1  pooka  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     21  1.1  pooka  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22  1.1  pooka  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     23  1.1  pooka  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     24  1.1  pooka  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     25  1.1  pooka  * SUCH DAMAGE.
     26  1.1  pooka  */
     27  1.1  pooka 
     28  1.1  pooka #include <sys/cdefs.h>
     29  1.7  pooka __RCSID("$NetBSD: hijack.c,v 1.7 2011/01/09 19:56:33 pooka Exp $");
     30  1.1  pooka 
     31  1.1  pooka #include <sys/param.h>
     32  1.1  pooka #include <sys/types.h>
     33  1.1  pooka #include <sys/ioctl.h>
     34  1.1  pooka #include <sys/socket.h>
     35  1.1  pooka #include <sys/poll.h>
     36  1.1  pooka 
     37  1.1  pooka #include <rump/rump.h>
     38  1.1  pooka #include <rump/rumpclient.h>
     39  1.1  pooka #include <rump/rump_syscalls.h>
     40  1.1  pooka 
     41  1.1  pooka #include <assert.h>
     42  1.1  pooka #include <dlfcn.h>
     43  1.1  pooka #include <err.h>
     44  1.1  pooka #include <errno.h>
     45  1.1  pooka #include <fcntl.h>
     46  1.1  pooka #include <poll.h>
     47  1.1  pooka #include <pthread.h>
     48  1.3  pooka #include <signal.h>
     49  1.1  pooka #include <stdarg.h>
     50  1.1  pooka #include <stdio.h>
     51  1.1  pooka #include <stdlib.h>
     52  1.3  pooka #include <time.h>
     53  1.1  pooka #include <unistd.h>
     54  1.1  pooka 
     55  1.1  pooka enum {	RUMPCALL_SOCKET, RUMPCALL_ACCEPT, RUMPCALL_BIND, RUMPCALL_CONNECT,
     56  1.1  pooka 	RUMPCALL_GETPEERNAME, RUMPCALL_GETSOCKNAME, RUMPCALL_LISTEN,
     57  1.1  pooka 	RUMPCALL_RECVFROM, RUMPCALL_RECVMSG,
     58  1.1  pooka 	RUMPCALL_SENDTO, RUMPCALL_SENDMSG,
     59  1.1  pooka 	RUMPCALL_GETSOCKOPT, RUMPCALL_SETSOCKOPT,
     60  1.1  pooka 	RUMPCALL_SHUTDOWN,
     61  1.1  pooka 	RUMPCALL_READ, RUMPCALL_READV,
     62  1.1  pooka 	RUMPCALL_WRITE, RUMPCALL_WRITEV,
     63  1.1  pooka 	RUMPCALL_IOCTL, RUMPCALL_FCNTL,
     64  1.1  pooka 	RUMPCALL_CLOSE,
     65  1.4  pooka 	RUMPCALL_POLLTS,
     66  1.1  pooka 	RUMPCALL__NUM
     67  1.1  pooka };
     68  1.1  pooka 
     69  1.1  pooka const char *sysnames[] = {
     70  1.1  pooka 	"__socket30",
     71  1.1  pooka 	"accept",
     72  1.1  pooka 	"bind",
     73  1.1  pooka 	"connect",
     74  1.1  pooka 	"getpeername",
     75  1.1  pooka 	"getsockname",
     76  1.1  pooka 	"listen",
     77  1.1  pooka 	"recvfrom",
     78  1.1  pooka 	"recvmsg",
     79  1.1  pooka 	"sendto",
     80  1.1  pooka 	"sendmsg",
     81  1.1  pooka 	"getsockopt",
     82  1.1  pooka 	"setsockopt",
     83  1.1  pooka 	"shutdown",
     84  1.1  pooka 	"read",
     85  1.1  pooka 	"readv",
     86  1.1  pooka 	"write",
     87  1.1  pooka 	"writev",
     88  1.1  pooka 	"ioctl",
     89  1.1  pooka 	"fcntl",
     90  1.1  pooka 	"close",
     91  1.1  pooka 	"__pollts50",
     92  1.1  pooka };
     93  1.1  pooka 
     94  1.7  pooka static int	(*host_socket)(int, int, int);
     95  1.7  pooka static int	(*host_connect)(int, const struct sockaddr *, socklen_t);
     96  1.7  pooka static int	(*host_bind)(int, const struct sockaddr *, socklen_t);
     97  1.7  pooka static int	(*host_listen)(int, int);
     98  1.7  pooka static int	(*host_accept)(int, struct sockaddr *, socklen_t *);
     99  1.7  pooka static int	(*host_getpeername)(int, struct sockaddr *, socklen_t *);
    100  1.7  pooka static int	(*host_getsockname)(int, struct sockaddr *, socklen_t *);
    101  1.7  pooka static int	(*host_setsockopt)(int, int, int, const void *, socklen_t);
    102  1.7  pooka 
    103  1.1  pooka static ssize_t	(*host_read)(int, void *, size_t);
    104  1.1  pooka static ssize_t	(*host_readv)(int, const struct iovec *, int);
    105  1.1  pooka static ssize_t	(*host_write)(int, const void *, size_t);
    106  1.1  pooka static ssize_t	(*host_writev)(int, const struct iovec *, int);
    107  1.1  pooka static int	(*host_ioctl)(int, unsigned long, ...);
    108  1.1  pooka static int	(*host_fcntl)(int, int, ...);
    109  1.1  pooka static int	(*host_close)(int);
    110  1.3  pooka static int	(*host_pollts)(struct pollfd *, nfds_t,
    111  1.3  pooka 			       const struct timespec *, const sigset_t *);
    112  1.2  pooka static pid_t	(*host_fork)(void);
    113  1.2  pooka static int	(*host_dup2)(int, int);
    114  1.1  pooka 
    115  1.1  pooka static void *rumpcalls[RUMPCALL__NUM];
    116  1.1  pooka 
    117  1.1  pooka /*
    118  1.1  pooka  * This is called from librumpclient in case of LD_PRELOAD.
    119  1.1  pooka  * It ensures correct RTLD_NEXT.
    120  1.1  pooka  */
    121  1.1  pooka static void *
    122  1.1  pooka hijackdlsym(void *handle, const char *symbol)
    123  1.1  pooka {
    124  1.1  pooka 
    125  1.1  pooka 	return dlsym(handle, symbol);
    126  1.1  pooka }
    127  1.1  pooka 
    128  1.7  pooka /* low calorie sockets? */
    129  1.7  pooka static bool hostlocalsockets = false;
    130  1.7  pooka 
    131  1.1  pooka static void __attribute__((constructor))
    132  1.1  pooka rcinit(void)
    133  1.1  pooka {
    134  1.1  pooka 	int (*rumpcinit)(void);
    135  1.1  pooka 	void **rumpcdlsym;
    136  1.1  pooka 	void *hand;
    137  1.1  pooka 	int i;
    138  1.1  pooka 
    139  1.1  pooka 	hand = dlopen("librumpclient.so", RTLD_LAZY|RTLD_GLOBAL);
    140  1.1  pooka 	if (!hand)
    141  1.1  pooka 		err(1, "cannot open librumpclient.so");
    142  1.1  pooka 	rumpcinit = dlsym(hand, "rumpclient_init");
    143  1.1  pooka 	_DIAGASSERT(rumpcinit);
    144  1.1  pooka 
    145  1.1  pooka 	rumpcdlsym = dlsym(hand, "rumpclient_dlsym");
    146  1.1  pooka 	*rumpcdlsym = hijackdlsym;
    147  1.1  pooka 
    148  1.7  pooka 	host_socket = dlsym(RTLD_NEXT, "__socket30");
    149  1.7  pooka 	host_listen = dlsym(RTLD_NEXT, "listen");
    150  1.7  pooka 	host_connect = dlsym(RTLD_NEXT, "connect");
    151  1.7  pooka 	host_bind = dlsym(RTLD_NEXT, "bind");
    152  1.7  pooka 	host_accept = dlsym(RTLD_NEXT, "accept");
    153  1.7  pooka 	host_getpeername = dlsym(RTLD_NEXT, "getpeername");
    154  1.7  pooka 	host_getsockname = dlsym(RTLD_NEXT, "getsockname");
    155  1.7  pooka 	host_setsockopt = dlsym(RTLD_NEXT, "setsockopt");
    156  1.7  pooka 
    157  1.1  pooka 	host_read = dlsym(RTLD_NEXT, "read");
    158  1.1  pooka 	host_readv = dlsym(RTLD_NEXT, "readv");
    159  1.1  pooka 	host_write = dlsym(RTLD_NEXT, "write");
    160  1.1  pooka 	host_writev = dlsym(RTLD_NEXT, "writev");
    161  1.1  pooka 	host_ioctl = dlsym(RTLD_NEXT, "ioctl");
    162  1.1  pooka 	host_fcntl = dlsym(RTLD_NEXT, "fcntl");
    163  1.1  pooka 	host_close = dlsym(RTLD_NEXT, "close");
    164  1.3  pooka 	host_pollts = dlsym(RTLD_NEXT, "pollts");
    165  1.2  pooka 	host_fork = dlsym(RTLD_NEXT, "fork");
    166  1.2  pooka 	host_dup2 = dlsym(RTLD_NEXT, "dup2");
    167  1.1  pooka 
    168  1.1  pooka 	for (i = 0; i < RUMPCALL__NUM; i++) {
    169  1.1  pooka 		char sysname[128];
    170  1.1  pooka 
    171  1.1  pooka 		snprintf(sysname, sizeof(sysname), "rump_sys_%s", sysnames[i]);
    172  1.1  pooka 		rumpcalls[i] = dlsym(hand, sysname);
    173  1.1  pooka 		if (!rumpcalls[i]) {
    174  1.3  pooka 			fprintf(stderr, "cannot find symbol: %s\n", sysname);
    175  1.1  pooka 			exit(1);
    176  1.1  pooka 		}
    177  1.1  pooka 	}
    178  1.1  pooka 
    179  1.1  pooka 	if (rumpcinit() == -1)
    180  1.1  pooka 		err(1, "rumpclient init");
    181  1.1  pooka }
    182  1.1  pooka 
    183  1.5  pooka static unsigned dup2mask;
    184  1.5  pooka #define ISDUP2D(fd) (((fd+1) & dup2mask) == ((fd)+1))
    185  1.5  pooka 
    186  1.1  pooka //#define DEBUGJACK
    187  1.1  pooka #ifdef DEBUGJACK
    188  1.5  pooka #define DPRINTF(x) mydprintf x
    189  1.5  pooka static void
    190  1.5  pooka mydprintf(const char *fmt, ...)
    191  1.5  pooka {
    192  1.5  pooka 	va_list ap;
    193  1.5  pooka 
    194  1.5  pooka 	if (ISDUP2D(STDERR_FILENO))
    195  1.5  pooka 		return;
    196  1.5  pooka 
    197  1.5  pooka 	va_start(ap, fmt);
    198  1.5  pooka 	vfprintf(stderr, fmt, ap);
    199  1.5  pooka 	va_end(ap);
    200  1.5  pooka }
    201  1.5  pooka 
    202  1.1  pooka #else
    203  1.1  pooka #define DPRINTF(x)
    204  1.1  pooka #endif
    205  1.1  pooka 
    206  1.2  pooka /* XXX: need runtime selection.  low for now due to FD_SETSIZE */
    207  1.2  pooka #define HIJACK_FDOFF 128
    208  1.2  pooka #define HIJACK_SELECT 128 /* XXX */
    209  1.2  pooka #define HIJACK_ASSERT 128 /* XXX */
    210  1.2  pooka static int
    211  1.2  pooka fd_rump2host(int fd)
    212  1.2  pooka {
    213  1.2  pooka 
    214  1.2  pooka 	if (fd == -1)
    215  1.2  pooka 		return fd;
    216  1.2  pooka 
    217  1.2  pooka 	if (!ISDUP2D(fd))
    218  1.2  pooka 		fd += HIJACK_FDOFF;
    219  1.2  pooka 
    220  1.2  pooka 	return fd;
    221  1.2  pooka }
    222  1.2  pooka 
    223  1.2  pooka static int
    224  1.2  pooka fd_host2rump(int fd)
    225  1.2  pooka {
    226  1.2  pooka 
    227  1.2  pooka 	if (!ISDUP2D(fd))
    228  1.2  pooka 		fd -= HIJACK_FDOFF;
    229  1.2  pooka 	return fd;
    230  1.2  pooka }
    231  1.2  pooka 
    232  1.2  pooka static bool
    233  1.2  pooka fd_isrump(int fd)
    234  1.2  pooka {
    235  1.2  pooka 
    236  1.2  pooka 	return ISDUP2D(fd) || fd >= HIJACK_FDOFF;
    237  1.2  pooka }
    238  1.2  pooka 
    239  1.2  pooka #define assertfd(_fd_) assert(ISDUP2D(_fd_) || (_fd_) >= HIJACK_ASSERT)
    240  1.2  pooka #undef HIJACK_FDOFF
    241  1.2  pooka 
    242  1.1  pooka /*
    243  1.1  pooka  * Following wrappers always call the rump kernel.
    244  1.1  pooka  */
    245  1.1  pooka 
    246  1.1  pooka int __socket30(int, int, int);
    247  1.1  pooka int
    248  1.1  pooka __socket30(int domain, int type, int protocol)
    249  1.1  pooka {
    250  1.1  pooka 	int (*rc_socket)(int, int, int);
    251  1.1  pooka 	int fd;
    252  1.7  pooka 	bool dohost;
    253  1.7  pooka 
    254  1.7  pooka 	dohost = hostlocalsockets && (domain == AF_LOCAL);
    255  1.1  pooka 
    256  1.7  pooka 	if (dohost)
    257  1.7  pooka 		rc_socket = host_socket;
    258  1.7  pooka 	else
    259  1.7  pooka 		rc_socket = rumpcalls[RUMPCALL_SOCKET];
    260  1.1  pooka 	fd = rc_socket(domain, type, protocol);
    261  1.2  pooka 
    262  1.7  pooka 	if (!dohost)
    263  1.7  pooka 		fd = fd_rump2host(fd);
    264  1.7  pooka 	DPRINTF(("socket <- %d\n", fd));
    265  1.2  pooka 
    266  1.7  pooka 	return fd;
    267  1.1  pooka }
    268  1.1  pooka 
    269  1.1  pooka int
    270  1.1  pooka accept(int s, struct sockaddr *addr, socklen_t *addrlen)
    271  1.1  pooka {
    272  1.1  pooka 	int (*rc_accept)(int, struct sockaddr *, socklen_t *);
    273  1.1  pooka 	int fd;
    274  1.7  pooka 	bool isrump;
    275  1.7  pooka 
    276  1.7  pooka 	isrump = fd_isrump(s);
    277  1.1  pooka 
    278  1.2  pooka 	DPRINTF(("accept -> %d", s));
    279  1.7  pooka 	if (isrump) {
    280  1.7  pooka 		rc_accept = rumpcalls[RUMPCALL_ACCEPT];
    281  1.7  pooka 		s = fd_host2rump(s);
    282  1.7  pooka 	} else {
    283  1.7  pooka 		rc_accept = host_accept;
    284  1.7  pooka 	}
    285  1.7  pooka 	fd = rc_accept(s, addr, addrlen);
    286  1.7  pooka 	if (fd != -1 && isrump)
    287  1.7  pooka 		fd = fd_rump2host(fd);
    288  1.7  pooka 
    289  1.7  pooka 	DPRINTF((" <- %d\n", fd));
    290  1.2  pooka 
    291  1.7  pooka 	return fd;
    292  1.1  pooka }
    293  1.1  pooka 
    294  1.1  pooka int
    295  1.1  pooka bind(int s, const struct sockaddr *name, socklen_t namelen)
    296  1.1  pooka {
    297  1.1  pooka 	int (*rc_bind)(int, const struct sockaddr *, socklen_t);
    298  1.1  pooka 
    299  1.2  pooka 	DPRINTF(("bind -> %d\n", s));
    300  1.7  pooka 	if (fd_isrump(s)) {
    301  1.7  pooka 		rc_bind = rumpcalls[RUMPCALL_BIND];
    302  1.7  pooka 		s = fd_host2rump(s);
    303  1.7  pooka 	} else {
    304  1.7  pooka 		rc_bind = host_bind;
    305  1.7  pooka 	}
    306  1.7  pooka 	return rc_bind(s, name, namelen);
    307  1.1  pooka }
    308  1.1  pooka 
    309  1.1  pooka int
    310  1.1  pooka connect(int s, const struct sockaddr *name, socklen_t namelen)
    311  1.1  pooka {
    312  1.1  pooka 	int (*rc_connect)(int, const struct sockaddr *, socklen_t);
    313  1.1  pooka 
    314  1.2  pooka 	DPRINTF(("connect -> %d\n", s));
    315  1.7  pooka 	if (fd_isrump(s)) {
    316  1.7  pooka 		rc_connect = rumpcalls[RUMPCALL_CONNECT];
    317  1.7  pooka 		s = fd_host2rump(s);
    318  1.7  pooka 	} else {
    319  1.7  pooka 		rc_connect = host_connect;
    320  1.7  pooka 	}
    321  1.2  pooka 
    322  1.7  pooka 	return rc_connect(s, name, namelen);
    323  1.1  pooka }
    324  1.1  pooka 
    325  1.1  pooka int
    326  1.1  pooka getpeername(int s, struct sockaddr *name, socklen_t *namelen)
    327  1.1  pooka {
    328  1.1  pooka 	int (*rc_getpeername)(int, struct sockaddr *, socklen_t *);
    329  1.1  pooka 
    330  1.2  pooka 	DPRINTF(("getpeername -> %d\n", s));
    331  1.7  pooka 	if (fd_isrump(s)) {
    332  1.7  pooka 		rc_getpeername = rumpcalls[RUMPCALL_GETPEERNAME];
    333  1.7  pooka 		s = fd_host2rump(s);
    334  1.7  pooka 	} else {
    335  1.7  pooka 		rc_getpeername = host_getpeername;
    336  1.7  pooka 	}
    337  1.7  pooka 	return rc_getpeername(s, name, namelen);
    338  1.1  pooka }
    339  1.1  pooka 
    340  1.1  pooka int
    341  1.1  pooka getsockname(int s, struct sockaddr *name, socklen_t *namelen)
    342  1.1  pooka {
    343  1.1  pooka 	int (*rc_getsockname)(int, struct sockaddr *, socklen_t *);
    344  1.1  pooka 
    345  1.2  pooka 	DPRINTF(("getsockname -> %d\n", s));
    346  1.7  pooka 	if (fd_isrump(s)) {
    347  1.7  pooka 		rc_getsockname = rumpcalls[RUMPCALL_GETSOCKNAME];
    348  1.7  pooka 		s = fd_host2rump(s);
    349  1.7  pooka 	} else {
    350  1.7  pooka 		rc_getsockname = host_getsockname;
    351  1.7  pooka 	}
    352  1.7  pooka 	return rc_getsockname(s, name, namelen);
    353  1.1  pooka }
    354  1.1  pooka 
    355  1.1  pooka int
    356  1.1  pooka listen(int s, int backlog)
    357  1.1  pooka {
    358  1.1  pooka 	int (*rc_listen)(int, int);
    359  1.1  pooka 
    360  1.2  pooka 	DPRINTF(("listen -> %d\n", s));
    361  1.7  pooka 	if (fd_isrump(s)) {
    362  1.7  pooka 		rc_listen = rumpcalls[RUMPCALL_LISTEN];
    363  1.7  pooka 		s = fd_host2rump(s);
    364  1.7  pooka 	} else {
    365  1.7  pooka 		rc_listen = host_listen;
    366  1.7  pooka 	}
    367  1.7  pooka 	return rc_listen(s, backlog);
    368  1.1  pooka }
    369  1.1  pooka 
    370  1.1  pooka ssize_t
    371  1.1  pooka recv(int s, void *buf, size_t len, int flags)
    372  1.1  pooka {
    373  1.1  pooka 
    374  1.1  pooka 	return recvfrom(s, buf, len, flags, NULL, NULL);
    375  1.1  pooka }
    376  1.1  pooka 
    377  1.1  pooka ssize_t
    378  1.1  pooka recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from,
    379  1.1  pooka 	socklen_t *fromlen)
    380  1.1  pooka {
    381  1.1  pooka 	int (*rc_recvfrom)(int, void *, size_t, int,
    382  1.1  pooka 	    struct sockaddr *, socklen_t *);
    383  1.1  pooka 
    384  1.1  pooka 	DPRINTF(("recvfrom\n"));
    385  1.1  pooka 	assertfd(s);
    386  1.1  pooka 	rc_recvfrom = rumpcalls[RUMPCALL_RECVFROM];
    387  1.2  pooka 	return rc_recvfrom(fd_host2rump(s), buf, len, flags, from, fromlen);
    388  1.1  pooka }
    389  1.1  pooka 
    390  1.1  pooka ssize_t
    391  1.1  pooka recvmsg(int s, struct msghdr *msg, int flags)
    392  1.1  pooka {
    393  1.1  pooka 	int (*rc_recvmsg)(int, struct msghdr *, int);
    394  1.1  pooka 
    395  1.1  pooka 	DPRINTF(("recvmsg\n"));
    396  1.1  pooka 	assertfd(s);
    397  1.1  pooka 	rc_recvmsg = rumpcalls[RUMPCALL_RECVMSG];
    398  1.2  pooka 	return rc_recvmsg(fd_host2rump(s), msg, flags);
    399  1.1  pooka }
    400  1.1  pooka 
    401  1.1  pooka ssize_t
    402  1.1  pooka send(int s, const void *buf, size_t len, int flags)
    403  1.1  pooka {
    404  1.1  pooka 
    405  1.1  pooka 	return sendto(s, buf, len, flags, NULL, 0);
    406  1.1  pooka }
    407  1.1  pooka 
    408  1.1  pooka ssize_t
    409  1.1  pooka sendto(int s, const void *buf, size_t len, int flags,
    410  1.1  pooka 	const struct sockaddr *to, socklen_t tolen)
    411  1.1  pooka {
    412  1.1  pooka 	int (*rc_sendto)(int, const void *, size_t, int,
    413  1.1  pooka 	    const struct sockaddr *, socklen_t);
    414  1.1  pooka 
    415  1.1  pooka 	if (s == -1)
    416  1.1  pooka 		return len;
    417  1.1  pooka 
    418  1.1  pooka 	DPRINTF(("sendto\n"));
    419  1.1  pooka 	assertfd(s);
    420  1.1  pooka 	rc_sendto = rumpcalls[RUMPCALL_SENDTO];
    421  1.2  pooka 	return rc_sendto(fd_host2rump(s), buf, len, flags, to, tolen);
    422  1.1  pooka }
    423  1.1  pooka 
    424  1.1  pooka ssize_t
    425  1.1  pooka sendmsg(int s, const struct msghdr *msg, int flags)
    426  1.1  pooka {
    427  1.1  pooka 	int (*rc_sendmsg)(int, const struct msghdr *, int);
    428  1.1  pooka 
    429  1.1  pooka 	DPRINTF(("sendmsg\n"));
    430  1.1  pooka 	assertfd(s);
    431  1.1  pooka 	rc_sendmsg = rumpcalls[RUMPCALL_SENDTO];
    432  1.2  pooka 	return rc_sendmsg(fd_host2rump(s), msg, flags);
    433  1.1  pooka }
    434  1.1  pooka 
    435  1.1  pooka int
    436  1.1  pooka getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
    437  1.1  pooka {
    438  1.1  pooka 	int (*rc_getsockopt)(int, int, int, void *, socklen_t *);
    439  1.1  pooka 
    440  1.7  pooka 	DPRINTF(("getsockopt -> %d\n", s));
    441  1.1  pooka 	assertfd(s);
    442  1.1  pooka 	rc_getsockopt = rumpcalls[RUMPCALL_GETSOCKOPT];
    443  1.2  pooka 	return rc_getsockopt(fd_host2rump(s), level, optname, optval, optlen);
    444  1.1  pooka }
    445  1.1  pooka 
    446  1.1  pooka int
    447  1.1  pooka setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
    448  1.1  pooka {
    449  1.1  pooka 	int (*rc_setsockopt)(int, int, int, const void *, socklen_t);
    450  1.1  pooka 
    451  1.7  pooka 	DPRINTF(("setsockopt -> %d\n", s));
    452  1.7  pooka 	if (fd_isrump(s)) {
    453  1.7  pooka 		rc_setsockopt = rumpcalls[RUMPCALL_SETSOCKOPT];
    454  1.7  pooka 		s = fd_host2rump(s);
    455  1.7  pooka 	} else {
    456  1.7  pooka 		rc_setsockopt = host_setsockopt;
    457  1.7  pooka 	}
    458  1.7  pooka 	return rc_setsockopt(s, level, optname, optval, optlen);
    459  1.1  pooka }
    460  1.1  pooka 
    461  1.1  pooka int
    462  1.1  pooka shutdown(int s, int how)
    463  1.1  pooka {
    464  1.1  pooka 	int (*rc_shutdown)(int, int);
    465  1.1  pooka 
    466  1.7  pooka 	DPRINTF(("shutdown -> %d\n", s));
    467  1.1  pooka 	assertfd(s);
    468  1.1  pooka 	rc_shutdown = rumpcalls[RUMPCALL_SHUTDOWN];
    469  1.2  pooka 	return rc_shutdown(fd_host2rump(s), how);
    470  1.2  pooka }
    471  1.2  pooka 
    472  1.2  pooka /*
    473  1.2  pooka  * dup2 is special.  we allow dup2 of a rump kernel fd to 0-2 since
    474  1.2  pooka  * many programs do that.  dup2 of a rump kernel fd to another value
    475  1.2  pooka  * not >= fdoff is an error.
    476  1.2  pooka  *
    477  1.2  pooka  * Note: cannot rump2host newd, because it is often hardcoded.
    478  1.2  pooka  *
    479  1.2  pooka  * XXX: should disable debug prints after stdout/stderr are dup2'd
    480  1.2  pooka  */
    481  1.2  pooka int
    482  1.2  pooka dup2(int oldd, int newd)
    483  1.2  pooka {
    484  1.2  pooka 	int rv;
    485  1.2  pooka 
    486  1.2  pooka 	DPRINTF(("dup2 -> %d (o) -> %d (n)\n", oldd, newd));
    487  1.2  pooka 
    488  1.2  pooka 	if (fd_isrump(oldd)) {
    489  1.2  pooka 		if (!(newd >= 0 && newd <= 2))
    490  1.2  pooka 			return EBADF;
    491  1.2  pooka 		oldd = fd_host2rump(oldd);
    492  1.2  pooka 		rv = rump_sys_dup2(oldd, newd);
    493  1.2  pooka 		if (rv != -1)
    494  1.2  pooka 			dup2mask |= newd+1;
    495  1.2  pooka 		return rv;
    496  1.2  pooka 	} else {
    497  1.2  pooka 		return host_dup2(oldd, newd);
    498  1.2  pooka 	}
    499  1.2  pooka }
    500  1.2  pooka 
    501  1.2  pooka /*
    502  1.2  pooka  * We just wrap fork the appropriate rump client calls to preserve
    503  1.2  pooka  * the file descriptors of the forked parent in the child, but
    504  1.2  pooka  * prevent double use of connection fd.
    505  1.2  pooka  */
    506  1.2  pooka 
    507  1.2  pooka pid_t
    508  1.2  pooka fork()
    509  1.2  pooka {
    510  1.2  pooka 	struct rumpclient_fork *rf;
    511  1.2  pooka 	pid_t rv;
    512  1.2  pooka 
    513  1.2  pooka 	DPRINTF(("fork\n"));
    514  1.2  pooka 
    515  1.2  pooka 	if ((rf = rumpclient_prefork()) == NULL)
    516  1.2  pooka 		return -1;
    517  1.2  pooka 
    518  1.2  pooka 	switch ((rv = host_fork())) {
    519  1.2  pooka 	case -1:
    520  1.2  pooka 		/* XXX: cancel rf */
    521  1.2  pooka 		break;
    522  1.2  pooka 	case 0:
    523  1.2  pooka 		if (rumpclient_fork_init(rf) == -1)
    524  1.2  pooka 			rv = -1;
    525  1.2  pooka 		break;
    526  1.2  pooka 	default:
    527  1.2  pooka 		break;
    528  1.2  pooka 	}
    529  1.2  pooka 
    530  1.2  pooka 	DPRINTF(("fork returns %d\n", rv));
    531  1.2  pooka 	return rv;
    532  1.1  pooka }
    533  1.1  pooka 
    534  1.1  pooka /*
    535  1.1  pooka  * Hybrids
    536  1.1  pooka  */
    537  1.1  pooka 
    538  1.1  pooka ssize_t
    539  1.1  pooka read(int fd, void *buf, size_t len)
    540  1.1  pooka {
    541  1.1  pooka 	int (*op_read)(int, void *, size_t);
    542  1.1  pooka 	ssize_t n;
    543  1.1  pooka 
    544  1.1  pooka 	DPRINTF(("read %d\n", fd));
    545  1.2  pooka 	if (fd_isrump(fd)) {
    546  1.2  pooka 		fd = fd_host2rump(fd);
    547  1.2  pooka 		op_read = rumpcalls[RUMPCALL_READ];
    548  1.2  pooka 	} else {
    549  1.1  pooka 		op_read = host_read;
    550  1.1  pooka 	}
    551  1.1  pooka 
    552  1.1  pooka 	n = op_read(fd, buf, len);
    553  1.1  pooka 	return n;
    554  1.1  pooka }
    555  1.1  pooka 
    556  1.1  pooka ssize_t
    557  1.1  pooka readv(int fd, const struct iovec *iov, int iovcnt)
    558  1.1  pooka {
    559  1.1  pooka 	int (*op_readv)(int, const struct iovec *, int);
    560  1.1  pooka 
    561  1.7  pooka 	DPRINTF(("readv %d\n", fd));
    562  1.2  pooka 	if (fd_isrump(fd)) {
    563  1.2  pooka 		fd = fd_host2rump(fd);
    564  1.2  pooka 		op_readv = rumpcalls[RUMPCALL_READV];
    565  1.2  pooka 	} else {
    566  1.1  pooka 		op_readv = host_readv;
    567  1.1  pooka 	}
    568  1.1  pooka 
    569  1.1  pooka 	return op_readv(fd, iov, iovcnt);
    570  1.1  pooka }
    571  1.1  pooka 
    572  1.1  pooka ssize_t
    573  1.1  pooka write(int fd, const void *buf, size_t len)
    574  1.1  pooka {
    575  1.1  pooka 	int (*op_write)(int, const void *, size_t);
    576  1.1  pooka 
    577  1.2  pooka 	if (fd_isrump(fd)) {
    578  1.2  pooka 		fd = fd_host2rump(fd);
    579  1.2  pooka 		op_write = rumpcalls[RUMPCALL_WRITE];
    580  1.2  pooka 	} else {
    581  1.1  pooka 		op_write = host_write;
    582  1.1  pooka 	}
    583  1.1  pooka 
    584  1.1  pooka 	return op_write(fd, buf, len);
    585  1.1  pooka }
    586  1.1  pooka 
    587  1.1  pooka ssize_t
    588  1.1  pooka writev(int fd, const struct iovec *iov, int iovcnt)
    589  1.1  pooka {
    590  1.1  pooka 	int (*op_writev)(int, const struct iovec *, int);
    591  1.1  pooka 
    592  1.7  pooka 	DPRINTF(("writev %d\n", fd));
    593  1.2  pooka 	if (fd_isrump(fd)) {
    594  1.2  pooka 		fd = fd_host2rump(fd);
    595  1.2  pooka 		op_writev = rumpcalls[RUMPCALL_WRITEV];
    596  1.2  pooka 	} else {
    597  1.1  pooka 		op_writev = host_writev;
    598  1.1  pooka 	}
    599  1.1  pooka 
    600  1.1  pooka 	return op_writev(fd, iov, iovcnt);
    601  1.1  pooka }
    602  1.1  pooka 
    603  1.1  pooka int
    604  1.1  pooka ioctl(int fd, unsigned long cmd, ...)
    605  1.1  pooka {
    606  1.1  pooka 	int (*op_ioctl)(int, unsigned long cmd, ...);
    607  1.1  pooka 	va_list ap;
    608  1.1  pooka 	int rv;
    609  1.1  pooka 
    610  1.1  pooka 	DPRINTF(("ioctl\n"));
    611  1.2  pooka 	if (fd_isrump(fd)) {
    612  1.2  pooka 		fd = fd_host2rump(fd);
    613  1.2  pooka 		op_ioctl = rumpcalls[RUMPCALL_IOCTL];
    614  1.2  pooka 	} else {
    615  1.1  pooka 		op_ioctl = host_ioctl;
    616  1.1  pooka 	}
    617  1.1  pooka 
    618  1.1  pooka 	va_start(ap, cmd);
    619  1.1  pooka 	rv = op_ioctl(fd, cmd, va_arg(ap, void *));
    620  1.1  pooka 	va_end(ap);
    621  1.1  pooka 	return rv;
    622  1.1  pooka }
    623  1.1  pooka 
    624  1.1  pooka int
    625  1.1  pooka fcntl(int fd, int cmd, ...)
    626  1.1  pooka {
    627  1.1  pooka 	int (*op_fcntl)(int, int, ...);
    628  1.1  pooka 	va_list ap;
    629  1.1  pooka 	int rv;
    630  1.1  pooka 
    631  1.1  pooka 	DPRINTF(("fcntl\n"));
    632  1.2  pooka 	if (fd_isrump(fd)) {
    633  1.2  pooka 		fd = fd_host2rump(fd);
    634  1.2  pooka 		op_fcntl = rumpcalls[RUMPCALL_FCNTL];
    635  1.2  pooka 	} else {
    636  1.1  pooka 		op_fcntl = host_fcntl;
    637  1.1  pooka 	}
    638  1.1  pooka 
    639  1.1  pooka 	va_start(ap, cmd);
    640  1.1  pooka 	rv = op_fcntl(fd, cmd, va_arg(ap, void *));
    641  1.1  pooka 	va_end(ap);
    642  1.1  pooka 	return rv;
    643  1.1  pooka }
    644  1.1  pooka 
    645  1.1  pooka int
    646  1.1  pooka close(int fd)
    647  1.1  pooka {
    648  1.1  pooka 	int (*op_close)(int);
    649  1.1  pooka 
    650  1.1  pooka 	DPRINTF(("close %d\n", fd));
    651  1.2  pooka 	if (fd_isrump(fd)) {
    652  1.2  pooka 		fd = fd_host2rump(fd);
    653  1.2  pooka 		op_close = rumpcalls[RUMPCALL_CLOSE];
    654  1.2  pooka 	} else {
    655  1.1  pooka 		op_close = host_close;
    656  1.1  pooka 	}
    657  1.1  pooka 
    658  1.1  pooka 	return op_close(fd);
    659  1.1  pooka }
    660  1.1  pooka 
    661  1.4  pooka int
    662  1.4  pooka select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
    663  1.4  pooka 	struct timeval *timeout)
    664  1.1  pooka {
    665  1.4  pooka 	struct pollfd *pfds;
    666  1.4  pooka 	struct timespec ts, *tsp = NULL;
    667  1.4  pooka 	nfds_t i, j, realnfds;
    668  1.4  pooka 	int rv, incr;
    669  1.4  pooka 
    670  1.7  pooka 	DPRINTF(("select\n"));
    671  1.7  pooka 
    672  1.4  pooka 	/*
    673  1.4  pooka 	 * Well, first we must scan the fds to figure out how many
    674  1.4  pooka 	 * fds there really are.  This is because up to and including
    675  1.4  pooka 	 * nb5 poll() silently refuses nfds > process_open_fds.
    676  1.4  pooka 	 * Seems to be fixed in current, thank the maker.
    677  1.4  pooka 	 * god damn cluster...bomb.
    678  1.4  pooka 	 */
    679  1.4  pooka 
    680  1.4  pooka 	for (i = 0, realnfds = 0; i < nfds; i++) {
    681  1.4  pooka 		if (readfds && FD_ISSET(i, readfds)) {
    682  1.4  pooka 			realnfds++;
    683  1.4  pooka 			continue;
    684  1.4  pooka 		}
    685  1.4  pooka 		if (writefds && FD_ISSET(i, writefds)) {
    686  1.4  pooka 			realnfds++;
    687  1.4  pooka 			continue;
    688  1.4  pooka 		}
    689  1.4  pooka 		if (exceptfds && FD_ISSET(i, exceptfds)) {
    690  1.4  pooka 			realnfds++;
    691  1.4  pooka 			continue;
    692  1.1  pooka 		}
    693  1.1  pooka 	}
    694  1.1  pooka 
    695  1.6  pooka 	if (realnfds) {
    696  1.6  pooka 		pfds = malloc(sizeof(*pfds) * realnfds);
    697  1.6  pooka 		if (!pfds)
    698  1.6  pooka 			return -1;
    699  1.6  pooka 	} else {
    700  1.6  pooka 		pfds = NULL;
    701  1.6  pooka 	}
    702  1.1  pooka 
    703  1.4  pooka 	for (i = 0, j = 0; i < nfds; i++) {
    704  1.4  pooka 		incr = 0;
    705  1.4  pooka 		pfds[j].events = pfds[j].revents = 0;
    706  1.4  pooka 		if (readfds && FD_ISSET(i, readfds)) {
    707  1.4  pooka 			pfds[j].fd = i;
    708  1.4  pooka 			pfds[j].events |= POLLIN;
    709  1.4  pooka 			incr=1;
    710  1.4  pooka 		}
    711  1.4  pooka 		if (writefds && FD_ISSET(i, writefds)) {
    712  1.4  pooka 			pfds[j].fd = i;
    713  1.4  pooka 			pfds[j].events |= POLLOUT;
    714  1.4  pooka 			incr=1;
    715  1.4  pooka 		}
    716  1.4  pooka 		if (exceptfds && FD_ISSET(i, exceptfds)) {
    717  1.4  pooka 			pfds[j].fd = i;
    718  1.4  pooka 			pfds[j].events |= POLLHUP|POLLERR;
    719  1.4  pooka 			incr=1;
    720  1.1  pooka 		}
    721  1.4  pooka 		if (incr)
    722  1.4  pooka 			j++;
    723  1.1  pooka 	}
    724  1.1  pooka 
    725  1.4  pooka 	if (timeout) {
    726  1.4  pooka 		TIMEVAL_TO_TIMESPEC(timeout, &ts);
    727  1.4  pooka 		tsp = &ts;
    728  1.4  pooka 	}
    729  1.4  pooka 	rv = pollts(pfds, realnfds, tsp, NULL);
    730  1.4  pooka 	if (rv <= 0)
    731  1.4  pooka 		goto out;
    732  1.4  pooka 
    733  1.4  pooka 	/*
    734  1.4  pooka 	 * ok, harvest results.  first zero out entries (can't use
    735  1.4  pooka 	 * FD_ZERO for the obvious select-me-not reason).  whee.
    736  1.4  pooka 	 */
    737  1.4  pooka 	for (i = 0; i < nfds; i++) {
    738  1.4  pooka 		if (readfds)
    739  1.4  pooka 			FD_CLR(i, readfds);
    740  1.4  pooka 		if (writefds)
    741  1.4  pooka 			FD_CLR(i, writefds);
    742  1.4  pooka 		if (exceptfds)
    743  1.4  pooka 			FD_CLR(i, exceptfds);
    744  1.1  pooka 	}
    745  1.1  pooka 
    746  1.4  pooka 	/* and then plug in the results */
    747  1.4  pooka 	for (i = 0; i < realnfds; i++) {
    748  1.4  pooka 		if (readfds) {
    749  1.4  pooka 			if (pfds[i].revents & POLLIN) {
    750  1.4  pooka 				FD_SET(pfds[i].fd, readfds);
    751  1.4  pooka 			}
    752  1.4  pooka 		}
    753  1.4  pooka 		if (writefds) {
    754  1.4  pooka 			if (pfds[i].revents & POLLOUT) {
    755  1.4  pooka 				FD_SET(pfds[i].fd, writefds);
    756  1.4  pooka 			}
    757  1.4  pooka 		}
    758  1.4  pooka 		if (exceptfds) {
    759  1.4  pooka 			if (pfds[i].revents & (POLLHUP|POLLERR)) {
    760  1.4  pooka 				FD_SET(pfds[i].fd, exceptfds);
    761  1.4  pooka 			}
    762  1.4  pooka 		}
    763  1.1  pooka 	}
    764  1.1  pooka 
    765  1.4  pooka  out:
    766  1.4  pooka 	free(pfds);
    767  1.1  pooka 	return rv;
    768  1.1  pooka }
    769  1.1  pooka 
    770  1.1  pooka static void
    771  1.1  pooka checkpoll(struct pollfd *fds, nfds_t nfds, int *hostcall, int *rumpcall)
    772  1.1  pooka {
    773  1.1  pooka 	nfds_t i;
    774  1.1  pooka 
    775  1.1  pooka 	for (i = 0; i < nfds; i++) {
    776  1.2  pooka 		if (fd_isrump(fds[i].fd))
    777  1.2  pooka 			(*rumpcall)++;
    778  1.2  pooka 		else
    779  1.1  pooka 			(*hostcall)++;
    780  1.1  pooka 	}
    781  1.1  pooka }
    782  1.1  pooka 
    783  1.1  pooka static void
    784  1.2  pooka adjustpoll(struct pollfd *fds, nfds_t nfds, int (*fdadj)(int))
    785  1.1  pooka {
    786  1.1  pooka 	nfds_t i;
    787  1.1  pooka 
    788  1.1  pooka 	for (i = 0; i < nfds; i++) {
    789  1.2  pooka 		fds[i].fd = fdadj(fds[i].fd);
    790  1.1  pooka 	}
    791  1.1  pooka }
    792  1.1  pooka 
    793  1.3  pooka struct mytimespec {
    794  1.3  pooka 	uint64_t tv_sec;
    795  1.3  pooka 	long tv_nsec;
    796  1.3  pooka };
    797  1.3  pooka 
    798  1.1  pooka /*
    799  1.1  pooka  * poll is easy as long as the call comes in the fds only in one
    800  1.1  pooka  * kernel.  otherwise its quite tricky...
    801  1.1  pooka  */
    802  1.1  pooka struct pollarg {
    803  1.1  pooka 	struct pollfd *pfds;
    804  1.1  pooka 	nfds_t nfds;
    805  1.3  pooka 	const struct timespec *ts;
    806  1.3  pooka 	const sigset_t *sigmask;
    807  1.1  pooka 	int pipefd;
    808  1.1  pooka 	int errnum;
    809  1.1  pooka };
    810  1.1  pooka 
    811  1.1  pooka static void *
    812  1.1  pooka hostpoll(void *arg)
    813  1.1  pooka {
    814  1.1  pooka 	struct pollarg *parg = arg;
    815  1.1  pooka 	intptr_t rv;
    816  1.1  pooka 
    817  1.3  pooka 	rv = host_pollts(parg->pfds, parg->nfds, parg->ts, parg->sigmask);
    818  1.1  pooka 	if (rv == -1)
    819  1.1  pooka 		parg->errnum = errno;
    820  1.1  pooka 	rump_sys_write(parg->pipefd, &rv, sizeof(rv));
    821  1.1  pooka 
    822  1.1  pooka 	return (void *)(intptr_t)rv;
    823  1.1  pooka }
    824  1.1  pooka 
    825  1.1  pooka int
    826  1.3  pooka pollts(struct pollfd *fds, nfds_t nfds, const struct timespec *ts,
    827  1.3  pooka 	const sigset_t *sigmask)
    828  1.1  pooka {
    829  1.3  pooka 	int (*op_pollts)(struct pollfd *, nfds_t, const struct timespec *,
    830  1.3  pooka 			 const sigset_t *);
    831  1.1  pooka 	int hostcall = 0, rumpcall = 0;
    832  1.1  pooka 	pthread_t pt;
    833  1.1  pooka 	nfds_t i;
    834  1.1  pooka 	int rv;
    835  1.1  pooka 
    836  1.3  pooka #if 0
    837  1.3  pooka 	/* XXX: quick 5.0 kludge.  do syscall compat in rumpclient properly */
    838  1.3  pooka 	struct mytimespec mts;
    839  1.3  pooka 	if (ts) {
    840  1.3  pooka 		mts.tv_sec = ts->tv_sec;
    841  1.3  pooka 		mts.tv_nsec = ts->tv_nsec;
    842  1.3  pooka 		ts = (struct timespec *)&mts;
    843  1.3  pooka 	}
    844  1.3  pooka #endif
    845  1.3  pooka 
    846  1.2  pooka 	DPRINTF(("poll\n"));
    847  1.1  pooka 	checkpoll(fds, nfds, &hostcall, &rumpcall);
    848  1.1  pooka 
    849  1.1  pooka 	if (hostcall && rumpcall) {
    850  1.1  pooka 		struct pollfd *pfd_host = NULL, *pfd_rump = NULL;
    851  1.1  pooka 		int rpipe[2] = {-1,-1}, hpipe[2] = {-1,-1};
    852  1.1  pooka 		struct pollarg parg;
    853  1.1  pooka 		uintptr_t lrv;
    854  1.1  pooka 		int sverrno = 0, trv;
    855  1.1  pooka 
    856  1.1  pooka 		/*
    857  1.1  pooka 		 * ok, this is where it gets tricky.  We must support
    858  1.1  pooka 		 * this since it's a very common operation in certain
    859  1.1  pooka 		 * types of software (telnet, netcat, etc).  We allocate
    860  1.1  pooka 		 * two vectors and run two poll commands in separate
    861  1.1  pooka 		 * threads.  Whichever returns first "wins" and the
    862  1.1  pooka 		 * other kernel's fds won't show activity.
    863  1.1  pooka 		 */
    864  1.1  pooka 		rv = -1;
    865  1.1  pooka 
    866  1.1  pooka 		/* allocate full vector for O(n) joining after call */
    867  1.1  pooka 		pfd_host = malloc(sizeof(*pfd_host)*(nfds+1));
    868  1.1  pooka 		if (!pfd_host)
    869  1.1  pooka 			goto out;
    870  1.1  pooka 		pfd_rump = malloc(sizeof(*pfd_rump)*(nfds+1));
    871  1.1  pooka 		if (!pfd_rump) {
    872  1.1  pooka 			goto out;
    873  1.1  pooka 		}
    874  1.1  pooka 
    875  1.1  pooka 		/* split vectors */
    876  1.1  pooka 		for (i = 0; i < nfds; i++) {
    877  1.3  pooka 			if (fds[i].fd == -1) {
    878  1.3  pooka 				pfd_host[i].fd = -1;
    879  1.3  pooka 				pfd_rump[i].fd = -1;
    880  1.3  pooka 			} else if (fd_isrump(fds[i].fd)) {
    881  1.2  pooka 				pfd_host[i].fd = -1;
    882  1.2  pooka 				pfd_rump[i].fd = fd_host2rump(fds[i].fd);
    883  1.2  pooka 				pfd_rump[i].events = fds[i].events;
    884  1.2  pooka 			} else {
    885  1.2  pooka 				pfd_rump[i].fd = -1;
    886  1.1  pooka 				pfd_host[i].fd = fds[i].fd;
    887  1.1  pooka 				pfd_host[i].events = fds[i].events;
    888  1.1  pooka 			}
    889  1.1  pooka 		}
    890  1.1  pooka 
    891  1.1  pooka 		/*
    892  1.1  pooka 		 * then, open two pipes, one for notifications
    893  1.1  pooka 		 * to each kernel.
    894  1.1  pooka 		 */
    895  1.1  pooka 		if (rump_sys_pipe(rpipe) == -1)
    896  1.1  pooka 			goto out;
    897  1.1  pooka 		if (pipe(hpipe) == -1)
    898  1.1  pooka 			goto out;
    899  1.1  pooka 
    900  1.1  pooka 		pfd_host[nfds].fd = hpipe[0];
    901  1.1  pooka 		pfd_host[nfds].events = POLLIN;
    902  1.1  pooka 		pfd_rump[nfds].fd = rpipe[0];
    903  1.1  pooka 		pfd_rump[nfds].events = POLLIN;
    904  1.1  pooka 
    905  1.1  pooka 		/*
    906  1.1  pooka 		 * then, create a thread to do host part and meanwhile
    907  1.1  pooka 		 * do rump kernel part right here
    908  1.1  pooka 		 */
    909  1.1  pooka 
    910  1.1  pooka 		parg.pfds = pfd_host;
    911  1.1  pooka 		parg.nfds = nfds+1;
    912  1.3  pooka 		parg.ts = ts;
    913  1.3  pooka 		parg.sigmask = sigmask;
    914  1.1  pooka 		parg.pipefd = rpipe[1];
    915  1.1  pooka 		pthread_create(&pt, NULL, hostpoll, &parg);
    916  1.1  pooka 
    917  1.3  pooka 		op_pollts = rumpcalls[RUMPCALL_POLLTS];
    918  1.3  pooka 		lrv = op_pollts(pfd_rump, nfds+1, ts, NULL);
    919  1.1  pooka 		sverrno = errno;
    920  1.1  pooka 		write(hpipe[1], &rv, sizeof(rv));
    921  1.1  pooka 		pthread_join(pt, (void *)&trv);
    922  1.1  pooka 
    923  1.1  pooka 		/* check who "won" and merge results */
    924  1.1  pooka 		if (lrv != 0 && pfd_host[nfds].revents & POLLIN) {
    925  1.1  pooka 			rv = trv;
    926  1.1  pooka 
    927  1.1  pooka 			for (i = 0; i < nfds; i++) {
    928  1.1  pooka 				if (pfd_rump[i].fd != -1)
    929  1.1  pooka 					fds[i].revents = pfd_rump[i].revents;
    930  1.1  pooka 			}
    931  1.1  pooka 			sverrno = parg.errnum;
    932  1.1  pooka 		} else if (trv != 0 && pfd_rump[nfds].revents & POLLIN) {
    933  1.1  pooka 			rv = trv;
    934  1.1  pooka 
    935  1.1  pooka 			for (i = 0; i < nfds; i++) {
    936  1.1  pooka 				if (pfd_host[i].fd != -1)
    937  1.1  pooka 					fds[i].revents = pfd_host[i].revents;
    938  1.1  pooka 			}
    939  1.1  pooka 		} else {
    940  1.1  pooka 			rv = 0;
    941  1.1  pooka 		}
    942  1.1  pooka 
    943  1.1  pooka  out:
    944  1.1  pooka 		if (rpipe[0] != -1)
    945  1.1  pooka 			rump_sys_close(rpipe[0]);
    946  1.1  pooka 		if (rpipe[1] != -1)
    947  1.1  pooka 			rump_sys_close(rpipe[1]);
    948  1.1  pooka 		if (hpipe[0] != -1)
    949  1.1  pooka 			close(hpipe[0]);
    950  1.1  pooka 		if (hpipe[1] != -1)
    951  1.1  pooka 			close(hpipe[1]);
    952  1.1  pooka 		free(pfd_host);
    953  1.1  pooka 		free(pfd_rump);
    954  1.1  pooka 		errno = sverrno;
    955  1.1  pooka 	} else {
    956  1.1  pooka 		if (hostcall) {
    957  1.3  pooka 			op_pollts = host_pollts;
    958  1.1  pooka 		} else {
    959  1.3  pooka 			op_pollts = rumpcalls[RUMPCALL_POLLTS];
    960  1.2  pooka 			adjustpoll(fds, nfds, fd_host2rump);
    961  1.1  pooka 		}
    962  1.1  pooka 
    963  1.3  pooka 		rv = op_pollts(fds, nfds, ts, sigmask);
    964  1.1  pooka 		if (rumpcall)
    965  1.2  pooka 			adjustpoll(fds, nfds, fd_rump2host);
    966  1.1  pooka 	}
    967  1.1  pooka 
    968  1.1  pooka 	return rv;
    969  1.1  pooka }
    970  1.1  pooka 
    971  1.1  pooka int
    972  1.3  pooka poll(struct pollfd *fds, nfds_t nfds, int timeout)
    973  1.1  pooka {
    974  1.3  pooka 	struct timespec ts;
    975  1.3  pooka 	struct timespec *tsp = NULL;
    976  1.3  pooka 
    977  1.3  pooka 	if (timeout != INFTIM) {
    978  1.3  pooka 		ts.tv_sec = timeout / 1000;
    979  1.3  pooka 		ts.tv_nsec = (timeout % 1000) * 1000;
    980  1.3  pooka 
    981  1.3  pooka 		tsp = &ts;
    982  1.3  pooka 	}
    983  1.1  pooka 
    984  1.3  pooka 	return pollts(fds, nfds, tsp, NULL);
    985  1.1  pooka }
    986