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