1 /*
2  * xdr.c, Generic XDR routines implementation.
3  *
4  * Copyright (c) 2010, Oracle America, Inc.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  *     * Redistributions of source code must retain the above copyright
11  *       notice, this list of conditions and the following disclaimer.
12  *     * Redistributions in binary form must reproduce the above
13  *       copyright notice, this list of conditions and the following
14  *       disclaimer in the documentation and/or other materials
15  *       provided with the distribution.
16  *     * Neither the name of the "Oracle America, Inc." nor the names of its
17  *       contributors may be used to endorse or promote products derived
18  *       from this software without specific prior written permission.
19  *
20  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25  *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27  *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29  *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30  *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  * These are the "generic" xdr routines used to serialize and de-serialize
34  * most common data items.  See xdr.h for more info on the interface to
35  * xdr.
36  */
37 
38 #include <stdio.h>
39 #include <limits.h>
40 #include <string.h>
41 #include <libintl.h>
42 #include <wchar.h>
43 #include <stdint.h>
44 
45 #include <rpc/types.h>
46 #include <rpc/xdr.h>
47 #include <shlib-compat.h>
48 
49 
50 /*
51  * constants specific to the xdr "protocol"
52  */
53 #define XDR_FALSE	((long) 0)
54 #define XDR_TRUE	((long) 1)
55 #define LASTUNSIGNED	((u_int) 0-1)
56 
57 /*
58  * for unit alignment
59  */
60 static const char xdr_zero[BYTES_PER_XDR_UNIT] = {0, 0, 0, 0};
61 
62 /*
63  * Free a data structure using XDR
64  * Not a filter, but a convenient utility nonetheless
65  */
66 void
xdr_free(xdrproc_t proc,char * objp)67 xdr_free (xdrproc_t proc, char *objp)
68 {
69   XDR x;
70 
71   x.x_op = XDR_FREE;
72   (*proc) (&x, objp);
73 }
74 #ifdef EXPORT_RPC_SYMBOLS
libc_hidden_def(xdr_free)75 libc_hidden_def (xdr_free)
76 #else
77 libc_hidden_nolink_sunrpc (xdr_free, GLIBC_2_0)
78 #endif
79 
80 /*
81  * XDR nothing
82  */
83 bool_t
84 xdr_void (void)
85 {
86   return TRUE;
87 }
88 #ifdef EXPORT_RPC_SYMBOLS
libc_hidden_def(xdr_void)89 libc_hidden_def (xdr_void)
90 #else
91 libc_hidden_nolink_sunrpc (xdr_void, GLIBC_2_0)
92 #endif
93 
94 /*
95  * XDR integers
96  */
97 bool_t
98 xdr_int (XDR *xdrs, int *ip)
99 {
100 
101 #if INT_MAX < LONG_MAX
102   long l;
103 
104   switch (xdrs->x_op)
105     {
106     case XDR_ENCODE:
107       l = (long) *ip;
108       return XDR_PUTLONG (xdrs, &l);
109 
110     case XDR_DECODE:
111       if (!XDR_GETLONG (xdrs, &l))
112 	{
113 	  return FALSE;
114 	}
115       *ip = (int) l;
116       /* Fall through.  */
117     case XDR_FREE:
118       return TRUE;
119     }
120   return FALSE;
121 #elif INT_MAX == LONG_MAX
122   return xdr_long (xdrs, (long *) ip);
123 #elif INT_MAX == SHRT_MAX
124   return xdr_short (xdrs, (short *) ip);
125 #else
126 #error unexpected integer sizes in_xdr_int()
127 #endif
128 }
129 #ifdef EXPORT_RPC_SYMBOLS
libc_hidden_def(xdr_int)130 libc_hidden_def (xdr_int)
131 #else
132 libc_hidden_nolink_sunrpc (xdr_int, GLIBC_2_0)
133 #endif
134 
135 /*
136  * XDR unsigned integers
137  */
138 bool_t
139 xdr_u_int (XDR *xdrs, u_int *up)
140 {
141 #if UINT_MAX < ULONG_MAX
142   long l;
143 
144   switch (xdrs->x_op)
145     {
146     case XDR_ENCODE:
147       l = (u_long) * up;
148       return XDR_PUTLONG (xdrs, &l);
149 
150     case XDR_DECODE:
151       if (!XDR_GETLONG (xdrs, &l))
152 	{
153 	  return FALSE;
154 	}
155       *up = (u_int) (u_long) l;
156       /* Fall through.  */
157     case XDR_FREE:
158       return TRUE;
159     }
160   return FALSE;
161 #elif UINT_MAX == ULONG_MAX
162   return xdr_u_long (xdrs, (u_long *) up);
163 #elif UINT_MAX == USHRT_MAX
164   return xdr_short (xdrs, (short *) up);
165 #else
166 #error unexpected integer sizes in_xdr_u_int()
167 #endif
168 }
169 #ifdef EXPORT_RPC_SYMBOLS
libc_hidden_def(xdr_u_int)170 libc_hidden_def (xdr_u_int)
171 #else
172 libc_hidden_nolink_sunrpc (xdr_u_int, GLIBC_2_0)
173 #endif
174 
175 /*
176  * XDR long integers
177  * The definition of xdr_long() is kept for backward
178  * compatibility. Instead xdr_int() should be used.
179  */
180 bool_t
181 xdr_long (XDR *xdrs, long *lp)
182 {
183 
184   if (xdrs->x_op == XDR_ENCODE
185       && (sizeof (int32_t) == sizeof (long)
186 	  || (int32_t) *lp == *lp))
187     return XDR_PUTLONG (xdrs, lp);
188 
189   if (xdrs->x_op == XDR_DECODE)
190     return XDR_GETLONG (xdrs, lp);
191 
192   if (xdrs->x_op == XDR_FREE)
193     return TRUE;
194 
195   return FALSE;
196 }
197 #ifdef EXPORT_RPC_SYMBOLS
libc_hidden_def(xdr_long)198 libc_hidden_def (xdr_long)
199 #else
200 libc_hidden_nolink_sunrpc (xdr_long, GLIBC_2_0)
201 #endif
202 
203 /*
204  * XDR unsigned long integers
205  * The definition of xdr_u_long() is kept for backward
206  * compatibility. Instead xdr_u_int() should be used.
207  */
208 bool_t
209 xdr_u_long (XDR *xdrs, u_long *ulp)
210 {
211   switch (xdrs->x_op)
212     {
213     case XDR_DECODE:
214       {
215 	long int tmp;
216 
217 	if (XDR_GETLONG (xdrs, &tmp) == FALSE)
218 	  return FALSE;
219 
220 	*ulp = (uint32_t) tmp;
221 	return TRUE;
222       }
223 
224     case XDR_ENCODE:
225       if (sizeof (uint32_t) != sizeof (u_long)
226 	  && (uint32_t) *ulp != *ulp)
227 	return FALSE;
228 
229       return XDR_PUTLONG (xdrs, (long *) ulp);
230 
231     case XDR_FREE:
232       return TRUE;
233     }
234   return FALSE;
235 }
236 #ifdef EXPORT_RPC_SYMBOLS
libc_hidden_def(xdr_u_long)237 libc_hidden_def (xdr_u_long)
238 #else
239 libc_hidden_nolink_sunrpc (xdr_u_long, GLIBC_2_0)
240 #endif
241 
242 /*
243  * XDR hyper integers
244  * same as xdr_u_hyper - open coded to save a proc call!
245  */
246 bool_t
247 xdr_hyper (XDR *xdrs, quad_t *llp)
248 {
249   long int t1, t2;
250 
251   if (xdrs->x_op == XDR_ENCODE)
252     {
253       t1 = (long) ((*llp) >> 32);
254       t2 = (long) (*llp);
255       return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, &t2));
256     }
257 
258   if (xdrs->x_op == XDR_DECODE)
259     {
260       if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2))
261 	return FALSE;
262       *llp = ((quad_t) t1) << 32;
263       *llp |= (uint32_t) t2;
264       return TRUE;
265     }
266 
267   if (xdrs->x_op == XDR_FREE)
268     return TRUE;
269 
270   return FALSE;
271 }
272 #ifdef EXPORT_RPC_SYMBOLS
libc_hidden_def(xdr_hyper)273 libc_hidden_def (xdr_hyper)
274 #else
275 libc_hidden_nolink_sunrpc (xdr_hyper, GLIBC_2_1_1)
276 #endif
277 
278 /*
279  * XDR hyper integers
280  * same as xdr_hyper - open coded to save a proc call!
281  */
282 bool_t
283 xdr_u_hyper (XDR *xdrs, u_quad_t *ullp)
284 {
285   long int t1, t2;
286 
287   if (xdrs->x_op == XDR_ENCODE)
288     {
289       t1 = (unsigned long) ((*ullp) >> 32);
290       t2 = (unsigned long) (*ullp);
291       return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, &t2));
292     }
293 
294   if (xdrs->x_op == XDR_DECODE)
295     {
296       if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2))
297 	return FALSE;
298       *ullp = ((u_quad_t) t1) << 32;
299       *ullp |= (uint32_t) t2;
300       return TRUE;
301     }
302 
303   if (xdrs->x_op == XDR_FREE)
304     return TRUE;
305 
306   return FALSE;
307 }
308 #ifdef EXPORT_RPC_SYMBOLS
libc_hidden_def(xdr_u_hyper)309 libc_hidden_def (xdr_u_hyper)
310 #else
311 libc_hidden_nolink_sunrpc (xdr_u_hyper, GLIBC_2_1_1)
312 #endif
313 
314 bool_t
315 xdr_longlong_t (XDR *xdrs, quad_t *llp)
316 {
317   return xdr_hyper (xdrs, llp);
318 }
319 #ifdef EXPORT_RPC_SYMBOLS
libc_hidden_def(xdr_longlong_t)320 libc_hidden_def (xdr_longlong_t)
321 #else
322 libc_hidden_nolink_sunrpc (xdr_longlong_t, GLIBC_2_1_1)
323 #endif
324 
325 bool_t
326 xdr_u_longlong_t (XDR *xdrs, u_quad_t *ullp)
327 {
328   return xdr_u_hyper (xdrs, ullp);
329 }
330 #ifdef EXPORT_RPC_SYMBOLS
libc_hidden_def(xdr_u_longlong_t)331 libc_hidden_def (xdr_u_longlong_t)
332 #else
333 libc_hidden_nolink_sunrpc (xdr_u_longlong_t, GLIBC_2_1_1)
334 #endif
335 
336 /*
337  * XDR short integers
338  */
339 bool_t
340 xdr_short (XDR *xdrs, short *sp)
341 {
342   long l;
343 
344   switch (xdrs->x_op)
345     {
346     case XDR_ENCODE:
347       l = (long) *sp;
348       return XDR_PUTLONG (xdrs, &l);
349 
350     case XDR_DECODE:
351       if (!XDR_GETLONG (xdrs, &l))
352 	{
353 	  return FALSE;
354 	}
355       *sp = (short) l;
356       return TRUE;
357 
358     case XDR_FREE:
359       return TRUE;
360     }
361   return FALSE;
362 }
363 #ifdef EXPORT_RPC_SYMBOLS
libc_hidden_def(xdr_short)364 libc_hidden_def (xdr_short)
365 #else
366 libc_hidden_nolink_sunrpc (xdr_short, GLIBC_2_0)
367 #endif
368 
369 /*
370  * XDR unsigned short integers
371  */
372 bool_t
373 xdr_u_short (XDR *xdrs, u_short *usp)
374 {
375   long l;
376 
377   switch (xdrs->x_op)
378     {
379     case XDR_ENCODE:
380       l = (u_long) * usp;
381       return XDR_PUTLONG (xdrs, &l);
382 
383     case XDR_DECODE:
384       if (!XDR_GETLONG (xdrs, &l))
385 	{
386 	  return FALSE;
387 	}
388       *usp = (u_short) (u_long) l;
389       return TRUE;
390 
391     case XDR_FREE:
392       return TRUE;
393     }
394   return FALSE;
395 }
396 #ifdef EXPORT_RPC_SYMBOLS
libc_hidden_def(xdr_u_short)397 libc_hidden_def (xdr_u_short)
398 #else
399 libc_hidden_nolink_sunrpc (xdr_u_short, GLIBC_2_0)
400 #endif
401 
402 
403 /*
404  * XDR a char
405  */
406 bool_t
407 xdr_char (XDR *xdrs, char *cp)
408 {
409   int i;
410 
411   i = (*cp);
412   if (!xdr_int (xdrs, &i))
413     {
414       return FALSE;
415     }
416   *cp = i;
417   return TRUE;
418 }
419 #ifdef EXPORT_RPC_SYMBOLS
libc_hidden_def(xdr_char)420 libc_hidden_def (xdr_char)
421 #else
422 libc_hidden_nolink_sunrpc (xdr_char, GLIBC_2_0)
423 #endif
424 
425 /*
426  * XDR an unsigned char
427  */
428 bool_t
429 xdr_u_char (XDR *xdrs, u_char *cp)
430 {
431   u_int u;
432 
433   u = (*cp);
434   if (!xdr_u_int (xdrs, &u))
435     {
436       return FALSE;
437     }
438   *cp = u;
439   return TRUE;
440 }
441 #ifdef EXPORT_RPC_SYMBOLS
libc_hidden_def(xdr_u_char)442 libc_hidden_def (xdr_u_char)
443 #else
444 libc_hidden_nolink_sunrpc (xdr_u_char, GLIBC_2_0)
445 #endif
446 
447 /*
448  * XDR booleans
449  */
450 bool_t
451 xdr_bool (XDR *xdrs, bool_t *bp)
452 {
453   long lb;
454 
455   switch (xdrs->x_op)
456     {
457     case XDR_ENCODE:
458       lb = *bp ? XDR_TRUE : XDR_FALSE;
459       return XDR_PUTLONG (xdrs, &lb);
460 
461     case XDR_DECODE:
462       if (!XDR_GETLONG (xdrs, &lb))
463 	{
464 	  return FALSE;
465 	}
466       *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
467       return TRUE;
468 
469     case XDR_FREE:
470       return TRUE;
471     }
472   return FALSE;
473 }
474 #ifdef EXPORT_RPC_SYMBOLS
libc_hidden_def(xdr_bool)475 libc_hidden_def (xdr_bool)
476 #else
477 libc_hidden_nolink_sunrpc (xdr_bool, GLIBC_2_0)
478 #endif
479 
480 /*
481  * XDR enumerations
482  */
483 bool_t
484 xdr_enum (XDR *xdrs, enum_t *ep)
485 {
486   enum sizecheck
487     {
488       SIZEVAL
489     };				/* used to find the size of an enum */
490 
491   /*
492    * enums are treated as ints
493    */
494   if (sizeof (enum sizecheck) == 4)
495     {
496 #if INT_MAX < LONG_MAX
497       long l;
498 
499       switch (xdrs->x_op)
500 	{
501 	case XDR_ENCODE:
502 	  l = *ep;
503 	  return XDR_PUTLONG (xdrs, &l);
504 
505 	case XDR_DECODE:
506 	  if (!XDR_GETLONG (xdrs, &l))
507 	    {
508 	      return FALSE;
509 	    }
510 	  *ep = l;
511 	  /* Fall through.  */
512 	case XDR_FREE:
513 	  return TRUE;
514 
515 	}
516       return FALSE;
517 #else
518       return xdr_long (xdrs, (long *) ep);
519 #endif
520     }
521   else if (sizeof (enum sizecheck) == sizeof (short))
522     {
523       return xdr_short (xdrs, (short *) ep);
524     }
525   else
526     {
527       return FALSE;
528     }
529 }
530 #ifdef EXPORT_RPC_SYMBOLS
libc_hidden_def(xdr_enum)531 libc_hidden_def (xdr_enum)
532 #else
533 libc_hidden_nolink_sunrpc (xdr_enum, GLIBC_2_0)
534 #endif
535 
536 /*
537  * XDR opaque data
538  * Allows the specification of a fixed size sequence of opaque bytes.
539  * cp points to the opaque object and cnt gives the byte length.
540  */
541 bool_t
542 xdr_opaque (XDR *xdrs, caddr_t cp, u_int cnt)
543 {
544   u_int rndup;
545   static char crud[BYTES_PER_XDR_UNIT];
546 
547   /*
548    * if no data we are done
549    */
550   if (cnt == 0)
551     return TRUE;
552 
553   /*
554    * round byte count to full xdr units
555    */
556   rndup = cnt % BYTES_PER_XDR_UNIT;
557   if (rndup > 0)
558     rndup = BYTES_PER_XDR_UNIT - rndup;
559 
560   switch (xdrs->x_op)
561     {
562     case XDR_DECODE:
563       if (!XDR_GETBYTES (xdrs, cp, cnt))
564 	{
565 	  return FALSE;
566 	}
567       if (rndup == 0)
568 	return TRUE;
569       return XDR_GETBYTES (xdrs, (caddr_t)crud, rndup);
570 
571     case XDR_ENCODE:
572       if (!XDR_PUTBYTES (xdrs, cp, cnt))
573 	{
574 	  return FALSE;
575 	}
576       if (rndup == 0)
577 	return TRUE;
578       return XDR_PUTBYTES (xdrs, xdr_zero, rndup);
579 
580     case XDR_FREE:
581       return TRUE;
582     }
583   return FALSE;
584 }
585 #ifdef EXPORT_RPC_SYMBOLS
libc_hidden_def(xdr_opaque)586 libc_hidden_def (xdr_opaque)
587 #else
588 libc_hidden_nolink_sunrpc (xdr_opaque, GLIBC_2_0)
589 #endif
590 
591 /*
592  * XDR counted bytes
593  * *cpp is a pointer to the bytes, *sizep is the count.
594  * If *cpp is NULL maxsize bytes are allocated
595  */
596 bool_t
597 xdr_bytes (XDR *xdrs, char **cpp, u_int *sizep, u_int maxsize)
598 {
599   char *sp = *cpp;	/* sp is the actual string pointer */
600   u_int nodesize;
601 
602   /*
603    * first deal with the length since xdr bytes are counted
604    */
605   if (!xdr_u_int (xdrs, sizep))
606     {
607       return FALSE;
608     }
609   nodesize = *sizep;
610   if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE))
611     {
612       return FALSE;
613     }
614 
615   /*
616    * now deal with the actual bytes
617    */
618   switch (xdrs->x_op)
619     {
620     case XDR_DECODE:
621       if (nodesize == 0)
622 	{
623 	  return TRUE;
624 	}
625       if (sp == NULL)
626 	{
627 	  *cpp = sp = (char *) mem_alloc (nodesize);
628 	}
629       if (sp == NULL)
630 	{
631 	  (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n"));
632 	  return FALSE;
633 	}
634       /* Fall through.  */
635 
636     case XDR_ENCODE:
637       return xdr_opaque (xdrs, sp, nodesize);
638 
639     case XDR_FREE:
640       if (sp != NULL)
641 	{
642 	  mem_free (sp, nodesize);
643 	  *cpp = NULL;
644 	}
645       return TRUE;
646     }
647   return FALSE;
648 }
649 #ifdef EXPORT_RPC_SYMBOLS
libc_hidden_def(xdr_bytes)650 libc_hidden_def (xdr_bytes)
651 #else
652 libc_hidden_nolink_sunrpc (xdr_bytes, GLIBC_2_0)
653 #endif
654 
655 /*
656  * Implemented here due to commonality of the object.
657  */
658 bool_t
659 xdr_netobj (XDR *xdrs, struct netobj *np)
660 {
661 
662   return xdr_bytes (xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ);
663 }
664 #ifdef EXPORT_RPC_SYMBOLS
libc_hidden_def(xdr_netobj)665 libc_hidden_def (xdr_netobj)
666 #else
667 libc_hidden_nolink_sunrpc (xdr_netobj, GLIBC_2_0)
668 #endif
669 
670 /*
671  * XDR a discriminated union
672  * Support routine for discriminated unions.
673  * You create an array of xdrdiscrim structures, terminated with
674  * an entry with a null procedure pointer.  The routine gets
675  * the discriminant value and then searches the array of xdrdiscrims
676  * looking for that value.  It calls the procedure given in the xdrdiscrim
677  * to handle the discriminant.  If there is no specific routine a default
678  * routine may be called.
679  * If there is no specific or default routine an error is returned.
680  */
681 bool_t
682 xdr_union (XDR *xdrs,
683 	   /* enum to decide which arm to work on */
684 	   enum_t *dscmp,
685 	   /* the union itself */
686 	   char *unp,
687 	   /* [value, xdr proc] for each arm */
688 	   const struct xdr_discrim *choices,
689 	   /* default xdr routine */
690 	   xdrproc_t dfault)
691 {
692   enum_t dscm;
693 
694   /*
695    * we deal with the discriminator;  it's an enum
696    */
697   if (!xdr_enum (xdrs, dscmp))
698     {
699       return FALSE;
700     }
701   dscm = *dscmp;
702 
703   /*
704    * search choices for a value that matches the discriminator.
705    * if we find one, execute the xdr routine for that value.
706    */
707   for (; choices->proc != NULL_xdrproc_t; choices++)
708     {
709       if (choices->value == dscm)
710 	return (*(choices->proc)) (xdrs, unp, LASTUNSIGNED);
711     }
712 
713   /*
714    * no match - execute the default xdr routine if there is one
715    */
716   return ((dfault == NULL_xdrproc_t) ? FALSE :
717 	  (*dfault) (xdrs, unp, LASTUNSIGNED));
718 }
libc_hidden_nolink_sunrpc(xdr_union,GLIBC_2_0)719 libc_hidden_nolink_sunrpc (xdr_union, GLIBC_2_0)
720 
721 
722 /*
723  * Non-portable xdr primitives.
724  * Care should be taken when moving these routines to new architectures.
725  */
726 
727 
728 /*
729  * XDR null terminated ASCII strings
730  * xdr_string deals with "C strings" - arrays of bytes that are
731  * terminated by a NUL character.  The parameter cpp references a
732  * pointer to storage; If the pointer is null, then the necessary
733  * storage is allocated.  The last parameter is the max allowed length
734  * of the string as specified by a protocol.
735  */
736 bool_t
737 xdr_string (XDR *xdrs, char **cpp, u_int maxsize)
738 {
739   char *sp = *cpp;	/* sp is the actual string pointer */
740   /* Initialize to silence the compiler.  It is not really needed because SIZE
741      never actually gets used without being initialized.  */
742   u_int size = 0;
743   u_int nodesize;
744 
745   /*
746    * first deal with the length since xdr strings are counted-strings
747    */
748   switch (xdrs->x_op)
749     {
750     case XDR_FREE:
751       if (sp == NULL)
752 	{
753 	  return TRUE;		/* already free */
754 	}
755       /* fall through... */
756     case XDR_ENCODE:
757       if (sp == NULL)
758 	return FALSE;
759       size = strlen (sp);
760       break;
761     case XDR_DECODE:
762       break;
763     }
764   if (!xdr_u_int (xdrs, &size))
765     {
766       return FALSE;
767     }
768   if (size > maxsize)
769     {
770       return FALSE;
771     }
772   nodesize = size + 1;
773   if (nodesize == 0)
774     {
775       /* This means an overflow.  It a bug in the caller which
776 	 provided a too large maxsize but nevertheless catch it
777 	 here.  */
778       return FALSE;
779     }
780 
781   /*
782    * now deal with the actual bytes
783    */
784   switch (xdrs->x_op)
785     {
786     case XDR_DECODE:
787       if (sp == NULL)
788 	*cpp = sp = (char *) mem_alloc (nodesize);
789       if (sp == NULL)
790 	{
791 	  (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n"));
792 	  return FALSE;
793 	}
794       sp[size] = 0;
795       /* Fall through.  */
796 
797     case XDR_ENCODE:
798       return xdr_opaque (xdrs, sp, size);
799 
800     case XDR_FREE:
801       mem_free (sp, nodesize);
802       *cpp = NULL;
803       return TRUE;
804     }
805   return FALSE;
806 }
807 #ifdef EXPORT_RPC_SYMBOLS
libc_hidden_def(xdr_string)808 libc_hidden_def (xdr_string)
809 #else
810 libc_hidden_nolink_sunrpc (xdr_string, GLIBC_2_0)
811 #endif
812 
813 /*
814  * Wrapper for xdr_string that can be called directly from
815  * routines like clnt_call
816  */
817 bool_t
818 xdr_wrapstring (XDR *xdrs, char **cpp)
819 {
820   if (xdr_string (xdrs, cpp, LASTUNSIGNED))
821     {
822       return TRUE;
823     }
824   return FALSE;
825 }
826 #ifdef EXPORT_RPC_SYMBOLS
827 libc_hidden_def (xdr_wrapstring)
828 #else
829 libc_hidden_nolink_sunrpc (xdr_wrapstring, GLIBC_2_0)
830 #endif
831