aboutsummaryrefslogtreecommitdiff
path: root/src/libsunrpc/rpc.c
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2004-04-21 03:04:30 +0000
committerrsc <devnull@localhost>2004-04-21 03:04:30 +0000
commit551445b92c1f11d4f543e96790ff29762ab1ad10 (patch)
tree5129ea4e5cc91ff823623b080540fedcfaa72786 /src/libsunrpc/rpc.c
parentfa256eecfaf035cd6c46335452357856dc0bd9e9 (diff)
downloadplan9port-551445b92c1f11d4f543e96790ff29762ab1ad10.tar.gz
plan9port-551445b92c1f11d4f543e96790ff29762ab1ad10.tar.bz2
plan9port-551445b92c1f11d4f543e96790ff29762ab1ad10.zip
Add sunrpc.
Diffstat (limited to 'src/libsunrpc/rpc.c')
-rw-r--r--src/libsunrpc/rpc.c528
1 files changed, 528 insertions, 0 deletions
diff --git a/src/libsunrpc/rpc.c b/src/libsunrpc/rpc.c
new file mode 100644
index 00000000..43835934
--- /dev/null
+++ b/src/libsunrpc/rpc.c
@@ -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;
+}
+