plan9fox/sys/src/cmd/9nfs/rpc.c
2011-03-30 19:35:09 +03:00

315 lines
5.5 KiB
C

#include "all.h"
#define SHORT(x) r->x = (p[1] | (p[0]<<8)); p += 2
#define LONG(x) r->x = (p[3] | (p[2]<<8) |\
(p[1]<<16) | (p[0]<<24)); p += 4
#define SKIPLONG p += 4
#define PTR(x, n) r->x = (void *)(p); p += ROUNDUP(n)
int
rpcM2S(void *ap, Rpccall *r, int n)
{
int k;
uchar *p;
Udphdr *up;
/* copy IPv4 header fields from Udphdr */
up = ap;
p = &up->raddr[IPaddrlen - IPv4addrlen];
LONG(host);
USED(p);
p = &up->laddr[IPaddrlen - IPv4addrlen];
LONG(lhost);
USED(p);
/* ignore up->ifcaddr */
p = up->rport;
SHORT(port);
SHORT(lport);
LONG(xid);
LONG(mtype);
switch(r->mtype){
case CALL:
LONG(rpcvers);
if(r->rpcvers != 2)
break;
LONG(prog);
LONG(vers);
LONG(proc);
LONG(cred.flavor);
LONG(cred.count);
PTR(cred.data, r->cred.count);
LONG(verf.flavor);
LONG(verf.count);
PTR(verf.data, r->verf.count);
r->up = 0;
k = n - (p - (uchar *)ap);
if(k < 0)
break;
PTR(args, k);
break;
case REPLY:
LONG(stat);
switch(r->stat){
case MSG_ACCEPTED:
LONG(averf.flavor);
LONG(averf.count);
PTR(averf.data, r->averf.count);
LONG(astat);
switch(r->astat){
case SUCCESS:
k = n - (p - (uchar *)ap);
if(k < 0)
break;
PTR(results, k);
break;
case PROG_MISMATCH:
LONG(plow);
LONG(phigh);
break;
}
break;
case MSG_DENIED:
LONG(rstat);
switch(r->rstat){
case RPC_MISMATCH:
LONG(rlow);
LONG(rhigh);
break;
case AUTH_ERROR:
LONG(authstat);
break;
}
break;
}
break;
}
n -= p - (uchar *)ap;
return n;
}
int
auth2unix(Auth *arg, Authunix *r)
{
int i, n;
uchar *p;
if(arg->flavor != AUTH_UNIX)
return -1;
p = arg->data;
LONG(stamp);
LONG(mach.n);
PTR(mach.s, r->mach.n);
LONG(uid);
LONG(gid);
LONG(gidlen);
n = r->gidlen;
for(i=0; i<n && i < nelem(r->gids); i++){
LONG(gids[i]);
}
for(; i<n; i++){
SKIPLONG;
}
return arg->count - (p - (uchar *)arg->data);
}
int
string2S(void *arg, String *r)
{
uchar *p;
char *s;
p = arg;
LONG(n);
PTR(s, r->n);
/* must NUL terminate */
s = malloc(r->n+1);
if(s == nil)
panic("malloc(%ld) failed in string2S\n", r->n+1);
memmove(s, r->s, r->n);
s[r->n] = '\0';
r->s = strstore(s);
free(s);
return p - (uchar *)arg;
}
#undef SHORT
#undef LONG
#undef PTR
#define SHORT(x) p[1] = r->x; p[0] = r->x>>8; p += 2
#define LONG(x) p[3] = r->x; p[2] = r->x>>8; p[1] = r->x>>16; p[0] = r->x>>24; p += 4
#define PTR(x,n) memmove(p, r->x, n); p += ROUNDUP(n)
int
rpcS2M(Rpccall *r, int ndata, void *ap)
{
uchar *p;
Udphdr *up;
/* copy header fields to Udphdr */
up = ap;
memmove(up->raddr, v4prefix, IPaddrlen);
p = &up->raddr[IPaddrlen - IPv4addrlen];
LONG(host);
USED(p);
memmove(up->laddr, v4prefix, IPaddrlen);
p = &up->laddr[IPaddrlen - IPv4addrlen];
LONG(lhost);
USED(p);
memmove(up->ifcaddr, IPnoaddr, sizeof up->ifcaddr);
p = up->rport;
SHORT(port);
SHORT(lport);
LONG(xid);
LONG(mtype);
switch(r->mtype){
case CALL:
LONG(rpcvers);
LONG(prog);
LONG(vers);
LONG(proc);
LONG(cred.flavor);
LONG(cred.count);
PTR(cred.data, r->cred.count);
LONG(verf.flavor);
LONG(verf.count);
PTR(verf.data, r->verf.count);
PTR(args, ndata);
break;
case REPLY:
LONG(stat);
switch(r->stat){
case MSG_ACCEPTED:
LONG(averf.flavor);
LONG(averf.count);
PTR(averf.data, r->averf.count);
LONG(astat);
switch(r->astat){
case SUCCESS:
PTR(results, ndata);
break;
case PROG_MISMATCH:
LONG(plow);
LONG(phigh);
break;
}
break;
case MSG_DENIED:
LONG(rstat);
switch(r->rstat){
case RPC_MISMATCH:
LONG(rlow);
LONG(rhigh);
break;
case AUTH_ERROR:
LONG(authstat);
break;
}
break;
}
break;
}
return p - (uchar *)ap;
}
#undef SHORT
#undef LONG
#undef PTR
#define LONG(m, x) fprint(fd, "%s = %ld\n", m, r->x)
#define PTR(m, count) fprint(fd, "%s [%ld]\n", m, count)
void
rpcprint(int fd, Rpccall *r)
{
fprint(fd, "%s: host = %I, port = %ld\n",
argv0, r->host, r->port);
LONG("xid", xid);
LONG("mtype", mtype);
switch(r->mtype){
case CALL:
LONG("rpcvers", rpcvers);
LONG("prog", prog);
LONG("vers", vers);
LONG("proc", proc);
LONG("cred.flavor", cred.flavor);
PTR("cred.data", r->cred.count);
LONG("verf.flavor", verf.flavor);
PTR("verf.data", r->verf.count);
fprint(fd, "args...\n");
break;
case REPLY:
LONG("stat", stat);
switch(r->stat){
case MSG_ACCEPTED:
LONG("averf.flavor", averf.flavor);
PTR("averf.data", r->averf.count);
LONG("astat", astat);
switch(r->astat){
case SUCCESS:
fprint(fd, "results...\n");
break;
case PROG_MISMATCH:
LONG("plow", plow);
LONG("phigh", phigh);
break;
}
break;
case MSG_DENIED:
LONG("rstat", rstat);
switch(r->rstat){
case RPC_MISMATCH:
LONG("rlow", rlow);
LONG("rhigh", rhigh);
break;
case AUTH_ERROR:
LONG("authstat", authstat);
break;
}
break;
}
}
}
void
showauth(Auth *ap)
{
Authunix au;
int i;
if(auth2unix(ap, &au) != 0){
chat("auth flavor=%ld, count=%ld",
ap->flavor, ap->count);
for(i=0; i<ap->count; i++)
chat(" %.2ux", ((uchar *)ap->data)[i]);
}else{
chat("auth: %ld %.*s u=%ld g=%ld",
au.stamp, utfnlen(au.mach.s, au.mach.n), au.mach.s, au.uid, au.gid);
for(i=0; i<au.gidlen; i++)
chat(", %ld", au.gids[i]);
}
chat("...");
}
int
garbage(Rpccall *reply, char *msg)
{
chat("%s\n", msg ? msg : "garbage");
reply->astat = GARBAGE_ARGS;
return 0;
}
int
error(Rpccall *reply, int errno)
{
uchar *dataptr = reply->results;
chat("error %d\n", errno);
PLONG(errno);
return dataptr - (uchar *)reply->results;
}