1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  */
9 /* @(#)xdr.c    2.1 88/07/29 4.0 RPCSRC */
10 /*
11  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
12  * unrestricted use provided that this legend is included on all tape
13  * media and as a part of the software program in whole or part.  Users
14  * may copy or modify Sun RPC without charge, but are not authorized
15  * to license or distribute it to anyone else except as part of a product or
16  * program developed by the user.
17  *
18  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
19  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
21  *
22  * Sun RPC is provided with no support and without any obligation on the
23  * part of Sun Microsystems, Inc. to assist in its use, correction,
24  * modification or enhancement.
25  *
26  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
27  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
28  * OR ANY PART THEREOF.
29  *
30  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
31  * or profits or other special, indirect and consequential damages, even if
32  * Sun has been advised of the possibility of such damages.
33  *
34  * Sun Microsystems, Inc.
35  * 2550 Garcia Avenue
36  * Mountain View, California  94043
37  */
38 #if !defined(lint) && defined(SCCSIDS)
39 static char sccsid[] = "@(#)xdr.c 1.35 87/08/12";
40 #endif
41 
42 /*
43  * xdr.c, Generic XDR routines implementation.
44  *
45  * Copyright (C) 1986, Sun Microsystems, Inc.
46  *
47  * These are the "generic" xdr routines used to serialize and de-serialize
48  * most common data items.  See xdr.h for more info on the interface to
49  * xdr.
50  */
51 
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <rpc/types.h>
55 #include <rpc/xdr.h>
56 #include <string.h>
57 
58 /*
59  * constants specific to the xdr "protocol"
60  */
61 #define XDR_FALSE       ((long) 0)
62 #define XDR_TRUE        ((long) 1)
63 #define LASTUNSIGNED    ((unsigned int) 0-1)
64 
65 /*
66  * for unit alignment
67  */
68 static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
69 
70 /*
71  * Free a data structure using XDR
72  * Not a filter, but a convenient utility nonetheless
73  */
xdr_free(xdrproc_t proc,char * objp)74 void xdr_free(xdrproc_t proc, char* objp)
75 {
76     XDR x;
77 
78     x.x_op = XDR_FREE;
79     (*proc) (&x, objp);
80 }
81 
82 /*
83  * XDR nothing
84  */
xdr_void()85 bool_t xdr_void( /* xdrs, addr */ )
86     /* XDR *xdrs; */
87     /* char* addr; */
88 {
89 
90     return (TRUE);
91 }
92 
93 /*
94  * XDR integers
95  */
xdr_int(XDR * xdrs,int * ip)96 bool_t xdr_int(XDR* xdrs, int* ip)
97 {
98     if (sizeof(int) == sizeof(long)) {
99         return (xdr_long(xdrs, (long *) ip));
100     } else if (sizeof(int) < sizeof(long)) {
101       long l;
102       switch (xdrs->x_op) {
103       case XDR_ENCODE:
104         l = (long) *ip;
105         return XDR_PUTLONG(xdrs, &l);
106       case XDR_DECODE:
107         if (!XDR_GETLONG(xdrs, &l))
108           return FALSE;
109         *ip = (int) l;
110       case XDR_FREE:
111         return TRUE;
112       }
113       return FALSE;
114     } else {
115         return (xdr_short(xdrs, (short *) ip));
116     }
117 }
118 
119 /*
120  * XDR unsigned integers
121  */
xdr_u_int(XDR * xdrs,unsigned int * up)122 bool_t xdr_u_int(XDR* xdrs, unsigned int* up)
123 {
124     if (sizeof(unsigned int) == sizeof(unsigned long)) {
125         return (xdr_u_long(xdrs, (unsigned long *) up));
126     } else if (sizeof(unsigned int) < sizeof(unsigned long)) {
127       unsigned long l;
128       switch (xdrs->x_op) {
129       case XDR_ENCODE:
130         l = (unsigned long) *up;
131         return XDR_PUTLONG(xdrs, (long*)&l);
132       case XDR_DECODE:
133         if (!XDR_GETLONG(xdrs, (long*)&l))
134           return FALSE;
135         *up = (unsigned int) l;
136       case XDR_FREE:
137         return TRUE;
138       }
139       return FALSE;
140     } else {
141         return (xdr_short(xdrs, (short *) up));
142     }
143 }
144 
145 /*
146  * XDR long integers
147  * same as xdr_u_long - open coded to save a proc call!
148  */
xdr_long(XDR * xdrs,long * lp)149 bool_t xdr_long(XDR* xdrs, long* lp)
150 {
151 
152     if (xdrs->x_op == XDR_ENCODE
153         && (sizeof(int32_t) == sizeof(long)
154             || (int32_t) *lp == *lp))
155         return (XDR_PUTLONG(xdrs, lp));
156 
157     if (xdrs->x_op == XDR_DECODE)
158         return (XDR_GETLONG(xdrs, lp));
159 
160     if (xdrs->x_op == XDR_FREE)
161         return (TRUE);
162 
163     return (FALSE);
164 }
165 
166 /*
167  * XDR unsigned long integers
168  * same as xdr_long - open coded to save a proc call!
169  */
xdr_u_long(XDR * xdrs,unsigned long * ulp)170 bool_t xdr_u_long(XDR* xdrs, unsigned long* ulp)
171 {
172 
173   if (xdrs->x_op == XDR_DECODE) {
174     long l;
175     if (XDR_GETLONG(xdrs, &l) == FALSE)
176       return FALSE;
177     *ulp = (uint32_t) l;
178     return TRUE;
179   }
180 
181   if (xdrs->x_op == XDR_ENCODE) {
182     if (sizeof(uint32_t) != sizeof(unsigned long)
183         && (uint32_t) *ulp != *ulp)
184       return FALSE;
185 
186         return (XDR_PUTLONG(xdrs, (long *) ulp));
187   }
188 
189     if (xdrs->x_op == XDR_FREE)
190         return (TRUE);
191 
192     return (FALSE);
193 }
194 
195 
196 /*
197  * XDR long long integers
198  */
xdr_longlong_t(XDR * xdrs,int64_t * llp)199 bool_t xdr_longlong_t (XDR * xdrs, int64_t* llp)
200 {
201   int32_t t1, t2;
202 
203   switch (xdrs->x_op)
204     {
205     case XDR_ENCODE:
206       t1 = (int32_t) ((*llp) >> 32);
207       t2 = (int32_t) (*llp);
208       return (XDR_PUTLONG (xdrs, &t1) && XDR_PUTLONG (xdrs, &t2));
209 
210     case XDR_DECODE:
211       if (!XDR_GETLONG (xdrs, &t1) || !XDR_GETLONG (xdrs, &t2))
212         return FALSE;
213       *llp = ((int64_t) t1) << 32;
214       *llp |= (uint32_t) t2;
215       return TRUE;
216 
217     case XDR_FREE:
218       return TRUE;
219     }
220   return FALSE;
221 }
222 
223 /*
224  * XDR unsigned long long integers
225  */
xdr_u_longlong_t(XDR * xdrs,uint64_t * ullp)226 bool_t xdr_u_longlong_t (XDR * xdrs, uint64_t* ullp)
227 {
228   uint32_t t1, t2;
229 
230   switch (xdrs->x_op)
231     {
232     case XDR_ENCODE:
233       t1 = (uint32_t) ((*ullp) >> 32);
234       t2 = (uint32_t) (*ullp);
235       return (XDR_PUTLONG (xdrs, (int32_t *)&t1) &&
236               XDR_PUTLONG (xdrs, (int32_t *)&t2));
237 
238     case XDR_DECODE:
239       if (!XDR_GETLONG (xdrs, (int32_t *)&t1) ||
240           !XDR_GETLONG (xdrs, (int32_t *)&t2))
241         return FALSE;
242       *ullp = ((uint64_t) t1) << 32;
243       *ullp |= t2;
244       return TRUE;
245 
246     case XDR_FREE:
247       return TRUE;
248     }
249   return FALSE;
250 }
251 
252 /*
253  * XDR short integers
254  */
xdr_short(XDR * xdrs,short * sp)255 bool_t xdr_short(XDR* xdrs, short* sp)
256 {
257     long l;
258 
259     switch (xdrs->x_op) {
260 
261     case XDR_ENCODE:
262         l = (long) *sp;
263         return (XDR_PUTLONG(xdrs, &l));
264 
265     case XDR_DECODE:
266         if (!XDR_GETLONG(xdrs, &l)) {
267             return (FALSE);
268         }
269         *sp = (short) l;
270         return (TRUE);
271 
272     case XDR_FREE:
273         return (TRUE);
274     }
275     return (FALSE);
276 }
277 
278 /*
279  * XDR unsigned short integers
280  */
xdr_u_short(XDR * xdrs,unsigned short * usp)281 bool_t xdr_u_short(XDR* xdrs, unsigned short* usp)
282 {
283     unsigned long l;
284 
285     switch (xdrs->x_op) {
286 
287     case XDR_ENCODE:
288         l = (unsigned long) * usp;
289         return (XDR_PUTLONG(xdrs, (long*)&l));
290 
291     case XDR_DECODE:
292         if (!XDR_GETLONG(xdrs, (long*)&l)) {
293             return (FALSE);
294         }
295         *usp = (unsigned short) l;
296         return (TRUE);
297 
298     case XDR_FREE:
299         return (TRUE);
300     }
301     return (FALSE);
302 }
303 
304 
305 /*
306  * XDR a char
307  */
xdr_char(XDR * xdrs,char * cp)308 bool_t xdr_char(XDR* xdrs, char* cp)
309 {
310     int i;
311 
312     i = (*cp);
313     if (!xdr_int(xdrs, &i)) {
314         return (FALSE);
315     }
316     *cp = i;
317     return (TRUE);
318 }
319 
320 /*
321  * XDR an unsigned char
322  */
xdr_u_char(XDR * xdrs,unsigned char * cp)323 bool_t xdr_u_char(XDR* xdrs, unsigned char* cp)
324 {
325     unsigned int u;
326 
327     u = (*cp);
328     if (!xdr_u_int(xdrs, &u)) {
329         return (FALSE);
330     }
331     *cp = u;
332     return (TRUE);
333 }
334 
335 /*
336  * XDR booleans
337  */
xdr_bool(XDR * xdrs,bool_t * bp)338 bool_t xdr_bool(XDR *xdrs, bool_t *bp)
339 {
340     long lb;
341 
342     switch (xdrs->x_op) {
343 
344     case XDR_ENCODE:
345         lb = *bp ? XDR_TRUE : XDR_FALSE;
346         return (XDR_PUTLONG(xdrs, &lb));
347 
348     case XDR_DECODE:
349         if (!XDR_GETLONG(xdrs, &lb)) {
350             return (FALSE);
351         }
352         *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
353         return (TRUE);
354 
355     case XDR_FREE:
356         return (TRUE);
357     }
358     return (FALSE);
359 }
360 
361 /*
362  * XDR enumerations
363  */
xdr_enum(XDR * xdrs,enum_t * ep)364 bool_t xdr_enum(XDR *xdrs, enum_t *ep)
365 {
366     enum sizecheck { SIZEVAL };	/* used to find the size of an enum */
367 
368     /*
369      * enums are treated as ints
370      */
371     /* LINTED */ if (sizeof (enum sizecheck) == sizeof (long)) {
372         return (xdr_long(xdrs, (long *)(void *)ep));
373     } else /* LINTED */ if (sizeof (enum sizecheck) == sizeof (int)) {
374         return (xdr_int(xdrs, (int *)(void *)ep));
375     } else /* LINTED */ if (sizeof (enum sizecheck) == sizeof (short)) {
376         return (xdr_short(xdrs, (short *)(void *)ep));
377     } else {
378         return (FALSE);
379     }
380 }
381 
382 /*
383  * XDR opaque data
384  * Allows the specification of a fixed size sequence of opaque bytes.
385  * cp points to the opaque object and cnt gives the byte length.
386  */
xdr_opaque(XDR * xdrs,char * cp,unsigned int cnt)387 bool_t xdr_opaque(XDR *xdrs, char* cp, unsigned int cnt)
388 {
389     register unsigned int rndup;
390     static char crud[BYTES_PER_XDR_UNIT];
391 
392     /*
393      * if no data we are done
394      */
395     if (cnt == 0)
396         return (TRUE);
397 
398     /*
399      * round byte count to full xdr units
400      */
401     rndup = cnt % BYTES_PER_XDR_UNIT;
402     if (rndup > 0)
403         rndup = BYTES_PER_XDR_UNIT - rndup;
404 
405     if (xdrs->x_op == XDR_DECODE) {
406         if (!XDR_GETBYTES(xdrs, cp, cnt)) {
407             return (FALSE);
408         }
409         if (rndup == 0)
410             return (TRUE);
411         return (XDR_GETBYTES(xdrs, crud, rndup));
412     }
413 
414     if (xdrs->x_op == XDR_ENCODE) {
415         if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
416             return (FALSE);
417         }
418         if (rndup == 0)
419             return (TRUE);
420         return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
421     }
422 
423     if (xdrs->x_op == XDR_FREE) {
424         return (TRUE);
425     }
426 
427     return (FALSE);
428 }
429 
430 /*
431  * XDR counted bytes
432  * *cpp is a pointer to the bytes, *sizep is the count.
433  * If *cpp is NULL maxsize bytes are allocated
434  */
xdr_bytes(XDR * xdrs,char ** cpp,unsigned int * sizep,unsigned int maxsize)435 bool_t xdr_bytes(XDR *xdrs, char** cpp, unsigned int *sizep, unsigned int maxsize)
436 {
437     register char *sp = *cpp;   /* sp is the actual string pointer */
438     register unsigned int nodesize;
439 
440     /*
441      * first deal with the length since xdr bytes are counted
442      */
443     if (!xdr_u_int(xdrs, sizep)) {
444         return (FALSE);
445     }
446     nodesize = *sizep;
447     if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
448         return (FALSE);
449     }
450 
451     /*
452      * now deal with the actual bytes
453      */
454     switch (xdrs->x_op) {
455 
456     case XDR_DECODE:
457         if (nodesize == 0) {
458             return (TRUE);
459         }
460         if (sp == NULL) {
461             *cpp = sp = (char *) rt_malloc(nodesize);
462         }
463         if (sp == NULL) {
464             rt_kprintf("xdr_bytes: out of memory\n");
465             return (FALSE);
466         }
467         /* fall into ... */
468 
469     case XDR_ENCODE:
470         return (xdr_opaque(xdrs, sp, nodesize));
471 
472     case XDR_FREE:
473         if (sp != NULL) {
474             rt_free(sp);
475             *cpp = NULL;
476         }
477         return (TRUE);
478     }
479     return (FALSE);
480 }
481 
482 /*
483  * Implemented here due to commonality of the object.
484  */
xdr_netobj(XDR * xdrs,struct netobj * np)485 bool_t xdr_netobj(XDR *xdrs, struct netobj *np)
486 {
487     return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
488 }
489 
490 /*
491  * XDR a descriminated union
492  * Support routine for discriminated unions.
493  * You create an array of xdrdiscrim structures, terminated with
494  * an entry with a null procedure pointer.  The routine gets
495  * the discriminant value and then searches the array of xdrdiscrims
496  * looking for that value.  It calls the procedure given in the xdrdiscrim
497  * to handle the discriminant.  If there is no specific routine a default
498  * routine may be called.
499  * If there is no specific or default routine an error is returned.
500  */
xdr_union(XDR * xdrs,enum_t * dscmp,char * unp,const struct xdr_discrim * choices,xdrproc_t dfault)501 bool_t xdr_union(XDR* xdrs, enum_t* dscmp, char* unp, const struct xdr_discrim* choices, xdrproc_t dfault)
502 {
503     register enum_t dscm;
504 
505     /*
506      * we deal with the discriminator;  it's an enum
507      */
508     if (!xdr_enum(xdrs, dscmp)) {
509         return (FALSE);
510     }
511     dscm = *dscmp;
512 
513     /*
514      * search choices for a value that matches the discriminator.
515      * if we find one, execute the xdr routine for that value.
516      */
517     for (; choices->proc != NULL_xdrproc_t; choices++) {
518         if (choices->value == dscm)
519             return ((*(choices->proc)) (xdrs, unp, LASTUNSIGNED));
520     }
521 
522     /*
523      * no match - execute the default xdr routine if there is one
524      */
525     return ((dfault == NULL_xdrproc_t) ? FALSE :
526             (*dfault) (xdrs, unp, LASTUNSIGNED));
527 }
528 
529 
530 /*
531  * Non-portable xdr primitives.
532  * Care should be taken when moving these routines to new architectures.
533  */
534 
535 
536 /*
537  * XDR null terminated ASCII strings
538  * xdr_string deals with "C strings" - arrays of bytes that are
539  * terminated by a NULL character.  The parameter cpp references a
540  * pointer to storage; If the pointer is null, then the necessary
541  * storage is allocated.  The last parameter is the max allowed length
542  * of the string as specified by a protocol.
543  */
xdr_string(XDR * xdrs,char ** cpp,unsigned int maxsize)544 bool_t xdr_string(XDR *xdrs, char **cpp, unsigned int maxsize)
545 {
546     register char *sp = *cpp;   /* sp is the actual string pointer */
547     unsigned int size;
548     unsigned int nodesize;
549 
550     /*
551      * first deal with the length since xdr strings are counted-strings
552      */
553     switch (xdrs->x_op) {
554     case XDR_FREE:
555         if (sp == NULL) {
556             return (TRUE);      /* already free */
557         }
558         /* fall through... */
559     case XDR_ENCODE:
560         size = strlen(sp);
561         break;
562     }
563     if (!xdr_u_int(xdrs, &size)) {
564         return (FALSE);
565     }
566     if (size > maxsize) {
567         return (FALSE);
568     }
569     nodesize = size + 1;
570 
571     /*
572      * now deal with the actual bytes
573      */
574     switch (xdrs->x_op) {
575 
576     case XDR_DECODE:
577         if (nodesize == 0) {
578             return (TRUE);
579         }
580         if (sp == NULL)
581             *cpp = sp = (char *) rt_malloc(nodesize);
582         if (sp == NULL) {
583             rt_kprintf("xdr_string: out of memory\n");
584             return (FALSE);
585         }
586         sp[size] = 0;
587         /* fall into ... */
588 
589     case XDR_ENCODE:
590         return (xdr_opaque(xdrs, sp, size));
591 
592     case XDR_FREE:
593         rt_free(sp);
594         *cpp = NULL;
595         return (TRUE);
596     }
597     return (FALSE);
598 }
599 
600 /*
601  * Wrapper for xdr_string that can be called directly from
602  * routines like clnt_call
603  */
xdr_wrapstring(XDR * xdrs,char ** cpp)604 bool_t xdr_wrapstring(XDR *xdrs, char **cpp)
605 {
606     if (xdr_string(xdrs, cpp, LASTUNSIGNED)) {
607         return (TRUE);
608     }
609     return (FALSE);
610 }
611 
612 /*
613  * XDR an array of arbitrary elements
614  * *addrp is a pointer to the array, *sizep is the number of elements.
615  * If addrp is NULL (*sizep * elsize) bytes are allocated.
616  * elsize is the size (in bytes) of each element, and elproc is the
617  * xdr procedure to call to handle each element of the array.
618  */
xdr_array(XDR * xdrs,char ** addrp,unsigned int * sizep,unsigned int maxsize,unsigned int elsize,xdrproc_t elproc)619 bool_t xdr_array(XDR *xdrs, char **addrp, unsigned int *sizep, unsigned int maxsize, unsigned int elsize, xdrproc_t elproc)
620 {
621     register unsigned int i;
622     register char* target = *addrp;
623     register unsigned int c;            /* the actual element count */
624     register bool_t stat = TRUE;
625     register unsigned int nodesize;
626 
627     /* like strings, arrays are really counted arrays */
628     if (!xdr_u_int(xdrs, sizep)) {
629         return (FALSE);
630     }
631     c = *sizep;
632     if ((c > maxsize) && (xdrs->x_op != XDR_FREE)) {
633         return (FALSE);
634     }
635     /* duh, look for integer overflow (fefe) */
636     {
637       unsigned int i;
638       nodesize = 0;
639       for (i=c; i; --i) {
640         unsigned int tmp=nodesize+elsize;
641         if (tmp<nodesize)   /* overflow */
642           return FALSE;
643         nodesize=tmp;
644       }
645     }
646 
647     /*
648      * if we are deserializing, we may need to allocate an array.
649      * We also save time by checking for a null array if we are freeing.
650      */
651     if (target == NULL)
652         switch (xdrs->x_op) {
653         case XDR_DECODE:
654             if (c == 0)
655                 return (TRUE);
656             *addrp = target = rt_malloc(nodesize);
657             if (target == NULL) {
658                 rt_kprintf("xdr_array: out of memory\n");
659                 return (FALSE);
660             }
661             memset(target, 0, nodesize);
662             break;
663 
664         case XDR_FREE:
665             return (TRUE);
666         }
667 
668     /*
669      * now we xdr each element of array
670      */
671     for (i = 0; (i < c) && stat; i++) {
672         stat = (*elproc) (xdrs, target, LASTUNSIGNED);
673         target += elsize;
674     }
675 
676     /*
677      * the array may need freeing
678      */
679     if (xdrs->x_op == XDR_FREE) {
680         rt_free(*addrp);
681         *addrp = NULL;
682     }
683     return (stat);
684 }
685 
686 /*
687  * xdr_vector():
688  *
689  * XDR a fixed length array. Unlike variable-length arrays,
690  * the storage of fixed length arrays is static and unfreeable.
691  * > basep: base of the array
692  * > size: size of the array
693  * > elemsize: size of each element
694  * > xdr_elem: routine to XDR each element
695  */
xdr_vector(XDR * xdrs,char * basep,unsigned int nelem,unsigned int elemsize,xdrproc_t xdr_elem)696 bool_t xdr_vector(XDR *xdrs, char *basep, unsigned int nelem, unsigned int elemsize, xdrproc_t xdr_elem)
697 {
698     register unsigned int i;
699     register char *elptr;
700 
701     elptr = basep;
702     for (i = 0; i < nelem; i++) {
703         if (!(*xdr_elem) (xdrs, elptr, LASTUNSIGNED)) {
704             return (FALSE);
705         }
706         elptr += elemsize;
707     }
708     return (TRUE);
709 }
710 
711 
712 /*
713  * XDR an indirect pointer
714  * xdr_reference is for recursively translating a structure that is
715  * referenced by a pointer inside the structure that is currently being
716  * translated.  pp references a pointer to storage. If *pp is null
717  * the  necessary storage is allocated.
718  * size is the sizeof the referneced structure.
719  * proc is the routine to handle the referenced structure.
720  */
xdr_reference(XDR * xdrs,char ** pp,unsigned int size,xdrproc_t proc)721 bool_t xdr_reference(XDR *xdrs, char **pp, unsigned int size, xdrproc_t proc)
722 {
723     register char* loc = *pp;
724     register bool_t stat;
725 
726     if (loc == NULL)
727         switch (xdrs->x_op) {
728         case XDR_FREE:
729             return (TRUE);
730 
731         case XDR_DECODE:
732             *pp = loc = (char*) rt_malloc(size);
733             if (loc == NULL) {
734                 rt_kprintf("xdr_reference: out of memory\n");
735                 return (FALSE);
736             }
737             memset(loc, 0, (int) size);
738             break;
739         }
740 
741     stat = (*proc) (xdrs, loc, LASTUNSIGNED);
742 
743     if (xdrs->x_op == XDR_FREE) {
744         rt_free(loc);
745         *pp = NULL;
746     }
747     return (stat);
748 }
749 
750 
751 /*
752  * xdr_pointer():
753  *
754  * XDR a pointer to a possibly recursive data structure. This
755  * differs with xdr_reference in that it can serialize/deserialiaze
756  * trees correctly.
757  *
758  *  What's sent is actually a union:
759  *
760  *  union object_pointer switch (boolean b) {
761  *  case TRUE: object_data data;
762  *  case FALSE: void nothing;
763  *  }
764  *
765  * > objpp: Pointer to the pointer to the object.
766  * > obj_size: size of the object.
767  * > xdr_obj: routine to XDR an object.
768  *
769  */
xdr_pointer(XDR * xdrs,char ** objpp,unsigned int obj_size,xdrproc_t xdr_obj)770 bool_t xdr_pointer(XDR *xdrs, char **objpp, unsigned int obj_size, xdrproc_t xdr_obj)
771 {
772 
773     bool_t more_data;
774 
775     more_data = (*objpp != NULL);
776     if (!xdr_bool(xdrs, &more_data)) {
777         return (FALSE);
778     }
779     if (!more_data) {
780         *objpp = NULL;
781         return (TRUE);
782     }
783     return (xdr_reference(xdrs, objpp, obj_size, xdr_obj));
784 }
785