fix implicit decl warnings
[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
45 struct opaque_auth _null_auth;
46
47 bool_t libnfs_zdr_setpos(ZDR *zdrs, uint32_t pos)
48 {
49 zdrs->pos = pos;
50
51 return TRUE;
52 }
53
54 uint32_t libnfs_zdr_getpos(ZDR *zdrs)
55 {
56 return zdrs->pos;
57 }
58
59 void 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
68 static 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
81 void 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
91 bool_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
113 bool_t libnfs_zdr_int(ZDR *zdrs, int32_t *i)
114 {
115 return libnfs_zdr_u_int(zdrs, (uint32_t *)i);
116 }
117
118 bool_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;
136 *u |= (uint32_t)ntohl(*(uint32_t *)&zdrs->buf[zdrs->pos]);
137 zdrs->pos += 4;
138 return TRUE;
139 break;
140 }
141
142 return FALSE;
143 }
144
145 bool_t libnfs_zdr_quad_t(ZDR *zdrs, int64_t *i)
146 {
147 return libnfs_zdr_u_quad_t(zdrs, (uint64_t *)i);
148 }
149
150 bool_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
180 bool_t libnfs_zdr_enum(ZDR *zdrs, enum_t *e)
181 {
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;
189 }
190
191 bool_t libnfs_zdr_bool(ZDR *zdrs, bool_t *b)
192 {
193 return libnfs_zdr_u_int(zdrs, (uint32_t *)b);
194 }
195
196 bool_t libnfs_zdr_void(void)
197 {
198 return TRUE;
199 }
200
201 bool_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
225 bool_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;
231 if (zdrs->pos & 3) {
232 memset(&zdrs->buf[zdrs->pos], 0x00, 4 - (zdrs->pos & 3));
233 }
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
246 bool_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
277 bool_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++) {
298 if (!proc(zdrs, *arrp + i * elsize)) {
299 return FALSE;
300 }
301 }
302 return TRUE;
303 }
304
305 void libnfs_zdr_free(zdrproc_t proc, char *objp)
306 {
307 }
308
309 static 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
315 if (!libnfs_zdr_bytes(zdrs, &auth->oa_base, &auth->oa_length, auth->oa_length)) {
316 return FALSE;
317 }
318
319 return TRUE;
320 }
321
322 static bool_t libnfs_rpc_call_body(struct rpc_context *rpc, ZDR *zdrs, struct call_body *cmb)
323 {
324 if (!libnfs_zdr_u_int(zdrs, &cmb->rpcvers)) {
325 rpc_set_error(rpc, "libnfs_rpc_call_body failed to encode "
326 "RPCVERS");
327 return FALSE;
328 }
329
330 if (!libnfs_zdr_u_int(zdrs, &cmb->prog)) {
331 rpc_set_error(rpc, "libnfs_rpc_call_body failed to encode "
332 "PROG");
333 return FALSE;
334 }
335
336 if (!libnfs_zdr_u_int(zdrs, &cmb->vers)) {
337 rpc_set_error(rpc, "libnfs_rpc_call_body failed to encode "
338 "VERS");
339 return FALSE;
340 }
341
342 if (!libnfs_zdr_u_int(zdrs, &cmb->proc)) {
343 rpc_set_error(rpc, "libnfs_rpc_call_body failed to encode "
344 "PROC");
345 return FALSE;
346 }
347
348 if (!libnfs_opaque_auth(zdrs, &cmb->cred)) {
349 rpc_set_error(rpc, "libnfs_rpc_call_body failed to encode "
350 "CRED");
351 return FALSE;
352 }
353
354 if (!libnfs_opaque_auth(zdrs, &cmb->verf)) {
355 rpc_set_error(rpc, "libnfs_rpc_call_body failed to encode "
356 "VERF");
357 return FALSE;
358 }
359
360 return TRUE;
361 }
362
363 static bool_t libnfs_accepted_reply(ZDR *zdrs, struct accepted_reply *ar)
364 {
365 if (!libnfs_opaque_auth(zdrs, &ar->verf)) {
366 return FALSE;
367 }
368
369 if (!libnfs_zdr_u_int(zdrs, &ar->stat)) {
370 return FALSE;
371 }
372
373 switch (ar->stat) {
374 case SUCCESS:
375 if (!ar->reply_data.results.proc(zdrs, ar->reply_data.results.where)) {
376 return FALSE;
377 }
378 return TRUE;
379 case PROG_MISMATCH:
380 if (!libnfs_zdr_u_int(zdrs, &ar->reply_data.mismatch_info.low)) {
381 return FALSE;
382 }
383 if (!libnfs_zdr_u_int(zdrs, &ar->reply_data.mismatch_info.high)) {
384 return FALSE;
385 }
386 return TRUE;
387 default:
388 return TRUE;
389 }
390
391 return FALSE;
392 }
393
394 static bool_t libnfs_rejected_reply(ZDR *zdrs, struct rejected_reply *rr)
395 {
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;
419 }
420
421 static bool_t libnfs_rpc_reply_body(struct rpc_context *rpc, ZDR *zdrs, struct reply_body *rmb)
422 {
423 if (!libnfs_zdr_u_int(zdrs, &rmb->stat)) {
424 rpc_set_error(rpc, "libnfs_rpc_reply_body failed to decode "
425 "STAT");
426 return FALSE;
427 }
428
429 switch (rmb->stat) {
430 case MSG_ACCEPTED:
431 if (!libnfs_accepted_reply(zdrs, &rmb->reply.areply)) {
432 rpc_set_error(rpc, "libnfs_rpc_reply_body failed to "
433 "decode ACCEPTED");
434 return FALSE;
435 }
436 return TRUE;
437 case MSG_DENIED:
438 if (!libnfs_rejected_reply(zdrs, &rmb->reply.rreply)) {
439 rpc_set_error(rpc, "libnfs_rpc_reply_body failed to "
440 "decode DENIED");
441 return FALSE;
442 }
443 return TRUE;
444 }
445
446 rpc_set_error(rpc, "libnfs_rpc_reply_body failed to "
447 "decode. Neither ACCEPTED nor DENIED");
448 return FALSE;
449 }
450
451 static bool_t libnfs_rpc_msg(struct rpc_context *rpc, ZDR *zdrs, struct rpc_msg *msg)
452 {
453 int ret;
454
455 if (!libnfs_zdr_u_int(zdrs, &msg->xid)) {
456 rpc_set_error(rpc, "libnfs_rpc_msg failed to decode XID");
457 return FALSE;
458 }
459
460 if (!libnfs_zdr_u_int(zdrs, &msg->direction)) {
461 rpc_set_error(rpc, "libnfs_rpc_msg failed to decode DIRECTION");
462 return FALSE;
463 }
464
465 switch (msg->direction) {
466 case CALL:
467 ret = libnfs_rpc_call_body(rpc, zdrs, &msg->body.cbody);
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 }
472 return ret;
473 case REPLY:
474 ret = libnfs_rpc_reply_body(rpc, zdrs, &msg->body.rbody);
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 }
479 return ret;
480 default:
481 rpc_set_error(rpc, "libnfs_rpc_msg failed to decode. "
482 "Neither CALL not REPLY");
483 return FALSE;
484 }
485 }
486
487 bool_t libnfs_zdr_callmsg(struct rpc_context *rpc, ZDR *zdrs, struct rpc_msg *msg)
488 {
489 return libnfs_rpc_msg(rpc, zdrs, msg);
490 }
491
492 bool_t libnfs_zdr_replymsg(struct rpc_context *rpc, ZDR *zdrs, struct rpc_msg *msg)
493 {
494 return libnfs_rpc_msg(rpc, zdrs, msg);
495 }
496
497 struct AUTH *authnone_create(void)
498 {
499 struct AUTH *auth;
500
501 auth = malloc(sizeof(struct AUTH));
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
516 struct AUTH *libnfs_authunix_create(char *host, uint32_t uid, uint32_t gid, uint32_t len, uint32_t *groups)
517 {
518 struct AUTH *auth;
519 int size;
520 uint32_t *buf;
521 int idx;
522
523 size = 4 + 4 + ((strlen(host) + 3) & ~3) + 4 + 4 + 4 + len * 4;
524 auth = malloc(sizeof(struct AUTH));
525 memset(auth, 0x00, sizeof(struct AUTH));
526 auth->ah_cred.oa_flavor = AUTH_UNIX;
527 auth->ah_cred.oa_length = size;
528 auth->ah_cred.oa_base = malloc(size);
529
530 memset(auth->ah_cred.oa_base, 0x00, size);
531 buf = (uint32_t *)auth->ah_cred.oa_base;
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
554 struct AUTH *libnfs_authunix_create_default(void)
555 {
556 #ifdef WIN32
557 return libnfs_authunix_create("libnfs", 65534, 65534, 0, NULL);
558 #else
559 return libnfs_authunix_create("libnfs", getuid(), getgid(), 0, NULL);
560 #endif
561 }
562
563 void libnfs_auth_destroy(struct AUTH *auth)
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