diff options
author | rsc <devnull@localhost> | 2004-04-21 03:04:30 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2004-04-21 03:04:30 +0000 |
commit | 551445b92c1f11d4f543e96790ff29762ab1ad10 (patch) | |
tree | 5129ea4e5cc91ff823623b080540fedcfaa72786 /src/libsunrpc/rpc.c | |
parent | fa256eecfaf035cd6c46335452357856dc0bd9e9 (diff) | |
download | plan9port-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.c | 528 |
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; +} + |