2 * Copyright (c) 2009, Sun Microsystems, Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * - Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * - Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
12 * - Neither the name of Sun Microsystems, Inc. nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
30 * xdr.c, Generic XDR routines implementation.
32 * Copyright (C) 1986, Sun Microsystems, Inc.
34 * These are the "generic" xdr routines used to serialize and de-serialize
35 * most common data items. See xdr.h for more info on the interface to
43 #include <rpc/types.h>
46 #include "xdr_private.h"
49 * constants specific to the xdr "protocol"
51 #define XDR_FALSE ((long) 0)
52 #define XDR_TRUE ((long) 1)
53 #define LASTUNSIGNED ((u_int) 0-1)
58 static const char xdr_zero
[BYTES_PER_XDR_UNIT
] = { 0, 0, 0, 0 };
61 * Free a data structure using XDR
62 * Not a filter, but a convenient utility nonetheless
65 xdr_free (xdrproc_t proc
,
91 #if INT_MAX < LONG_MAX
97 return (XDR_PUTLONG (xdrs
, &l
));
100 if (!XDR_GETLONG (xdrs
, &l
))
111 #elif INT_MAX == LONG_MAX
112 return xdr_long (xdrs
, (long *) ip
);
114 # error Unexpected integer sizes in xdr_int()
119 * XDR unsigned integers
122 xdr_u_int (XDR
* xdrs
,
125 #if UINT_MAX < ULONG_MAX
131 return (XDR_PUTLONG (xdrs
, (long *) &l
));
134 if (!XDR_GETLONG (xdrs
, (long *) &l
))
138 *up
= (u_int
) (u_long
) l
;
145 #elif UINT_MAX == ULONG_MAX
146 return xdr_u_long (xdrs
, (u_long
*) up
);
148 # error Unexpected integer sizes in xdr_int()
156 xdr_long (XDR
* xdrs
,
159 if ((xdrs
->x_op
== XDR_ENCODE
)
160 && ((sizeof (int32_t) == sizeof (long)) || ((int32_t) *lp
== *lp
)))
161 return XDR_PUTLONG (xdrs
, lp
);
163 if (xdrs
->x_op
== XDR_DECODE
)
164 return XDR_GETLONG (xdrs
, lp
);
166 if (xdrs
->x_op
== XDR_FREE
)
173 * XDR unsigned long integers
176 xdr_u_long (XDR
* xdrs
,
182 if ((sizeof (uint32_t) != sizeof (u_long
)) && ((uint32_t) *ulp
!= *ulp
))
184 return (XDR_PUTLONG (xdrs
, (long *) ulp
));
189 if (XDR_GETLONG (xdrs
, &tmp
) == FALSE
)
191 *ulp
= (u_long
) (uint32_t) tmp
;
203 * XDR 32-bit integers
206 xdr_int32_t (XDR
* xdrs
,
212 return XDR_PUTINT32 (xdrs
, int32_p
);
215 return XDR_GETINT32(xdrs
, int32_p
);
224 * XDR unsigned 32-bit integers
227 xdr_u_int32_t (XDR
* xdrs
,
228 u_int32_t
* u_int32_p
)
233 return XDR_PUTINT32 (xdrs
, (int32_t *)u_int32_p
);
236 return XDR_GETINT32 (xdrs
, (int32_t *)u_int32_p
);
245 * XDR unsigned 32-bit integers
248 xdr_uint32_t (XDR
* xdrs
,
254 return XDR_PUTINT32 (xdrs
, (int32_t *)uint32_p
);
257 return XDR_GETINT32 (xdrs
, (int32_t *)uint32_p
);
269 xdr_short (XDR
* xdrs
,
278 return (XDR_PUTLONG (xdrs
, &l
));
281 if (!XDR_GETLONG (xdrs
, &l
))
293 * XDR unsigned short integers
296 xdr_u_short (XDR
* xdrs
,
305 return XDR_PUTLONG (xdrs
, &l
);
308 if (!XDR_GETLONG (xdrs
, &l
))
310 *usp
= (u_short
) (u_long
) l
;
321 * XDR 16-bit integers
324 xdr_int16_t (XDR
* xdrs
,
332 t
= (int32_t) *int16_p
;
333 return XDR_PUTINT32 (xdrs
, &t
);
336 if (!XDR_GETINT32 (xdrs
, &t
))
338 *int16_p
= (int16_t) t
;
348 * XDR unsigned 16-bit integers
351 xdr_u_int16_t (XDR
* xdrs
,
352 u_int16_t
* u_int16_p
)
359 ut
= (uint32_t) *u_int16_p
;
360 return XDR_PUTINT32 (xdrs
, (int32_t *)&ut
);
363 if (!XDR_GETINT32 (xdrs
, (int32_t *)&ut
))
365 *u_int16_p
= (u_int16_t
) ut
;
375 * XDR unsigned 16-bit integers
378 xdr_uint16_t (XDR
* xdrs
,
386 ut
= (uint32_t) *uint16_p
;
387 return XDR_PUTINT32 (xdrs
, (int32_t *)&ut
);
390 if (!XDR_GETINT32 (xdrs
, (int32_t *)&ut
))
392 *uint16_p
= (uint16_t) ut
;
405 xdr_int8_t (XDR
* xdrs
,
413 t
= (int32_t) *int8_p
;
414 return XDR_PUTINT32 (xdrs
, &t
);
417 if (!XDR_GETINT32 (xdrs
, &t
))
419 *int8_p
= (int8_t) t
;
429 * XDR unsigned 8-bit integers
432 xdr_u_int8_t (XDR
* xdrs
,
440 ut
= (uint32_t) *u_int8_p
;
441 return XDR_PUTINT32 (xdrs
, (int32_t *)&ut
);
444 if (!XDR_GETINT32 (xdrs
, (int32_t *)&ut
))
446 *u_int8_p
= (u_int8_t
) ut
;
456 * XDR unsigned 8-bit integers
459 xdr_uint8_t (XDR
* xdrs
,
467 ut
= (uint32_t) *uint8_p
;
468 return XDR_PUTINT32 (xdrs
, (int32_t *)&ut
);
471 if (!XDR_GETINT32 (xdrs
, (int32_t *)&ut
))
473 *uint8_p
= (uint8_t) ut
;
488 xdr_char (XDR
* xdrs
,
494 if (!xdr_int (xdrs
, &i
))
501 * XDR an unsigned char
504 xdr_u_char (XDR
* xdrs
,
510 if (!xdr_u_int (xdrs
, &u
))
520 xdr_bool (XDR
* xdrs
,
528 lb
= *bp
? XDR_TRUE
: XDR_FALSE
;
529 return XDR_PUTLONG (xdrs
, &lb
);
532 if (!XDR_GETLONG (xdrs
, &lb
))
534 *bp
= (lb
== XDR_FALSE
) ? FALSE
: TRUE
;
547 xdr_enum (XDR
* xdrs
,
551 { SIZEVAL
}; /* used to find the size of an enum */
554 * enums are treated as ints
556 /* LINTED */ if (sizeof (enum sizecheck
) == 4)
558 #if INT_MAX < LONG_MAX
564 return XDR_PUTLONG (xdrs
, &l
);
567 if (!XDR_GETLONG (xdrs
, &l
))
574 return xdr_long (xdrs
, (long *) (void *) ep
);
577 else /* LINTED */ if (sizeof (enum sizecheck
) == sizeof (short))
579 return (xdr_short (xdrs
, (short *) (void *) ep
));
586 * Allows the specification of a fixed size sequence of opaque bytes.
587 * cp points to the opaque object and cnt gives the byte length.
590 xdr_opaque (XDR
* xdrs
,
595 static char crud
[BYTES_PER_XDR_UNIT
];
598 * if no data we are done
604 * round byte count to full xdr units
606 rndup
= cnt
% BYTES_PER_XDR_UNIT
;
608 rndup
= BYTES_PER_XDR_UNIT
- rndup
;
613 if (!XDR_GETBYTES (xdrs
, cp
, cnt
))
617 return XDR_GETBYTES (xdrs
, (caddr_t
) crud
, rndup
);
620 if (!XDR_PUTBYTES (xdrs
, cp
, cnt
))
624 return (XDR_PUTBYTES (xdrs
, xdr_zero
, rndup
));
634 * *cpp is a pointer to the bytes, *sizep is the count.
635 * If *cpp is NULL maxsize bytes are allocated
638 xdr_bytes (XDR
* xdrs
,
643 char *sp
= *cpp
; /* sp is the actual string pointer */
647 * first deal with the length since xdr bytes are counted
649 if (!xdr_u_int (xdrs
, sizep
))
653 if ((nodesize
> maxsize
) && (xdrs
->x_op
!= XDR_FREE
))
657 * now deal with the actual bytes
665 *cpp
= sp
= mem_alloc (nodesize
);
668 xdr_warnx ("xdr_bytes: out of memory");
675 return xdr_opaque (xdrs
, sp
, nodesize
);
680 mem_free (sp
, nodesize
);
689 * Implemented here due to commonality of the object.
692 xdr_netobj (XDR
* xdrs
,
695 return (xdr_bytes (xdrs
, &np
->n_bytes
, &np
->n_len
, MAX_NETOBJ_SZ
));
699 * XDR a descriminated union
700 * Support routine for discriminated unions.
701 * You create an array of xdrdiscrim structures, terminated with
702 * an entry with a null procedure pointer. The routine gets
703 * the discriminant value and then searches the array of xdrdiscrims
704 * looking for that value. It calls the procedure given in the xdrdiscrim
705 * to handle the discriminant. If there is no specific routine a default
706 * routine may be called.
707 * If there is no specific or default routine an error is returned.
708 * dscmp: enum to decide which arm to work on
709 * unp: ptr to the union itself
710 * choices: ptr to array of [value, xdr proc] for each arm
711 * dfault: default xdr routine
714 xdr_union (XDR
* xdrs
,
717 const struct xdr_discrim
* choices
,
723 * we deal with the discriminator; it's an enum
725 if (!xdr_enum (xdrs
, dscmp
))
731 * search choices for a value that matches the discriminator.
732 * if we find one, execute the xdr routine for that value.
734 for (; choices
->proc
!= NULL_xdrproc_t
; choices
++)
736 if (choices
->value
== dscm
)
737 return ((*(choices
->proc
)) (xdrs
, unp
, LASTUNSIGNED
));
741 * no match - execute the default xdr routine if there is one
743 return ((dfault
== NULL_xdrproc_t
) ? FALSE
: (*dfault
) (xdrs
, unp
, LASTUNSIGNED
));
748 * Non-portable xdr primitives.
749 * Care should be taken when moving these routines to new architectures.
754 * XDR null terminated ASCII strings
755 * xdr_string deals with "C strings" - arrays of bytes that are
756 * terminated by a NULL character. The parameter cpp references a
757 * pointer to storage; If the pointer is null, then the necessary
758 * storage is allocated. The last parameter is the max allowed length
759 * of the string as specified by a protocol.
762 xdr_string (XDR
* xdrs
,
766 char *sp
= *cpp
; /* sp is the actual string pointer */
771 * first deal with the length since xdr strings are counted-strings
777 return TRUE
; /* already free */
789 if (!xdr_u_int (xdrs
, &size
))
798 /* This means an overflow. It a bug in the caller which
799 * provided a too large maxsize but nevertheless catch it
806 * now deal with the actual bytes
813 *cpp
= sp
= mem_alloc (nodesize
);
816 xdr_warnx ("xdr_string: out of memory");
824 return xdr_opaque (xdrs
, sp
, size
);
827 mem_free (sp
, nodesize
);
835 * Wrapper for xdr_string that can be called directly from
836 * routines like clnt_call
839 xdr_wrapstring (XDR
* xdrs
,
842 return xdr_string (xdrs
, cpp
, LASTUNSIGNED
);
846 #if defined(___int64_t_defined)
848 * NOTE: xdr_hyper(), xdr_u_hyper(), xdr_longlong_t(), and xdr_u_longlong_t()
849 * are in the "non-portable" section because they require that a `long long'
852 * --thorpej@netbsd.org, November 30, 1999
856 * XDR 64-bit integers
859 xdr_int64_t (XDR
* xdrs
,
867 t1
= (int32_t) ((*llp
) >> 32);
868 t2
= (int32_t) (*llp
);
869 return (XDR_PUTINT32 (xdrs
, &t1
) && XDR_PUTINT32 (xdrs
, &t2
));
872 if (!XDR_GETINT32 (xdrs
, &t1
) || !XDR_GETINT32 (xdrs
, &t2
))
874 *llp
= ((int64_t) t1
) << 32;
875 *llp
|= (uint32_t) t2
;
886 * XDR unsigned 64-bit integers
889 xdr_u_int64_t (XDR
* xdrs
,
897 t1
= (uint32_t) ((*ullp
) >> 32);
898 t2
= (uint32_t) (*ullp
);
899 return (XDR_PUTINT32 (xdrs
, (int32_t *)&t1
) &&
900 XDR_PUTINT32 (xdrs
, (int32_t *)&t2
));
903 if (!XDR_GETINT32 (xdrs
, (int32_t *)&t1
) ||
904 !XDR_GETINT32 (xdrs
, (int32_t *)&t2
))
906 *ullp
= ((u_int64_t
) t1
) << 32;
917 * XDR unsigned 64-bit integers
920 xdr_uint64_t (XDR
* xdrs
,
928 t1
= (uint32_t) ((*ullp
) >> 32);
929 t2
= (uint32_t) (*ullp
);
930 return (XDR_PUTINT32 (xdrs
, (int32_t *)&t1
) &&
931 XDR_PUTINT32 (xdrs
, (int32_t *)&t2
));
934 if (!XDR_GETINT32 (xdrs
, (int32_t *)&t1
) ||
935 !XDR_GETINT32 (xdrs
, (int32_t *)&t2
))
937 *ullp
= ((uint64_t) t1
) << 32;
952 xdr_hyper (XDR
* xdrs
,
956 * Don't bother open-coding this; it's a fair amount of code. Just
957 * call xdr_int64_t().
959 return (xdr_int64_t (xdrs
, (int64_t *) llp
));
964 * XDR unsigned hypers
967 xdr_u_hyper (XDR
* xdrs
,
971 * Don't bother open-coding this; it's a fair amount of code. Just
972 * call xdr_uint64_t().
974 return (xdr_uint64_t (xdrs
, (uint64_t *) ullp
));
982 xdr_longlong_t (XDR
* xdrs
,
986 * Don't bother open-coding this; it's a fair amount of code. Just
987 * call xdr_int64_t().
989 return (xdr_int64_t (xdrs
, (int64_t *) llp
));
997 xdr_u_longlong_t (XDR
* xdrs
,
1001 * Don't bother open-coding this; it's a fair amount of code. Just
1002 * call xdr_u_int64_t().
1004 return (xdr_uint64_t (xdrs
, (uint64_t *) ullp
));
1007 #endif /* ___int64_t_defined */