Add sunrpc.

This commit is contained in:
rsc 2004-04-21 03:04:30 +00:00
parent fa256eecfa
commit 551445b92c
16 changed files with 7163 additions and 0 deletions

60
src/libsunrpc/authunix.c Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load diff

498
src/libsunrpc/portmap.c Normal file
View 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
View 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
View 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
View 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
View 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
View 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;
}