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