Add a missing ChangeLog item in commit 371b220f620
[glibc.git] / sunrpc / xdr.c
blob8b0b91995b79b859a8ff12d81f1720368b645b16
1 /*
2 * xdr.c, Generic XDR routines implementation.
4 * Copyright (c) 2010, Oracle America, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
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.
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.
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.
38 #include <stdio.h>
39 #include <limits.h>
40 #include <string.h>
41 #include <libintl.h>
42 #include <wchar.h>
43 #include <stdint.h>
45 #include <rpc/types.h>
46 #include <rpc/xdr.h>
47 #include <shlib-compat.h>
51 * constants specific to the xdr "protocol"
53 #define XDR_FALSE ((long) 0)
54 #define XDR_TRUE ((long) 1)
55 #define LASTUNSIGNED ((u_int) 0-1)
58 * for unit alignment
60 static const char xdr_zero[BYTES_PER_XDR_UNIT] = {0, 0, 0, 0};
63 * Free a data structure using XDR
64 * Not a filter, but a convenient utility nonetheless
66 void
67 xdr_free (xdrproc_t proc, char *objp)
69 XDR x;
71 x.x_op = XDR_FREE;
72 (*proc) (&x, objp);
74 #ifdef EXPORT_RPC_SYMBOLS
75 libc_hidden_def (xdr_free)
76 #else
77 libc_hidden_nolink_sunrpc (xdr_free, GLIBC_2_0)
78 #endif
81 * XDR nothing
83 bool_t
84 xdr_void (void)
86 return TRUE;
88 #ifdef EXPORT_RPC_SYMBOLS
89 libc_hidden_def (xdr_void)
90 #else
91 libc_hidden_nolink_sunrpc (xdr_void, GLIBC_2_0)
92 #endif
95 * XDR integers
97 bool_t
98 xdr_int (XDR *xdrs, int *ip)
101 #if INT_MAX < LONG_MAX
102 long l;
104 switch (xdrs->x_op)
106 case XDR_ENCODE:
107 l = (long) *ip;
108 return XDR_PUTLONG (xdrs, &l);
110 case XDR_DECODE:
111 if (!XDR_GETLONG (xdrs, &l))
113 return FALSE;
115 *ip = (int) l;
116 case XDR_FREE:
117 return TRUE;
119 return FALSE;
120 #elif INT_MAX == LONG_MAX
121 return xdr_long (xdrs, (long *) ip);
122 #elif INT_MAX == SHRT_MAX
123 return xdr_short (xdrs, (short *) ip);
124 #else
125 #error unexpected integer sizes in_xdr_int()
126 #endif
128 #ifdef EXPORT_RPC_SYMBOLS
129 libc_hidden_def (xdr_int)
130 #else
131 libc_hidden_nolink_sunrpc (xdr_int, GLIBC_2_0)
132 #endif
135 * XDR unsigned integers
137 bool_t
138 xdr_u_int (XDR *xdrs, u_int *up)
140 #if UINT_MAX < ULONG_MAX
141 long l;
143 switch (xdrs->x_op)
145 case XDR_ENCODE:
146 l = (u_long) * up;
147 return XDR_PUTLONG (xdrs, &l);
149 case XDR_DECODE:
150 if (!XDR_GETLONG (xdrs, &l))
152 return FALSE;
154 *up = (u_int) (u_long) l;
155 case XDR_FREE:
156 return TRUE;
158 return FALSE;
159 #elif UINT_MAX == ULONG_MAX
160 return xdr_u_long (xdrs, (u_long *) up);
161 #elif UINT_MAX == USHRT_MAX
162 return xdr_short (xdrs, (short *) up);
163 #else
164 #error unexpected integer sizes in_xdr_u_int()
165 #endif
167 #ifdef EXPORT_RPC_SYMBOLS
168 libc_hidden_def (xdr_u_int)
169 #else
170 libc_hidden_nolink_sunrpc (xdr_u_int, GLIBC_2_0)
171 #endif
174 * XDR long integers
175 * The definition of xdr_long() is kept for backward
176 * compatibility. Instead xdr_int() should be used.
178 bool_t
179 xdr_long (XDR *xdrs, long *lp)
182 if (xdrs->x_op == XDR_ENCODE
183 && (sizeof (int32_t) == sizeof (long)
184 || (int32_t) *lp == *lp))
185 return XDR_PUTLONG (xdrs, lp);
187 if (xdrs->x_op == XDR_DECODE)
188 return XDR_GETLONG (xdrs, lp);
190 if (xdrs->x_op == XDR_FREE)
191 return TRUE;
193 return FALSE;
195 #ifdef EXPORT_RPC_SYMBOLS
196 libc_hidden_def (xdr_long)
197 #else
198 libc_hidden_nolink_sunrpc (xdr_long, GLIBC_2_0)
199 #endif
202 * XDR unsigned long integers
203 * The definition of xdr_u_long() is kept for backward
204 * compatibility. Instead xdr_u_int() should be used.
206 bool_t
207 xdr_u_long (XDR *xdrs, u_long *ulp)
209 switch (xdrs->x_op)
211 case XDR_DECODE:
213 long int tmp;
215 if (XDR_GETLONG (xdrs, &tmp) == FALSE)
216 return FALSE;
218 *ulp = (uint32_t) tmp;
219 return TRUE;
222 case XDR_ENCODE:
223 if (sizeof (uint32_t) != sizeof (u_long)
224 && (uint32_t) *ulp != *ulp)
225 return FALSE;
227 return XDR_PUTLONG (xdrs, (long *) ulp);
229 case XDR_FREE:
230 return TRUE;
232 return FALSE;
234 #ifdef EXPORT_RPC_SYMBOLS
235 libc_hidden_def (xdr_u_long)
236 #else
237 libc_hidden_nolink_sunrpc (xdr_u_long, GLIBC_2_0)
238 #endif
241 * XDR hyper integers
242 * same as xdr_u_hyper - open coded to save a proc call!
244 bool_t
245 xdr_hyper (XDR *xdrs, quad_t *llp)
247 long int t1, t2;
249 if (xdrs->x_op == XDR_ENCODE)
251 t1 = (long) ((*llp) >> 32);
252 t2 = (long) (*llp);
253 return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, &t2));
256 if (xdrs->x_op == XDR_DECODE)
258 if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2))
259 return FALSE;
260 *llp = ((quad_t) t1) << 32;
261 *llp |= (uint32_t) t2;
262 return TRUE;
265 if (xdrs->x_op == XDR_FREE)
266 return TRUE;
268 return FALSE;
270 #ifdef EXPORT_RPC_SYMBOLS
271 libc_hidden_def (xdr_hyper)
272 #else
273 libc_hidden_nolink_sunrpc (xdr_hyper, GLIBC_2_1_1)
274 #endif
277 * XDR hyper integers
278 * same as xdr_hyper - open coded to save a proc call!
280 bool_t
281 xdr_u_hyper (XDR *xdrs, u_quad_t *ullp)
283 long int t1, t2;
285 if (xdrs->x_op == XDR_ENCODE)
287 t1 = (unsigned long) ((*ullp) >> 32);
288 t2 = (unsigned long) (*ullp);
289 return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, &t2));
292 if (xdrs->x_op == XDR_DECODE)
294 if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2))
295 return FALSE;
296 *ullp = ((u_quad_t) t1) << 32;
297 *ullp |= (uint32_t) t2;
298 return TRUE;
301 if (xdrs->x_op == XDR_FREE)
302 return TRUE;
304 return FALSE;
306 #ifdef EXPORT_RPC_SYMBOLS
307 libc_hidden_def (xdr_u_hyper)
308 #else
309 libc_hidden_nolink_sunrpc (xdr_u_hyper, GLIBC_2_1_1)
310 #endif
312 bool_t
313 xdr_longlong_t (XDR *xdrs, quad_t *llp)
315 return xdr_hyper (xdrs, llp);
317 #ifdef EXPORT_RPC_SYMBOLS
318 libc_hidden_def (xdr_longlong_t)
319 #else
320 libc_hidden_nolink_sunrpc (xdr_longlong_t, GLIBC_2_1_1)
321 #endif
323 bool_t
324 xdr_u_longlong_t (XDR *xdrs, u_quad_t *ullp)
326 return xdr_u_hyper (xdrs, ullp);
328 #ifdef EXPORT_RPC_SYMBOLS
329 libc_hidden_def (xdr_u_longlong_t)
330 #else
331 libc_hidden_nolink_sunrpc (xdr_u_longlong_t, GLIBC_2_1_1)
332 #endif
335 * XDR short integers
337 bool_t
338 xdr_short (XDR *xdrs, short *sp)
340 long l;
342 switch (xdrs->x_op)
344 case XDR_ENCODE:
345 l = (long) *sp;
346 return XDR_PUTLONG (xdrs, &l);
348 case XDR_DECODE:
349 if (!XDR_GETLONG (xdrs, &l))
351 return FALSE;
353 *sp = (short) l;
354 return TRUE;
356 case XDR_FREE:
357 return TRUE;
359 return FALSE;
361 #ifdef EXPORT_RPC_SYMBOLS
362 libc_hidden_def (xdr_short)
363 #else
364 libc_hidden_nolink_sunrpc (xdr_short, GLIBC_2_0)
365 #endif
368 * XDR unsigned short integers
370 bool_t
371 xdr_u_short (XDR *xdrs, u_short *usp)
373 long l;
375 switch (xdrs->x_op)
377 case XDR_ENCODE:
378 l = (u_long) * usp;
379 return XDR_PUTLONG (xdrs, &l);
381 case XDR_DECODE:
382 if (!XDR_GETLONG (xdrs, &l))
384 return FALSE;
386 *usp = (u_short) (u_long) l;
387 return TRUE;
389 case XDR_FREE:
390 return TRUE;
392 return FALSE;
394 #ifdef EXPORT_RPC_SYMBOLS
395 libc_hidden_def (xdr_u_short)
396 #else
397 libc_hidden_nolink_sunrpc (xdr_u_short, GLIBC_2_0)
398 #endif
402 * XDR a char
404 bool_t
405 xdr_char (XDR *xdrs, char *cp)
407 int i;
409 i = (*cp);
410 if (!xdr_int (xdrs, &i))
412 return FALSE;
414 *cp = i;
415 return TRUE;
417 #ifdef EXPORT_RPC_SYMBOLS
418 libc_hidden_def (xdr_char)
419 #else
420 libc_hidden_nolink_sunrpc (xdr_char, GLIBC_2_0)
421 #endif
424 * XDR an unsigned char
426 bool_t
427 xdr_u_char (XDR *xdrs, u_char *cp)
429 u_int u;
431 u = (*cp);
432 if (!xdr_u_int (xdrs, &u))
434 return FALSE;
436 *cp = u;
437 return TRUE;
439 #ifdef EXPORT_RPC_SYMBOLS
440 libc_hidden_def (xdr_u_char)
441 #else
442 libc_hidden_nolink_sunrpc (xdr_u_char, GLIBC_2_0)
443 #endif
446 * XDR booleans
448 bool_t
449 xdr_bool (XDR *xdrs, bool_t *bp)
451 long lb;
453 switch (xdrs->x_op)
455 case XDR_ENCODE:
456 lb = *bp ? XDR_TRUE : XDR_FALSE;
457 return XDR_PUTLONG (xdrs, &lb);
459 case XDR_DECODE:
460 if (!XDR_GETLONG (xdrs, &lb))
462 return FALSE;
464 *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
465 return TRUE;
467 case XDR_FREE:
468 return TRUE;
470 return FALSE;
472 #ifdef EXPORT_RPC_SYMBOLS
473 libc_hidden_def (xdr_bool)
474 #else
475 libc_hidden_nolink_sunrpc (xdr_bool, GLIBC_2_0)
476 #endif
479 * XDR enumerations
481 bool_t
482 xdr_enum (XDR *xdrs, enum_t *ep)
484 enum sizecheck
486 SIZEVAL
487 }; /* used to find the size of an enum */
490 * enums are treated as ints
492 if (sizeof (enum sizecheck) == 4)
494 #if INT_MAX < LONG_MAX
495 long l;
497 switch (xdrs->x_op)
499 case XDR_ENCODE:
500 l = *ep;
501 return XDR_PUTLONG (xdrs, &l);
503 case XDR_DECODE:
504 if (!XDR_GETLONG (xdrs, &l))
506 return FALSE;
508 *ep = l;
509 case XDR_FREE:
510 return TRUE;
513 return FALSE;
514 #else
515 return xdr_long (xdrs, (long *) ep);
516 #endif
518 else if (sizeof (enum sizecheck) == sizeof (short))
520 return xdr_short (xdrs, (short *) ep);
522 else
524 return FALSE;
527 #ifdef EXPORT_RPC_SYMBOLS
528 libc_hidden_def (xdr_enum)
529 #else
530 libc_hidden_nolink_sunrpc (xdr_enum, GLIBC_2_0)
531 #endif
534 * XDR opaque data
535 * Allows the specification of a fixed size sequence of opaque bytes.
536 * cp points to the opaque object and cnt gives the byte length.
538 bool_t
539 xdr_opaque (XDR *xdrs, caddr_t cp, u_int cnt)
541 u_int rndup;
542 static char crud[BYTES_PER_XDR_UNIT];
545 * if no data we are done
547 if (cnt == 0)
548 return TRUE;
551 * round byte count to full xdr units
553 rndup = cnt % BYTES_PER_XDR_UNIT;
554 if (rndup > 0)
555 rndup = BYTES_PER_XDR_UNIT - rndup;
557 switch (xdrs->x_op)
559 case XDR_DECODE:
560 if (!XDR_GETBYTES (xdrs, cp, cnt))
562 return FALSE;
564 if (rndup == 0)
565 return TRUE;
566 return XDR_GETBYTES (xdrs, (caddr_t)crud, rndup);
568 case XDR_ENCODE:
569 if (!XDR_PUTBYTES (xdrs, cp, cnt))
571 return FALSE;
573 if (rndup == 0)
574 return TRUE;
575 return XDR_PUTBYTES (xdrs, xdr_zero, rndup);
577 case XDR_FREE:
578 return TRUE;
580 return FALSE;
582 #ifdef EXPORT_RPC_SYMBOLS
583 libc_hidden_def (xdr_opaque)
584 #else
585 libc_hidden_nolink_sunrpc (xdr_opaque, GLIBC_2_0)
586 #endif
589 * XDR counted bytes
590 * *cpp is a pointer to the bytes, *sizep is the count.
591 * If *cpp is NULL maxsize bytes are allocated
593 bool_t
594 xdr_bytes (XDR *xdrs, char **cpp, u_int *sizep, u_int maxsize)
596 char *sp = *cpp; /* sp is the actual string pointer */
597 u_int nodesize;
600 * first deal with the length since xdr bytes are counted
602 if (!xdr_u_int (xdrs, sizep))
604 return FALSE;
606 nodesize = *sizep;
607 if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE))
609 return FALSE;
613 * now deal with the actual bytes
615 switch (xdrs->x_op)
617 case XDR_DECODE:
618 if (nodesize == 0)
620 return TRUE;
622 if (sp == NULL)
624 *cpp = sp = (char *) mem_alloc (nodesize);
626 if (sp == NULL)
628 (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n"));
629 return FALSE;
631 /* fall into ... */
633 case XDR_ENCODE:
634 return xdr_opaque (xdrs, sp, nodesize);
636 case XDR_FREE:
637 if (sp != NULL)
639 mem_free (sp, nodesize);
640 *cpp = NULL;
642 return TRUE;
644 return FALSE;
646 #ifdef EXPORT_RPC_SYMBOLS
647 libc_hidden_def (xdr_bytes)
648 #else
649 libc_hidden_nolink_sunrpc (xdr_bytes, GLIBC_2_0)
650 #endif
653 * Implemented here due to commonality of the object.
655 bool_t
656 xdr_netobj (XDR *xdrs, struct netobj *np)
659 return xdr_bytes (xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ);
661 #ifdef EXPORT_RPC_SYMBOLS
662 libc_hidden_def (xdr_netobj)
663 #else
664 libc_hidden_nolink_sunrpc (xdr_netobj, GLIBC_2_0)
665 #endif
668 * XDR a discriminated union
669 * Support routine for discriminated unions.
670 * You create an array of xdrdiscrim structures, terminated with
671 * an entry with a null procedure pointer. The routine gets
672 * the discriminant value and then searches the array of xdrdiscrims
673 * looking for that value. It calls the procedure given in the xdrdiscrim
674 * to handle the discriminant. If there is no specific routine a default
675 * routine may be called.
676 * If there is no specific or default routine an error is returned.
678 bool_t
679 xdr_union (XDR *xdrs,
680 /* enum to decide which arm to work on */
681 enum_t *dscmp,
682 /* the union itself */
683 char *unp,
684 /* [value, xdr proc] for each arm */
685 const struct xdr_discrim *choices,
686 /* default xdr routine */
687 xdrproc_t dfault)
689 enum_t dscm;
692 * we deal with the discriminator; it's an enum
694 if (!xdr_enum (xdrs, dscmp))
696 return FALSE;
698 dscm = *dscmp;
701 * search choices for a value that matches the discriminator.
702 * if we find one, execute the xdr routine for that value.
704 for (; choices->proc != NULL_xdrproc_t; choices++)
706 if (choices->value == dscm)
707 return (*(choices->proc)) (xdrs, unp, LASTUNSIGNED);
711 * no match - execute the default xdr routine if there is one
713 return ((dfault == NULL_xdrproc_t) ? FALSE :
714 (*dfault) (xdrs, unp, LASTUNSIGNED));
716 libc_hidden_nolink_sunrpc (xdr_union, GLIBC_2_0)
720 * Non-portable xdr primitives.
721 * Care should be taken when moving these routines to new architectures.
726 * XDR null terminated ASCII strings
727 * xdr_string deals with "C strings" - arrays of bytes that are
728 * terminated by a NULL character. The parameter cpp references a
729 * pointer to storage; If the pointer is null, then the necessary
730 * storage is allocated. The last parameter is the max allowed length
731 * of the string as specified by a protocol.
733 bool_t
734 xdr_string (XDR *xdrs, char **cpp, u_int maxsize)
736 char *sp = *cpp; /* sp is the actual string pointer */
737 /* Initialize to silence the compiler. It is not really needed because SIZE
738 never actually gets used without being initialized. */
739 u_int size = 0;
740 u_int nodesize;
743 * first deal with the length since xdr strings are counted-strings
745 switch (xdrs->x_op)
747 case XDR_FREE:
748 if (sp == NULL)
750 return TRUE; /* already free */
752 /* fall through... */
753 case XDR_ENCODE:
754 if (sp == NULL)
755 return FALSE;
756 size = strlen (sp);
757 break;
758 case XDR_DECODE:
759 break;
761 if (!xdr_u_int (xdrs, &size))
763 return FALSE;
765 if (size > maxsize)
767 return FALSE;
769 nodesize = size + 1;
770 if (nodesize == 0)
772 /* This means an overflow. It a bug in the caller which
773 provided a too large maxsize but nevertheless catch it
774 here. */
775 return FALSE;
779 * now deal with the actual bytes
781 switch (xdrs->x_op)
783 case XDR_DECODE:
784 if (sp == NULL)
785 *cpp = sp = (char *) mem_alloc (nodesize);
786 if (sp == NULL)
788 (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n"));
789 return FALSE;
791 sp[size] = 0;
792 /* fall into ... */
794 case XDR_ENCODE:
795 return xdr_opaque (xdrs, sp, size);
797 case XDR_FREE:
798 mem_free (sp, nodesize);
799 *cpp = NULL;
800 return TRUE;
802 return FALSE;
804 #ifdef EXPORT_RPC_SYMBOLS
805 libc_hidden_def (xdr_string)
806 #else
807 libc_hidden_nolink_sunrpc (xdr_string, GLIBC_2_0)
808 #endif
811 * Wrapper for xdr_string that can be called directly from
812 * routines like clnt_call
814 bool_t
815 xdr_wrapstring (XDR *xdrs, char **cpp)
817 if (xdr_string (xdrs, cpp, LASTUNSIGNED))
819 return TRUE;
821 return FALSE;
823 #ifdef EXPORT_RPC_SYMBOLS
824 libc_hidden_def (xdr_wrapstring)
825 #else
826 libc_hidden_nolink_sunrpc (xdr_wrapstring, GLIBC_2_0)
827 #endif