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
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
45 #include <rpc/types.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)
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
67 xdr_free (xdrproc_t proc
, char *objp
)
74 #ifdef EXPORT_RPC_SYMBOLS
75 libc_hidden_def (xdr_free
)
77 libc_hidden_nolink_sunrpc (xdr_free
, GLIBC_2_0
)
88 #ifdef EXPORT_RPC_SYMBOLS
89 libc_hidden_def (xdr_void
)
91 libc_hidden_nolink_sunrpc (xdr_void
, GLIBC_2_0
)
98 xdr_int (XDR
*xdrs
, int *ip
)
101 #if INT_MAX < LONG_MAX
108 return XDR_PUTLONG (xdrs
, &l
);
111 if (!XDR_GETLONG (xdrs
, &l
))
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
);
125 #error unexpected integer sizes in_xdr_int()
128 #ifdef EXPORT_RPC_SYMBOLS
129 libc_hidden_def (xdr_int
)
131 libc_hidden_nolink_sunrpc (xdr_int
, GLIBC_2_0
)
135 * XDR unsigned integers
138 xdr_u_int (XDR
*xdrs
, u_int
*up
)
140 #if UINT_MAX < ULONG_MAX
147 return XDR_PUTLONG (xdrs
, &l
);
150 if (!XDR_GETLONG (xdrs
, &l
))
154 *up
= (u_int
) (u_long
) l
;
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
);
164 #error unexpected integer sizes in_xdr_u_int()
167 #ifdef EXPORT_RPC_SYMBOLS
168 libc_hidden_def (xdr_u_int
)
170 libc_hidden_nolink_sunrpc (xdr_u_int
, GLIBC_2_0
)
175 * The definition of xdr_long() is kept for backward
176 * compatibility. Instead xdr_int() should be used.
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
)
195 #ifdef EXPORT_RPC_SYMBOLS
196 libc_hidden_def (xdr_long
)
198 libc_hidden_nolink_sunrpc (xdr_long
, GLIBC_2_0
)
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.
207 xdr_u_long (XDR
*xdrs
, u_long
*ulp
)
215 if (XDR_GETLONG (xdrs
, &tmp
) == FALSE
)
218 *ulp
= (uint32_t) tmp
;
223 if (sizeof (uint32_t) != sizeof (u_long
)
224 && (uint32_t) *ulp
!= *ulp
)
227 return XDR_PUTLONG (xdrs
, (long *) ulp
);
234 #ifdef EXPORT_RPC_SYMBOLS
235 libc_hidden_def (xdr_u_long
)
237 libc_hidden_nolink_sunrpc (xdr_u_long
, GLIBC_2_0
)
242 * same as xdr_u_hyper - open coded to save a proc call!
245 xdr_hyper (XDR
*xdrs
, quad_t
*llp
)
249 if (xdrs
->x_op
== XDR_ENCODE
)
251 t1
= (long) ((*llp
) >> 32);
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
))
260 *llp
= ((quad_t
) t1
) << 32;
261 *llp
|= (uint32_t) t2
;
265 if (xdrs
->x_op
== XDR_FREE
)
270 #ifdef EXPORT_RPC_SYMBOLS
271 libc_hidden_def (xdr_hyper
)
273 libc_hidden_nolink_sunrpc (xdr_hyper
, GLIBC_2_1_1
)
278 * same as xdr_hyper - open coded to save a proc call!
281 xdr_u_hyper (XDR
*xdrs
, u_quad_t
*ullp
)
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
))
296 *ullp
= ((u_quad_t
) t1
) << 32;
297 *ullp
|= (uint32_t) t2
;
301 if (xdrs
->x_op
== XDR_FREE
)
306 #ifdef EXPORT_RPC_SYMBOLS
307 libc_hidden_def (xdr_u_hyper
)
309 libc_hidden_nolink_sunrpc (xdr_u_hyper
, GLIBC_2_1_1
)
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
)
320 libc_hidden_nolink_sunrpc (xdr_longlong_t
, GLIBC_2_1_1
)
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
)
331 libc_hidden_nolink_sunrpc (xdr_u_longlong_t
, GLIBC_2_1_1
)
338 xdr_short (XDR
*xdrs
, short *sp
)
346 return XDR_PUTLONG (xdrs
, &l
);
349 if (!XDR_GETLONG (xdrs
, &l
))
361 #ifdef EXPORT_RPC_SYMBOLS
362 libc_hidden_def (xdr_short
)
364 libc_hidden_nolink_sunrpc (xdr_short
, GLIBC_2_0
)
368 * XDR unsigned short integers
371 xdr_u_short (XDR
*xdrs
, u_short
*usp
)
379 return XDR_PUTLONG (xdrs
, &l
);
382 if (!XDR_GETLONG (xdrs
, &l
))
386 *usp
= (u_short
) (u_long
) l
;
394 #ifdef EXPORT_RPC_SYMBOLS
395 libc_hidden_def (xdr_u_short
)
397 libc_hidden_nolink_sunrpc (xdr_u_short
, GLIBC_2_0
)
405 xdr_char (XDR
*xdrs
, char *cp
)
410 if (!xdr_int (xdrs
, &i
))
417 #ifdef EXPORT_RPC_SYMBOLS
418 libc_hidden_def (xdr_char
)
420 libc_hidden_nolink_sunrpc (xdr_char
, GLIBC_2_0
)
424 * XDR an unsigned char
427 xdr_u_char (XDR
*xdrs
, u_char
*cp
)
432 if (!xdr_u_int (xdrs
, &u
))
439 #ifdef EXPORT_RPC_SYMBOLS
440 libc_hidden_def (xdr_u_char
)
442 libc_hidden_nolink_sunrpc (xdr_u_char
, GLIBC_2_0
)
449 xdr_bool (XDR
*xdrs
, bool_t
*bp
)
456 lb
= *bp
? XDR_TRUE
: XDR_FALSE
;
457 return XDR_PUTLONG (xdrs
, &lb
);
460 if (!XDR_GETLONG (xdrs
, &lb
))
464 *bp
= (lb
== XDR_FALSE
) ? FALSE
: TRUE
;
472 #ifdef EXPORT_RPC_SYMBOLS
473 libc_hidden_def (xdr_bool
)
475 libc_hidden_nolink_sunrpc (xdr_bool
, GLIBC_2_0
)
482 xdr_enum (XDR
*xdrs
, enum_t
*ep
)
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
501 return XDR_PUTLONG (xdrs
, &l
);
504 if (!XDR_GETLONG (xdrs
, &l
))
515 return xdr_long (xdrs
, (long *) ep
);
518 else if (sizeof (enum sizecheck
) == sizeof (short))
520 return xdr_short (xdrs
, (short *) ep
);
527 #ifdef EXPORT_RPC_SYMBOLS
528 libc_hidden_def (xdr_enum
)
530 libc_hidden_nolink_sunrpc (xdr_enum
, GLIBC_2_0
)
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.
539 xdr_opaque (XDR
*xdrs
, caddr_t cp
, u_int cnt
)
542 static char crud
[BYTES_PER_XDR_UNIT
];
545 * if no data we are done
551 * round byte count to full xdr units
553 rndup
= cnt
% BYTES_PER_XDR_UNIT
;
555 rndup
= BYTES_PER_XDR_UNIT
- rndup
;
560 if (!XDR_GETBYTES (xdrs
, cp
, cnt
))
566 return XDR_GETBYTES (xdrs
, (caddr_t
)crud
, rndup
);
569 if (!XDR_PUTBYTES (xdrs
, cp
, cnt
))
575 return XDR_PUTBYTES (xdrs
, xdr_zero
, rndup
);
582 #ifdef EXPORT_RPC_SYMBOLS
583 libc_hidden_def (xdr_opaque
)
585 libc_hidden_nolink_sunrpc (xdr_opaque
, GLIBC_2_0
)
590 * *cpp is a pointer to the bytes, *sizep is the count.
591 * If *cpp is NULL maxsize bytes are allocated
594 xdr_bytes (XDR
*xdrs
, char **cpp
, u_int
*sizep
, u_int maxsize
)
596 char *sp
= *cpp
; /* sp is the actual string pointer */
600 * first deal with the length since xdr bytes are counted
602 if (!xdr_u_int (xdrs
, sizep
))
607 if ((nodesize
> maxsize
) && (xdrs
->x_op
!= XDR_FREE
))
613 * now deal with the actual bytes
624 *cpp
= sp
= (char *) mem_alloc (nodesize
);
628 (void) __fxprintf (NULL
, "%s: %s", __func__
, _("out of memory\n"));
634 return xdr_opaque (xdrs
, sp
, nodesize
);
639 mem_free (sp
, nodesize
);
646 #ifdef EXPORT_RPC_SYMBOLS
647 libc_hidden_def (xdr_bytes
)
649 libc_hidden_nolink_sunrpc (xdr_bytes
, GLIBC_2_0
)
653 * Implemented here due to commonality of the object.
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
)
664 libc_hidden_nolink_sunrpc (xdr_netobj
, GLIBC_2_0
)
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.
679 xdr_union (XDR
*xdrs
,
680 /* enum to decide which arm to work on */
682 /* the union itself */
684 /* [value, xdr proc] for each arm */
685 const struct xdr_discrim
*choices
,
686 /* default xdr routine */
692 * we deal with the discriminator; it's an enum
694 if (!xdr_enum (xdrs
, 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.
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. */
743 * first deal with the length since xdr strings are counted-strings
750 return TRUE
; /* already free */
752 /* fall through... */
761 if (!xdr_u_int (xdrs
, &size
))
772 /* This means an overflow. It a bug in the caller which
773 provided a too large maxsize but nevertheless catch it
779 * now deal with the actual bytes
785 *cpp
= sp
= (char *) mem_alloc (nodesize
);
788 (void) __fxprintf (NULL
, "%s: %s", __func__
, _("out of memory\n"));
795 return xdr_opaque (xdrs
, sp
, size
);
798 mem_free (sp
, nodesize
);
804 #ifdef EXPORT_RPC_SYMBOLS
805 libc_hidden_def (xdr_string
)
807 libc_hidden_nolink_sunrpc (xdr_string
, GLIBC_2_0
)
811 * Wrapper for xdr_string that can be called directly from
812 * routines like clnt_call
815 xdr_wrapstring (XDR
*xdrs
, char **cpp
)
817 if (xdr_string (xdrs
, cpp
, LASTUNSIGNED
))
823 #ifdef EXPORT_RPC_SYMBOLS
824 libc_hidden_def (xdr_wrapstring
)
826 libc_hidden_nolink_sunrpc (xdr_wrapstring
, GLIBC_2_0
)