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