Initial AROS support.
[deb_libnfs.git] / lib / libnfs-zdr.c
1 /*
2 Copyright (C) 2012 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 2.1 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17 /*
18 * This file contains definitions for the built in ZDR implementation.
19 * This is a very limited ZDR subset that can only marshal to/from a momory buffer,
20 * i.e. zdrmem_create() buffers.
21 * It aims to be compatible with normal rpcgen generated functions.
22 */
23 #ifdef WIN32
24 #include "win32_compat.h"
25 #else
26 #include <sys/types.h>
27 #include <arpa/inet.h>
28 #endif/*WIN32*/
29
30 #include <stdlib.h>
31 #include <string.h>
32 #include <time.h>
33 #include "libnfs-zdr.h"
34
35 struct opaque_auth _null_auth;
36
37 bool_t libnfs_zdr_setpos(ZDR *zdrs, uint32_t pos)
38 {
39 zdrs->pos = pos;
40
41 return TRUE;
42 }
43
44 uint32_t libnfs_zdr_getpos(ZDR *zdrs)
45 {
46 return zdrs->pos;
47 }
48
49 void libnfs_zdrmem_create(ZDR *zdrs, const caddr_t addr, uint32_t size, enum zdr_op xop)
50 {
51 zdrs->x_op = xop;
52 zdrs->buf = addr;
53 zdrs->size = size;
54 zdrs->pos = 0;
55 zdrs->mem = NULL;
56 }
57
58 static void *zdr_malloc(ZDR *zdrs, uint32_t size)
59 {
60 struct zdr_mem *mem;
61
62 mem = malloc(sizeof(struct zdr_mem));
63 mem->next = zdrs->mem;
64 mem->size = size;
65 mem->buf = malloc(mem->size);
66 zdrs->mem = mem;
67
68 return mem->buf;
69 }
70
71 void libnfs_zdr_destroy(ZDR *zdrs)
72 {
73 while (zdrs->mem != NULL) {
74 struct zdr_mem *mem = zdrs->mem->next;
75 free(zdrs->mem->buf);
76 free(zdrs->mem);
77 zdrs->mem = mem;
78 }
79 }
80
81 bool_t libnfs_zdr_u_int(ZDR *zdrs, uint32_t *u)
82 {
83 if (zdrs->pos + 4 > zdrs->size) {
84 return FALSE;
85 }
86
87 switch (zdrs->x_op) {
88 case ZDR_ENCODE:
89 *(uint32_t *)&zdrs->buf[zdrs->pos] = htonl(*u);
90 zdrs->pos += 4;
91 return TRUE;
92 break;
93 case ZDR_DECODE:
94 *u = ntohl(*(uint32_t *)&zdrs->buf[zdrs->pos]);
95 zdrs->pos += 4;
96 return TRUE;
97 break;
98 }
99
100 return FALSE;
101 }
102
103 bool_t libnfs_zdr_int(ZDR *zdrs, int32_t *i)
104 {
105 return libnfs_zdr_u_int(zdrs, (uint32_t *)i);
106 }
107
108 bool_t libnfs_zdr_u_quad_t(ZDR *zdrs, uint64_t *u)
109 {
110 if (zdrs->pos + 8 > zdrs->size) {
111 return FALSE;
112 }
113
114 switch (zdrs->x_op) {
115 case ZDR_ENCODE:
116 *(uint32_t *)&zdrs->buf[zdrs->pos] = htonl((*u >> 32));
117 zdrs->pos += 4;
118 *(uint32_t *)&zdrs->buf[zdrs->pos] = htonl((*u & 0xffffffff));
119 zdrs->pos += 4;
120 return TRUE;
121 break;
122 case ZDR_DECODE:
123 *u = ntohl(*(uint32_t *)&zdrs->buf[zdrs->pos]);
124 zdrs->pos += 4;
125 *u <<= 32;
126 *u |= ntohl(*(uint32_t *)&zdrs->buf[zdrs->pos]);
127 zdrs->pos += 4;
128 return TRUE;
129 break;
130 }
131
132 return FALSE;
133 }
134
135 bool_t libnfs_zdr_quad_t(ZDR *zdrs, int64_t *i)
136 {
137 return libnfs_zdr_u_quad_t(zdrs, (uint64_t *)i);
138 }
139
140 bool_t libnfs_zdr_bytes(ZDR *zdrs, char **bufp, uint32_t *size, uint32_t maxsize)
141 {
142 if (!libnfs_zdr_u_int(zdrs, size)) {
143 return FALSE;
144 }
145
146 if (zdrs->pos + *size > zdrs->size) {
147 return FALSE;
148 }
149
150 switch (zdrs->x_op) {
151 case ZDR_ENCODE:
152 memcpy(&zdrs->buf[zdrs->pos], *bufp, *size);
153 zdrs->pos += *size;
154 zdrs->pos = (zdrs->pos + 3) & ~3;
155 return TRUE;
156 case ZDR_DECODE:
157 if (*bufp == NULL) {
158 *bufp = zdr_malloc(zdrs, *size);
159 }
160 memcpy(*bufp, &zdrs->buf[zdrs->pos], *size);
161 zdrs->pos += *size;
162 zdrs->pos = (zdrs->pos + 3) & ~3;
163 return TRUE;
164 }
165
166 return FALSE;
167 }
168
169
170 bool_t libnfs_zdr_enum(ZDR *zdrs, enum_t *e)
171 {
172 bool_t ret;
173 int32_t i = *e;
174
175 ret = libnfs_zdr_u_int(zdrs, (uint32_t *)&i);
176 *e = i;
177
178 return ret;
179 }
180
181 bool_t libnfs_zdr_bool(ZDR *zdrs, bool_t *b)
182 {
183 return libnfs_zdr_u_int(zdrs, (uint32_t *)b);
184 }
185
186 bool_t libnfs_zdr_void(void)
187 {
188 return TRUE;
189 }
190
191 bool_t libnfs_zdr_pointer(ZDR *zdrs, char **objp, uint32_t size, zdrproc_t proc)
192 {
193 bool_t more_data;
194
195 more_data = (*objp != NULL);
196
197 if (!libnfs_zdr_bool(zdrs, &more_data)) {
198 return FALSE;
199 }
200 if (more_data == 0) {
201 *objp = NULL;
202 return TRUE;
203 }
204
205 if (zdrs->x_op == ZDR_DECODE) {
206 *objp = zdr_malloc(zdrs, size);
207 if (*objp == NULL) {
208 return FALSE;
209 }
210 memset(*objp, 0, size);
211 }
212 return proc(zdrs, *objp);
213 }
214
215 bool_t libnfs_zdr_opaque(ZDR *zdrs, char *objp, uint32_t size)
216 {
217 switch (zdrs->x_op) {
218 case ZDR_ENCODE:
219 memcpy(&zdrs->buf[zdrs->pos], objp, size);
220 zdrs->pos += size;
221 zdrs->pos = (zdrs->pos + 3) & ~3;
222 return TRUE;
223 case ZDR_DECODE:
224 memcpy(objp, &zdrs->buf[zdrs->pos], size);
225 zdrs->pos += size;
226 zdrs->pos = (zdrs->pos + 3) & ~3;
227 return TRUE;
228 }
229
230 return FALSE;
231 }
232
233 bool_t libnfs_zdr_string(ZDR *zdrs, char **strp, uint32_t maxsize)
234 {
235 uint32_t size;
236
237 if (zdrs->x_op == ZDR_ENCODE) {
238 size = strlen(*strp);
239 }
240
241 if (!libnfs_zdr_u_int(zdrs, &size)) {
242 return FALSE;
243 }
244
245 if (zdrs->pos + size > zdrs->size) {
246 return FALSE;
247 }
248
249 switch (zdrs->x_op) {
250 case ZDR_ENCODE:
251 return libnfs_zdr_opaque(zdrs, *strp, size);
252 case ZDR_DECODE:
253 *strp = zdr_malloc(zdrs, size + 1);
254 if (*strp == NULL) {
255 return FALSE;
256 }
257 (*strp)[size] = 0;
258 return libnfs_zdr_opaque(zdrs, *strp, size);
259 }
260
261 return FALSE;
262 }
263
264 bool_t libnfs_zdr_array(ZDR *zdrs, char **arrp, uint32_t *size, uint32_t maxsize, uint32_t elsize, zdrproc_t proc)
265 {
266 int i;
267
268 if (!libnfs_zdr_u_int(zdrs, size)) {
269 return FALSE;
270 }
271
272 if (zdrs->pos + *size * elsize > zdrs->size) {
273 return FALSE;
274 }
275
276 if (zdrs->x_op == ZDR_DECODE) {
277 *arrp = zdr_malloc(zdrs, *size * elsize);
278 if (*arrp == NULL) {
279 return FALSE;
280 }
281 memset(*arrp, 0, *size * elsize);
282 }
283
284 for (i = 0; i < *size; i++) {
285 if (!proc(zdrs, *arrp + i * elsize)) {
286 return FALSE;
287 }
288 }
289 return TRUE;
290 }
291
292 void libnfs_zdr_free(zdrproc_t proc, char *objp)
293 {
294 }
295
296 static bool_t libnfs_opaque_auth(ZDR *zdrs, struct opaque_auth *auth)
297 {
298 if (!libnfs_zdr_u_int(zdrs, &auth->oa_flavor)) {
299 return FALSE;
300 }
301
302 if (!libnfs_zdr_bytes(zdrs, &auth->oa_base, &auth->oa_length, auth->oa_length)) {
303 return FALSE;
304 }
305
306 return TRUE;
307 }
308
309 static bool_t libnfs_rpc_call_body(ZDR *zdrs, struct call_body *cmb)
310 {
311 if (!libnfs_zdr_u_int(zdrs, &cmb->rpcvers)) {
312 return FALSE;
313 }
314
315 if (!libnfs_zdr_u_int(zdrs, &cmb->prog)) {
316 return FALSE;
317 }
318
319 if (!libnfs_zdr_u_int(zdrs, &cmb->vers)) {
320 return FALSE;
321 }
322
323 if (!libnfs_zdr_u_int(zdrs, &cmb->proc)) {
324 return FALSE;
325 }
326
327 if (!libnfs_opaque_auth(zdrs, &cmb->cred)) {
328 return FALSE;
329 }
330
331 if (!libnfs_opaque_auth(zdrs, &cmb->verf)) {
332 return FALSE;
333 }
334
335 return TRUE;
336 }
337
338 static bool_t libnfs_accepted_reply(ZDR *zdrs, struct accepted_reply *ar)
339 {
340 if (!libnfs_opaque_auth(zdrs, &ar->verf)) {
341 return FALSE;
342 }
343
344 if (!libnfs_zdr_u_int(zdrs, &ar->stat)) {
345 return FALSE;
346 }
347
348 switch (ar->stat) {
349 case SUCCESS:
350 if (!ar->reply_data.results.proc(zdrs, ar->reply_data.results.where)) {
351 return FALSE;
352 }
353 return TRUE;
354 case PROG_MISMATCH:
355 if (!libnfs_zdr_u_int(zdrs, &ar->reply_data.mismatch_info.low)) {
356 return FALSE;
357 }
358 if (!libnfs_zdr_u_int(zdrs, &ar->reply_data.mismatch_info.high)) {
359 return FALSE;
360 }
361 return TRUE;
362 default:
363 return TRUE;
364 }
365
366 return FALSE;
367 }
368
369 static bool_t libnfs_rejected_reply(ZDR *zdrs, struct rejected_reply *rr)
370 {
371 if (!libnfs_zdr_u_int(zdrs, &rr->stat)) {
372 return FALSE;
373 }
374
375 switch (rr->stat) {
376 case RPC_MISMATCH:
377 if (!libnfs_zdr_u_int(zdrs, &rr->reject_data.mismatch_info.low)) {
378 return FALSE;
379 }
380 if (!libnfs_zdr_u_int(zdrs, &rr->reject_data.mismatch_info.high)) {
381 return FALSE;
382 }
383 return TRUE;
384 case AUTH_ERROR:
385 if (!libnfs_zdr_u_int(zdrs, &rr->reject_data.stat)) {
386 return FALSE;
387 }
388 return TRUE;
389 default:
390 return TRUE;
391 }
392
393 return FALSE;
394 }
395
396 static bool_t libnfs_rpc_reply_body(ZDR *zdrs, struct reply_body *rmb)
397 {
398 if (!libnfs_zdr_u_int(zdrs, &rmb->stat)) {
399 return FALSE;
400 }
401
402 switch (rmb->stat) {
403 case MSG_ACCEPTED:
404 if (!libnfs_accepted_reply(zdrs, &rmb->reply.areply)) {
405 return FALSE;
406 }
407 return TRUE;
408 case MSG_DENIED:
409 if (!libnfs_rejected_reply(zdrs, &rmb->reply.rreply)) {
410 return FALSE;
411 }
412 return TRUE;
413 }
414
415 return FALSE;
416 }
417
418 static bool_t libnfs_rpc_msg(ZDR *zdrs, struct rpc_msg *msg)
419 {
420 if (!libnfs_zdr_u_int(zdrs, &msg->xid)) {
421 return FALSE;
422 }
423
424 if (!libnfs_zdr_u_int(zdrs, &msg->direction)) {
425 return FALSE;
426 }
427
428 switch (msg->direction) {
429 case CALL:
430 return libnfs_rpc_call_body(zdrs, &msg->body.cbody);
431 break;
432 case REPLY:
433 return libnfs_rpc_reply_body(zdrs, &msg->body.rbody);
434 break;
435 default:
436 return FALSE;
437 }
438 }
439
440 bool_t libnfs_zdr_callmsg(ZDR *zdrs, struct rpc_msg *msg)
441 {
442 return libnfs_rpc_msg(zdrs, msg);
443 }
444
445 bool_t libnfs_zdr_replymsg(ZDR *zdrs, struct rpc_msg *msg)
446 {
447 return libnfs_rpc_msg(zdrs, msg);
448 }
449
450 struct AUTH *authnone_create(void)
451 {
452 struct AUTH *auth;
453
454 auth = malloc(sizeof(struct AUTH));
455
456 auth->ah_cred.oa_flavor = AUTH_NONE;
457 auth->ah_cred.oa_length = 0;
458 auth->ah_cred.oa_base = NULL;
459
460 auth->ah_verf.oa_flavor = AUTH_NONE;
461 auth->ah_verf.oa_length = 0;
462 auth->ah_verf.oa_base = NULL;
463
464 auth->ah_private = NULL;
465
466 return auth;
467 }
468
469 struct AUTH *libnfs_authunix_create(char *host, uint32_t uid, uint32_t gid, uint32_t len, uint32_t *groups)
470 {
471 struct AUTH *auth;
472 int size;
473 uint32_t *buf;
474 int idx;
475
476 size = 4 + 4 + ((strlen(host) + 3) & ~3) + 4 + 4 + 4 + len * 4;
477 auth = malloc(sizeof(struct AUTH));
478 auth->ah_cred.oa_flavor = AUTH_UNIX;
479 auth->ah_cred.oa_length = size;
480 auth->ah_cred.oa_base = malloc(size);
481
482 buf = (uint32_t *)auth->ah_cred.oa_base;
483 idx = 0;
484 buf[idx++] = htonl(time(NULL));
485 buf[idx++] = htonl(strlen(host));
486 memcpy(&buf[2], host, strlen(host));
487
488 idx += (strlen(host) + 3) >> 2;
489 buf[idx++] = htonl(uid);
490 buf[idx++] = htonl(gid);
491 buf[idx++] = htonl(len);
492 while (len-- > 0) {
493 buf[idx++] = htonl(*groups++);
494 }
495
496 auth->ah_verf.oa_flavor = AUTH_NONE;
497 auth->ah_verf.oa_length = 0;
498 auth->ah_verf.oa_base = NULL;
499
500 auth->ah_private = NULL;
501
502 return auth;
503 }
504
505 struct AUTH *libnfs_authunix_create_default(void)
506 {
507 return libnfs_authunix_create("libnfs", getuid(), -1, 0, NULL);
508 }
509
510 void libnfs_auth_destroy(struct AUTH *auth)
511 {
512 if (auth->ah_cred.oa_base) {
513 free(auth->ah_cred.oa_base);
514 }
515 if (auth->ah_verf.oa_base) {
516 free(auth->ah_verf.oa_base);
517 }
518 free(auth);
519 }
520