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