diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/libsunrpc/rpc.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/libsunrpc/rpc.c')
-rwxr-xr-x | sys/src/libsunrpc/rpc.c | 528 |
1 files changed, 528 insertions, 0 deletions
diff --git a/sys/src/libsunrpc/rpc.c b/sys/src/libsunrpc/rpc.c new file mode 100755 index 000000000..657e04233 --- /dev/null +++ b/sys/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; +} + |