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
))
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
);
126 #error unexpected integer sizes in_xdr_int()
129 #ifdef EXPORT_RPC_SYMBOLS
130 libc_hidden_def (xdr_int
)
132 libc_hidden_nolink_sunrpc (xdr_int
, GLIBC_2_0
)
136 * XDR unsigned integers
139 xdr_u_int (XDR
*xdrs
, u_int
*up
)
141 #if UINT_MAX < ULONG_MAX
148 return XDR_PUTLONG (xdrs
, &l
);
151 if (!XDR_GETLONG (xdrs
, &l
))
155 *up
= (u_int
) (u_long
) l
;
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
);
166 #error unexpected integer sizes in_xdr_u_int()
169 #ifdef EXPORT_RPC_SYMBOLS
170 libc_hidden_def (xdr_u_int
)
172 libc_hidden_nolink_sunrpc (xdr_u_int
, GLIBC_2_0
)
177 * The definition of xdr_long() is kept for backward
178 * compatibility. Instead xdr_int() should be used.
181 xdr_long (XDR
*xdrs
, long *lp
)
184 if (xdrs
->x_op
== XDR_ENCODE
185 && (sizeof (int32_t) == sizeof (long)
186 || (int32_t) *lp
== *lp
))
187 return XDR_PUTLONG (xdrs
, lp
);
189 if (xdrs
->x_op
== XDR_DECODE
)
190 return XDR_GETLONG (xdrs
, lp
);
192 if (xdrs
->x_op
== XDR_FREE
)
197 #ifdef EXPORT_RPC_SYMBOLS
198 libc_hidden_def (xdr_long
)
200 libc_hidden_nolink_sunrpc (xdr_long
, GLIBC_2_0
)
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.
209 xdr_u_long (XDR
*xdrs
, u_long
*ulp
)
217 if (XDR_GETLONG (xdrs
, &tmp
) == FALSE
)
220 *ulp
= (uint32_t) tmp
;
225 if (sizeof (uint32_t) != sizeof (u_long
)
226 && (uint32_t) *ulp
!= *ulp
)
229 return XDR_PUTLONG (xdrs
, (long *) ulp
);
236 #ifdef EXPORT_RPC_SYMBOLS
237 libc_hidden_def (xdr_u_long
)
239 libc_hidden_nolink_sunrpc (xdr_u_long
, GLIBC_2_0
)
244 * same as xdr_u_hyper - open coded to save a proc call!
247 xdr_hyper (XDR
*xdrs
, quad_t
*llp
)
251 if (xdrs
->x_op
== XDR_ENCODE
)
253 t1
= (long) ((*llp
) >> 32);
255 return (XDR_PUTLONG(xdrs
, &t1
) && XDR_PUTLONG(xdrs
, &t2
));
258 if (xdrs
->x_op
== XDR_DECODE
)
260 if (!XDR_GETLONG(xdrs
, &t1
) || !XDR_GETLONG(xdrs
, &t2
))
262 *llp
= ((quad_t
) t1
) << 32;
263 *llp
|= (uint32_t) t2
;
267 if (xdrs
->x_op
== XDR_FREE
)
272 #ifdef EXPORT_RPC_SYMBOLS
273 libc_hidden_def (xdr_hyper
)
275 libc_hidden_nolink_sunrpc (xdr_hyper
, GLIBC_2_1_1
)
280 * same as xdr_hyper - open coded to save a proc call!
283 xdr_u_hyper (XDR
*xdrs
, u_quad_t
*ullp
)
287 if (xdrs
->x_op
== XDR_ENCODE
)
289 t1
= (unsigned long) ((*ullp
) >> 32);
290 t2
= (unsigned long) (*ullp
);
291 return (XDR_PUTLONG(xdrs
, &t1
) && XDR_PUTLONG(xdrs
, &t2
));
294 if (xdrs
->x_op
== XDR_DECODE
)
296 if (!XDR_GETLONG(xdrs
, &t1
) || !XDR_GETLONG(xdrs
, &t2
))
298 *ullp
= ((u_quad_t
) t1
) << 32;
299 *ullp
|= (uint32_t) t2
;
303 if (xdrs
->x_op
== XDR_FREE
)
308 #ifdef EXPORT_RPC_SYMBOLS
309 libc_hidden_def (xdr_u_hyper
)
311 libc_hidden_nolink_sunrpc (xdr_u_hyper
, GLIBC_2_1_1
)
315 xdr_longlong_t (XDR
*xdrs
, quad_t
*llp
)
317 return xdr_hyper (xdrs
, llp
);
319 #ifdef EXPORT_RPC_SYMBOLS
320 libc_hidden_def (xdr_longlong_t
)
322 libc_hidden_nolink_sunrpc (xdr_longlong_t
, GLIBC_2_1_1
)
326 xdr_u_longlong_t (XDR
*xdrs
, u_quad_t
*ullp
)
328 return xdr_u_hyper (xdrs
, ullp
);
330 #ifdef EXPORT_RPC_SYMBOLS
331 libc_hidden_def (xdr_u_longlong_t
)
333 libc_hidden_nolink_sunrpc (xdr_u_longlong_t
, GLIBC_2_1_1
)
340 xdr_short (XDR
*xdrs
, short *sp
)
348 return XDR_PUTLONG (xdrs
, &l
);
351 if (!XDR_GETLONG (xdrs
, &l
))
363 #ifdef EXPORT_RPC_SYMBOLS
364 libc_hidden_def (xdr_short
)
366 libc_hidden_nolink_sunrpc (xdr_short
, GLIBC_2_0
)
370 * XDR unsigned short integers
373 xdr_u_short (XDR
*xdrs
, u_short
*usp
)
381 return XDR_PUTLONG (xdrs
, &l
);
384 if (!XDR_GETLONG (xdrs
, &l
))
388 *usp
= (u_short
) (u_long
) l
;
396 #ifdef EXPORT_RPC_SYMBOLS
397 libc_hidden_def (xdr_u_short
)
399 libc_hidden_nolink_sunrpc (xdr_u_short
, GLIBC_2_0
)
407 xdr_char (XDR
*xdrs
, char *cp
)
412 if (!xdr_int (xdrs
, &i
))
419 #ifdef EXPORT_RPC_SYMBOLS
420 libc_hidden_def (xdr_char
)
422 libc_hidden_nolink_sunrpc (xdr_char
, GLIBC_2_0
)
426 * XDR an unsigned char
429 xdr_u_char (XDR
*xdrs
, u_char
*cp
)
434 if (!xdr_u_int (xdrs
, &u
))
441 #ifdef EXPORT_RPC_SYMBOLS
442 libc_hidden_def (xdr_u_char
)
444 libc_hidden_nolink_sunrpc (xdr_u_char
, GLIBC_2_0
)
451 xdr_bool (XDR
*xdrs
, bool_t
*bp
)
458 lb
= *bp
? XDR_TRUE
: XDR_FALSE
;
459 return XDR_PUTLONG (xdrs
, &lb
);
462 if (!XDR_GETLONG (xdrs
, &lb
))
466 *bp
= (lb
== XDR_FALSE
) ? FALSE
: TRUE
;
474 #ifdef EXPORT_RPC_SYMBOLS
475 libc_hidden_def (xdr_bool
)
477 libc_hidden_nolink_sunrpc (xdr_bool
, GLIBC_2_0
)
484 xdr_enum (XDR
*xdrs
, enum_t
*ep
)
489 }; /* used to find the size of an enum */
492 * enums are treated as ints
494 if (sizeof (enum sizecheck
) == 4)
496 #if INT_MAX < LONG_MAX
503 return XDR_PUTLONG (xdrs
, &l
);
506 if (!XDR_GETLONG (xdrs
, &l
))
518 return xdr_long (xdrs
, (long *) ep
);
521 else if (sizeof (enum sizecheck
) == sizeof (short))
523 return xdr_short (xdrs
, (short *) ep
);
530 #ifdef EXPORT_RPC_SYMBOLS
531 libc_hidden_def (xdr_enum
)
533 libc_hidden_nolink_sunrpc (xdr_enum
, GLIBC_2_0
)
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.
542 xdr_opaque (XDR
*xdrs
, caddr_t cp
, u_int cnt
)
545 static char crud
[BYTES_PER_XDR_UNIT
];
548 * if no data we are done
554 * round byte count to full xdr units
556 rndup
= cnt
% BYTES_PER_XDR_UNIT
;
558 rndup
= BYTES_PER_XDR_UNIT
- rndup
;
563 if (!XDR_GETBYTES (xdrs
, cp
, cnt
))
569 return XDR_GETBYTES (xdrs
, (caddr_t
)crud
, rndup
);
572 if (!XDR_PUTBYTES (xdrs
, cp
, cnt
))
578 return XDR_PUTBYTES (xdrs
, xdr_zero
, rndup
);
585 #ifdef EXPORT_RPC_SYMBOLS
586 libc_hidden_def (xdr_opaque
)
588 libc_hidden_nolink_sunrpc (xdr_opaque
, GLIBC_2_0
)
593 * *cpp is a pointer to the bytes, *sizep is the count.
594 * If *cpp is NULL maxsize bytes are allocated
597 xdr_bytes (XDR
*xdrs
, char **cpp
, u_int
*sizep
, u_int maxsize
)
599 char *sp
= *cpp
; /* sp is the actual string pointer */
603 * first deal with the length since xdr bytes are counted
605 if (!xdr_u_int (xdrs
, sizep
))
610 if ((nodesize
> maxsize
) && (xdrs
->x_op
!= XDR_FREE
))
616 * now deal with the actual bytes
627 *cpp
= sp
= (char *) mem_alloc (nodesize
);
631 (void) __fxprintf (NULL
, "%s: %s", __func__
, _("out of memory\n"));
637 return xdr_opaque (xdrs
, sp
, nodesize
);
642 mem_free (sp
, nodesize
);
649 #ifdef EXPORT_RPC_SYMBOLS
650 libc_hidden_def (xdr_bytes
)
652 libc_hidden_nolink_sunrpc (xdr_bytes
, GLIBC_2_0
)
656 * Implemented here due to commonality of the object.
659 xdr_netobj (XDR
*xdrs
, struct netobj
*np
)
662 return xdr_bytes (xdrs
, &np
->n_bytes
, &np
->n_len
, MAX_NETOBJ_SZ
);
664 #ifdef EXPORT_RPC_SYMBOLS
665 libc_hidden_def (xdr_netobj
)
667 libc_hidden_nolink_sunrpc (xdr_netobj
, GLIBC_2_0
)
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.
682 xdr_union (XDR
*xdrs
,
683 /* enum to decide which arm to work on */
685 /* the union itself */
687 /* [value, xdr proc] for each arm */
688 const struct xdr_discrim
*choices
,
689 /* default xdr routine */
695 * we deal with the discriminator; it's an enum
697 if (!xdr_enum (xdrs
, dscmp
))
704 * search choices for a value that matches the discriminator.
705 * if we find one, execute the xdr routine for that value.
707 for (; choices
->proc
!= NULL_xdrproc_t
; choices
++)
709 if (choices
->value
== dscm
)
710 return (*(choices
->proc
)) (xdrs
, unp
, LASTUNSIGNED
);
714 * no match - execute the default xdr routine if there is one
716 return ((dfault
== NULL_xdrproc_t
) ? FALSE
:
717 (*dfault
) (xdrs
, unp
, LASTUNSIGNED
));
719 libc_hidden_nolink_sunrpc (xdr_union
, GLIBC_2_0
)
723 * Non-portable xdr primitives.
724 * Care should be taken when moving these routines to new architectures.
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.
737 xdr_string (XDR
*xdrs
, char **cpp
, u_int maxsize
)
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. */
746 * first deal with the length since xdr strings are counted-strings
753 return TRUE
; /* already free */
755 /* fall through... */
764 if (!xdr_u_int (xdrs
, &size
))
775 /* This means an overflow. It a bug in the caller which
776 provided a too large maxsize but nevertheless catch it
782 * now deal with the actual bytes
788 *cpp
= sp
= (char *) mem_alloc (nodesize
);
791 (void) __fxprintf (NULL
, "%s: %s", __func__
, _("out of memory\n"));
798 return xdr_opaque (xdrs
, sp
, size
);
801 mem_free (sp
, nodesize
);
807 #ifdef EXPORT_RPC_SYMBOLS
808 libc_hidden_def (xdr_string
)
810 libc_hidden_nolink_sunrpc (xdr_string
, GLIBC_2_0
)
814 * Wrapper for xdr_string that can be called directly from
815 * routines like clnt_call
818 xdr_wrapstring (XDR
*xdrs
, char **cpp
)
820 if (xdr_string (xdrs
, cpp
, LASTUNSIGNED
))
826 #ifdef EXPORT_RPC_SYMBOLS
827 libc_hidden_def (xdr_wrapstring
)
829 libc_hidden_nolink_sunrpc (xdr_wrapstring
, GLIBC_2_0
)