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