/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #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) intrpcM2S(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;} intauth2unix(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);} intstring2S(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) intrpcS2M(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) voidrpcprint(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; } }} voidshowauth(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("...");} intgarbage(Rpccall *reply, char *msg){ chat("%s\n", msg ? msg : "garbage"); reply->astat = GARBAGE_ARGS; return 0;} interror(Rpccall *reply, int errno){ uchar *dataptr = reply->results; chat("error %d\n", errno); PLONG(errno); return dataptr - (uchar *)reply->results;}
/*
* This file is part of the UCB release of Plan 9. It is subject to the license
* terms in the LICENSE file found in the top-level directory of this
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
* part of the UCB release of Plan 9, including this file, may be copied,
* modified, propagated, or distributed except according to the terms contained
* in the LICENSE file.
*/
#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;
}