xref: /plan9/sys/src/libsunrpc/rpc.c (revision 34e0422554c8e8bef66509534d2c44f4660bf678)
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
sunRpcPack(uchar * a,uchar * ea,uchar ** pa,SunRpc * rpc)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 		default:
72 			if(sunUint32Pack(a, ea, &a, (x=MsgDenied, &x)) < 0)
73 				goto Err;
74 			break;
75 		}
76 
77 		switch(rpc->status){
78 		case SunSuccess:
79 			if(sunUint32Pack(a, ea, &a, (x=MsgSuccess, &x)) < 0
80 			|| sunFixedOpaquePack(a, ea, &a, rpc->data, rpc->ndata) < 0)
81 				goto Err;
82 			break;
83 		case SunRpcMismatch:
84 		case SunProgMismatch:
85 			if(sunUint32Pack(a, ea, &a, (x=rpc->status&0xFFFF, &x)) < 0
86 			|| sunUint32Pack(a, ea, &a, &rpc->low) < 0
87 			|| sunUint32Pack(a, ea, &a, &rpc->high) < 0)
88 				goto Err;
89 			break;
90 		default:
91 			if(sunUint32Pack(a, ea, &a, (x=rpc->status&0xFFFF, &x)) < 0)
92 				goto Err;
93 			break;
94 		}
95 	}
96 	*pa = a;
97 	return SunSuccess;
98 
99 Err:
100 	*pa = ea;
101 	return SunGarbageArgs;
102 }
103 
104 uint
sunRpcSize(SunRpc * rpc)105 sunRpcSize(SunRpc *rpc)
106 {
107 	uint a;
108 
109 	a = 4;
110 	if(rpc->iscall){
111 		a += 5*4;
112 		a += sunAuthInfoSize(&rpc->cred);
113 		a += sunAuthInfoSize(&rpc->verf);
114 		a += sunFixedOpaqueSize(rpc->ndata);
115 	}else{
116 		a += 4;
117 		switch(rpc->status&0xF0000){
118 		case 0:
119 		case SunAcceptError:
120 			a += 4+sunAuthInfoSize(&rpc->verf);
121 			break;
122 		default:
123 			a += 4;
124 			break;
125 		}
126 
127 		switch(rpc->status){
128 		case SunSuccess:
129 			a += 4+sunFixedOpaqueSize(rpc->ndata);
130 			break;
131 		case SunRpcMismatch:
132 		case SunProgMismatch:
133 			a += 3*4;
134 		default:
135 			a += 4;
136 		}
137 	}
138 	return a;
139 }
140 
141 SunStatus
sunRpcUnpack(uchar * a,uchar * ea,uchar ** pa,SunRpc * rpc)142 sunRpcUnpack(uchar *a, uchar *ea, uchar **pa, SunRpc *rpc)
143 {
144 	u32int x;
145 
146 	memset(rpc, 0, sizeof *rpc);
147 	if(sunUint32Unpack(a, ea, &a, &rpc->xid) < 0
148 	|| sunUint32Unpack(a, ea, &a, &x) < 0)
149 		goto Err;
150 
151 	switch(x){
152 	default:
153 		goto Err;
154 	case MsgCall:
155 		rpc->iscall = 1;
156 		if(sunUint32Unpack(a, ea, &a, &x) < 0 || x != RpcVersion
157 		|| sunUint32Unpack(a, ea, &a, &rpc->prog) < 0
158 		|| sunUint32Unpack(a, ea, &a, &rpc->vers) < 0
159 		|| sunUint32Unpack(a, ea, &a, &rpc->proc) < 0
160 		|| sunAuthInfoUnpack(a, ea, &a, &rpc->cred) < 0
161 		|| sunAuthInfoUnpack(a, ea, &a, &rpc->verf) < 0)
162 			goto Err;
163 		rpc->ndata = ea-a;
164 		rpc->data = a;
165 		a = ea;
166 		break;
167 
168 	case MsgReply:
169 		rpc->iscall = 0;
170 		if(sunUint32Unpack(a, ea, &a, &x) < 0)
171 			goto Err;
172 		switch(x){
173 		default:
174 			goto Err;
175 		case MsgAccepted:
176 			if(sunAuthInfoUnpack(a, ea, &a, &rpc->verf) < 0
177 			|| sunUint32Unpack(a, ea, &a, &x) < 0)
178 				goto Err;
179 			switch(x){
180 			case MsgSuccess:
181 				rpc->status = SunSuccess;
182 				rpc->ndata = ea-a;
183 				rpc->data = a;
184 				a = ea;
185 				break;
186 			case MsgProgUnavail:
187 			case MsgProcUnavail:
188 			case MsgGarbageArgs:
189 			case MsgSystemErr:
190 				rpc->status = SunAcceptError | x;
191 				break;
192 			case MsgProgMismatch:
193 				rpc->status = SunAcceptError | x;
194 				if(sunUint32Unpack(a, ea, &a, &rpc->low) < 0
195 				|| sunUint32Unpack(a, ea, &a, &rpc->high) < 0)
196 					goto Err;
197 				break;
198 			}
199 			break;
200 		case MsgDenied:
201 			if(sunUint32Unpack(a, ea, &a, &x) < 0)
202 				goto Err;
203 			switch(x){
204 			default:
205 				goto Err;
206 			case MsgAuthError:
207 				if(sunUint32Unpack(a, ea, &a, &x) < 0)
208 					goto Err;
209 				rpc->status = SunAuthError | x;
210 				break;
211 			case MsgRpcMismatch:
212 				rpc->status = SunRejectError | x;
213 				if(sunUint32Unpack(a, ea, &a, &rpc->low) < 0
214 				|| sunUint32Unpack(a, ea, &a, &rpc->high) < 0)
215 					goto Err;
216 				break;
217 			}
218 			break;
219 		}
220 	}
221 	*pa = a;
222 	return SunSuccess;
223 
224 Err:
225 	*pa = ea;
226 	return SunGarbageArgs;
227 }
228 
229 void
sunRpcPrint(Fmt * fmt,SunRpc * rpc)230 sunRpcPrint(Fmt *fmt, SunRpc *rpc)
231 {
232 	fmtprint(fmt, "xid=%#ux", rpc->xid);
233 	if(rpc->iscall){
234 		fmtprint(fmt, " prog %#ux vers %#ux proc %#ux [", rpc->prog, rpc->vers, rpc->proc);
235 		sunAuthInfoPrint(fmt, &rpc->cred);
236 		fmtprint(fmt, "] [");
237 		sunAuthInfoPrint(fmt, &rpc->verf);
238 		fmtprint(fmt, "]");
239 	}else{
240 		fmtprint(fmt, " status %#ux [", rpc->status);
241 		sunAuthInfoPrint(fmt, &rpc->verf);
242 		fmtprint(fmt, "] low %#ux high %#ux", rpc->low, rpc->high);
243 	}
244 }
245 
246 void
sunAuthInfoPrint(Fmt * fmt,SunAuthInfo * ai)247 sunAuthInfoPrint(Fmt *fmt, SunAuthInfo *ai)
248 {
249 	switch(ai->flavor){
250 	case SunAuthNone:
251 		fmtprint(fmt, "none");
252 		break;
253 	case SunAuthShort:
254 		fmtprint(fmt, "short");
255 		break;
256 	case SunAuthSys:
257 		fmtprint(fmt, "sys");
258 		break;
259 	default:
260 		fmtprint(fmt, "%#ux", ai->flavor);
261 		break;
262 	}
263 //	if(ai->ndata)
264 //		fmtprint(fmt, " %.*H", ai->ndata, ai->data);
265 }
266 
267 uint
sunAuthInfoSize(SunAuthInfo * ai)268 sunAuthInfoSize(SunAuthInfo *ai)
269 {
270 	return 4 + sunVarOpaqueSize(ai->ndata);
271 }
272 
273 int
sunAuthInfoPack(uchar * a,uchar * ea,uchar ** pa,SunAuthInfo * ai)274 sunAuthInfoPack(uchar *a, uchar *ea, uchar **pa, SunAuthInfo *ai)
275 {
276 	if(sunUint32Pack(a, ea, &a, &ai->flavor) < 0
277 	|| sunVarOpaquePack(a, ea, &a, &ai->data, &ai->ndata, 400) < 0)
278 		goto Err;
279 	*pa = a;
280 	return 0;
281 
282 Err:
283 	*pa = ea;
284 	return -1;
285 }
286 
287 int
sunAuthInfoUnpack(uchar * a,uchar * ea,uchar ** pa,SunAuthInfo * ai)288 sunAuthInfoUnpack(uchar *a, uchar *ea, uchar **pa, SunAuthInfo *ai)
289 {
290 	if(sunUint32Unpack(a, ea, &a, &ai->flavor) < 0
291 	|| sunVarOpaqueUnpack(a, ea, &a, &ai->data, &ai->ndata, 400) < 0)
292 		goto Err;
293 	*pa = a;
294 	return 0;
295 
296 Err:
297 	*pa = ea;
298 	return -1;
299 }
300 
301 int
sunEnumPack(uchar * a,uchar * ea,uchar ** pa,int * e)302 sunEnumPack(uchar *a, uchar *ea, uchar **pa, int *e)
303 {
304 	u32int x;
305 
306 	x = *e;
307 	return sunUint32Pack(a, ea, pa, &x);
308 }
309 
310 int
sunUint1Pack(uchar * a,uchar * ea,uchar ** pa,u1int * u)311 sunUint1Pack(uchar *a, uchar *ea, uchar **pa, u1int *u)
312 {
313 	u32int x;
314 
315 	x = *u;
316 	return sunUint32Pack(a, ea, pa, &x);
317 }
318 
319 int
sunUint32Pack(uchar * a,uchar * ea,uchar ** pa,u32int * u)320 sunUint32Pack(uchar *a, uchar *ea, uchar **pa, u32int *u)
321 {
322 	u32int x;
323 
324 	if(ea-a < 4)
325 		goto Err;
326 
327 	x = *u;
328 	*a++ = x>>24;
329 	*a++ = x>>16;
330 	*a++ = x>>8;
331 	*a++ = x;
332 	*pa = a;
333 	return 0;
334 
335 Err:
336 	*pa = ea;
337 	return -1;
338 }
339 
340 int
sunEnumUnpack(uchar * a,uchar * ea,uchar ** pa,int * e)341 sunEnumUnpack(uchar *a, uchar *ea, uchar **pa, int *e)
342 {
343 	u32int x;
344 	if(sunUint32Unpack(a, ea, pa, &x) < 0)
345 		return -1;
346 	*e = x;
347 	return 0;
348 }
349 
350 int
sunUint1Unpack(uchar * a,uchar * ea,uchar ** pa,u1int * u)351 sunUint1Unpack(uchar *a, uchar *ea, uchar **pa, u1int *u)
352 {
353 	u32int x;
354 	if(sunUint32Unpack(a, ea, pa, &x) < 0 || (x!=0 && x!=1)){
355 		*pa = ea;
356 		return -1;
357 	}
358 	*u = x;
359 	return 0;
360 }
361 
362 int
sunUint32Unpack(uchar * a,uchar * ea,uchar ** pa,u32int * u)363 sunUint32Unpack(uchar *a, uchar *ea, uchar **pa, u32int *u)
364 {
365 	u32int x;
366 
367 	if(ea-a < 4)
368 		goto Err;
369 	x = *a++ << 24;
370 	x |= *a++ << 16;
371 	x |= *a++ << 8;
372 	x |= *a++;
373 	*pa = a;
374 	*u = x;
375 	return 0;
376 
377 Err:
378 	*pa = ea;
379 	return -1;
380 }
381 
382 int
sunUint64Unpack(uchar * a,uchar * ea,uchar ** pa,u64int * u)383 sunUint64Unpack(uchar *a, uchar *ea, uchar **pa, u64int *u)
384 {
385 	u32int x, y;
386 
387 	if(sunUint32Unpack(a, ea, &a, &x) < 0
388 	|| sunUint32Unpack(a, ea, &a, &y) < 0)
389 		goto Err;
390 	*u = ((uvlong)x<<32) | y;
391 	*pa = a;
392 	return 0;
393 Err:
394 	*pa = ea;
395 	return -1;
396 }
397 
398 int
sunUint64Pack(uchar * a,uchar * ea,uchar ** pa,u64int * u)399 sunUint64Pack(uchar *a, uchar *ea, uchar **pa, u64int *u)
400 {
401 	u32int x, y;
402 
403 	x = *u >> 32;
404 	y = *u;
405 	if(sunUint32Pack(a, ea, &a, &x) < 0
406 	|| sunUint32Pack(a, ea, &a, &y) < 0)
407 		goto Err;
408 	*pa = a;
409 	return 0;
410 Err:
411 	*pa = ea;
412 	return -1;
413 }
414 
415 uint
sunStringSize(char * s)416 sunStringSize(char *s)
417 {
418 	return (4+strlen(s)+3) & ~3;
419 }
420 
421 int
sunStringUnpack(uchar * a,uchar * ea,uchar ** pa,char ** s,u32int max)422 sunStringUnpack(uchar *a, uchar *ea, uchar **pa, char **s, u32int max)
423 {
424 	uchar *dat;
425 	u32int n;
426 
427 	if(sunVarOpaqueUnpack(a, ea, pa, &dat, &n, max) < 0)
428 		goto Err;
429 	/* slide string down over length to make room for NUL */
430 	memmove(dat-1, dat, n);
431 	dat[-1+n] = 0;
432 	*s = (char*)(dat-1);
433 	return 0;
434 Err:
435 	return -1;
436 }
437 
438 int
sunStringPack(uchar * a,uchar * ea,uchar ** pa,char ** s,u32int max)439 sunStringPack(uchar *a, uchar *ea, uchar **pa, char **s, u32int max)
440 {
441 	u32int n;
442 
443 	n = strlen(*s);
444 	return sunVarOpaquePack(a, ea, pa, (uchar**)s, &n, max);
445 }
446 
447 uint
sunVarOpaqueSize(u32int n)448 sunVarOpaqueSize(u32int n)
449 {
450 	return (4+n+3) & ~3;
451 }
452 
453 int
sunVarOpaquePack(uchar * a,uchar * ea,uchar ** pa,uchar ** dat,u32int * ndat,u32int max)454 sunVarOpaquePack(uchar *a, uchar *ea, uchar **pa, uchar **dat, u32int *ndat, u32int max)
455 {
456 	if(*ndat > max || sunUint32Pack(a, ea, &a, ndat) < 0
457 	|| sunFixedOpaquePack(a, ea, &a, *dat, *ndat) < 0)
458 		goto Err;
459 	*pa = a;
460 	return 0;
461 
462 Err:
463 	*pa = ea;
464 	return -1;
465 }
466 
467 int
sunVarOpaqueUnpack(uchar * a,uchar * ea,uchar ** pa,uchar ** dat,u32int * ndat,u32int max)468 sunVarOpaqueUnpack(uchar *a, uchar *ea, uchar **pa, uchar **dat, u32int *ndat, u32int max)
469 {
470 	if(sunUint32Unpack(a, ea, &a, ndat) < 0
471 	|| *ndat > max)
472 		goto Err;
473 	*dat = a;
474 	a += (*ndat+3)&~3;
475 	if(a > ea)
476 		goto Err;
477 	*pa = a;
478 	return 0;
479 
480 Err:
481 	*pa = ea;
482 	return -1;
483 }
484 
485 uint
sunFixedOpaqueSize(u32int n)486 sunFixedOpaqueSize(u32int n)
487 {
488 	return (n+3) & ~3;
489 }
490 
491 int
sunFixedOpaquePack(uchar * a,uchar * ea,uchar ** pa,uchar * dat,u32int n)492 sunFixedOpaquePack(uchar *a, uchar *ea, uchar **pa, uchar *dat, u32int n)
493 {
494 	uint nn;
495 
496 	nn = (n+3)&~3;
497 	if(a+nn > ea)
498 		goto Err;
499 	memmove(a, dat, n);
500 	if(nn > n)
501 		memset(a+n, 0, nn-n);
502 	a += nn;
503 	*pa = a;
504 	return 0;
505 
506 Err:
507 	*pa = ea;
508 	return -1;
509 }
510 
511 int
sunFixedOpaqueUnpack(uchar * a,uchar * ea,uchar ** pa,uchar * dat,u32int n)512 sunFixedOpaqueUnpack(uchar *a, uchar *ea, uchar **pa, uchar *dat, u32int n)
513 {
514 	uint nn;
515 
516 	nn = (n+3)&~3;
517 	if(a+nn > ea)
518 		goto Err;
519 	memmove(dat, a, n);
520 	a += nn;
521 	*pa = a;
522 	return 0;
523 
524 Err:
525 	*pa = ea;
526 	return -1;
527 }
528 
529