]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libsunrpc/rpc.c
libaml: fix gc bug, need to amltake()/amldrop() temporary buffer
[plan9front.git] / sys / src / libsunrpc / rpc.c
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                 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
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
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
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
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
268 sunAuthInfoSize(SunAuthInfo *ai)
269 {
270         return 4 + sunVarOpaqueSize(ai->ndata);
271 }
272
273 int
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
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
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
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
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
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
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
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
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
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
416 sunStringSize(char *s)
417 {
418         return (4+strlen(s)+3) & ~3;
419 }
420
421 int
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--;
432         dat[n] = 0;
433         *s = (char*)dat;
434         return 0;
435 Err:
436         return -1;
437 }
438
439 int
440 sunStringPack(uchar *a, uchar *ea, uchar **pa, char **s, u32int max)
441 {
442         u32int n;
443
444         n = strlen(*s);
445         return sunVarOpaquePack(a, ea, pa, (uchar**)s, &n, max);
446 }
447
448 uint
449 sunVarOpaqueSize(u32int n)
450 {
451         return (4+n+3) & ~3;
452 }
453
454 int
455 sunVarOpaquePack(uchar *a, uchar *ea, uchar **pa, uchar **dat, u32int *ndat, u32int max)
456 {
457         if(*ndat > max || sunUint32Pack(a, ea, &a, ndat) < 0
458         || sunFixedOpaquePack(a, ea, &a, *dat, *ndat) < 0)
459                 goto Err;
460         *pa = a;
461         return 0;
462
463 Err:
464         *pa = ea;
465         return -1;
466 }
467
468 int
469 sunVarOpaqueUnpack(uchar *a, uchar *ea, uchar **pa, uchar **dat, u32int *ndat, u32int max)
470 {
471         if(sunUint32Unpack(a, ea, &a, ndat) < 0
472         || *ndat > max)
473                 goto Err;
474         *dat = a;
475         a += (*ndat+3)&~3;
476         if(a > ea)
477                 goto Err;
478         *pa = a;
479         return 0;
480
481 Err:
482         *pa = ea;
483         return -1;
484 }
485
486 uint
487 sunFixedOpaqueSize(u32int n)
488 {
489         return (n+3) & ~3;
490 }
491
492 int
493 sunFixedOpaquePack(uchar *a, uchar *ea, uchar **pa, uchar *dat, u32int n)
494 {
495         uint nn;
496
497         nn = (n+3)&~3;
498         if(a+nn > ea)
499                 goto Err;
500         memmove(a, dat, n);
501         if(nn > n)
502                 memset(a+n, 0, nn-n);
503         a += nn;
504         *pa = a;
505         return 0;
506
507 Err:
508         *pa = ea;
509         return -1;
510 }
511
512 int
513 sunFixedOpaqueUnpack(uchar *a, uchar *ea, uchar **pa, uchar *dat, u32int n)
514 {
515         uint nn;
516
517         nn = (n+3)&~3;
518         if(a+nn > ea)
519                 goto Err;
520         memmove(dat, a, n);
521         a += nn;
522         *pa = a;
523         return 0;
524
525 Err:
526         *pa = ea;
527         return -1;
528 }
529