Thu Oct 28 14:37:29 2010 UTC ()
Run different clients (different sockets) in different processes
inside the rump kernel.  Now different host processes can no longer
step on each other inside the rump kernel.


(pooka)
diff -r1.1 -r1.2 src/lib/librumpuser/rumpuser_sp.c

cvs diff -r1.1 -r1.2 src/lib/librumpuser/rumpuser_sp.c (switch to unified diff)

--- src/lib/librumpuser/rumpuser_sp.c 2010/10/27 20:44:50 1.1
+++ src/lib/librumpuser/rumpuser_sp.c 2010/10/28 14:37:29 1.2
@@ -1,950 +1,965 @@ @@ -1,950 +1,965 @@
1/* $NetBSD: rumpuser_sp.c,v 1.1 2010/10/27 20:44:50 pooka Exp $ */ 1/* $NetBSD: rumpuser_sp.c,v 1.2 2010/10/28 14:37:29 pooka Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2010 Antti Kantee. All Rights Reserved. 4 * Copyright (c) 2010 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/* 28/*
29 * Sysproxy routines. This provides system RPC support over host sockets. 29 * Sysproxy routines. This provides system RPC support over host sockets.
30 * The most notable limitation is that the client and server must share 30 * The most notable limitation is that the client and server must share
31 * the same ABI. This does not mean that they have to be the same 31 * the same ABI. This does not mean that they have to be the same
32 * machine or that they need to run the same version of the host OS, 32 * machine or that they need to run the same version of the host OS,
33 * just that they must agree on the data structures. This even *might* 33 * just that they must agree on the data structures. This even *might*
34 * work correctly from one hardware architecture to another. 34 * work correctly from one hardware architecture to another.
35 * 35 *
36 * Not finished yet, i.e. don't use in production. Lacks locking plus 36 * Not finished yet, i.e. don't use in production. Lacks locking plus
37 * handling of multiple clients and unexpected connection closes. 37 * handling of multiple clients and unexpected connection closes.
38 */ 38 */
39 39
40#include <sys/cdefs.h> 40#include <sys/cdefs.h>
41__RCSID("$NetBSD: rumpuser_sp.c,v 1.1 2010/10/27 20:44:50 pooka Exp $"); 41__RCSID("$NetBSD: rumpuser_sp.c,v 1.2 2010/10/28 14:37:29 pooka Exp $");
42 42
43#include <sys/types.h> 43#include <sys/types.h>
44#include <sys/mman.h> 44#include <sys/mman.h>
45#include <sys/socket.h> 45#include <sys/socket.h>
46 46
47#include <arpa/inet.h> 47#include <arpa/inet.h>
48#include <netinet/in.h> 48#include <netinet/in.h>
49#include <netinet/tcp.h> 49#include <netinet/tcp.h>
50 50
51#include <assert.h> 51#include <assert.h>
52#include <errno.h> 52#include <errno.h>
53#include <fcntl.h> 53#include <fcntl.h>
54#include <poll.h> 54#include <poll.h>
55#include <pthread.h> 55#include <pthread.h>
56#include <stdarg.h> 56#include <stdarg.h>
57#include <stdio.h> 57#include <stdio.h>
58#include <stdlib.h> 58#include <stdlib.h>
59#include <string.h> 59#include <string.h>
60#include <unistd.h> 60#include <unistd.h>
61 61
62#include <rump/rump.h> 62#include <rump/rump.h>
63#include <rump/rumpuser.h> 63#include <rump/rumpuser.h>
64 64
65//#define DEBUG 65//#define DEBUG
66#ifdef DEBUG 66#ifdef DEBUG
67#define DPRINTF(x) mydprintf x 67#define DPRINTF(x) mydprintf x
68static void 68static void
69mydprintf(const char *fmt, ...) 69mydprintf(const char *fmt, ...)
70{ 70{
71 va_list ap; 71 va_list ap;
72 72
73 va_start(ap, fmt); 73 va_start(ap, fmt);
74 vfprintf(stderr, fmt, ap); 74 vfprintf(stderr, fmt, ap);
75 va_end(ap); 75 va_end(ap);
76} 76}
77#else 77#else
78#define DPRINTF(x) 78#define DPRINTF(x)
79#endif 79#endif
80 80
81/* 81/*
82 * Bah, I hate writing on-off-wire conversions in C 82 * Bah, I hate writing on-off-wire conversions in C
83 */ 83 */
84 84
85enum { 85enum {
86 RUMPSP_SYSCALL_REQ, RUMPSP_SYSCALL_RESP, 86 RUMPSP_SYSCALL_REQ, RUMPSP_SYSCALL_RESP,
87 RUMPSP_COPYIN_REQ, RUMPSP_COPYIN_RESP, 87 RUMPSP_COPYIN_REQ, RUMPSP_COPYIN_RESP,
88 RUMPSP_COPYOUT_REQ, /* no copyout resp */ 88 RUMPSP_COPYOUT_REQ, /* no copyout resp */
89 RUMPSP_ANONMMAP_REQ, RUMPSP_ANONMMAP_RESP 89 RUMPSP_ANONMMAP_REQ, RUMPSP_ANONMMAP_RESP
90}; 90};
91 91
92struct rsp_hdr { 92struct rsp_hdr {
93 uint64_t rsp_len; 93 uint64_t rsp_len;
94 uint64_t rsp_reqno; 94 uint64_t rsp_reqno;
95 uint32_t rsp_type; 95 uint32_t rsp_type;
96 /* 96 /*
97 * We want this structure 64bit-aligned for typecast fun, 97 * We want this structure 64bit-aligned for typecast fun,
98 * so might as well use the following for something. 98 * so might as well use the following for something.
99 */ 99 */
100 uint32_t rsp_sysnum; 100 uint32_t rsp_sysnum;
101}; 101};
102#define HDRSZ sizeof(struct rsp_hdr) 102#define HDRSZ sizeof(struct rsp_hdr)
103 103
104/* 104/*
105 * Data follows the header. We have two types of structured data. 105 * Data follows the header. We have two types of structured data.
106 */ 106 */
107 107
108/* copyin/copyout */ 108/* copyin/copyout */
109struct rsp_copydata { 109struct rsp_copydata {
110 size_t rcp_len; 110 size_t rcp_len;
111 void *rcp_addr; 111 void *rcp_addr;
112 uint8_t rcp_data[0]; 112 uint8_t rcp_data[0];
113}; 113};
114 114
115/* syscall response */ 115/* syscall response */
116struct rsp_sysresp { 116struct rsp_sysresp {
117 int rsys_error; 117 int rsys_error;
118 register_t rsys_retval[2]; 118 register_t rsys_retval[2];
119}; 119};
120 120
121 121
122struct spclient { 122struct spclient {
123 int spc_fd; 123 int spc_fd;
 124 struct lwp *spc_lwp;
124 125
125 /* incoming */ 126 /* incoming */
126 struct rsp_hdr spc_hdr; 127 struct rsp_hdr spc_hdr;
127 uint8_t *spc_buf; 128 uint8_t *spc_buf;
128 size_t spc_off; 129 size_t spc_off;
129 130
130#if 0 131#if 0
131 /* outgoing */ 132 /* outgoing */
132 int spc_obusy; 133 int spc_obusy;
133 pthread_mutex_t spc_omtx; 134 pthread_mutex_t spc_omtx;
134 pthread_cond_t spc_cv; 135 pthread_cond_t spc_cv;
135#endif 136#endif
136}; 137};
137 138
138typedef int (*addrparse_fn)(const char *, int, struct sockaddr **); 139typedef int (*addrparse_fn)(const char *, int, struct sockaddr **);
139typedef int (*connecthook_fn)(int); 140typedef int (*connecthook_fn)(int);
140 141
141#define MAXCLI 4 142#define MAXCLI 4
142 143
143static struct pollfd pfdlist[MAXCLI]; 144static struct pollfd pfdlist[MAXCLI];
144static struct spclient spclist[MAXCLI]; 145static struct spclient spclist[MAXCLI];
145static unsigned int nfds, maxidx; 146static unsigned int nfds, maxidx;
146static uint64_t nextreq; 147static uint64_t nextreq;
147static pthread_key_t spclient_tls; 148static pthread_key_t spclient_tls;
148 149
149static struct spclient clispc; 150static struct spclient clispc;
150 151
151 152
152static int 153static int
153dosend(struct spclient *spc, const void *data, size_t dlen) 154dosend(struct spclient *spc, const void *data, size_t dlen)
154{ 155{
155 struct pollfd pfd; 156 struct pollfd pfd;
156 const uint8_t *sdata = data; 157 const uint8_t *sdata = data;
157 ssize_t n; 158 ssize_t n;
158 size_t sent; 159 size_t sent;
159 int fd = spc->spc_fd; 160 int fd = spc->spc_fd;
160 161
161 pfd.fd = fd; 162 pfd.fd = fd;
162 pfd.events = POLLOUT; 163 pfd.events = POLLOUT;
163 164
164 for (sent = 0, n = 0; sent < dlen; ) { 165 for (sent = 0, n = 0; sent < dlen; ) {
165 if (n) { 166 if (n) {
166 if (poll(&pfd, 1, INFTIM) == -1) { 167 if (poll(&pfd, 1, INFTIM) == -1) {
167 if (errno == EINTR) 168 if (errno == EINTR)
168 continue; 169 continue;
169 return errno; 170 return errno;
170 } 171 }
171 } 172 }
172 173
173 n = write(fd, sdata + sent, dlen - sent); 174 n = write(fd, sdata + sent, dlen - sent);
174 if (n == 0) { 175 if (n == 0) {
175 return EFAULT; 176 return EFAULT;
176 } 177 }
177 if (n == -1 && errno != EAGAIN) { 178 if (n == -1 && errno != EAGAIN) {
178 return EFAULT; 179 return EFAULT;
179 } 180 }
180 sent += n; 181 sent += n;
181 } 182 }
182 183
183 return 0; 184 return 0;
184} 185}
185 186
186static int 187static int
187send_syscall_req(struct spclient *spc, int sysnum, 188send_syscall_req(struct spclient *spc, int sysnum,
188 const void *data, size_t dlen) 189 const void *data, size_t dlen)
189{ 190{
190 struct rsp_hdr rhdr; 191 struct rsp_hdr rhdr;
191 192
192 rhdr.rsp_len = sizeof(rhdr) + dlen; 193 rhdr.rsp_len = sizeof(rhdr) + dlen;
193 rhdr.rsp_reqno = nextreq++; 194 rhdr.rsp_reqno = nextreq++;
194 rhdr.rsp_type = RUMPSP_SYSCALL_REQ; 195 rhdr.rsp_type = RUMPSP_SYSCALL_REQ;
195 rhdr.rsp_sysnum = sysnum; 196 rhdr.rsp_sysnum = sysnum;
196 197
197 dosend(spc, &rhdr, sizeof(rhdr)); 198 dosend(spc, &rhdr, sizeof(rhdr));
198 dosend(spc, data, dlen); 199 dosend(spc, data, dlen);
199 200
200 return 0; 201 return 0;
201} 202}
202 203
203static int 204static int
204send_syscall_resp(struct spclient *spc, uint64_t reqno, int error, 205send_syscall_resp(struct spclient *spc, uint64_t reqno, int error,
205 register_t retval[2]) 206 register_t retval[2])
206{ 207{
207 struct rsp_hdr rhdr; 208 struct rsp_hdr rhdr;
208 struct rsp_sysresp sysresp; 209 struct rsp_sysresp sysresp;
209 210
210 rhdr.rsp_len = sizeof(rhdr) + sizeof(sysresp); 211 rhdr.rsp_len = sizeof(rhdr) + sizeof(sysresp);
211 rhdr.rsp_reqno = reqno; 212 rhdr.rsp_reqno = reqno;
212 rhdr.rsp_type = RUMPSP_SYSCALL_RESP; 213 rhdr.rsp_type = RUMPSP_SYSCALL_RESP;
213 rhdr.rsp_sysnum = 0; 214 rhdr.rsp_sysnum = 0;
214 215
215 sysresp.rsys_error = error; 216 sysresp.rsys_error = error;
216 memcpy(sysresp.rsys_retval, retval, sizeof(retval)); 217 memcpy(sysresp.rsys_retval, retval, sizeof(retval));
217 218
218 dosend(spc, &rhdr, sizeof(rhdr)); 219 dosend(spc, &rhdr, sizeof(rhdr));
219 dosend(spc, &sysresp, sizeof(sysresp)); 220 dosend(spc, &sysresp, sizeof(sysresp));
220 221
221 return 0; 222 return 0;
222} 223}
223 224
224static int 225static int
225send_copyin_req(struct spclient *spc, const void *remaddr, size_t dlen) 226send_copyin_req(struct spclient *spc, const void *remaddr, size_t dlen)
226{ 227{
227 struct rsp_hdr rhdr; 228 struct rsp_hdr rhdr;
228 struct rsp_copydata copydata; 229 struct rsp_copydata copydata;
229 230
230 rhdr.rsp_len = sizeof(rhdr) + sizeof(copydata); 231 rhdr.rsp_len = sizeof(rhdr) + sizeof(copydata);
231 rhdr.rsp_reqno = nextreq++; 232 rhdr.rsp_reqno = nextreq++;
232 rhdr.rsp_type = RUMPSP_COPYIN_REQ; 233 rhdr.rsp_type = RUMPSP_COPYIN_REQ;
233 rhdr.rsp_sysnum = 0; 234 rhdr.rsp_sysnum = 0;
234 235
235 copydata.rcp_addr = __UNCONST(remaddr); 236 copydata.rcp_addr = __UNCONST(remaddr);
236 copydata.rcp_len = dlen; 237 copydata.rcp_len = dlen;
237 238
238 dosend(spc, &rhdr, sizeof(rhdr)); 239 dosend(spc, &rhdr, sizeof(rhdr));
239 dosend(spc, &copydata, sizeof(copydata)); 240 dosend(spc, &copydata, sizeof(copydata));
240 241
241 return 0; 242 return 0;
242} 243}
243 244
244static int 245static int
245send_copyin_resp(struct spclient *spc, uint64_t reqno, void *data, size_t dlen) 246send_copyin_resp(struct spclient *spc, uint64_t reqno, void *data, size_t dlen)
246{ 247{
247 struct rsp_hdr rhdr; 248 struct rsp_hdr rhdr;
248 249
249 rhdr.rsp_len = sizeof(rhdr) + dlen; 250 rhdr.rsp_len = sizeof(rhdr) + dlen;
250 rhdr.rsp_reqno = reqno; 251 rhdr.rsp_reqno = reqno;
251 rhdr.rsp_type = RUMPSP_COPYIN_RESP; 252 rhdr.rsp_type = RUMPSP_COPYIN_RESP;
252 rhdr.rsp_sysnum = 0; 253 rhdr.rsp_sysnum = 0;
253 254
254 dosend(spc, &rhdr, sizeof(rhdr)); 255 dosend(spc, &rhdr, sizeof(rhdr));
255 dosend(spc, data, dlen); 256 dosend(spc, data, dlen);
256 257
257 return 0; 258 return 0;
258} 259}
259 260
260static int 261static int
261send_copyout_req(struct spclient *spc, const void *remaddr, 262send_copyout_req(struct spclient *spc, const void *remaddr,
262 const void *data, size_t dlen) 263 const void *data, size_t dlen)
263{ 264{
264 struct rsp_hdr rhdr; 265 struct rsp_hdr rhdr;
265 struct rsp_copydata copydata; 266 struct rsp_copydata copydata;
266 267
267 rhdr.rsp_len = sizeof(rhdr) + sizeof(copydata) + dlen; 268 rhdr.rsp_len = sizeof(rhdr) + sizeof(copydata) + dlen;
268 rhdr.rsp_reqno = nextreq++; 269 rhdr.rsp_reqno = nextreq++;
269 rhdr.rsp_type = RUMPSP_COPYOUT_REQ; 270 rhdr.rsp_type = RUMPSP_COPYOUT_REQ;
270 rhdr.rsp_sysnum = 0; 271 rhdr.rsp_sysnum = 0;
271 272
272 copydata.rcp_addr = __UNCONST(remaddr); 273 copydata.rcp_addr = __UNCONST(remaddr);
273 copydata.rcp_len = dlen; 274 copydata.rcp_len = dlen;
274 275
275 dosend(spc, &rhdr, sizeof(rhdr)); 276 dosend(spc, &rhdr, sizeof(rhdr));
276 dosend(spc, &copydata, sizeof(copydata)); 277 dosend(spc, &copydata, sizeof(copydata));
277 dosend(spc, data, dlen); 278 dosend(spc, data, dlen);
278 279
279 return 0; 280 return 0;
280} 281}
281 282
282static int 283static int
283send_anonmmap_req(struct spclient *spc, size_t howmuch) 284send_anonmmap_req(struct spclient *spc, size_t howmuch)
284{ 285{
285 struct rsp_hdr rhdr; 286 struct rsp_hdr rhdr;
286 287
287 rhdr.rsp_len = sizeof(rhdr) + sizeof(howmuch); 288 rhdr.rsp_len = sizeof(rhdr) + sizeof(howmuch);
288 rhdr.rsp_reqno = nextreq++; 289 rhdr.rsp_reqno = nextreq++;
289 rhdr.rsp_type = RUMPSP_ANONMMAP_REQ; 290 rhdr.rsp_type = RUMPSP_ANONMMAP_REQ;
290 rhdr.rsp_sysnum = 0; 291 rhdr.rsp_sysnum = 0;
291 292
292 dosend(spc, &rhdr, sizeof(rhdr)); 293 dosend(spc, &rhdr, sizeof(rhdr));
293 dosend(spc, &howmuch, sizeof(howmuch)); 294 dosend(spc, &howmuch, sizeof(howmuch));
294 295
295 return 0; 296 return 0;
296} 297}
297 298
298static int 299static int
299send_anonmmap_resp(struct spclient *spc, uint64_t reqno, void *addr) 300send_anonmmap_resp(struct spclient *spc, uint64_t reqno, void *addr)
300{ 301{
301 struct rsp_hdr rhdr; 302 struct rsp_hdr rhdr;
302 303
303 rhdr.rsp_len = sizeof(rhdr) + sizeof(addr); 304 rhdr.rsp_len = sizeof(rhdr) + sizeof(addr);
304 rhdr.rsp_reqno = reqno; 305 rhdr.rsp_reqno = reqno;
305 rhdr.rsp_type = RUMPSP_ANONMMAP_RESP; 306 rhdr.rsp_type = RUMPSP_ANONMMAP_RESP;
306 rhdr.rsp_sysnum = 0; 307 rhdr.rsp_sysnum = 0;
307 308
308 dosend(spc, &rhdr, sizeof(rhdr)); 309 dosend(spc, &rhdr, sizeof(rhdr));
309 dosend(spc, &addr, sizeof(addr)); 310 dosend(spc, &addr, sizeof(addr));
310 311
311 return 0; 312 return 0;
312} 313}
313 314
314static void 315static void
315serv_handle_disco(unsigned int idx) 316serv_handledisco(unsigned int idx)
316{ 317{
317 struct spclient *spc = &spclist[idx]; 318 struct spclient *spc = &spclist[idx];
318 int fd = spc->spc_fd; 319 int fd = spc->spc_fd;
319 320
320 DPRINTF(("rump_sp: disconnecting [%u]\n", idx)); 321 DPRINTF(("rump_sp: disconnecting [%u]\n", idx));
321 322
 323 rump_pub_lwproc_switch(spc->spc_lwp);
 324 rump_pub_lwproc_releaselwp();
 325
322 free(spc->spc_buf); 326 free(spc->spc_buf);
323 memset(spc, 0, sizeof(*spc)); 327 memset(spc, 0, sizeof(*spc));
324 close(fd); 328 close(fd);
325 pfdlist[idx].fd = -1; 329 pfdlist[idx].fd = -1;
326 nfds--; 330 nfds--;
327 331
328 if (idx == maxidx) { 332 if (idx == maxidx) {
329 while (idx--) { 333 while (idx--) {
330 if (pfdlist[idx].fd != -1) { 334 if (pfdlist[idx].fd != -1) {
331 maxidx = idx; 335 maxidx = idx;
332 break; 336 break;
333 } 337 }
334 assert(idx != 0); 338 assert(idx != 0);
335 } 339 }
336 DPRINTF(("rump_sp: set maxidx to [%u]\n", maxidx)); 340 DPRINTF(("rump_sp: set maxidx to [%u]\n", maxidx));
337 } 341 }
338} 342}
339 343
340static int 344static int
341serv_handleconn(int fd, connecthook_fn connhook) 345serv_handleconn(int fd, connecthook_fn connhook)
342{ 346{
343 struct sockaddr_storage ss; 347 struct sockaddr_storage ss;
344 socklen_t sl = sizeof(ss); 348 socklen_t sl = sizeof(ss);
345 int newfd, flags, error; 349 int newfd, flags, error;
346 unsigned i; 350 unsigned i;
347 351
348 /*LINTED: cast ok */ 352 /*LINTED: cast ok */
349 newfd = accept(fd, (struct sockaddr *)&ss, &sl); 353 newfd = accept(fd, (struct sockaddr *)&ss, &sl);
350 if (newfd == -1) 354 if (newfd == -1)
351 return errno; 355 return errno;
352 356
353 /* XXX: should do some sort of handshake too */ 357 /* XXX: should do some sort of handshake too */
354 358
355 if (nfds == MAXCLI) { 359 if (nfds == MAXCLI) {
356 close(newfd); /* EBUSY */ 360 close(newfd); /* EBUSY */
357 return EBUSY; 361 return EBUSY;
358 } 362 }
359 363
360 flags = fcntl(newfd, F_GETFL, 0); 364 flags = fcntl(newfd, F_GETFL, 0);
361 if (fcntl(newfd, F_SETFL, flags | O_NONBLOCK) == -1) { 365 if (fcntl(newfd, F_SETFL, flags | O_NONBLOCK) == -1) {
362 close(newfd); 366 close(newfd);
363 return errno; 367 return errno;
364 } 368 }
365 flags = 1; 369 flags = 1;
366 370
367 if ((error = connhook(newfd)) != 0) { 371 if ((error = connhook(newfd)) != 0) {
368 close(newfd); 372 close(newfd);
369 return error; 373 return error;
370 } 374 }
371 375
 376 if ((error = rump_pub_lwproc_newproc()) != 0) {
 377 close(newfd);
 378 return error;
 379 }
 380
372 /* find empty slot the simple way */ 381 /* find empty slot the simple way */
373 for (i = 0; i < MAXCLI; i++) { 382 for (i = 0; i < MAXCLI; i++) {
374 if (pfdlist[i].fd == -1) 383 if (pfdlist[i].fd == -1)
375 break; 384 break;
376 } 385 }
377 386
378 assert(i < MAXCLI); 387 assert(i < MAXCLI);
379 nfds++; 388 nfds++;
380 389
381 pfdlist[i].fd = newfd; 390 pfdlist[i].fd = newfd;
382 spclist[i].spc_fd = newfd; 391 spclist[i].spc_fd = newfd;
 392 spclist[i].spc_lwp = rump_pub_lwproc_curlwp();
383 if (maxidx < i) 393 if (maxidx < i)
384 maxidx = i; 394 maxidx = i;
385 395
386 DPRINTF(("rump_sp: added new connection at idx %u\n", i)); 396 DPRINTF(("rump_sp: added new connection at idx %u, pid %d\n",
 397 i, rump_sys_getpid()));
 398
 399 rump_pub_lwproc_switch(NULL);
387 400
388 return 0; 401 return 0;
389} 402}
390 403
391static void 404static void
392serv_handlesyscall(struct spclient *spc, struct rsp_hdr *rhdr, uint8_t *data) 405serv_handlesyscall(struct spclient *spc, struct rsp_hdr *rhdr, uint8_t *data)
393{ 406{
394 register_t retval[2]; 407 register_t retval[2];
395 int rv, sysnum; 408 int rv, sysnum;
396 409
397 sysnum = (int)rhdr->rsp_sysnum; 410 sysnum = (int)rhdr->rsp_sysnum;
398 DPRINTF(("rump_sp: handling syscall %d from client %d\n", 411 DPRINTF(("rump_sp: handling syscall %d from client %d\n",
399 sysnum, 0)); 412 sysnum, 0));
400 413
401 pthread_setspecific(spclient_tls, spc); 414 pthread_setspecific(spclient_tls, spc);
 415 rump_pub_lwproc_switch(spc->spc_lwp);
402 rv = rump_pub_syscall(sysnum, data, retval); 416 rv = rump_pub_syscall(sysnum, data, retval);
 417 rump_pub_lwproc_switch(NULL);
403 pthread_setspecific(spclient_tls, NULL); 418 pthread_setspecific(spclient_tls, NULL);
404 419
405 send_syscall_resp(spc, rhdr->rsp_reqno, rv, retval); 420 send_syscall_resp(spc, rhdr->rsp_reqno, rv, retval);
406} 421}
407 422
408static int 423static int
409readframe(struct spclient *spc) 424readframe(struct spclient *spc)
410{ 425{
411 int fd = spc->spc_fd; 426 int fd = spc->spc_fd;
412 size_t left; 427 size_t left;
413 size_t framelen; 428 size_t framelen;
414 ssize_t n; 429 ssize_t n;
415 430
416 /* still reading header? */ 431 /* still reading header? */
417 if (spc->spc_off < HDRSZ) { 432 if (spc->spc_off < HDRSZ) {
418 DPRINTF(("rump_sp: readframe getting header at offset %zu\n", 433 DPRINTF(("rump_sp: readframe getting header at offset %zu\n",
419 spc->spc_off)); 434 spc->spc_off));
420 435
421 left = HDRSZ - spc->spc_off; 436 left = HDRSZ - spc->spc_off;
422 /*LINTED: cast ok */ 437 /*LINTED: cast ok */
423 n = read(fd, (uint8_t *)&spc->spc_hdr + spc->spc_off, left); 438 n = read(fd, (uint8_t *)&spc->spc_hdr + spc->spc_off, left);
424 if (n == 0) { 439 if (n == 0) {
425 return -1; 440 return -1;
426 } 441 }
427 if (n == -1) { 442 if (n == -1) {
428 if (errno == EAGAIN) 443 if (errno == EAGAIN)
429 return 0; 444 return 0;
430 return -1; 445 return -1;
431 } 446 }
432 447
433 spc->spc_off += n; 448 spc->spc_off += n;
434 if (spc->spc_off < HDRSZ) 449 if (spc->spc_off < HDRSZ)
435 return -1; 450 return -1;
436 451
437 /*LINTED*/ 452 /*LINTED*/
438 framelen = spc->spc_hdr.rsp_len; 453 framelen = spc->spc_hdr.rsp_len;
439 454
440 if (framelen < HDRSZ) { 455 if (framelen < HDRSZ) {
441 return -1; 456 return -1;
442 } else if (framelen == HDRSZ) { 457 } else if (framelen == HDRSZ) {
443 return 1; 458 return 1;
444 } 459 }
445 460
446 spc->spc_buf = malloc(framelen - HDRSZ); 461 spc->spc_buf = malloc(framelen - HDRSZ);
447 if (spc->spc_buf == NULL) { 462 if (spc->spc_buf == NULL) {
448 return -1; 463 return -1;
449 } 464 }
450 memset(spc->spc_buf, 0, framelen - HDRSZ); 465 memset(spc->spc_buf, 0, framelen - HDRSZ);
451 466
452 /* "fallthrough" */ 467 /* "fallthrough" */
453 } else { 468 } else {
454 /*LINTED*/ 469 /*LINTED*/
455 framelen = spc->spc_hdr.rsp_len; 470 framelen = spc->spc_hdr.rsp_len;
456 } 471 }
457 472
458 left = framelen - spc->spc_off; 473 left = framelen - spc->spc_off;
459 474
460 DPRINTF(("rump_sp: readframe getting body at offset %zu, left %zu\n", 475 DPRINTF(("rump_sp: readframe getting body at offset %zu, left %zu\n",
461 spc->spc_off, left)); 476 spc->spc_off, left));
462 477
463 if (left == 0) 478 if (left == 0)
464 return 1; 479 return 1;
465 n = read(fd, spc->spc_buf + (spc->spc_off - HDRSZ), left); 480 n = read(fd, spc->spc_buf + (spc->spc_off - HDRSZ), left);
466 if (n == 0) { 481 if (n == 0) {
467 return -1; 482 return -1;
468 } 483 }
469 if (n == -1) { 484 if (n == -1) {
470 if (errno == EAGAIN) 485 if (errno == EAGAIN)
471 return 0; 486 return 0;
472 return -1; 487 return -1;
473 } 488 }
474 spc->spc_off += n; 489 spc->spc_off += n;
475 left -= n; 490 left -= n;
476 491
477 /* got everything? */ 492 /* got everything? */
478 if (left == 0) 493 if (left == 0)
479 return 1; 494 return 1;
480 else 495 else
481 return 0; 496 return 0;
482} 497}
483 498
484int 499int
485rumpuser_sp_copyin(const void *uaddr, void *kaddr, size_t len) 500rumpuser_sp_copyin(const void *uaddr, void *kaddr, size_t len)
486{ 501{
487 struct spclient *spc; 502 struct spclient *spc;
488 struct pollfd pfd; 503 struct pollfd pfd;
489 504
490 spc = pthread_getspecific(spclient_tls); 505 spc = pthread_getspecific(spclient_tls);
491 if (!spc) 506 if (!spc)
492 return EFAULT; 507 return EFAULT;
493 508
494 send_copyin_req(spc, uaddr, len); 509 send_copyin_req(spc, uaddr, len);
495 510
496 pfd.fd = spc->spc_fd; 511 pfd.fd = spc->spc_fd;
497 pfd.events = POLLIN; 512 pfd.events = POLLIN;
498 do { 513 do {
499 poll(&pfd, 1, INFTIM); 514 poll(&pfd, 1, INFTIM);
500 } while (readframe(spc) < 1); 515 } while (readframe(spc) < 1);
501 516
502 if (spc->spc_hdr.rsp_type != RUMPSP_COPYIN_RESP) { 517 if (spc->spc_hdr.rsp_type != RUMPSP_COPYIN_RESP) {
503 abort(); 518 abort();
504 } 519 }
505 520
506 memcpy(kaddr, spc->spc_buf, len); 521 memcpy(kaddr, spc->spc_buf, len);
507 free(spc->spc_buf); 522 free(spc->spc_buf);
508 spc->spc_off = 0; 523 spc->spc_off = 0;
509 524
510 return 0; 525 return 0;
511} 526}
512 527
513int 528int
514rumpuser_sp_copyout(const void *kaddr, void *uaddr, size_t dlen) 529rumpuser_sp_copyout(const void *kaddr, void *uaddr, size_t dlen)
515{ 530{
516 struct spclient *spc; 531 struct spclient *spc;
517 532
518 spc = pthread_getspecific(spclient_tls); 533 spc = pthread_getspecific(spclient_tls);
519 if (!spc) { 534 if (!spc) {
520 DPRINTF(("rump_sp: copyout curlwp not found\n")); 535 DPRINTF(("rump_sp: copyout curlwp not found\n"));
521 return EFAULT; 536 return EFAULT;
522 } 537 }
523 538
524 send_copyout_req(spc, uaddr, kaddr, dlen); 539 send_copyout_req(spc, uaddr, kaddr, dlen);
525 540
526 return 0; 541 return 0;
527} 542}
528 543
529int 544int
530rumpuser_sp_anonmmap(size_t howmuch, void **addr) 545rumpuser_sp_anonmmap(size_t howmuch, void **addr)
531{ 546{
532 struct spclient *spc; 547 struct spclient *spc;
533 struct pollfd pfd; 548 struct pollfd pfd;
534 void *resp; 549 void *resp;
535 550
536 spc = pthread_getspecific(spclient_tls); 551 spc = pthread_getspecific(spclient_tls);
537 if (!spc) 552 if (!spc)
538 return EFAULT; 553 return EFAULT;
539 554
540 send_anonmmap_req(spc, howmuch); 555 send_anonmmap_req(spc, howmuch);
541 556
542 pfd.fd = spc->spc_fd; 557 pfd.fd = spc->spc_fd;
543 pfd.events = POLLIN; 558 pfd.events = POLLIN;
544 do { 559 do {
545 poll(&pfd, 1, INFTIM); 560 poll(&pfd, 1, INFTIM);
546 } while (readframe(spc) < 1); 561 } while (readframe(spc) < 1);
547 562
548 if (spc->spc_hdr.rsp_type != RUMPSP_ANONMMAP_RESP) { 563 if (spc->spc_hdr.rsp_type != RUMPSP_ANONMMAP_RESP) {
549 abort(); 564 abort();
550 } 565 }
551 566
552 /*LINTED*/ 567 /*LINTED*/
553 resp = *(void **)spc->spc_buf; 568 resp = *(void **)spc->spc_buf;
554 spc->spc_off = 0; 569 spc->spc_off = 0;
555 570
556 if (resp == NULL) 571 if (resp == NULL)
557 return ENOMEM; 572 return ENOMEM;
558 573
559 *addr = resp; 574 *addr = resp;
560 return 0; 575 return 0;
561} 576}
562 577
563int 578int
564rumpuser_sp_syscall(int sysnum, const void *data, size_t dlen, 579rumpuser_sp_syscall(int sysnum, const void *data, size_t dlen,
565 register_t *retval) 580 register_t *retval)
566{ 581{
567 struct rsp_sysresp *resp; 582 struct rsp_sysresp *resp;
568 struct rsp_copydata *copydata; 583 struct rsp_copydata *copydata;
569 struct pollfd pfd; 584 struct pollfd pfd;
570 size_t maplen; 585 size_t maplen;
571 void *mapaddr; 586 void *mapaddr;
572 int gotresp; 587 int gotresp;
573 588
574 DPRINTF(("rump_sp_syscall: executing syscall %d\n", sysnum)); 589 DPRINTF(("rump_sp_syscall: executing syscall %d\n", sysnum));
575 590
576 send_syscall_req(&clispc, sysnum, data, dlen); 591 send_syscall_req(&clispc, sysnum, data, dlen);
577 592
578 DPRINTF(("rump_sp_syscall: syscall %d request sent. " 593 DPRINTF(("rump_sp_syscall: syscall %d request sent. "
579 "waiting for response\n", sysnum)); 594 "waiting for response\n", sysnum));
580 595
581 pfd.fd = clispc.spc_fd; 596 pfd.fd = clispc.spc_fd;
582 pfd.events = POLLIN; 597 pfd.events = POLLIN;
583 598
584 gotresp = 0; 599 gotresp = 0;
585 while (!gotresp) { 600 while (!gotresp) {
586 while (readframe(&clispc) < 1) 601 while (readframe(&clispc) < 1)
587 poll(&pfd, 1, INFTIM); 602 poll(&pfd, 1, INFTIM);
588 603
589 switch (clispc.spc_hdr.rsp_type) { 604 switch (clispc.spc_hdr.rsp_type) {
590 case RUMPSP_COPYIN_REQ: 605 case RUMPSP_COPYIN_REQ:
591 /*LINTED*/ 606 /*LINTED*/
592 copydata = (struct rsp_copydata *)clispc.spc_buf; 607 copydata = (struct rsp_copydata *)clispc.spc_buf;
593 DPRINTF(("rump_sp_syscall: copyin request: %p/%zu\n", 608 DPRINTF(("rump_sp_syscall: copyin request: %p/%zu\n",
594 copydata->rcp_addr, copydata->rcp_len)); 609 copydata->rcp_addr, copydata->rcp_len));
595 send_copyin_resp(&clispc, clispc.spc_hdr.rsp_reqno, 610 send_copyin_resp(&clispc, clispc.spc_hdr.rsp_reqno,
596 copydata->rcp_addr, copydata->rcp_len); 611 copydata->rcp_addr, copydata->rcp_len);
597 clispc.spc_off = 0; 612 clispc.spc_off = 0;
598 break; 613 break;
599 case RUMPSP_COPYOUT_REQ: 614 case RUMPSP_COPYOUT_REQ:
600 /*LINTED*/ 615 /*LINTED*/
601 copydata = (struct rsp_copydata *)clispc.spc_buf; 616 copydata = (struct rsp_copydata *)clispc.spc_buf;
602 DPRINTF(("rump_sp_syscall: copyout request: %p/%zu\n", 617 DPRINTF(("rump_sp_syscall: copyout request: %p/%zu\n",
603 copydata->rcp_addr, copydata->rcp_len)); 618 copydata->rcp_addr, copydata->rcp_len));
604 /*LINTED*/ 619 /*LINTED*/
605 memcpy(copydata->rcp_addr, copydata->rcp_data, 620 memcpy(copydata->rcp_addr, copydata->rcp_data,
606 copydata->rcp_len); 621 copydata->rcp_len);
607 clispc.spc_off = 0; 622 clispc.spc_off = 0;
608 break; 623 break;
609 case RUMPSP_ANONMMAP_REQ: 624 case RUMPSP_ANONMMAP_REQ:
610 /*LINTED*/ 625 /*LINTED*/
611 maplen = *(size_t *)clispc.spc_buf; 626 maplen = *(size_t *)clispc.spc_buf;
612 mapaddr = mmap(NULL, maplen, PROT_READ|PROT_WRITE, 627 mapaddr = mmap(NULL, maplen, PROT_READ|PROT_WRITE,
613 MAP_ANON, -1, 0); 628 MAP_ANON, -1, 0);
614 if (mapaddr == MAP_FAILED) 629 if (mapaddr == MAP_FAILED)
615 mapaddr = NULL; 630 mapaddr = NULL;
616 send_anonmmap_resp(&clispc, 631 send_anonmmap_resp(&clispc,
617 clispc.spc_hdr.rsp_reqno, mapaddr); 632 clispc.spc_hdr.rsp_reqno, mapaddr);
618 clispc.spc_off = 0; 633 clispc.spc_off = 0;
619 break; 634 break;
620 case RUMPSP_SYSCALL_RESP: 635 case RUMPSP_SYSCALL_RESP:
621 DPRINTF(("rump_sp_syscall: got response \n")); 636 DPRINTF(("rump_sp_syscall: got response \n"));
622 gotresp = 1; 637 gotresp = 1;
623 break; 638 break;
624 } 639 }
625 } 640 }
626 641
627 /*LINTED*/ 642 /*LINTED*/
628 resp = (struct rsp_sysresp *)clispc.spc_buf; 643 resp = (struct rsp_sysresp *)clispc.spc_buf;
629 memcpy(retval, &resp->rsys_retval, sizeof(resp->rsys_retval)); 644 memcpy(retval, &resp->rsys_retval, sizeof(resp->rsys_retval));
630 clispc.spc_off = 0; 645 clispc.spc_off = 0;
631 646
632 return resp->rsys_error; 647 return resp->rsys_error;
633} 648}
634 649
635/* 650/*
636 * 651 *
637 * Startup routines and mainloop for server. 652 * Startup routines and mainloop for server.
638 * 653 *
639 */ 654 */
640 655
641static int 656static int
642tcp_parse(const char *addr, int type, struct sockaddr **sa) 657tcp_parse(const char *addr, int type, struct sockaddr **sa)
643{ 658{
644 struct sockaddr_in sin; 659 struct sockaddr_in sin;
645 char buf[64]; 660 char buf[64];
646 const char *p; 661 const char *p;
647 size_t l; 662 size_t l;
648 int port; 663 int port;
649 664
650 memset(&sin, 0, sizeof(sin)); 665 memset(&sin, 0, sizeof(sin));
651 sin.sin_len = sizeof(sin); 666 sin.sin_len = sizeof(sin);
652 sin.sin_family = AF_INET; 667 sin.sin_family = AF_INET;
653 668
654 p = strchr(addr, ':'); 669 p = strchr(addr, ':');
655 if (!p) { 670 if (!p) {
656 fprintf(stderr, "rump_sp_tcp: missing port specifier\n"); 671 fprintf(stderr, "rump_sp_tcp: missing port specifier\n");
657 return EINVAL; 672 return EINVAL;
658 } 673 }
659 674
660 l = p - addr; 675 l = p - addr;
661 if (l > sizeof(buf)-1) { 676 if (l > sizeof(buf)-1) {
662 fprintf(stderr, "rump_sp_tcp: address too long\n"); 677 fprintf(stderr, "rump_sp_tcp: address too long\n");
663 return EINVAL; 678 return EINVAL;
664 } 679 }
665 strncpy(buf, addr, l); 680 strncpy(buf, addr, l);
666 buf[l] = '\0'; 681 buf[l] = '\0';
667 682
668 /* special INADDR_ANY treatment */ 683 /* special INADDR_ANY treatment */
669 if (strcmp(buf, "*") == 0 || strcmp(buf, "0") == 0) { 684 if (strcmp(buf, "*") == 0 || strcmp(buf, "0") == 0) {
670 sin.sin_addr.s_addr = INADDR_ANY; 685 sin.sin_addr.s_addr = INADDR_ANY;
671 } else { 686 } else {
672 switch (inet_pton(AF_INET, buf, &sin.sin_addr)) { 687 switch (inet_pton(AF_INET, buf, &sin.sin_addr)) {
673 case 1: 688 case 1:
674 break; 689 break;
675 case 0: 690 case 0:
676 fprintf(stderr, "rump_sp_tcp: cannot parse %s\n", buf); 691 fprintf(stderr, "rump_sp_tcp: cannot parse %s\n", buf);
677 return EINVAL; 692 return EINVAL;
678 case -1: 693 case -1:
679 fprintf(stderr, "rump_sp_tcp: inet_pton failed\n"); 694 fprintf(stderr, "rump_sp_tcp: inet_pton failed\n");
680 return errno; 695 return errno;
681 default: 696 default:
682 assert(/*CONSTCOND*/0); 697 assert(/*CONSTCOND*/0);
683 return EINVAL; 698 return EINVAL;
684 } 699 }
685 } 700 }
686 701
687 if (type == RUMP_SP_CLIENT && sin.sin_addr.s_addr == INADDR_ANY) { 702 if (type == RUMP_SP_CLIENT && sin.sin_addr.s_addr == INADDR_ANY) {
688 fprintf(stderr, "rump_sp_tcp: client needs !INADDR_ANY\n"); 703 fprintf(stderr, "rump_sp_tcp: client needs !INADDR_ANY\n");
689 return EINVAL; 704 return EINVAL;
690 } 705 }
691 706
692 /* advance to port number & parse */ 707 /* advance to port number & parse */
693 p++; 708 p++;
694 l = strspn(p, "0123456789"); 709 l = strspn(p, "0123456789");
695 if (l == 0) { 710 if (l == 0) {
696 fprintf(stderr, "rump_sp_tcp: port now found: %s\n", p); 711 fprintf(stderr, "rump_sp_tcp: port now found: %s\n", p);
697 return EINVAL; 712 return EINVAL;
698 } 713 }
699 strncpy(buf, p, l); 714 strncpy(buf, p, l);
700 buf[l] = '\0'; 715 buf[l] = '\0';
701 716
702 if (*(p+l) != '/' && *(p+l) != '\0') { 717 if (*(p+l) != '/' && *(p+l) != '\0') {
703 fprintf(stderr, "rump_sp_tcp: junk at end of port: %s\n", addr); 718 fprintf(stderr, "rump_sp_tcp: junk at end of port: %s\n", addr);
704 return EINVAL; 719 return EINVAL;
705 } 720 }
706 721
707 port = atoi(buf); 722 port = atoi(buf);
708 if (port < 0 || port >= (1<<(8*sizeof(in_port_t)))) { 723 if (port < 0 || port >= (1<<(8*sizeof(in_port_t)))) {
709 fprintf(stderr, "rump_sp_tcp: port %d out of range\n", port); 724 fprintf(stderr, "rump_sp_tcp: port %d out of range\n", port);
710 return ERANGE; 725 return ERANGE;
711 } 726 }
712 sin.sin_port = htons(port); 727 sin.sin_port = htons(port);
713 728
714 *sa = malloc(sizeof(sin)); 729 *sa = malloc(sizeof(sin));
715 if (*sa == NULL) 730 if (*sa == NULL)
716 return errno; 731 return errno;
717 memcpy(*sa, &sin, sizeof(sin)); 732 memcpy(*sa, &sin, sizeof(sin));
718 return 0; 733 return 0;
719} 734}
720 735
721static int 736static int
722tcp_connecthook(int s) 737tcp_connecthook(int s)
723{ 738{
724 int x; 739 int x;
725 740
726 x = 1; 741 x = 1;
727 setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &x, sizeof(x)); 742 setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &x, sizeof(x));
728 743
729 return 0; 744 return 0;
730} 745}
731 746
732/*ARGSUSED*/ 747/*ARGSUSED*/
733static int 748static int
734notsupp(void) 749notsupp(void)
735{ 750{
736 751
737 fprintf(stderr, "rump_sp: support not yet implemented\n"); 752 fprintf(stderr, "rump_sp: support not yet implemented\n");
738 return EOPNOTSUPP; 753 return EOPNOTSUPP;
739} 754}
740 755
741static int 756static int
742success(void) 757success(void)
743{ 758{
744 759
745 return 0; 760 return 0;
746} 761}
747 762
748struct { 763struct {
749 const char *id; 764 const char *id;
750 int domain; 765 int domain;
751 addrparse_fn ap; 766 addrparse_fn ap;
752 connecthook_fn connhook; 767 connecthook_fn connhook;
753} parsetab[] = { 768} parsetab[] = {
754 { "tcp", PF_INET, tcp_parse, tcp_connecthook }, 769 { "tcp", PF_INET, tcp_parse, tcp_connecthook },
755 { "unix", PF_LOCAL, (addrparse_fn)notsupp, (connecthook_fn)success }, 770 { "unix", PF_LOCAL, (addrparse_fn)notsupp, (connecthook_fn)success },
756 { "tcp6", PF_INET6, (addrparse_fn)notsupp, (connecthook_fn)success }, 771 { "tcp6", PF_INET6, (addrparse_fn)notsupp, (connecthook_fn)success },
757}; 772};
758#define NPARSE (sizeof(parsetab)/sizeof(parsetab[0])) 773#define NPARSE (sizeof(parsetab)/sizeof(parsetab[0]))
759 774
760struct spservarg { 775struct spservarg {
761 int sps_sock; 776 int sps_sock;
762 connecthook_fn sps_connhook; 777 connecthook_fn sps_connhook;
763}; 778};
764 779
765static void * 780static void *
766spserver(void *arg) 781spserver(void *arg)
767{ 782{
768 struct spservarg *sarg = arg; 783 struct spservarg *sarg = arg;
769 unsigned idx; 784 unsigned idx;
770 int seen; 785 int seen;
771 int rv; 786 int rv;
772 787
773 for (idx = 1; idx < MAXCLI; idx++) { 788 for (idx = 1; idx < MAXCLI; idx++) {
774 pfdlist[idx].fd = -1; 789 pfdlist[idx].fd = -1;
775 pfdlist[idx].events = POLLIN; 790 pfdlist[idx].events = POLLIN;
776 } 791 }
777 pfdlist[0].fd = sarg->sps_sock; 792 pfdlist[0].fd = sarg->sps_sock;
778 pfdlist[0].events = POLLIN; 793 pfdlist[0].events = POLLIN;
779 nfds = 1; 794 nfds = 1;
780 maxidx = 0; 795 maxidx = 0;
781 796
782 DPRINTF(("rump_sp: server mainloop\n")); 797 DPRINTF(("rump_sp: server mainloop\n"));
783 798
784 for (;;) { 799 for (;;) {
785 DPRINTF(("rump_sp: loop nfd %d\n", maxidx+1)); 800 DPRINTF(("rump_sp: loop nfd %d\n", maxidx+1));
786 seen = 0; 801 seen = 0;
787 rv = poll(pfdlist, maxidx+1, INFTIM); 802 rv = poll(pfdlist, maxidx+1, INFTIM);
788 assert(maxidx+1 <= MAXCLI); 803 assert(maxidx+1 <= MAXCLI);
789 assert(rv != 0); 804 assert(rv != 0);
790 if (rv == -1) { 805 if (rv == -1) {
791 if (errno == EINTR) 806 if (errno == EINTR)
792 continue; 807 continue;
793 fprintf(stderr, "rump_spserver: poll returned %d\n", 808 fprintf(stderr, "rump_spserver: poll returned %d\n",
794 errno); 809 errno);
795 break; 810 break;
796 } 811 }
797 812
798 for (idx = 0; seen < rv; idx++) { 813 for (idx = 0; seen < rv; idx++) {
799 assert(idx < MAXCLI); 814 assert(idx < MAXCLI);
800 815
801 if ((pfdlist[idx].revents & POLLIN) == 0) 816 if ((pfdlist[idx].revents & POLLIN) == 0)
802 continue; 817 continue;
803 818
804 seen++; 819 seen++;
805 DPRINTF(("rump_sp: activity at [%u] %d/%d\n", 820 DPRINTF(("rump_sp: activity at [%u] %d/%d\n",
806 idx, seen, rv)); 821 idx, seen, rv));
807 if (idx > 0) { 822 if (idx > 0) {
808 struct spclient *spc = &spclist[idx]; 823 struct spclient *spc = &spclist[idx];
809 824
810 DPRINTF(("rump_sp: mainloop read [%u]\n", idx)); 825 DPRINTF(("rump_sp: mainloop read [%u]\n", idx));
811 switch (readframe(spc)) { 826 switch (readframe(spc)) {
812 case 0: 827 case 0:
813 break; 828 break;
814 case -1: 829 case -1:
815 serv_handle_disco(idx); 830 serv_handledisco(idx);
816 break; 831 break;
817 default: 832 default:
818 spc->spc_off = 0; 833 spc->spc_off = 0;
819 serv_handlesyscall(spc, 834 serv_handlesyscall(spc,
820 &spc->spc_hdr, spc->spc_buf); 835 &spc->spc_hdr, spc->spc_buf);
821 spc->spc_buf = NULL; 836 spc->spc_buf = NULL;
822 break; 837 break;
823 } 838 }
824 } else { 839 } else {
825 DPRINTF(("rump_sp: mainloop new connection\n")); 840 DPRINTF(("rump_sp: mainloop new connection\n"));
826 serv_handleconn(pfdlist[0].fd, 841 serv_handleconn(pfdlist[0].fd,
827 sarg->sps_connhook); 842 sarg->sps_connhook);
828 } 843 }
829 } 844 }
830 } 845 }
831 846
832 return NULL; 847 return NULL;
833} 848}
834 849
835int 850int
836rumpuser_sp_init(int *typep) 851rumpuser_sp_init(int *typep)
837{ 852{
838 struct spservarg *sarg; 853 struct spservarg *sarg;
839 struct sockaddr *sap; 854 struct sockaddr *sap;
840 char id[16]; 855 char id[16];
841 char *p, *p2; 856 char *p, *p2;
842 size_t l; 857 size_t l;
843 unsigned i; 858 unsigned i;
844 int error, type, s; 859 int error, type, s;
845 860
846 p = NULL; 861 p = NULL;
847 error = 0; 862 error = 0;
848 863
849 type = RUMP_SP_NONE; 864 type = RUMP_SP_NONE;
850 if ((p = getenv("RUMP_SP_SERVER")) != NULL) { 865 if ((p = getenv("RUMP_SP_SERVER")) != NULL) {
851 type = RUMP_SP_SERVER; 866 type = RUMP_SP_SERVER;
852 } 867 }
853 if ((p2 = getenv("RUMP_SP_CLIENT")) != NULL) { 868 if ((p2 = getenv("RUMP_SP_CLIENT")) != NULL) {
854 if (type != RUMP_SP_NONE) 869 if (type != RUMP_SP_NONE)
855 return EEXIST; 870 return EEXIST;
856 type = RUMP_SP_CLIENT; 871 type = RUMP_SP_CLIENT;
857 p = p2; 872 p = p2;
858 } 873 }
859 874
860 /* 875 /*
861 * Parse the url 876 * Parse the url
862 */ 877 */
863 878
864 if (type == RUMP_SP_NONE) 879 if (type == RUMP_SP_NONE)
865 return RUMP_SP_NONE; 880 return RUMP_SP_NONE;
866 881
867 p2 = strstr(p, "://"); 882 p2 = strstr(p, "://");
868 if (!p2) { 883 if (!p2) {
869 fprintf(stderr, "rump_sp: invalid locator ``%s''\n", p); 884 fprintf(stderr, "rump_sp: invalid locator ``%s''\n", p);
870 return EINVAL; 885 return EINVAL;
871 } 886 }
872 l = p2-p; 887 l = p2-p;
873 if (l > sizeof(id)-1) { 888 if (l > sizeof(id)-1) {
874 fprintf(stderr, "rump_sp: identifier too long in ``%s''\n", p); 889 fprintf(stderr, "rump_sp: identifier too long in ``%s''\n", p);
875 return EINVAL; 890 return EINVAL;
876 } 891 }
877 892
878 strncpy(id, p, l); 893 strncpy(id, p, l);
879 id[l] = '\0'; 894 id[l] = '\0';
880 p2 += 3; /* beginning of address */ 895 p2 += 3; /* beginning of address */
881 896
882 for (i = 0; i < NPARSE; i++) { 897 for (i = 0; i < NPARSE; i++) {
883 if (strcmp(id, parsetab[i].id) == 0) { 898 if (strcmp(id, parsetab[i].id) == 0) {
884 error = parsetab[i].ap(p2, type, &sap); 899 error = parsetab[i].ap(p2, type, &sap);
885 if (error) 900 if (error)
886 return error; 901 return error;
887 break; 902 break;
888 } 903 }
889 } 904 }
890 if (i == NPARSE) { 905 if (i == NPARSE) {
891 fprintf(stderr, "rump_sp: invalid identifier ``%s''\n", p); 906 fprintf(stderr, "rump_sp: invalid identifier ``%s''\n", p);
892 return EINVAL; 907 return EINVAL;
893 } 908 }
894 909
895 s = socket(parsetab[i].domain, SOCK_STREAM, 0); 910 s = socket(parsetab[i].domain, SOCK_STREAM, 0);
896 if (s == -1) 911 if (s == -1)
897 return errno; 912 return errno;
898 913
899 if (type == RUMP_SP_CLIENT) { 914 if (type == RUMP_SP_CLIENT) {
900 /*LINTED*/ 915 /*LINTED*/
901 if (connect(s, sap, sap->sa_len) == -1) { 916 if (connect(s, sap, sap->sa_len) == -1) {
902 fprintf(stderr, "rump_sp: client connect failed\n"); 917 fprintf(stderr, "rump_sp: client connect failed\n");
903 return errno; 918 return errno;
904 } 919 }
905 if ((error = parsetab[i].connhook(s)) != 0) { 920 if ((error = parsetab[i].connhook(s)) != 0) {
906 fprintf(stderr, "rump_sp: connect hook failed\n"); 921 fprintf(stderr, "rump_sp: connect hook failed\n");
907 return error; 922 return error;
908 } 923 }
909 924
910 clispc.spc_fd = s; 925 clispc.spc_fd = s;
911 } else { 926 } else {
912 pthread_t pt; 927 pthread_t pt;
913 928
914 sarg = malloc(sizeof(*sarg)); 929 sarg = malloc(sizeof(*sarg));
915 if (sarg == NULL) { 930 if (sarg == NULL) {
916 close(s); 931 close(s);
917 return ENOMEM; 932 return ENOMEM;
918 } 933 }
919 934
920 sarg->sps_sock = s; 935 sarg->sps_sock = s;
921 sarg->sps_connhook = parsetab[i].connhook; 936 sarg->sps_connhook = parsetab[i].connhook;
922 937
923 /* sloppy error recovery */ 938 /* sloppy error recovery */
924 939
925 error = pthread_key_create(&spclient_tls, NULL); 940 error = pthread_key_create(&spclient_tls, NULL);
926 if (error) { 941 if (error) {
927 fprintf(stderr, "rump_sp: tls create failed\n"); 942 fprintf(stderr, "rump_sp: tls create failed\n");
928 return error; 943 return error;
929 } 944 }
930 945
931 /*LINTED*/ 946 /*LINTED*/
932 if (bind(s, sap, sap->sa_len) == -1) { 947 if (bind(s, sap, sap->sa_len) == -1) {
933 fprintf(stderr, "rump_sp: server bind failed\n"); 948 fprintf(stderr, "rump_sp: server bind failed\n");
934 return errno; 949 return errno;
935 } 950 }
936 if (listen(s, 20) == -1) { 951 if (listen(s, 20) == -1) {
937 fprintf(stderr, "rump_sp: server listen failed\n"); 952 fprintf(stderr, "rump_sp: server listen failed\n");
938 return errno; 953 return errno;
939 } 954 }
940 955
941 if ((error = pthread_create(&pt, NULL, spserver, sarg)) != 0) { 956 if ((error = pthread_create(&pt, NULL, spserver, sarg)) != 0) {
942 fprintf(stderr, "rump_sp: cannot create wrkr thread\n"); 957 fprintf(stderr, "rump_sp: cannot create wrkr thread\n");
943 return errno; 958 return errno;
944 } 959 }
945 pthread_detach(pt); 960 pthread_detach(pt);
946 } 961 }
947 962
948 *typep = type; 963 *typep = type;
949 return 0; 964 return 0;
950} 965}