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