4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
30 * Portions of this source code were derived from Berkeley 4.3 BSD
31 * under license from the Regents of the University of California.
35 * xdr.c, generic XDR routines implementation.
36 * These are the "generic" xdr routines used to serialize and de-serialize
37 * most common data items. See xdr.h for more info on the interface to
41 #include <sys/param.h>
42 #include <sys/cmn_err.h>
43 #include <sys/types.h>
44 #include <sys/systm.h>
46 #include <rpc/types.h>
48 #include <sys/isa_defs.h>
50 #pragma weak xdr_int32_t = xdr_int
51 #pragma weak xdr_uint32_t = xdr_u_int
52 #pragma weak xdr_int64_t = xdr_longlong_t
53 #pragma weak xdr_uint64_t = xdr_u_longlong_t
55 #if !defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)
56 #error "Exactly one of _BIG_ENDIAN or _LITTLE_ENDIAN must be defined"
57 #elif defined(_BIG_ENDIAN) && defined(_LITTLE_ENDIAN)
58 #error "Only one of _BIG_ENDIAN or _LITTLE_ENDIAN may be defined"
62 * constants specific to the xdr "protocol"
64 #define XDR_FALSE ((int32_t)0)
65 #define XDR_TRUE ((int32_t)1)
66 #define LASTUNSIGNED ((uint_t)0-1)
71 static char xdr_zero
[BYTES_PER_XDR_UNIT
] = { 0, 0, 0, 0 };
74 * Free a data structure using XDR
75 * Not a filter, but a convenient utility nonetheless
78 xdr_free(xdrproc_t proc
, char *objp
)
98 * PSARC 2003/523 Contract Private Interface
100 * Changes must be reviewed by Solaris File Sharing
101 * Changes must be communicated to contract-2003-523@sun.com
104 xdr_int(XDR
*xdrs
, int *ip
)
106 if (xdrs
->x_op
== XDR_ENCODE
)
107 return (XDR_PUTINT32(xdrs
, ip
));
109 if (xdrs
->x_op
== XDR_DECODE
)
110 return (XDR_GETINT32(xdrs
, ip
));
112 if (xdrs
->x_op
== XDR_FREE
)
119 * XDR unsigned integers
121 * PSARC 2003/523 Contract Private Interface
123 * Changes must be reviewed by Solaris File Sharing
124 * Changes must be communicated to contract-2003-523@sun.com
127 xdr_u_int(XDR
*xdrs
, uint_t
*up
)
129 if (xdrs
->x_op
== XDR_ENCODE
)
130 return (XDR_PUTINT32(xdrs
, (int32_t *)up
));
132 if (xdrs
->x_op
== XDR_DECODE
)
133 return (XDR_GETINT32(xdrs
, (int32_t *)up
));
135 if (xdrs
->x_op
== XDR_FREE
)
144 * xdr_long and xdr_u_long for binary compatability on ILP32 kernels.
146 * No prototypes since new code should not be using these interfaces.
149 xdr_long(XDR
*xdrs
, long *ip
)
151 return (xdr_int(xdrs
, (int *)ip
));
155 xdr_u_long(XDR
*xdrs
, unsigned long *up
)
157 return (xdr_u_int(xdrs
, (uint_t
*)up
));
163 * XDR long long integers
166 xdr_longlong_t(XDR
*xdrs
, longlong_t
*hp
)
168 if (xdrs
->x_op
== XDR_ENCODE
) {
169 #if defined(_LITTLE_ENDIAN)
170 if (XDR_PUTINT32(xdrs
, (int32_t *)((char *)hp
+
171 BYTES_PER_XDR_UNIT
)) == TRUE
) {
172 return (XDR_PUTINT32(xdrs
, (int32_t *)hp
));
174 #elif defined(_BIG_ENDIAN)
175 if (XDR_PUTINT32(xdrs
, (int32_t *)hp
) == TRUE
) {
176 return (XDR_PUTINT32(xdrs
, (int32_t *)((char *)hp
+
177 BYTES_PER_XDR_UNIT
)));
183 if (xdrs
->x_op
== XDR_DECODE
) {
184 #if defined(_LITTLE_ENDIAN)
185 if (XDR_GETINT32(xdrs
, (int32_t *)((char *)hp
+
186 BYTES_PER_XDR_UNIT
)) == TRUE
) {
187 return (XDR_GETINT32(xdrs
, (int32_t *)hp
));
189 #elif defined(_BIG_ENDIAN)
190 if (XDR_GETINT32(xdrs
, (int32_t *)hp
) == TRUE
) {
191 return (XDR_GETINT32(xdrs
, (int32_t *)((char *)hp
+
192 BYTES_PER_XDR_UNIT
)));
201 * XDR unsigned long long integers
204 xdr_u_longlong_t(XDR
*xdrs
, u_longlong_t
*hp
)
207 if (xdrs
->x_op
== XDR_ENCODE
) {
208 #if defined(_LITTLE_ENDIAN)
209 if (XDR_PUTINT32(xdrs
, (int32_t *)((char *)hp
+
210 BYTES_PER_XDR_UNIT
)) == TRUE
) {
211 return (XDR_PUTINT32(xdrs
, (int32_t *)hp
));
213 #elif defined(_BIG_ENDIAN)
214 if (XDR_PUTINT32(xdrs
, (int32_t *)hp
) == TRUE
) {
215 return (XDR_PUTINT32(xdrs
, (int32_t *)((char *)hp
+
216 BYTES_PER_XDR_UNIT
)));
222 if (xdrs
->x_op
== XDR_DECODE
) {
223 #if defined(_LITTLE_ENDIAN)
224 if (XDR_GETINT32(xdrs
, (int32_t *)((char *)hp
+
225 BYTES_PER_XDR_UNIT
)) == TRUE
) {
226 return (XDR_GETINT32(xdrs
, (int32_t *)hp
));
228 #elif defined(_BIG_ENDIAN)
229 if (XDR_GETINT32(xdrs
, (int32_t *)hp
) == TRUE
) {
230 return (XDR_GETINT32(xdrs
, (int32_t *)((char *)hp
+
231 BYTES_PER_XDR_UNIT
)));
243 xdr_short(XDR
*xdrs
, short *sp
)
247 switch (xdrs
->x_op
) {
251 return (XDR_PUTINT32(xdrs
, &l
));
254 if (!XDR_GETINT32(xdrs
, &l
))
266 * XDR unsigned short integers
269 xdr_u_short(XDR
*xdrs
, ushort_t
*usp
)
273 switch (xdrs
->x_op
) {
277 return (XDR_PUTINT32(xdrs
, (int32_t *)&l
));
280 if (!XDR_GETINT32(xdrs
, (int32_t *)&l
)) {
297 xdr_char(XDR
*xdrs
, char *cp
)
302 if (!xdr_int(xdrs
, &i
)) {
310 * XDR an unsigned char
313 xdr_u_char(XDR
*xdrs
, uchar_t
*cp
)
317 switch (xdrs
->x_op
) {
320 return (XDR_PUTINT32(xdrs
, &i
));
322 if (!XDR_GETINT32(xdrs
, &i
))
335 * PSARC 2003/523 Contract Private Interface
337 * Changes must be reviewed by Solaris File Sharing
338 * Changes must be communicated to contract-2003-523@sun.com
341 xdr_bool(XDR
*xdrs
, bool_t
*bp
)
345 switch (xdrs
->x_op
) {
348 i32b
= *bp
? XDR_TRUE
: XDR_FALSE
;
349 return (XDR_PUTINT32(xdrs
, &i32b
));
352 if (!XDR_GETINT32(xdrs
, &i32b
)) {
355 *bp
= (i32b
== XDR_FALSE
) ? FALSE
: TRUE
;
367 * PSARC 2003/523 Contract Private Interface
369 * Changes must be reviewed by Solaris File Sharing
370 * Changes must be communicated to contract-2003-523@sun.com
373 enum sizecheck
{ SIZEVAL
} sizecheckvar
; /* used to find the size of */
377 xdr_enum(XDR
*xdrs
, enum_t
*ep
)
381 * enums are treated as ints
383 if (sizeof (sizecheckvar
) == sizeof (int32_t)) {
384 return (xdr_int(xdrs
, (int32_t *)ep
));
385 } else if (sizeof (sizecheckvar
) == sizeof (short)) {
386 return (xdr_short(xdrs
, (short *)ep
));
391 (void) (xdr_short(xdrs
, (short *)ep
));
392 return (xdr_int(xdrs
, (int32_t *)ep
));
398 * Allows the specification of a fixed size sequence of opaque bytes.
399 * cp points to the opaque object and cnt gives the byte length.
401 * PSARC 2003/523 Contract Private Interface
403 * Changes must be reviewed by Solaris File Sharing
404 * Changes must be communicated to contract-2003-523@sun.com
407 xdr_opaque(XDR
*xdrs
, caddr_t cp
, const uint_t cnt
)
410 static char crud
[BYTES_PER_XDR_UNIT
];
413 * if no data we are done
419 * round byte count to full xdr units
421 rndup
= cnt
% BYTES_PER_XDR_UNIT
;
423 rndup
= BYTES_PER_XDR_UNIT
- rndup
;
425 if (xdrs
->x_op
== XDR_DECODE
) {
426 if (!XDR_GETBYTES(xdrs
, cp
, cnt
)) {
431 return (XDR_GETBYTES(xdrs
, (caddr_t
)crud
, rndup
));
434 if (xdrs
->x_op
== XDR_ENCODE
) {
435 if (!XDR_PUTBYTES(xdrs
, cp
, cnt
)) {
440 return (XDR_PUTBYTES(xdrs
, xdr_zero
, rndup
));
443 if (xdrs
->x_op
== XDR_FREE
)
451 * *cpp is a pointer to the bytes, *sizep is the count.
452 * If *cpp is NULL maxsize bytes are allocated
454 * PSARC 2003/523 Contract Private Interface
456 * Changes must be reviewed by Solaris File Sharing
457 * Changes must be communicated to contract-2003-523@sun.com
460 xdr_bytes(XDR
*xdrs
, char **cpp
, uint_t
*sizep
, const uint_t maxsize
)
462 char *sp
= *cpp
; /* sp is the actual string pointer */
466 * first deal with the length since xdr bytes are counted
468 if (!xdr_u_int(xdrs
, sizep
)) {
472 if ((nodesize
> maxsize
) && (xdrs
->x_op
!= XDR_FREE
)) {
477 * now deal with the actual bytes
479 switch (xdrs
->x_op
) {
484 *cpp
= sp
= (char *)mem_alloc(nodesize
);
488 return (xdr_opaque(xdrs
, sp
, nodesize
));
492 mem_free(sp
, nodesize
);
501 * Implemented here due to commonality of the object.
504 xdr_netobj(XDR
*xdrs
, struct netobj
*np
)
506 return (xdr_bytes(xdrs
, &np
->n_bytes
, &np
->n_len
, MAX_NETOBJ_SZ
));
510 * XDR a descriminated union
511 * Support routine for discriminated unions.
512 * You create an array of xdrdiscrim structures, terminated with
513 * an entry with a null procedure pointer. The routine gets
514 * the discriminant value and then searches the array of xdrdiscrims
515 * looking for that value. It calls the procedure given in the xdrdiscrim
516 * to handle the discriminant. If there is no specific routine a default
517 * routine may be called.
518 * If there is no specific or default routine an error is returned.
521 xdr_union(XDR
*xdrs
, enum_t
*dscmp
, char *unp
,
522 const struct xdr_discrim
*choices
, const xdrproc_t dfault
)
527 * we deal with the discriminator; it's an enum
529 if (!xdr_enum(xdrs
, dscmp
)) {
535 * search choices for a value that matches the discriminator.
536 * if we find one, execute the xdr routine for that value.
538 for (; choices
->proc
!= NULL_xdrproc_t
; choices
++) {
539 if (choices
->value
== dscm
)
540 return ((*(choices
->proc
))(xdrs
, unp
, LASTUNSIGNED
));
544 * no match - execute the default xdr routine if there is one
546 return ((dfault
== NULL_xdrproc_t
) ? FALSE
:
547 (*dfault
)(xdrs
, unp
, LASTUNSIGNED
));
552 * Non-portable xdr primitives.
553 * Care should be taken when moving these routines to new architectures.
558 * XDR null terminated ASCII strings
559 * xdr_string deals with "C strings" - arrays of bytes that are
560 * terminated by a NULL character. The parameter cpp references a
561 * pointer to storage; If the pointer is null, then the necessary
562 * storage is allocated. The last parameter is the max allowed length
563 * of the string as specified by a protocol.
566 xdr_string(XDR
*xdrs
, char **cpp
, const uint_t maxsize
)
568 char *sp
= *cpp
; /* sp is the actual string pointer */
573 * first deal with the length since xdr strings are counted-strings
575 switch (xdrs
->x_op
) {
578 return (TRUE
); /* already free */
581 size
= (sp
!= NULL
) ? (uint_t
)strlen(sp
) : 0;
586 if (!xdr_u_int(xdrs
, &size
)) {
589 if (size
> maxsize
) {
595 * now deal with the actual bytes
597 switch (xdrs
->x_op
) {
602 sp
= (char *)mem_alloc(nodesize
);
604 if (!xdr_opaque(xdrs
, sp
, size
)) {
606 * free up memory if allocated here
609 mem_free(sp
, nodesize
);
613 if (strlen(sp
) != size
) {
615 mem_free(sp
, nodesize
);
623 return (xdr_opaque(xdrs
, sp
, size
));
626 mem_free(sp
, nodesize
);
636 * XDR a fixed length array. Unlike variable-length arrays, the storage
637 * of fixed length arrays is static and unfreeable.
638 * > basep: base of the array
639 * > size: size of the array
640 * > elemsize: size of each element
641 * > xdr_elem: routine to XDR each element
644 xdr_vector(XDR
*xdrs
, char *basep
, const uint_t nelem
,
645 const uint_t elemsize
, const xdrproc_t xdr_elem
)
651 for (i
= 0; i
< nelem
; i
++) {
652 if (!(*xdr_elem
)(xdrs
, elptr
, LASTUNSIGNED
))
660 * Wrapper for xdr_string that can be called directly from
661 * routines like clnt_call
664 xdr_wrapstring(XDR
*xdrs
, char **cpp
)
666 if (xdr_string(xdrs
, cpp
, LASTUNSIGNED
))