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 default:
72 if(sunuint32pack(a, ea, &a, (x=MsgDenied, &x)) < 0)
73 goto Err;
74 break;
75 }
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;
99 Err:
100 *pa = ea;
101 return SunGarbageArgs;
104 uint
105 sunrpcsize(SunRpc *rpc)
107 uint a;
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;
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;
138 return a;
141 SunStatus
142 sunrpcunpack(uchar *a, uchar *ea, uchar **pa, SunRpc *rpc)
144 u32int x;
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;
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;
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;
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;
218 break;
221 *pa = a;
222 return SunSuccess;
224 Err:
225 *pa = ea;
226 return SunGarbageArgs;
229 void
230 sunrpcprint(Fmt *fmt, SunRpc *rpc)
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);
246 void
247 sunauthinfoprint(Fmt *fmt, SunAuthInfo *ai)
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;
263 // if(ai->ndata)
264 // fmtprint(fmt, " %.*H", ai->ndata, ai->data);
267 uint
268 sunauthinfosize(SunAuthInfo *ai)
270 return 4 + sunvaropaquesize(ai->ndata);
273 int
274 sunauthinfopack(uchar *a, uchar *ea, uchar **pa, SunAuthInfo *ai)
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;
282 Err:
283 *pa = ea;
284 return -1;
287 int
288 sunauthinfounpack(uchar *a, uchar *ea, uchar **pa, SunAuthInfo *ai)
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;
296 Err:
297 *pa = ea;
298 return -1;
301 int
302 sunenumpack(uchar *a, uchar *ea, uchar **pa, int *e)
304 u32int x;
306 x = *e;
307 return sunuint32pack(a, ea, pa, &x);
310 int
311 sunuint1pack(uchar *a, uchar *ea, uchar **pa, u1int *u)
313 u32int x;
315 x = *u;
316 return sunuint32pack(a, ea, pa, &x);
319 int
320 sunuint32pack(uchar *a, uchar *ea, uchar **pa, u32int *u)
322 u32int x;
324 if(ea-a < 4)
325 goto Err;
327 x = *u;
328 *a++ = x>>24;
329 *a++ = x>>16;
330 *a++ = x>>8;
331 *a++ = x;
332 *pa = a;
333 return 0;
335 Err:
336 *pa = ea;
337 return -1;
340 int
341 sunenumunpack(uchar *a, uchar *ea, uchar **pa, int *e)
343 u32int x;
344 if(sunuint32unpack(a, ea, pa, &x) < 0)
345 return -1;
346 *e = x;
347 return 0;
350 int
351 sunuint1unpack(uchar *a, uchar *ea, uchar **pa, u1int *u)
353 u32int x;
354 if(sunuint32unpack(a, ea, pa, &x) < 0 || (x!=0 && x!=1)){
355 *pa = ea;
356 return -1;
358 *u = x;
359 return 0;
362 int
363 sunuint32unpack(uchar *a, uchar *ea, uchar **pa, u32int *u)
365 u32int x;
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;
377 Err:
378 *pa = ea;
379 return -1;
382 int
383 sunuint64unpack(uchar *a, uchar *ea, uchar **pa, u64int *u)
385 u32int x, y;
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;
398 int
399 sunuint64pack(uchar *a, uchar *ea, uchar **pa, u64int *u)
401 u32int x, y;
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;
415 uint
416 sunstringsize(char *s)
418 return (4+strlen(s)+3) & ~3;
421 int
422 sunstringunpack(uchar *a, uchar *ea, uchar **pa, char **s, u32int max)
424 uchar *dat;
425 u32int n;
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;
438 int
439 sunstringpack(uchar *a, uchar *ea, uchar **pa, char **s, u32int max)
441 u32int n;
443 n = strlen(*s);
444 return sunvaropaquepack(a, ea, pa, (uchar**)s, &n, max);
447 uint
448 sunvaropaquesize(u32int n)
450 return (4+n+3) & ~3;
453 int
454 sunvaropaquepack(uchar *a, uchar *ea, uchar **pa, uchar **dat, u32int *ndat, u32int max)
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;
462 Err:
463 *pa = ea;
464 return -1;
467 int
468 sunvaropaqueunpack(uchar *a, uchar *ea, uchar **pa, uchar **dat, u32int *ndat, u32int max)
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;
480 Err:
481 *pa = ea;
482 return -1;
485 uint
486 sunfixedopaquesize(u32int n)
488 return (n+3) & ~3;
491 int
492 sunfixedopaquepack(uchar *a, uchar *ea, uchar **pa, uchar *dat, u32int n)
494 uint nn;
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;
506 Err:
507 *pa = ea;
508 return -1;
511 int
512 sunfixedopaqueunpack(uchar *a, uchar *ea, uchar **pa, uchar *dat, u32int n)
514 uint nn;
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;
524 Err:
525 *pa = ea;
526 return -1;