Add sunrpc.
This commit is contained in:
parent
fa256eecfa
commit
551445b92c
16 changed files with 7163 additions and 0 deletions
60
src/libsunrpc/authunix.c
Normal file
60
src/libsunrpc/authunix.c
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <thread.h>
|
||||
#include <sunrpc.h>
|
||||
|
||||
uint
|
||||
sunauthunixsize(SunAuthUnix *x)
|
||||
{
|
||||
return 4 + sunstringsize(x->sysname) + 4 + 4 + 4 + 4*x->ng;
|
||||
}
|
||||
int
|
||||
sunauthunixunpack(uchar *a, uchar *ea, uchar **pa, SunAuthUnix *x)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(sunuint32unpack(a, ea, &a, &x->stamp) < 0) goto Err;
|
||||
if(sunstringunpack(a, ea, &a, &x->sysname, 256) < 0) goto Err;
|
||||
if(sunuint32unpack(a, ea, &a, &x->uid) < 0) goto Err;
|
||||
if(sunuint32unpack(a, ea, &a, &x->gid) < 0) goto Err;
|
||||
if(sunuint32unpack(a, ea, &a, &x->ng) < 0 || x->ng > nelem(x->g)) goto Err;
|
||||
for(i=0; i<x->ng; i++)
|
||||
if(sunuint32unpack(a, ea, &a, &x->g[i]) < 0) goto Err;
|
||||
|
||||
*pa = a;
|
||||
return 0;
|
||||
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
int
|
||||
sunauthunixpack(uchar *a, uchar *ea, uchar **pa, SunAuthUnix *x)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(sunuint32pack(a, ea, &a, &x->stamp) < 0) goto Err;
|
||||
if(sunstringpack(a, ea, &a, &x->sysname, 256) < 0) goto Err;
|
||||
if(sunuint32pack(a, ea, &a, &x->uid) < 0) goto Err;
|
||||
if(sunuint32pack(a, ea, &a, &x->gid) < 0) goto Err;
|
||||
if(sunuint32pack(a, ea, &a, &x->ng) < 0 || x->ng > nelem(x->g)) goto Err;
|
||||
for(i=0; i<x->ng; i++)
|
||||
if(sunuint32pack(a, ea, &a, &x->g[i]) < 0) goto Err;
|
||||
|
||||
*pa = a;
|
||||
return 0;
|
||||
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
void
|
||||
sunauthunixprint(Fmt *fmt, SunAuthUnix *x)
|
||||
{
|
||||
int i;
|
||||
fmtprint(fmt, "unix %.8lux %s %lud %lud (", (ulong)x->stamp,
|
||||
x->sysname, (ulong)x->uid, (ulong)x->gid);
|
||||
for(i=0; i<x->ng; i++)
|
||||
fmtprint(fmt, "%s%lud", i ? " ":"", (ulong)x->g[i]);
|
||||
fmtprint(fmt, ")");
|
||||
}
|
||||
490
src/libsunrpc/client.c
Normal file
490
src/libsunrpc/client.c
Normal file
|
|
@ -0,0 +1,490 @@
|
|||
/*
|
||||
* Sun RPC client.
|
||||
*/
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <thread.h>
|
||||
#include <sunrpc.h>
|
||||
|
||||
typedef struct Out Out;
|
||||
struct Out
|
||||
{
|
||||
char err[ERRMAX]; /* error string */
|
||||
Channel *creply; /* send to finish rpc */
|
||||
uchar *p; /* pending request packet */
|
||||
int n; /* size of request */
|
||||
ulong tag; /* flush tag of pending request */
|
||||
ulong xid; /* xid of pending request */
|
||||
ulong st; /* first send time */
|
||||
ulong t; /* resend time */
|
||||
int nresend; /* number of resends */
|
||||
SunRpc rpc; /* response rpc */
|
||||
};
|
||||
|
||||
static void
|
||||
udpThread(void *v)
|
||||
{
|
||||
uchar *p, *buf;
|
||||
Ioproc *io;
|
||||
int n;
|
||||
SunClient *cli;
|
||||
enum { BufSize = 65536 };
|
||||
|
||||
cli = v;
|
||||
buf = emalloc(BufSize);
|
||||
io = ioproc();
|
||||
p = nil;
|
||||
for(;;){
|
||||
n = ioread(io, cli->fd, buf, BufSize);
|
||||
if(n <= 0)
|
||||
break;
|
||||
p = emalloc(4+n);
|
||||
memmove(p+4, buf, n);
|
||||
p[0] = n>>24;
|
||||
p[1] = n>>16;
|
||||
p[2] = n>>8;
|
||||
p[3] = n;
|
||||
if(sendp(cli->readchan, p) == 0)
|
||||
break;
|
||||
p = nil;
|
||||
}
|
||||
free(p);
|
||||
closeioproc(io);
|
||||
while(send(cli->dying, nil) == -1)
|
||||
;
|
||||
}
|
||||
|
||||
static void
|
||||
netThread(void *v)
|
||||
{
|
||||
uchar *p, buf[4];
|
||||
Ioproc *io;
|
||||
uint n, tot;
|
||||
int done;
|
||||
SunClient *cli;
|
||||
|
||||
cli = v;
|
||||
io = ioproc();
|
||||
tot = 0;
|
||||
p = nil;
|
||||
for(;;){
|
||||
n = ioreadn(io, cli->fd, buf, 4);
|
||||
if(n != 4)
|
||||
break;
|
||||
n = (buf[0]<<24)|(buf[1]<<16)|(buf[2]<<8)|buf[3];
|
||||
if(cli->chatty)
|
||||
fprint(2, "%.8ux...", n);
|
||||
done = n&0x80000000;
|
||||
n &= ~0x80000000;
|
||||
if(tot == 0){
|
||||
p = emalloc(4+n);
|
||||
tot = 4;
|
||||
}else
|
||||
p = erealloc(p, tot+n);
|
||||
if(ioreadn(io, cli->fd, p+tot, n) != n)
|
||||
break;
|
||||
tot += n;
|
||||
if(done){
|
||||
p[0] = tot>>24;
|
||||
p[1] = tot>>16;
|
||||
p[2] = tot>>8;
|
||||
p[3] = tot;
|
||||
if(sendp(cli->readchan, p) == 0)
|
||||
break;
|
||||
p = nil;
|
||||
tot = 0;
|
||||
}
|
||||
}
|
||||
free(p);
|
||||
closeioproc(io);
|
||||
while(send(cli->dying, 0) == -1)
|
||||
;
|
||||
}
|
||||
|
||||
static void
|
||||
timerThread(void *v)
|
||||
{
|
||||
Ioproc *io;
|
||||
SunClient *cli;
|
||||
|
||||
cli = v;
|
||||
io = ioproc();
|
||||
for(;;){
|
||||
if(iosleep(io, 200) < 0)
|
||||
break;
|
||||
if(sendul(cli->timerchan, 0) == 0)
|
||||
break;
|
||||
}
|
||||
closeioproc(io);
|
||||
while(send(cli->dying, 0) == -1)
|
||||
;
|
||||
}
|
||||
|
||||
static ulong
|
||||
msec(void)
|
||||
{
|
||||
return nsec()/1000000;
|
||||
}
|
||||
|
||||
static ulong
|
||||
twait(ulong rtt, int nresend)
|
||||
{
|
||||
ulong t;
|
||||
|
||||
t = rtt;
|
||||
if(nresend <= 1)
|
||||
{}
|
||||
else if(nresend <= 3)
|
||||
t *= 2;
|
||||
else if(nresend <= 18)
|
||||
t <<= nresend-2;
|
||||
else
|
||||
t = 60*1000;
|
||||
if(t > 60*1000)
|
||||
t = 60*1000;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static void
|
||||
rpcMuxThread(void *v)
|
||||
{
|
||||
uchar *buf, *p, *ep;
|
||||
int i, n, nout, mout;
|
||||
ulong t, xidgen, tag;
|
||||
Alt a[5];
|
||||
Out *o, **out;
|
||||
SunRpc rpc;
|
||||
SunClient *cli;
|
||||
|
||||
cli = v;
|
||||
mout = 16;
|
||||
nout = 0;
|
||||
out = emalloc(mout*sizeof(out[0]));
|
||||
xidgen = truerand();
|
||||
|
||||
a[0].op = CHANRCV;
|
||||
a[0].c = cli->rpcchan;
|
||||
a[0].v = &o;
|
||||
a[1].op = CHANNOP;
|
||||
a[1].c = cli->timerchan;
|
||||
a[1].v = nil;
|
||||
a[2].op = CHANRCV;
|
||||
a[2].c = cli->flushchan;
|
||||
a[2].v = &tag;
|
||||
a[3].op = CHANRCV;
|
||||
a[3].c = cli->readchan;
|
||||
a[3].v = &buf;
|
||||
a[4].op = CHANEND;
|
||||
|
||||
for(;;){
|
||||
switch(alt(a)){
|
||||
case 0: /* o = <-rpcchan */
|
||||
if(o == nil)
|
||||
goto Done;
|
||||
cli->nsend++;
|
||||
/* set xid */
|
||||
o->xid = ++xidgen;
|
||||
if(cli->needcount)
|
||||
p = o->p+4;
|
||||
else
|
||||
p = o->p;
|
||||
p[0] = xidgen>>24;
|
||||
p[1] = xidgen>>16;
|
||||
p[2] = xidgen>>8;
|
||||
p[3] = xidgen;
|
||||
if(write(cli->fd, o->p, o->n) != o->n){
|
||||
free(o->p);
|
||||
o->p = nil;
|
||||
snprint(o->err, sizeof o->err, "write: %r");
|
||||
sendp(o->creply, 0);
|
||||
break;
|
||||
}
|
||||
if(nout >= mout){
|
||||
mout *= 2;
|
||||
out = erealloc(out, mout*sizeof(out[0]));
|
||||
}
|
||||
o->st = msec();
|
||||
o->nresend = 0;
|
||||
o->t = o->st + twait(cli->rtt.avg, 0);
|
||||
if(cli->chatty) fprint(2, "send %lux %lud %lud\n", o->xid, o->st, o->t);
|
||||
out[nout++] = o;
|
||||
a[1].op = CHANRCV;
|
||||
break;
|
||||
|
||||
case 1: /* <-timerchan */
|
||||
t = msec();
|
||||
for(i=0; i<nout; i++){
|
||||
o = out[i];
|
||||
if((int)(t - o->t) > 0){
|
||||
if(cli->chatty) fprint(2, "resend %lux %lud %lud\n", o->xid, t, o->t);
|
||||
if(cli->maxwait && t - o->st >= cli->maxwait){
|
||||
free(o->p);
|
||||
o->p = nil;
|
||||
strcpy(o->err, "timeout");
|
||||
sendp(o->creply, 0);
|
||||
out[i--] = out[--nout];
|
||||
continue;
|
||||
}
|
||||
cli->nresend++;
|
||||
o->nresend++;
|
||||
o->t = t + twait(cli->rtt.avg, o->nresend);
|
||||
if(write(cli->fd, o->p, o->n) != o->n){
|
||||
free(o->p);
|
||||
o->p = nil;
|
||||
snprint(o->err, sizeof o->err, "rewrite: %r");
|
||||
sendp(o->creply, 0);
|
||||
out[i--] = out[--nout];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* stop ticking if no work; rpcchan will turn it back on */
|
||||
if(nout == 0)
|
||||
a[1].op = CHANNOP;
|
||||
break;
|
||||
|
||||
case 2: /* tag = <-flushchan */
|
||||
for(i=0; i<nout; i++){
|
||||
o = out[i];
|
||||
if(o->tag == tag){
|
||||
out[i--] = out[--nout];
|
||||
strcpy(o->err, "flushed");
|
||||
free(o->p);
|
||||
o->p = nil;
|
||||
sendp(o->creply, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: /* buf = <-readchan */
|
||||
p = buf;
|
||||
n = (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
|
||||
p += 4;
|
||||
ep = p+n;
|
||||
if(sunrpcunpack(p, ep, &p, &rpc) < 0){
|
||||
fprint(2, "%s: in: %.*H unpack failed\n", argv0, n, buf+4);
|
||||
free(buf);
|
||||
break;
|
||||
}
|
||||
if(cli->chatty)
|
||||
fprint(2, "in: %B\n", &rpc);
|
||||
if(rpc.iscall){
|
||||
fprint(2, "did not get reply\n");
|
||||
free(buf);
|
||||
break;
|
||||
}
|
||||
o = nil;
|
||||
for(i=0; i<nout; i++){
|
||||
o = out[i];
|
||||
if(o->xid == rpc.xid)
|
||||
break;
|
||||
}
|
||||
if(i==nout){
|
||||
if(cli->chatty) fprint(2, "did not find waiting request\n");
|
||||
free(buf);
|
||||
break;
|
||||
}
|
||||
out[i] = out[--nout];
|
||||
free(o->p);
|
||||
o->p = nil;
|
||||
if(rpc.status == SunSuccess){
|
||||
o->p = buf;
|
||||
o->rpc = rpc;
|
||||
}else{
|
||||
o->p = nil;
|
||||
free(buf);
|
||||
sunerrstr(rpc.status);
|
||||
rerrstr(o->err, sizeof o->err);
|
||||
}
|
||||
sendp(o->creply, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Done:
|
||||
free(out);
|
||||
sendp(cli->dying, 0);
|
||||
}
|
||||
|
||||
SunClient*
|
||||
sundial(char *address)
|
||||
{
|
||||
int fd;
|
||||
SunClient *cli;
|
||||
|
||||
if((fd = dial(address, 0, 0, 0)) < 0)
|
||||
return nil;
|
||||
|
||||
cli = emalloc(sizeof(SunClient));
|
||||
cli->fd = fd;
|
||||
cli->maxwait = 15000;
|
||||
cli->rtt.avg = 1000;
|
||||
cli->dying = chancreate(sizeof(void*), 0);
|
||||
cli->rpcchan = chancreate(sizeof(Out*), 0);
|
||||
cli->timerchan = chancreate(sizeof(ulong), 0);
|
||||
cli->flushchan = chancreate(sizeof(ulong), 0);
|
||||
cli->readchan = chancreate(sizeof(uchar*), 0);
|
||||
if(strstr(address, "udp!")){
|
||||
cli->needcount = 0;
|
||||
cli->nettid = threadcreate(udpThread, cli, SunStackSize);
|
||||
cli->timertid = threadcreate(timerThread, cli, SunStackSize);
|
||||
}else{
|
||||
cli->needcount = 1;
|
||||
cli->nettid = threadcreate(netThread, cli, SunStackSize);
|
||||
/* assume reliable: don't need timer */
|
||||
/* BUG: netThread should know how to redial */
|
||||
}
|
||||
threadcreate(rpcMuxThread, cli, SunStackSize);
|
||||
|
||||
return cli;
|
||||
}
|
||||
|
||||
void
|
||||
sunclientclose(SunClient *cli)
|
||||
{
|
||||
int n;
|
||||
|
||||
/*
|
||||
* Threadints get you out of any stuck system calls
|
||||
* or thread rendezvouses, but do nothing if the thread
|
||||
* is in the ready state. Keep interrupting until it takes.
|
||||
*/
|
||||
n = 0;
|
||||
if(!cli->timertid)
|
||||
n++;
|
||||
while(n < 2){
|
||||
threadint(cli->nettid);
|
||||
if(cli->timertid)
|
||||
threadint(cli->timertid);
|
||||
yield();
|
||||
while(nbrecv(cli->dying, nil) == 1)
|
||||
n++;
|
||||
}
|
||||
|
||||
sendp(cli->rpcchan, 0);
|
||||
recvp(cli->dying);
|
||||
|
||||
/* everyone's gone: clean up */
|
||||
close(cli->fd);
|
||||
chanfree(cli->flushchan);
|
||||
chanfree(cli->readchan);
|
||||
chanfree(cli->timerchan);
|
||||
free(cli);
|
||||
}
|
||||
|
||||
void
|
||||
sunclientflushrpc(SunClient *cli, ulong tag)
|
||||
{
|
||||
sendul(cli->flushchan, tag);
|
||||
}
|
||||
|
||||
void
|
||||
sunclientprog(SunClient *cli, SunProg *p)
|
||||
{
|
||||
if(cli->nprog%16 == 0)
|
||||
cli->prog = erealloc(cli->prog, (cli->nprog+16)*sizeof(cli->prog[0]));
|
||||
cli->prog[cli->nprog++] = p;
|
||||
}
|
||||
|
||||
int
|
||||
sunclientrpc(SunClient *cli, ulong tag, SunCall *tx, SunCall *rx, uchar **tofree)
|
||||
{
|
||||
uchar *bp, *p, *ep;
|
||||
int i, n1, n2, n, nn;
|
||||
Out o;
|
||||
SunProg *prog;
|
||||
SunStatus ok;
|
||||
|
||||
for(i=0; i<cli->nprog; i++)
|
||||
if(cli->prog[i]->prog == tx->rpc.prog && cli->prog[i]->vers == tx->rpc.vers)
|
||||
break;
|
||||
if(i==cli->nprog){
|
||||
werrstr("unknown sun rpc program %d version %d", tx->rpc.prog, tx->rpc.vers);
|
||||
return -1;
|
||||
}
|
||||
prog = cli->prog[i];
|
||||
|
||||
if(cli->chatty){
|
||||
fprint(2, "out: %B\n", &tx->rpc);
|
||||
fprint(2, "\t%C\n", tx);
|
||||
}
|
||||
|
||||
n1 = sunrpcsize(&tx->rpc);
|
||||
n2 = suncallsize(prog, tx);
|
||||
|
||||
n = n1+n2;
|
||||
if(cli->needcount)
|
||||
n += 4;
|
||||
|
||||
/*
|
||||
* The dance with 100 is to leave some padding in case
|
||||
* suncallsize is slightly underestimating. If this happens,
|
||||
* the pack will succeed and then we can give a good size
|
||||
* mismatch error below. Otherwise the pack fails with
|
||||
* garbage args, which is less helpful.
|
||||
*/
|
||||
bp = emalloc(n+100);
|
||||
ep = bp+n+100;
|
||||
p = bp;
|
||||
if(cli->needcount){
|
||||
nn = n-4;
|
||||
p[0] = (nn>>24)|0x80;
|
||||
p[1] = nn>>16;
|
||||
p[2] = nn>>8;
|
||||
p[3] = nn;
|
||||
p += 4;
|
||||
}
|
||||
if((ok = sunrpcpack(p, ep, &p, &tx->rpc)) != SunSuccess
|
||||
|| (ok = suncallpack(prog, p, ep, &p, tx)) != SunSuccess){
|
||||
sunerrstr(ok);
|
||||
free(bp);
|
||||
return -1;
|
||||
}
|
||||
ep -= 100;
|
||||
if(p != ep){
|
||||
werrstr("rpc: packet size mismatch %d %ld %ld", n, ep-bp, p-bp);
|
||||
free(bp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&o, 0, sizeof o);
|
||||
o.creply = chancreate(sizeof(void*), 0);
|
||||
o.tag = tag;
|
||||
o.p = bp;
|
||||
o.n = n;
|
||||
|
||||
sendp(cli->rpcchan, &o);
|
||||
recvp(o.creply);
|
||||
chanfree(o.creply);
|
||||
|
||||
if(o.p == nil){
|
||||
werrstr("%s", o.err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
p = o.rpc.data;
|
||||
ep = p+o.rpc.ndata;
|
||||
rx->rpc = o.rpc;
|
||||
rx->rpc.proc = tx->rpc.proc;
|
||||
rx->rpc.prog = tx->rpc.prog;
|
||||
rx->rpc.vers = tx->rpc.vers;
|
||||
rx->type = (rx->rpc.proc<<1)|1;
|
||||
if((ok = suncallunpack(prog, p, ep, &p, rx)) != SunSuccess){
|
||||
sunerrstr(ok);
|
||||
werrstr("unpack: %r");
|
||||
free(o.p);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(cli->chatty){
|
||||
fprint(2, "in: %B\n", &rx->rpc);
|
||||
fprint(2, "in:\t%C\n", rx);
|
||||
}
|
||||
|
||||
if(tofree)
|
||||
*tofree = o.p;
|
||||
else
|
||||
free(o.p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
34
src/libsunrpc/emalloc.c
Normal file
34
src/libsunrpc/emalloc.c
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <thread.h>
|
||||
#include <sunrpc.h>
|
||||
|
||||
void*
|
||||
emalloc(ulong n)
|
||||
{
|
||||
void *v;
|
||||
|
||||
v = mallocz(n, 1);
|
||||
if(v == nil)
|
||||
{
|
||||
abort();
|
||||
sysfatal("out of memory");
|
||||
}
|
||||
setmalloctag(v, getcallerpc(&n));
|
||||
return v;
|
||||
}
|
||||
|
||||
void*
|
||||
erealloc(void *v, ulong n)
|
||||
{
|
||||
v = realloc(v, n);
|
||||
if(v == nil)
|
||||
{
|
||||
abort();
|
||||
sysfatal("out of memory");
|
||||
}
|
||||
setrealloctag(v, getcallerpc(&n));
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
37
src/libsunrpc/error.c
Normal file
37
src/libsunrpc/error.c
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <thread.h>
|
||||
#include <sunrpc.h>
|
||||
|
||||
static struct {
|
||||
SunStatus status;
|
||||
char *msg;
|
||||
} tab[] = {
|
||||
SunProgUnavail, "program unavailable",
|
||||
SunProgMismatch, "program mismatch",
|
||||
SunProcUnavail, "procedure unavailable",
|
||||
SunGarbageArgs, "garbage args",
|
||||
SunSystemErr, "system error",
|
||||
SunRpcMismatch, "rpc mismatch",
|
||||
SunAuthBadCred, "bad auth cred",
|
||||
SunAuthRejectedCred, "rejected auth cred",
|
||||
SunAuthBadVerf, "bad auth verf",
|
||||
SunAuthRejectedVerf, "rejected auth verf",
|
||||
SunAuthTooWeak, "auth too weak",
|
||||
SunAuthInvalidResp, "invalid auth response",
|
||||
SunAuthFailed, "auth failed",
|
||||
};
|
||||
|
||||
void
|
||||
sunerrstr(SunStatus status)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<nelem(tab); i++){
|
||||
if(tab[i].status == status){
|
||||
werrstr(tab[i].msg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
werrstr("unknown sun error %d", (int)status);
|
||||
}
|
||||
107
src/libsunrpc/fd.c
Normal file
107
src/libsunrpc/fd.c
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <thread.h>
|
||||
#include <sunrpc.h>
|
||||
|
||||
enum
|
||||
{
|
||||
MaxRead = 17000,
|
||||
};
|
||||
|
||||
typedef struct SunMsgFd SunMsgFd;
|
||||
struct SunMsgFd
|
||||
{
|
||||
SunMsg msg;
|
||||
int fd;
|
||||
};
|
||||
|
||||
typedef struct Arg Arg;
|
||||
struct Arg
|
||||
{
|
||||
SunSrv *srv;
|
||||
Channel *creply;
|
||||
Channel *csync;
|
||||
int fd;
|
||||
};
|
||||
|
||||
static void
|
||||
sunfdread(void *v)
|
||||
{
|
||||
uint n, tot;
|
||||
int done;
|
||||
uchar buf[4], *p;
|
||||
Arg arg = *(Arg*)v;
|
||||
SunMsgFd *msg;
|
||||
|
||||
sendp(arg.csync, 0);
|
||||
|
||||
p = nil;
|
||||
tot = 0;
|
||||
for(;;){
|
||||
n = readn(arg.fd, buf, 4);
|
||||
if(n != 4)
|
||||
break;
|
||||
n = (buf[0]<<24)|(buf[1]<<16)|(buf[2]<<8)|buf[3];
|
||||
if(arg.srv->chatty) fprint(2, "%.8ux...", n);
|
||||
done = n&0x80000000;
|
||||
n &= ~0x80000000;
|
||||
p = erealloc(p, tot+n);
|
||||
if(readn(arg.fd, p+tot, n) != n)
|
||||
break;
|
||||
tot += n;
|
||||
if(done){
|
||||
msg = emalloc(sizeof(SunMsgFd));
|
||||
msg->msg.data = p;
|
||||
msg->msg.count = tot;
|
||||
msg->msg.creply = arg.creply;
|
||||
sendp(arg.srv->crequest, msg);
|
||||
p = nil;
|
||||
tot = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sunfdwrite(void *v)
|
||||
{
|
||||
uchar buf[4];
|
||||
u32int n;
|
||||
Arg arg = *(Arg*)v;
|
||||
SunMsgFd *msg;
|
||||
|
||||
sendp(arg.csync, 0);
|
||||
|
||||
while((msg = recvp(arg.creply)) != nil){
|
||||
n = msg->msg.count;
|
||||
buf[0] = (n>>24)|0x80;
|
||||
buf[1] = n>>16;
|
||||
buf[2] = n>>8;
|
||||
buf[3] = n;
|
||||
if(write(arg.fd, buf, 4) != 4
|
||||
|| write(arg.fd, msg->msg.data, msg->msg.count) != msg->msg.count)
|
||||
fprint(2, "sunfdwrite: %r\n");
|
||||
free(msg->msg.data);
|
||||
free(msg);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
sunsrvfd(SunSrv *srv, int fd)
|
||||
{
|
||||
Arg *arg;
|
||||
|
||||
arg = emalloc(sizeof(Arg));
|
||||
arg->fd = fd;
|
||||
arg->srv = srv;
|
||||
arg->csync = chancreate(sizeof(void*), 0);
|
||||
arg->creply = chancreate(sizeof(SunMsg*), 10);
|
||||
|
||||
proccreate(sunfdread, arg, SunStackSize);
|
||||
proccreate(sunfdwrite, arg, SunStackSize);
|
||||
recvp(arg->csync);
|
||||
recvp(arg->csync);
|
||||
|
||||
chanfree(arg->csync);
|
||||
free(arg);
|
||||
return 0;
|
||||
}
|
||||
64
src/libsunrpc/fmt.c
Normal file
64
src/libsunrpc/fmt.c
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <thread.h>
|
||||
#include <sunrpc.h>
|
||||
|
||||
/*
|
||||
* print formatters
|
||||
*/
|
||||
int
|
||||
sunrpcfmt(Fmt *f)
|
||||
{
|
||||
SunRpc *rpc;
|
||||
|
||||
rpc = va_arg(f->args, SunRpc*);
|
||||
sunrpcprint(f, rpc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SunProg **fmtProg;
|
||||
static int nfmtProg;
|
||||
static RWLock fmtLock;
|
||||
|
||||
void
|
||||
sunfmtinstall(SunProg *p)
|
||||
{
|
||||
int i;
|
||||
|
||||
wlock(&fmtLock);
|
||||
for(i=0; i<nfmtProg; i++){
|
||||
if(fmtProg[i] == p){
|
||||
wunlock(&fmtLock);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(nfmtProg%16 == 0)
|
||||
fmtProg = erealloc(fmtProg, sizeof(fmtProg[0])*(nfmtProg+16));
|
||||
fmtProg[nfmtProg++] = p;
|
||||
wunlock(&fmtLock);
|
||||
}
|
||||
|
||||
int
|
||||
suncallfmt(Fmt *f)
|
||||
{
|
||||
int i;
|
||||
void (*fmt)(Fmt*, SunCall*);
|
||||
SunCall *c;
|
||||
SunProg *p;
|
||||
|
||||
c = va_arg(f->args, SunCall*);
|
||||
rlock(&fmtLock);
|
||||
for(i=0; i<nfmtProg; i++){
|
||||
p = fmtProg[i];
|
||||
if(p->prog == c->rpc.prog && p->vers == c->rpc.vers){
|
||||
runlock(&fmtLock);
|
||||
if(c->type < 0 || c->type >= p->nproc || (fmt=p->proc[c->type].fmt) == nil)
|
||||
return fmtprint(f, "unknown proc %c%d", "TR"[c->type&1], c->type>>1);
|
||||
(*fmt)(f, c);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
runlock(&fmtLock);
|
||||
fmtprint(f, "<sunrpc %d %d %c%d>", c->rpc.prog, c->rpc.vers, "TR"[c->type&1], c->type>>1);
|
||||
return 0;
|
||||
}
|
||||
31
src/libsunrpc/mkfile
Normal file
31
src/libsunrpc/mkfile
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
PLAN9=../..
|
||||
<$PLAN9/src/mkhdr
|
||||
|
||||
PROTO=\
|
||||
mount3.$O\
|
||||
nfs3.$O\
|
||||
portmap.$O\
|
||||
|
||||
OFILES=\
|
||||
authunix.$O\
|
||||
client.$O\
|
||||
emalloc.$O\
|
||||
error.$O\
|
||||
fd.$O\
|
||||
fmt.$O\
|
||||
net.$O\
|
||||
prog.$O\
|
||||
rpc.$O\
|
||||
server.$O\
|
||||
suncall.$O\
|
||||
udp.$O\
|
||||
$PROTO\
|
||||
|
||||
HFILES=\
|
||||
$PLAN9/include/sunrpc.h\
|
||||
|
||||
LIB=libsunrpc.a
|
||||
|
||||
<$PLAN9/src/mksyslib
|
||||
|
||||
mount3.$O: $PLAN9/include/nfs3.h
|
||||
727
src/libsunrpc/mount3.c
Normal file
727
src/libsunrpc/mount3.c
Normal file
|
|
@ -0,0 +1,727 @@
|
|||
/*
|
||||
* SUN NFSv3 Mounter. See RFC 1813
|
||||
*/
|
||||
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <thread.h>
|
||||
#include <sunrpc.h>
|
||||
#include <nfs3.h>
|
||||
|
||||
void
|
||||
nfsmount3tnullprint(Fmt *fmt, NfsMount3TNull *x)
|
||||
{
|
||||
USED(x);
|
||||
fmtprint(fmt, "%s\n", "NfsMount3TNull");
|
||||
}
|
||||
uint
|
||||
nfsmount3tnullsize(NfsMount3TNull *x)
|
||||
{
|
||||
uint a;
|
||||
USED(x);
|
||||
a = 0;
|
||||
return a;
|
||||
}
|
||||
int
|
||||
nfsmount3tnullpack(uchar *a, uchar *ea, uchar **pa, NfsMount3TNull *x)
|
||||
{
|
||||
USED(ea);
|
||||
USED(x);
|
||||
*pa = a;
|
||||
return 0;
|
||||
}
|
||||
int
|
||||
nfsmount3tnullunpack(uchar *a, uchar *ea, uchar **pa, NfsMount3TNull *x)
|
||||
{
|
||||
USED(ea);
|
||||
USED(x);
|
||||
*pa = a;
|
||||
return 0;
|
||||
}
|
||||
void
|
||||
nfsmount3rnullprint(Fmt *fmt, NfsMount3RNull *x)
|
||||
{
|
||||
USED(x);
|
||||
fmtprint(fmt, "%s\n", "NfsMount3RNull");
|
||||
}
|
||||
uint
|
||||
nfsmount3rnullsize(NfsMount3RNull *x)
|
||||
{
|
||||
uint a;
|
||||
USED(x);
|
||||
a = 0;
|
||||
return a;
|
||||
}
|
||||
int
|
||||
nfsmount3rnullpack(uchar *a, uchar *ea, uchar **pa, NfsMount3RNull *x)
|
||||
{
|
||||
USED(ea);
|
||||
USED(x);
|
||||
*pa = a;
|
||||
return 0;
|
||||
}
|
||||
int
|
||||
nfsmount3rnullunpack(uchar *a, uchar *ea, uchar **pa, NfsMount3RNull *x)
|
||||
{
|
||||
USED(ea);
|
||||
USED(x);
|
||||
*pa = a;
|
||||
return 0;
|
||||
}
|
||||
void
|
||||
nfsmount3tmntprint(Fmt *fmt, NfsMount3TMnt *x)
|
||||
{
|
||||
fmtprint(fmt, "%s\n", "NfsMount3TMnt");
|
||||
fmtprint(fmt, "\t%s=", "path");
|
||||
fmtprint(fmt, "\"%s\"", x->path);
|
||||
fmtprint(fmt, "\n");
|
||||
}
|
||||
uint
|
||||
nfsmount3tmntsize(NfsMount3TMnt *x)
|
||||
{
|
||||
uint a;
|
||||
USED(x);
|
||||
a = 0 + sunstringsize(x->path);
|
||||
return a;
|
||||
}
|
||||
int
|
||||
nfsmount3tmntpack(uchar *a, uchar *ea, uchar **pa, NfsMount3TMnt *x)
|
||||
{
|
||||
if(sunstringpack(a, ea, &a, &x->path, 1024) < 0) goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
int
|
||||
nfsmount3tmntunpack(uchar *a, uchar *ea, uchar **pa, NfsMount3TMnt *x)
|
||||
{
|
||||
if(sunstringunpack(a, ea, &a, &x->path, 1024) < 0) goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
void
|
||||
nfsmount3rmntprint(Fmt *fmt, NfsMount3RMnt *x)
|
||||
{
|
||||
fmtprint(fmt, "%s\n", "NfsMount3RMnt");
|
||||
fmtprint(fmt, "\t%s=", "status");
|
||||
fmtprint(fmt, "%ud", x->status);
|
||||
fmtprint(fmt, "\n");
|
||||
switch(x->status){
|
||||
case 0:
|
||||
fmtprint(fmt, "\t%s=", "handle");
|
||||
fmtprint(fmt, "%.*H", x->len, x->handle);
|
||||
fmtprint(fmt, "\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
uint
|
||||
nfsmount3rmntsize(NfsMount3RMnt *x)
|
||||
{
|
||||
uint a;
|
||||
USED(x);
|
||||
a = 0 + 4;
|
||||
switch(x->status){
|
||||
case 0:
|
||||
a = a + sunvaropaquesize(x->len);
|
||||
a = a + 4 + 4 * x->nauth;
|
||||
break;
|
||||
}
|
||||
a = a;
|
||||
return a;
|
||||
}
|
||||
uint
|
||||
nfsmount1rmntsize(NfsMount3RMnt *x)
|
||||
{
|
||||
uint a;
|
||||
USED(x);
|
||||
a = 0 + 4;
|
||||
switch(x->status){
|
||||
case 0:
|
||||
a = a + NfsMount1HandleSize;
|
||||
break;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
int
|
||||
nfsmount3rmntpack(uchar *a, uchar *ea, uchar **pa, NfsMount3RMnt *x)
|
||||
{
|
||||
int i;
|
||||
if(sunuint32pack(a, ea, &a, &x->status) < 0) goto Err;
|
||||
switch(x->status){
|
||||
case 0:
|
||||
if(sunvaropaquepack(a, ea, &a, &x->handle, &x->len, NfsMount3MaxHandleSize) < 0) goto Err;
|
||||
if(sunuint32pack(a, ea, &a, &x->nauth) < 0) goto Err;
|
||||
for(i=0; i<x->nauth; i++)
|
||||
if(sunuint32pack(a, ea, &a, &x->auth[i]) < 0) goto Err;
|
||||
break;
|
||||
}
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
int
|
||||
nfsmount1rmntpack(uchar *a, uchar *ea, uchar **pa, NfsMount3RMnt *x)
|
||||
{
|
||||
if(sunuint32pack(a, ea, &a, &x->status) < 0) goto Err;
|
||||
switch(x->status){
|
||||
case 0:
|
||||
if(x->len != NfsMount1HandleSize)
|
||||
goto Err;
|
||||
if(sunfixedopaquepack(a, ea, &a, x->handle, NfsMount1HandleSize) < 0) goto Err;
|
||||
if(x->nauth != 0)
|
||||
goto Err;
|
||||
break;
|
||||
}
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
int
|
||||
nfsmount1rmntunpack(uchar *a, uchar *ea, uchar **pa, NfsMount3RMnt *x)
|
||||
{
|
||||
if(sunuint32unpack(a, ea, &a, &x->status) < 0) goto Err;
|
||||
switch(x->status){
|
||||
case 0:
|
||||
x->len = NfsMount1HandleSize;
|
||||
x->nauth = 0;
|
||||
x->auth = 0;
|
||||
if(sunfixedopaqueunpack(a, ea, &a, x->handle, NfsMount1HandleSize) < 0) goto Err;
|
||||
if(x->nauth != 0)
|
||||
goto Err;
|
||||
break;
|
||||
}
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
nfsmount3rmntunpack(uchar *a, uchar *ea, uchar **pa, NfsMount3RMnt *x)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(sunuint32unpack(a, ea, &a, &x->status) < 0) goto Err;
|
||||
switch(x->status){
|
||||
case 0:
|
||||
if(sunvaropaqueunpack(a, ea, &a, &x->handle, &x->len, NfsMount3MaxHandleSize) < 0) goto Err;
|
||||
if(sunuint32unpack(a, ea, &a, &x->nauth) < 0) goto Err;
|
||||
x->auth = (u32int*)a;
|
||||
for(i=0; i<x->nauth; i++)
|
||||
if(sunuint32unpack(a, ea, &a, &x->auth[i]) < 0) goto Err;
|
||||
break;
|
||||
}
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
void
|
||||
nfsmount3tdumpprint(Fmt *fmt, NfsMount3TDump *x)
|
||||
{
|
||||
USED(x);
|
||||
fmtprint(fmt, "%s\n", "NfsMount3TDump");
|
||||
}
|
||||
uint
|
||||
nfsmount3tdumpsize(NfsMount3TDump *x)
|
||||
{
|
||||
uint a;
|
||||
USED(x);
|
||||
a = 0;
|
||||
return a;
|
||||
}
|
||||
int
|
||||
nfsmount3tdumppack(uchar *a, uchar *ea, uchar **pa, NfsMount3TDump *x)
|
||||
{
|
||||
USED(ea);
|
||||
USED(x);
|
||||
*pa = a;
|
||||
return 0;
|
||||
}
|
||||
int
|
||||
nfsmount3tdumpunpack(uchar *a, uchar *ea, uchar **pa, NfsMount3TDump *x)
|
||||
{
|
||||
USED(ea);
|
||||
USED(x);
|
||||
*pa = a;
|
||||
return 0;
|
||||
}
|
||||
void
|
||||
nfsmount3entryprint(Fmt *fmt, NfsMount3Entry *x)
|
||||
{
|
||||
fmtprint(fmt, "%s\n", "NfsMount3Entry");
|
||||
fmtprint(fmt, "\t%s=", "host");
|
||||
fmtprint(fmt, "\"%s\"", x->host);
|
||||
fmtprint(fmt, "\n");
|
||||
fmtprint(fmt, "\t%s=", "path");
|
||||
fmtprint(fmt, "\"%s\"", x->path);
|
||||
fmtprint(fmt, "\n");
|
||||
}
|
||||
uint
|
||||
nfsmount3entrysize(NfsMount3Entry *x)
|
||||
{
|
||||
uint a;
|
||||
USED(x);
|
||||
a = 0 + sunstringsize(x->host) + sunstringsize(x->path);
|
||||
return a;
|
||||
}
|
||||
int
|
||||
nfsmount3entrypack(uchar *a, uchar *ea, uchar **pa, NfsMount3Entry *x)
|
||||
{
|
||||
u1int one;
|
||||
|
||||
one = 1;
|
||||
if(sunuint1pack(a, ea, &a, &one) < 0) goto Err;
|
||||
if(sunstringpack(a, ea, &a, &x->host, 255) < 0) goto Err;
|
||||
if(sunstringpack(a, ea, &a, &x->path, 1024) < 0) goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
int
|
||||
nfsmount3entryunpack(uchar *a, uchar *ea, uchar **pa, NfsMount3Entry *x)
|
||||
{
|
||||
u1int one;
|
||||
|
||||
if(sunuint1unpack(a, ea, &a, &one) < 0 || one != 1) goto Err;
|
||||
if(sunstringunpack(a, ea, &a, &x->host, NfsMount3MaxNameSize) < 0) goto Err;
|
||||
if(sunstringunpack(a, ea, &a, &x->path, NfsMount3MaxPathSize) < 0) goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
void
|
||||
nfsmount3rdumpprint(Fmt *fmt, NfsMount3RDump *x)
|
||||
{
|
||||
USED(x);
|
||||
fmtprint(fmt, "%s\n", "NfsMount3RDump");
|
||||
}
|
||||
uint
|
||||
nfsmount3rdumpsize(NfsMount3RDump *x)
|
||||
{
|
||||
uint a;
|
||||
USED(x);
|
||||
a = 0;
|
||||
a += x->count;
|
||||
a += 4;
|
||||
return a;
|
||||
}
|
||||
int
|
||||
nfsmount3rdumppack(uchar *a, uchar *ea, uchar **pa, NfsMount3RDump *x)
|
||||
{
|
||||
u1int zero;
|
||||
|
||||
zero = 0;
|
||||
if(a+x->count > ea) goto Err;
|
||||
memmove(a, x->data, x->count);
|
||||
a += x->count;
|
||||
if(sunuint1pack(a, ea, &a, &zero) < 0)
|
||||
goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
int
|
||||
nfsmount3rdumpunpack(uchar *a, uchar *ea, uchar **pa, NfsMount3RDump *x)
|
||||
{
|
||||
int i;
|
||||
uchar *oa;
|
||||
u1int u1;
|
||||
u32int u32;
|
||||
|
||||
oa = a;
|
||||
for(i=0;; i++){
|
||||
if(sunuint1unpack(a, ea, &a, &u1) < 0)
|
||||
goto Err;
|
||||
if(u1 == 0)
|
||||
break;
|
||||
if(sunuint32unpack(a, ea, &a, &u32) < 0
|
||||
|| u32 > NfsMount3MaxNameSize
|
||||
|| (a+=u32) >= ea
|
||||
|| sunuint32unpack(a, ea, &a, &u32) < 0
|
||||
|| u32 > NfsMount3MaxPathSize
|
||||
|| (a+=u32) >= ea)
|
||||
goto Err;
|
||||
}
|
||||
x->count = (a-4) - oa;
|
||||
x->data = oa;
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
void
|
||||
nfsmount3tumntprint(Fmt *fmt, NfsMount3TUmnt *x)
|
||||
{
|
||||
fmtprint(fmt, "%s\n", "NfsMount3TUmnt");
|
||||
fmtprint(fmt, "\t%s=", "path");
|
||||
fmtprint(fmt, "\"%s\"", x->path);
|
||||
fmtprint(fmt, "\n");
|
||||
}
|
||||
uint
|
||||
nfsmount3tumntsize(NfsMount3TUmnt *x)
|
||||
{
|
||||
uint a;
|
||||
USED(x);
|
||||
a = 0 + sunstringsize(x->path);
|
||||
return a;
|
||||
}
|
||||
int
|
||||
nfsmount3tumntpack(uchar *a, uchar *ea, uchar **pa, NfsMount3TUmnt *x)
|
||||
{
|
||||
if(sunstringpack(a, ea, &a, &x->path, 1024) < 0) goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
int
|
||||
nfsmount3tumntunpack(uchar *a, uchar *ea, uchar **pa, NfsMount3TUmnt *x)
|
||||
{
|
||||
if(sunstringunpack(a, ea, &a, &x->path, 1024) < 0) goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
void
|
||||
nfsmount3rumntprint(Fmt *fmt, NfsMount3RUmnt *x)
|
||||
{
|
||||
USED(x);
|
||||
fmtprint(fmt, "%s\n", "NfsMount3RUmnt");
|
||||
}
|
||||
uint
|
||||
nfsmount3rumntsize(NfsMount3RUmnt *x)
|
||||
{
|
||||
uint a;
|
||||
USED(x);
|
||||
a = 0;
|
||||
return a;
|
||||
}
|
||||
int
|
||||
nfsmount3rumntpack(uchar *a, uchar *ea, uchar **pa, NfsMount3RUmnt *x)
|
||||
{
|
||||
USED(ea);
|
||||
USED(x);
|
||||
*pa = a;
|
||||
return 0;
|
||||
}
|
||||
int
|
||||
nfsmount3rumntunpack(uchar *a, uchar *ea, uchar **pa, NfsMount3RUmnt *x)
|
||||
{
|
||||
USED(ea);
|
||||
USED(x);
|
||||
*pa = a;
|
||||
return 0;
|
||||
}
|
||||
void
|
||||
nfsmount3tumntallprint(Fmt *fmt, NfsMount3TUmntall *x)
|
||||
{
|
||||
USED(x);
|
||||
fmtprint(fmt, "%s\n", "NfsMount3TUmntall");
|
||||
}
|
||||
uint
|
||||
nfsmount3tumntallsize(NfsMount3TUmntall *x)
|
||||
{
|
||||
uint a;
|
||||
USED(x);
|
||||
a = 0;
|
||||
return a;
|
||||
}
|
||||
int
|
||||
nfsmount3tumntallpack(uchar *a, uchar *ea, uchar **pa, NfsMount3TUmntall *x)
|
||||
{
|
||||
USED(ea);
|
||||
USED(x);
|
||||
*pa = a;
|
||||
return 0;
|
||||
}
|
||||
int
|
||||
nfsmount3tumntallunpack(uchar *a, uchar *ea, uchar **pa, NfsMount3TUmntall *x)
|
||||
{
|
||||
USED(ea);
|
||||
USED(x);
|
||||
*pa = a;
|
||||
return 0;
|
||||
}
|
||||
void
|
||||
nfsmount3rumntallprint(Fmt *fmt, NfsMount3RUmntall *x)
|
||||
{
|
||||
USED(x);
|
||||
fmtprint(fmt, "%s\n", "NfsMount3RUmntall");
|
||||
}
|
||||
uint
|
||||
nfsmount3rumntallsize(NfsMount3RUmntall *x)
|
||||
{
|
||||
uint a;
|
||||
USED(x);
|
||||
a = 0;
|
||||
return a;
|
||||
}
|
||||
int
|
||||
nfsmount3rumntallpack(uchar *a, uchar *ea, uchar **pa, NfsMount3RUmntall *x)
|
||||
{
|
||||
USED(ea);
|
||||
USED(x);
|
||||
*pa = a;
|
||||
return 0;
|
||||
}
|
||||
int
|
||||
nfsmount3rumntallunpack(uchar *a, uchar *ea, uchar **pa, NfsMount3RUmntall *x)
|
||||
{
|
||||
USED(ea);
|
||||
USED(x);
|
||||
*pa = a;
|
||||
return 0;
|
||||
}
|
||||
void
|
||||
nfsmount3texportprint(Fmt *fmt, NfsMount3TExport *x)
|
||||
{
|
||||
USED(x);
|
||||
fmtprint(fmt, "%s\n", "NfsMount3TExport");
|
||||
}
|
||||
uint
|
||||
nfsmount3texportsize(NfsMount3TExport *x)
|
||||
{
|
||||
uint a;
|
||||
USED(x);
|
||||
a = 0;
|
||||
return a;
|
||||
}
|
||||
int
|
||||
nfsmount3texportpack(uchar *a, uchar *ea, uchar **pa, NfsMount3TExport *x)
|
||||
{
|
||||
USED(ea);
|
||||
USED(x);
|
||||
*pa = a;
|
||||
return 0;
|
||||
}
|
||||
int
|
||||
nfsmount3texportunpack(uchar *a, uchar *ea, uchar **pa, NfsMount3TExport *x)
|
||||
{
|
||||
USED(ea);
|
||||
USED(x);
|
||||
*pa = a;
|
||||
return 0;
|
||||
}
|
||||
void
|
||||
nfsmount3rexportprint(Fmt *fmt, NfsMount3RExport *x)
|
||||
{
|
||||
USED(x);
|
||||
fmtprint(fmt, "%s\n", "NfsMount3RExport");
|
||||
fmtprint(fmt, "\n");
|
||||
}
|
||||
uint
|
||||
nfsmount3rexportsize(NfsMount3RExport *x)
|
||||
{
|
||||
uint a;
|
||||
USED(x);
|
||||
a = 0;
|
||||
a += x->count;
|
||||
a += 4; /* end of export list */
|
||||
return a;
|
||||
}
|
||||
int
|
||||
nfsmount3rexportpack(uchar *a, uchar *ea, uchar **pa, NfsMount3RExport *x)
|
||||
{
|
||||
u1int zero;
|
||||
|
||||
zero = 0;
|
||||
if(a+x->count > ea) goto Err;
|
||||
memmove(a, x->data, x->count);
|
||||
a += x->count;
|
||||
if(sunuint1pack(a, ea, &a, &zero) < 0)
|
||||
goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
int
|
||||
nfsmount3rexportunpack(uchar *a, uchar *ea, uchar **pa, NfsMount3RExport *x)
|
||||
{
|
||||
int ng, ne;
|
||||
uchar *oa;
|
||||
u1int u1;
|
||||
u32int u32;
|
||||
|
||||
oa = a;
|
||||
ng = 0;
|
||||
for(ne=0;; ne++){
|
||||
if(sunuint1unpack(a, ea, &a, &u1) < 0)
|
||||
goto Err;
|
||||
if(u1 == 0)
|
||||
break;
|
||||
if(sunuint32unpack(a, ea, &a, &u32) < 0
|
||||
|| (a += (u32+3)&~3) >= ea)
|
||||
goto Err;
|
||||
for(;; ng++){
|
||||
if(sunuint1unpack(a, ea, &a, &u1) < 0)
|
||||
goto Err;
|
||||
if(u1 == 0)
|
||||
break;
|
||||
if(sunuint32unpack(a, ea, &a, &u32) < 0
|
||||
|| (a += (u32+3)&~3) >= ea)
|
||||
goto Err;
|
||||
}
|
||||
}
|
||||
x->data = oa;
|
||||
x->count = (a-4) - oa;
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
uint
|
||||
nfsmount3exportgroupsize(uchar *a)
|
||||
{
|
||||
int ng;
|
||||
u1int have;
|
||||
u32int n;
|
||||
|
||||
a += 4;
|
||||
sunuint32unpack(a, a+4, &a, &n);
|
||||
a += (n+3)&~3;
|
||||
ng = 0;
|
||||
for(;;){
|
||||
sunuint1unpack(a, a+4, &a, &have);
|
||||
if(have == 0)
|
||||
break;
|
||||
ng++;
|
||||
sunuint32unpack(a, a+4, &a, &n);
|
||||
a += (n+3)&~3;
|
||||
}
|
||||
return ng;
|
||||
}
|
||||
int
|
||||
nfsmount3exportunpack(uchar *a, uchar *ea, uchar **pa, char **gp, char ***pgp, NfsMount3Export *x)
|
||||
{
|
||||
int ng;
|
||||
u1int u1;
|
||||
|
||||
if(sunuint1unpack(a, ea, &a, &u1) < 0 || u1 != 1) goto Err;
|
||||
if(sunstringunpack(a, ea, &a, &x->path, NfsMount3MaxPathSize) < 0) goto Err;
|
||||
x->g = gp;
|
||||
ng = 0;
|
||||
for(;;){
|
||||
if(sunuint1unpack(a, ea, &a, &u1) < 0) goto Err;
|
||||
if(u1 == 0)
|
||||
break;
|
||||
if(sunstringunpack(a, ea, &a, &gp[ng++], NfsMount3MaxNameSize) < 0) goto Err;
|
||||
}
|
||||
x->ng = ng;
|
||||
*pgp = gp+ng;
|
||||
*pa = a;
|
||||
return 0;
|
||||
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
uint
|
||||
nfsmount3exportsize(NfsMount3Export *x)
|
||||
{
|
||||
int i;
|
||||
uint a;
|
||||
|
||||
a = 4 + sunstringsize(x->path);
|
||||
for(i=0; i<x->ng; i++)
|
||||
a += 4 + sunstringsize(x->g[i]);
|
||||
a += 4;
|
||||
return a;
|
||||
}
|
||||
int
|
||||
nfsmount3exportpack(uchar *a, uchar *ea, uchar **pa, NfsMount3Export *x)
|
||||
{
|
||||
int i;
|
||||
u1int u1;
|
||||
|
||||
u1 = 1;
|
||||
if(sunuint1pack(a, ea, &a, &u1) < 0) goto Err;
|
||||
if(sunstringpack(a, ea, &a, &x->path, NfsMount3MaxPathSize) < 0) goto Err;
|
||||
for(i=0; i<x->ng; i++){
|
||||
if(sunuint1pack(a, ea, &a, &u1) < 0) goto Err;
|
||||
if(sunstringpack(a, ea, &a, &x->g[i], NfsMount3MaxNameSize) < 0) goto Err;
|
||||
}
|
||||
u1 = 0;
|
||||
if(sunuint1pack(a, ea, &a, &u1) < 0) goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
|
||||
typedef int (*P)(uchar*, uchar*, uchar**, SunCall*);
|
||||
typedef void (*F)(Fmt*, SunCall*);
|
||||
typedef uint (*S)(SunCall*);
|
||||
|
||||
static SunProc proc3[] = {
|
||||
(P)nfsmount3tnullpack, (P)nfsmount3tnullunpack, (S)nfsmount3tnullsize, (F)nfsmount3tnullprint, sizeof(NfsMount3TNull),
|
||||
(P)nfsmount3rnullpack, (P)nfsmount3rnullunpack, (S)nfsmount3rnullsize, (F)nfsmount3rnullprint, sizeof(NfsMount3RNull),
|
||||
(P)nfsmount3tmntpack, (P)nfsmount3tmntunpack, (S)nfsmount3tmntsize, (F)nfsmount3tmntprint, sizeof(NfsMount3TMnt),
|
||||
(P)nfsmount3rmntpack, (P)nfsmount3rmntunpack, (S)nfsmount3rmntsize, (F)nfsmount3rmntprint, sizeof(NfsMount3RMnt),
|
||||
(P)nfsmount3tdumppack, (P)nfsmount3tdumpunpack, (S)nfsmount3tdumpsize, (F)nfsmount3tdumpprint, sizeof(NfsMount3TDump),
|
||||
(P)nfsmount3rdumppack, (P)nfsmount3rdumpunpack, (S)nfsmount3rdumpsize, (F)nfsmount3rdumpprint, sizeof(NfsMount3RDump),
|
||||
(P)nfsmount3tumntpack, (P)nfsmount3tumntunpack, (S)nfsmount3tumntsize, (F)nfsmount3tumntprint, sizeof(NfsMount3TUmnt),
|
||||
(P)nfsmount3rumntpack, (P)nfsmount3rumntunpack, (S)nfsmount3rumntsize, (F)nfsmount3rumntprint, sizeof(NfsMount3RUmnt),
|
||||
(P)nfsmount3tumntallpack, (P)nfsmount3tumntallunpack, (S)nfsmount3tumntallsize, (F)nfsmount3tumntallprint, sizeof(NfsMount3TUmntall),
|
||||
(P)nfsmount3rumntallpack, (P)nfsmount3rumntallunpack, (S)nfsmount3rumntallsize, (F)nfsmount3rumntallprint, sizeof(NfsMount3RUmntall),
|
||||
(P)nfsmount3texportpack, (P)nfsmount3texportunpack, (S)nfsmount3texportsize, (F)nfsmount3texportprint, sizeof(NfsMount3TExport),
|
||||
(P)nfsmount3rexportpack, (P)nfsmount3rexportunpack, (S)nfsmount3rexportsize, (F)nfsmount3rexportprint, sizeof(NfsMount3RExport),
|
||||
};
|
||||
|
||||
static SunProc proc1[] = {
|
||||
(P)nfsmount3tnullpack, (P)nfsmount3tnullunpack, (S)nfsmount3tnullsize, (F)nfsmount3tnullprint, sizeof(NfsMount3TNull),
|
||||
(P)nfsmount3rnullpack, (P)nfsmount3rnullunpack, (S)nfsmount3rnullsize, (F)nfsmount3rnullprint, sizeof(NfsMount3RNull),
|
||||
(P)nfsmount3tmntpack, (P)nfsmount3tmntunpack, (S)nfsmount3tmntsize, (F)nfsmount3tmntprint, sizeof(NfsMount3TMnt),
|
||||
(P)nfsmount1rmntpack, (P)nfsmount1rmntunpack, (S)nfsmount1rmntsize, (F)nfsmount3rmntprint, sizeof(NfsMount3RMnt),
|
||||
(P)nfsmount3tdumppack, (P)nfsmount3tdumpunpack, (S)nfsmount3tdumpsize, (F)nfsmount3tdumpprint, sizeof(NfsMount3TDump),
|
||||
(P)nfsmount3rdumppack, (P)nfsmount3rdumpunpack, (S)nfsmount3rdumpsize, (F)nfsmount3rdumpprint, sizeof(NfsMount3RDump),
|
||||
(P)nfsmount3tumntpack, (P)nfsmount3tumntunpack, (S)nfsmount3tumntsize, (F)nfsmount3tumntprint, sizeof(NfsMount3TUmnt),
|
||||
(P)nfsmount3rumntpack, (P)nfsmount3rumntunpack, (S)nfsmount3rumntsize, (F)nfsmount3rumntprint, sizeof(NfsMount3RUmnt),
|
||||
(P)nfsmount3tumntallpack, (P)nfsmount3tumntallunpack, (S)nfsmount3tumntallsize, (F)nfsmount3tumntallprint, sizeof(NfsMount3TUmntall),
|
||||
(P)nfsmount3rumntallpack, (P)nfsmount3rumntallunpack, (S)nfsmount3rumntallsize, (F)nfsmount3rumntallprint, sizeof(NfsMount3RUmntall),
|
||||
(P)nfsmount3texportpack, (P)nfsmount3texportunpack, (S)nfsmount3texportsize, (F)nfsmount3texportprint, sizeof(NfsMount3TExport),
|
||||
(P)nfsmount3rexportpack, (P)nfsmount3rexportunpack, (S)nfsmount3rexportsize, (F)nfsmount3rexportprint, sizeof(NfsMount3RExport),
|
||||
};
|
||||
|
||||
SunProg nfsmount3prog =
|
||||
{
|
||||
NfsMount3Program,
|
||||
NfsMount3Version,
|
||||
proc3,
|
||||
nelem(proc3),
|
||||
};
|
||||
|
||||
SunProg nfsmount1prog =
|
||||
{
|
||||
NfsMount1Program,
|
||||
NfsMount1Version,
|
||||
proc1,
|
||||
nelem(proc1),
|
||||
};
|
||||
57
src/libsunrpc/net.c
Normal file
57
src/libsunrpc/net.c
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <thread.h>
|
||||
#include <sunrpc.h>
|
||||
|
||||
typedef struct Arg Arg;
|
||||
struct Arg
|
||||
{
|
||||
int fd;
|
||||
char adir[40];
|
||||
SunSrv *srv;
|
||||
};
|
||||
|
||||
static void
|
||||
sunnetlisten(void *v)
|
||||
{
|
||||
int fd, lcfd;
|
||||
char ldir[40];
|
||||
Arg *a = v;
|
||||
|
||||
for(;;){
|
||||
lcfd = listen(a->adir, ldir);
|
||||
if(lcfd < 0)
|
||||
break;
|
||||
fd = accept(lcfd, ldir);
|
||||
close(lcfd);
|
||||
if(fd < 0)
|
||||
continue;
|
||||
if(!sunsrvfd(a->srv, fd))
|
||||
close(fd);
|
||||
}
|
||||
free(a);
|
||||
close(a->fd);
|
||||
}
|
||||
|
||||
int
|
||||
sunsrvnet(SunSrv *srv, char *addr)
|
||||
{
|
||||
Arg *a;
|
||||
|
||||
a = emalloc(sizeof(Arg));
|
||||
if((a->fd = announce(addr, a->adir)) < 0)
|
||||
return -1;
|
||||
a->srv = srv;
|
||||
|
||||
proccreate(sunnetlisten, a, SunStackSize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sunsrvannounce(SunSrv *srv, char *addr)
|
||||
{
|
||||
if(strstr(addr, "udp!"))
|
||||
return sunsrvudp(srv, addr);
|
||||
else
|
||||
return sunsrvnet(srv, addr);
|
||||
}
|
||||
4045
src/libsunrpc/nfs3.c
Normal file
4045
src/libsunrpc/nfs3.c
Normal file
File diff suppressed because it is too large
Load diff
498
src/libsunrpc/portmap.c
Normal file
498
src/libsunrpc/portmap.c
Normal file
|
|
@ -0,0 +1,498 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <thread.h>
|
||||
#include <sunrpc.h>
|
||||
|
||||
static void
|
||||
portMapPrint(Fmt *fmt, PortMap *x)
|
||||
{
|
||||
fmtprint(fmt, "[%ud %ud %ud %ud]", x->prog, x->vers, x->prot, x->port);
|
||||
}
|
||||
static uint
|
||||
portMapSize(PortMap *x)
|
||||
{
|
||||
uint a;
|
||||
USED(x);
|
||||
a = 0 + 4 + 4 + 4 + 4;
|
||||
return a;
|
||||
}
|
||||
static int
|
||||
portMapPack(uchar *a, uchar *ea, uchar **pa, PortMap *x)
|
||||
{
|
||||
if(sunuint32pack(a, ea, &a, &x->prog) < 0) goto Err;
|
||||
if(sunuint32pack(a, ea, &a, &x->vers) < 0) goto Err;
|
||||
if(sunuint32pack(a, ea, &a, &x->prot) < 0) goto Err;
|
||||
if(sunuint32pack(a, ea, &a, &x->port) < 0) goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
static int
|
||||
portMapUnpack(uchar *a, uchar *ea, uchar **pa, PortMap *x)
|
||||
{
|
||||
if(sunuint32unpack(a, ea, &a, &x->prog) < 0) goto Err;
|
||||
if(sunuint32unpack(a, ea, &a, &x->vers) < 0) goto Err;
|
||||
if(sunuint32unpack(a, ea, &a, &x->prot) < 0) goto Err;
|
||||
if(sunuint32unpack(a, ea, &a, &x->port) < 0) goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
static void
|
||||
portTNullPrint(Fmt *fmt, PortTNull *x)
|
||||
{
|
||||
USED(x);
|
||||
fmtprint(fmt, "%s", "PortTNull");
|
||||
}
|
||||
static uint
|
||||
portTNullSize(PortTNull *x)
|
||||
{
|
||||
uint a;
|
||||
USED(x);
|
||||
a = 0;
|
||||
return a;
|
||||
}
|
||||
static int
|
||||
portTNullPack(uchar *a, uchar *ea, uchar **pa, PortTNull *x)
|
||||
{
|
||||
USED(ea);
|
||||
USED(x);
|
||||
*pa = a;
|
||||
return 0;
|
||||
}
|
||||
static int
|
||||
portTNullUnpack(uchar *a, uchar *ea, uchar **pa, PortTNull *x)
|
||||
{
|
||||
USED(ea);
|
||||
USED(x);
|
||||
*pa = a;
|
||||
return 0;
|
||||
}
|
||||
static void
|
||||
portRNullPrint(Fmt *fmt, PortRNull *x)
|
||||
{
|
||||
USED(x);
|
||||
fmtprint(fmt, "%s", "PortRNull");
|
||||
}
|
||||
static uint
|
||||
portRNullSize(PortRNull *x)
|
||||
{
|
||||
uint a;
|
||||
USED(x);
|
||||
a = 0;
|
||||
return a;
|
||||
}
|
||||
static int
|
||||
portRNullPack(uchar *a, uchar *ea, uchar **pa, PortRNull *x)
|
||||
{
|
||||
USED(ea);
|
||||
USED(x);
|
||||
*pa = a;
|
||||
return 0;
|
||||
}
|
||||
static int
|
||||
portRNullUnpack(uchar *a, uchar *ea, uchar **pa, PortRNull *x)
|
||||
{
|
||||
USED(ea);
|
||||
USED(x);
|
||||
*pa = a;
|
||||
return 0;
|
||||
}
|
||||
static void
|
||||
portTSetPrint(Fmt *fmt, PortTSet *x)
|
||||
{
|
||||
fmtprint(fmt, "PortTSet ");
|
||||
portMapPrint(fmt, &x->map);
|
||||
}
|
||||
static uint
|
||||
portTSetSize(PortTSet *x)
|
||||
{
|
||||
uint a;
|
||||
USED(x);
|
||||
a = 0 + portMapSize(&x->map);
|
||||
return a;
|
||||
}
|
||||
static int
|
||||
portTSetPack(uchar *a, uchar *ea, uchar **pa, PortTSet *x)
|
||||
{
|
||||
if(portMapPack(a, ea, &a, &x->map) < 0) goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
static int
|
||||
portTSetUnpack(uchar *a, uchar *ea, uchar **pa, PortTSet *x)
|
||||
{
|
||||
if(portMapUnpack(a, ea, &a, &x->map) < 0) goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
static void
|
||||
portRSetPrint(Fmt *fmt, PortRSet *x)
|
||||
{
|
||||
fmtprint(fmt, "PortRSet %ud", x->b);
|
||||
}
|
||||
static uint
|
||||
portRSetSize(PortRSet *x)
|
||||
{
|
||||
uint a;
|
||||
USED(x);
|
||||
a = 0 + 4;
|
||||
return a;
|
||||
}
|
||||
static int
|
||||
portRSetPack(uchar *a, uchar *ea, uchar **pa, PortRSet *x)
|
||||
{
|
||||
if(sunuint1pack(a, ea, &a, &x->b) < 0) goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
static int
|
||||
portRSetUnpack(uchar *a, uchar *ea, uchar **pa, PortRSet *x)
|
||||
{
|
||||
if(sunuint1unpack(a, ea, &a, &x->b) < 0) goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
static void
|
||||
portTUnsetPrint(Fmt *fmt, PortTUnset *x)
|
||||
{
|
||||
fmtprint(fmt, "PortTUnset ");
|
||||
portMapPrint(fmt, &x->map);
|
||||
}
|
||||
static uint
|
||||
portTUnsetSize(PortTUnset *x)
|
||||
{
|
||||
uint a;
|
||||
USED(x);
|
||||
a = 0 + portMapSize(&x->map);
|
||||
return a;
|
||||
}
|
||||
static int
|
||||
portTUnsetPack(uchar *a, uchar *ea, uchar **pa, PortTUnset *x)
|
||||
{
|
||||
if(portMapPack(a, ea, &a, &x->map) < 0) goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
static int
|
||||
portTUnsetUnpack(uchar *a, uchar *ea, uchar **pa, PortTUnset *x)
|
||||
{
|
||||
if(portMapUnpack(a, ea, &a, &x->map) < 0) goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
static void
|
||||
portRUnsetPrint(Fmt *fmt, PortRUnset *x)
|
||||
{
|
||||
fmtprint(fmt, "PortRUnset %ud", x->b);
|
||||
}
|
||||
static uint
|
||||
portRUnsetSize(PortRUnset *x)
|
||||
{
|
||||
uint a;
|
||||
USED(x);
|
||||
a = 0 + 4;
|
||||
return a;
|
||||
}
|
||||
static int
|
||||
portRUnsetPack(uchar *a, uchar *ea, uchar **pa, PortRUnset *x)
|
||||
{
|
||||
if(sunuint1pack(a, ea, &a, &x->b) < 0) goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
static int
|
||||
portRUnsetUnpack(uchar *a, uchar *ea, uchar **pa, PortRUnset *x)
|
||||
{
|
||||
if(sunuint1unpack(a, ea, &a, &x->b) < 0) goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
static void
|
||||
portTGetportPrint(Fmt *fmt, PortTGetport *x)
|
||||
{
|
||||
fmtprint(fmt, "PortTGetport ");
|
||||
portMapPrint(fmt, &x->map);
|
||||
}
|
||||
static uint
|
||||
portTGetportSize(PortTGetport *x)
|
||||
{
|
||||
uint a;
|
||||
USED(x);
|
||||
a = 0 + portMapSize(&x->map);
|
||||
return a;
|
||||
}
|
||||
static int
|
||||
portTGetportPack(uchar *a, uchar *ea, uchar **pa, PortTGetport *x)
|
||||
{
|
||||
if(portMapPack(a, ea, &a, &x->map) < 0) goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
static int
|
||||
portTGetportUnpack(uchar *a, uchar *ea, uchar **pa, PortTGetport *x)
|
||||
{
|
||||
if(portMapUnpack(a, ea, &a, &x->map) < 0) goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
static void
|
||||
portRGetportPrint(Fmt *fmt, PortRGetport *x)
|
||||
{
|
||||
fmtprint(fmt, "PortRGetport %ud", x->port);
|
||||
}
|
||||
static uint
|
||||
portRGetportSize(PortRGetport *x)
|
||||
{
|
||||
uint a;
|
||||
USED(x);
|
||||
a = 0 + 4;
|
||||
return a;
|
||||
}
|
||||
static int
|
||||
portRGetportPack(uchar *a, uchar *ea, uchar **pa, PortRGetport *x)
|
||||
{
|
||||
if(sunuint32pack(a, ea, &a, &x->port) < 0) goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
static int
|
||||
portRGetportUnpack(uchar *a, uchar *ea, uchar **pa, PortRGetport *x)
|
||||
{
|
||||
if(sunuint32unpack(a, ea, &a, &x->port) < 0) goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
static void
|
||||
portTDumpPrint(Fmt *fmt, PortTDump *x)
|
||||
{
|
||||
USED(x);
|
||||
fmtprint(fmt, "PortTDump");
|
||||
}
|
||||
static uint
|
||||
portTDumpSize(PortTDump *x)
|
||||
{
|
||||
uint a;
|
||||
USED(x);
|
||||
a = 0;
|
||||
return a;
|
||||
}
|
||||
static int
|
||||
portTDumpPack(uchar *a, uchar *ea, uchar **pa, PortTDump *x)
|
||||
{
|
||||
USED(ea);
|
||||
USED(x);
|
||||
*pa = a;
|
||||
return 0;
|
||||
}
|
||||
static int
|
||||
portTDumpUnpack(uchar *a, uchar *ea, uchar **pa, PortTDump *x)
|
||||
{
|
||||
USED(ea);
|
||||
USED(x);
|
||||
*pa = a;
|
||||
return 0;
|
||||
}
|
||||
static void
|
||||
portRDumpPrint(Fmt *fmt, PortRDump *x)
|
||||
{
|
||||
int i;
|
||||
|
||||
fmtprint(fmt, "PortRDump");
|
||||
for(i=0; i<x->nmap; i++){
|
||||
fmtprint(fmt, " ");
|
||||
portMapPrint(fmt, &x->map[i]);
|
||||
}
|
||||
}
|
||||
static uint
|
||||
portRDumpSize(PortRDump *x)
|
||||
{
|
||||
return (5*4*x->nmap) + 4;
|
||||
}
|
||||
static int
|
||||
portRDumpPack(uchar *a, uchar *ea, uchar **pa, PortRDump *x)
|
||||
{
|
||||
int i;
|
||||
u32int zero, one;
|
||||
|
||||
zero = 0;
|
||||
one = 1;
|
||||
for(i=0; i<x->nmap; i++){
|
||||
if(sunuint32pack(a, ea, &a, &one) < 0
|
||||
|| portMapPack(a, ea, &a, &x->map[i]) < 0)
|
||||
goto Err;
|
||||
}
|
||||
if(sunuint32pack(a, ea, &a, &zero) < 0)
|
||||
goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
static int
|
||||
portRDumpUnpack(uchar *a, uchar *ea, uchar **pa, PortRDump *x)
|
||||
{
|
||||
int i;
|
||||
u1int u1;
|
||||
PortMap *m;
|
||||
|
||||
m = (PortMap*)a;
|
||||
for(i=0;; i++){
|
||||
if(sunuint1unpack(a, ea, &a, &u1) < 0)
|
||||
goto Err;
|
||||
if(u1 == 0)
|
||||
break;
|
||||
if(portMapUnpack(a, ea, &a, &m[i]) < 0)
|
||||
goto Err;
|
||||
}
|
||||
x->nmap = i;
|
||||
x->map = m;
|
||||
*pa = a;
|
||||
return 0;
|
||||
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
static void
|
||||
portTCallitPrint(Fmt *fmt, PortTCallit *x)
|
||||
{
|
||||
fmtprint(fmt, "PortTCallit [%ud,%ud,%ud] %ud", x->prog, x->vers, x->proc, x->count);
|
||||
}
|
||||
static uint
|
||||
portTCallitSize(PortTCallit *x)
|
||||
{
|
||||
uint a;
|
||||
USED(x);
|
||||
a = 0 + 4 + 4 + 4 + sunvaropaquesize(x->count);
|
||||
return a;
|
||||
}
|
||||
static int
|
||||
portTCallitPack(uchar *a, uchar *ea, uchar **pa, PortTCallit *x)
|
||||
{
|
||||
if(sunuint32pack(a, ea, &a, &x->prog) < 0) goto Err;
|
||||
if(sunuint32pack(a, ea, &a, &x->vers) < 0) goto Err;
|
||||
if(sunuint32pack(a, ea, &a, &x->proc) < 0) goto Err;
|
||||
if(sunvaropaquepack(a, ea, &a, &x->data, &x->count, -1) < 0) goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
static int
|
||||
portTCallitUnpack(uchar *a, uchar *ea, uchar **pa, PortTCallit *x)
|
||||
{
|
||||
if(sunuint32unpack(a, ea, &a, &x->prog) < 0) goto Err;
|
||||
if(sunuint32unpack(a, ea, &a, &x->vers) < 0) goto Err;
|
||||
if(sunuint32unpack(a, ea, &a, &x->proc) < 0) goto Err;
|
||||
if(sunvaropaqueunpack(a, ea, &a, &x->data, &x->count, -1) < 0) goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
static void
|
||||
portRCallitPrint(Fmt *fmt, PortRCallit *x)
|
||||
{
|
||||
fmtprint(fmt, "PortRCallit %ud %ud", x->port, x->count);
|
||||
}
|
||||
static uint
|
||||
portRCallitSize(PortRCallit *x)
|
||||
{
|
||||
uint a;
|
||||
USED(x);
|
||||
a = 0 + 4 + sunvaropaquesize(x->count);
|
||||
return a;
|
||||
}
|
||||
static int
|
||||
portRCallitPack(uchar *a, uchar *ea, uchar **pa, PortRCallit *x)
|
||||
{
|
||||
if(sunuint32pack(a, ea, &a, &x->port) < 0) goto Err;
|
||||
if(sunvaropaquepack(a, ea, &a, &x->data, &x->count, -1) < 0) goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
static int
|
||||
portRCallitUnpack(uchar *a, uchar *ea, uchar **pa, PortRCallit *x)
|
||||
{
|
||||
if(sunuint32unpack(a, ea, &a, &x->port) < 0) goto Err;
|
||||
if(sunvaropaqueunpack(a, ea, &a, &x->data, &x->count, -1) < 0) goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
|
||||
typedef int (*P)(uchar*, uchar*, uchar**, SunCall*);
|
||||
typedef void (*F)(Fmt*, SunCall*);
|
||||
typedef uint (*S)(SunCall*);
|
||||
|
||||
static SunProc proc[] = {
|
||||
(P)portTNullPack, (P)portTNullUnpack, (S)portTNullSize, (F)portTNullPrint, sizeof(PortTNull),
|
||||
(P)portRNullPack, (P)portRNullUnpack, (S)portRNullSize, (F)portRNullPrint, sizeof(PortRNull),
|
||||
(P)portTSetPack, (P)portTSetUnpack, (S)portTSetSize, (F)portTSetPrint, sizeof(PortTSet),
|
||||
(P)portRSetPack, (P)portRSetUnpack, (S)portRSetSize, (F)portRSetPrint, sizeof(PortRSet),
|
||||
(P)portTUnsetPack, (P)portTUnsetUnpack, (S)portTUnsetSize, (F)portTUnsetPrint, sizeof(PortTUnset),
|
||||
(P)portRUnsetPack, (P)portRUnsetUnpack, (S)portRUnsetSize, (F)portRUnsetPrint, sizeof(PortRUnset),
|
||||
(P)portTGetportPack, (P)portTGetportUnpack, (S)portTGetportSize, (F)portTGetportPrint, sizeof(PortTGetport),
|
||||
(P)portRGetportPack, (P)portRGetportUnpack, (S)portRGetportSize, (F)portRGetportPrint, sizeof(PortRGetport),
|
||||
(P)portTDumpPack, (P)portTDumpUnpack, (S)portTDumpSize, (F)portTDumpPrint, sizeof(PortTDump),
|
||||
(P)portRDumpPack, (P)portRDumpUnpack, (S)portRDumpSize, (F)portRDumpPrint, sizeof(PortRDump),
|
||||
(P)portTCallitPack, (P)portTCallitUnpack, (S)portTCallitSize, (F)portTCallitPrint, sizeof(PortTCallit),
|
||||
(P)portRCallitPack, (P)portRCallitUnpack, (S)portRCallitSize, (F)portRCallitPrint, sizeof(PortRCallit),
|
||||
};
|
||||
|
||||
SunProg portProg =
|
||||
{
|
||||
PortProgram,
|
||||
PortVersion,
|
||||
proc,
|
||||
nelem(proc),
|
||||
};
|
||||
74
src/libsunrpc/prog.c
Normal file
74
src/libsunrpc/prog.c
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <thread.h>
|
||||
#include <sunrpc.h>
|
||||
|
||||
SunStatus
|
||||
suncallpack(SunProg *prog, uchar *a, uchar *ea, uchar **pa, SunCall *c)
|
||||
{
|
||||
uchar *x;
|
||||
int (*pack)(uchar*, uchar*, uchar**, SunCall*);
|
||||
|
||||
if(pa == nil)
|
||||
pa = &x;
|
||||
if(c->type < 0 || c->type >= prog->nproc || (pack=prog->proc[c->type].pack) == nil)
|
||||
return SunProcUnavail;
|
||||
if((*pack)(a, ea, pa, c) < 0)
|
||||
return SunGarbageArgs;
|
||||
return SunSuccess;
|
||||
}
|
||||
|
||||
SunStatus
|
||||
suncallunpack(SunProg *prog, uchar *a, uchar *ea, uchar **pa, SunCall *c)
|
||||
{
|
||||
uchar *x;
|
||||
int (*unpack)(uchar*, uchar*, uchar**, SunCall*);
|
||||
|
||||
if(pa == nil)
|
||||
pa = &x;
|
||||
if(c->type < 0 || c->type >= prog->nproc || (unpack=prog->proc[c->type].unpack) == nil)
|
||||
return SunProcUnavail;
|
||||
if((*unpack)(a, ea, pa, c) < 0){
|
||||
fprint(2, "%lud %d: %.*H unpack failed\n", prog->prog, c->type, (int)(ea-a), a);
|
||||
return SunGarbageArgs;
|
||||
}
|
||||
return SunSuccess;
|
||||
}
|
||||
|
||||
SunStatus
|
||||
suncallunpackalloc(SunProg *prog, SunCallType type, uchar *a, uchar *ea, uchar **pa, SunCall **pc)
|
||||
{
|
||||
uchar *x;
|
||||
uint size;
|
||||
int (*unpack)(uchar*, uchar*, uchar**, SunCall*);
|
||||
SunCall *c;
|
||||
|
||||
if(pa == nil)
|
||||
pa = &x;
|
||||
if(type < 0 || type >= prog->nproc || (unpack=prog->proc[type].unpack) == nil)
|
||||
return SunProcUnavail;
|
||||
size = prog->proc[type].sizeoftype;
|
||||
if(size == 0)
|
||||
return SunProcUnavail;
|
||||
c = mallocz(size, 1);
|
||||
if(c == nil)
|
||||
return SunSystemErr;
|
||||
c->type = type;
|
||||
if((*unpack)(a, ea, pa, c) < 0){
|
||||
fprint(2, "in: %.*H unpack failed\n", (int)(ea-a), a);
|
||||
free(c);
|
||||
return SunGarbageArgs;
|
||||
}
|
||||
*pc = c;
|
||||
return SunSuccess;
|
||||
}
|
||||
|
||||
uint
|
||||
suncallsize(SunProg *prog, SunCall *c)
|
||||
{
|
||||
uint (*size)(SunCall*);
|
||||
|
||||
if(c->type < 0 || c->type >= prog->nproc || (size=prog->proc[c->type].size) == nil)
|
||||
return ~0;
|
||||
return (*size)(c);
|
||||
}
|
||||
528
src/libsunrpc/rpc.c
Normal file
528
src/libsunrpc/rpc.c
Normal file
|
|
@ -0,0 +1,528 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <thread.h>
|
||||
#include <sunrpc.h>
|
||||
|
||||
/*
|
||||
* RPC protocol constants
|
||||
*/
|
||||
enum
|
||||
{
|
||||
RpcVersion = 2,
|
||||
|
||||
/* msg type */
|
||||
MsgCall = 0,
|
||||
MsgReply = 1,
|
||||
|
||||
/* reply stat */
|
||||
MsgAccepted = 0,
|
||||
MsgDenied = 1,
|
||||
|
||||
/* accept stat */
|
||||
MsgSuccess = 0,
|
||||
MsgProgUnavail = 1,
|
||||
MsgProgMismatch = 2,
|
||||
MsgProcUnavail = 3,
|
||||
MsgGarbageArgs = 4,
|
||||
MsgSystemErr = 5,
|
||||
|
||||
/* reject stat */
|
||||
MsgRpcMismatch = 0,
|
||||
MsgAuthError = 1,
|
||||
|
||||
/* msg auth xxx */
|
||||
MsgAuthOk = 0,
|
||||
MsgAuthBadCred = 1,
|
||||
MsgAuthRejectedCred = 2,
|
||||
MsgAuthBadVerf = 3,
|
||||
MsgAuthRejectedVerf = 4,
|
||||
MsgAuthTooWeak = 5,
|
||||
MsgAuthInvalidResp = 6,
|
||||
MsgAuthFailed = 7,
|
||||
};
|
||||
|
||||
SunStatus
|
||||
sunrpcpack(uchar *a, uchar *ea, uchar **pa, SunRpc *rpc)
|
||||
{
|
||||
u32int x;
|
||||
|
||||
if(sunuint32pack(a, ea, &a, &rpc->xid) < 0)
|
||||
goto Err;
|
||||
if(rpc->iscall){
|
||||
if(sunuint32pack(a, ea, &a, (x=MsgCall, &x)) < 0
|
||||
|| sunuint32pack(a, ea, &a, (x=RpcVersion, &x)) < 0
|
||||
|| sunuint32pack(a, ea, &a, &rpc->prog) < 0
|
||||
|| sunuint32pack(a, ea, &a, &rpc->vers) < 0
|
||||
|| sunuint32pack(a, ea, &a, &rpc->proc) < 0
|
||||
|| sunauthinfopack(a, ea, &a, &rpc->cred) < 0
|
||||
|| sunauthinfopack(a, ea, &a, &rpc->verf) < 0
|
||||
|| sunfixedopaquepack(a, ea, &a, rpc->data, rpc->ndata) < 0)
|
||||
goto Err;
|
||||
}else{
|
||||
if(sunuint32pack(a, ea, &a, (x=MsgReply, &x)) < 0)
|
||||
goto Err;
|
||||
switch(rpc->status&0xF0000){
|
||||
case 0:
|
||||
case SunAcceptError:
|
||||
if(sunuint32pack(a, ea, &a, (x=MsgAccepted, &x)) < 0
|
||||
|| sunauthinfopack(a, ea, &a, &rpc->verf) < 0)
|
||||
goto Err;
|
||||
break;
|
||||
default:
|
||||
if(sunuint32pack(a, ea, &a, (x=MsgDenied, &x)) < 0)
|
||||
goto Err;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(rpc->status){
|
||||
case SunSuccess:
|
||||
if(sunuint32pack(a, ea, &a, (x=MsgSuccess, &x)) < 0
|
||||
|| sunfixedopaquepack(a, ea, &a, rpc->data, rpc->ndata) < 0)
|
||||
goto Err;
|
||||
break;
|
||||
case SunRpcMismatch:
|
||||
case SunProgMismatch:
|
||||
if(sunuint32pack(a, ea, &a, (x=rpc->status&0xFFFF, &x)) < 0
|
||||
|| sunuint32pack(a, ea, &a, &rpc->low) < 0
|
||||
|| sunuint32pack(a, ea, &a, &rpc->high) < 0)
|
||||
goto Err;
|
||||
break;
|
||||
default:
|
||||
if(sunuint32pack(a, ea, &a, (x=rpc->status&0xFFFF, &x)) < 0)
|
||||
goto Err;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*pa = a;
|
||||
return SunSuccess;
|
||||
|
||||
Err:
|
||||
*pa = ea;
|
||||
return SunGarbageArgs;
|
||||
}
|
||||
|
||||
uint
|
||||
sunrpcsize(SunRpc *rpc)
|
||||
{
|
||||
uint a;
|
||||
|
||||
a = 4;
|
||||
if(rpc->iscall){
|
||||
a += 5*4;
|
||||
a += sunauthinfosize(&rpc->cred);
|
||||
a += sunauthinfosize(&rpc->verf);
|
||||
a += sunfixedopaquesize(rpc->ndata);
|
||||
}else{
|
||||
a += 4;
|
||||
switch(rpc->status&0xF0000){
|
||||
case 0:
|
||||
case SunAcceptError:
|
||||
a += 4+sunauthinfosize(&rpc->verf);
|
||||
break;
|
||||
default:
|
||||
a += 4;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(rpc->status){
|
||||
case SunSuccess:
|
||||
a += 4+sunfixedopaquesize(rpc->ndata);
|
||||
break;
|
||||
case SunRpcMismatch:
|
||||
case SunProgMismatch:
|
||||
a += 3*4;
|
||||
default:
|
||||
a += 4;
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
SunStatus
|
||||
sunrpcunpack(uchar *a, uchar *ea, uchar **pa, SunRpc *rpc)
|
||||
{
|
||||
u32int x;
|
||||
|
||||
memset(rpc, 0, sizeof *rpc);
|
||||
if(sunuint32unpack(a, ea, &a, &rpc->xid) < 0
|
||||
|| sunuint32unpack(a, ea, &a, &x) < 0)
|
||||
goto Err;
|
||||
|
||||
switch(x){
|
||||
default:
|
||||
goto Err;
|
||||
case MsgCall:
|
||||
rpc->iscall = 1;
|
||||
if(sunuint32unpack(a, ea, &a, &x) < 0 || x != RpcVersion
|
||||
|| sunuint32unpack(a, ea, &a, &rpc->prog) < 0
|
||||
|| sunuint32unpack(a, ea, &a, &rpc->vers) < 0
|
||||
|| sunuint32unpack(a, ea, &a, &rpc->proc) < 0
|
||||
|| sunauthinfounpack(a, ea, &a, &rpc->cred) < 0
|
||||
|| sunauthinfounpack(a, ea, &a, &rpc->verf) < 0)
|
||||
goto Err;
|
||||
rpc->ndata = ea-a;
|
||||
rpc->data = a;
|
||||
a = ea;
|
||||
break;
|
||||
|
||||
case MsgReply:
|
||||
rpc->iscall = 0;
|
||||
if(sunuint32unpack(a, ea, &a, &x) < 0)
|
||||
goto Err;
|
||||
switch(x){
|
||||
default:
|
||||
goto Err;
|
||||
case MsgAccepted:
|
||||
if(sunauthinfounpack(a, ea, &a, &rpc->verf) < 0
|
||||
|| sunuint32unpack(a, ea, &a, &x) < 0)
|
||||
goto Err;
|
||||
switch(x){
|
||||
case MsgSuccess:
|
||||
rpc->status = SunSuccess;
|
||||
rpc->ndata = ea-a;
|
||||
rpc->data = a;
|
||||
a = ea;
|
||||
break;
|
||||
case MsgProgUnavail:
|
||||
case MsgProcUnavail:
|
||||
case MsgGarbageArgs:
|
||||
case MsgSystemErr:
|
||||
rpc->status = SunAcceptError | x;
|
||||
break;
|
||||
case MsgProgMismatch:
|
||||
rpc->status = SunAcceptError | x;
|
||||
if(sunuint32unpack(a, ea, &a, &rpc->low) < 0
|
||||
|| sunuint32unpack(a, ea, &a, &rpc->high) < 0)
|
||||
goto Err;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MsgDenied:
|
||||
if(sunuint32unpack(a, ea, &a, &x) < 0)
|
||||
goto Err;
|
||||
switch(x){
|
||||
default:
|
||||
goto Err;
|
||||
case MsgAuthError:
|
||||
if(sunuint32unpack(a, ea, &a, &x) < 0)
|
||||
goto Err;
|
||||
rpc->status = SunAuthError | x;
|
||||
break;
|
||||
case MsgRpcMismatch:
|
||||
rpc->status = SunRejectError | x;
|
||||
if(sunuint32unpack(a, ea, &a, &rpc->low) < 0
|
||||
|| sunuint32unpack(a, ea, &a, &rpc->high) < 0)
|
||||
goto Err;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
*pa = a;
|
||||
return SunSuccess;
|
||||
|
||||
Err:
|
||||
*pa = ea;
|
||||
return SunGarbageArgs;
|
||||
}
|
||||
|
||||
void
|
||||
sunrpcprint(Fmt *fmt, SunRpc *rpc)
|
||||
{
|
||||
fmtprint(fmt, "xid=%#ux", rpc->xid);
|
||||
if(rpc->iscall){
|
||||
fmtprint(fmt, " prog %#ux vers %#ux proc %#ux [", rpc->prog, rpc->vers, rpc->proc);
|
||||
sunauthinfoprint(fmt, &rpc->cred);
|
||||
fmtprint(fmt, "] [");
|
||||
sunauthinfoprint(fmt, &rpc->verf);
|
||||
fmtprint(fmt, "]");
|
||||
}else{
|
||||
fmtprint(fmt, " status %#ux [", rpc->status);
|
||||
sunauthinfoprint(fmt, &rpc->verf);
|
||||
fmtprint(fmt, "] low %#ux high %#ux", rpc->low, rpc->high);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sunauthinfoprint(Fmt *fmt, SunAuthInfo *ai)
|
||||
{
|
||||
switch(ai->flavor){
|
||||
case SunAuthNone:
|
||||
fmtprint(fmt, "none");
|
||||
break;
|
||||
case SunAuthShort:
|
||||
fmtprint(fmt, "short");
|
||||
break;
|
||||
case SunAuthSys:
|
||||
fmtprint(fmt, "sys");
|
||||
break;
|
||||
default:
|
||||
fmtprint(fmt, "%#ux", ai->flavor);
|
||||
break;
|
||||
}
|
||||
// if(ai->ndata)
|
||||
// fmtprint(fmt, " %.*H", ai->ndata, ai->data);
|
||||
}
|
||||
|
||||
uint
|
||||
sunauthinfosize(SunAuthInfo *ai)
|
||||
{
|
||||
return 4 + sunvaropaquesize(ai->ndata);
|
||||
}
|
||||
|
||||
int
|
||||
sunauthinfopack(uchar *a, uchar *ea, uchar **pa, SunAuthInfo *ai)
|
||||
{
|
||||
if(sunuint32pack(a, ea, &a, &ai->flavor) < 0
|
||||
|| sunvaropaquepack(a, ea, &a, &ai->data, &ai->ndata, 400) < 0)
|
||||
goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
sunauthinfounpack(uchar *a, uchar *ea, uchar **pa, SunAuthInfo *ai)
|
||||
{
|
||||
if(sunuint32unpack(a, ea, &a, &ai->flavor) < 0
|
||||
|| sunvaropaqueunpack(a, ea, &a, &ai->data, &ai->ndata, 400) < 0)
|
||||
goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
sunenumpack(uchar *a, uchar *ea, uchar **pa, int *e)
|
||||
{
|
||||
u32int x;
|
||||
|
||||
x = *e;
|
||||
return sunuint32pack(a, ea, pa, &x);
|
||||
}
|
||||
|
||||
int
|
||||
sunuint1pack(uchar *a, uchar *ea, uchar **pa, u1int *u)
|
||||
{
|
||||
u32int x;
|
||||
|
||||
x = *u;
|
||||
return sunuint32pack(a, ea, pa, &x);
|
||||
}
|
||||
|
||||
int
|
||||
sunuint32pack(uchar *a, uchar *ea, uchar **pa, u32int *u)
|
||||
{
|
||||
u32int x;
|
||||
|
||||
if(ea-a < 4)
|
||||
goto Err;
|
||||
|
||||
x = *u;
|
||||
*a++ = x>>24;
|
||||
*a++ = x>>16;
|
||||
*a++ = x>>8;
|
||||
*a++ = x;
|
||||
*pa = a;
|
||||
return 0;
|
||||
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
sunenumunpack(uchar *a, uchar *ea, uchar **pa, int *e)
|
||||
{
|
||||
u32int x;
|
||||
if(sunuint32unpack(a, ea, pa, &x) < 0)
|
||||
return -1;
|
||||
*e = x;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sunuint1unpack(uchar *a, uchar *ea, uchar **pa, u1int *u)
|
||||
{
|
||||
u32int x;
|
||||
if(sunuint32unpack(a, ea, pa, &x) < 0 || (x!=0 && x!=1)){
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
*u = x;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sunuint32unpack(uchar *a, uchar *ea, uchar **pa, u32int *u)
|
||||
{
|
||||
u32int x;
|
||||
|
||||
if(ea-a < 4)
|
||||
goto Err;
|
||||
x = *a++ << 24;
|
||||
x |= *a++ << 16;
|
||||
x |= *a++ << 8;
|
||||
x |= *a++;
|
||||
*pa = a;
|
||||
*u = x;
|
||||
return 0;
|
||||
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
sunuint64unpack(uchar *a, uchar *ea, uchar **pa, u64int *u)
|
||||
{
|
||||
u32int x, y;
|
||||
|
||||
if(sunuint32unpack(a, ea, &a, &x) < 0
|
||||
|| sunuint32unpack(a, ea, &a, &y) < 0)
|
||||
goto Err;
|
||||
*u = ((uvlong)x<<32) | y;
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
sunuint64pack(uchar *a, uchar *ea, uchar **pa, u64int *u)
|
||||
{
|
||||
u32int x, y;
|
||||
|
||||
x = *u >> 32;
|
||||
y = *u;
|
||||
if(sunuint32pack(a, ea, &a, &x) < 0
|
||||
|| sunuint32pack(a, ea, &a, &y) < 0)
|
||||
goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint
|
||||
sunstringsize(char *s)
|
||||
{
|
||||
return (4+strlen(s)+3) & ~3;
|
||||
}
|
||||
|
||||
int
|
||||
sunstringunpack(uchar *a, uchar *ea, uchar **pa, char **s, u32int max)
|
||||
{
|
||||
uchar *dat;
|
||||
u32int n;
|
||||
|
||||
if(sunvaropaqueunpack(a, ea, pa, &dat, &n, max) < 0)
|
||||
goto Err;
|
||||
/* slide string down over length to make room for NUL */
|
||||
memmove(dat-1, dat, n);
|
||||
dat[-1+n] = 0;
|
||||
*s = (char*)(dat-1);
|
||||
return 0;
|
||||
Err:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
sunstringpack(uchar *a, uchar *ea, uchar **pa, char **s, u32int max)
|
||||
{
|
||||
u32int n;
|
||||
|
||||
n = strlen(*s);
|
||||
return sunvaropaquepack(a, ea, pa, (uchar**)s, &n, max);
|
||||
}
|
||||
|
||||
uint
|
||||
sunvaropaquesize(u32int n)
|
||||
{
|
||||
return (4+n+3) & ~3;
|
||||
}
|
||||
|
||||
int
|
||||
sunvaropaquepack(uchar *a, uchar *ea, uchar **pa, uchar **dat, u32int *ndat, u32int max)
|
||||
{
|
||||
if(*ndat > max || sunuint32pack(a, ea, &a, ndat) < 0
|
||||
|| sunfixedopaquepack(a, ea, &a, *dat, *ndat) < 0)
|
||||
goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
sunvaropaqueunpack(uchar *a, uchar *ea, uchar **pa, uchar **dat, u32int *ndat, u32int max)
|
||||
{
|
||||
if(sunuint32unpack(a, ea, &a, ndat) < 0
|
||||
|| *ndat > max)
|
||||
goto Err;
|
||||
*dat = a;
|
||||
a += (*ndat+3)&~3;
|
||||
if(a > ea)
|
||||
goto Err;
|
||||
*pa = a;
|
||||
return 0;
|
||||
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint
|
||||
sunfixedopaquesize(u32int n)
|
||||
{
|
||||
return (n+3) & ~3;
|
||||
}
|
||||
|
||||
int
|
||||
sunfixedopaquepack(uchar *a, uchar *ea, uchar **pa, uchar *dat, u32int n)
|
||||
{
|
||||
uint nn;
|
||||
|
||||
nn = (n+3)&~3;
|
||||
if(a+nn > ea)
|
||||
goto Err;
|
||||
memmove(a, dat, n);
|
||||
if(nn > n)
|
||||
memset(a+n, 0, nn-n);
|
||||
a += nn;
|
||||
*pa = a;
|
||||
return 0;
|
||||
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
sunfixedopaqueunpack(uchar *a, uchar *ea, uchar **pa, uchar *dat, u32int n)
|
||||
{
|
||||
uint nn;
|
||||
|
||||
nn = (n+3)&~3;
|
||||
if(a+nn > ea)
|
||||
goto Err;
|
||||
memmove(dat, a, n);
|
||||
a += nn;
|
||||
*pa = a;
|
||||
return 0;
|
||||
|
||||
Err:
|
||||
*pa = ea;
|
||||
return -1;
|
||||
}
|
||||
|
||||
277
src/libsunrpc/server.c
Normal file
277
src/libsunrpc/server.c
Normal file
|
|
@ -0,0 +1,277 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <thread.h>
|
||||
#include <sunrpc.h>
|
||||
|
||||
/*
|
||||
* Sun RPC server; for now, no reply cache
|
||||
*/
|
||||
|
||||
static void sunrpcproc(void*);
|
||||
static void sunrpcrequestthread(void*);
|
||||
static void sunrpcreplythread(void*);
|
||||
static void sunrpcforkthread(void*);
|
||||
static SunProg *sunfindprog(SunSrv*, SunMsg*, SunRpc*, Channel**);
|
||||
|
||||
typedef struct Targ Targ;
|
||||
struct Targ
|
||||
{
|
||||
void (*fn)(void*);
|
||||
void *arg;
|
||||
};
|
||||
|
||||
SunSrv*
|
||||
sunsrv(void)
|
||||
{
|
||||
SunSrv *srv;
|
||||
|
||||
srv = emalloc(sizeof(SunSrv));
|
||||
srv->chatty = 0;
|
||||
srv->crequest = chancreate(sizeof(SunMsg*), 16);
|
||||
srv->creply = chancreate(sizeof(SunMsg*), 16);
|
||||
srv->cthread = chancreate(sizeof(Targ), 4);
|
||||
|
||||
proccreate(sunrpcproc, srv, SunStackSize);
|
||||
return srv;
|
||||
}
|
||||
|
||||
void
|
||||
sunsrvprog(SunSrv *srv, SunProg *prog, Channel *c)
|
||||
{
|
||||
if(srv->nprog%16 == 0){
|
||||
srv->prog = erealloc(srv->prog, (srv->nprog+16)*sizeof(srv->prog[0]));
|
||||
srv->cdispatch = erealloc(srv->cdispatch, (srv->nprog+16)*sizeof(srv->cdispatch[0]));
|
||||
}
|
||||
srv->prog[srv->nprog] = prog;
|
||||
srv->cdispatch[srv->nprog] = c;
|
||||
srv->nprog++;
|
||||
}
|
||||
|
||||
static void
|
||||
sunrpcproc(void *v)
|
||||
{
|
||||
threadcreate(sunrpcreplythread, v, SunStackSize);
|
||||
threadcreate(sunrpcrequestthread, v, SunStackSize);
|
||||
threadcreate(sunrpcforkthread, v, SunStackSize);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
sunrpcforkthread(void *v)
|
||||
{
|
||||
SunSrv *srv = v;
|
||||
Targ t;
|
||||
|
||||
while(recv(srv->cthread, &t) == 1)
|
||||
threadcreate(t.fn, t.arg, SunStackSize);
|
||||
}
|
||||
|
||||
void
|
||||
sunsrvthreadcreate(SunSrv *srv, void (*fn)(void*), void *arg)
|
||||
{
|
||||
Targ t;
|
||||
|
||||
t.fn = fn;
|
||||
t.arg = arg;
|
||||
send(srv->cthread, &t);
|
||||
}
|
||||
|
||||
static void
|
||||
sunrpcrequestthread(void *v)
|
||||
{
|
||||
uchar *p, *ep;
|
||||
Channel *c;
|
||||
SunSrv *srv = v;
|
||||
SunMsg *m;
|
||||
SunProg *pg;
|
||||
SunStatus ok;
|
||||
|
||||
while((m = recvp(srv->crequest)) != nil){
|
||||
/* could look up in cache here? */
|
||||
|
||||
if(srv->chatty) fprint(2, "sun msg %p count %d\n", m, m->count);
|
||||
m->srv = srv;
|
||||
p = m->data;
|
||||
ep = p+m->count;
|
||||
if(sunrpcunpack(p, ep, &p, &m->rpc) != SunSuccess){
|
||||
fprint(2, "in: %.*H unpack failed\n", m->count, m->data);
|
||||
sunmsgdrop(m);
|
||||
continue;
|
||||
}
|
||||
if(srv->chatty)
|
||||
fprint(2, "in: %B\n", &m->rpc);
|
||||
|
||||
if(srv->alwaysreject){
|
||||
if(srv->chatty)
|
||||
fprint(2, "\trejecting\n");
|
||||
sunmsgreplyerror(m, SunAuthTooWeak);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!m->rpc.iscall){
|
||||
sunmsgreplyerror(m, SunGarbageArgs);
|
||||
continue;
|
||||
}
|
||||
|
||||
if((pg = sunfindprog(srv, m, &m->rpc, &c)) == nil){
|
||||
/* sunfindprog sent error */
|
||||
continue;
|
||||
}
|
||||
|
||||
p = m->rpc.data;
|
||||
ep = p+m->rpc.ndata;
|
||||
m->call = nil;
|
||||
if((ok = suncallunpackalloc(pg, m->rpc.proc<<1, p, ep, &p, &m->call)) != SunSuccess){
|
||||
sunmsgreplyerror(m, ok);
|
||||
continue;
|
||||
}
|
||||
m->call->rpc = m->rpc;
|
||||
|
||||
if(srv->chatty)
|
||||
fprint(2, "\t%C\n", m->call);
|
||||
|
||||
m->pg = pg;
|
||||
sendp(c, m);
|
||||
}
|
||||
}
|
||||
|
||||
static SunProg*
|
||||
sunfindprog(SunSrv *srv, SunMsg *m, SunRpc *rpc, Channel **pc)
|
||||
{
|
||||
int i, vlo, vhi;
|
||||
SunProg *pg;
|
||||
|
||||
vlo = 0x7fffffff;
|
||||
vhi = -1;
|
||||
|
||||
for(i=0; i<srv->nprog; i++){
|
||||
pg = srv->prog[i];
|
||||
if(pg->prog != rpc->prog)
|
||||
continue;
|
||||
if(pg->vers == rpc->vers){
|
||||
*pc = srv->cdispatch[i];
|
||||
return pg;
|
||||
}
|
||||
/* right program, wrong version: record range */
|
||||
if(pg->vers < vlo)
|
||||
vlo = pg->vers;
|
||||
if(pg->vers > vhi)
|
||||
vhi = pg->vers;
|
||||
}
|
||||
if(vhi == -1){
|
||||
if(srv->chatty)
|
||||
fprint(2, "\tprogram %ud unavailable\n", rpc->prog);
|
||||
sunmsgreplyerror(m, SunProgUnavail);
|
||||
}else{
|
||||
/* putting these in rpc is a botch */
|
||||
rpc->low = vlo;
|
||||
rpc->high = vhi;
|
||||
if(srv->chatty)
|
||||
fprint(2, "\tversion %ud unavailable; have %d-%d\n", rpc->vers, vlo, vhi);
|
||||
sunmsgreplyerror(m, SunProgMismatch);
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
static void
|
||||
sunrpcreplythread(void *v)
|
||||
{
|
||||
SunMsg *m;
|
||||
SunSrv *srv = v;
|
||||
|
||||
while((m = recvp(srv->creply)) != nil){
|
||||
/* could record in cache here? */
|
||||
sendp(m->creply, m);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
sunmsgreplyerror(SunMsg *m, SunStatus error)
|
||||
{
|
||||
uchar *p, *bp, *ep;
|
||||
int n;
|
||||
|
||||
m->rpc.status = error;
|
||||
m->rpc.iscall = 0;
|
||||
m->rpc.verf.flavor = SunAuthNone;
|
||||
m->rpc.data = nil;
|
||||
m->rpc.ndata = 0;
|
||||
|
||||
if(m->srv->chatty)
|
||||
fprint(2, "out: %B\n", &m->rpc);
|
||||
|
||||
n = sunrpcsize(&m->rpc);
|
||||
bp = emalloc(n);
|
||||
ep = bp+n;
|
||||
p = bp;
|
||||
if(sunrpcpack(p, ep, &p, &m->rpc) < 0){
|
||||
fprint(2, "sunrpcpack failed\n");
|
||||
sunmsgdrop(m);
|
||||
return 0;
|
||||
}
|
||||
if(p != ep){
|
||||
fprint(2, "sunmsgreplyerror: rpc sizes didn't work out\n");
|
||||
sunmsgdrop(m);
|
||||
return 0;
|
||||
}
|
||||
free(m->data);
|
||||
m->data = bp;
|
||||
m->count = n;
|
||||
sendp(m->srv->creply, m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sunmsgreply(SunMsg *m, SunCall *c)
|
||||
{
|
||||
int n1, n2;
|
||||
uchar *bp, *p, *ep;
|
||||
|
||||
c->type = m->call->type+1;
|
||||
c->rpc.iscall = 0;
|
||||
c->rpc.prog = m->rpc.prog;
|
||||
c->rpc.vers = m->rpc.vers;
|
||||
c->rpc.proc = m->rpc.proc;
|
||||
c->rpc.xid = m->rpc.xid;
|
||||
|
||||
if(m->srv->chatty){
|
||||
fprint(2, "out: %B\n", &c->rpc);
|
||||
fprint(2, "\t%C\n", c);
|
||||
}
|
||||
|
||||
n1 = sunrpcsize(&c->rpc);
|
||||
n2 = suncallsize(m->pg, c);
|
||||
|
||||
bp = emalloc(n1+n2);
|
||||
ep = bp+n1+n2;
|
||||
p = bp;
|
||||
if(sunrpcpack(p, ep, &p, &c->rpc) != SunSuccess){
|
||||
fprint(2, "sunrpcpack failed\n");
|
||||
return sunmsgdrop(m);
|
||||
}
|
||||
if(suncallpack(m->pg, p, ep, &p, c) != SunSuccess){
|
||||
fprint(2, "pg->pack failed\n");
|
||||
return sunmsgdrop(m);
|
||||
}
|
||||
if(p != ep){
|
||||
fprint(2, "sunmsgreply: sizes didn't work out\n");
|
||||
return sunmsgdrop(m);
|
||||
}
|
||||
free(m->data);
|
||||
m->data = bp;
|
||||
m->count = n1+n2;
|
||||
|
||||
sendp(m->srv->creply, m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sunmsgdrop(SunMsg *m)
|
||||
{
|
||||
free(m->data);
|
||||
free(m->call);
|
||||
memset(m, 0xFB, sizeof *m);
|
||||
free(m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
14
src/libsunrpc/suncall.c
Normal file
14
src/libsunrpc/suncall.c
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <thread.h>
|
||||
#include <sunrpc.h>
|
||||
|
||||
void
|
||||
suncallsetup(SunCall *c, SunProg *prog, uint proc)
|
||||
{
|
||||
c->rpc.prog = prog->prog;
|
||||
c->rpc.vers = prog->vers;
|
||||
c->rpc.proc = proc>>1;
|
||||
c->rpc.iscall = !(proc&1);
|
||||
c->type = proc;
|
||||
}
|
||||
120
src/libsunrpc/udp.c
Normal file
120
src/libsunrpc/udp.c
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <ip.h>
|
||||
#include <thread.h>
|
||||
#include <sunrpc.h>
|
||||
|
||||
typedef struct SunMsgUdp SunMsgUdp;
|
||||
struct SunMsgUdp
|
||||
{
|
||||
SunMsg msg;
|
||||
Udphdr udp;
|
||||
};
|
||||
|
||||
typedef struct Arg Arg;
|
||||
struct Arg
|
||||
{
|
||||
SunSrv *srv;
|
||||
Channel *creply;
|
||||
Channel *csync;
|
||||
int fd;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
UdpMaxRead = 65536+Udphdrsize
|
||||
};
|
||||
static void
|
||||
sunudpread(void *v)
|
||||
{
|
||||
int n, paraport, port;
|
||||
uchar *buf;
|
||||
Arg arg = *(Arg*)v;
|
||||
SunMsgUdp *msg;
|
||||
SunSrv *srv;
|
||||
Udphdr udp;
|
||||
uchar localip[IPaddrlen];
|
||||
|
||||
sendp(arg.csync, 0);
|
||||
srv = arg.srv;
|
||||
paraport = -1;
|
||||
|
||||
/* 127.1 */
|
||||
memmove(localip, v4prefix, IPaddrlen);
|
||||
localip[12] = 127;
|
||||
localip[15] = 1;
|
||||
|
||||
buf = emalloc(UdpMaxRead);
|
||||
while((n = udpread(arg.fd, &udp, buf, UdpMaxRead)) > 0){
|
||||
if(arg.srv->chatty)
|
||||
fprint(2, "udpread got %d (%d) from %I\n", n, Udphdrsize, udp.raddr);
|
||||
if((srv->localonly || srv->localparanoia) && ipcmp(udp.raddr, localip) != 0){
|
||||
fprint(2, "dropping message from %I: not local\n", udp.raddr);
|
||||
continue;
|
||||
}
|
||||
if(srv->localparanoia){
|
||||
port = nhgets(udp.rport);
|
||||
if(paraport == -1){
|
||||
fprint(2, "paranoid mode: only %I/%d allowed\n", localip, port);
|
||||
paraport = port;
|
||||
}else if(paraport != port){
|
||||
fprint(2, "dropping message from %I: not port %d\n", udp.raddr, port);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
msg = emalloc(sizeof(SunMsgUdp));
|
||||
msg->udp = udp;
|
||||
msg->msg.data = emalloc(n);
|
||||
msg->msg.count = n;
|
||||
memmove(msg->msg.data, buf, n);
|
||||
msg->msg.creply = arg.creply;
|
||||
if(arg.srv->chatty)
|
||||
fprint(2, "message %p count %d\n", msg, msg->msg.count);
|
||||
sendp(arg.srv->crequest, msg);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sunudpwrite(void *v)
|
||||
{
|
||||
uchar *buf;
|
||||
Arg arg = *(Arg*)v;
|
||||
SunMsgUdp *msg;
|
||||
|
||||
sendp(arg.csync, 0);
|
||||
|
||||
buf = emalloc(UdpMaxRead);
|
||||
while((msg = recvp(arg.creply)) != nil){
|
||||
if(udpwrite(arg.fd, &msg->udp, msg->msg.data, msg->msg.count) != msg->msg.count)
|
||||
fprint(2, "udpwrite: %r\n");
|
||||
free(msg->msg.data);
|
||||
free(msg);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
sunsrvudp(SunSrv *srv, char *address)
|
||||
{
|
||||
int fd;
|
||||
char adir[40];
|
||||
Arg *arg;
|
||||
|
||||
fd = announce(address, adir);
|
||||
if(fd < 0)
|
||||
return -1;
|
||||
|
||||
arg = emalloc(sizeof(Arg));
|
||||
arg->fd = fd;
|
||||
arg->srv = srv;
|
||||
arg->creply = chancreate(sizeof(SunMsg*), 10);
|
||||
arg->csync = chancreate(sizeof(void*), 10);
|
||||
|
||||
proccreate(sunudpread, arg, SunStackSize);
|
||||
proccreate(sunudpwrite, arg, SunStackSize);
|
||||
recvp(arg->csync);
|
||||
recvp(arg->csync);
|
||||
chanfree(arg->csync);
|
||||
free(arg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue