Home | History | Annotate | Line # | Download | only in librumphijack
hijack.c revision 1.1
      1  1.1  pooka /*      $NetBSD: hijack.c,v 1.1 2011/01/07 19:52:43 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.1  pooka __RCSID("$NetBSD: hijack.c,v 1.1 2011/01/07 19:52:43 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.1  pooka #include <stdarg.h>
     49  1.1  pooka #include <stdio.h>
     50  1.1  pooka #include <stdlib.h>
     51  1.1  pooka #include <unistd.h>
     52  1.1  pooka 
     53  1.1  pooka /* XXX: need runtime selection.  low for now due to FD_SETSIZE */
     54  1.1  pooka #define HIJACK_FDOFF 128
     55  1.1  pooka 
     56  1.1  pooka enum {	RUMPCALL_SOCKET, RUMPCALL_ACCEPT, RUMPCALL_BIND, RUMPCALL_CONNECT,
     57  1.1  pooka 	RUMPCALL_GETPEERNAME, RUMPCALL_GETSOCKNAME, RUMPCALL_LISTEN,
     58  1.1  pooka 	RUMPCALL_RECVFROM, RUMPCALL_RECVMSG,
     59  1.1  pooka 	RUMPCALL_SENDTO, RUMPCALL_SENDMSG,
     60  1.1  pooka 	RUMPCALL_GETSOCKOPT, RUMPCALL_SETSOCKOPT,
     61  1.1  pooka 	RUMPCALL_SHUTDOWN,
     62  1.1  pooka 	RUMPCALL_READ, RUMPCALL_READV,
     63  1.1  pooka 	RUMPCALL_WRITE, RUMPCALL_WRITEV,
     64  1.1  pooka 	RUMPCALL_IOCTL, RUMPCALL_FCNTL,
     65  1.1  pooka 	RUMPCALL_CLOSE,
     66  1.1  pooka 	RUMPCALL_SELECT, RUMPCALL_POLL, RUMPCALL_POLLTS,
     67  1.1  pooka 	RUMPCALL__NUM
     68  1.1  pooka };
     69  1.1  pooka 
     70  1.1  pooka const char *sysnames[] = {
     71  1.1  pooka 	"__socket30",
     72  1.1  pooka 	"accept",
     73  1.1  pooka 	"bind",
     74  1.1  pooka 	"connect",
     75  1.1  pooka 	"getpeername",
     76  1.1  pooka 	"getsockname",
     77  1.1  pooka 	"listen",
     78  1.1  pooka 	"recvfrom",
     79  1.1  pooka 	"recvmsg",
     80  1.1  pooka 	"sendto",
     81  1.1  pooka 	"sendmsg",
     82  1.1  pooka 	"getsockopt",
     83  1.1  pooka 	"setsockopt",
     84  1.1  pooka 	"shutdown",
     85  1.1  pooka 	"read",
     86  1.1  pooka 	"readv",
     87  1.1  pooka 	"write",
     88  1.1  pooka 	"writev",
     89  1.1  pooka 	"ioctl",
     90  1.1  pooka 	"fcntl",
     91  1.1  pooka 	"close",
     92  1.1  pooka 	"__select50",
     93  1.1  pooka 	"poll",
     94  1.1  pooka 	"__pollts50",
     95  1.1  pooka };
     96  1.1  pooka 
     97  1.1  pooka static ssize_t	(*host_read)(int, void *, size_t);
     98  1.1  pooka static ssize_t	(*host_readv)(int, const struct iovec *, int);
     99  1.1  pooka static ssize_t	(*host_write)(int, const void *, size_t);
    100  1.1  pooka static ssize_t	(*host_writev)(int, const struct iovec *, int);
    101  1.1  pooka static int	(*host_ioctl)(int, unsigned long, ...);
    102  1.1  pooka static int	(*host_fcntl)(int, int, ...);
    103  1.1  pooka static int	(*host_close)(int);
    104  1.1  pooka static int	(*host_select)(int, fd_set *, fd_set *, fd_set *,
    105  1.1  pooka 			       struct timeval *);
    106  1.1  pooka static int	(*host_poll)(struct pollfd *, nfds_t, int);
    107  1.1  pooka #if 0
    108  1.1  pooka static int	(*host_pollts)(struct pollfd *, nfds_t,
    109  1.1  pooka 			       const struct timespec *, const sigset_t *);
    110  1.1  pooka #endif
    111  1.1  pooka 
    112  1.1  pooka #define assertfd(_fd_) assert((_fd_) >= HIJACK_FDOFF)
    113  1.1  pooka 
    114  1.1  pooka static void *rumpcalls[RUMPCALL__NUM];
    115  1.1  pooka 
    116  1.1  pooka /*
    117  1.1  pooka  * This is called from librumpclient in case of LD_PRELOAD.
    118  1.1  pooka  * It ensures correct RTLD_NEXT.
    119  1.1  pooka  */
    120  1.1  pooka static void *
    121  1.1  pooka hijackdlsym(void *handle, const char *symbol)
    122  1.1  pooka {
    123  1.1  pooka 
    124  1.1  pooka 	return dlsym(handle, symbol);
    125  1.1  pooka }
    126  1.1  pooka 
    127  1.1  pooka static void __attribute__((constructor))
    128  1.1  pooka rcinit(void)
    129  1.1  pooka {
    130  1.1  pooka 	int (*rumpcinit)(void);
    131  1.1  pooka 	void **rumpcdlsym;
    132  1.1  pooka 	void *hand;
    133  1.1  pooka 	int i;
    134  1.1  pooka 
    135  1.1  pooka 	hand = dlopen("librumpclient.so", RTLD_LAZY|RTLD_GLOBAL);
    136  1.1  pooka 	if (!hand)
    137  1.1  pooka 		err(1, "cannot open librumpclient.so");
    138  1.1  pooka 	rumpcinit = dlsym(hand, "rumpclient_init");
    139  1.1  pooka 	_DIAGASSERT(rumpcinit);
    140  1.1  pooka 
    141  1.1  pooka 	rumpcdlsym = dlsym(hand, "rumpclient_dlsym");
    142  1.1  pooka 	*rumpcdlsym = hijackdlsym;
    143  1.1  pooka 
    144  1.1  pooka 	host_read = dlsym(RTLD_NEXT, "read");
    145  1.1  pooka 	host_readv = dlsym(RTLD_NEXT, "readv");
    146  1.1  pooka 	host_write = dlsym(RTLD_NEXT, "write");
    147  1.1  pooka 	host_writev = dlsym(RTLD_NEXT, "writev");
    148  1.1  pooka 	host_ioctl = dlsym(RTLD_NEXT, "ioctl");
    149  1.1  pooka 	host_fcntl = dlsym(RTLD_NEXT, "fcntl");
    150  1.1  pooka 	host_close = dlsym(RTLD_NEXT, "close");
    151  1.1  pooka 	host_select = dlsym(RTLD_NEXT, "select");
    152  1.1  pooka 	host_poll = dlsym(RTLD_NEXT, "poll");
    153  1.1  pooka 
    154  1.1  pooka 	for (i = 0; i < RUMPCALL__NUM; i++) {
    155  1.1  pooka 		char sysname[128];
    156  1.1  pooka 
    157  1.1  pooka 		snprintf(sysname, sizeof(sysname), "rump_sys_%s", sysnames[i]);
    158  1.1  pooka 		rumpcalls[i] = dlsym(hand, sysname);
    159  1.1  pooka 		if (!rumpcalls[i]) {
    160  1.1  pooka 			fprintf(stderr, "%s\n", sysname);
    161  1.1  pooka 			exit(1);
    162  1.1  pooka 		}
    163  1.1  pooka 	}
    164  1.1  pooka 
    165  1.1  pooka 	if (rumpcinit() == -1)
    166  1.1  pooka 		err(1, "rumpclient init");
    167  1.1  pooka }
    168  1.1  pooka 
    169  1.1  pooka #define ADJ(fd) (fd - HIJACK_FDOFF)
    170  1.1  pooka //#define DEBUGJACK
    171  1.1  pooka #ifdef DEBUGJACK
    172  1.1  pooka #define DPRINTF(x) printf x
    173  1.1  pooka #else
    174  1.1  pooka #define DPRINTF(x)
    175  1.1  pooka #endif
    176  1.1  pooka 
    177  1.1  pooka /*
    178  1.1  pooka  * Following wrappers always call the rump kernel.
    179  1.1  pooka  */
    180  1.1  pooka 
    181  1.1  pooka int __socket30(int, int, int);
    182  1.1  pooka int
    183  1.1  pooka __socket30(int domain, int type, int protocol)
    184  1.1  pooka {
    185  1.1  pooka 	int (*rc_socket)(int, int, int);
    186  1.1  pooka 	int fd;
    187  1.1  pooka 
    188  1.1  pooka 	DPRINTF(("socket\n"));
    189  1.1  pooka 	rc_socket = rumpcalls[RUMPCALL_SOCKET];
    190  1.1  pooka 	fd = rc_socket(domain, type, protocol);
    191  1.1  pooka 	if (fd != -1)
    192  1.1  pooka 		fd += HIJACK_FDOFF;
    193  1.1  pooka 	return fd;
    194  1.1  pooka }
    195  1.1  pooka 
    196  1.1  pooka int
    197  1.1  pooka accept(int s, struct sockaddr *addr, socklen_t *addrlen)
    198  1.1  pooka {
    199  1.1  pooka 	int (*rc_accept)(int, struct sockaddr *, socklen_t *);
    200  1.1  pooka 	int fd;
    201  1.1  pooka 
    202  1.1  pooka 	DPRINTF(("accept %d\n", s));
    203  1.1  pooka 	assertfd(s);
    204  1.1  pooka 	rc_accept = rumpcalls[RUMPCALL_ACCEPT];
    205  1.1  pooka 	fd = rc_accept(ADJ(s), addr, addrlen);
    206  1.1  pooka 	if (fd != -1)
    207  1.1  pooka 		fd += HIJACK_FDOFF;
    208  1.1  pooka 	return fd;
    209  1.1  pooka }
    210  1.1  pooka 
    211  1.1  pooka int
    212  1.1  pooka bind(int s, const struct sockaddr *name, socklen_t namelen)
    213  1.1  pooka {
    214  1.1  pooka 	int (*rc_bind)(int, const struct sockaddr *, socklen_t);
    215  1.1  pooka 
    216  1.1  pooka 	DPRINTF(("bind\n"));
    217  1.1  pooka 	assertfd(s);
    218  1.1  pooka 	rc_bind = rumpcalls[RUMPCALL_BIND];
    219  1.1  pooka 	return rc_bind(ADJ(s), name, namelen);
    220  1.1  pooka }
    221  1.1  pooka 
    222  1.1  pooka int
    223  1.1  pooka connect(int s, const struct sockaddr *name, socklen_t namelen)
    224  1.1  pooka {
    225  1.1  pooka 	int (*rc_connect)(int, const struct sockaddr *, socklen_t);
    226  1.1  pooka 
    227  1.1  pooka 	DPRINTF(("connect %d\n", s));
    228  1.1  pooka 	assertfd(s);
    229  1.1  pooka 	rc_connect = rumpcalls[RUMPCALL_CONNECT];
    230  1.1  pooka 	return rc_connect(ADJ(s), name, namelen);
    231  1.1  pooka }
    232  1.1  pooka 
    233  1.1  pooka int
    234  1.1  pooka getpeername(int s, struct sockaddr *name, socklen_t *namelen)
    235  1.1  pooka {
    236  1.1  pooka 	int (*rc_getpeername)(int, struct sockaddr *, socklen_t *);
    237  1.1  pooka 
    238  1.1  pooka 	DPRINTF(("getpeername\n"));
    239  1.1  pooka 	assertfd(s);
    240  1.1  pooka 	rc_getpeername = rumpcalls[RUMPCALL_GETPEERNAME];
    241  1.1  pooka 	return rc_getpeername(ADJ(s), name, namelen);
    242  1.1  pooka }
    243  1.1  pooka 
    244  1.1  pooka int
    245  1.1  pooka getsockname(int s, struct sockaddr *name, socklen_t *namelen)
    246  1.1  pooka {
    247  1.1  pooka 	int (*rc_getsockname)(int, struct sockaddr *, socklen_t *);
    248  1.1  pooka 
    249  1.1  pooka 	DPRINTF(("getsockname\n"));
    250  1.1  pooka 	assertfd(s);
    251  1.1  pooka 	rc_getsockname = rumpcalls[RUMPCALL_GETSOCKNAME];
    252  1.1  pooka 	return rc_getsockname(ADJ(s), name, namelen);
    253  1.1  pooka }
    254  1.1  pooka 
    255  1.1  pooka int
    256  1.1  pooka listen(int s, int backlog)
    257  1.1  pooka {
    258  1.1  pooka 	int (*rc_listen)(int, int);
    259  1.1  pooka 
    260  1.1  pooka 	DPRINTF(("listen\n"));
    261  1.1  pooka 	assertfd(s);
    262  1.1  pooka 	rc_listen = rumpcalls[RUMPCALL_LISTEN];
    263  1.1  pooka 	return rc_listen(ADJ(s), backlog);
    264  1.1  pooka }
    265  1.1  pooka 
    266  1.1  pooka ssize_t
    267  1.1  pooka recv(int s, void *buf, size_t len, int flags)
    268  1.1  pooka {
    269  1.1  pooka 
    270  1.1  pooka 	return recvfrom(s, buf, len, flags, NULL, NULL);
    271  1.1  pooka }
    272  1.1  pooka 
    273  1.1  pooka ssize_t
    274  1.1  pooka recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from,
    275  1.1  pooka 	socklen_t *fromlen)
    276  1.1  pooka {
    277  1.1  pooka 	int (*rc_recvfrom)(int, void *, size_t, int,
    278  1.1  pooka 	    struct sockaddr *, socklen_t *);
    279  1.1  pooka 
    280  1.1  pooka 	DPRINTF(("recvfrom\n"));
    281  1.1  pooka 	assertfd(s);
    282  1.1  pooka 	rc_recvfrom = rumpcalls[RUMPCALL_RECVFROM];
    283  1.1  pooka 	return rc_recvfrom(ADJ(s), buf, len, flags, from, fromlen);
    284  1.1  pooka }
    285  1.1  pooka 
    286  1.1  pooka ssize_t
    287  1.1  pooka recvmsg(int s, struct msghdr *msg, int flags)
    288  1.1  pooka {
    289  1.1  pooka 	int (*rc_recvmsg)(int, struct msghdr *, int);
    290  1.1  pooka 
    291  1.1  pooka 	DPRINTF(("recvmsg\n"));
    292  1.1  pooka 	assertfd(s);
    293  1.1  pooka 	rc_recvmsg = rumpcalls[RUMPCALL_RECVMSG];
    294  1.1  pooka 	return rc_recvmsg(ADJ(s), msg, flags);
    295  1.1  pooka }
    296  1.1  pooka 
    297  1.1  pooka ssize_t
    298  1.1  pooka send(int s, const void *buf, size_t len, int flags)
    299  1.1  pooka {
    300  1.1  pooka 
    301  1.1  pooka 	return sendto(s, buf, len, flags, NULL, 0);
    302  1.1  pooka }
    303  1.1  pooka 
    304  1.1  pooka ssize_t
    305  1.1  pooka sendto(int s, const void *buf, size_t len, int flags,
    306  1.1  pooka 	const struct sockaddr *to, socklen_t tolen)
    307  1.1  pooka {
    308  1.1  pooka 	int (*rc_sendto)(int, const void *, size_t, int,
    309  1.1  pooka 	    const struct sockaddr *, socklen_t);
    310  1.1  pooka 
    311  1.1  pooka 	if (s == -1)
    312  1.1  pooka 		return len;
    313  1.1  pooka 
    314  1.1  pooka 	DPRINTF(("sendto\n"));
    315  1.1  pooka 	assertfd(s);
    316  1.1  pooka 	rc_sendto = rumpcalls[RUMPCALL_SENDTO];
    317  1.1  pooka 	return rc_sendto(ADJ(s), buf, len, flags, to, tolen);
    318  1.1  pooka }
    319  1.1  pooka 
    320  1.1  pooka ssize_t
    321  1.1  pooka sendmsg(int s, const struct msghdr *msg, int flags)
    322  1.1  pooka {
    323  1.1  pooka 	int (*rc_sendmsg)(int, const struct msghdr *, int);
    324  1.1  pooka 
    325  1.1  pooka 	DPRINTF(("sendmsg\n"));
    326  1.1  pooka 	assertfd(s);
    327  1.1  pooka 	rc_sendmsg = rumpcalls[RUMPCALL_SENDTO];
    328  1.1  pooka 	return rc_sendmsg(ADJ(s), msg, flags);
    329  1.1  pooka }
    330  1.1  pooka 
    331  1.1  pooka int
    332  1.1  pooka getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
    333  1.1  pooka {
    334  1.1  pooka 	int (*rc_getsockopt)(int, int, int, void *, socklen_t *);
    335  1.1  pooka 
    336  1.1  pooka 	DPRINTF(("getsockopt\n"));
    337  1.1  pooka 	assertfd(s);
    338  1.1  pooka 	rc_getsockopt = rumpcalls[RUMPCALL_GETSOCKOPT];
    339  1.1  pooka 	return rc_getsockopt(ADJ(s), level, optname, optval, optlen);
    340  1.1  pooka }
    341  1.1  pooka 
    342  1.1  pooka int
    343  1.1  pooka setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
    344  1.1  pooka {
    345  1.1  pooka 	int (*rc_setsockopt)(int, int, int, const void *, socklen_t);
    346  1.1  pooka 
    347  1.1  pooka 	DPRINTF(("setsockopt\n"));
    348  1.1  pooka 	assertfd(s);
    349  1.1  pooka 	rc_setsockopt = rumpcalls[RUMPCALL_SETSOCKOPT];
    350  1.1  pooka 	return rc_setsockopt(ADJ(s), level, optname, optval, optlen);
    351  1.1  pooka }
    352  1.1  pooka 
    353  1.1  pooka int
    354  1.1  pooka shutdown(int s, int how)
    355  1.1  pooka {
    356  1.1  pooka 	int (*rc_shutdown)(int, int);
    357  1.1  pooka 
    358  1.1  pooka 	DPRINTF(("shutdown\n"));
    359  1.1  pooka 	assertfd(s);
    360  1.1  pooka 	rc_shutdown = rumpcalls[RUMPCALL_SHUTDOWN];
    361  1.1  pooka 	return rc_shutdown(ADJ(s), how);
    362  1.1  pooka }
    363  1.1  pooka 
    364  1.1  pooka /*
    365  1.1  pooka  * Hybrids
    366  1.1  pooka  */
    367  1.1  pooka 
    368  1.1  pooka ssize_t
    369  1.1  pooka read(int fd, void *buf, size_t len)
    370  1.1  pooka {
    371  1.1  pooka 	int (*op_read)(int, void *, size_t);
    372  1.1  pooka 	ssize_t n;
    373  1.1  pooka 
    374  1.1  pooka 	DPRINTF(("read %d\n", fd));
    375  1.1  pooka 	if (fd < HIJACK_FDOFF) {
    376  1.1  pooka 		op_read = host_read;
    377  1.1  pooka 	} else {
    378  1.1  pooka 		fd = ADJ(fd);
    379  1.1  pooka 		op_read = rumpcalls[RUMPCALL_READ];
    380  1.1  pooka 	}
    381  1.1  pooka 
    382  1.1  pooka 	n = op_read(fd, buf, len);
    383  1.1  pooka 	return n;
    384  1.1  pooka }
    385  1.1  pooka 
    386  1.1  pooka ssize_t
    387  1.1  pooka readv(int fd, const struct iovec *iov, int iovcnt)
    388  1.1  pooka {
    389  1.1  pooka 	int (*op_readv)(int, const struct iovec *, int);
    390  1.1  pooka 
    391  1.1  pooka 	if (fd < HIJACK_FDOFF) {
    392  1.1  pooka 		op_readv = host_readv;
    393  1.1  pooka 	} else {
    394  1.1  pooka 		fd = ADJ(fd);
    395  1.1  pooka 		op_readv = rumpcalls[RUMPCALL_READV];
    396  1.1  pooka 	}
    397  1.1  pooka 
    398  1.1  pooka 	DPRINTF(("readv\n"));
    399  1.1  pooka 	return op_readv(fd, iov, iovcnt);
    400  1.1  pooka }
    401  1.1  pooka 
    402  1.1  pooka ssize_t
    403  1.1  pooka write(int fd, const void *buf, size_t len)
    404  1.1  pooka {
    405  1.1  pooka 	int (*op_write)(int, const void *, size_t);
    406  1.1  pooka 
    407  1.1  pooka 	if (fd < HIJACK_FDOFF) {
    408  1.1  pooka 		op_write = host_write;
    409  1.1  pooka 	} else {
    410  1.1  pooka 		fd = ADJ(fd);
    411  1.1  pooka 		op_write = rumpcalls[RUMPCALL_WRITE];
    412  1.1  pooka 	}
    413  1.1  pooka 
    414  1.1  pooka 	return op_write(fd, buf, len);
    415  1.1  pooka }
    416  1.1  pooka 
    417  1.1  pooka ssize_t
    418  1.1  pooka writev(int fd, const struct iovec *iov, int iovcnt)
    419  1.1  pooka {
    420  1.1  pooka 	int (*op_writev)(int, const struct iovec *, int);
    421  1.1  pooka 
    422  1.1  pooka 	if (fd < HIJACK_FDOFF) {
    423  1.1  pooka 		op_writev = host_writev;
    424  1.1  pooka 	} else {
    425  1.1  pooka 		fd = ADJ(fd);
    426  1.1  pooka 		op_writev = rumpcalls[RUMPCALL_WRITEV];
    427  1.1  pooka 	}
    428  1.1  pooka 
    429  1.1  pooka 	return op_writev(fd, iov, iovcnt);
    430  1.1  pooka }
    431  1.1  pooka 
    432  1.1  pooka int
    433  1.1  pooka ioctl(int fd, unsigned long cmd, ...)
    434  1.1  pooka {
    435  1.1  pooka 	int (*op_ioctl)(int, unsigned long cmd, ...);
    436  1.1  pooka 	va_list ap;
    437  1.1  pooka 	int rv;
    438  1.1  pooka 
    439  1.1  pooka 	DPRINTF(("ioctl\n"));
    440  1.1  pooka 	if (fd < HIJACK_FDOFF) {
    441  1.1  pooka 		op_ioctl = host_ioctl;
    442  1.1  pooka 	} else {
    443  1.1  pooka 		fd = ADJ(fd);
    444  1.1  pooka 		op_ioctl = rumpcalls[RUMPCALL_IOCTL];
    445  1.1  pooka 	}
    446  1.1  pooka 
    447  1.1  pooka 	va_start(ap, cmd);
    448  1.1  pooka 	rv = op_ioctl(fd, cmd, va_arg(ap, void *));
    449  1.1  pooka 	va_end(ap);
    450  1.1  pooka 	return rv;
    451  1.1  pooka }
    452  1.1  pooka 
    453  1.1  pooka int
    454  1.1  pooka fcntl(int fd, int cmd, ...)
    455  1.1  pooka {
    456  1.1  pooka 	int (*op_fcntl)(int, int, ...);
    457  1.1  pooka 	va_list ap;
    458  1.1  pooka 	int rv;
    459  1.1  pooka 
    460  1.1  pooka 	DPRINTF(("fcntl\n"));
    461  1.1  pooka 	if (fd < HIJACK_FDOFF) {
    462  1.1  pooka 		op_fcntl = host_fcntl;
    463  1.1  pooka 	} else {
    464  1.1  pooka 		fd = ADJ(fd);
    465  1.1  pooka 		op_fcntl = rumpcalls[RUMPCALL_FCNTL];
    466  1.1  pooka 	}
    467  1.1  pooka 
    468  1.1  pooka 	va_start(ap, cmd);
    469  1.1  pooka 	rv = op_fcntl(fd, cmd, va_arg(ap, void *));
    470  1.1  pooka 	va_end(ap);
    471  1.1  pooka 	return rv;
    472  1.1  pooka }
    473  1.1  pooka 
    474  1.1  pooka int
    475  1.1  pooka close(int fd)
    476  1.1  pooka {
    477  1.1  pooka 	int (*op_close)(int);
    478  1.1  pooka 
    479  1.1  pooka 	DPRINTF(("close %d\n", fd));
    480  1.1  pooka 	if (fd < HIJACK_FDOFF) {
    481  1.1  pooka 		op_close = host_close;
    482  1.1  pooka 	} else {
    483  1.1  pooka 		fd = ADJ(fd);
    484  1.1  pooka 		op_close = rumpcalls[RUMPCALL_CLOSE];
    485  1.1  pooka 	}
    486  1.1  pooka 
    487  1.1  pooka 	return op_close(fd);
    488  1.1  pooka }
    489  1.1  pooka 
    490  1.1  pooka /*
    491  1.1  pooka  * select() has more than one implication.  e.g. we cannot know
    492  1.1  pooka  * the caller's FD_SETSIZE.  So just assume something and hope.
    493  1.1  pooka  */
    494  1.1  pooka static void
    495  1.1  pooka checkset(fd_set *setti, int nfds, int *hostcall, int *rumpcall)
    496  1.1  pooka {
    497  1.1  pooka 	int i;
    498  1.1  pooka 
    499  1.1  pooka 	if (!setti)
    500  1.1  pooka 		return;
    501  1.1  pooka 
    502  1.1  pooka 	for (i = 0; i < MIN(nfds, FD_SETSIZE); i++) {
    503  1.1  pooka 		if (FD_ISSET(i, setti)) {
    504  1.1  pooka 			if (i < HIJACK_FDOFF)
    505  1.1  pooka 				*hostcall = 1;
    506  1.1  pooka 			else
    507  1.1  pooka 				*rumpcall = 1;
    508  1.1  pooka 		}
    509  1.1  pooka 	}
    510  1.1  pooka }
    511  1.1  pooka 
    512  1.1  pooka static void
    513  1.1  pooka adjustset(fd_set *setti, int nfds, int plus)
    514  1.1  pooka {
    515  1.1  pooka 	int fd, i;
    516  1.1  pooka 
    517  1.1  pooka 	if (!setti)
    518  1.1  pooka 		return;
    519  1.1  pooka 
    520  1.1  pooka 	for (i = 0; i < MIN(nfds, FD_SETSIZE); i++) {
    521  1.1  pooka 		assert(i < HIJACK_FDOFF || !plus);
    522  1.1  pooka 		assert(i >= HIJACK_FDOFF || plus);
    523  1.1  pooka 		if (FD_ISSET(i, setti)) {
    524  1.1  pooka 			FD_CLR(i, setti);
    525  1.1  pooka 			if (plus)
    526  1.1  pooka 				fd = i + HIJACK_FDOFF;
    527  1.1  pooka 			else
    528  1.1  pooka 				fd = i - HIJACK_FDOFF;
    529  1.1  pooka 			FD_SET(fd, setti);
    530  1.1  pooka 		}
    531  1.1  pooka 	}
    532  1.1  pooka }
    533  1.1  pooka 
    534  1.1  pooka int
    535  1.1  pooka select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
    536  1.1  pooka 	struct timeval *timeout)
    537  1.1  pooka {
    538  1.1  pooka 	int (*op_select)(int, fd_set *, fd_set *, fd_set *, struct timeval *);
    539  1.1  pooka 	int hostcall = 0, rumpcall = 0;
    540  1.1  pooka 	int rv;
    541  1.1  pooka 
    542  1.1  pooka 	checkset(readfds, nfds, &hostcall, &rumpcall);
    543  1.1  pooka 	checkset(writefds, nfds, &hostcall, &rumpcall);
    544  1.1  pooka 	checkset(exceptfds, nfds, &hostcall, &rumpcall);
    545  1.1  pooka 
    546  1.1  pooka 	if (hostcall && rumpcall) {
    547  1.1  pooka 		fprintf(stderr, "cannot select() two kernels! (fixme)\n");
    548  1.1  pooka 		return EINVAL;
    549  1.1  pooka 	}
    550  1.1  pooka 
    551  1.1  pooka 	if (hostcall) {
    552  1.1  pooka 		op_select = host_select;
    553  1.1  pooka 	} else {
    554  1.1  pooka 		adjustset(readfds, nfds, 1);
    555  1.1  pooka 		adjustset(writefds, nfds, 1);
    556  1.1  pooka 		adjustset(exceptfds, nfds, 1);
    557  1.1  pooka 		op_select = rumpcalls[RUMPCALL_SELECT];
    558  1.1  pooka 	}
    559  1.1  pooka 
    560  1.1  pooka 	DPRINTF(("select\n"));
    561  1.1  pooka 	rv = op_select(nfds+HIJACK_FDOFF,
    562  1.1  pooka 	    readfds, writefds, exceptfds, timeout);
    563  1.1  pooka 	if (rumpcall) {
    564  1.1  pooka 		adjustset(readfds, nfds, 0);
    565  1.1  pooka 		adjustset(writefds, nfds, 0);
    566  1.1  pooka 		adjustset(exceptfds, nfds, 0);
    567  1.1  pooka 	}
    568  1.1  pooka 	return rv;
    569  1.1  pooka }
    570  1.1  pooka 
    571  1.1  pooka static void
    572  1.1  pooka checkpoll(struct pollfd *fds, nfds_t nfds, int *hostcall, int *rumpcall)
    573  1.1  pooka {
    574  1.1  pooka 	nfds_t i;
    575  1.1  pooka 
    576  1.1  pooka 	for (i = 0; i < nfds; i++) {
    577  1.1  pooka 		if (fds[i].fd < HIJACK_FDOFF)
    578  1.1  pooka 			(*hostcall)++;
    579  1.1  pooka 		else
    580  1.1  pooka 			(*rumpcall)++;
    581  1.1  pooka 	}
    582  1.1  pooka }
    583  1.1  pooka 
    584  1.1  pooka static void
    585  1.1  pooka adjustpoll(struct pollfd *fds, nfds_t nfds, int plus)
    586  1.1  pooka {
    587  1.1  pooka 	nfds_t i;
    588  1.1  pooka 
    589  1.1  pooka 	for (i = 0; i < nfds; i++) {
    590  1.1  pooka 		if (plus)
    591  1.1  pooka 			fds[i].fd += HIJACK_FDOFF;
    592  1.1  pooka 		else
    593  1.1  pooka 			fds[i].fd -= HIJACK_FDOFF;
    594  1.1  pooka 	}
    595  1.1  pooka }
    596  1.1  pooka 
    597  1.1  pooka /*
    598  1.1  pooka  * poll is easy as long as the call comes in the fds only in one
    599  1.1  pooka  * kernel.  otherwise its quite tricky...
    600  1.1  pooka  */
    601  1.1  pooka struct pollarg {
    602  1.1  pooka 	struct pollfd *pfds;
    603  1.1  pooka 	nfds_t nfds;
    604  1.1  pooka 	int timeout;
    605  1.1  pooka 	int pipefd;
    606  1.1  pooka 	int errnum;
    607  1.1  pooka };
    608  1.1  pooka 
    609  1.1  pooka static void *
    610  1.1  pooka hostpoll(void *arg)
    611  1.1  pooka {
    612  1.1  pooka 	struct pollarg *parg = arg;
    613  1.1  pooka 	intptr_t rv;
    614  1.1  pooka 
    615  1.1  pooka 	rv = poll(parg->pfds, parg->nfds, parg->timeout);
    616  1.1  pooka 	if (rv == -1)
    617  1.1  pooka 		parg->errnum = errno;
    618  1.1  pooka 	rump_sys_write(parg->pipefd, &rv, sizeof(rv));
    619  1.1  pooka 
    620  1.1  pooka 	return (void *)(intptr_t)rv;
    621  1.1  pooka }
    622  1.1  pooka 
    623  1.1  pooka int
    624  1.1  pooka poll(struct pollfd *fds, nfds_t nfds, int timeout)
    625  1.1  pooka {
    626  1.1  pooka 	int (*op_poll)(struct pollfd *, nfds_t, int);
    627  1.1  pooka 	int hostcall = 0, rumpcall = 0;
    628  1.1  pooka 	pthread_t pt;
    629  1.1  pooka 	nfds_t i;
    630  1.1  pooka 	int rv;
    631  1.1  pooka 
    632  1.1  pooka 	checkpoll(fds, nfds, &hostcall, &rumpcall);
    633  1.1  pooka 
    634  1.1  pooka 	if (hostcall && rumpcall) {
    635  1.1  pooka 		struct pollfd *pfd_host = NULL, *pfd_rump = NULL;
    636  1.1  pooka 		int rpipe[2] = {-1,-1}, hpipe[2] = {-1,-1};
    637  1.1  pooka 		struct pollarg parg;
    638  1.1  pooka 		uintptr_t lrv;
    639  1.1  pooka 		int sverrno = 0, trv;
    640  1.1  pooka 
    641  1.1  pooka 		/*
    642  1.1  pooka 		 * ok, this is where it gets tricky.  We must support
    643  1.1  pooka 		 * this since it's a very common operation in certain
    644  1.1  pooka 		 * types of software (telnet, netcat, etc).  We allocate
    645  1.1  pooka 		 * two vectors and run two poll commands in separate
    646  1.1  pooka 		 * threads.  Whichever returns first "wins" and the
    647  1.1  pooka 		 * other kernel's fds won't show activity.
    648  1.1  pooka 		 */
    649  1.1  pooka 		rv = -1;
    650  1.1  pooka 
    651  1.1  pooka 		/* allocate full vector for O(n) joining after call */
    652  1.1  pooka 		pfd_host = malloc(sizeof(*pfd_host)*(nfds+1));
    653  1.1  pooka 		if (!pfd_host)
    654  1.1  pooka 			goto out;
    655  1.1  pooka 		pfd_rump = malloc(sizeof(*pfd_rump)*(nfds+1));
    656  1.1  pooka 		if (!pfd_rump) {
    657  1.1  pooka 			goto out;
    658  1.1  pooka 		}
    659  1.1  pooka 
    660  1.1  pooka 		/* split vectors */
    661  1.1  pooka 		for (i = 0; i < nfds; i++) {
    662  1.1  pooka 			if (fds[i].fd < HIJACK_FDOFF) {
    663  1.1  pooka 				pfd_host[i].fd = fds[i].fd;
    664  1.1  pooka 				pfd_host[i].events = fds[i].events;
    665  1.1  pooka 				pfd_rump[i].fd = -1;
    666  1.1  pooka 			} else {
    667  1.1  pooka 				pfd_host[i].fd = -1;
    668  1.1  pooka 				pfd_rump[i].fd = ADJ(fds[i].fd);
    669  1.1  pooka 				pfd_rump[i].events = fds[i].events;
    670  1.1  pooka 			}
    671  1.1  pooka 		}
    672  1.1  pooka 
    673  1.1  pooka 		/*
    674  1.1  pooka 		 * then, open two pipes, one for notifications
    675  1.1  pooka 		 * to each kernel.
    676  1.1  pooka 		 */
    677  1.1  pooka 		if (rump_sys_pipe(rpipe) == -1)
    678  1.1  pooka 			goto out;
    679  1.1  pooka 		if (pipe(hpipe) == -1)
    680  1.1  pooka 			goto out;
    681  1.1  pooka 
    682  1.1  pooka 		pfd_host[nfds].fd = hpipe[0];
    683  1.1  pooka 		pfd_host[nfds].events = POLLIN;
    684  1.1  pooka 		pfd_rump[nfds].fd = rpipe[0];
    685  1.1  pooka 		pfd_rump[nfds].events = POLLIN;
    686  1.1  pooka 
    687  1.1  pooka 		/*
    688  1.1  pooka 		 * then, create a thread to do host part and meanwhile
    689  1.1  pooka 		 * do rump kernel part right here
    690  1.1  pooka 		 */
    691  1.1  pooka 
    692  1.1  pooka 		parg.pfds = pfd_host;
    693  1.1  pooka 		parg.nfds = nfds+1;
    694  1.1  pooka 		parg.timeout = timeout;
    695  1.1  pooka 		parg.pipefd = rpipe[1];
    696  1.1  pooka 		pthread_create(&pt, NULL, hostpoll, &parg);
    697  1.1  pooka 
    698  1.1  pooka 		lrv = rump_sys_poll(pfd_rump, nfds+1, timeout);
    699  1.1  pooka 		sverrno = errno;
    700  1.1  pooka 		write(hpipe[1], &rv, sizeof(rv));
    701  1.1  pooka 		pthread_join(pt, (void *)&trv);
    702  1.1  pooka 
    703  1.1  pooka 		/* check who "won" and merge results */
    704  1.1  pooka 		if (lrv != 0 && pfd_host[nfds].revents & POLLIN) {
    705  1.1  pooka 			rv = trv;
    706  1.1  pooka 
    707  1.1  pooka 			for (i = 0; i < nfds; i++) {
    708  1.1  pooka 				if (pfd_rump[i].fd != -1)
    709  1.1  pooka 					fds[i].revents = pfd_rump[i].revents;
    710  1.1  pooka 			}
    711  1.1  pooka 			sverrno = parg.errnum;
    712  1.1  pooka 		} else if (trv != 0 && pfd_rump[nfds].revents & POLLIN) {
    713  1.1  pooka 			rv = trv;
    714  1.1  pooka 
    715  1.1  pooka 			for (i = 0; i < nfds; i++) {
    716  1.1  pooka 				if (pfd_host[i].fd != -1)
    717  1.1  pooka 					fds[i].revents = pfd_host[i].revents;
    718  1.1  pooka 			}
    719  1.1  pooka 		} else {
    720  1.1  pooka 			rv = 0;
    721  1.1  pooka 			assert(timeout != -1);
    722  1.1  pooka 		}
    723  1.1  pooka 
    724  1.1  pooka  out:
    725  1.1  pooka 		if (rpipe[0] != -1)
    726  1.1  pooka 			rump_sys_close(rpipe[0]);
    727  1.1  pooka 		if (rpipe[1] != -1)
    728  1.1  pooka 			rump_sys_close(rpipe[1]);
    729  1.1  pooka 		if (hpipe[0] != -1)
    730  1.1  pooka 			close(hpipe[0]);
    731  1.1  pooka 		if (hpipe[1] != -1)
    732  1.1  pooka 			close(hpipe[1]);
    733  1.1  pooka 		free(pfd_host);
    734  1.1  pooka 		free(pfd_rump);
    735  1.1  pooka 		errno = sverrno;
    736  1.1  pooka 	} else {
    737  1.1  pooka 		if (hostcall) {
    738  1.1  pooka 			op_poll = host_poll;
    739  1.1  pooka 		} else {
    740  1.1  pooka 			op_poll = rumpcalls[RUMPCALL_POLL];
    741  1.1  pooka 			adjustpoll(fds, nfds, 0);
    742  1.1  pooka 		}
    743  1.1  pooka 
    744  1.1  pooka 		rv = op_poll(fds, nfds, timeout);
    745  1.1  pooka 		if (rumpcall)
    746  1.1  pooka 			adjustpoll(fds, nfds, 1);
    747  1.1  pooka 	}
    748  1.1  pooka 
    749  1.1  pooka 	return rv;
    750  1.1  pooka }
    751  1.1  pooka 
    752  1.1  pooka int
    753  1.1  pooka pollts(struct pollfd *fds, nfds_t nfds, const struct timespec *ts,
    754  1.1  pooka 	const sigset_t *sigmask)
    755  1.1  pooka {
    756  1.1  pooka 
    757  1.1  pooka 	abort();
    758  1.1  pooka }
    759