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