Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <thread.h>
4 #include <sunrpc.h>
6 /*
7 * RPC protocol constants
8 */
9 enum
10 {
11 RpcVersion = 2,
13 /* msg type */
14 MsgCall = 0,
15 MsgReply = 1,
17 /* reply stat */
18 MsgAccepted = 0,
19 MsgDenied = 1,
21 /* accept stat */
22 MsgSuccess = 0,
23 MsgProgUnavail = 1,
24 MsgProgMismatch = 2,
25 MsgProcUnavail = 3,
26 MsgGarbageArgs = 4,
27 MsgSystemErr = 5,
29 /* reject stat */
30 MsgRpcMismatch = 0,
31 MsgAuthError = 1,
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 };
44 SunStatus
45 sunrpcpack(uchar *a, uchar *ea, uchar **pa, SunRpc *rpc)
46 {
47 u32int x;
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 }
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;
99 break;
102 *pa = a;
103 return SunSuccess;
105 Err:
106 *pa = ea;
107 return SunGarbageArgs;
110 uint
111 sunrpcsize(SunRpc *rpc)
113 uint a;
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;
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 default:
144 a += 4;
147 return a;
150 SunStatus
151 sunrpcunpack(uchar *a, uchar *ea, uchar **pa, SunRpc *rpc)
153 u32int x;
155 memset(rpc, 0, sizeof *rpc);
156 if(sunuint32unpack(a, ea, &a, &rpc->xid) < 0
157 || sunuint32unpack(a, ea, &a, &x) < 0)
158 goto Err;
160 switch(x){
161 default:
162 goto Err;
163 case MsgCall:
164 rpc->iscall = 1;
165 if(sunuint32unpack(a, ea, &a, &x) < 0 || x != RpcVersion
166 || sunuint32unpack(a, ea, &a, &rpc->prog) < 0
167 || sunuint32unpack(a, ea, &a, &rpc->vers) < 0
168 || sunuint32unpack(a, ea, &a, &rpc->proc) < 0
169 || sunauthinfounpack(a, ea, &a, &rpc->cred) < 0
170 || sunauthinfounpack(a, ea, &a, &rpc->verf) < 0)
171 goto Err;
172 rpc->ndata = ea-a;
173 rpc->data = a;
174 a = ea;
175 break;
177 case MsgReply:
178 rpc->iscall = 0;
179 if(sunuint32unpack(a, ea, &a, &x) < 0)
180 goto Err;
181 fprint(2, "x %x\n", x);
182 switch(x){
183 default:
184 goto Err;
185 case MsgAccepted:
186 if(sunauthinfounpack(a, ea, &a, &rpc->verf) < 0
187 || sunuint32unpack(a, ea, &a, &x) < 0)
188 goto Err;
189 switch(x){
190 case MsgSuccess:
191 rpc->status = SunSuccess;
192 rpc->ndata = ea-a;
193 rpc->data = a;
194 a = ea;
195 break;
196 case MsgProgUnavail:
197 case MsgProcUnavail:
198 case MsgGarbageArgs:
199 case MsgSystemErr:
200 rpc->status = SunAcceptError | x;
201 break;
202 case MsgProgMismatch:
203 rpc->status = SunAcceptError | x;
204 if(sunuint32unpack(a, ea, &a, &rpc->low) < 0
205 || sunuint32unpack(a, ea, &a, &rpc->high) < 0)
206 goto Err;
207 break;
209 break;
210 case MsgDenied:
211 if(sunuint32unpack(a, ea, &a, &x) < 0)
212 goto Err;
213 fprint(2, "xx %ux\n", x);
214 switch(x){
215 default:
216 goto Err;
217 case MsgAuthError:
218 if(sunuint32unpack(a, ea, &a, &x) < 0)
219 goto Err;
220 rpc->status = SunAuthError | x;
221 break;
222 case MsgRpcMismatch:
223 rpc->status = SunRejectError | x;
224 if(sunuint32unpack(a, ea, &a, &rpc->low) < 0
225 || sunuint32unpack(a, ea, &a, &rpc->high) < 0)
226 goto Err;
227 break;
229 break;
232 *pa = a;
233 return SunSuccess;
235 Err:
236 *pa = ea;
237 return SunGarbageArgs;
240 void
241 sunrpcprint(Fmt *fmt, SunRpc *rpc)
243 fmtprint(fmt, "xid=%#ux", rpc->xid);
244 if(rpc->iscall){
245 fmtprint(fmt, " prog %#ux vers %#ux proc %#ux [", rpc->prog, rpc->vers, rpc->proc);
246 sunauthinfoprint(fmt, &rpc->cred);
247 fmtprint(fmt, "] [");
248 sunauthinfoprint(fmt, &rpc->verf);
249 fmtprint(fmt, "]");
250 }else{
251 fmtprint(fmt, " status %#ux [", rpc->status);
252 sunauthinfoprint(fmt, &rpc->verf);
253 fmtprint(fmt, "] low %#ux high %#ux", rpc->low, rpc->high);
257 void
258 sunauthinfoprint(Fmt *fmt, SunAuthInfo *ai)
260 switch(ai->flavor){
261 case SunAuthNone:
262 fmtprint(fmt, "none");
263 break;
264 case SunAuthShort:
265 fmtprint(fmt, "short");
266 break;
267 case SunAuthSys:
268 fmtprint(fmt, "sys");
269 break;
270 default:
271 fmtprint(fmt, "%#ux", ai->flavor);
272 break;
274 // if(ai->ndata)
275 // fmtprint(fmt, " %.*H", ai->ndata, ai->data);
278 uint
279 sunauthinfosize(SunAuthInfo *ai)
281 return 4 + sunvaropaquesize(ai->ndata);
284 int
285 sunauthinfopack(uchar *a, uchar *ea, uchar **pa, SunAuthInfo *ai)
287 if(sunuint32pack(a, ea, &a, &ai->flavor) < 0
288 || sunvaropaquepack(a, ea, &a, &ai->data, &ai->ndata, 400) < 0)
289 goto Err;
290 *pa = a;
291 return 0;
293 Err:
294 *pa = ea;
295 return -1;
298 int
299 sunauthinfounpack(uchar *a, uchar *ea, uchar **pa, SunAuthInfo *ai)
301 if(sunuint32unpack(a, ea, &a, &ai->flavor) < 0
302 || sunvaropaqueunpack(a, ea, &a, &ai->data, &ai->ndata, 400) < 0)
303 goto Err;
304 *pa = a;
305 return 0;
307 Err:
308 *pa = ea;
309 return -1;
312 int
313 sunenumpack(uchar *a, uchar *ea, uchar **pa, int *e)
315 u32int x;
317 x = *e;
318 return sunuint32pack(a, ea, pa, &x);
321 int
322 sunuint1pack(uchar *a, uchar *ea, uchar **pa, u1int *u)
324 u32int x;
326 x = *u;
327 return sunuint32pack(a, ea, pa, &x);
330 int
331 sunuint32pack(uchar *a, uchar *ea, uchar **pa, u32int *u)
333 u32int x;
335 if(ea-a < 4)
336 goto Err;
338 x = *u;
339 *a++ = x>>24;
340 *a++ = x>>16;
341 *a++ = x>>8;
342 *a++ = x;
343 *pa = a;
344 return 0;
346 Err:
347 *pa = ea;
348 return -1;
351 int
352 sunenumunpack(uchar *a, uchar *ea, uchar **pa, int *e)
354 u32int x;
355 if(sunuint32unpack(a, ea, pa, &x) < 0)
356 return -1;
357 *e = x;
358 return 0;
361 int
362 sunuint1unpack(uchar *a, uchar *ea, uchar **pa, u1int *u)
364 u32int x;
365 if(sunuint32unpack(a, ea, pa, &x) < 0 || (x!=0 && x!=1)){
366 *pa = ea;
367 return -1;
369 *u = x;
370 return 0;
373 int
374 sunuint32unpack(uchar *a, uchar *ea, uchar **pa, u32int *u)
376 u32int x;
378 if(ea-a < 4)
379 goto Err;
380 x = *a++ << 24;
381 x |= *a++ << 16;
382 x |= *a++ << 8;
383 x |= *a++;
384 *pa = a;
385 *u = x;
386 return 0;
388 Err:
389 *pa = ea;
390 return -1;
393 int
394 sunuint64unpack(uchar *a, uchar *ea, uchar **pa, u64int *u)
396 u32int x, y;
398 if(sunuint32unpack(a, ea, &a, &x) < 0
399 || sunuint32unpack(a, ea, &a, &y) < 0)
400 goto Err;
401 *u = ((uvlong)x<<32) | y;
402 *pa = a;
403 return 0;
404 Err:
405 *pa = ea;
406 return -1;
409 int
410 sunuint64pack(uchar *a, uchar *ea, uchar **pa, u64int *u)
412 u32int x, y;
414 x = *u >> 32;
415 y = *u;
416 if(sunuint32pack(a, ea, &a, &x) < 0
417 || sunuint32pack(a, ea, &a, &y) < 0)
418 goto Err;
419 *pa = a;
420 return 0;
421 Err:
422 *pa = ea;
423 return -1;
426 uint
427 sunstringsize(char *s)
429 return (4+strlen(s)+3) & ~3;
432 int
433 sunstringunpack(uchar *a, uchar *ea, uchar **pa, char **s, u32int max)
435 uchar *dat;
436 u32int n;
438 if(sunvaropaqueunpack(a, ea, pa, &dat, &n, max) < 0)
439 goto Err;
440 /* slide string down over length to make room for NUL */
441 memmove(dat-1, dat, n);
442 dat[-1+n] = 0;
443 *s = (char*)(dat-1);
444 return 0;
445 Err:
446 return -1;
449 int
450 sunstringpack(uchar *a, uchar *ea, uchar **pa, char **s, u32int max)
452 u32int n;
454 n = strlen(*s);
455 return sunvaropaquepack(a, ea, pa, (uchar**)s, &n, max);
458 uint
459 sunvaropaquesize(u32int n)
461 return (4+n+3) & ~3;
464 int
465 sunvaropaquepack(uchar *a, uchar *ea, uchar **pa, uchar **dat, u32int *ndat, u32int max)
467 if(*ndat > max || sunuint32pack(a, ea, &a, ndat) < 0
468 || sunfixedopaquepack(a, ea, &a, *dat, *ndat) < 0)
469 goto Err;
470 *pa = a;
471 return 0;
473 Err:
474 *pa = ea;
475 return -1;
478 int
479 sunvaropaqueunpack(uchar *a, uchar *ea, uchar **pa, uchar **dat, u32int *ndat, u32int max)
481 if(sunuint32unpack(a, ea, &a, ndat) < 0
482 || *ndat > max)
483 goto Err;
484 *dat = a;
485 a += (*ndat+3)&~3;
486 if(a > ea)
487 goto Err;
488 *pa = a;
489 return 0;
491 Err:
492 *pa = ea;
493 return -1;
496 uint
497 sunfixedopaquesize(u32int n)
499 return (n+3) & ~3;
502 int
503 sunfixedopaquepack(uchar *a, uchar *ea, uchar **pa, uchar *dat, u32int n)
505 uint nn;
507 nn = (n+3)&~3;
508 if(a+nn > ea)
509 goto Err;
510 memmove(a, dat, n);
511 if(nn > n)
512 memset(a+n, 0, nn-n);
513 a += nn;
514 *pa = a;
515 return 0;
517 Err:
518 *pa = ea;
519 return -1;
522 int
523 sunfixedopaqueunpack(uchar *a, uchar *ea, uchar **pa, uchar *dat, u32int n)
525 uint nn;
527 nn = (n+3)&~3;
528 if(a+nn > ea)
529 goto Err;
530 memmove(dat, a, n);
531 a += nn;
532 *pa = a;
533 return 0;
535 Err:
536 *pa = ea;
537 return -1;