Merge pull request #47 from Memphiz/win32fix3
[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 WIN32
24 #include "win32_compat.h"
25 #endif
26
27 #ifdef AROS
28 #include "aros_compat.h"
29 #endif
30
31 #include <stdlib.h>
32 #include <string.h>
33 #include <time.h>
34 #include "libnfs-zdr.h"
35
36 struct opaque_auth _null_auth;
37
38 bool_t libnfs_zdr_setpos(ZDR *zdrs, uint32_t pos)
39 {
40 zdrs->pos = pos;
41
42 return TRUE;
43 }
44
45 uint32_t libnfs_zdr_getpos(ZDR *zdrs)
46 {
47 return zdrs->pos;
48 }
49
50 void 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
59 static 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
72 void 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
82 bool_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
104 bool_t libnfs_zdr_int(ZDR *zdrs, int32_t *i)
105 {
106 return libnfs_zdr_u_int(zdrs, (uint32_t *)i);
107 }
108
109 bool_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 |= (uint32_t)ntohl(*(uint32_t *)&zdrs->buf[zdrs->pos]);
128 zdrs->pos += 4;
129 return TRUE;
130 break;
131 }
132
133 return FALSE;
134 }
135
136 bool_t libnfs_zdr_quad_t(ZDR *zdrs, int64_t *i)
137 {
138 return libnfs_zdr_u_quad_t(zdrs, (uint64_t *)i);
139 }
140
141 bool_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
171 bool_t libnfs_zdr_enum(ZDR *zdrs, enum_t *e)
172 {
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;
180 }
181
182 bool_t libnfs_zdr_bool(ZDR *zdrs, bool_t *b)
183 {
184 return libnfs_zdr_u_int(zdrs, (uint32_t *)b);
185 }
186
187 bool_t libnfs_zdr_void(void)
188 {
189 return TRUE;
190 }
191
192 bool_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
216 bool_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 if (zdrs->pos & 3) {
223 memset(&zdrs->buf[zdrs->pos], 0x00, 4 - (zdrs->pos & 3));
224 }
225 zdrs->pos = (zdrs->pos + 3) & ~3;
226 return TRUE;
227 case ZDR_DECODE:
228 memcpy(objp, &zdrs->buf[zdrs->pos], size);
229 zdrs->pos += size;
230 zdrs->pos = (zdrs->pos + 3) & ~3;
231 return TRUE;
232 }
233
234 return FALSE;
235 }
236
237 bool_t libnfs_zdr_string(ZDR *zdrs, char **strp, uint32_t maxsize)
238 {
239 uint32_t size;
240
241 if (zdrs->x_op == ZDR_ENCODE) {
242 size = strlen(*strp);
243 }
244
245 if (!libnfs_zdr_u_int(zdrs, &size)) {
246 return FALSE;
247 }
248
249 if (zdrs->pos + size > zdrs->size) {
250 return FALSE;
251 }
252
253 switch (zdrs->x_op) {
254 case ZDR_ENCODE:
255 return libnfs_zdr_opaque(zdrs, *strp, size);
256 case ZDR_DECODE:
257 *strp = zdr_malloc(zdrs, size + 1);
258 if (*strp == NULL) {
259 return FALSE;
260 }
261 (*strp)[size] = 0;
262 return libnfs_zdr_opaque(zdrs, *strp, size);
263 }
264
265 return FALSE;
266 }
267
268 bool_t libnfs_zdr_array(ZDR *zdrs, char **arrp, uint32_t *size, uint32_t maxsize, uint32_t elsize, zdrproc_t proc)
269 {
270 int i;
271
272 if (!libnfs_zdr_u_int(zdrs, size)) {
273 return FALSE;
274 }
275
276 if (zdrs->pos + *size * elsize > zdrs->size) {
277 return FALSE;
278 }
279
280 if (zdrs->x_op == ZDR_DECODE) {
281 *arrp = zdr_malloc(zdrs, *size * elsize);
282 if (*arrp == NULL) {
283 return FALSE;
284 }
285 memset(*arrp, 0, *size * elsize);
286 }
287
288 for (i = 0; i < *size; i++) {
289 if (!proc(zdrs, *arrp + i * elsize)) {
290 return FALSE;
291 }
292 }
293 return TRUE;
294 }
295
296 void libnfs_zdr_free(zdrproc_t proc, char *objp)
297 {
298 }
299
300 static bool_t libnfs_opaque_auth(ZDR *zdrs, struct opaque_auth *auth)
301 {
302 if (!libnfs_zdr_u_int(zdrs, &auth->oa_flavor)) {
303 return FALSE;
304 }
305
306 if (!libnfs_zdr_bytes(zdrs, &auth->oa_base, &auth->oa_length, auth->oa_length)) {
307 return FALSE;
308 }
309
310 return TRUE;
311 }
312
313 static bool_t libnfs_rpc_call_body(ZDR *zdrs, struct call_body *cmb)
314 {
315 if (!libnfs_zdr_u_int(zdrs, &cmb->rpcvers)) {
316 return FALSE;
317 }
318
319 if (!libnfs_zdr_u_int(zdrs, &cmb->prog)) {
320 return FALSE;
321 }
322
323 if (!libnfs_zdr_u_int(zdrs, &cmb->vers)) {
324 return FALSE;
325 }
326
327 if (!libnfs_zdr_u_int(zdrs, &cmb->proc)) {
328 return FALSE;
329 }
330
331 if (!libnfs_opaque_auth(zdrs, &cmb->cred)) {
332 return FALSE;
333 }
334
335 if (!libnfs_opaque_auth(zdrs, &cmb->verf)) {
336 return FALSE;
337 }
338
339 return TRUE;
340 }
341
342 static bool_t libnfs_accepted_reply(ZDR *zdrs, struct accepted_reply *ar)
343 {
344 if (!libnfs_opaque_auth(zdrs, &ar->verf)) {
345 return FALSE;
346 }
347
348 if (!libnfs_zdr_u_int(zdrs, &ar->stat)) {
349 return FALSE;
350 }
351
352 switch (ar->stat) {
353 case SUCCESS:
354 if (!ar->reply_data.results.proc(zdrs, ar->reply_data.results.where)) {
355 return FALSE;
356 }
357 return TRUE;
358 case PROG_MISMATCH:
359 if (!libnfs_zdr_u_int(zdrs, &ar->reply_data.mismatch_info.low)) {
360 return FALSE;
361 }
362 if (!libnfs_zdr_u_int(zdrs, &ar->reply_data.mismatch_info.high)) {
363 return FALSE;
364 }
365 return TRUE;
366 default:
367 return TRUE;
368 }
369
370 return FALSE;
371 }
372
373 static bool_t libnfs_rejected_reply(ZDR *zdrs, struct rejected_reply *rr)
374 {
375 if (!libnfs_zdr_u_int(zdrs, &rr->stat)) {
376 return FALSE;
377 }
378
379 switch (rr->stat) {
380 case RPC_MISMATCH:
381 if (!libnfs_zdr_u_int(zdrs, &rr->reject_data.mismatch_info.low)) {
382 return FALSE;
383 }
384 if (!libnfs_zdr_u_int(zdrs, &rr->reject_data.mismatch_info.high)) {
385 return FALSE;
386 }
387 return TRUE;
388 case AUTH_ERROR:
389 if (!libnfs_zdr_u_int(zdrs, &rr->reject_data.stat)) {
390 return FALSE;
391 }
392 return TRUE;
393 default:
394 return TRUE;
395 }
396
397 return FALSE;
398 }
399
400 static bool_t libnfs_rpc_reply_body(ZDR *zdrs, struct reply_body *rmb)
401 {
402 if (!libnfs_zdr_u_int(zdrs, &rmb->stat)) {
403 return FALSE;
404 }
405
406 switch (rmb->stat) {
407 case MSG_ACCEPTED:
408 if (!libnfs_accepted_reply(zdrs, &rmb->reply.areply)) {
409 return FALSE;
410 }
411 return TRUE;
412 case MSG_DENIED:
413 if (!libnfs_rejected_reply(zdrs, &rmb->reply.rreply)) {
414 return FALSE;
415 }
416 return TRUE;
417 }
418
419 return FALSE;
420 }
421
422 static bool_t libnfs_rpc_msg(ZDR *zdrs, struct rpc_msg *msg)
423 {
424 if (!libnfs_zdr_u_int(zdrs, &msg->xid)) {
425 return FALSE;
426 }
427
428 if (!libnfs_zdr_u_int(zdrs, &msg->direction)) {
429 return FALSE;
430 }
431
432 switch (msg->direction) {
433 case CALL:
434 return libnfs_rpc_call_body(zdrs, &msg->body.cbody);
435 break;
436 case REPLY:
437 return libnfs_rpc_reply_body(zdrs, &msg->body.rbody);
438 break;
439 default:
440 return FALSE;
441 }
442 }
443
444 bool_t libnfs_zdr_callmsg(ZDR *zdrs, struct rpc_msg *msg)
445 {
446 return libnfs_rpc_msg(zdrs, msg);
447 }
448
449 bool_t libnfs_zdr_replymsg(ZDR *zdrs, struct rpc_msg *msg)
450 {
451 return libnfs_rpc_msg(zdrs, msg);
452 }
453
454 struct AUTH *authnone_create(void)
455 {
456 struct AUTH *auth;
457
458 auth = malloc(sizeof(struct AUTH));
459
460 auth->ah_cred.oa_flavor = AUTH_NONE;
461 auth->ah_cred.oa_length = 0;
462 auth->ah_cred.oa_base = NULL;
463
464 auth->ah_verf.oa_flavor = AUTH_NONE;
465 auth->ah_verf.oa_length = 0;
466 auth->ah_verf.oa_base = NULL;
467
468 auth->ah_private = NULL;
469
470 return auth;
471 }
472
473 struct AUTH *libnfs_authunix_create(char *host, uint32_t uid, uint32_t gid, uint32_t len, uint32_t *groups)
474 {
475 struct AUTH *auth;
476 int size;
477 uint32_t *buf;
478 int idx;
479
480 size = 4 + 4 + ((strlen(host) + 3) & ~3) + 4 + 4 + 4 + len * 4;
481 auth = malloc(sizeof(struct AUTH));
482 memset(auth, 0x00, sizeof(struct AUTH));
483 auth->ah_cred.oa_flavor = AUTH_UNIX;
484 auth->ah_cred.oa_length = size;
485 auth->ah_cred.oa_base = malloc(size);
486
487 memset(auth->ah_cred.oa_base, 0x00, size);
488 buf = (uint32_t *)auth->ah_cred.oa_base;
489 idx = 0;
490 buf[idx++] = htonl(time(NULL));
491 buf[idx++] = htonl(strlen(host));
492 memcpy(&buf[2], host, strlen(host));
493
494 idx += (strlen(host) + 3) >> 2;
495 buf[idx++] = htonl(uid);
496 buf[idx++] = htonl(gid);
497 buf[idx++] = htonl(len);
498 while (len-- > 0) {
499 buf[idx++] = htonl(*groups++);
500 }
501
502 auth->ah_verf.oa_flavor = AUTH_NONE;
503 auth->ah_verf.oa_length = 0;
504 auth->ah_verf.oa_base = NULL;
505
506 auth->ah_private = NULL;
507
508 return auth;
509 }
510
511 struct AUTH *libnfs_authunix_create_default(void)
512 {
513 #ifdef WIN32
514 return libnfs_authunix_create("libnfs", 65534, 65534, 0, NULL);
515 #else
516 return libnfs_authunix_create("libnfs", getuid(), getgid(), 0, NULL);
517 #endif
518 }
519
520 void libnfs_auth_destroy(struct AUTH *auth)
521 {
522 if (auth->ah_cred.oa_base) {
523 free(auth->ah_cred.oa_base);
524 }
525 if (auth->ah_verf.oa_base) {
526 free(auth->ah_verf.oa_base);
527 }
528 free(auth);
529 }
530