xref: /illumos-gate/usr/src/lib/libnsl/rpc/xdr.c (revision e8031f0a)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
2161961e0fSrobinson  */
2261961e0fSrobinson 
2361961e0fSrobinson /*
24*e8031f0aSraf  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
257c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
267c478bd9Sstevel@tonic-gate  */
27*e8031f0aSraf 
287c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
297c478bd9Sstevel@tonic-gate /* All Rights Reserved */
307c478bd9Sstevel@tonic-gate /*
317c478bd9Sstevel@tonic-gate  * Portions of this source code were derived from Berkeley
327c478bd9Sstevel@tonic-gate  * 4.3 BSD under license from the Regents of the University of
337c478bd9Sstevel@tonic-gate  * California.
347c478bd9Sstevel@tonic-gate  */
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate /*
39*e8031f0aSraf  * Generic XDR routines implementation.
407c478bd9Sstevel@tonic-gate  *
417c478bd9Sstevel@tonic-gate  * These are the "generic" xdr routines used to serialize and de-serialize
427c478bd9Sstevel@tonic-gate  * most common data items.  See xdr.h for more info on the interface to
437c478bd9Sstevel@tonic-gate  * xdr.
447c478bd9Sstevel@tonic-gate  */
45*e8031f0aSraf #include "mt.h"
4661961e0fSrobinson #include <stdlib.h>
477c478bd9Sstevel@tonic-gate #include <sys/types.h>
487c478bd9Sstevel@tonic-gate #include <sys/isa_defs.h>
497c478bd9Sstevel@tonic-gate #include <syslog.h>
507c478bd9Sstevel@tonic-gate #include <stdio.h>
517c478bd9Sstevel@tonic-gate #include <stdlib.h>
527c478bd9Sstevel@tonic-gate #include <string.h>
537c478bd9Sstevel@tonic-gate #include <limits.h>
547c478bd9Sstevel@tonic-gate #include <rpc/types.h>
557c478bd9Sstevel@tonic-gate #include <rpc/xdr.h>
567c478bd9Sstevel@tonic-gate #include <inttypes.h>
577c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
5861961e0fSrobinson #include <assert.h>
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate #pragma weak xdr_int64_t = xdr_hyper
617c478bd9Sstevel@tonic-gate #pragma weak xdr_uint64_t = xdr_u_hyper
627c478bd9Sstevel@tonic-gate #pragma weak xdr_int32_t = xdr_int
637c478bd9Sstevel@tonic-gate #pragma weak xdr_uint32_t = xdr_u_int
647c478bd9Sstevel@tonic-gate #pragma weak xdr_int16_t = xdr_short
657c478bd9Sstevel@tonic-gate #pragma weak xdr_uint16_t = xdr_u_short
667c478bd9Sstevel@tonic-gate #pragma weak xdr_int8_t = xdr_char
677c478bd9Sstevel@tonic-gate #pragma weak xdr_uint8_t = xdr_u_char
687c478bd9Sstevel@tonic-gate 
6961961e0fSrobinson /*
7061961e0fSrobinson  * The following routine was part of a workaround for an rpcgen
7161961e0fSrobinson  * that was fixed, this routine should be removed sometime.
7261961e0fSrobinson  */
7361961e0fSrobinson #pragma weak xdr_ulonglong_t = xdr_u_longlong_t
7461961e0fSrobinson 
757c478bd9Sstevel@tonic-gate /*
767c478bd9Sstevel@tonic-gate  * constants specific to the xdr "protocol"
777c478bd9Sstevel@tonic-gate  */
787c478bd9Sstevel@tonic-gate #define	XDR_FALSE	((uint_t)0)
797c478bd9Sstevel@tonic-gate #define	XDR_TRUE	((uint_t)1)
807c478bd9Sstevel@tonic-gate #define	LASTUNSIGNED	((uint_t)0-1)
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate /* fragment size to use when doing an xdr_string() */
837c478bd9Sstevel@tonic-gate #define	FRAGMENT	65536
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate /*
867c478bd9Sstevel@tonic-gate  * for unit alignment
877c478bd9Sstevel@tonic-gate  */
887c478bd9Sstevel@tonic-gate static const char xdr_zero[BYTES_PER_XDR_UNIT]	= { 0 };
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate /*
917c478bd9Sstevel@tonic-gate  * Free a data structure using XDR
927c478bd9Sstevel@tonic-gate  * Not a filter, but a convenient utility nonetheless
937c478bd9Sstevel@tonic-gate  */
947c478bd9Sstevel@tonic-gate void
957c478bd9Sstevel@tonic-gate xdr_free(xdrproc_t proc, char *objp)
967c478bd9Sstevel@tonic-gate {
977c478bd9Sstevel@tonic-gate 	XDR x;
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate 	x.x_op = XDR_FREE;
1007c478bd9Sstevel@tonic-gate 	(*proc)(&x, objp);
1017c478bd9Sstevel@tonic-gate }
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate /*
1047c478bd9Sstevel@tonic-gate  * XDR nothing
1057c478bd9Sstevel@tonic-gate  */
1067c478bd9Sstevel@tonic-gate bool_t
10761961e0fSrobinson xdr_void(void)
1087c478bd9Sstevel@tonic-gate {
1097c478bd9Sstevel@tonic-gate 	return (TRUE);
1107c478bd9Sstevel@tonic-gate }
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate /*
1137c478bd9Sstevel@tonic-gate  * xdr_time_t  sends time_t value over the wire.
1147c478bd9Sstevel@tonic-gate  * Due to RPC Protocol limitation, it can only send
1157c478bd9Sstevel@tonic-gate  * up to 32-bit integer quantity over the wire.
1167c478bd9Sstevel@tonic-gate  *
1177c478bd9Sstevel@tonic-gate  */
1187c478bd9Sstevel@tonic-gate bool_t
1197c478bd9Sstevel@tonic-gate xdr_time_t(XDR *xdrs, time_t *tp)
1207c478bd9Sstevel@tonic-gate {
1217c478bd9Sstevel@tonic-gate 	int32_t i;
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate 	switch (xdrs->x_op) {
1247c478bd9Sstevel@tonic-gate 	case XDR_ENCODE:
1257c478bd9Sstevel@tonic-gate 	/*
1267c478bd9Sstevel@tonic-gate 	 * Check for the time overflow, when encoding it.
1277c478bd9Sstevel@tonic-gate 	 * Don't want to send OTW the time value too large to
1287c478bd9Sstevel@tonic-gate 	 * handle by the protocol.
1297c478bd9Sstevel@tonic-gate 	 */
1307c478bd9Sstevel@tonic-gate #if defined(_LP64)
1317c478bd9Sstevel@tonic-gate 	if (*tp > INT32_MAX)
1327c478bd9Sstevel@tonic-gate 		*tp = INT32_MAX;
1337c478bd9Sstevel@tonic-gate 	else if (*tp < INT32_MIN)
1347c478bd9Sstevel@tonic-gate 		*tp = INT32_MIN;
1357c478bd9Sstevel@tonic-gate #endif
1367c478bd9Sstevel@tonic-gate 		i =  (int32_t)*tp;
13761961e0fSrobinson 		return (XDR_PUTINT32(xdrs, &i));
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate 	case XDR_DECODE:
14061961e0fSrobinson 		if (!XDR_GETINT32(xdrs, &i))
1417c478bd9Sstevel@tonic-gate 			return (FALSE);
1427c478bd9Sstevel@tonic-gate 		*tp = (time_t)i;
1437c478bd9Sstevel@tonic-gate 		return (TRUE);
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 	case XDR_FREE:
1467c478bd9Sstevel@tonic-gate 		return (TRUE);
1477c478bd9Sstevel@tonic-gate 	}
1487c478bd9Sstevel@tonic-gate 	return (FALSE);
1497c478bd9Sstevel@tonic-gate }
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate /*
1527c478bd9Sstevel@tonic-gate  * XDR integers
1537c478bd9Sstevel@tonic-gate  */
1547c478bd9Sstevel@tonic-gate bool_t
1557c478bd9Sstevel@tonic-gate xdr_int(XDR *xdrs, int *ip)
1567c478bd9Sstevel@tonic-gate {
15761961e0fSrobinson 	switch (xdrs->x_op) {
15861961e0fSrobinson 	case XDR_ENCODE:
1597c478bd9Sstevel@tonic-gate 		return (XDR_PUTINT32(xdrs, ip));
16061961e0fSrobinson 	case XDR_DECODE:
1617c478bd9Sstevel@tonic-gate 		return (XDR_GETINT32(xdrs, ip));
16261961e0fSrobinson 	case XDR_FREE:
1637c478bd9Sstevel@tonic-gate 		return (TRUE);
16461961e0fSrobinson 	}
1657c478bd9Sstevel@tonic-gate 	return (FALSE);
1667c478bd9Sstevel@tonic-gate }
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate /*
1697c478bd9Sstevel@tonic-gate  * XDR unsigned integers
1707c478bd9Sstevel@tonic-gate  */
1717c478bd9Sstevel@tonic-gate bool_t
1727c478bd9Sstevel@tonic-gate xdr_u_int(XDR *xdrs, uint_t *up)
1737c478bd9Sstevel@tonic-gate {
17461961e0fSrobinson 	switch (xdrs->x_op) {
17561961e0fSrobinson 	case XDR_ENCODE:
1767c478bd9Sstevel@tonic-gate 		return (XDR_PUTINT32(xdrs, (int *)up));
17761961e0fSrobinson 	case XDR_DECODE:
1787c478bd9Sstevel@tonic-gate 		return (XDR_GETINT32(xdrs, (int *)up));
17961961e0fSrobinson 	case XDR_FREE:
1807c478bd9Sstevel@tonic-gate 		return (TRUE);
18161961e0fSrobinson 	}
1827c478bd9Sstevel@tonic-gate 	return (FALSE);
1837c478bd9Sstevel@tonic-gate }
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate /*
1867c478bd9Sstevel@tonic-gate  * The definition of xdr_long()/xdr_u_long() is kept for backward
1877c478bd9Sstevel@tonic-gate  * compatibitlity.
1887c478bd9Sstevel@tonic-gate  * XDR long integers, same as xdr_u_long
1897c478bd9Sstevel@tonic-gate  */
1907c478bd9Sstevel@tonic-gate bool_t
1917c478bd9Sstevel@tonic-gate xdr_long(XDR *xdrs, long *lp)
1927c478bd9Sstevel@tonic-gate {
1937c478bd9Sstevel@tonic-gate 	int32_t i;
1947c478bd9Sstevel@tonic-gate 
19561961e0fSrobinson 	switch (xdrs->x_op) {
19661961e0fSrobinson 	case XDR_ENCODE:
1977c478bd9Sstevel@tonic-gate #if defined(_LP64)
19861961e0fSrobinson 		if ((*lp > INT32_MAX) || (*lp < INT32_MIN))
1997c478bd9Sstevel@tonic-gate 			return (FALSE);
2007c478bd9Sstevel@tonic-gate #endif
2017c478bd9Sstevel@tonic-gate 		i = (int32_t)*lp;
20261961e0fSrobinson 		return (XDR_PUTINT32(xdrs, &i));
20361961e0fSrobinson 	case XDR_DECODE:
20461961e0fSrobinson 		if (!XDR_GETINT32(xdrs, &i))
20561961e0fSrobinson 			return (FALSE);
2067c478bd9Sstevel@tonic-gate 		*lp = (long)i;
20761961e0fSrobinson 		return (TRUE);
20861961e0fSrobinson 	case XDR_FREE:
20961961e0fSrobinson 		return (TRUE);
21061961e0fSrobinson 	}
21161961e0fSrobinson 	return (FALSE);
2127c478bd9Sstevel@tonic-gate }
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate /*
2157c478bd9Sstevel@tonic-gate  * XDR unsigned long integers
2167c478bd9Sstevel@tonic-gate  * same as xdr_long
2177c478bd9Sstevel@tonic-gate  */
2187c478bd9Sstevel@tonic-gate bool_t
2197c478bd9Sstevel@tonic-gate xdr_u_long(XDR *xdrs, ulong_t *ulp)
2207c478bd9Sstevel@tonic-gate {
2217c478bd9Sstevel@tonic-gate 	uint32_t ui;
2227c478bd9Sstevel@tonic-gate 
22361961e0fSrobinson 	switch (xdrs->x_op) {
22461961e0fSrobinson 	case XDR_ENCODE:
2257c478bd9Sstevel@tonic-gate #if defined(_LP64)
22661961e0fSrobinson 		if (*ulp > UINT32_MAX)
2277c478bd9Sstevel@tonic-gate 			return (FALSE);
2287c478bd9Sstevel@tonic-gate #endif
2297c478bd9Sstevel@tonic-gate 		ui = (uint32_t)*ulp;
23061961e0fSrobinson 		return (XDR_PUTINT32(xdrs, (int32_t *)&ui));
23161961e0fSrobinson 	case XDR_DECODE:
23261961e0fSrobinson 		if (!XDR_GETINT32(xdrs, (int32_t *)&ui))
23361961e0fSrobinson 			return (FALSE);
2347c478bd9Sstevel@tonic-gate 		*ulp = (ulong_t)ui;
23561961e0fSrobinson 		return (TRUE);
23661961e0fSrobinson 	case XDR_FREE:
23761961e0fSrobinson 		return (TRUE);
23861961e0fSrobinson 	}
23961961e0fSrobinson 	return (FALSE);
2407c478bd9Sstevel@tonic-gate }
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate /*
2437c478bd9Sstevel@tonic-gate  * XDR short integers
2447c478bd9Sstevel@tonic-gate  */
2457c478bd9Sstevel@tonic-gate bool_t
2467c478bd9Sstevel@tonic-gate xdr_short(XDR *xdrs, short *sp)
2477c478bd9Sstevel@tonic-gate {
2487c478bd9Sstevel@tonic-gate 	int32_t l;
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate 	switch (xdrs->x_op) {
2517c478bd9Sstevel@tonic-gate 	case XDR_ENCODE:
2527c478bd9Sstevel@tonic-gate 		l = (int32_t)*sp;
25361961e0fSrobinson 		return (XDR_PUTINT32(xdrs, &l));
2547c478bd9Sstevel@tonic-gate 	case XDR_DECODE:
25561961e0fSrobinson 		if (!XDR_GETINT32(xdrs, &l))
2567c478bd9Sstevel@tonic-gate 			return (FALSE);
2577c478bd9Sstevel@tonic-gate 		*sp = (short)l;
2587c478bd9Sstevel@tonic-gate 		return (TRUE);
2597c478bd9Sstevel@tonic-gate 	case XDR_FREE:
2607c478bd9Sstevel@tonic-gate 		return (TRUE);
2617c478bd9Sstevel@tonic-gate 	}
2627c478bd9Sstevel@tonic-gate 	return (FALSE);
2637c478bd9Sstevel@tonic-gate }
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate /*
2667c478bd9Sstevel@tonic-gate  * XDR unsigned short integers
2677c478bd9Sstevel@tonic-gate  */
2687c478bd9Sstevel@tonic-gate bool_t
2697c478bd9Sstevel@tonic-gate xdr_u_short(XDR *xdrs, ushort_t *usp)
2707c478bd9Sstevel@tonic-gate {
2717c478bd9Sstevel@tonic-gate 	uint_t i;
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate 	switch (xdrs->x_op) {
2747c478bd9Sstevel@tonic-gate 	case XDR_ENCODE:
2757c478bd9Sstevel@tonic-gate 		i = (uint_t)*usp;
27661961e0fSrobinson 		return (XDR_PUTINT32(xdrs, (int *)&i));
2777c478bd9Sstevel@tonic-gate 	case XDR_DECODE:
27861961e0fSrobinson 		if (!XDR_GETINT32(xdrs, (int *)&i))
2797c478bd9Sstevel@tonic-gate 			return (FALSE);
2807c478bd9Sstevel@tonic-gate 		*usp = (ushort_t)i;
2817c478bd9Sstevel@tonic-gate 		return (TRUE);
2827c478bd9Sstevel@tonic-gate 	case XDR_FREE:
2837c478bd9Sstevel@tonic-gate 		return (TRUE);
2847c478bd9Sstevel@tonic-gate 	}
2857c478bd9Sstevel@tonic-gate 	return (FALSE);
2867c478bd9Sstevel@tonic-gate }
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate /*
2907c478bd9Sstevel@tonic-gate  * XDR a char
2917c478bd9Sstevel@tonic-gate  */
2927c478bd9Sstevel@tonic-gate bool_t
2937c478bd9Sstevel@tonic-gate xdr_char(XDR *xdrs, char *cp)
2947c478bd9Sstevel@tonic-gate {
2957c478bd9Sstevel@tonic-gate 	int i;
2967c478bd9Sstevel@tonic-gate 
29761961e0fSrobinson 	switch (xdrs->x_op) {
29861961e0fSrobinson 	case XDR_ENCODE:
2997c478bd9Sstevel@tonic-gate 		i = (*cp);
30061961e0fSrobinson 		return (XDR_PUTINT32(xdrs, &i));
30161961e0fSrobinson 	case XDR_DECODE:
30261961e0fSrobinson 		if (!XDR_GETINT32(xdrs, &i))
30361961e0fSrobinson 			return (FALSE);
3047c478bd9Sstevel@tonic-gate 		*cp = (char)i;
30561961e0fSrobinson 		return (TRUE);
30661961e0fSrobinson 	case XDR_FREE:
30761961e0fSrobinson 		return (TRUE);
30861961e0fSrobinson 	}
30961961e0fSrobinson 	return (FALSE);
3107c478bd9Sstevel@tonic-gate }
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate /*
3137c478bd9Sstevel@tonic-gate  * XDR an unsigned char
3147c478bd9Sstevel@tonic-gate  */
3157c478bd9Sstevel@tonic-gate bool_t
3167c478bd9Sstevel@tonic-gate xdr_u_char(XDR *xdrs, uchar_t *cp)
3177c478bd9Sstevel@tonic-gate {
3187c478bd9Sstevel@tonic-gate 	int i;
3197c478bd9Sstevel@tonic-gate 
32061961e0fSrobinson 	switch (xdrs->x_op) {
32161961e0fSrobinson 	case XDR_ENCODE:
3227c478bd9Sstevel@tonic-gate 		i = (*cp);
32361961e0fSrobinson 		return (XDR_PUTINT32(xdrs, &i));
32461961e0fSrobinson 	case XDR_DECODE:
32561961e0fSrobinson 		if (!XDR_GETINT32(xdrs, &i))
32661961e0fSrobinson 			return (FALSE);
3277c478bd9Sstevel@tonic-gate 		*cp = (uchar_t)i;
32861961e0fSrobinson 		return (TRUE);
32961961e0fSrobinson 	case XDR_FREE:
33061961e0fSrobinson 		return (TRUE);
33161961e0fSrobinson 	}
33261961e0fSrobinson 	return (FALSE);
3337c478bd9Sstevel@tonic-gate }
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate /*
3367c478bd9Sstevel@tonic-gate  * XDR booleans
3377c478bd9Sstevel@tonic-gate  */
3387c478bd9Sstevel@tonic-gate bool_t
3397c478bd9Sstevel@tonic-gate xdr_bool(XDR *xdrs, bool_t *bp)
3407c478bd9Sstevel@tonic-gate {
3417c478bd9Sstevel@tonic-gate 	int i;
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate 	switch (xdrs->x_op) {
3447c478bd9Sstevel@tonic-gate 	case XDR_ENCODE:
3457c478bd9Sstevel@tonic-gate 		i = *bp ? XDR_TRUE : XDR_FALSE;
34661961e0fSrobinson 		return (XDR_PUTINT32(xdrs, &i));
3477c478bd9Sstevel@tonic-gate 	case XDR_DECODE:
34861961e0fSrobinson 		if (!XDR_GETINT32(xdrs, &i))
3497c478bd9Sstevel@tonic-gate 			return (FALSE);
3507c478bd9Sstevel@tonic-gate 		*bp = (i == XDR_FALSE) ? FALSE : TRUE;
3517c478bd9Sstevel@tonic-gate 		return (TRUE);
3527c478bd9Sstevel@tonic-gate 	case XDR_FREE:
3537c478bd9Sstevel@tonic-gate 		return (TRUE);
3547c478bd9Sstevel@tonic-gate 	}
3557c478bd9Sstevel@tonic-gate 	return (FALSE);
3567c478bd9Sstevel@tonic-gate }
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate /*
3597c478bd9Sstevel@tonic-gate  * XDR enumerations
3607c478bd9Sstevel@tonic-gate  */
3617c478bd9Sstevel@tonic-gate bool_t
3627c478bd9Sstevel@tonic-gate xdr_enum(XDR *xdrs, enum_t *ep)
3637c478bd9Sstevel@tonic-gate {
3647c478bd9Sstevel@tonic-gate 	enum sizecheck { SIZEVAL };	/* used to find the size of an enum */
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 	/*
3677c478bd9Sstevel@tonic-gate 	 * enums are treated as ints
3687c478bd9Sstevel@tonic-gate 	 */
36961961e0fSrobinson 	/* CONSTCOND */
37061961e0fSrobinson 	assert(sizeof (enum sizecheck) == sizeof (int32_t));
37161961e0fSrobinson 	return (xdr_int(xdrs, (int *)ep));
3727c478bd9Sstevel@tonic-gate }
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate /*
3757c478bd9Sstevel@tonic-gate  * XDR opaque data
3767c478bd9Sstevel@tonic-gate  * Allows the specification of a fixed size sequence of opaque bytes.
3777c478bd9Sstevel@tonic-gate  * cp points to the opaque object and cnt gives the byte length.
3787c478bd9Sstevel@tonic-gate  */
3797c478bd9Sstevel@tonic-gate bool_t
38061961e0fSrobinson xdr_opaque(XDR *xdrs, caddr_t cp, const uint_t cnt)
3817c478bd9Sstevel@tonic-gate {
38261961e0fSrobinson 	uint_t rndup;
3837c478bd9Sstevel@tonic-gate 	char crud[BYTES_PER_XDR_UNIT];
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate 	/*
3867c478bd9Sstevel@tonic-gate 	 * if no data we are done
3877c478bd9Sstevel@tonic-gate 	 */
38861961e0fSrobinson 	if (cnt == 0)
3897c478bd9Sstevel@tonic-gate 		return (TRUE);
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate 	/*
3927c478bd9Sstevel@tonic-gate 	 * round byte count to full xdr units
3937c478bd9Sstevel@tonic-gate 	 */
3947c478bd9Sstevel@tonic-gate 	rndup = cnt % BYTES_PER_XDR_UNIT;
3957c478bd9Sstevel@tonic-gate 	if ((int)rndup > 0)
3967c478bd9Sstevel@tonic-gate 		rndup = BYTES_PER_XDR_UNIT - rndup;
3977c478bd9Sstevel@tonic-gate 
39861961e0fSrobinson 	switch (xdrs->x_op) {
39961961e0fSrobinson 	case XDR_DECODE:
40061961e0fSrobinson 		if (!XDR_GETBYTES(xdrs, cp, cnt))
4017c478bd9Sstevel@tonic-gate 			return (FALSE);
40261961e0fSrobinson 		if (rndup == 0)
4037c478bd9Sstevel@tonic-gate 			return (TRUE);
40461961e0fSrobinson 		return (XDR_GETBYTES(xdrs, crud, rndup));
40561961e0fSrobinson 	case XDR_ENCODE:
40661961e0fSrobinson 		if (!XDR_PUTBYTES(xdrs, cp, cnt))
4077c478bd9Sstevel@tonic-gate 			return (FALSE);
40861961e0fSrobinson 		if (rndup == 0)
4097c478bd9Sstevel@tonic-gate 			return (TRUE);
41061961e0fSrobinson 		return (XDR_PUTBYTES(xdrs, (caddr_t)&xdr_zero[0], rndup));
41161961e0fSrobinson 	case XDR_FREE:
4127c478bd9Sstevel@tonic-gate 		return (TRUE);
4137c478bd9Sstevel@tonic-gate 	}
4147c478bd9Sstevel@tonic-gate 	return (FALSE);
4157c478bd9Sstevel@tonic-gate }
4167c478bd9Sstevel@tonic-gate 
4177c478bd9Sstevel@tonic-gate /*
4187c478bd9Sstevel@tonic-gate  * XDR counted bytes
4197c478bd9Sstevel@tonic-gate  * *cpp is a pointer to the bytes, *sizep is the count.
4207c478bd9Sstevel@tonic-gate  * If *cpp is NULL maxsize bytes are allocated
4217c478bd9Sstevel@tonic-gate  */
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate static const char xdr_err[] = "xdr_%s: out of memory";
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate bool_t
42661961e0fSrobinson xdr_bytes(XDR *xdrs, char **cpp, uint_t *sizep, const uint_t maxsize)
4277c478bd9Sstevel@tonic-gate {
42861961e0fSrobinson 	char *sp = *cpp;  /* sp is the actual string pointer */
42961961e0fSrobinson 	uint_t nodesize;
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 	/*
4327c478bd9Sstevel@tonic-gate 	 * first deal with the length since xdr bytes are counted
4337c478bd9Sstevel@tonic-gate 	 * We decided not to use MACRO XDR_U_INT here, because the
4347c478bd9Sstevel@tonic-gate 	 * advantages here will be miniscule compared to xdr_bytes.
4357c478bd9Sstevel@tonic-gate 	 * This saved us 100 bytes in the library size.
4367c478bd9Sstevel@tonic-gate 	 */
43761961e0fSrobinson 	if (!xdr_u_int(xdrs, sizep))
4387c478bd9Sstevel@tonic-gate 		return (FALSE);
4397c478bd9Sstevel@tonic-gate 	nodesize = *sizep;
44061961e0fSrobinson 	if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE))
4417c478bd9Sstevel@tonic-gate 		return (FALSE);
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate 	/*
4447c478bd9Sstevel@tonic-gate 	 * now deal with the actual bytes
4457c478bd9Sstevel@tonic-gate 	 */
4467c478bd9Sstevel@tonic-gate 	switch (xdrs->x_op) {
4477c478bd9Sstevel@tonic-gate 	case XDR_DECODE:
44861961e0fSrobinson 		if (nodesize == 0)
4497c478bd9Sstevel@tonic-gate 			return (TRUE);
45061961e0fSrobinson 		if (sp == NULL)
45161961e0fSrobinson 			*cpp = sp = malloc(nodesize);
4527c478bd9Sstevel@tonic-gate 		if (sp == NULL) {
4537c478bd9Sstevel@tonic-gate 			(void) syslog(LOG_ERR, xdr_err, (const char *)"bytes");
4547c478bd9Sstevel@tonic-gate 			return (FALSE);
4557c478bd9Sstevel@tonic-gate 		}
4567c478bd9Sstevel@tonic-gate 		/*FALLTHROUGH*/
4577c478bd9Sstevel@tonic-gate 	case XDR_ENCODE:
45861961e0fSrobinson 		return (xdr_opaque(xdrs, sp, nodesize));
4597c478bd9Sstevel@tonic-gate 	case XDR_FREE:
4607c478bd9Sstevel@tonic-gate 		if (sp != NULL) {
46161961e0fSrobinson 			free(sp);
4627c478bd9Sstevel@tonic-gate 			*cpp = NULL;
4637c478bd9Sstevel@tonic-gate 		}
4647c478bd9Sstevel@tonic-gate 		return (TRUE);
4657c478bd9Sstevel@tonic-gate 	}
4667c478bd9Sstevel@tonic-gate 	return (FALSE);
4677c478bd9Sstevel@tonic-gate }
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate /*
4707c478bd9Sstevel@tonic-gate  * Implemented here due to commonality of the object.
4717c478bd9Sstevel@tonic-gate  */
4727c478bd9Sstevel@tonic-gate bool_t
4737c478bd9Sstevel@tonic-gate xdr_netobj(XDR *xdrs, struct netobj *np)
4747c478bd9Sstevel@tonic-gate {
47561961e0fSrobinson 	return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
4767c478bd9Sstevel@tonic-gate }
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate /*
4797c478bd9Sstevel@tonic-gate  * XDR a descriminated union
4807c478bd9Sstevel@tonic-gate  * Support routine for discriminated unions.
4817c478bd9Sstevel@tonic-gate  * You create an array of xdrdiscrim structures, terminated with
4827c478bd9Sstevel@tonic-gate  * an entry with a null procedure pointer.  The routine gets
4837c478bd9Sstevel@tonic-gate  * the discriminant value and then searches the array of xdrdiscrims
4847c478bd9Sstevel@tonic-gate  * looking for that value.  It calls the procedure given in the xdrdiscrim
4857c478bd9Sstevel@tonic-gate  * to handle the discriminant.  If there is no specific routine a default
4867c478bd9Sstevel@tonic-gate  * routine may be called.
4877c478bd9Sstevel@tonic-gate  * If there is no specific or default routine an error is returned.
4887c478bd9Sstevel@tonic-gate  */
4897c478bd9Sstevel@tonic-gate bool_t
4907c478bd9Sstevel@tonic-gate xdr_union(XDR *xdrs, enum_t *dscmp, char *unp,
49161961e0fSrobinson 		const struct xdr_discrim *choices, const xdrproc_t dfault)
4927c478bd9Sstevel@tonic-gate {
49361961e0fSrobinson 	enum_t dscm;
4947c478bd9Sstevel@tonic-gate 
4957c478bd9Sstevel@tonic-gate 	/*
4967c478bd9Sstevel@tonic-gate 	 * we deal with the discriminator;  it's an enum
4977c478bd9Sstevel@tonic-gate 	 */
49861961e0fSrobinson 	if (!xdr_enum(xdrs, dscmp))
4997c478bd9Sstevel@tonic-gate 		return (FALSE);
5007c478bd9Sstevel@tonic-gate 	dscm = *dscmp;
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate 	/*
5037c478bd9Sstevel@tonic-gate 	 * search choices for a value that matches the discriminator.
5047c478bd9Sstevel@tonic-gate 	 * if we find one, execute the xdr routine for that value.
5057c478bd9Sstevel@tonic-gate 	 */
5067c478bd9Sstevel@tonic-gate 	for (; choices->proc != NULL_xdrproc_t; choices++) {
50761961e0fSrobinson 		if (choices->value == dscm)
50861961e0fSrobinson 			return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED));
5097c478bd9Sstevel@tonic-gate 	}
5107c478bd9Sstevel@tonic-gate 
5117c478bd9Sstevel@tonic-gate 	/*
5127c478bd9Sstevel@tonic-gate 	 * no match - execute the default xdr routine if there is one
5137c478bd9Sstevel@tonic-gate 	 */
51461961e0fSrobinson 	return ((dfault == NULL_xdrproc_t) ? FALSE :
51561961e0fSrobinson 	    (*dfault)(xdrs, unp, LASTUNSIGNED));
5167c478bd9Sstevel@tonic-gate }
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate /*
5207c478bd9Sstevel@tonic-gate  * Non-portable xdr primitives.
5217c478bd9Sstevel@tonic-gate  * Care should be taken when moving these routines to new architectures.
5227c478bd9Sstevel@tonic-gate  */
5237c478bd9Sstevel@tonic-gate 
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate /*
5267c478bd9Sstevel@tonic-gate  * XDR null terminated ASCII strings
5277c478bd9Sstevel@tonic-gate  * xdr_string deals with "C strings" - arrays of bytes that are
5287c478bd9Sstevel@tonic-gate  * terminated by a NULL character.  The parameter cpp references a
5297c478bd9Sstevel@tonic-gate  * pointer to storage; If the pointer is null, then the necessary
5307c478bd9Sstevel@tonic-gate  * storage is allocated.  The last parameter is the max allowed length
5317c478bd9Sstevel@tonic-gate  * of the string as specified by a protocol.
5327c478bd9Sstevel@tonic-gate  */
5337c478bd9Sstevel@tonic-gate bool_t
53461961e0fSrobinson xdr_string(XDR *xdrs, char **cpp, const uint_t maxsize)
5357c478bd9Sstevel@tonic-gate {
53661961e0fSrobinson 	char *newsp, *sp = *cpp;  /* sp is the actual string pointer */
5377c478bd9Sstevel@tonic-gate 	uint_t size, block;
5387c478bd9Sstevel@tonic-gate 	uint64_t bytesread;
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate 	/*
5417c478bd9Sstevel@tonic-gate 	 * first deal with the length since xdr strings are counted-strings
5427c478bd9Sstevel@tonic-gate 	 */
5437c478bd9Sstevel@tonic-gate 	switch (xdrs->x_op) {
5447c478bd9Sstevel@tonic-gate 	case XDR_FREE:
54561961e0fSrobinson 		if (sp == NULL)
5467c478bd9Sstevel@tonic-gate 			return (TRUE);	/* already free */
5477c478bd9Sstevel@tonic-gate 		/*FALLTHROUGH*/
5487c478bd9Sstevel@tonic-gate 	case XDR_ENCODE:
5497c478bd9Sstevel@tonic-gate 		size = (sp != NULL) ? (uint_t)strlen(sp) : 0;
5507c478bd9Sstevel@tonic-gate 		break;
5517c478bd9Sstevel@tonic-gate 	}
5527c478bd9Sstevel@tonic-gate 	/*
5537c478bd9Sstevel@tonic-gate 	 * We decided not to use MACRO XDR_U_INT here, because the
5547c478bd9Sstevel@tonic-gate 	 * advantages here will be miniscule compared to xdr_string.
5557c478bd9Sstevel@tonic-gate 	 * This saved us 100 bytes in the library size.
5567c478bd9Sstevel@tonic-gate 	 */
55761961e0fSrobinson 	if (!xdr_u_int(xdrs, &size))
5587c478bd9Sstevel@tonic-gate 		return (FALSE);
55961961e0fSrobinson 	if (size > maxsize)
5607c478bd9Sstevel@tonic-gate 		return (FALSE);
5617c478bd9Sstevel@tonic-gate 
5627c478bd9Sstevel@tonic-gate 	/*
5637c478bd9Sstevel@tonic-gate 	 * now deal with the actual bytes
5647c478bd9Sstevel@tonic-gate 	 */
5657c478bd9Sstevel@tonic-gate 	switch (xdrs->x_op) {
5667c478bd9Sstevel@tonic-gate 	case XDR_DECODE:
5677c478bd9Sstevel@tonic-gate 		/* if buffer is already given, call xdr_opaque() directly */
5687c478bd9Sstevel@tonic-gate 		if (sp != NULL) {
56961961e0fSrobinson 			if (!xdr_opaque(xdrs, sp, size))
57061961e0fSrobinson 				return (FALSE);
5717c478bd9Sstevel@tonic-gate 			sp[size] = 0;
57261961e0fSrobinson 			return (TRUE);
5737c478bd9Sstevel@tonic-gate 		}
5747c478bd9Sstevel@tonic-gate 
5757c478bd9Sstevel@tonic-gate 		/*
5767c478bd9Sstevel@tonic-gate 		 * We have to allocate a buffer of size 'size'. To avoid
5777c478bd9Sstevel@tonic-gate 		 * malloc()ing one huge chunk, we'll read the bytes in max
5787c478bd9Sstevel@tonic-gate 		 * FRAGMENT size blocks and keep realloc()ing. 'block' is
5797c478bd9Sstevel@tonic-gate 		 * the number of bytes to read in each xdr_opaque() and
5807c478bd9Sstevel@tonic-gate 		 * 'bytesread' is what we have already read. sp is NULL
5817c478bd9Sstevel@tonic-gate 		 * when we are in the loop for the first time.
5827c478bd9Sstevel@tonic-gate 		 */
5837c478bd9Sstevel@tonic-gate 		bytesread = 0;
5847c478bd9Sstevel@tonic-gate 		do {
5857c478bd9Sstevel@tonic-gate 			block = MIN(size - bytesread, FRAGMENT);
5867c478bd9Sstevel@tonic-gate 			/*
5877c478bd9Sstevel@tonic-gate 			 * allocate enough for 'bytesread + block' bytes and
5887c478bd9Sstevel@tonic-gate 			 * one extra for the terminating NULL.
5897c478bd9Sstevel@tonic-gate 			 */
5907c478bd9Sstevel@tonic-gate 			newsp = realloc(sp, bytesread + block + 1);
5917c478bd9Sstevel@tonic-gate 			if (newsp == NULL) {
5927c478bd9Sstevel@tonic-gate 				if (sp != NULL)
5937c478bd9Sstevel@tonic-gate 					free(sp);
5947c478bd9Sstevel@tonic-gate 				return (FALSE);
5957c478bd9Sstevel@tonic-gate 			}
5967c478bd9Sstevel@tonic-gate 			sp = newsp;
5977c478bd9Sstevel@tonic-gate 			if (!xdr_opaque(xdrs, &sp[bytesread], block)) {
5987c478bd9Sstevel@tonic-gate 				free(sp);
5997c478bd9Sstevel@tonic-gate 				return (FALSE);
6007c478bd9Sstevel@tonic-gate 			}
6017c478bd9Sstevel@tonic-gate 			bytesread += block;
6027c478bd9Sstevel@tonic-gate 		} while (bytesread < size);
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate 		sp[bytesread] = 0; /* terminate the string with a NULL */
6057c478bd9Sstevel@tonic-gate 		*cpp = sp;
6067c478bd9Sstevel@tonic-gate 		return (TRUE);
6077c478bd9Sstevel@tonic-gate 	case XDR_ENCODE:
60861961e0fSrobinson 		return (xdr_opaque(xdrs, sp, size));
6097c478bd9Sstevel@tonic-gate 	case XDR_FREE:
6107c478bd9Sstevel@tonic-gate 		free(sp);
6117c478bd9Sstevel@tonic-gate 		*cpp = NULL;
6127c478bd9Sstevel@tonic-gate 		return (TRUE);
6137c478bd9Sstevel@tonic-gate 	}
6147c478bd9Sstevel@tonic-gate 	return (FALSE);
6157c478bd9Sstevel@tonic-gate }
6167c478bd9Sstevel@tonic-gate 
6177c478bd9Sstevel@tonic-gate bool_t
6187c478bd9Sstevel@tonic-gate xdr_hyper(XDR *xdrs, longlong_t *hp)
6197c478bd9Sstevel@tonic-gate {
6207c478bd9Sstevel@tonic-gate 	if (xdrs->x_op == XDR_ENCODE) {
6217c478bd9Sstevel@tonic-gate #if defined(_LONG_LONG_HTOL)
62261961e0fSrobinson 		if (XDR_PUTINT32(xdrs, (int *)hp) == TRUE)
62361961e0fSrobinson 			/* LINTED pointer cast */
62461961e0fSrobinson 			return (XDR_PUTINT32(xdrs, (int *)((char *)hp +
62561961e0fSrobinson 				BYTES_PER_XDR_UNIT)));
6267c478bd9Sstevel@tonic-gate #else
62761961e0fSrobinson 		/* LINTED pointer cast */
6287c478bd9Sstevel@tonic-gate 		if (XDR_PUTINT32(xdrs, (int *)((char *)hp +
62961961e0fSrobinson 				BYTES_PER_XDR_UNIT)) == TRUE)
63061961e0fSrobinson 			return (XDR_PUTINT32(xdrs, (int32_t *)hp));
6317c478bd9Sstevel@tonic-gate #endif
6327c478bd9Sstevel@tonic-gate 		return (FALSE);
63361961e0fSrobinson 	}
6347c478bd9Sstevel@tonic-gate 
63561961e0fSrobinson 	if (xdrs->x_op == XDR_DECODE) {
6367c478bd9Sstevel@tonic-gate #if defined(_LONG_LONG_HTOL)
6377c478bd9Sstevel@tonic-gate 		if (XDR_GETINT32(xdrs, (int *)hp) == FALSE ||
63861961e0fSrobinson 		    /* LINTED pointer cast */
6397c478bd9Sstevel@tonic-gate 		    (XDR_GETINT32(xdrs, (int *)((char *)hp +
64061961e0fSrobinson 				BYTES_PER_XDR_UNIT)) == FALSE))
6417c478bd9Sstevel@tonic-gate 			return (FALSE);
6427c478bd9Sstevel@tonic-gate #else
64361961e0fSrobinson 		/* LINTED pointer cast */
6447c478bd9Sstevel@tonic-gate 		if ((XDR_GETINT32(xdrs, (int *)((char *)hp +
6457c478bd9Sstevel@tonic-gate 				BYTES_PER_XDR_UNIT)) == FALSE) ||
64661961e0fSrobinson 				(XDR_GETINT32(xdrs, (int *)hp) == FALSE))
6477c478bd9Sstevel@tonic-gate 			return (FALSE);
6487c478bd9Sstevel@tonic-gate #endif
6497c478bd9Sstevel@tonic-gate 		return (TRUE);
6507c478bd9Sstevel@tonic-gate 	}
6517c478bd9Sstevel@tonic-gate 	return (TRUE);
6527c478bd9Sstevel@tonic-gate }
6537c478bd9Sstevel@tonic-gate 
6547c478bd9Sstevel@tonic-gate bool_t
6557c478bd9Sstevel@tonic-gate xdr_u_hyper(XDR *xdrs, u_longlong_t *hp)
6567c478bd9Sstevel@tonic-gate {
65761961e0fSrobinson 	return (xdr_hyper(xdrs, (longlong_t *)hp));
6587c478bd9Sstevel@tonic-gate }
6597c478bd9Sstevel@tonic-gate 
6607c478bd9Sstevel@tonic-gate bool_t
6617c478bd9Sstevel@tonic-gate xdr_longlong_t(XDR *xdrs, longlong_t *hp)
6627c478bd9Sstevel@tonic-gate {
66361961e0fSrobinson 	return (xdr_hyper(xdrs, hp));
6647c478bd9Sstevel@tonic-gate }
6657c478bd9Sstevel@tonic-gate 
6667c478bd9Sstevel@tonic-gate bool_t
6677c478bd9Sstevel@tonic-gate xdr_u_longlong_t(XDR *xdrs, u_longlong_t *hp)
6687c478bd9Sstevel@tonic-gate {
66961961e0fSrobinson 	return (xdr_hyper(xdrs, (longlong_t *)hp));
6707c478bd9Sstevel@tonic-gate }
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate /*
6737c478bd9Sstevel@tonic-gate  * Wrapper for xdr_string that can be called directly from
6747c478bd9Sstevel@tonic-gate  * routines like clnt_call
6757c478bd9Sstevel@tonic-gate  */
6767c478bd9Sstevel@tonic-gate bool_t
6777c478bd9Sstevel@tonic-gate xdr_wrapstring(XDR *xdrs, char **cpp)
6787c478bd9Sstevel@tonic-gate {
67961961e0fSrobinson 	return (xdr_string(xdrs, cpp, LASTUNSIGNED));
6807c478bd9Sstevel@tonic-gate }
681