fix implicit decl warnings
[deb_libnfs.git] / lib / libnfs-zdr.c
... / ...
CommitLineData
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
45struct opaque_auth _null_auth;
46
47bool_t libnfs_zdr_setpos(ZDR *zdrs, uint32_t pos)
48{
49 zdrs->pos = pos;
50
51 return TRUE;
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;
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
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
180bool_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
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;
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
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++) {
298 if (!proc(zdrs, *arrp + i * elsize)) {
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
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
322static 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
363static 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
394static 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
421static 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
451static 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
487bool_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
492bool_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
497struct 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
516struct 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
554struct 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
563void 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