1 #include <rpc/rpc.h>
2 #include <string.h>
3
4 #define LASTUNSIGNED ((u_int)((int)0-1))
5
6 /*
7 * Primitives for stuffing data into and retrieving data from an XDR
8 */
9
xdr_bytes(XDR * xdr,char ** cpp,u_int * sizep,u_int maxsize)10 bool_t xdr_bytes (XDR *xdr, char **cpp, u_int *sizep, u_int maxsize)
11 {
12 switch(xdr->x_op) {
13 case XDR_DECODE:
14 if(!XDR_RECV_UINT(xdr, sizep) || *sizep > maxsize)
15 return FALSE;
16 if(*sizep == 0)
17 return TRUE;
18 if(*cpp == NULL)
19 *cpp = (char *) mem_alloc(*sizep);
20 if(*cpp == NULL) return FALSE;
21 return XDR_RECV_BYTES(xdr, (uint8 *) *cpp, *sizep);
22 case XDR_ENCODE:
23 return (XDR_SEND_UINT(xdr, sizep) &&
24 *sizep <= maxsize &&
25 XDR_SEND_BYTES(xdr, (uint8 *) *cpp, *sizep));
26 case XDR_FREE:
27 if (*cpp) {
28 mem_free(*cpp);
29 *cpp = NULL;
30 }
31 return TRUE;
32 default:
33 break;
34 }
35 return FALSE;
36 } /* xdr_bytes */
37
xdr_send_enum(xdr_s_type * xdr,const void * value,uint32 size)38 bool_t xdr_send_enum (xdr_s_type *xdr, const void *value, uint32 size)
39 {
40 switch (size) {
41 case 4:
42 return XDR_SEND_INT32(xdr, (int32 *) value);
43 case 2:
44 return XDR_SEND_INT16(xdr, (int16 *) value);
45 case 1:
46 return XDR_SEND_INT8(xdr, (int8 *) value);
47 default:
48 return FALSE;
49 }
50 } /* xdr_send_enum */
51
xdr_recv_enum(xdr_s_type * xdr,void * value,uint32 size)52 bool_t xdr_recv_enum (xdr_s_type *xdr, void *value, uint32 size)
53 {
54 switch (size) {
55 case 4:
56 return XDR_RECV_INT32(xdr, (int32 *) value);
57 case 2:
58 return XDR_RECV_INT16(xdr, (int16 *) value);
59 case 1:
60 return XDR_RECV_INT8(xdr, (int8 *) value);
61 default:
62 return FALSE;
63 }
64 } /* xdr_recv_enum */
65
66 #include <stdio.h>
67
xdr_enum(XDR * xdr,enum_t * ep)68 bool_t xdr_enum (XDR *xdr, enum_t *ep)
69 {
70 switch(xdr->x_op) {
71 case XDR_ENCODE:
72 return XDR_SEND_INT32(xdr, (int32 *)ep);
73 case XDR_DECODE:
74 return XDR_RECV_INT32(xdr, (int32 *)ep);
75 case XDR_FREE:
76 return TRUE;
77 default:
78 break;
79 }
80 return FALSE;
81 } /* xdr_enum */
82
xdr_u_int(XDR * xdr,u_int * uip)83 bool_t xdr_u_int (XDR *xdr, u_int *uip)
84 {
85 switch(xdr->x_op) {
86 case XDR_ENCODE:
87 return XDR_SEND_UINT32(xdr, (uint32 *) uip);
88 case XDR_DECODE:
89 return XDR_RECV_UINT32(xdr, (uint32 *) uip);
90 case XDR_FREE:
91 return TRUE;
92 default:
93 break;
94 }
95 return FALSE;
96 } /* xdr_u_int */
97
xdr_u_char(XDR * xdr,u_char * cp)98 bool_t xdr_u_char (XDR *xdr, u_char *cp)
99 {
100 u_int u = (*cp);
101 if (!xdr_u_int (xdr, &u))
102 return FALSE;
103 *cp = (u_char) u;
104 return TRUE;
105 } /* xdr_u_char */
106
xdr_long(XDR * xdr,long * lp)107 bool_t xdr_long (XDR *xdr, long *lp)
108 {
109 switch (xdr->x_op) {
110 case XDR_ENCODE:
111 return XDR_SEND_INT32(xdr, (int32_t *)lp);
112 case XDR_DECODE:
113 return XDR_RECV_INT32(xdr, (int32_t *)lp);
114 case XDR_FREE:
115 return TRUE;
116 default:
117 break;
118 }
119 return FALSE;
120 } /* xdr_long */
121
xdr_u_long(XDR * xdr,u_long * ulp)122 bool_t xdr_u_long (XDR *xdr, u_long *ulp)
123 {
124 switch (xdr->x_op) {
125 case XDR_ENCODE:
126 return XDR_SEND_UINT32(xdr, (uint32_t *)ulp);
127 case XDR_DECODE:
128 return XDR_RECV_UINT32(xdr, (uint32_t *)ulp);
129 case XDR_FREE:
130 return TRUE;
131 default:
132 break;
133 }
134 return FALSE;
135 } /* xdr_u_long */
136
137 /*
138 * XDR hyper integers
139 * same as xdr_hyper - open coded to save a proc call!
140 */
xdr_u_hyper(XDR * xdrs,u_quad_t * ullp)141 bool_t xdr_u_hyper (XDR *xdrs, u_quad_t *ullp)
142 {
143 unsigned long t1;
144 unsigned long t2;
145
146 if (xdrs->x_op == XDR_ENCODE) {
147 t1 = (unsigned long) ((*ullp) >> 32);
148 t2 = (unsigned long) (*ullp);
149 return (XDR_SEND_INT32(xdrs, (int32 *)&t1) &&
150 XDR_SEND_INT32(xdrs, (int32 *)&t2));
151 }
152
153 if (xdrs->x_op == XDR_DECODE) {
154 if (!XDR_RECV_INT32(xdrs, (int32 *)&t1) ||
155 !XDR_RECV_INT32(xdrs, (int32 *)&t2))
156 return FALSE;
157 *ullp = ((u_quad_t) t1) << 32;
158 *ullp |= t2;
159 return TRUE;
160 }
161
162 return xdrs->x_op == XDR_FREE;
163 }
164
165 bool_t
xdr_u_quad_t(XDR * xdrs,u_quad_t * ullp)166 xdr_u_quad_t (XDR *xdrs, u_quad_t *ullp)
167 {
168 return xdr_u_hyper(xdrs, ullp);
169 }
170
xdr_u_short(XDR * xdr,u_short * usp)171 bool_t xdr_u_short (XDR *xdr, u_short *usp)
172 {
173 u_long l;
174
175 switch (xdr->x_op) {
176 case XDR_ENCODE:
177 l = *usp;
178 return XDR_SEND_UINT32(xdr, (uint32_t *)&l);
179 case XDR_DECODE:
180 if(!XDR_RECV_UINT32(xdr, (uint32_t *)&l))
181 return FALSE;
182 *usp = (u_short)l;
183 return TRUE;
184 case XDR_FREE:
185 return TRUE;
186 default:
187 break;
188 }
189
190 return FALSE;
191 } /* xdr_u_short */
192
193 /*
194 * xdr_vector():
195 *
196 * XDR a fixed length array. Unlike variable-length arrays,
197 * the storage of fixed length arrays is static and unfreeable.
198 * > basep: base of the array
199 * > size: size of the array
200 * > elemsize: size of each element
201 * > xdr_elem: routine to XDR each element
202 */
203 bool_t
xdr_vector(XDR * xdrs,char * basep,u_int nelem,u_int elemsize,xdrproc_t xdr_elem)204 xdr_vector (XDR *xdrs,
205 char *basep,
206 u_int nelem,
207 u_int elemsize,
208 xdrproc_t xdr_elem)
209 {
210 u_int i;
211 char *elptr;
212
213 elptr = basep;
214 for (i = 0; i < nelem; i++) {
215 if (!(*xdr_elem) (xdrs, elptr, LASTUNSIGNED))
216 return FALSE;
217 elptr += elemsize;
218 }
219 return TRUE;
220 }
221
xdr_bool(XDR * xdr,bool_t * bp)222 bool_t xdr_bool (XDR *xdr, bool_t *bp)
223 {
224 uint32 lb;
225
226 switch(xdr->x_op) {
227 case XDR_ENCODE:
228 lb = *bp ? TRUE : FALSE;
229 return XDR_SEND_UINT32(xdr, &lb);
230 case XDR_DECODE:
231 if (!XDR_RECV_UINT32(xdr, &lb))
232 return FALSE;
233 *bp = (lb == FALSE) ? FALSE : TRUE;
234 return TRUE;
235 case XDR_FREE:
236 return TRUE;
237 default:
238 break;
239 }
240
241 return FALSE;
242 } /* xdr_bool */
243
244 /*
245 * XDR an indirect pointer
246 * xdr_reference is for recursively translating a structure that is
247 * referenced by a pointer inside the structure that is currently being
248 * translated. pp references a pointer to storage. If *pp is null
249 * the necessary storage is allocated.
250 * size is the size of the referneced structure.
251 * proc is the routine to handle the referenced structure.
252 */
253 bool_t
xdr_reference(XDR * xdrs,caddr_t * pp,u_int size,xdrproc_t proc)254 xdr_reference (XDR *xdrs,
255 caddr_t *pp, /* the pointer to work on */
256 u_int size, /* size of the object pointed to */
257 xdrproc_t proc) /* xdr routine to handle the object */
258 {
259 bool_t stat;
260
261 if (*pp == NULL) {
262 switch (xdrs->x_op) {
263 case XDR_FREE:
264 return TRUE;
265
266 case XDR_DECODE:
267 *pp = (caddr_t) mem_alloc (size);
268 if (*pp == NULL) return FALSE;
269 memset(*pp, 0, size);
270 break;
271 default:
272 break;
273 }
274 }
275
276 stat = (*proc) (xdrs, *pp, LASTUNSIGNED);
277
278 if (xdrs->x_op == XDR_FREE) {
279 mem_free(*pp);
280 *pp = NULL;
281 }
282 return stat;
283 } /* xdr_reference */
284
285 /*
286 * xdr_pointer():
287 *
288 * XDR a pointer to a possibly recursive data structure. This
289 * differs with xdr_reference in that it can serialize/deserialize
290 * trees correctly.
291 *
292 * What's sent is actually a union:
293 *
294 * union object_pointer switch (bool_t b) {
295 * case TRUE: object_data data;
296 * case FALSE: void nothing;
297 * }
298 *
299 * > objpp: Pointer to the pointer to the object.
300 * > obj_size: size of the object.
301 * > xdr_obj: routine to XDR an object.
302 *
303 */
304
305 bool_t
xdr_pointer(XDR * xdrs,char ** objpp,u_int obj_size,xdrproc_t xdr_obj)306 xdr_pointer (XDR *xdrs,
307 char **objpp,
308 u_int obj_size,
309 xdrproc_t xdr_obj)
310 {
311 bool_t more_data;
312
313 more_data = (*objpp != NULL);
314 if (!xdr_bool (xdrs, &more_data))
315 return FALSE;
316
317 if (!more_data) {
318 *objpp = NULL;
319 return TRUE;
320 }
321 return xdr_reference (xdrs, objpp, obj_size, xdr_obj);
322 } /* xdr_pointer */
323
xdr_void(void)324 bool_t xdr_void (void)
325 {
326 return TRUE;
327 } /* xdr_void */
328
329 /*
330 * XDR an array of arbitrary elements
331 * *addrp is a pointer to the array, *sizep is the number of elements.
332 * If addrp is NULL (*sizep * elsize) bytes are allocated.
333 * elsize is the size (in bytes) of each element, and elproc is the
334 * xdr procedure to call to handle each element of the array.
335 */
336 bool_t
xdr_array(XDR * xdrs,caddr_t * addrp,u_int * sizep,u_int maxsize,u_int elsize,xdrproc_t elproc)337 xdr_array (XDR *xdrs,
338 caddr_t *addrp,/* array pointer */
339 u_int *sizep, /* number of elements */
340 u_int maxsize, /* max numberof elements */
341 u_int elsize, /* size in bytes of each element */
342 xdrproc_t elproc) /* xdr routine to handle each element */
343 {
344 u_int i;
345 caddr_t target = *addrp;
346 u_int c;/* the actual element count */
347 bool_t stat = TRUE;
348 u_int nodesize;
349
350 /* like strings, arrays are really counted arrays */
351 if (!xdr_u_int (xdrs, sizep))
352 return FALSE;
353 c = *sizep;
354 if ((c > maxsize) && (xdrs->x_op != XDR_FREE))
355 return FALSE;
356 nodesize = c * elsize;
357
358 /*
359 * if we are deserializing, we may need to allocate an array.
360 * We also save time by checking for a null array if we are freeing.
361 */
362 if (target == NULL)
363 switch (xdrs->x_op) {
364 case XDR_DECODE:
365 if (c == 0)
366 return TRUE;
367 *addrp = target = mem_alloc (nodesize);
368 if (!*addrp) return FALSE;
369 memset (target, 0, nodesize);
370 break;
371 case XDR_FREE:
372 return TRUE;
373 default:
374 break;
375 }
376
377 /*
378 * now we xdr each element of array
379 */
380 for (i = 0; (i < c) && stat; i++) {
381 stat = (*elproc) (xdrs, target, LASTUNSIGNED);
382 target += elsize;
383 }
384
385 /*
386 * the array may need freeing
387 */
388 if (xdrs->x_op == XDR_FREE) {
389 mem_free(*addrp);
390 *addrp = NULL;
391 }
392
393 return stat;
394 }
395
xdr_int(XDR * xdr,int * ip)396 bool_t xdr_int(XDR *xdr, int *ip)
397 {
398 switch (xdr->x_op) {
399 case XDR_ENCODE:
400 return XDR_SEND_INT32(xdr, (int32 *) ip);
401 case XDR_DECODE:
402 return XDR_RECV_INT32(xdr, (int32 *) ip);
403 case XDR_FREE:
404 return TRUE;
405 default:
406 break;
407 }
408
409 return FALSE;
410 } /* xdr_int */
411
xdr_opaque(XDR * xdr,caddr_t cp,u_int cnt)412 bool_t xdr_opaque (XDR *xdr, caddr_t cp, u_int cnt)
413 {
414 /* if no data we are done */
415 if (cnt == 0)
416 return TRUE;
417
418 switch (xdr->x_op) {
419 case XDR_ENCODE:
420 return XDR_SEND_BYTES(xdr, (uint8 *) cp, cnt);
421 case XDR_DECODE:
422 return XDR_RECV_BYTES(xdr, (uint8 *) cp, cnt);
423 case XDR_FREE:
424 return TRUE;
425 default:
426 break;
427 }
428
429 return FALSE;
430 } /* xdr_opaque */
431
xdr_char(XDR * xdr,char * cp)432 bool_t xdr_char (XDR *xdr, char *cp)
433 {
434 int i;
435 i = (*cp);
436 if (!xdr_int (xdr, &i))
437 return FALSE;
438 *cp = i;
439 return TRUE;
440 } /* xdr_char */
441
442 bool_t
xdr_quad_t(XDR * xdrs,quad_t * llp)443 xdr_quad_t (XDR *xdrs, quad_t *llp)
444 {
445 return xdr_u_quad_t(xdrs, (u_quad_t *)llp);
446 }
447
xdr_short(XDR * xdr,short * sp)448 bool_t xdr_short (XDR *xdr, short *sp)
449 {
450 long l;
451 switch (xdr->x_op) {
452 case XDR_ENCODE:
453 l = *sp;
454 return XDR_SEND_INT32(xdr, (int32_t *)&l);
455 case XDR_DECODE:
456 if (!XDR_RECV_INT32(xdr, (int32_t *)&l))
457 return FALSE;
458 *sp = (short)l;
459 return TRUE;
460 case XDR_FREE:
461 return TRUE;
462 default:
463 break;
464 }
465 return FALSE;
466 } /* xdr_short */
467
468 /*
469 * Non-portable xdr primitives.
470 * Care should be taken when moving these routines to new architectures.
471 */
472
473 /*
474 * XDR null terminated ASCII strings
475 * xdr_string deals with "C strings" - arrays of bytes that are
476 * terminated by a NULL character. The parameter cpp references a
477 * pointer to storage; If the pointer is null, then the necessary
478 * storage is allocated. The last parameter is the max allowed length
479 * of the string as specified by a protocol.
480 */
xdr_string(XDR * xdr,char ** cpp,u_int maxsize)481 bool_t xdr_string (XDR *xdr, char **cpp, u_int maxsize)
482 {
483 u_int size;
484 u_int nodesize;
485
486 /*
487 * first deal with the length since xdr strings are counted-strings
488 */
489 switch (xdr->x_op) {
490 case XDR_FREE:
491 if (*cpp == NULL) return TRUE;
492 /* fall through... */
493 case XDR_ENCODE:
494 if (*cpp == NULL) return FALSE;
495 size = strlen(*cpp);
496 break;
497 case XDR_DECODE:
498 break;
499 default:
500 break;
501 }
502
503 if (!xdr_u_int(xdr, &size)) return FALSE;
504 if (size > maxsize) return FALSE;
505 nodesize = size + 1;
506
507 /*
508 * now deal with the actual bytes
509 */
510 switch (xdr->x_op) {
511 case XDR_DECODE:
512 if (nodesize == 0) return TRUE;
513 if (*cpp == NULL)
514 *cpp = (char *)mem_alloc(nodesize);
515 if (*cpp == NULL) return FALSE;
516 (*cpp)[size] = 0;
517 /* fall through... */
518 case XDR_ENCODE:
519 return xdr_opaque(xdr, *cpp, size);
520 case XDR_FREE:
521 mem_free(*cpp);
522 *cpp = NULL;
523 return TRUE;
524 default:
525 break;
526 }
527 return FALSE;
528 } /* xdr_string */
529