Module Name: src Committed By: pooka Date: Thu Nov 4 20:54:08 UTC 2010
Modified Files: src/lib/librumpuser: rumpuser_sp.c src/sys/rump/include/rump: rump_syscalls.h rumpuser.h src/sys/rump/librump/rumpkern: rump.c rump_private.h Added Files: src/lib/librumpuser: sp_common.c Log Message: Refactor the sysproxy code so that rumpuser contains only the server side. To generate a diff of this commit: cvs rdiff -u -r1.4 -r1.5 src/lib/librumpuser/rumpuser_sp.c cvs rdiff -u -r0 -r1.1 src/lib/librumpuser/sp_common.c cvs rdiff -u -r1.31 -r1.32 src/sys/rump/include/rump/rump_syscalls.h cvs rdiff -u -r1.48 -r1.49 src/sys/rump/include/rump/rumpuser.h cvs rdiff -u -r1.195 -r1.196 src/sys/rump/librump/rumpkern/rump.c cvs rdiff -u -r1.60 -r1.61 src/sys/rump/librump/rumpkern/rump_private.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/librumpuser/rumpuser_sp.c diff -u src/lib/librumpuser/rumpuser_sp.c:1.4 src/lib/librumpuser/rumpuser_sp.c:1.5 --- src/lib/librumpuser/rumpuser_sp.c:1.4 Mon Nov 1 13:55:19 2010 +++ src/lib/librumpuser/rumpuser_sp.c Thu Nov 4 20:54:07 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: rumpuser_sp.c,v 1.4 2010/11/01 13:55:19 pooka Exp $ */ +/* $NetBSD: rumpuser_sp.c,v 1.5 2010/11/04 20:54:07 pooka Exp $ */ /* * Copyright (c) 2010 Antti Kantee. All Rights Reserved. @@ -38,7 +38,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: rumpuser_sp.c,v 1.4 2010/11/01 13:55:19 pooka Exp $"); +__RCSID("$NetBSD: rumpuser_sp.c,v 1.5 2010/11/04 20:54:07 pooka Exp $"); #include <sys/types.h> #include <sys/mman.h> @@ -61,84 +61,7 @@ #include <rump/rumpuser.h> -//#define DEBUG -#ifdef DEBUG -#include <rump/rump.h> -#include <rump/rump_syscalls.h> -#define DPRINTF(x) mydprintf x -static void -mydprintf(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); -} -#else -#define DPRINTF(x) -#endif - -/* - * Bah, I hate writing on-off-wire conversions in C - */ - -enum { - RUMPSP_SYSCALL_REQ, RUMPSP_SYSCALL_RESP, - RUMPSP_COPYIN_REQ, RUMPSP_COPYIN_RESP, - RUMPSP_COPYOUT_REQ, /* no copyout resp */ - RUMPSP_ANONMMAP_REQ, RUMPSP_ANONMMAP_RESP -}; - -struct rsp_hdr { - uint64_t rsp_len; - uint64_t rsp_reqno; - uint32_t rsp_type; - /* - * We want this structure 64bit-aligned for typecast fun, - * so might as well use the following for something. - */ - uint32_t rsp_sysnum; -}; -#define HDRSZ sizeof(struct rsp_hdr) - -/* - * Data follows the header. We have two types of structured data. - */ - -/* copyin/copyout */ -struct rsp_copydata { - size_t rcp_len; - void *rcp_addr; - uint8_t rcp_data[0]; -}; - -/* syscall response */ -struct rsp_sysresp { - int rsys_error; - register_t rsys_retval[2]; -}; - - -struct spclient { - int spc_fd; - struct lwp *spc_lwp; - - /* incoming */ - struct rsp_hdr spc_hdr; - uint8_t *spc_buf; - size_t spc_off; - -#if 0 - /* outgoing */ - int spc_obusy; - pthread_mutex_t spc_omtx; - pthread_cond_t spc_cv; -#endif -}; - -typedef int (*addrparse_fn)(const char *, int, struct sockaddr **); -typedef int (*connecthook_fn)(int); +#include "sp_common.c" #define MAXCLI 4 @@ -148,8 +71,6 @@ static uint64_t nextreq; static pthread_key_t spclient_tls; -static struct spclient clispc; - static struct rumpuser_sp_ops spops; /* @@ -212,57 +133,6 @@ } static int -dosend(struct spclient *spc, const void *data, size_t dlen) -{ - struct pollfd pfd; - const uint8_t *sdata = data; - ssize_t n; - size_t sent; - int fd = spc->spc_fd; - - pfd.fd = fd; - pfd.events = POLLOUT; - - for (sent = 0, n = 0; sent < dlen; ) { - if (n) { - if (poll(&pfd, 1, INFTIM) == -1) { - if (errno == EINTR) - continue; - return errno; - } - } - - n = write(fd, sdata + sent, dlen - sent); - if (n == 0) { - return EFAULT; - } - if (n == -1 && errno != EAGAIN) { - return EFAULT; - } - sent += n; - } - - return 0; -} - -static int -send_syscall_req(struct spclient *spc, int sysnum, - const void *data, size_t dlen) -{ - struct rsp_hdr rhdr; - - rhdr.rsp_len = sizeof(rhdr) + dlen; - rhdr.rsp_reqno = nextreq++; - rhdr.rsp_type = RUMPSP_SYSCALL_REQ; - rhdr.rsp_sysnum = sysnum; - - dosend(spc, &rhdr, sizeof(rhdr)); - dosend(spc, data, dlen); - - return 0; -} - -static int send_syscall_resp(struct spclient *spc, uint64_t reqno, int error, register_t retval[2]) { @@ -304,22 +174,6 @@ } static int -send_copyin_resp(struct spclient *spc, uint64_t reqno, void *data, size_t dlen) -{ - struct rsp_hdr rhdr; - - rhdr.rsp_len = sizeof(rhdr) + dlen; - rhdr.rsp_reqno = reqno; - rhdr.rsp_type = RUMPSP_COPYIN_RESP; - rhdr.rsp_sysnum = 0; - - dosend(spc, &rhdr, sizeof(rhdr)); - dosend(spc, data, dlen); - - return 0; -} - -static int send_copyout_req(struct spclient *spc, const void *remaddr, const void *data, size_t dlen) { @@ -357,22 +211,6 @@ return 0; } -static int -send_anonmmap_resp(struct spclient *spc, uint64_t reqno, void *addr) -{ - struct rsp_hdr rhdr; - - rhdr.rsp_len = sizeof(rhdr) + sizeof(addr); - rhdr.rsp_reqno = reqno; - rhdr.rsp_type = RUMPSP_ANONMMAP_RESP; - rhdr.rsp_sysnum = 0; - - dosend(spc, &rhdr, sizeof(rhdr)); - dosend(spc, &addr, sizeof(addr)); - - return 0; -} - static void serv_handledisco(unsigned int idx) { @@ -455,7 +293,7 @@ maxidx = i; DPRINTF(("rump_sp: added new connection at idx %u, pid %d\n", - i, rump_sys_getpid())); /* XXX: getpid not spop */ + i, 9)); /* XXX: getpid not spop */ lwproc_switch(NULL); @@ -478,83 +316,9 @@ lwproc_switch(NULL); pthread_setspecific(spclient_tls, NULL); - send_syscall_resp(spc, rhdr->rsp_reqno, rv, retval); -} - -static int -readframe(struct spclient *spc) -{ - int fd = spc->spc_fd; - size_t left; - size_t framelen; - ssize_t n; - - /* still reading header? */ - if (spc->spc_off < HDRSZ) { - DPRINTF(("rump_sp: readframe getting header at offset %zu\n", - spc->spc_off)); - - left = HDRSZ - spc->spc_off; - /*LINTED: cast ok */ - n = read(fd, (uint8_t *)&spc->spc_hdr + spc->spc_off, left); - if (n == 0) { - return -1; - } - if (n == -1) { - if (errno == EAGAIN) - return 0; - return -1; - } - - spc->spc_off += n; - if (spc->spc_off < HDRSZ) - return -1; - - /*LINTED*/ - framelen = spc->spc_hdr.rsp_len; - - if (framelen < HDRSZ) { - return -1; - } else if (framelen == HDRSZ) { - return 1; - } - - spc->spc_buf = malloc(framelen - HDRSZ); - if (spc->spc_buf == NULL) { - return -1; - } - memset(spc->spc_buf, 0, framelen - HDRSZ); - - /* "fallthrough" */ - } else { - /*LINTED*/ - framelen = spc->spc_hdr.rsp_len; - } - - left = framelen - spc->spc_off; - - DPRINTF(("rump_sp: readframe getting body at offset %zu, left %zu\n", - spc->spc_off, left)); - - if (left == 0) - return 1; - n = read(fd, spc->spc_buf + (spc->spc_off - HDRSZ), left); - if (n == 0) { - return -1; - } - if (n == -1) { - if (errno == EAGAIN) - return 0; - return -1; - } - spc->spc_off += n; - left -= n; + DPRINTF(("rump_sp: got return value %d\n", rv)); - /* got everything? */ - if (left == 0) - return 1; - else - return 0; + send_syscall_resp(spc, rhdr->rsp_reqno, rv, retval); } int @@ -636,203 +400,12 @@ return 0; } -int -rumpuser_sp_syscall(int sysnum, const void *data, size_t dlen, - register_t *retval) -{ - struct rsp_sysresp *resp; - struct rsp_copydata *copydata; - struct pollfd pfd; - size_t maplen; - void *mapaddr; - int gotresp; - - DPRINTF(("rump_sp_syscall: executing syscall %d\n", sysnum)); - - send_syscall_req(&clispc, sysnum, data, dlen); - - DPRINTF(("rump_sp_syscall: syscall %d request sent. " - "waiting for response\n", sysnum)); - - pfd.fd = clispc.spc_fd; - pfd.events = POLLIN; - - gotresp = 0; - while (!gotresp) { - while (readframe(&clispc) < 1) - poll(&pfd, 1, INFTIM); - - switch (clispc.spc_hdr.rsp_type) { - case RUMPSP_COPYIN_REQ: - /*LINTED*/ - copydata = (struct rsp_copydata *)clispc.spc_buf; - DPRINTF(("rump_sp_syscall: copyin request: %p/%zu\n", - copydata->rcp_addr, copydata->rcp_len)); - send_copyin_resp(&clispc, clispc.spc_hdr.rsp_reqno, - copydata->rcp_addr, copydata->rcp_len); - clispc.spc_off = 0; - break; - case RUMPSP_COPYOUT_REQ: - /*LINTED*/ - copydata = (struct rsp_copydata *)clispc.spc_buf; - DPRINTF(("rump_sp_syscall: copyout request: %p/%zu\n", - copydata->rcp_addr, copydata->rcp_len)); - /*LINTED*/ - memcpy(copydata->rcp_addr, copydata->rcp_data, - copydata->rcp_len); - clispc.spc_off = 0; - break; - case RUMPSP_ANONMMAP_REQ: - /*LINTED*/ - maplen = *(size_t *)clispc.spc_buf; - mapaddr = mmap(NULL, maplen, PROT_READ|PROT_WRITE, - MAP_ANON, -1, 0); - if (mapaddr == MAP_FAILED) - mapaddr = NULL; - send_anonmmap_resp(&clispc, - clispc.spc_hdr.rsp_reqno, mapaddr); - clispc.spc_off = 0; - break; - case RUMPSP_SYSCALL_RESP: - DPRINTF(("rump_sp_syscall: got response \n")); - gotresp = 1; - break; - } - } - - /*LINTED*/ - resp = (struct rsp_sysresp *)clispc.spc_buf; - memcpy(retval, &resp->rsys_retval, sizeof(resp->rsys_retval)); - clispc.spc_off = 0; - - return resp->rsys_error; -} - /* * * Startup routines and mainloop for server. * */ -static int -tcp_parse(const char *addr, int type, struct sockaddr **sa) -{ - struct sockaddr_in sin; - char buf[64]; - const char *p; - size_t l; - int port; - - memset(&sin, 0, sizeof(sin)); - sin.sin_len = sizeof(sin); - sin.sin_family = AF_INET; - - p = strchr(addr, ':'); - if (!p) { - fprintf(stderr, "rump_sp_tcp: missing port specifier\n"); - return EINVAL; - } - - l = p - addr; - if (l > sizeof(buf)-1) { - fprintf(stderr, "rump_sp_tcp: address too long\n"); - return EINVAL; - } - strncpy(buf, addr, l); - buf[l] = '\0'; - - /* special INADDR_ANY treatment */ - if (strcmp(buf, "*") == 0 || strcmp(buf, "0") == 0) { - sin.sin_addr.s_addr = INADDR_ANY; - } else { - switch (inet_pton(AF_INET, buf, &sin.sin_addr)) { - case 1: - break; - case 0: - fprintf(stderr, "rump_sp_tcp: cannot parse %s\n", buf); - return EINVAL; - case -1: - fprintf(stderr, "rump_sp_tcp: inet_pton failed\n"); - return errno; - default: - assert(/*CONSTCOND*/0); - return EINVAL; - } - } - - if (type == RUMP_SP_CLIENT && sin.sin_addr.s_addr == INADDR_ANY) { - fprintf(stderr, "rump_sp_tcp: client needs !INADDR_ANY\n"); - return EINVAL; - } - - /* advance to port number & parse */ - p++; - l = strspn(p, "0123456789"); - if (l == 0) { - fprintf(stderr, "rump_sp_tcp: port now found: %s\n", p); - return EINVAL; - } - strncpy(buf, p, l); - buf[l] = '\0'; - - if (*(p+l) != '/' && *(p+l) != '\0') { - fprintf(stderr, "rump_sp_tcp: junk at end of port: %s\n", addr); - return EINVAL; - } - - port = atoi(buf); - if (port < 0 || port >= (1<<(8*sizeof(in_port_t)))) { - fprintf(stderr, "rump_sp_tcp: port %d out of range\n", port); - return ERANGE; - } - sin.sin_port = htons(port); - - *sa = malloc(sizeof(sin)); - if (*sa == NULL) - return errno; - memcpy(*sa, &sin, sizeof(sin)); - return 0; -} - -static int -tcp_connecthook(int s) -{ - int x; - - x = 1; - setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &x, sizeof(x)); - - return 0; -} - -/*ARGSUSED*/ -static int -notsupp(void) -{ - - fprintf(stderr, "rump_sp: support not yet implemented\n"); - return EOPNOTSUPP; -} - -static int -success(void) -{ - - return 0; -} - -struct { - const char *id; - int domain; - addrparse_fn ap; - connecthook_fn connhook; -} parsetab[] = { - { "tcp", PF_INET, tcp_parse, tcp_connecthook }, - { "unix", PF_LOCAL, (addrparse_fn)notsupp, (connecthook_fn)success }, - { "tcp6", PF_INET6, (addrparse_fn)notsupp, (connecthook_fn)success }, -}; -#define NPARSE (sizeof(parsetab)/sizeof(parsetab[0])) - struct spservarg { int sps_sock; connecthook_fn sps_connhook; @@ -909,119 +482,60 @@ } int -rumpuser_sp_init(const struct rumpuser_sp_ops *spopsp, int *typep) +rumpuser_sp_init(const struct rumpuser_sp_ops *spopsp, const char *url) { + pthread_t pt; struct spservarg *sarg; struct sockaddr *sap; - char id[16]; - char *p, *p2; - size_t l; - unsigned i; - int error, type, s; - - p = NULL; - error = 0; - spops = *spopsp; - - type = RUMP_SP_NONE; - if ((p = getenv("RUMP_SP_SERVER")) != NULL) { - type = RUMP_SP_SERVER; - } - if ((p2 = getenv("RUMP_SP_CLIENT")) != NULL) { - if (type != RUMP_SP_NONE) - return EEXIST; - type = RUMP_SP_CLIENT; - p = p2; - } - - /* - * Parse the url - */ - - if (type == RUMP_SP_NONE) - return RUMP_SP_NONE; - - p2 = strstr(p, "://"); - if (!p2) { - fprintf(stderr, "rump_sp: invalid locator ``%s''\n", p); - return EINVAL; - } - l = p2-p; - if (l > sizeof(id)-1) { - fprintf(stderr, "rump_sp: identifier too long in ``%s''\n", p); - return EINVAL; - } + char *p; + unsigned idx; + int error, s; - strncpy(id, p, l); - id[l] = '\0'; - p2 += 3; /* beginning of address */ - - for (i = 0; i < NPARSE; i++) { - if (strcmp(id, parsetab[i].id) == 0) { - error = parsetab[i].ap(p2, type, &sap); - if (error) - return error; - break; - } - } - if (i == NPARSE) { - fprintf(stderr, "rump_sp: invalid identifier ``%s''\n", p); - return EINVAL; - } + p = strdup(url); + if (p == NULL) + return ENOMEM; + error = parseurl(p, &sap, &idx, 1); + free(p); + if (error) + return error; - s = socket(parsetab[i].domain, SOCK_STREAM, 0); + s = socket(parsetab[idx].domain, SOCK_STREAM, 0); if (s == -1) return errno; - if (type == RUMP_SP_CLIENT) { - /*LINTED*/ - if (connect(s, sap, sap->sa_len) == -1) { - fprintf(stderr, "rump_sp: client connect failed\n"); - return errno; - } - if ((error = parsetab[i].connhook(s)) != 0) { - fprintf(stderr, "rump_sp: connect hook failed\n"); - return error; - } - - clispc.spc_fd = s; - } else { - pthread_t pt; - - sarg = malloc(sizeof(*sarg)); - if (sarg == NULL) { - close(s); - return ENOMEM; - } + spops = *spopsp; + sarg = malloc(sizeof(*sarg)); + if (sarg == NULL) { + close(s); + return ENOMEM; + } - sarg->sps_sock = s; - sarg->sps_connhook = parsetab[i].connhook; + sarg->sps_sock = s; + sarg->sps_connhook = parsetab[idx].connhook; - /* sloppy error recovery */ + /* sloppy error recovery */ - error = pthread_key_create(&spclient_tls, NULL); - if (error) { - fprintf(stderr, "rump_sp: tls create failed\n"); - return error; - } + error = pthread_key_create(&spclient_tls, NULL); + if (error) { + fprintf(stderr, "rump_sp: tls create failed\n"); + return error; + } - /*LINTED*/ - if (bind(s, sap, sap->sa_len) == -1) { - fprintf(stderr, "rump_sp: server bind failed\n"); - return errno; - } - if (listen(s, 20) == -1) { - fprintf(stderr, "rump_sp: server listen failed\n"); - return errno; - } + /*LINTED*/ + if (bind(s, sap, sap->sa_len) == -1) { + fprintf(stderr, "rump_sp: server bind failed\n"); + return errno; + } + if (listen(s, 20) == -1) { + fprintf(stderr, "rump_sp: server listen failed\n"); + return errno; + } - if ((error = pthread_create(&pt, NULL, spserver, sarg)) != 0) { - fprintf(stderr, "rump_sp: cannot create wrkr thread\n"); - return errno; - } - pthread_detach(pt); + if ((error = pthread_create(&pt, NULL, spserver, sarg)) != 0) { + fprintf(stderr, "rump_sp: cannot create wrkr thread\n"); + return errno; } + pthread_detach(pt); - *typep = type; return 0; } Index: src/sys/rump/include/rump/rump_syscalls.h diff -u src/sys/rump/include/rump/rump_syscalls.h:1.31 src/sys/rump/include/rump/rump_syscalls.h:1.32 --- src/sys/rump/include/rump/rump_syscalls.h:1.31 Tue Sep 7 17:10:48 2010 +++ src/sys/rump/include/rump/rump_syscalls.h Thu Nov 4 20:54:07 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: rump_syscalls.h,v 1.31 2010/09/07 17:10:48 pooka Exp $ */ +/* $NetBSD: rump_syscalls.h,v 1.32 2010/11/04 20:54:07 pooka Exp $ */ /* * System call protos in rump namespace. Index: src/sys/rump/include/rump/rumpuser.h diff -u src/sys/rump/include/rump/rumpuser.h:1.48 src/sys/rump/include/rump/rumpuser.h:1.49 --- src/sys/rump/include/rump/rumpuser.h:1.48 Mon Nov 1 13:55:19 2010 +++ src/sys/rump/include/rump/rumpuser.h Thu Nov 4 20:54:08 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: rumpuser.h,v 1.48 2010/11/01 13:55:19 pooka Exp $ */ +/* $NetBSD: rumpuser.h,v 1.49 2010/11/04 20:54:08 pooka Exp $ */ /* * Copyright (c) 2007 Antti Kantee. All Rights Reserved. @@ -215,14 +215,9 @@ int (*spop_syscall)(int, void *, register_t *); }; -int rumpuser_sp_init(const struct rumpuser_sp_ops *, int *); +int rumpuser_sp_init(const struct rumpuser_sp_ops *, const char *); int rumpuser_sp_copyin(const void *, void *, size_t); int rumpuser_sp_copyout(const void *, void *, size_t); -int rumpuser_sp_syscall(int, const void *, size_t, register_t *); int rumpuser_sp_anonmmap(size_t, void **); -#define RUMP_SP_NONE 0 -#define RUMP_SP_CLIENT 1 -#define RUMP_SP_SERVER 2 - #endif /* _RUMP_RUMPUSER_H_ */ Index: src/sys/rump/librump/rumpkern/rump.c diff -u src/sys/rump/librump/rumpkern/rump.c:1.195 src/sys/rump/librump/rumpkern/rump.c:1.196 --- src/sys/rump/librump/rumpkern/rump.c:1.195 Mon Nov 1 13:55:20 2010 +++ src/sys/rump/librump/rumpkern/rump.c Thu Nov 4 20:54:07 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: rump.c,v 1.195 2010/11/01 13:55:20 pooka Exp $ */ +/* $NetBSD: rump.c,v 1.196 2010/11/04 20:54:07 pooka Exp $ */ /* * Copyright (c) 2007 Antti Kantee. All Rights Reserved. @@ -28,7 +28,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rump.c,v 1.195 2010/11/01 13:55:20 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rump.c,v 1.196 2010/11/04 20:54:07 pooka Exp $"); #include <sys/systm.h> #define ELFSIZE ARCH_ELFSIZE @@ -105,7 +105,7 @@ * but good enough for now. */ static struct vmspace sp_vmspace; -static int rumpsp_type; +static bool iamtheserver = false; static char rump_msgbuf[16*1024]; /* 16k should be enough for std rump needs */ @@ -215,16 +215,12 @@ spops.spop_lwproc_newproc = rump_lwproc_newproc; spops.spop_lwproc_curlwp = rump_lwproc_curlwp; spops.spop_syscall = rump_syscall; - if ((error = rumpuser_sp_init(&spops, &rumpsp_type)) != 0) - return error; - /* If we're a client, we can return directly. Otherwise, proceed. */ - switch (rumpsp_type) { - case RUMP_SP_CLIENT: - return 0; - case RUMP_SP_SERVER: - case RUMP_SP_NONE: - break; + if (rumpuser_getenv("RUMP_SP_SERVER", buf, sizeof(buf), &error) == 0) { + error = rumpuser_sp_init(&spops, buf); + if (error) + return error; + iamtheserver = true; } if (rumpuser_getversion() != RUMPUSER_VERSION) { @@ -637,7 +633,6 @@ return 0; } -void *rump_sysproxy_arg; /* XXX: nukeme */ int rump_syscall(int num, void *arg, register_t *retval) { @@ -650,33 +645,16 @@ callp = rump_sysent + num; l = curlwp; - if (rumpsp_type == RUMP_SP_SERVER) + if (iamtheserver) curproc->p_vmspace = &sp_vmspace; rv = sy_call(callp, l, (void *)arg, retval); - if (rumpsp_type == RUMP_SP_SERVER) + if (iamtheserver) curproc->p_vmspace = &vmspace0; return rv; } int -rump_sysproxy(int num, void *arg, uint8_t *data, size_t dlen, - register_t *retval) -{ - int rv; - - if (rumpsp_type == RUMP_SP_CLIENT) { - rv = rumpuser_sp_syscall(num, data, dlen, retval); - } else { - rump_schedule(); - rv = rump_syscall(num, data, retval); - rump_unschedule(); - } - - return rv; -} - -int rump_boot_gethowto() { Index: src/sys/rump/librump/rumpkern/rump_private.h diff -u src/sys/rump/librump/rumpkern/rump_private.h:1.60 src/sys/rump/librump/rumpkern/rump_private.h:1.61 --- src/sys/rump/librump/rumpkern/rump_private.h:1.60 Fri Oct 29 15:32:24 2010 +++ src/sys/rump/librump/rumpkern/rump_private.h Thu Nov 4 20:54:07 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: rump_private.h,v 1.60 2010/10/29 15:32:24 pooka Exp $ */ +/* $NetBSD: rump_private.h,v 1.61 2010/11/04 20:54:07 pooka Exp $ */ /* * Copyright (c) 2007 Antti Kantee. All Rights Reserved. @@ -138,7 +138,4 @@ void *rump_hypermalloc(size_t, int, bool, const char *); void rump_hyperfree(void *, size_t); -int rump_sysproxy(int, void *, uint8_t *, size_t, register_t *); -extern void *rump_sysproxy_arg; - #endif /* _SYS_RUMP_PRIVATE_H_ */ Added files: Index: src/lib/librumpuser/sp_common.c diff -u /dev/null src/lib/librumpuser/sp_common.c:1.1 --- /dev/null Thu Nov 4 20:54:08 2010 +++ src/lib/librumpuser/sp_common.c Thu Nov 4 20:54:07 2010 @@ -0,0 +1,405 @@ +/* $NetBSD: sp_common.c,v 1.1 2010/11/04 20:54:07 pooka Exp $ */ + +/* + * Copyright (c) 2010 Antti Kantee. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Common client/server sysproxy routines. #included. + */ + +#include <sys/cdefs.h> + +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/socket.h> + +#include <arpa/inet.h> +#include <netinet/in.h> +#include <netinet/tcp.h> + +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <poll.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +//#define DEBUG +#ifdef DEBUG +#define DPRINTF(x) mydprintf x +static void +mydprintf(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); +} +#else +#define DPRINTF(x) +#endif + +/* + * Bah, I hate writing on-off-wire conversions in C + */ + +enum { + RUMPSP_SYSCALL_REQ, RUMPSP_SYSCALL_RESP, + RUMPSP_COPYIN_REQ, RUMPSP_COPYIN_RESP, + RUMPSP_COPYOUT_REQ, /* no copyout resp */ + RUMPSP_ANONMMAP_REQ, RUMPSP_ANONMMAP_RESP +}; + +struct rsp_hdr { + uint64_t rsp_len; + uint64_t rsp_reqno; + uint32_t rsp_type; + /* + * We want this structure 64bit-aligned for typecast fun, + * so might as well use the following for something. + */ + uint32_t rsp_sysnum; +}; +#define HDRSZ sizeof(struct rsp_hdr) + +/* + * Data follows the header. We have two types of structured data. + */ + +/* copyin/copyout */ +struct rsp_copydata { + size_t rcp_len; + void *rcp_addr; + uint8_t rcp_data[0]; +}; + +/* syscall response */ +struct rsp_sysresp { + int rsys_error; + register_t rsys_retval[2]; +}; + + +struct spclient { + int spc_fd; + struct lwp *spc_lwp; + + /* incoming */ + struct rsp_hdr spc_hdr; + uint8_t *spc_buf; + size_t spc_off; + +#if 0 + /* outgoing */ + int spc_obusy; + pthread_mutex_t spc_omtx; + pthread_cond_t spc_cv; +#endif +}; + +typedef int (*addrparse_fn)(const char *, struct sockaddr **, int); +typedef int (*connecthook_fn)(int); + +static uint64_t nextreq; + +static int +dosend(struct spclient *spc, const void *data, size_t dlen) +{ + struct pollfd pfd; + const uint8_t *sdata = data; + ssize_t n; + size_t sent; + int fd = spc->spc_fd; + + pfd.fd = fd; + pfd.events = POLLOUT; + + for (sent = 0, n = 0; sent < dlen; ) { + if (n) { + if (poll(&pfd, 1, INFTIM) == -1) { + if (errno == EINTR) + continue; + return errno; + } + } + + n = write(fd, sdata + sent, dlen - sent); + if (n == 0) { + return EFAULT; + } + if (n == -1 && errno != EAGAIN) { + return EFAULT; + } + sent += n; + } + + return 0; +} + +static int +readframe(struct spclient *spc) +{ + int fd = spc->spc_fd; + size_t left; + size_t framelen; + ssize_t n; + + /* still reading header? */ + if (spc->spc_off < HDRSZ) { + DPRINTF(("rump_sp: readframe getting header at offset %zu\n", + spc->spc_off)); + + left = HDRSZ - spc->spc_off; + /*LINTED: cast ok */ + n = read(fd, (uint8_t *)&spc->spc_hdr + spc->spc_off, left); + if (n == 0) { + return -1; + } + if (n == -1) { + if (errno == EAGAIN) + return 0; + return -1; + } + + spc->spc_off += n; + if (spc->spc_off < HDRSZ) + return -1; + + /*LINTED*/ + framelen = spc->spc_hdr.rsp_len; + + if (framelen < HDRSZ) { + return -1; + } else if (framelen == HDRSZ) { + return 1; + } + + spc->spc_buf = malloc(framelen - HDRSZ); + if (spc->spc_buf == NULL) { + return -1; + } + memset(spc->spc_buf, 0, framelen - HDRSZ); + + /* "fallthrough" */ + } else { + /*LINTED*/ + framelen = spc->spc_hdr.rsp_len; + } + + left = framelen - spc->spc_off; + + DPRINTF(("rump_sp: readframe getting body at offset %zu, left %zu\n", + spc->spc_off, left)); + + if (left == 0) + return 1; + n = read(fd, spc->spc_buf + (spc->spc_off - HDRSZ), left); + if (n == 0) { + return -1; + } + if (n == -1) { + if (errno == EAGAIN) + return 0; + return -1; + } + spc->spc_off += n; + left -= n; + + /* got everything? */ + if (left == 0) + return 1; + else + return 0; +} + +static int +tcp_parse(const char *addr, struct sockaddr **sa, int allow_wildcard) +{ + struct sockaddr_in sin; + char buf[64]; + const char *p; + size_t l; + int port; + + memset(&sin, 0, sizeof(sin)); + sin.sin_len = sizeof(sin); + sin.sin_family = AF_INET; + + p = strchr(addr, ':'); + if (!p) { + fprintf(stderr, "rump_sp_tcp: missing port specifier\n"); + return EINVAL; + } + + l = p - addr; + if (l > sizeof(buf)-1) { + fprintf(stderr, "rump_sp_tcp: address too long\n"); + return EINVAL; + } + strncpy(buf, addr, l); + buf[l] = '\0'; + + /* special INADDR_ANY treatment */ + if (strcmp(buf, "*") == 0 || strcmp(buf, "0") == 0) { + sin.sin_addr.s_addr = INADDR_ANY; + } else { + switch (inet_pton(AF_INET, buf, &sin.sin_addr)) { + case 1: + break; + case 0: + fprintf(stderr, "rump_sp_tcp: cannot parse %s\n", buf); + return EINVAL; + case -1: + fprintf(stderr, "rump_sp_tcp: inet_pton failed\n"); + return errno; + default: + assert(/*CONSTCOND*/0); + return EINVAL; + } + } + + if (!allow_wildcard && sin.sin_addr.s_addr == INADDR_ANY) { + fprintf(stderr, "rump_sp_tcp: client needs !INADDR_ANY\n"); + return EINVAL; + } + + /* advance to port number & parse */ + p++; + l = strspn(p, "0123456789"); + if (l == 0) { + fprintf(stderr, "rump_sp_tcp: port now found: %s\n", p); + return EINVAL; + } + strncpy(buf, p, l); + buf[l] = '\0'; + + if (*(p+l) != '/' && *(p+l) != '\0') { + fprintf(stderr, "rump_sp_tcp: junk at end of port: %s\n", addr); + return EINVAL; + } + + port = atoi(buf); + if (port < 0 || port >= (1<<(8*sizeof(in_port_t)))) { + fprintf(stderr, "rump_sp_tcp: port %d out of range\n", port); + return ERANGE; + } + sin.sin_port = htons(port); + + *sa = malloc(sizeof(sin)); + if (*sa == NULL) + return errno; + memcpy(*sa, &sin, sizeof(sin)); + return 0; +} + +static int +tcp_connecthook(int s) +{ + int x; + + x = 1; + setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &x, sizeof(x)); + + return 0; +} + +/*ARGSUSED*/ +static int +notsupp(void) +{ + + fprintf(stderr, "rump_sp: support not yet implemented\n"); + return EOPNOTSUPP; +} + +static int +success(void) +{ + + return 0; +} + +struct { + const char *id; + int domain; + addrparse_fn ap; + connecthook_fn connhook; +} parsetab[] = { + { "tcp", PF_INET, tcp_parse, tcp_connecthook }, + { "unix", PF_LOCAL, (addrparse_fn)notsupp, (connecthook_fn)success }, + { "tcp6", PF_INET6, (addrparse_fn)notsupp, (connecthook_fn)success }, +}; +#define NPARSE (sizeof(parsetab)/sizeof(parsetab[0])) + +static int +parseurl(const char *url, struct sockaddr **sap, unsigned *idxp, + int allow_wildcard) +{ + char id[16]; + const char *p, *p2; + size_t l; + unsigned i; + int error; + + /* + * Parse the url + */ + + p = url; + p2 = strstr(p, "://"); + if (!p2) { + fprintf(stderr, "rump_sp: invalid locator ``%s''\n", p); + return EINVAL; + } + l = p2-p; + if (l > sizeof(id)-1) { + fprintf(stderr, "rump_sp: identifier too long in ``%s''\n", p); + return EINVAL; + } + + strncpy(id, p, l); + id[l] = '\0'; + p2 += 3; /* beginning of address */ + + for (i = 0; i < NPARSE; i++) { + if (strcmp(id, parsetab[i].id) == 0) { + error = parsetab[i].ap(p2, sap, allow_wildcard); + if (error) + return error; + break; + } + } + if (i == NPARSE) { + fprintf(stderr, "rump_sp: invalid identifier ``%s''\n", p); + return EINVAL; + } + + *idxp = i; + return 0; +}