2 Copyright (C) 2012 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
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.
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.
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/>.
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.
28 #include "win32_compat.h"
32 #include "aros_compat.h"
35 #ifdef HAVE_ARPA_INET_H
36 #include <arpa/inet.h>
43 #include "libnfs-zdr.h"
45 #include "libnfs-raw.h"
46 #include "libnfs-private.h"
48 struct opaque_auth _null_auth
;
50 bool_t
libnfs_zdr_setpos(ZDR
*zdrs
, uint32_t pos
)
57 uint32_t libnfs_zdr_getpos(ZDR
*zdrs
)
62 void libnfs_zdrmem_create(ZDR
*zdrs
, const caddr_t addr
, uint32_t size
, enum zdr_op xop
)
71 static void *zdr_malloc(ZDR
*zdrs
, uint32_t size
)
75 mem
= malloc(sizeof(struct zdr_mem
));
76 mem
->next
= zdrs
->mem
;
78 mem
->buf
= malloc(mem
->size
);
84 void libnfs_zdr_destroy(ZDR
*zdrs
)
86 while (zdrs
->mem
!= NULL
) {
87 struct zdr_mem
*mem
= zdrs
->mem
->next
;
94 bool_t
libnfs_zdr_u_int(ZDR
*zdrs
, uint32_t *u
)
96 if (zdrs
->pos
+ 4 > zdrs
->size
) {
100 switch (zdrs
->x_op
) {
102 *(uint32_t *)&zdrs
->buf
[zdrs
->pos
] = htonl(*u
);
107 *u
= ntohl(*(uint32_t *)&zdrs
->buf
[zdrs
->pos
]);
116 bool_t
libnfs_zdr_int(ZDR
*zdrs
, int32_t *i
)
118 return libnfs_zdr_u_int(zdrs
, (uint32_t *)i
);
121 bool_t
libnfs_zdr_uint64_t(ZDR
*zdrs
, uint64_t *u
)
123 if (zdrs
->pos
+ 8 > zdrs
->size
) {
127 switch (zdrs
->x_op
) {
129 *(uint32_t *)&zdrs
->buf
[zdrs
->pos
] = htonl((*u
>> 32));
131 *(uint32_t *)&zdrs
->buf
[zdrs
->pos
] = htonl((*u
& 0xffffffff));
136 *u
= ntohl(*(uint32_t *)&zdrs
->buf
[zdrs
->pos
]);
139 *u
|= (uint32_t)ntohl(*(uint32_t *)&zdrs
->buf
[zdrs
->pos
]);
148 bool_t
libnfs_zdr_int64_t(ZDR
*zdrs
, int64_t *i
)
150 return libnfs_zdr_uint64_t(zdrs
, (uint64_t *)i
);
153 bool_t
libnfs_zdr_bytes(ZDR
*zdrs
, char **bufp
, uint32_t *size
, uint32_t maxsize
)
155 if (!libnfs_zdr_u_int(zdrs
, size
)) {
159 if (zdrs
->pos
+ *size
> zdrs
->size
) {
163 switch (zdrs
->x_op
) {
165 memcpy(&zdrs
->buf
[zdrs
->pos
], *bufp
, *size
);
167 zdrs
->pos
= (zdrs
->pos
+ 3) & ~3;
171 *bufp
= zdr_malloc(zdrs
, *size
);
173 memcpy(*bufp
, &zdrs
->buf
[zdrs
->pos
], *size
);
175 zdrs
->pos
= (zdrs
->pos
+ 3) & ~3;
183 bool_t
libnfs_zdr_enum(ZDR
*zdrs
, enum_t
*e
)
188 ret
= libnfs_zdr_u_int(zdrs
, (uint32_t *)&i
);
194 bool_t
libnfs_zdr_bool(ZDR
*zdrs
, bool_t
*b
)
196 return libnfs_zdr_u_int(zdrs
, (uint32_t *)b
);
199 bool_t
libnfs_zdr_void(void)
204 bool_t
libnfs_zdr_pointer(ZDR
*zdrs
, char **objp
, uint32_t size
, zdrproc_t proc
)
208 more_data
= (*objp
!= NULL
);
210 if (!libnfs_zdr_bool(zdrs
, &more_data
)) {
213 if (more_data
== 0) {
218 if (zdrs
->x_op
== ZDR_DECODE
) {
219 *objp
= zdr_malloc(zdrs
, size
);
223 memset(*objp
, 0, size
);
225 return proc(zdrs
, *objp
);
228 bool_t
libnfs_zdr_opaque(ZDR
*zdrs
, char *objp
, uint32_t size
)
230 switch (zdrs
->x_op
) {
232 memcpy(&zdrs
->buf
[zdrs
->pos
], objp
, size
);
235 memset(&zdrs
->buf
[zdrs
->pos
], 0x00, 4 - (zdrs
->pos
& 3));
237 zdrs
->pos
= (zdrs
->pos
+ 3) & ~3;
240 memcpy(objp
, &zdrs
->buf
[zdrs
->pos
], size
);
242 zdrs
->pos
= (zdrs
->pos
+ 3) & ~3;
249 bool_t
libnfs_zdr_string(ZDR
*zdrs
, char **strp
, uint32_t maxsize
)
253 if (zdrs
->x_op
== ZDR_ENCODE
) {
254 size
= strlen(*strp
);
257 if (!libnfs_zdr_u_int(zdrs
, &size
)) {
261 if (zdrs
->pos
+ size
> zdrs
->size
) {
265 switch (zdrs
->x_op
) {
267 return libnfs_zdr_opaque(zdrs
, *strp
, size
);
269 *strp
= zdr_malloc(zdrs
, size
+ 1);
274 return libnfs_zdr_opaque(zdrs
, *strp
, size
);
280 bool_t
libnfs_zdr_array(ZDR
*zdrs
, char **arrp
, uint32_t *size
, uint32_t maxsize
, uint32_t elsize
, zdrproc_t proc
)
284 if (!libnfs_zdr_u_int(zdrs
, size
)) {
288 if (zdrs
->pos
+ *size
* elsize
> zdrs
->size
) {
292 if (zdrs
->x_op
== ZDR_DECODE
) {
293 *arrp
= zdr_malloc(zdrs
, *size
* elsize
);
297 memset(*arrp
, 0, *size
* elsize
);
300 for (i
= 0; i
< *size
; i
++) {
301 if (!proc(zdrs
, *arrp
+ i
* elsize
)) {
308 void libnfs_zdr_free(zdrproc_t proc
, char *objp
)
312 static bool_t
libnfs_opaque_auth(ZDR
*zdrs
, struct opaque_auth
*auth
)
314 if (!libnfs_zdr_u_int(zdrs
, &auth
->oa_flavor
)) {
318 if (!libnfs_zdr_bytes(zdrs
, &auth
->oa_base
, &auth
->oa_length
, auth
->oa_length
)) {
325 static bool_t
libnfs_rpc_call_body(struct rpc_context
*rpc
, ZDR
*zdrs
, struct call_body
*cmb
)
327 if (!libnfs_zdr_u_int(zdrs
, &cmb
->rpcvers
)) {
328 rpc_set_error(rpc
, "libnfs_rpc_call_body failed to encode "
333 if (!libnfs_zdr_u_int(zdrs
, &cmb
->prog
)) {
334 rpc_set_error(rpc
, "libnfs_rpc_call_body failed to encode "
339 if (!libnfs_zdr_u_int(zdrs
, &cmb
->vers
)) {
340 rpc_set_error(rpc
, "libnfs_rpc_call_body failed to encode "
345 if (!libnfs_zdr_u_int(zdrs
, &cmb
->proc
)) {
346 rpc_set_error(rpc
, "libnfs_rpc_call_body failed to encode "
351 if (!libnfs_opaque_auth(zdrs
, &cmb
->cred
)) {
352 rpc_set_error(rpc
, "libnfs_rpc_call_body failed to encode "
357 if (!libnfs_opaque_auth(zdrs
, &cmb
->verf
)) {
358 rpc_set_error(rpc
, "libnfs_rpc_call_body failed to encode "
366 static bool_t
libnfs_accepted_reply(ZDR
*zdrs
, struct accepted_reply
*ar
)
368 if (!libnfs_opaque_auth(zdrs
, &ar
->verf
)) {
372 if (!libnfs_zdr_u_int(zdrs
, &ar
->stat
)) {
378 if (!ar
->reply_data
.results
.proc(zdrs
, ar
->reply_data
.results
.where
)) {
383 if (!libnfs_zdr_u_int(zdrs
, &ar
->reply_data
.mismatch_info
.low
)) {
386 if (!libnfs_zdr_u_int(zdrs
, &ar
->reply_data
.mismatch_info
.high
)) {
397 static bool_t
libnfs_rejected_reply(ZDR
*zdrs
, struct rejected_reply
*rr
)
399 if (!libnfs_zdr_u_int(zdrs
, &rr
->stat
)) {
405 if (!libnfs_zdr_u_int(zdrs
, &rr
->reject_data
.mismatch_info
.low
)) {
408 if (!libnfs_zdr_u_int(zdrs
, &rr
->reject_data
.mismatch_info
.high
)) {
413 if (!libnfs_zdr_u_int(zdrs
, &rr
->reject_data
.stat
)) {
424 static bool_t
libnfs_rpc_reply_body(struct rpc_context
*rpc
, ZDR
*zdrs
, struct reply_body
*rmb
)
426 if (!libnfs_zdr_u_int(zdrs
, &rmb
->stat
)) {
427 rpc_set_error(rpc
, "libnfs_rpc_reply_body failed to decode "
434 if (!libnfs_accepted_reply(zdrs
, &rmb
->reply
.areply
)) {
435 rpc_set_error(rpc
, "libnfs_rpc_reply_body failed to "
441 if (!libnfs_rejected_reply(zdrs
, &rmb
->reply
.rreply
)) {
442 rpc_set_error(rpc
, "libnfs_rpc_reply_body failed to "
449 rpc_set_error(rpc
, "libnfs_rpc_reply_body failed to "
450 "decode. Neither ACCEPTED nor DENIED");
454 static bool_t
libnfs_rpc_msg(struct rpc_context
*rpc
, ZDR
*zdrs
, struct rpc_msg
*msg
)
458 if (!libnfs_zdr_u_int(zdrs
, &msg
->xid
)) {
459 rpc_set_error(rpc
, "libnfs_rpc_msg failed to decode XID");
463 if (!libnfs_zdr_u_int(zdrs
, &msg
->direction
)) {
464 rpc_set_error(rpc
, "libnfs_rpc_msg failed to decode DIRECTION");
468 switch (msg
->direction
) {
470 ret
= libnfs_rpc_call_body(rpc
, zdrs
, &msg
->body
.cbody
);
472 rpc_set_error(rpc
, "libnfs_rpc_msg failed to encode "
473 "CALL, ret=%d: %s", ret
, rpc_get_error(rpc
));
477 ret
= libnfs_rpc_reply_body(rpc
, zdrs
, &msg
->body
.rbody
);
479 rpc_set_error(rpc
, "libnfs_rpc_msg failed to decode "
480 "REPLY, ret=%d: %s", ret
, rpc_get_error(rpc
));
484 rpc_set_error(rpc
, "libnfs_rpc_msg failed to decode. "
485 "Neither CALL not REPLY");
490 bool_t
libnfs_zdr_callmsg(struct rpc_context
*rpc
, ZDR
*zdrs
, struct rpc_msg
*msg
)
492 return libnfs_rpc_msg(rpc
, zdrs
, msg
);
495 bool_t
libnfs_zdr_replymsg(struct rpc_context
*rpc
, ZDR
*zdrs
, struct rpc_msg
*msg
)
497 return libnfs_rpc_msg(rpc
, zdrs
, msg
);
500 struct AUTH
*authnone_create(void)
504 auth
= malloc(sizeof(struct AUTH
));
506 auth
->ah_cred
.oa_flavor
= AUTH_NONE
;
507 auth
->ah_cred
.oa_length
= 0;
508 auth
->ah_cred
.oa_base
= NULL
;
510 auth
->ah_verf
.oa_flavor
= AUTH_NONE
;
511 auth
->ah_verf
.oa_length
= 0;
512 auth
->ah_verf
.oa_base
= NULL
;
514 auth
->ah_private
= NULL
;
519 struct AUTH
*libnfs_authunix_create(char *host
, uint32_t uid
, uint32_t gid
, uint32_t len
, uint32_t *groups
)
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
);
533 memset(auth
->ah_cred
.oa_base
, 0x00, size
);
534 buf
= (uint32_t *)auth
->ah_cred
.oa_base
;
536 buf
[idx
++] = htonl(time(NULL
));
537 buf
[idx
++] = htonl(strlen(host
));
538 memcpy(&buf
[2], host
, strlen(host
));
540 idx
+= (strlen(host
) + 3) >> 2;
541 buf
[idx
++] = htonl(uid
);
542 buf
[idx
++] = htonl(gid
);
543 buf
[idx
++] = htonl(len
);
545 buf
[idx
++] = htonl(*groups
++);
548 auth
->ah_verf
.oa_flavor
= AUTH_NONE
;
549 auth
->ah_verf
.oa_length
= 0;
550 auth
->ah_verf
.oa_base
= NULL
;
552 auth
->ah_private
= NULL
;
557 struct AUTH
*libnfs_authunix_create_default(void)
560 return libnfs_authunix_create("libnfs", 65534, 65534, 0, NULL
);
562 return libnfs_authunix_create("libnfs", getuid(), getgid(), 0, NULL
);
566 void libnfs_auth_destroy(struct AUTH
*auth
)
568 if (auth
->ah_cred
.oa_base
) {
569 free(auth
->ah_cred
.oa_base
);
571 if (auth
->ah_verf
.oa_base
) {
572 free(auth
->ah_verf
.oa_base
);