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 2008 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>
49 #pragma weak xdr_int32_t = xdr_int
50 #pragma weak xdr_uint32_t = xdr_u_int
51 #pragma weak xdr_int64_t = xdr_longlong_t
52 #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"
63 * constants specific to the xdr "protocol"
65 #define XDR_FALSE ((int32_t)0)
66 #define XDR_TRUE ((int32_t)1)
67 #define LASTUNSIGNED ((uint_t)0-1)
72 static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
75 * Free a data structure using XDR
76 * Not a filter, but a convenient utility nonetheless
79 xdr_free(xdrproc_t proc, char *objp)
99 * PSARC 2003/523 Contract Private Interface
101 * Changes must be reviewed by Solaris File Sharing
102 * Changes must be communicated to contract-2003-523@sun.com
105 xdr_int(XDR *xdrs, int *ip)
107 if (xdrs->x_op == XDR_ENCODE)
108 return (XDR_PUTINT32(xdrs, ip));
110 if (xdrs->x_op == XDR_DECODE)
111 return (XDR_GETINT32(xdrs, ip));
113 if (xdrs->x_op == XDR_FREE)
120 * XDR unsigned integers
122 * PSARC 2003/523 Contract Private Interface
124 * Changes must be reviewed by Solaris File Sharing
125 * Changes must be communicated to contract-2003-523@sun.com
128 xdr_u_int(XDR *xdrs, uint_t *up)
130 if (xdrs->x_op == XDR_ENCODE)
131 return (XDR_PUTINT32(xdrs, (int32_t *)up));
133 if (xdrs->x_op == XDR_DECODE)
134 return (XDR_GETINT32(xdrs, (int32_t *)up));
136 if (xdrs->x_op == XDR_FREE)
145 * xdr_long and xdr_u_long for binary compatability on ILP32 kernels.
147 * No prototypes since new code should not be using these interfaces.
150 xdr_long(XDR *xdrs, long *ip)
152 return (xdr_int(xdrs, (int *)ip));
156 xdr_u_long(XDR *xdrs, unsigned long *up)
158 return (xdr_u_int(xdrs, (uint_t *)up));
164 * XDR long long integers
167 xdr_longlong_t(XDR *xdrs, longlong_t *hp)
169 if (xdrs->x_op == XDR_ENCODE) {
170 #if BYTE_ORDER == _LITTLE_ENDIAN
171 if (XDR_PUTINT32(xdrs, (int32_t *)((char *)hp +
172 BYTES_PER_XDR_UNIT)) == TRUE) {
173 return (XDR_PUTINT32(xdrs, (int32_t *)hp));
176 if (XDR_PUTINT32(xdrs, (int32_t *)hp) == TRUE) {
177 return (XDR_PUTINT32(xdrs, (int32_t *)((char *)hp +
178 BYTES_PER_XDR_UNIT)));
184 if (xdrs->x_op == XDR_DECODE) {
185 #if BYTE_ORDER == _LITTLE_ENDIAN
186 if (XDR_GETINT32(xdrs, (int32_t *)((char *)hp +
187 BYTES_PER_XDR_UNIT)) == TRUE) {
188 return (XDR_GETINT32(xdrs, (int32_t *)hp));
191 if (XDR_GETINT32(xdrs, (int32_t *)hp) == TRUE) {
192 return (XDR_GETINT32(xdrs, (int32_t *)((char *)hp +
193 BYTES_PER_XDR_UNIT)));
202 * XDR unsigned long long integers
205 xdr_u_longlong_t(XDR *xdrs, u_longlong_t *hp)
208 if (xdrs->x_op == XDR_ENCODE) {
209 #if BYTE_ORDER == _LITTLE_ENDIAN
210 if (XDR_PUTINT32(xdrs, (int32_t *)((char *)hp +
211 BYTES_PER_XDR_UNIT)) == TRUE) {
212 return (XDR_PUTINT32(xdrs, (int32_t *)hp));
215 if (XDR_PUTINT32(xdrs, (int32_t *)hp) == TRUE) {
216 return (XDR_PUTINT32(xdrs, (int32_t *)((char *)hp +
217 BYTES_PER_XDR_UNIT)));
223 if (xdrs->x_op == XDR_DECODE) {
224 #if BYTE_ORDER == _LITTLE_ENDIAN
225 if (XDR_GETINT32(xdrs, (int32_t *)((char *)hp +
226 BYTES_PER_XDR_UNIT)) == TRUE) {
227 return (XDR_GETINT32(xdrs, (int32_t *)hp));
230 if (XDR_GETINT32(xdrs, (int32_t *)hp) == TRUE) {
231 return (XDR_GETINT32(xdrs, (int32_t *)((char *)hp +
232 BYTES_PER_XDR_UNIT)));
244 xdr_short(XDR *xdrs, short *sp)
248 switch (xdrs->x_op) {
252 return (XDR_PUTINT32(xdrs, &l));
255 if (!XDR_GETINT32(xdrs, &l))
267 * XDR unsigned short integers
270 xdr_u_short(XDR *xdrs, ushort_t *usp)
274 switch (xdrs->x_op) {
278 return (XDR_PUTINT32(xdrs, (int32_t *)&l));
281 if (!XDR_GETINT32(xdrs, (int32_t *)&l)) {
298 xdr_char(XDR *xdrs, char *cp)
303 if (!xdr_int(xdrs, &i)) {
313 * PSARC 2003/523 Contract Private Interface
315 * Changes must be reviewed by Solaris File Sharing
316 * Changes must be communicated to contract-2003-523@sun.com
319 xdr_bool(XDR *xdrs, bool_t *bp)
323 switch (xdrs->x_op) {
326 i32b = *bp ? XDR_TRUE : XDR_FALSE;
327 return (XDR_PUTINT32(xdrs, &i32b));
330 if (!XDR_GETINT32(xdrs, &i32b)) {
333 *bp = (i32b == XDR_FALSE) ? FALSE : TRUE;
345 * PSARC 2003/523 Contract Private Interface
347 * Changes must be reviewed by Solaris File Sharing
348 * Changes must be communicated to contract-2003-523@sun.com
351 enum sizecheck { SIZEVAL } sizecheckvar; /* used to find the size of */
355 xdr_enum(XDR *xdrs, enum_t *ep)
359 * enums are treated as ints
361 if (sizeof (sizecheckvar) == sizeof (int32_t)) {
362 return (xdr_int(xdrs, (int32_t *)ep));
363 } else if (sizeof (sizecheckvar) == sizeof (short)) {
364 return (xdr_short(xdrs, (short *)ep));
369 (void) (xdr_short(xdrs, (short *)ep));
370 return (xdr_int(xdrs, (int32_t *)ep));
376 * Allows the specification of a fixed size sequence of opaque bytes.
377 * cp points to the opaque object and cnt gives the byte length.
379 * PSARC 2003/523 Contract Private Interface
381 * Changes must be reviewed by Solaris File Sharing
382 * Changes must be communicated to contract-2003-523@sun.com
385 xdr_opaque(XDR *xdrs, caddr_t cp, const uint_t cnt)
388 static char crud[BYTES_PER_XDR_UNIT];
391 * if no data we are done
397 * round byte count to full xdr units
399 rndup = cnt % BYTES_PER_XDR_UNIT;
401 rndup = BYTES_PER_XDR_UNIT - rndup;
403 if (xdrs->x_op == XDR_DECODE) {
404 if (!XDR_GETBYTES(xdrs, cp, cnt)) {
409 return (XDR_GETBYTES(xdrs, (caddr_t)crud, rndup));
412 if (xdrs->x_op == XDR_ENCODE) {
413 if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
418 return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
421 if (xdrs->x_op == XDR_FREE)
429 * *cpp is a pointer to the bytes, *sizep is the count.
430 * If *cpp is NULL maxsize bytes are allocated
432 * PSARC 2003/523 Contract Private Interface
434 * Changes must be reviewed by Solaris File Sharing
435 * Changes must be communicated to contract-2003-523@sun.com
438 xdr_bytes(XDR *xdrs, char **cpp, uint_t *sizep, const uint_t maxsize)
440 char *sp = *cpp; /* sp is the actual string pointer */
444 * first deal with the length since xdr bytes are counted
446 if (!xdr_u_int(xdrs, sizep)) {
450 if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
455 * now deal with the actual bytes
457 switch (xdrs->x_op) {
462 *cpp = sp = (char *)mem_alloc(nodesize);
466 return (xdr_opaque(xdrs, sp, nodesize));
470 mem_free(sp, nodesize);
479 * Implemented here due to commonality of the object.
482 xdr_netobj(XDR *xdrs, struct netobj *np)
484 return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
488 * XDR a descriminated union
489 * Support routine for discriminated unions.
490 * You create an array of xdrdiscrim structures, terminated with
491 * an entry with a null procedure pointer. The routine gets
492 * the discriminant value and then searches the array of xdrdiscrims
493 * looking for that value. It calls the procedure given in the xdrdiscrim
494 * to handle the discriminant. If there is no specific routine a default
495 * routine may be called.
496 * If there is no specific or default routine an error is returned.
499 xdr_union(XDR *xdrs, enum_t *dscmp, char *unp,
500 const struct xdr_discrim *choices, const xdrproc_t dfault)
505 * we deal with the discriminator; it's an enum
507 if (!xdr_enum(xdrs, dscmp)) {
513 * search choices for a value that matches the discriminator.
514 * if we find one, execute the xdr routine for that value.
516 for (; choices->proc != NULL_xdrproc_t; choices++) {
517 if (choices->value == dscm)
518 return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED));
522 * no match - execute the default xdr routine if there is one
524 return ((dfault == NULL_xdrproc_t) ? FALSE :
525 (*dfault)(xdrs, unp, LASTUNSIGNED));
530 * Non-portable xdr primitives.
531 * Care should be taken when moving these routines to new architectures.
536 * XDR null terminated ASCII strings
537 * xdr_string deals with "C strings" - arrays of bytes that are
538 * terminated by a NULL character. The parameter cpp references a
539 * pointer to storage; If the pointer is null, then the necessary
540 * storage is allocated. The last parameter is the max allowed length
541 * of the string as specified by a protocol.
544 xdr_string(XDR *xdrs, char **cpp, const uint_t maxsize)
546 char *sp = *cpp; /* sp is the actual string pointer */
551 * first deal with the length since xdr strings are counted-strings
553 switch (xdrs->x_op) {
556 return (TRUE); /* already free */
559 size = (sp != NULL) ? (uint_t)strlen(sp) : 0;
564 if (!xdr_u_int(xdrs, &size)) {
567 if (size > maxsize) {
573 * now deal with the actual bytes
575 switch (xdrs->x_op) {
580 sp = (char *)mem_alloc(nodesize);
582 if (!xdr_opaque(xdrs, sp, size)) {
584 * free up memory if allocated here
587 mem_free(sp, nodesize);
591 if (strlen(sp) != size) {
593 mem_free(sp, nodesize);
601 return (xdr_opaque(xdrs, sp, size));
604 mem_free(sp, nodesize);
612 * Wrapper for xdr_string that can be called directly from
613 * routines like clnt_call
616 xdr_wrapstring(XDR *xdrs, char **cpp)
618 if (xdr_string(xdrs, cpp, LASTUNSIGNED))