version 1.1, 2010/11/04 21:01:29 |
version 1.5, 2010/11/25 17:59:03 |
|
|
#include <sys/cdefs.h> |
#include <sys/cdefs.h> |
__RCSID("$NetBSD"); |
__RCSID("$NetBSD"); |
|
|
#include <sys/types.h> |
#include <sys/param.h> |
#include <sys/mman.h> |
#include <sys/mman.h> |
#include <sys/socket.h> |
#include <sys/socket.h> |
|
|
Line 58 __RCSID("$NetBSD"); |
|
Line 58 __RCSID("$NetBSD"); |
|
static struct spclient clispc; |
static struct spclient clispc; |
|
|
static int |
static int |
send_syscall_req(struct spclient *spc, int sysnum, |
syscall_req(struct spclient *spc, int sysnum, |
const void *data, size_t dlen) |
const void *data, size_t dlen, void **resp) |
{ |
{ |
struct rsp_hdr rhdr; |
struct rsp_hdr rhdr; |
|
struct respwait rw; |
|
int rv; |
|
|
rhdr.rsp_len = sizeof(rhdr) + dlen; |
rhdr.rsp_len = sizeof(rhdr) + dlen; |
rhdr.rsp_reqno = nextreq++; |
rhdr.rsp_class = RUMPSP_REQ; |
rhdr.rsp_type = RUMPSP_SYSCALL_REQ; |
rhdr.rsp_type = RUMPSP_SYSCALL; |
rhdr.rsp_sysnum = sysnum; |
rhdr.rsp_sysnum = sysnum; |
|
|
dosend(spc, &rhdr, sizeof(rhdr)); |
putwait(spc, &rw, &rhdr); |
dosend(spc, data, dlen); |
rv = dosend(spc, &rhdr, sizeof(rhdr)); |
|
rv = dosend(spc, data, dlen); |
|
if (rv) { |
|
unputwait(spc, &rw); |
|
return rv; |
|
} |
|
|
return 0; |
rv = waitresp(spc, &rw); |
|
*resp = rw.rw_data; |
|
return rv; |
} |
} |
|
|
static int |
static int |
send_copyin_resp(struct spclient *spc, uint64_t reqno, void *data, size_t dlen) |
send_copyin_resp(struct spclient *spc, uint64_t reqno, void *data, size_t dlen, |
|
int wantstr) |
{ |
{ |
struct rsp_hdr rhdr; |
struct rsp_hdr rhdr; |
|
int rv; |
|
|
|
if (wantstr) |
|
dlen = MIN(dlen, strlen(data)+1); |
|
|
rhdr.rsp_len = sizeof(rhdr) + dlen; |
rhdr.rsp_len = sizeof(rhdr) + dlen; |
rhdr.rsp_reqno = reqno; |
rhdr.rsp_reqno = reqno; |
rhdr.rsp_type = RUMPSP_COPYIN_RESP; |
rhdr.rsp_class = RUMPSP_RESP; |
|
rhdr.rsp_type = RUMPSP_COPYIN; |
rhdr.rsp_sysnum = 0; |
rhdr.rsp_sysnum = 0; |
|
|
dosend(spc, &rhdr, sizeof(rhdr)); |
sendlock(spc); |
dosend(spc, data, dlen); |
rv = dosend(spc, &rhdr, sizeof(rhdr)); |
|
rv = dosend(spc, data, dlen); |
|
sendunlock(spc); |
|
|
return 0; |
return rv; |
} |
} |
|
|
static int |
static int |
send_anonmmap_resp(struct spclient *spc, uint64_t reqno, void *addr) |
send_anonmmap_resp(struct spclient *spc, uint64_t reqno, void *addr) |
{ |
{ |
struct rsp_hdr rhdr; |
struct rsp_hdr rhdr; |
|
int rv; |
|
|
rhdr.rsp_len = sizeof(rhdr) + sizeof(addr); |
rhdr.rsp_len = sizeof(rhdr) + sizeof(addr); |
rhdr.rsp_reqno = reqno; |
rhdr.rsp_reqno = reqno; |
rhdr.rsp_type = RUMPSP_ANONMMAP_RESP; |
rhdr.rsp_class = RUMPSP_RESP; |
|
rhdr.rsp_type = RUMPSP_ANONMMAP; |
rhdr.rsp_sysnum = 0; |
rhdr.rsp_sysnum = 0; |
|
|
dosend(spc, &rhdr, sizeof(rhdr)); |
sendlock(spc); |
dosend(spc, &addr, sizeof(addr)); |
rv = dosend(spc, &rhdr, sizeof(rhdr)); |
|
rv = dosend(spc, &addr, sizeof(addr)); |
|
sendunlock(spc); |
|
|
return 0; |
return rv; |
} |
} |
|
|
int |
int |
Line 111 rumpclient_syscall(int sysnum, const voi |
|
Line 132 rumpclient_syscall(int sysnum, const voi |
|
register_t *retval) |
register_t *retval) |
{ |
{ |
struct rsp_sysresp *resp; |
struct rsp_sysresp *resp; |
struct rsp_copydata *copydata; |
void *rdata; |
struct pollfd pfd; |
int rv; |
size_t maplen; |
|
void *mapaddr; |
|
int gotresp; |
|
|
|
DPRINTF(("rump_sp_syscall: executing syscall %d\n", sysnum)); |
DPRINTF(("rumpsp syscall_req: syscall %d with %p/%zu\n", |
|
sysnum, data, dlen)); |
|
|
send_syscall_req(&clispc, sysnum, data, dlen); |
rv = syscall_req(&clispc, sysnum, data, dlen, &rdata); |
|
if (rv) |
|
return rv; |
|
|
|
resp = rdata; |
|
DPRINTF(("rumpsp syscall_resp: syscall %d error %d, rv: %d/%d\n", |
|
sysnum, rv, resp->rsys_retval[0], resp->rsys_retval[1])); |
|
|
DPRINTF(("rump_sp_syscall: syscall %d request sent. " |
memcpy(retval, &resp->rsys_retval, sizeof(resp->rsys_retval)); |
"waiting for response\n", sysnum)); |
rv = resp->rsys_error; |
|
free(rdata); |
|
|
pfd.fd = clispc.spc_fd; |
return rv; |
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*/ |
static void |
resp = (struct rsp_sysresp *)clispc.spc_buf; |
handlereq(struct spclient *spc) |
memcpy(retval, &resp->rsys_retval, sizeof(resp->rsys_retval)); |
{ |
clispc.spc_off = 0; |
struct rsp_copydata *copydata; |
|
void *mapaddr; |
|
size_t maplen; |
|
int reqtype = spc->spc_hdr.rsp_type; |
|
|
return resp->rsys_error; |
switch (reqtype) { |
|
case RUMPSP_COPYIN: |
|
case RUMPSP_COPYINSTR: |
|
/*LINTED*/ |
|
copydata = (struct rsp_copydata *)spc->spc_buf; |
|
DPRINTF(("rump_sp handlereq: copyin request: %p/%zu\n", |
|
copydata->rcp_addr, copydata->rcp_len)); |
|
send_copyin_resp(spc, spc->spc_hdr.rsp_reqno, |
|
copydata->rcp_addr, copydata->rcp_len, |
|
reqtype == RUMPSP_COPYINSTR); |
|
break; |
|
case RUMPSP_COPYOUT: |
|
case RUMPSP_COPYOUTSTR: |
|
/*LINTED*/ |
|
copydata = (struct rsp_copydata *)spc->spc_buf; |
|
DPRINTF(("rump_sp handlereq: copyout request: %p/%zu\n", |
|
copydata->rcp_addr, copydata->rcp_len)); |
|
/*LINTED*/ |
|
memcpy(copydata->rcp_addr, copydata->rcp_data, |
|
copydata->rcp_len); |
|
break; |
|
case RUMPSP_ANONMMAP: |
|
/*LINTED*/ |
|
maplen = *(size_t *)spc->spc_buf; |
|
mapaddr = mmap(NULL, maplen, PROT_READ|PROT_WRITE, |
|
MAP_ANON, -1, 0); |
|
if (mapaddr == MAP_FAILED) |
|
mapaddr = NULL; |
|
DPRINTF(("rump_sp handlereq: anonmmap: %p\n", mapaddr)); |
|
send_anonmmap_resp(spc, spc->spc_hdr.rsp_reqno, mapaddr); |
|
break; |
|
default: |
|
printf("PANIC: INVALID TYPE\n"); |
|
abort(); |
|
break; |
|
} |
|
|
|
free(spc->spc_buf); |
|
spc->spc_off = 0; |
|
spc->spc_buf = NULL; |
} |
} |
|
|
int |
int |
Line 186 rumpclient_init() |
|
Line 211 rumpclient_init() |
|
unsigned idx; |
unsigned idx; |
int error, s; |
int error, s; |
|
|
if ((p = getenv("RUMP_SP_CLIENT")) == NULL) |
if ((p = getenv("RUMP_SP_CLIENT")) == NULL) { |
return ENOENT; |
errno = ENOENT; |
|
return -1; |
|
} |
|
|
if ((error = parseurl(p, &sap, &idx, 0)) != 0) |
if ((error = parseurl(p, &sap, &idx, 0)) != 0) { |
return error; |
errno = error; |
|
return -1; |
|
} |
|
|
s = socket(parsetab[idx].domain, SOCK_STREAM, 0); |
s = socket(parsetab[idx].domain, SOCK_STREAM, 0); |
if (s == -1) |
if (s == -1) |
return errno; |
return -1; |
|
|
if (connect(s, sap, sap->sa_len) == -1) { |
if (connect(s, sap, sap->sa_len) == -1) { |
|
error = errno; |
fprintf(stderr, "rump_sp: client connect failed\n"); |
fprintf(stderr, "rump_sp: client connect failed\n"); |
return errno; |
errno = error; |
|
return -1; |
} |
} |
|
|
if ((error = parsetab[idx].connhook(s)) != 0) { |
if ((error = parsetab[idx].connhook(s)) != 0) { |
|
error = errno; |
fprintf(stderr, "rump_sp: connect hook failed\n"); |
fprintf(stderr, "rump_sp: connect hook failed\n"); |
return error; |
errno = error; |
|
return -1; |
} |
} |
|
|
clispc.spc_fd = s; |
clispc.spc_fd = s; |
|
TAILQ_INIT(&clispc.spc_respwait); |
|
pthread_mutex_init(&clispc.spc_mtx, NULL); |
|
pthread_cond_init(&clispc.spc_cv, NULL); |
|
|
return 0; |
return 0; |
} |
} |