types: remove the [u_]quad type and replace with [u]int64
[deb_libnfs.git] / lib / libnfs-zdr.c
CommitLineData
763cd6e3
RS
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 */
10a1a781
MF
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
b1406276
RS
27#ifdef WIN32
28#include "win32_compat.h"
833d5b9d 29#endif
763cd6e3 30
0556ee05
RS
31#ifdef AROS
32#include "aros_compat.h"
33#endif
34
10a1a781
MF
35#ifdef HAVE_ARPA_INET_H
36#include <arpa/inet.h>
37#endif
38
763cd6e3
RS
39#include <stdlib.h>
40#include <string.h>
b1406276 41#include <time.h>
10a1a781 42#include <unistd.h>
763cd6e3 43#include "libnfs-zdr.h"
e48cfe96
MF
44#include "libnfs.h"
45#include "libnfs-raw.h"
46#include "libnfs-private.h"
763cd6e3
RS
47
48struct opaque_auth _null_auth;
49
50bool_t libnfs_zdr_setpos(ZDR *zdrs, uint32_t pos)
51{
52 zdrs->pos = pos;
242b81cf
RS
53
54 return TRUE;
763cd6e3
RS
55}
56
57uint32_t libnfs_zdr_getpos(ZDR *zdrs)
58{
59 return zdrs->pos;
60}
61
62void 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
71static 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
84void 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
94bool_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
116bool_t libnfs_zdr_int(ZDR *zdrs, int32_t *i)
117{
118 return libnfs_zdr_u_int(zdrs, (uint32_t *)i);
119}
120
bce63d84 121bool_t libnfs_zdr_uint64_t(ZDR *zdrs, uint64_t *u)
763cd6e3
RS
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;
c81e7d89 139 *u |= (uint32_t)ntohl(*(uint32_t *)&zdrs->buf[zdrs->pos]);
763cd6e3
RS
140 zdrs->pos += 4;
141 return TRUE;
142 break;
143 }
144
145 return FALSE;
146}
147
bce63d84 148bool_t libnfs_zdr_int64_t(ZDR *zdrs, int64_t *i)
763cd6e3 149{
bce63d84 150 return libnfs_zdr_uint64_t(zdrs, (uint64_t *)i);
763cd6e3
RS
151}
152
153bool_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
442b829a 183bool_t libnfs_zdr_enum(ZDR *zdrs, enum_t *e)
763cd6e3 184{
442b829a
RS
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;
763cd6e3
RS
192}
193
194bool_t libnfs_zdr_bool(ZDR *zdrs, bool_t *b)
195{
196 return libnfs_zdr_u_int(zdrs, (uint32_t *)b);
197}
198
199bool_t libnfs_zdr_void(void)
200{
201 return TRUE;
202}
203
204bool_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
228bool_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;
1f3f0d58
PL
234 if (zdrs->pos & 3) {
235 memset(&zdrs->buf[zdrs->pos], 0x00, 4 - (zdrs->pos & 3));
236 }
763cd6e3
RS
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
249bool_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
280bool_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++) {
5f08d03e 301 if (!proc(zdrs, *arrp + i * elsize)) {
763cd6e3
RS
302 return FALSE;
303 }
304 }
305 return TRUE;
306}
307
308void libnfs_zdr_free(zdrproc_t proc, char *objp)
309{
310}
311
312static 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
020f1728 318 if (!libnfs_zdr_bytes(zdrs, &auth->oa_base, &auth->oa_length, auth->oa_length)) {
763cd6e3
RS
319 return FALSE;
320 }
321
322 return TRUE;
323}
324
f0cb8042 325static bool_t libnfs_rpc_call_body(struct rpc_context *rpc, ZDR *zdrs, struct call_body *cmb)
763cd6e3 326{
aab6538b 327 if (!libnfs_zdr_u_int(zdrs, &cmb->rpcvers)) {
f0cb8042
RS
328 rpc_set_error(rpc, "libnfs_rpc_call_body failed to encode "
329 "RPCVERS");
763cd6e3
RS
330 return FALSE;
331 }
332
aab6538b 333 if (!libnfs_zdr_u_int(zdrs, &cmb->prog)) {
f0cb8042
RS
334 rpc_set_error(rpc, "libnfs_rpc_call_body failed to encode "
335 "PROG");
763cd6e3
RS
336 return FALSE;
337 }
338
aab6538b 339 if (!libnfs_zdr_u_int(zdrs, &cmb->vers)) {
f0cb8042
RS
340 rpc_set_error(rpc, "libnfs_rpc_call_body failed to encode "
341 "VERS");
763cd6e3
RS
342 return FALSE;
343 }
344
aab6538b 345 if (!libnfs_zdr_u_int(zdrs, &cmb->proc)) {
f0cb8042
RS
346 rpc_set_error(rpc, "libnfs_rpc_call_body failed to encode "
347 "PROC");
763cd6e3
RS
348 return FALSE;
349 }
350
aab6538b 351 if (!libnfs_opaque_auth(zdrs, &cmb->cred)) {
f0cb8042
RS
352 rpc_set_error(rpc, "libnfs_rpc_call_body failed to encode "
353 "CRED");
763cd6e3
RS
354 return FALSE;
355 }
356
aab6538b 357 if (!libnfs_opaque_auth(zdrs, &cmb->verf)) {
f0cb8042
RS
358 rpc_set_error(rpc, "libnfs_rpc_call_body failed to encode "
359 "VERF");
763cd6e3
RS
360 return FALSE;
361 }
10a0ceaa
RS
362
363 return TRUE;
763cd6e3
RS
364}
365
366static bool_t libnfs_accepted_reply(ZDR *zdrs, struct accepted_reply *ar)
367{
aab6538b 368 if (!libnfs_opaque_auth(zdrs, &ar->verf)) {
763cd6e3
RS
369 return FALSE;
370 }
371
aab6538b 372 if (!libnfs_zdr_u_int(zdrs, &ar->stat)) {
763cd6e3
RS
373 return FALSE;
374 }
375
aab6538b 376 switch (ar->stat) {
763cd6e3 377 case SUCCESS:
aab6538b 378 if (!ar->reply_data.results.proc(zdrs, ar->reply_data.results.where)) {
763cd6e3
RS
379 return FALSE;
380 }
381 return TRUE;
382 case PROG_MISMATCH:
aab6538b 383 if (!libnfs_zdr_u_int(zdrs, &ar->reply_data.mismatch_info.low)) {
763cd6e3
RS
384 return FALSE;
385 }
aab6538b 386 if (!libnfs_zdr_u_int(zdrs, &ar->reply_data.mismatch_info.high)) {
763cd6e3
RS
387 return FALSE;
388 }
389 return TRUE;
390 default:
391 return TRUE;
392 }
393
394 return FALSE;
395}
396
aab6538b 397static bool_t libnfs_rejected_reply(ZDR *zdrs, struct rejected_reply *rr)
763cd6e3 398{
aab6538b
RS
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;
763cd6e3
RS
422}
423
f0cb8042 424static bool_t libnfs_rpc_reply_body(struct rpc_context *rpc, ZDR *zdrs, struct reply_body *rmb)
763cd6e3 425{
aab6538b 426 if (!libnfs_zdr_u_int(zdrs, &rmb->stat)) {
f0cb8042
RS
427 rpc_set_error(rpc, "libnfs_rpc_reply_body failed to decode "
428 "STAT");
763cd6e3
RS
429 return FALSE;
430 }
431
aab6538b 432 switch (rmb->stat) {
763cd6e3 433 case MSG_ACCEPTED:
aab6538b 434 if (!libnfs_accepted_reply(zdrs, &rmb->reply.areply)) {
f0cb8042
RS
435 rpc_set_error(rpc, "libnfs_rpc_reply_body failed to "
436 "decode ACCEPTED");
763cd6e3
RS
437 return FALSE;
438 }
439 return TRUE;
440 case MSG_DENIED:
aab6538b 441 if (!libnfs_rejected_reply(zdrs, &rmb->reply.rreply)) {
f0cb8042
RS
442 rpc_set_error(rpc, "libnfs_rpc_reply_body failed to "
443 "decode DENIED");
763cd6e3
RS
444 return FALSE;
445 }
446 return TRUE;
447 }
448
f0cb8042
RS
449 rpc_set_error(rpc, "libnfs_rpc_reply_body failed to "
450 "decode. Neither ACCEPTED nor DENIED");
763cd6e3
RS
451 return FALSE;
452}
453
f0cb8042 454static bool_t libnfs_rpc_msg(struct rpc_context *rpc, ZDR *zdrs, struct rpc_msg *msg)
763cd6e3 455{
f0cb8042
RS
456 int ret;
457
aab6538b 458 if (!libnfs_zdr_u_int(zdrs, &msg->xid)) {
f0cb8042 459 rpc_set_error(rpc, "libnfs_rpc_msg failed to decode XID");
763cd6e3
RS
460 return FALSE;
461 }
462
aab6538b 463 if (!libnfs_zdr_u_int(zdrs, &msg->direction)) {
f0cb8042 464 rpc_set_error(rpc, "libnfs_rpc_msg failed to decode DIRECTION");
763cd6e3
RS
465 return FALSE;
466 }
467
aab6538b 468 switch (msg->direction) {
763cd6e3 469 case CALL:
f0cb8042 470 ret = libnfs_rpc_call_body(rpc, zdrs, &msg->body.cbody);
b25c3aed
RS
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 }
f0cb8042 475 return ret;
763cd6e3 476 case REPLY:
f0cb8042 477 ret = libnfs_rpc_reply_body(rpc, zdrs, &msg->body.rbody);
b25c3aed
RS
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 }
f0cb8042 482 return ret;
763cd6e3 483 default:
f0cb8042
RS
484 rpc_set_error(rpc, "libnfs_rpc_msg failed to decode. "
485 "Neither CALL not REPLY");
763cd6e3
RS
486 return FALSE;
487 }
488}
489
f0cb8042 490bool_t libnfs_zdr_callmsg(struct rpc_context *rpc, ZDR *zdrs, struct rpc_msg *msg)
763cd6e3 491{
f0cb8042 492 return libnfs_rpc_msg(rpc, zdrs, msg);
763cd6e3
RS
493}
494
f0cb8042 495bool_t libnfs_zdr_replymsg(struct rpc_context *rpc, ZDR *zdrs, struct rpc_msg *msg)
763cd6e3 496{
f0cb8042 497 return libnfs_rpc_msg(rpc, zdrs, msg);
763cd6e3
RS
498}
499
67ba2239 500struct AUTH *authnone_create(void)
763cd6e3 501{
67ba2239 502 struct AUTH *auth;
763cd6e3 503
67ba2239 504 auth = malloc(sizeof(struct AUTH));
763cd6e3
RS
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
67ba2239 519struct AUTH *libnfs_authunix_create(char *host, uint32_t uid, uint32_t gid, uint32_t len, uint32_t *groups)
763cd6e3 520{
67ba2239 521 struct AUTH *auth;
763cd6e3
RS
522 int size;
523 uint32_t *buf;
524 int idx;
525
526 size = 4 + 4 + ((strlen(host) + 3) & ~3) + 4 + 4 + 4 + len * 4;
67ba2239 527 auth = malloc(sizeof(struct AUTH));
b554c8e8 528 memset(auth, 0x00, sizeof(struct AUTH));
763cd6e3
RS
529 auth->ah_cred.oa_flavor = AUTH_UNIX;
530 auth->ah_cred.oa_length = size;
531 auth->ah_cred.oa_base = malloc(size);
532
b554c8e8 533 memset(auth->ah_cred.oa_base, 0x00, size);
45670bd0 534 buf = (uint32_t *)auth->ah_cred.oa_base;
763cd6e3
RS
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
67ba2239 557struct AUTH *libnfs_authunix_create_default(void)
763cd6e3 558{
67a9f57e 559#ifdef WIN32
4e019b25 560 return libnfs_authunix_create("libnfs", 65534, 65534, 0, NULL);
67a9f57e 561#else
43e0e7a7 562 return libnfs_authunix_create("libnfs", getuid(), getgid(), 0, NULL);
67a9f57e 563#endif
763cd6e3
RS
564}
565
67ba2239 566void libnfs_auth_destroy(struct AUTH *auth)
763cd6e3
RS
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