58726188b177726e2b41aa1ef79cf477b86a9e3d
[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
323 static bool_t libnfs_accepted_reply(ZDR *zdrs, struct accepted_reply *ar)
324 {
325 if (!libnfs_opaque_auth(zdrs, &ar->ar_verf)) {
326 return FALSE;
327 }
328
329 if (!libnfs_zdr_u_int(zdrs, &ar->ar_stat)) {
330 return FALSE;
331 }
332
333 switch (ar->ar_stat) {
334 case SUCCESS:
335 if (!ar->ar_results.proc(zdrs, ar->ar_results.where)) {
336 return FALSE;
337 }
338 return TRUE;
339 case PROG_MISMATCH:
340 if (!libnfs_zdr_u_int(zdrs, &ar->ar_vers.low)) {
341 return FALSE;
342 }
343 if (!libnfs_zdr_u_int(zdrs, &ar->ar_vers.high)) {
344 return FALSE;
345 }
346 return TRUE;
347 default:
348 return TRUE;
349 }
350
351 return FALSE;
352 }
353
354 static bool_t libnfs_rejected_reply(ZDR *zdrs, struct rejected_reply *RP_dr)
355 {
356 printf("rejected reply\n");
357 exit(10);
358 }
359
360 static bool_t libnfs_rpc_reply_body(ZDR *zdrs, struct reply_body *rmb)
361 {
362 if (!libnfs_zdr_u_int(zdrs, &rmb->rp_stat)) {
363 return FALSE;
364 }
365
366 switch (rmb->rp_stat) {
367 case MSG_ACCEPTED:
368 if (!libnfs_accepted_reply(zdrs, &rmb->rp_acpt)) {
369 return FALSE;
370 }
371 return TRUE;
372 case MSG_DENIED:
373 if (!libnfs_rejected_reply(zdrs, &rmb->rp_rjct)) {
374 return FALSE;
375 }
376 return TRUE;
377 }
378
379 return FALSE;
380 }
381
382 static bool_t libnfs_rpc_msg(ZDR *zdrs, struct rpc_msg *msg)
383 {
384 if (!libnfs_zdr_u_int(zdrs, &msg->rm_xid)) {
385 return FALSE;
386 }
387
388 if (!libnfs_zdr_u_int(zdrs, &msg->rm_direction)) {
389 return FALSE;
390 }
391
392 switch (msg->rm_direction) {
393 case CALL:
394 return libnfs_rpc_call_body(zdrs, &msg->ru.RM_cmb);
395 break;
396 case REPLY:
397 return libnfs_rpc_reply_body(zdrs, &msg->ru.RM_rmb);
398 break;
399 default:
400 return FALSE;
401 }
402 }
403
404 bool_t libnfs_zdr_callmsg(ZDR *zdrs, struct rpc_msg *msg)
405 {
406 return libnfs_rpc_msg(zdrs, msg);
407 }
408
409 bool_t libnfs_zdr_replymsg(ZDR *zdrs, struct rpc_msg *msg)
410 {
411 return libnfs_rpc_msg(zdrs, msg);
412 }
413
414 AUTH *authnone_create(void)
415 {
416 AUTH *auth;
417
418 auth = malloc(sizeof(AUTH));
419
420 auth->ah_cred.oa_flavor = AUTH_NONE;
421 auth->ah_cred.oa_length = 0;
422 auth->ah_cred.oa_base = NULL;
423
424 auth->ah_verf.oa_flavor = AUTH_NONE;
425 auth->ah_verf.oa_length = 0;
426 auth->ah_verf.oa_base = NULL;
427
428 auth->ah_private = NULL;
429
430 return auth;
431 }
432
433 AUTH *libnfs_authunix_create(char *host, uint32_t uid, uint32_t gid, uint32_t len, uint32_t *groups)
434 {
435 AUTH *auth;
436 int size;
437 uint32_t *buf;
438 int idx;
439
440 size = 4 + 4 + ((strlen(host) + 3) & ~3) + 4 + 4 + 4 + len * 4;
441 auth = malloc(sizeof(AUTH));
442 auth->ah_cred.oa_flavor = AUTH_UNIX;
443 auth->ah_cred.oa_length = size;
444 auth->ah_cred.oa_base = malloc(size);
445
446 buf = auth->ah_cred.oa_base;
447 idx = 0;
448 buf[idx++] = htonl(time(NULL));
449 buf[idx++] = htonl(strlen(host));
450 memcpy(&buf[2], host, strlen(host));
451
452 idx += (strlen(host) + 3) >> 2;
453 buf[idx++] = htonl(uid);
454 buf[idx++] = htonl(gid);
455 buf[idx++] = htonl(len);
456 while (len-- > 0) {
457 buf[idx++] = htonl(*groups++);
458 }
459
460 auth->ah_verf.oa_flavor = AUTH_NONE;
461 auth->ah_verf.oa_length = 0;
462 auth->ah_verf.oa_base = NULL;
463
464 auth->ah_private = NULL;
465
466 return auth;
467 }
468
469 AUTH *libnfs_authunix_create_default(void)
470 {
471 return libnfs_authunix_create("libnfs", getuid(), -1, 0, NULL);
472 }
473
474 void libnfs_auth_destroy(AUTH *auth)
475 {
476 if (auth->ah_cred.oa_base) {
477 free(auth->ah_cred.oa_base);
478 }
479 if (auth->ah_verf.oa_base) {
480 free(auth->ah_verf.oa_base);
481 }
482 free(auth);
483 }
484