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