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