fix compiler warnings
[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, int32_t *e)
164 {
165 return libnfs_zdr_u_int(zdrs, (uint32_t *)e);
166 }
167
168 bool_t libnfs_zdr_bool(ZDR *zdrs, bool_t *b)
169 {
170 return libnfs_zdr_u_int(zdrs, (uint32_t *)b);
171 }
172
173 bool_t libnfs_zdr_void(void)
174 {
175 return TRUE;
176 }
177
178 bool_t libnfs_zdr_pointer(ZDR *zdrs, char **objp, uint32_t size, zdrproc_t proc)
179 {
180 bool_t more_data;
181
182 more_data = (*objp != NULL);
183
184 if (!libnfs_zdr_bool(zdrs, &more_data)) {
185 return FALSE;
186 }
187 if (more_data == 0) {
188 *objp = NULL;
189 return TRUE;
190 }
191
192 if (zdrs->x_op == ZDR_DECODE) {
193 *objp = zdr_malloc(zdrs, size);
194 if (*objp == NULL) {
195 return FALSE;
196 }
197 memset(*objp, 0, size);
198 }
199 return proc(zdrs, *objp);
200 }
201
202 bool_t libnfs_zdr_opaque(ZDR *zdrs, char *objp, uint32_t size)
203 {
204 switch (zdrs->x_op) {
205 case ZDR_ENCODE:
206 memcpy(&zdrs->buf[zdrs->pos], objp, size);
207 zdrs->pos += size;
208 zdrs->pos = (zdrs->pos + 3) & ~3;
209 return TRUE;
210 case ZDR_DECODE:
211 memcpy(objp, &zdrs->buf[zdrs->pos], size);
212 zdrs->pos += size;
213 zdrs->pos = (zdrs->pos + 3) & ~3;
214 return TRUE;
215 }
216
217 return FALSE;
218 }
219
220 bool_t libnfs_zdr_string(ZDR *zdrs, char **strp, uint32_t maxsize)
221 {
222 uint32_t size;
223
224 if (zdrs->x_op == ZDR_ENCODE) {
225 size = strlen(*strp);
226 }
227
228 if (!libnfs_zdr_u_int(zdrs, &size)) {
229 return FALSE;
230 }
231
232 if (zdrs->pos + size > zdrs->size) {
233 return FALSE;
234 }
235
236 switch (zdrs->x_op) {
237 case ZDR_ENCODE:
238 return libnfs_zdr_opaque(zdrs, *strp, size);
239 case ZDR_DECODE:
240 *strp = zdr_malloc(zdrs, size + 1);
241 if (*strp == NULL) {
242 return FALSE;
243 }
244 (*strp)[size] = 0;
245 return libnfs_zdr_opaque(zdrs, *strp, size);
246 }
247
248 return FALSE;
249 }
250
251 bool_t libnfs_zdr_array(ZDR *zdrs, char **arrp, uint32_t *size, uint32_t maxsize, uint32_t elsize, zdrproc_t proc)
252 {
253 int i;
254
255 if (!libnfs_zdr_u_int(zdrs, size)) {
256 return FALSE;
257 }
258
259 if (zdrs->pos + *size * elsize > zdrs->size) {
260 return FALSE;
261 }
262
263 if (zdrs->x_op == ZDR_DECODE) {
264 *arrp = zdr_malloc(zdrs, *size * elsize);
265 if (*arrp == NULL) {
266 return FALSE;
267 }
268 memset(*arrp, 0, *size * elsize);
269 }
270
271 for (i = 0; i < *size; i++) {
272 if (proc(zdrs, *arrp + i * elsize)) {
273 return FALSE;
274 }
275 }
276 return TRUE;
277 }
278
279 void libnfs_zdr_free(zdrproc_t proc, char *objp)
280 {
281 }
282
283 static bool_t libnfs_opaque_auth(ZDR *zdrs, struct opaque_auth *auth)
284 {
285 if (!libnfs_zdr_u_int(zdrs, &auth->oa_flavor)) {
286 return FALSE;
287 }
288
289 if (!libnfs_zdr_bytes(zdrs, &auth->oa_base, &auth->oa_length, auth->oa_length)) {
290 return FALSE;
291 }
292
293 return TRUE;
294 }
295
296 static bool_t libnfs_rpc_call_body(ZDR *zdrs, struct call_body *cmb)
297 {
298 if (!libnfs_zdr_u_int(zdrs, &cmb->cb_rpcvers)) {
299 return FALSE;
300 }
301
302 if (!libnfs_zdr_u_int(zdrs, &cmb->cb_prog)) {
303 return FALSE;
304 }
305
306 if (!libnfs_zdr_u_int(zdrs, &cmb->cb_vers)) {
307 return FALSE;
308 }
309
310 if (!libnfs_zdr_u_int(zdrs, &cmb->cb_proc)) {
311 return FALSE;
312 }
313
314 if (!libnfs_opaque_auth(zdrs, &cmb->cb_cred)) {
315 return FALSE;
316 }
317
318 if (!libnfs_opaque_auth(zdrs, &cmb->cb_verf)) {
319 return FALSE;
320 }
321
322 return TRUE;
323 }
324
325 static bool_t libnfs_accepted_reply(ZDR *zdrs, struct accepted_reply *ar)
326 {
327 if (!libnfs_opaque_auth(zdrs, &ar->ar_verf)) {
328 return FALSE;
329 }
330
331 if (!libnfs_zdr_u_int(zdrs, &ar->ar_stat)) {
332 return FALSE;
333 }
334
335 switch (ar->ar_stat) {
336 case SUCCESS:
337 if (!ar->ar_results.proc(zdrs, ar->ar_results.where)) {
338 return FALSE;
339 }
340 return TRUE;
341 case PROG_MISMATCH:
342 if (!libnfs_zdr_u_int(zdrs, &ar->ar_vers.low)) {
343 return FALSE;
344 }
345 if (!libnfs_zdr_u_int(zdrs, &ar->ar_vers.high)) {
346 return FALSE;
347 }
348 return TRUE;
349 default:
350 return TRUE;
351 }
352
353 return FALSE;
354 }
355
356 static bool_t libnfs_rejected_reply(ZDR *zdrs, struct rejected_reply *RP_dr)
357 {
358 printf("rejected reply\n");
359 exit(10);
360 }
361
362 static bool_t libnfs_rpc_reply_body(ZDR *zdrs, struct reply_body *rmb)
363 {
364 if (!libnfs_zdr_u_int(zdrs, &rmb->rp_stat)) {
365 return FALSE;
366 }
367
368 switch (rmb->rp_stat) {
369 case MSG_ACCEPTED:
370 if (!libnfs_accepted_reply(zdrs, &rmb->rp_acpt)) {
371 return FALSE;
372 }
373 return TRUE;
374 case MSG_DENIED:
375 if (!libnfs_rejected_reply(zdrs, &rmb->rp_rjct)) {
376 return FALSE;
377 }
378 return TRUE;
379 }
380
381 return FALSE;
382 }
383
384 static bool_t libnfs_rpc_msg(ZDR *zdrs, struct rpc_msg *msg)
385 {
386 if (!libnfs_zdr_u_int(zdrs, &msg->rm_xid)) {
387 return FALSE;
388 }
389
390 if (!libnfs_zdr_u_int(zdrs, &msg->rm_direction)) {
391 return FALSE;
392 }
393
394 switch (msg->rm_direction) {
395 case CALL:
396 return libnfs_rpc_call_body(zdrs, &msg->ru.RM_cmb);
397 break;
398 case REPLY:
399 return libnfs_rpc_reply_body(zdrs, &msg->ru.RM_rmb);
400 break;
401 default:
402 return FALSE;
403 }
404 }
405
406 bool_t libnfs_zdr_callmsg(ZDR *zdrs, struct rpc_msg *msg)
407 {
408 return libnfs_rpc_msg(zdrs, msg);
409 }
410
411 bool_t libnfs_zdr_replymsg(ZDR *zdrs, struct rpc_msg *msg)
412 {
413 return libnfs_rpc_msg(zdrs, msg);
414 }
415
416 AUTH *authnone_create(void)
417 {
418 AUTH *auth;
419
420 auth = malloc(sizeof(AUTH));
421
422 auth->ah_cred.oa_flavor = AUTH_NONE;
423 auth->ah_cred.oa_length = 0;
424 auth->ah_cred.oa_base = NULL;
425
426 auth->ah_verf.oa_flavor = AUTH_NONE;
427 auth->ah_verf.oa_length = 0;
428 auth->ah_verf.oa_base = NULL;
429
430 auth->ah_private = NULL;
431
432 return auth;
433 }
434
435 AUTH *libnfs_authunix_create(char *host, uint32_t uid, uint32_t gid, uint32_t len, uint32_t *groups)
436 {
437 AUTH *auth;
438 int size;
439 uint32_t *buf;
440 int idx;
441
442 size = 4 + 4 + ((strlen(host) + 3) & ~3) + 4 + 4 + 4 + len * 4;
443 auth = malloc(sizeof(AUTH));
444 auth->ah_cred.oa_flavor = AUTH_UNIX;
445 auth->ah_cred.oa_length = size;
446 auth->ah_cred.oa_base = malloc(size);
447
448 buf = (uint32_t *)auth->ah_cred.oa_base;
449 idx = 0;
450 buf[idx++] = htonl(time(NULL));
451 buf[idx++] = htonl(strlen(host));
452 memcpy(&buf[2], host, strlen(host));
453
454 idx += (strlen(host) + 3) >> 2;
455 buf[idx++] = htonl(uid);
456 buf[idx++] = htonl(gid);
457 buf[idx++] = htonl(len);
458 while (len-- > 0) {
459 buf[idx++] = htonl(*groups++);
460 }
461
462 auth->ah_verf.oa_flavor = AUTH_NONE;
463 auth->ah_verf.oa_length = 0;
464 auth->ah_verf.oa_base = NULL;
465
466 auth->ah_private = NULL;
467
468 return auth;
469 }
470
471 AUTH *libnfs_authunix_create_default(void)
472 {
473 return libnfs_authunix_create("libnfs", getuid(), -1, 0, NULL);
474 }
475
476 void libnfs_auth_destroy(AUTH *auth)
477 {
478 if (auth->ah_cred.oa_base) {
479 free(auth->ah_cred.oa_base);
480 }
481 if (auth->ah_verf.oa_base) {
482 free(auth->ah_verf.oa_base);
483 }
484 free(auth);
485 }
486