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