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