1 /* $NetBSD: xdr.c,v 1.33 2013/03/11 20:19:29 tron Exp $ */
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.
34 #include <sys/cdefs.h>
35 #if defined(LIBC_SCCS) && !defined(lint)
37 static char *sccsid
= "@(#)xdr.c 1.35 87/08/12";
38 static char *sccsid
= "@(#)xdr.c 2.1 88/07/29 4.0 RPCSRC";
40 __RCSID("$NetBSD: xdr.c,v 1.33 2013/03/11 20:19:29 tron Exp $");
45 * xdr.c, Generic XDR routines implementation.
47 * Copyright (C) 1986, Sun Microsystems, Inc.
49 * These are the "generic" xdr routines used to serialize and de-serialize
50 * most common data items. See xdr.h for more info on the interface to
54 #include "namespace.h"
62 #include <rpc/types.h>
66 __weak_alias(xdr_bool
,_xdr_bool
)
67 __weak_alias(xdr_bytes
,_xdr_bytes
)
68 __weak_alias(xdr_char
,_xdr_char
)
69 __weak_alias(xdr_enum
,_xdr_enum
)
70 __weak_alias(xdr_free
,_xdr_free
)
71 __weak_alias(xdr_hyper
,_xdr_hyper
)
72 __weak_alias(xdr_int
,_xdr_int
)
73 __weak_alias(xdr_int16_t
,_xdr_int16_t
)
74 __weak_alias(xdr_int32_t
,_xdr_int32_t
)
75 __weak_alias(xdr_int64_t
,_xdr_int64_t
)
76 __weak_alias(xdr_long
,_xdr_long
)
77 __weak_alias(xdr_longlong_t
,_xdr_longlong_t
)
78 __weak_alias(xdr_netobj
,_xdr_netobj
)
79 __weak_alias(xdr_opaque
,_xdr_opaque
)
80 __weak_alias(xdr_short
,_xdr_short
)
81 __weak_alias(xdr_string
,_xdr_string
)
82 __weak_alias(xdr_u_char
,_xdr_u_char
)
83 __weak_alias(xdr_u_hyper
,_xdr_u_hyper
)
84 __weak_alias(xdr_u_int
,_xdr_u_int
)
85 __weak_alias(xdr_u_int16_t
,_xdr_u_int16_t
)
86 __weak_alias(xdr_u_int32_t
,_xdr_u_int32_t
)
87 __weak_alias(xdr_u_int64_t
,_xdr_u_int64_t
)
88 __weak_alias(xdr_u_long
,_xdr_u_long
)
89 __weak_alias(xdr_u_longlong_t
,_xdr_u_longlong_t
)
90 __weak_alias(xdr_u_short
,_xdr_u_short
)
91 __weak_alias(xdr_union
,_xdr_union
)
92 __weak_alias(xdr_void
,_xdr_void
)
93 __weak_alias(xdr_wrapstring
,_xdr_wrapstring
)
97 * constants specific to the xdr "protocol"
99 #define XDR_FALSE ((long) 0)
100 #define XDR_TRUE ((long) 1)
101 #define LASTUNSIGNED ((u_int) 0-1)
106 static const char xdr_zero
[BYTES_PER_XDR_UNIT
] = { 0, 0, 0, 0 };
109 * Free a data structure using XDR
110 * Not a filter, but a convenient utility nonetheless
113 xdr_free(xdrproc_t proc
, char *objp
)
135 xdr_int(XDR
*xdrs
, int *ip
)
139 _DIAGASSERT(xdrs
!= NULL
);
140 _DIAGASSERT(ip
!= NULL
);
142 switch (xdrs
->x_op
) {
146 return (XDR_PUTLONG(xdrs
, &l
));
149 if (!XDR_GETLONG(xdrs
, &l
)) {
163 * XDR unsigned integers
166 xdr_u_int(XDR
*xdrs
, u_int
*up
)
170 _DIAGASSERT(xdrs
!= NULL
);
171 _DIAGASSERT(up
!= NULL
);
173 switch (xdrs
->x_op
) {
177 return (XDR_PUTLONG(xdrs
, (long *)&l
));
180 if (!XDR_GETLONG(xdrs
, (long *)&l
)) {
196 * same as xdr_u_long - open coded to save a proc call!
199 xdr_long(XDR
*xdrs
, long *lp
)
202 _DIAGASSERT(xdrs
!= NULL
);
203 _DIAGASSERT(lp
!= NULL
);
205 switch (xdrs
->x_op
) {
207 return (XDR_PUTLONG(xdrs
, lp
));
209 return (XDR_GETLONG(xdrs
, lp
));
218 * XDR unsigned long integers
219 * same as xdr_long - open coded to save a proc call!
222 xdr_u_long(XDR
*xdrs
, u_long
*ulp
)
225 _DIAGASSERT(xdrs
!= NULL
);
226 _DIAGASSERT(ulp
!= NULL
);
228 switch (xdrs
->x_op
) {
230 return (XDR_PUTLONG(xdrs
, (long *)ulp
));
232 return (XDR_GETLONG(xdrs
, (long *)ulp
));
242 * XDR 32-bit integers
243 * same as xdr_u_int32_t - open coded to save a proc call!
246 xdr_int32_t(XDR
*xdrs
, int32_t *int32_p
)
250 _DIAGASSERT(xdrs
!= NULL
);
251 _DIAGASSERT(int32_p
!= NULL
);
253 switch (xdrs
->x_op
) {
257 return (XDR_PUTLONG(xdrs
, &l
));
260 if (!XDR_GETLONG(xdrs
, &l
)) {
263 *int32_p
= (int32_t) l
;
274 * XDR unsigned 32-bit integers
275 * same as xdr_int32_t - open coded to save a proc call!
278 xdr_u_int32_t(XDR
*xdrs
, u_int32_t
*u_int32_p
)
282 _DIAGASSERT(xdrs
!= NULL
);
283 _DIAGASSERT(u_int32_p
!= NULL
);
285 switch (xdrs
->x_op
) {
288 l
= (u_long
) *u_int32_p
;
289 return (XDR_PUTLONG(xdrs
, (long *)&l
));
292 if (!XDR_GETLONG(xdrs
, (long *)&l
)) {
295 *u_int32_p
= (u_int32_t
) l
;
310 xdr_short(XDR
*xdrs
, short *sp
)
314 _DIAGASSERT(xdrs
!= NULL
);
315 _DIAGASSERT(sp
!= NULL
);
317 switch (xdrs
->x_op
) {
321 return (XDR_PUTLONG(xdrs
, &l
));
324 if (!XDR_GETLONG(xdrs
, &l
)) {
338 * XDR unsigned short integers
341 xdr_u_short(XDR
*xdrs
, u_short
*usp
)
345 _DIAGASSERT(xdrs
!= NULL
);
346 _DIAGASSERT(usp
!= NULL
);
348 switch (xdrs
->x_op
) {
352 return (XDR_PUTLONG(xdrs
, (long *)&l
));
355 if (!XDR_GETLONG(xdrs
, (long *)&l
)) {
370 * XDR 16-bit integers
373 xdr_int16_t(XDR
*xdrs
, int16_t *int16_p
)
377 _DIAGASSERT(xdrs
!= NULL
);
378 _DIAGASSERT(int16_p
!= NULL
);
380 switch (xdrs
->x_op
) {
384 return (XDR_PUTLONG(xdrs
, &l
));
387 if (!XDR_GETLONG(xdrs
, &l
)) {
390 *int16_p
= (int16_t) l
;
401 * XDR unsigned 16-bit integers
404 xdr_u_int16_t(XDR
*xdrs
, u_int16_t
*u_int16_p
)
408 _DIAGASSERT(xdrs
!= NULL
);
409 _DIAGASSERT(u_int16_p
!= NULL
);
411 switch (xdrs
->x_op
) {
414 l
= (u_long
) *u_int16_p
;
415 return (XDR_PUTLONG(xdrs
, (long *)&l
));
418 if (!XDR_GETLONG(xdrs
, (long *)&l
)) {
421 *u_int16_p
= (u_int16_t
) l
;
436 xdr_char(XDR
*xdrs
, char *cp
)
440 _DIAGASSERT(xdrs
!= NULL
);
441 _DIAGASSERT(cp
!= NULL
);
444 if (!xdr_int(xdrs
, &i
)) {
452 * XDR an unsigned char
455 xdr_u_char(XDR
*xdrs
, u_char
*cp
)
459 _DIAGASSERT(xdrs
!= NULL
);
460 _DIAGASSERT(cp
!= NULL
);
463 if (!xdr_u_int(xdrs
, &u
)) {
474 xdr_bool(XDR
*xdrs
, bool_t
*bp
)
478 _DIAGASSERT(xdrs
!= NULL
);
479 _DIAGASSERT(bp
!= NULL
);
481 switch (xdrs
->x_op
) {
484 lb
= *bp
? XDR_TRUE
: XDR_FALSE
;
485 return (XDR_PUTLONG(xdrs
, &lb
));
488 if (!XDR_GETLONG(xdrs
, &lb
)) {
491 *bp
= (lb
== XDR_FALSE
) ? FALSE
: TRUE
;
505 xdr_enum(XDR
*xdrs
, enum_t
*ep
)
509 _DIAGASSERT(xdrs
!= NULL
);
510 _DIAGASSERT(ep
!= NULL
);
512 switch (xdrs
->x_op
) {
516 return (XDR_PUTLONG(xdrs
, &l
));
519 if (!XDR_GETLONG(xdrs
, &l
)) {
534 * Allows the specification of a fixed size sequence of opaque bytes.
535 * cp points to the opaque object and cnt gives the byte length.
538 xdr_opaque(XDR
*xdrs
, caddr_t cp
, u_int cnt
)
541 static int crud
[BYTES_PER_XDR_UNIT
];
543 _DIAGASSERT(xdrs
!= NULL
);
545 * if no data we are done
549 _DIAGASSERT(cp
!= NULL
);
552 * round byte count to full xdr units
554 rndup
= cnt
% BYTES_PER_XDR_UNIT
;
556 rndup
= BYTES_PER_XDR_UNIT
- rndup
;
558 if (xdrs
->x_op
== XDR_DECODE
) {
559 if (!XDR_GETBYTES(xdrs
, cp
, cnt
)) {
564 return (XDR_GETBYTES(xdrs
, (caddr_t
)(void *)crud
, rndup
));
567 if (xdrs
->x_op
== XDR_ENCODE
) {
568 if (!XDR_PUTBYTES(xdrs
, cp
, cnt
)) {
573 return (XDR_PUTBYTES(xdrs
, xdr_zero
, rndup
));
576 if (xdrs
->x_op
== XDR_FREE
) {
585 * *cpp is a pointer to the bytes, *sizep is the count.
586 * If *cpp is NULL maxsize bytes are allocated
589 xdr_bytes(XDR
*xdrs
, char **cpp
, u_int
*sizep
, u_int maxsize
)
591 char *sp
; /* sp is the actual string pointer */
594 _DIAGASSERT(xdrs
!= NULL
);
595 _DIAGASSERT(cpp
!= NULL
);
596 _DIAGASSERT(sizep
!= NULL
);
601 * first deal with the length since xdr bytes are counted
603 if (! xdr_u_int(xdrs
, sizep
)) {
607 if ((nodesize
> maxsize
) && (xdrs
->x_op
!= XDR_FREE
)) {
612 * now deal with the actual bytes
614 switch (xdrs
->x_op
) {
621 *cpp
= sp
= mem_alloc(nodesize
);
624 warn("%s: out of memory", __func__
);
630 return (xdr_opaque(xdrs
, sp
, nodesize
));
634 mem_free(sp
, nodesize
);
644 * Implemented here due to commonality of the object.
647 xdr_netobj(XDR
*xdrs
, struct netobj
*np
)
650 _DIAGASSERT(xdrs
!= NULL
);
651 _DIAGASSERT(np
!= NULL
);
653 return (xdr_bytes(xdrs
, &np
->n_bytes
, &np
->n_len
, MAX_NETOBJ_SZ
));
657 * XDR a descriminated union
658 * Support routine for discriminated unions.
659 * You create an array of xdrdiscrim structures, terminated with
660 * an entry with a null procedure pointer. The routine gets
661 * the discriminant value and then searches the array of xdrdiscrims
662 * looking for that value. It calls the procedure given in the xdrdiscrim
663 * to handle the discriminant. If there is no specific routine a default
664 * routine may be called.
665 * If there is no specific or default routine an error is returned.
670 enum_t
*dscmp
, /* enum to decide which arm to work on */
671 char *unp
, /* the union itself */
672 const struct xdr_discrim
*choices
, /* [value, xdr proc] for each arm */
673 xdrproc_t dfault
/* default xdr routine */
678 _DIAGASSERT(xdrs
!= NULL
);
679 _DIAGASSERT(dscmp
!= NULL
);
680 _DIAGASSERT(unp
!= NULL
);
681 _DIAGASSERT(choices
!= NULL
);
682 /* dfault may be NULL */
685 * we deal with the discriminator; it's an enum
687 if (! xdr_enum(xdrs
, dscmp
)) {
693 * search choices for a value that matches the discriminator.
694 * if we find one, execute the xdr routine for that value.
696 for (; choices
->proc
!= NULL_xdrproc_t
; choices
++) {
697 if (choices
->value
== dscm
)
698 return ((*(choices
->proc
))(xdrs
, unp
));
702 * no match - execute the default xdr routine if there is one
704 return ((dfault
== NULL_xdrproc_t
) ? FALSE
:
705 (*dfault
)(xdrs
, unp
));
710 * Non-portable xdr primitives.
711 * Care should be taken when moving these routines to new architectures.
716 * XDR null terminated ASCII strings
717 * xdr_string deals with "C strings" - arrays of bytes that are
718 * terminated by a NULL character. The parameter cpp references a
719 * pointer to storage; If the pointer is null, then the necessary
720 * storage is allocated. The last parameter is the max allowed length
721 * of the string as specified by a protocol.
724 xdr_string(XDR
*xdrs
, char **cpp
, u_int maxsize
)
726 char *sp
; /* sp is the actual string pointer */
727 u_int size
= 0; /* XXX: GCC */
731 _DIAGASSERT(xdrs
!= NULL
);
732 _DIAGASSERT(cpp
!= NULL
);
737 * first deal with the length since xdr strings are counted-strings
739 switch (xdrs
->x_op
) {
742 return(TRUE
); /* already free */
747 _DIAGASSERT(__type_fit(u_int
, len
));
753 if (! xdr_u_int(xdrs
, &size
)) {
756 if (size
> maxsize
) {
762 * now deal with the actual bytes
764 switch (xdrs
->x_op
) {
771 *cpp
= sp
= mem_alloc(nodesize
);
773 warn("%s: out of memory", __func__
);
780 return (xdr_opaque(xdrs
, sp
, size
));
783 mem_free(sp
, nodesize
);
792 * Wrapper for xdr_string that can be called directly from
793 * routines like clnt_call
796 xdr_wrapstring(XDR
*xdrs
, char **cpp
)
799 _DIAGASSERT(xdrs
!= NULL
);
800 _DIAGASSERT(cpp
!= NULL
);
802 return xdr_string(xdrs
, cpp
, LASTUNSIGNED
);
806 * NOTE: xdr_hyper(), xdr_u_hyper(), xdr_longlong_t(), and xdr_u_longlong_t()
807 * are in the "non-portable" section because they require that a `long long'
810 * --thorpej@NetBSD.org, November 30, 1999
814 * XDR 64-bit integers
817 xdr_int64_t(XDR
*xdrs
, int64_t *llp
)
821 _DIAGASSERT(xdrs
!= NULL
);
822 _DIAGASSERT(llp
!= NULL
);
824 switch (xdrs
->x_op
) {
826 ul
[0] = (u_long
)(((uint64_t)*llp
>> 32) &
827 (uint64_t)0xffffffffULL
);
828 ul
[1] = (u_long
)(((uint64_t)*llp
) &
829 (uint64_t)0xffffffffULL
);
830 if (XDR_PUTLONG(xdrs
, (long *)&ul
[0]) == FALSE
)
832 return (XDR_PUTLONG(xdrs
, (long *)&ul
[1]));
834 if (XDR_GETLONG(xdrs
, (long *)&ul
[0]) == FALSE
)
836 if (XDR_GETLONG(xdrs
, (long *)&ul
[1]) == FALSE
)
839 (((u_int64_t
)ul
[0] << 32) | ((u_int64_t
)ul
[1]));
850 * XDR unsigned 64-bit integers
853 xdr_u_int64_t(XDR
*xdrs
, u_int64_t
*ullp
)
857 _DIAGASSERT(xdrs
!= NULL
);
858 _DIAGASSERT(ullp
!= NULL
);
860 switch (xdrs
->x_op
) {
862 ul
[0] = (u_long
)(*ullp
>> 32) & 0xffffffffUL
;
863 ul
[1] = (u_long
)(*ullp
) & 0xffffffffUL
;
864 if (XDR_PUTLONG(xdrs
, (long *)&ul
[0]) == FALSE
)
866 return (XDR_PUTLONG(xdrs
, (long *)&ul
[1]));
868 if (XDR_GETLONG(xdrs
, (long *)&ul
[0]) == FALSE
)
870 if (XDR_GETLONG(xdrs
, (long *)&ul
[1]) == FALSE
)
873 (((u_int64_t
)ul
[0] << 32) | ((u_int64_t
)ul
[1]));
887 xdr_hyper(XDR
*xdrs
, longlong_t
*llp
)
890 _DIAGASSERT(xdrs
!= NULL
);
891 _DIAGASSERT(llp
!= NULL
);
894 * Don't bother open-coding this; it's a fair amount of code. Just
895 * call xdr_int64_t().
897 return (xdr_int64_t(xdrs
, (int64_t *)llp
));
902 * XDR unsigned hypers
905 xdr_u_hyper(XDR
*xdrs
, u_longlong_t
*ullp
)
908 _DIAGASSERT(xdrs
!= NULL
);
909 _DIAGASSERT(ullp
!= NULL
);
912 * Don't bother open-coding this; it's a fair amount of code. Just
913 * call xdr_u_int64_t().
915 return (xdr_u_int64_t(xdrs
, (u_int64_t
*)ullp
));
923 xdr_longlong_t(XDR
*xdrs
, longlong_t
*llp
)
926 _DIAGASSERT(xdrs
!= NULL
);
927 _DIAGASSERT(llp
!= NULL
);
930 * Don't bother open-coding this; it's a fair amount of code. Just
931 * call xdr_int64_t().
933 return (xdr_int64_t(xdrs
, (int64_t *)llp
));
941 xdr_u_longlong_t(XDR
*xdrs
, u_longlong_t
*ullp
)
944 _DIAGASSERT(xdrs
!= NULL
);
945 _DIAGASSERT(ullp
!= NULL
);
948 * Don't bother open-coding this; it's a fair amount of code. Just
949 * call xdr_u_int64_t().
951 return (xdr_u_int64_t(xdrs
, (u_int64_t
*)ullp
));