• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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