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