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