types: remove the [u_]quad type and replace with [u]int64
[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 HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #ifdef WIN32
28 #include "win32_compat.h"
29 #endif
30
31 #ifdef AROS
32 #include "aros_compat.h"
33 #endif
34
35 #ifdef HAVE_ARPA_INET_H
36 #include <arpa/inet.h>
37 #endif
38
39 #include <stdlib.h>
40 #include <string.h>
41 #include <time.h>
42 #include <unistd.h>
43 #include "libnfs-zdr.h"
44 #include "libnfs.h"
45 #include "libnfs-raw.h"
46 #include "libnfs-private.h"
47
48 struct opaque_auth _null_auth;
49
50 bool_t libnfs_zdr_setpos(ZDR *zdrs, uint32_t pos)
51 {
52 zdrs->pos = pos;
53
54 return TRUE;
55 }
56
57 uint32_t libnfs_zdr_getpos(ZDR *zdrs)
58 {
59 return zdrs->pos;
60 }
61
62 void libnfs_zdrmem_create(ZDR *zdrs, const caddr_t addr, uint32_t size, enum zdr_op xop)
63 {
64 zdrs->x_op = xop;
65 zdrs->buf = addr;
66 zdrs->size = size;
67 zdrs->pos = 0;
68 zdrs->mem = NULL;
69 }
70
71 static void *zdr_malloc(ZDR *zdrs, uint32_t size)
72 {
73 struct zdr_mem *mem;
74
75 mem = malloc(sizeof(struct zdr_mem));
76 mem->next = zdrs->mem;
77 mem->size = size;
78 mem->buf = malloc(mem->size);
79 zdrs->mem = mem;
80
81 return mem->buf;
82 }
83
84 void libnfs_zdr_destroy(ZDR *zdrs)
85 {
86 while (zdrs->mem != NULL) {
87 struct zdr_mem *mem = zdrs->mem->next;
88 free(zdrs->mem->buf);
89 free(zdrs->mem);
90 zdrs->mem = mem;
91 }
92 }
93
94 bool_t libnfs_zdr_u_int(ZDR *zdrs, uint32_t *u)
95 {
96 if (zdrs->pos + 4 > zdrs->size) {
97 return FALSE;
98 }
99
100 switch (zdrs->x_op) {
101 case ZDR_ENCODE:
102 *(uint32_t *)&zdrs->buf[zdrs->pos] = htonl(*u);
103 zdrs->pos += 4;
104 return TRUE;
105 break;
106 case ZDR_DECODE:
107 *u = ntohl(*(uint32_t *)&zdrs->buf[zdrs->pos]);
108 zdrs->pos += 4;
109 return TRUE;
110 break;
111 }
112
113 return FALSE;
114 }
115
116 bool_t libnfs_zdr_int(ZDR *zdrs, int32_t *i)
117 {
118 return libnfs_zdr_u_int(zdrs, (uint32_t *)i);
119 }
120
121 bool_t libnfs_zdr_uint64_t(ZDR *zdrs, uint64_t *u)
122 {
123 if (zdrs->pos + 8 > zdrs->size) {
124 return FALSE;
125 }
126
127 switch (zdrs->x_op) {
128 case ZDR_ENCODE:
129 *(uint32_t *)&zdrs->buf[zdrs->pos] = htonl((*u >> 32));
130 zdrs->pos += 4;
131 *(uint32_t *)&zdrs->buf[zdrs->pos] = htonl((*u & 0xffffffff));
132 zdrs->pos += 4;
133 return TRUE;
134 break;
135 case ZDR_DECODE:
136 *u = ntohl(*(uint32_t *)&zdrs->buf[zdrs->pos]);
137 zdrs->pos += 4;
138 *u <<= 32;
139 *u |= (uint32_t)ntohl(*(uint32_t *)&zdrs->buf[zdrs->pos]);
140 zdrs->pos += 4;
141 return TRUE;
142 break;
143 }
144
145 return FALSE;
146 }
147
148 bool_t libnfs_zdr_int64_t(ZDR *zdrs, int64_t *i)
149 {
150 return libnfs_zdr_uint64_t(zdrs, (uint64_t *)i);
151 }
152
153 bool_t libnfs_zdr_bytes(ZDR *zdrs, char **bufp, uint32_t *size, uint32_t maxsize)
154 {
155 if (!libnfs_zdr_u_int(zdrs, size)) {
156 return FALSE;
157 }
158
159 if (zdrs->pos + *size > zdrs->size) {
160 return FALSE;
161 }
162
163 switch (zdrs->x_op) {
164 case ZDR_ENCODE:
165 memcpy(&zdrs->buf[zdrs->pos], *bufp, *size);
166 zdrs->pos += *size;
167 zdrs->pos = (zdrs->pos + 3) & ~3;
168 return TRUE;
169 case ZDR_DECODE:
170 if (*bufp == NULL) {
171 *bufp = zdr_malloc(zdrs, *size);
172 }
173 memcpy(*bufp, &zdrs->buf[zdrs->pos], *size);
174 zdrs->pos += *size;
175 zdrs->pos = (zdrs->pos + 3) & ~3;
176 return TRUE;
177 }
178
179 return FALSE;
180 }
181
182
183 bool_t libnfs_zdr_enum(ZDR *zdrs, enum_t *e)
184 {
185 bool_t ret;
186 int32_t i = *e;
187
188 ret = libnfs_zdr_u_int(zdrs, (uint32_t *)&i);
189 *e = i;
190
191 return ret;
192 }
193
194 bool_t libnfs_zdr_bool(ZDR *zdrs, bool_t *b)
195 {
196 return libnfs_zdr_u_int(zdrs, (uint32_t *)b);
197 }
198
199 bool_t libnfs_zdr_void(void)
200 {
201 return TRUE;
202 }
203
204 bool_t libnfs_zdr_pointer(ZDR *zdrs, char **objp, uint32_t size, zdrproc_t proc)
205 {
206 bool_t more_data;
207
208 more_data = (*objp != NULL);
209
210 if (!libnfs_zdr_bool(zdrs, &more_data)) {
211 return FALSE;
212 }
213 if (more_data == 0) {
214 *objp = NULL;
215 return TRUE;
216 }
217
218 if (zdrs->x_op == ZDR_DECODE) {
219 *objp = zdr_malloc(zdrs, size);
220 if (*objp == NULL) {
221 return FALSE;
222 }
223 memset(*objp, 0, size);
224 }
225 return proc(zdrs, *objp);
226 }
227
228 bool_t libnfs_zdr_opaque(ZDR *zdrs, char *objp, uint32_t size)
229 {
230 switch (zdrs->x_op) {
231 case ZDR_ENCODE:
232 memcpy(&zdrs->buf[zdrs->pos], objp, size);
233 zdrs->pos += size;
234 if (zdrs->pos & 3) {
235 memset(&zdrs->buf[zdrs->pos], 0x00, 4 - (zdrs->pos & 3));
236 }
237 zdrs->pos = (zdrs->pos + 3) & ~3;
238 return TRUE;
239 case ZDR_DECODE:
240 memcpy(objp, &zdrs->buf[zdrs->pos], size);
241 zdrs->pos += size;
242 zdrs->pos = (zdrs->pos + 3) & ~3;
243 return TRUE;
244 }
245
246 return FALSE;
247 }
248
249 bool_t libnfs_zdr_string(ZDR *zdrs, char **strp, uint32_t maxsize)
250 {
251 uint32_t size;
252
253 if (zdrs->x_op == ZDR_ENCODE) {
254 size = strlen(*strp);
255 }
256
257 if (!libnfs_zdr_u_int(zdrs, &size)) {
258 return FALSE;
259 }
260
261 if (zdrs->pos + size > zdrs->size) {
262 return FALSE;
263 }
264
265 switch (zdrs->x_op) {
266 case ZDR_ENCODE:
267 return libnfs_zdr_opaque(zdrs, *strp, size);
268 case ZDR_DECODE:
269 *strp = zdr_malloc(zdrs, size + 1);
270 if (*strp == NULL) {
271 return FALSE;
272 }
273 (*strp)[size] = 0;
274 return libnfs_zdr_opaque(zdrs, *strp, size);
275 }
276
277 return FALSE;
278 }
279
280 bool_t libnfs_zdr_array(ZDR *zdrs, char **arrp, uint32_t *size, uint32_t maxsize, uint32_t elsize, zdrproc_t proc)
281 {
282 int i;
283
284 if (!libnfs_zdr_u_int(zdrs, size)) {
285 return FALSE;
286 }
287
288 if (zdrs->pos + *size * elsize > zdrs->size) {
289 return FALSE;
290 }
291
292 if (zdrs->x_op == ZDR_DECODE) {
293 *arrp = zdr_malloc(zdrs, *size * elsize);
294 if (*arrp == NULL) {
295 return FALSE;
296 }
297 memset(*arrp, 0, *size * elsize);
298 }
299
300 for (i = 0; i < *size; i++) {
301 if (!proc(zdrs, *arrp + i * elsize)) {
302 return FALSE;
303 }
304 }
305 return TRUE;
306 }
307
308 void libnfs_zdr_free(zdrproc_t proc, char *objp)
309 {
310 }
311
312 static bool_t libnfs_opaque_auth(ZDR *zdrs, struct opaque_auth *auth)
313 {
314 if (!libnfs_zdr_u_int(zdrs, &auth->oa_flavor)) {
315 return FALSE;
316 }
317
318 if (!libnfs_zdr_bytes(zdrs, &auth->oa_base, &auth->oa_length, auth->oa_length)) {
319 return FALSE;
320 }
321
322 return TRUE;
323 }
324
325 static bool_t libnfs_rpc_call_body(struct rpc_context *rpc, ZDR *zdrs, struct call_body *cmb)
326 {
327 if (!libnfs_zdr_u_int(zdrs, &cmb->rpcvers)) {
328 rpc_set_error(rpc, "libnfs_rpc_call_body failed to encode "
329 "RPCVERS");
330 return FALSE;
331 }
332
333 if (!libnfs_zdr_u_int(zdrs, &cmb->prog)) {
334 rpc_set_error(rpc, "libnfs_rpc_call_body failed to encode "
335 "PROG");
336 return FALSE;
337 }
338
339 if (!libnfs_zdr_u_int(zdrs, &cmb->vers)) {
340 rpc_set_error(rpc, "libnfs_rpc_call_body failed to encode "
341 "VERS");
342 return FALSE;
343 }
344
345 if (!libnfs_zdr_u_int(zdrs, &cmb->proc)) {
346 rpc_set_error(rpc, "libnfs_rpc_call_body failed to encode "
347 "PROC");
348 return FALSE;
349 }
350
351 if (!libnfs_opaque_auth(zdrs, &cmb->cred)) {
352 rpc_set_error(rpc, "libnfs_rpc_call_body failed to encode "
353 "CRED");
354 return FALSE;
355 }
356
357 if (!libnfs_opaque_auth(zdrs, &cmb->verf)) {
358 rpc_set_error(rpc, "libnfs_rpc_call_body failed to encode "
359 "VERF");
360 return FALSE;
361 }
362
363 return TRUE;
364 }
365
366 static bool_t libnfs_accepted_reply(ZDR *zdrs, struct accepted_reply *ar)
367 {
368 if (!libnfs_opaque_auth(zdrs, &ar->verf)) {
369 return FALSE;
370 }
371
372 if (!libnfs_zdr_u_int(zdrs, &ar->stat)) {
373 return FALSE;
374 }
375
376 switch (ar->stat) {
377 case SUCCESS:
378 if (!ar->reply_data.results.proc(zdrs, ar->reply_data.results.where)) {
379 return FALSE;
380 }
381 return TRUE;
382 case PROG_MISMATCH:
383 if (!libnfs_zdr_u_int(zdrs, &ar->reply_data.mismatch_info.low)) {
384 return FALSE;
385 }
386 if (!libnfs_zdr_u_int(zdrs, &ar->reply_data.mismatch_info.high)) {
387 return FALSE;
388 }
389 return TRUE;
390 default:
391 return TRUE;
392 }
393
394 return FALSE;
395 }
396
397 static bool_t libnfs_rejected_reply(ZDR *zdrs, struct rejected_reply *rr)
398 {
399 if (!libnfs_zdr_u_int(zdrs, &rr->stat)) {
400 return FALSE;
401 }
402
403 switch (rr->stat) {
404 case RPC_MISMATCH:
405 if (!libnfs_zdr_u_int(zdrs, &rr->reject_data.mismatch_info.low)) {
406 return FALSE;
407 }
408 if (!libnfs_zdr_u_int(zdrs, &rr->reject_data.mismatch_info.high)) {
409 return FALSE;
410 }
411 return TRUE;
412 case AUTH_ERROR:
413 if (!libnfs_zdr_u_int(zdrs, &rr->reject_data.stat)) {
414 return FALSE;
415 }
416 return TRUE;
417 default:
418 return TRUE;
419 }
420
421 return FALSE;
422 }
423
424 static bool_t libnfs_rpc_reply_body(struct rpc_context *rpc, ZDR *zdrs, struct reply_body *rmb)
425 {
426 if (!libnfs_zdr_u_int(zdrs, &rmb->stat)) {
427 rpc_set_error(rpc, "libnfs_rpc_reply_body failed to decode "
428 "STAT");
429 return FALSE;
430 }
431
432 switch (rmb->stat) {
433 case MSG_ACCEPTED:
434 if (!libnfs_accepted_reply(zdrs, &rmb->reply.areply)) {
435 rpc_set_error(rpc, "libnfs_rpc_reply_body failed to "
436 "decode ACCEPTED");
437 return FALSE;
438 }
439 return TRUE;
440 case MSG_DENIED:
441 if (!libnfs_rejected_reply(zdrs, &rmb->reply.rreply)) {
442 rpc_set_error(rpc, "libnfs_rpc_reply_body failed to "
443 "decode DENIED");
444 return FALSE;
445 }
446 return TRUE;
447 }
448
449 rpc_set_error(rpc, "libnfs_rpc_reply_body failed to "
450 "decode. Neither ACCEPTED nor DENIED");
451 return FALSE;
452 }
453
454 static bool_t libnfs_rpc_msg(struct rpc_context *rpc, ZDR *zdrs, struct rpc_msg *msg)
455 {
456 int ret;
457
458 if (!libnfs_zdr_u_int(zdrs, &msg->xid)) {
459 rpc_set_error(rpc, "libnfs_rpc_msg failed to decode XID");
460 return FALSE;
461 }
462
463 if (!libnfs_zdr_u_int(zdrs, &msg->direction)) {
464 rpc_set_error(rpc, "libnfs_rpc_msg failed to decode DIRECTION");
465 return FALSE;
466 }
467
468 switch (msg->direction) {
469 case CALL:
470 ret = libnfs_rpc_call_body(rpc, zdrs, &msg->body.cbody);
471 if (!ret) {
472 rpc_set_error(rpc, "libnfs_rpc_msg failed to encode "
473 "CALL, ret=%d: %s", ret, rpc_get_error(rpc));
474 }
475 return ret;
476 case REPLY:
477 ret = libnfs_rpc_reply_body(rpc, zdrs, &msg->body.rbody);
478 if (!ret) {
479 rpc_set_error(rpc, "libnfs_rpc_msg failed to decode "
480 "REPLY, ret=%d: %s", ret, rpc_get_error(rpc));
481 }
482 return ret;
483 default:
484 rpc_set_error(rpc, "libnfs_rpc_msg failed to decode. "
485 "Neither CALL not REPLY");
486 return FALSE;
487 }
488 }
489
490 bool_t libnfs_zdr_callmsg(struct rpc_context *rpc, ZDR *zdrs, struct rpc_msg *msg)
491 {
492 return libnfs_rpc_msg(rpc, zdrs, msg);
493 }
494
495 bool_t libnfs_zdr_replymsg(struct rpc_context *rpc, ZDR *zdrs, struct rpc_msg *msg)
496 {
497 return libnfs_rpc_msg(rpc, zdrs, msg);
498 }
499
500 struct AUTH *authnone_create(void)
501 {
502 struct AUTH *auth;
503
504 auth = malloc(sizeof(struct AUTH));
505
506 auth->ah_cred.oa_flavor = AUTH_NONE;
507 auth->ah_cred.oa_length = 0;
508 auth->ah_cred.oa_base = NULL;
509
510 auth->ah_verf.oa_flavor = AUTH_NONE;
511 auth->ah_verf.oa_length = 0;
512 auth->ah_verf.oa_base = NULL;
513
514 auth->ah_private = NULL;
515
516 return auth;
517 }
518
519 struct AUTH *libnfs_authunix_create(char *host, uint32_t uid, uint32_t gid, uint32_t len, uint32_t *groups)
520 {
521 struct AUTH *auth;
522 int size;
523 uint32_t *buf;
524 int idx;
525
526 size = 4 + 4 + ((strlen(host) + 3) & ~3) + 4 + 4 + 4 + len * 4;
527 auth = malloc(sizeof(struct AUTH));
528 memset(auth, 0x00, sizeof(struct AUTH));
529 auth->ah_cred.oa_flavor = AUTH_UNIX;
530 auth->ah_cred.oa_length = size;
531 auth->ah_cred.oa_base = malloc(size);
532
533 memset(auth->ah_cred.oa_base, 0x00, size);
534 buf = (uint32_t *)auth->ah_cred.oa_base;
535 idx = 0;
536 buf[idx++] = htonl(time(NULL));
537 buf[idx++] = htonl(strlen(host));
538 memcpy(&buf[2], host, strlen(host));
539
540 idx += (strlen(host) + 3) >> 2;
541 buf[idx++] = htonl(uid);
542 buf[idx++] = htonl(gid);
543 buf[idx++] = htonl(len);
544 while (len-- > 0) {
545 buf[idx++] = htonl(*groups++);
546 }
547
548 auth->ah_verf.oa_flavor = AUTH_NONE;
549 auth->ah_verf.oa_length = 0;
550 auth->ah_verf.oa_base = NULL;
551
552 auth->ah_private = NULL;
553
554 return auth;
555 }
556
557 struct AUTH *libnfs_authunix_create_default(void)
558 {
559 #ifdef WIN32
560 return libnfs_authunix_create("libnfs", 65534, 65534, 0, NULL);
561 #else
562 return libnfs_authunix_create("libnfs", getuid(), getgid(), 0, NULL);
563 #endif
564 }
565
566 void libnfs_auth_destroy(struct AUTH *auth)
567 {
568 if (auth->ah_cred.oa_base) {
569 free(auth->ah_cred.oa_base);
570 }
571 if (auth->ah_verf.oa_base) {
572 free(auth->ah_verf.oa_base);
573 }
574 free(auth);
575 }
576