plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

rpc.c (9502B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <thread.h>
      4 #include <sunrpc.h>
      5 
      6 /*
      7  * RPC protocol constants
      8  */
      9 enum
     10 {
     11 	RpcVersion = 2,
     12 
     13 	/* msg type */
     14 	MsgCall = 0,
     15 	MsgReply = 1,
     16 
     17 	/* reply stat */
     18 	MsgAccepted = 0,
     19 	MsgDenied = 1,
     20 
     21 	/* accept stat */
     22 	MsgSuccess = 0,
     23 	MsgProgUnavail = 1,
     24 	MsgProgMismatch = 2,
     25 	MsgProcUnavail = 3,
     26 	MsgGarbageArgs = 4,
     27 	MsgSystemErr = 5,
     28 
     29 	/* reject stat */
     30 	MsgRpcMismatch = 0,
     31 	MsgAuthError = 1,
     32 
     33 	/* msg auth xxx */
     34 	MsgAuthOk = 0,
     35 	MsgAuthBadCred = 1,
     36 	MsgAuthRejectedCred = 2,
     37 	MsgAuthBadVerf = 3,
     38 	MsgAuthRejectedVerf = 4,
     39 	MsgAuthTooWeak = 5,
     40 	MsgAuthInvalidResp = 6,
     41 	MsgAuthFailed = 7
     42 };
     43 
     44 SunStatus
     45 sunrpcpack(uchar *a, uchar *ea, uchar **pa, SunRpc *rpc)
     46 {
     47 	u32int x;
     48 
     49 	if(sunuint32pack(a, ea, &a, &rpc->xid) < 0)
     50 		goto Err;
     51 	if(rpc->iscall){
     52 		if(sunuint32pack(a, ea, &a, (x=MsgCall, &x)) < 0
     53 		|| sunuint32pack(a, ea, &a, (x=RpcVersion, &x)) < 0
     54 		|| sunuint32pack(a, ea, &a, &rpc->prog) < 0
     55 		|| sunuint32pack(a, ea, &a, &rpc->vers) < 0
     56 		|| sunuint32pack(a, ea, &a, &rpc->proc) < 0
     57 		|| sunauthinfopack(a, ea, &a, &rpc->cred) < 0
     58 		|| sunauthinfopack(a, ea, &a, &rpc->verf) < 0
     59 		|| sunfixedopaquepack(a, ea, &a, rpc->data, rpc->ndata) < 0)
     60 			goto Err;
     61 	}else{
     62 		if(sunuint32pack(a, ea, &a, (x=MsgReply, &x)) < 0)
     63 			goto Err;
     64 		switch(rpc->status&0xF0000){
     65 		case 0:
     66 		case SunAcceptError:
     67 			if(sunuint32pack(a, ea, &a, (x=MsgAccepted, &x)) < 0
     68 			|| sunauthinfopack(a, ea, &a, &rpc->verf) < 0)
     69 				goto Err;
     70 			break;
     71 		case SunAuthError:
     72 			if(sunuint32pack(a, ea, &a, (x=MsgDenied, &x)) < 0
     73 			|| sunuint32pack(a, ea, &a, (x=MsgAuthError, &x)) < 0)
     74 				goto Err;
     75 			break;
     76 		default:
     77 			if(sunuint32pack(a, ea, &a, (x=MsgDenied, &x)) < 0)
     78 				goto Err;
     79 			break;
     80 		}
     81 
     82 		switch(rpc->status){
     83 		case SunSuccess:
     84 			if(sunuint32pack(a, ea, &a, (x=MsgSuccess, &x)) < 0
     85 			|| sunfixedopaquepack(a, ea, &a, rpc->data, rpc->ndata) < 0)
     86 				goto Err;
     87 			break;
     88 		case SunRpcMismatch:
     89 		case SunProgMismatch:
     90 			if(sunuint32pack(a, ea, &a, (x=rpc->status&0xFFFF, &x)) < 0
     91 			|| sunuint32pack(a, ea, &a, &rpc->low) < 0
     92 			|| sunuint32pack(a, ea, &a, &rpc->high) < 0)
     93 				goto Err;
     94 			break;
     95 		default:
     96 			if(sunuint32pack(a, ea, &a, (x=rpc->status&0xFFFF, &x)) < 0)
     97 				goto Err;
     98 
     99 			break;
    100 		}
    101 	}
    102 	*pa = a;
    103 	return SunSuccess;
    104 
    105 Err:
    106 	*pa = ea;
    107 	return SunGarbageArgs;
    108 }
    109 
    110 uint
    111 sunrpcsize(SunRpc *rpc)
    112 {
    113 	uint a;
    114 
    115 	a = 4;
    116 	if(rpc->iscall){
    117 		a += 5*4;
    118 		a += sunauthinfosize(&rpc->cred);
    119 		a += sunauthinfosize(&rpc->verf);
    120 		a += sunfixedopaquesize(rpc->ndata);
    121 	}else{
    122 		a += 4;
    123 		switch(rpc->status&0xF0000){
    124 		case 0:
    125 		case SunAcceptError:
    126 			a += 4+sunauthinfosize(&rpc->verf);
    127 			break;
    128 		case SunAuthError:
    129 			a += 4+4;
    130 			break;
    131 		default:
    132 			a += 4;
    133 			break;
    134 		}
    135 
    136 		switch(rpc->status){
    137 		case SunSuccess:
    138 			a += 4+sunfixedopaquesize(rpc->ndata);
    139 			break;
    140 		case SunRpcMismatch:
    141 		case SunProgMismatch:
    142 			a += 3*4;
    143 			break;
    144 		default:
    145 			a += 4;
    146 		}
    147 	}
    148 	return a;
    149 }
    150 
    151 SunStatus
    152 sunrpcunpack(uchar *a, uchar *ea, uchar **pa, SunRpc *rpc)
    153 {
    154 	u32int x;
    155 
    156 	memset(rpc, 0, sizeof *rpc);
    157 	if(sunuint32unpack(a, ea, &a, &rpc->xid) < 0
    158 	|| sunuint32unpack(a, ea, &a, &x) < 0)
    159 		goto Err;
    160 
    161 	switch(x){
    162 	default:
    163 		goto Err;
    164 	case MsgCall:
    165 		rpc->iscall = 1;
    166 		if(sunuint32unpack(a, ea, &a, &x) < 0 || x != RpcVersion
    167 		|| sunuint32unpack(a, ea, &a, &rpc->prog) < 0
    168 		|| sunuint32unpack(a, ea, &a, &rpc->vers) < 0
    169 		|| sunuint32unpack(a, ea, &a, &rpc->proc) < 0
    170 		|| sunauthinfounpack(a, ea, &a, &rpc->cred) < 0
    171 		|| sunauthinfounpack(a, ea, &a, &rpc->verf) < 0)
    172 			goto Err;
    173 		rpc->ndata = ea-a;
    174 		rpc->data = a;
    175 		a = ea;
    176 		break;
    177 
    178 	case MsgReply:
    179 		rpc->iscall = 0;
    180 		if(sunuint32unpack(a, ea, &a, &x) < 0)
    181 			goto Err;
    182 fprint(2, "x %x\n", x);
    183 		switch(x){
    184 		default:
    185 			goto Err;
    186 		case MsgAccepted:
    187 			if(sunauthinfounpack(a, ea, &a, &rpc->verf) < 0
    188 			|| sunuint32unpack(a, ea, &a, &x) < 0)
    189 				goto Err;
    190 			switch(x){
    191 			case MsgSuccess:
    192 				rpc->status = SunSuccess;
    193 				rpc->ndata = ea-a;
    194 				rpc->data = a;
    195 				a = ea;
    196 				break;
    197 			case MsgProgUnavail:
    198 			case MsgProcUnavail:
    199 			case MsgGarbageArgs:
    200 			case MsgSystemErr:
    201 				rpc->status = SunAcceptError | x;
    202 				break;
    203 			case MsgProgMismatch:
    204 				rpc->status = SunAcceptError | x;
    205 				if(sunuint32unpack(a, ea, &a, &rpc->low) < 0
    206 				|| sunuint32unpack(a, ea, &a, &rpc->high) < 0)
    207 					goto Err;
    208 				break;
    209 			}
    210 			break;
    211 		case MsgDenied:
    212 			if(sunuint32unpack(a, ea, &a, &x) < 0)
    213 				goto Err;
    214 fprint(2, "xx %ux\n", x);
    215 			switch(x){
    216 			default:
    217 				goto Err;
    218 			case MsgAuthError:
    219 				if(sunuint32unpack(a, ea, &a, &x) < 0)
    220 					goto Err;
    221 				rpc->status = SunAuthError | x;
    222 				break;
    223 			case MsgRpcMismatch:
    224 				rpc->status = SunRejectError | x;
    225 				if(sunuint32unpack(a, ea, &a, &rpc->low) < 0
    226 				|| sunuint32unpack(a, ea, &a, &rpc->high) < 0)
    227 					goto Err;
    228 				break;
    229 			}
    230 			break;
    231 		}
    232 	}
    233 	*pa = a;
    234 	return SunSuccess;
    235 
    236 Err:
    237 	*pa = ea;
    238 	return SunGarbageArgs;
    239 }
    240 
    241 void
    242 sunrpcprint(Fmt *fmt, SunRpc *rpc)
    243 {
    244 	fmtprint(fmt, "xid=%#ux", rpc->xid);
    245 	if(rpc->iscall){
    246 		fmtprint(fmt, " prog %#ux vers %#ux proc %#ux [", rpc->prog, rpc->vers, rpc->proc);
    247 		sunauthinfoprint(fmt, &rpc->cred);
    248 		fmtprint(fmt, "] [");
    249 		sunauthinfoprint(fmt, &rpc->verf);
    250 		fmtprint(fmt, "]");
    251 	}else{
    252 		fmtprint(fmt, " status %#ux [", rpc->status);
    253 		sunauthinfoprint(fmt, &rpc->verf);
    254 		fmtprint(fmt, "] low %#ux high %#ux", rpc->low, rpc->high);
    255 	}
    256 }
    257 
    258 void
    259 sunauthinfoprint(Fmt *fmt, SunAuthInfo *ai)
    260 {
    261 	switch(ai->flavor){
    262 	case SunAuthNone:
    263 		fmtprint(fmt, "none");
    264 		break;
    265 	case SunAuthShort:
    266 		fmtprint(fmt, "short");
    267 		break;
    268 	case SunAuthSys:
    269 		fmtprint(fmt, "sys");
    270 		break;
    271 	default:
    272 		fmtprint(fmt, "%#ux", ai->flavor);
    273 		break;
    274 	}
    275 /*	if(ai->ndata) */
    276 /*		fmtprint(fmt, " %.*H", ai->ndata, ai->data); */
    277 }
    278 
    279 uint
    280 sunauthinfosize(SunAuthInfo *ai)
    281 {
    282 	return 4 + sunvaropaquesize(ai->ndata);
    283 }
    284 
    285 int
    286 sunauthinfopack(uchar *a, uchar *ea, uchar **pa, SunAuthInfo *ai)
    287 {
    288 	if(sunuint32pack(a, ea, &a, &ai->flavor) < 0
    289 	|| sunvaropaquepack(a, ea, &a, &ai->data, &ai->ndata, 400) < 0)
    290 		goto Err;
    291 	*pa = a;
    292 	return 0;
    293 
    294 Err:
    295 	*pa = ea;
    296 	return -1;
    297 }
    298 
    299 int
    300 sunauthinfounpack(uchar *a, uchar *ea, uchar **pa, SunAuthInfo *ai)
    301 {
    302 	if(sunuint32unpack(a, ea, &a, &ai->flavor) < 0
    303 	|| sunvaropaqueunpack(a, ea, &a, &ai->data, &ai->ndata, 400) < 0)
    304 		goto Err;
    305 	*pa = a;
    306 	return 0;
    307 
    308 Err:
    309 	*pa = ea;
    310 	return -1;
    311 }
    312 
    313 int
    314 sunenumpack(uchar *a, uchar *ea, uchar **pa, int *e)
    315 {
    316 	u32int x;
    317 
    318 	x = *e;
    319 	return sunuint32pack(a, ea, pa, &x);
    320 }
    321 
    322 int
    323 sunuint1pack(uchar *a, uchar *ea, uchar **pa, u1int *u)
    324 {
    325 	u32int x;
    326 
    327 	x = *u;
    328 	return sunuint32pack(a, ea, pa, &x);
    329 }
    330 
    331 int
    332 sunuint32pack(uchar *a, uchar *ea, uchar **pa, u32int *u)
    333 {
    334 	u32int x;
    335 
    336 	if(ea-a < 4)
    337 		goto Err;
    338 
    339 	x = *u;
    340 	*a++ = x>>24;
    341 	*a++ = x>>16;
    342 	*a++ = x>>8;
    343 	*a++ = x;
    344 	*pa = a;
    345 	return 0;
    346 
    347 Err:
    348 	*pa = ea;
    349 	return -1;
    350 }
    351 
    352 int
    353 sunenumunpack(uchar *a, uchar *ea, uchar **pa, int *e)
    354 {
    355 	u32int x;
    356 	if(sunuint32unpack(a, ea, pa, &x) < 0)
    357 		return -1;
    358 	*e = x;
    359 	return 0;
    360 }
    361 
    362 int
    363 sunuint1unpack(uchar *a, uchar *ea, uchar **pa, u1int *u)
    364 {
    365 	u32int x;
    366 	if(sunuint32unpack(a, ea, pa, &x) < 0 || (x!=0 && x!=1)){
    367 		*pa = ea;
    368 		return -1;
    369 	}
    370 	*u = x;
    371 	return 0;
    372 }
    373 
    374 int
    375 sunuint32unpack(uchar *a, uchar *ea, uchar **pa, u32int *u)
    376 {
    377 	u32int x;
    378 
    379 	if(ea-a < 4)
    380 		goto Err;
    381 	x = *a++ << 24;
    382 	x |= *a++ << 16;
    383 	x |= *a++ << 8;
    384 	x |= *a++;
    385 	*pa = a;
    386 	*u = x;
    387 	return 0;
    388 
    389 Err:
    390 	*pa = ea;
    391 	return -1;
    392 }
    393 
    394 int
    395 sunuint64unpack(uchar *a, uchar *ea, uchar **pa, u64int *u)
    396 {
    397 	u32int x, y;
    398 
    399 	if(sunuint32unpack(a, ea, &a, &x) < 0
    400 	|| sunuint32unpack(a, ea, &a, &y) < 0)
    401 		goto Err;
    402 	*u = ((uvlong)x<<32) | y;
    403 	*pa = a;
    404 	return 0;
    405 Err:
    406 	*pa = ea;
    407 	return -1;
    408 }
    409 
    410 int
    411 sunuint64pack(uchar *a, uchar *ea, uchar **pa, u64int *u)
    412 {
    413 	u32int x, y;
    414 
    415 	x = *u >> 32;
    416 	y = *u;
    417 	if(sunuint32pack(a, ea, &a, &x) < 0
    418 	|| sunuint32pack(a, ea, &a, &y) < 0)
    419 		goto Err;
    420 	*pa = a;
    421 	return 0;
    422 Err:
    423 	*pa = ea;
    424 	return -1;
    425 }
    426 
    427 uint
    428 sunstringsize(char *s)
    429 {
    430 	return (4+strlen(s)+3) & ~3;
    431 }
    432 
    433 int
    434 sunstringunpack(uchar *a, uchar *ea, uchar **pa, char **s, u32int max)
    435 {
    436 	uchar *dat;
    437 	u32int n;
    438 
    439 	if(sunvaropaqueunpack(a, ea, pa, &dat, &n, max) < 0)
    440 		goto Err;
    441 	/* slide string down over length to make room for NUL */
    442 	dat--;
    443 	memmove(dat, dat+1, n);
    444 	dat[n] = 0;
    445 	*s = (char*)dat;
    446 	return 0;
    447 Err:
    448 	return -1;
    449 }
    450 
    451 int
    452 sunstringpack(uchar *a, uchar *ea, uchar **pa, char **s, u32int max)
    453 {
    454 	u32int n;
    455 
    456 	n = strlen(*s);
    457 	return sunvaropaquepack(a, ea, pa, (uchar**)s, &n, max);
    458 }
    459 
    460 uint
    461 sunvaropaquesize(u32int n)
    462 {
    463 	return (4+n+3) & ~3;
    464 }
    465 
    466 int
    467 sunvaropaquepack(uchar *a, uchar *ea, uchar **pa, uchar **dat, u32int *ndat, u32int max)
    468 {
    469 	if(*ndat > max || sunuint32pack(a, ea, &a, ndat) < 0
    470 	|| sunfixedopaquepack(a, ea, &a, *dat, *ndat) < 0)
    471 		goto Err;
    472 	*pa = a;
    473 	return 0;
    474 
    475 Err:
    476 	*pa = ea;
    477 	return -1;
    478 }
    479 
    480 int
    481 sunvaropaqueunpack(uchar *a, uchar *ea, uchar **pa, uchar **dat, u32int *ndat, u32int max)
    482 {
    483 	if(sunuint32unpack(a, ea, &a, ndat) < 0
    484 	|| *ndat > max)
    485 		goto Err;
    486 	*dat = a;
    487 	a += (*ndat+3)&~3;
    488 	if(a > ea)
    489 		goto Err;
    490 	*pa = a;
    491 	return 0;
    492 
    493 Err:
    494 	*pa = ea;
    495 	return -1;
    496 }
    497 
    498 uint
    499 sunfixedopaquesize(u32int n)
    500 {
    501 	return (n+3) & ~3;
    502 }
    503 
    504 int
    505 sunfixedopaquepack(uchar *a, uchar *ea, uchar **pa, uchar *dat, u32int n)
    506 {
    507 	uint nn;
    508 
    509 	nn = (n+3)&~3;
    510 	if(a+nn > ea)
    511 		goto Err;
    512 	memmove(a, dat, n);
    513 	if(nn > n)
    514 		memset(a+n, 0, nn-n);
    515 	a += nn;
    516 	*pa = a;
    517 	return 0;
    518 
    519 Err:
    520 	*pa = ea;
    521 	return -1;
    522 }
    523 
    524 int
    525 sunfixedopaqueunpack(uchar *a, uchar *ea, uchar **pa, uchar *dat, u32int n)
    526 {
    527 	uint nn;
    528 
    529 	nn = (n+3)&~3;
    530 	if(a+nn > ea)
    531 		goto Err;
    532 	memmove(dat, a, n);
    533 	a += nn;
    534 	*pa = a;
    535 	return 0;
    536 
    537 Err:
    538 	*pa = ea;
    539 	return -1;
    540 }