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 /* 24e8031f0aSraf * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 257c478bd9Sstevel@tonic-gate * Use is subject to license terms. 267c478bd9Sstevel@tonic-gate */ 27e8031f0aSraf 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 /* 37e8031f0aSraf * Generic XDR routines implementation. 387c478bd9Sstevel@tonic-gate * 397c478bd9Sstevel@tonic-gate * These are the "generic" xdr routines used to serialize and de-serialize 407c478bd9Sstevel@tonic-gate * most common data items. See xdr.h for more info on the interface to 417c478bd9Sstevel@tonic-gate * xdr. 427c478bd9Sstevel@tonic-gate */ 43e8031f0aSraf #include "mt.h" 4461961e0fSrobinson #include <stdlib.h> 457c478bd9Sstevel@tonic-gate #include <sys/types.h> 467c478bd9Sstevel@tonic-gate #include <sys/isa_defs.h> 477c478bd9Sstevel@tonic-gate #include <syslog.h> 487c478bd9Sstevel@tonic-gate #include <stdio.h> 497c478bd9Sstevel@tonic-gate #include <stdlib.h> 507c478bd9Sstevel@tonic-gate #include <string.h> 517c478bd9Sstevel@tonic-gate #include <limits.h> 527c478bd9Sstevel@tonic-gate #include <rpc/types.h> 537c478bd9Sstevel@tonic-gate #include <rpc/xdr.h> 547c478bd9Sstevel@tonic-gate #include <inttypes.h> 557c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 5661961e0fSrobinson #include <assert.h> 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate #pragma weak xdr_int64_t = xdr_hyper 597c478bd9Sstevel@tonic-gate #pragma weak xdr_uint64_t = xdr_u_hyper 607c478bd9Sstevel@tonic-gate #pragma weak xdr_int32_t = xdr_int 617c478bd9Sstevel@tonic-gate #pragma weak xdr_uint32_t = xdr_u_int 627c478bd9Sstevel@tonic-gate #pragma weak xdr_int16_t = xdr_short 637c478bd9Sstevel@tonic-gate #pragma weak xdr_uint16_t = xdr_u_short 647c478bd9Sstevel@tonic-gate #pragma weak xdr_int8_t = xdr_char 657c478bd9Sstevel@tonic-gate #pragma weak xdr_uint8_t = xdr_u_char 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate /* 6861961e0fSrobinson * The following routine was part of a workaround for an rpcgen 6961961e0fSrobinson * that was fixed, this routine should be removed sometime. 7061961e0fSrobinson */ 7161961e0fSrobinson #pragma weak xdr_ulonglong_t = xdr_u_longlong_t 7261961e0fSrobinson 7361961e0fSrobinson /* 747c478bd9Sstevel@tonic-gate * constants specific to the xdr "protocol" 757c478bd9Sstevel@tonic-gate */ 767c478bd9Sstevel@tonic-gate #define XDR_FALSE ((uint_t)0) 777c478bd9Sstevel@tonic-gate #define XDR_TRUE ((uint_t)1) 787c478bd9Sstevel@tonic-gate #define LASTUNSIGNED ((uint_t)0-1) 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate /* fragment size to use when doing an xdr_string() */ 817c478bd9Sstevel@tonic-gate #define FRAGMENT 65536 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate /* 847c478bd9Sstevel@tonic-gate * for unit alignment 857c478bd9Sstevel@tonic-gate */ 867c478bd9Sstevel@tonic-gate static const char xdr_zero[BYTES_PER_XDR_UNIT] = { 0 }; 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate /* 897c478bd9Sstevel@tonic-gate * Free a data structure using XDR 907c478bd9Sstevel@tonic-gate * Not a filter, but a convenient utility nonetheless 917c478bd9Sstevel@tonic-gate */ 927c478bd9Sstevel@tonic-gate void 937c478bd9Sstevel@tonic-gate xdr_free(xdrproc_t proc, char *objp) 947c478bd9Sstevel@tonic-gate { 957c478bd9Sstevel@tonic-gate XDR x; 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate x.x_op = XDR_FREE; 987c478bd9Sstevel@tonic-gate (*proc)(&x, objp); 997c478bd9Sstevel@tonic-gate } 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate /* 1027c478bd9Sstevel@tonic-gate * XDR nothing 1037c478bd9Sstevel@tonic-gate */ 1047c478bd9Sstevel@tonic-gate bool_t 10561961e0fSrobinson xdr_void(void) 1067c478bd9Sstevel@tonic-gate { 1077c478bd9Sstevel@tonic-gate return (TRUE); 1087c478bd9Sstevel@tonic-gate } 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate /* 1117c478bd9Sstevel@tonic-gate * xdr_time_t sends time_t value over the wire. 1127c478bd9Sstevel@tonic-gate * Due to RPC Protocol limitation, it can only send 1137c478bd9Sstevel@tonic-gate * up to 32-bit integer quantity over the wire. 1147c478bd9Sstevel@tonic-gate * 1157c478bd9Sstevel@tonic-gate */ 1167c478bd9Sstevel@tonic-gate bool_t 1177c478bd9Sstevel@tonic-gate xdr_time_t(XDR *xdrs, time_t *tp) 1187c478bd9Sstevel@tonic-gate { 1197c478bd9Sstevel@tonic-gate int32_t i; 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate switch (xdrs->x_op) { 1227c478bd9Sstevel@tonic-gate case XDR_ENCODE: 1237c478bd9Sstevel@tonic-gate /* 1247c478bd9Sstevel@tonic-gate * Check for the time overflow, when encoding it. 1257c478bd9Sstevel@tonic-gate * Don't want to send OTW the time value too large to 1267c478bd9Sstevel@tonic-gate * handle by the protocol. 1277c478bd9Sstevel@tonic-gate */ 1287c478bd9Sstevel@tonic-gate #if defined(_LP64) 1297c478bd9Sstevel@tonic-gate if (*tp > INT32_MAX) 1307c478bd9Sstevel@tonic-gate *tp = INT32_MAX; 1317c478bd9Sstevel@tonic-gate else if (*tp < INT32_MIN) 1327c478bd9Sstevel@tonic-gate *tp = INT32_MIN; 1337c478bd9Sstevel@tonic-gate #endif 1347c478bd9Sstevel@tonic-gate i = (int32_t)*tp; 13561961e0fSrobinson return (XDR_PUTINT32(xdrs, &i)); 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate case XDR_DECODE: 13861961e0fSrobinson if (!XDR_GETINT32(xdrs, &i)) 1397c478bd9Sstevel@tonic-gate return (FALSE); 1407c478bd9Sstevel@tonic-gate *tp = (time_t)i; 1417c478bd9Sstevel@tonic-gate return (TRUE); 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate case XDR_FREE: 1447c478bd9Sstevel@tonic-gate return (TRUE); 1457c478bd9Sstevel@tonic-gate } 1467c478bd9Sstevel@tonic-gate return (FALSE); 1477c478bd9Sstevel@tonic-gate } 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate /* 1507c478bd9Sstevel@tonic-gate * XDR integers 1517c478bd9Sstevel@tonic-gate */ 1527c478bd9Sstevel@tonic-gate bool_t 1537c478bd9Sstevel@tonic-gate xdr_int(XDR *xdrs, int *ip) 1547c478bd9Sstevel@tonic-gate { 15561961e0fSrobinson switch (xdrs->x_op) { 15661961e0fSrobinson case XDR_ENCODE: 1577c478bd9Sstevel@tonic-gate return (XDR_PUTINT32(xdrs, ip)); 15861961e0fSrobinson case XDR_DECODE: 1597c478bd9Sstevel@tonic-gate return (XDR_GETINT32(xdrs, ip)); 16061961e0fSrobinson case XDR_FREE: 1617c478bd9Sstevel@tonic-gate return (TRUE); 16261961e0fSrobinson } 1637c478bd9Sstevel@tonic-gate return (FALSE); 1647c478bd9Sstevel@tonic-gate } 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate /* 1677c478bd9Sstevel@tonic-gate * XDR unsigned integers 1687c478bd9Sstevel@tonic-gate */ 1697c478bd9Sstevel@tonic-gate bool_t 1707c478bd9Sstevel@tonic-gate xdr_u_int(XDR *xdrs, uint_t *up) 1717c478bd9Sstevel@tonic-gate { 17261961e0fSrobinson switch (xdrs->x_op) { 17361961e0fSrobinson case XDR_ENCODE: 1747c478bd9Sstevel@tonic-gate return (XDR_PUTINT32(xdrs, (int *)up)); 17561961e0fSrobinson case XDR_DECODE: 1767c478bd9Sstevel@tonic-gate return (XDR_GETINT32(xdrs, (int *)up)); 17761961e0fSrobinson case XDR_FREE: 1787c478bd9Sstevel@tonic-gate return (TRUE); 17961961e0fSrobinson } 1807c478bd9Sstevel@tonic-gate return (FALSE); 1817c478bd9Sstevel@tonic-gate } 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate /* 1847c478bd9Sstevel@tonic-gate * The definition of xdr_long()/xdr_u_long() is kept for backward 1857c478bd9Sstevel@tonic-gate * compatibitlity. 1867c478bd9Sstevel@tonic-gate * XDR long integers, same as xdr_u_long 1877c478bd9Sstevel@tonic-gate */ 1887c478bd9Sstevel@tonic-gate bool_t 1897c478bd9Sstevel@tonic-gate xdr_long(XDR *xdrs, long *lp) 1907c478bd9Sstevel@tonic-gate { 1917c478bd9Sstevel@tonic-gate int32_t i; 1927c478bd9Sstevel@tonic-gate 19361961e0fSrobinson switch (xdrs->x_op) { 19461961e0fSrobinson case XDR_ENCODE: 1957c478bd9Sstevel@tonic-gate #if defined(_LP64) 19661961e0fSrobinson if ((*lp > INT32_MAX) || (*lp < INT32_MIN)) 1977c478bd9Sstevel@tonic-gate return (FALSE); 1987c478bd9Sstevel@tonic-gate #endif 1997c478bd9Sstevel@tonic-gate i = (int32_t)*lp; 20061961e0fSrobinson return (XDR_PUTINT32(xdrs, &i)); 20161961e0fSrobinson case XDR_DECODE: 20261961e0fSrobinson if (!XDR_GETINT32(xdrs, &i)) 20361961e0fSrobinson return (FALSE); 2047c478bd9Sstevel@tonic-gate *lp = (long)i; 20561961e0fSrobinson return (TRUE); 20661961e0fSrobinson case XDR_FREE: 20761961e0fSrobinson return (TRUE); 20861961e0fSrobinson } 20961961e0fSrobinson return (FALSE); 2107c478bd9Sstevel@tonic-gate } 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate /* 2137c478bd9Sstevel@tonic-gate * XDR unsigned long integers 2147c478bd9Sstevel@tonic-gate * same as xdr_long 2157c478bd9Sstevel@tonic-gate */ 2167c478bd9Sstevel@tonic-gate bool_t 2177c478bd9Sstevel@tonic-gate xdr_u_long(XDR *xdrs, ulong_t *ulp) 2187c478bd9Sstevel@tonic-gate { 2197c478bd9Sstevel@tonic-gate uint32_t ui; 2207c478bd9Sstevel@tonic-gate 22161961e0fSrobinson switch (xdrs->x_op) { 22261961e0fSrobinson case XDR_ENCODE: 2237c478bd9Sstevel@tonic-gate #if defined(_LP64) 22461961e0fSrobinson if (*ulp > UINT32_MAX) 2257c478bd9Sstevel@tonic-gate return (FALSE); 2267c478bd9Sstevel@tonic-gate #endif 2277c478bd9Sstevel@tonic-gate ui = (uint32_t)*ulp; 22861961e0fSrobinson return (XDR_PUTINT32(xdrs, (int32_t *)&ui)); 22961961e0fSrobinson case XDR_DECODE: 23061961e0fSrobinson if (!XDR_GETINT32(xdrs, (int32_t *)&ui)) 23161961e0fSrobinson return (FALSE); 2327c478bd9Sstevel@tonic-gate *ulp = (ulong_t)ui; 23361961e0fSrobinson return (TRUE); 23461961e0fSrobinson case XDR_FREE: 23561961e0fSrobinson return (TRUE); 23661961e0fSrobinson } 23761961e0fSrobinson return (FALSE); 2387c478bd9Sstevel@tonic-gate } 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate /* 2417c478bd9Sstevel@tonic-gate * XDR short integers 2427c478bd9Sstevel@tonic-gate */ 2437c478bd9Sstevel@tonic-gate bool_t 2447c478bd9Sstevel@tonic-gate xdr_short(XDR *xdrs, short *sp) 2457c478bd9Sstevel@tonic-gate { 2467c478bd9Sstevel@tonic-gate int32_t l; 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate switch (xdrs->x_op) { 2497c478bd9Sstevel@tonic-gate case XDR_ENCODE: 2507c478bd9Sstevel@tonic-gate l = (int32_t)*sp; 25161961e0fSrobinson return (XDR_PUTINT32(xdrs, &l)); 2527c478bd9Sstevel@tonic-gate case XDR_DECODE: 25361961e0fSrobinson if (!XDR_GETINT32(xdrs, &l)) 2547c478bd9Sstevel@tonic-gate return (FALSE); 2557c478bd9Sstevel@tonic-gate *sp = (short)l; 2567c478bd9Sstevel@tonic-gate return (TRUE); 2577c478bd9Sstevel@tonic-gate case XDR_FREE: 2587c478bd9Sstevel@tonic-gate return (TRUE); 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate return (FALSE); 2617c478bd9Sstevel@tonic-gate } 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate /* 2647c478bd9Sstevel@tonic-gate * XDR unsigned short integers 2657c478bd9Sstevel@tonic-gate */ 2667c478bd9Sstevel@tonic-gate bool_t 2677c478bd9Sstevel@tonic-gate xdr_u_short(XDR *xdrs, ushort_t *usp) 2687c478bd9Sstevel@tonic-gate { 2697c478bd9Sstevel@tonic-gate uint_t i; 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate switch (xdrs->x_op) { 2727c478bd9Sstevel@tonic-gate case XDR_ENCODE: 2737c478bd9Sstevel@tonic-gate i = (uint_t)*usp; 27461961e0fSrobinson return (XDR_PUTINT32(xdrs, (int *)&i)); 2757c478bd9Sstevel@tonic-gate case XDR_DECODE: 27661961e0fSrobinson if (!XDR_GETINT32(xdrs, (int *)&i)) 2777c478bd9Sstevel@tonic-gate return (FALSE); 2787c478bd9Sstevel@tonic-gate *usp = (ushort_t)i; 2797c478bd9Sstevel@tonic-gate return (TRUE); 2807c478bd9Sstevel@tonic-gate case XDR_FREE: 2817c478bd9Sstevel@tonic-gate return (TRUE); 2827c478bd9Sstevel@tonic-gate } 2837c478bd9Sstevel@tonic-gate return (FALSE); 2847c478bd9Sstevel@tonic-gate } 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate /* 2887c478bd9Sstevel@tonic-gate * XDR a char 2897c478bd9Sstevel@tonic-gate */ 2907c478bd9Sstevel@tonic-gate bool_t 2917c478bd9Sstevel@tonic-gate xdr_char(XDR *xdrs, char *cp) 2927c478bd9Sstevel@tonic-gate { 2937c478bd9Sstevel@tonic-gate int i; 2947c478bd9Sstevel@tonic-gate 29561961e0fSrobinson switch (xdrs->x_op) { 29661961e0fSrobinson case XDR_ENCODE: 2977c478bd9Sstevel@tonic-gate i = (*cp); 29861961e0fSrobinson return (XDR_PUTINT32(xdrs, &i)); 29961961e0fSrobinson case XDR_DECODE: 30061961e0fSrobinson if (!XDR_GETINT32(xdrs, &i)) 3017c478bd9Sstevel@tonic-gate return (FALSE); 3027c478bd9Sstevel@tonic-gate *cp = (char)i; 30361961e0fSrobinson return (TRUE); 30461961e0fSrobinson case XDR_FREE: 3057c478bd9Sstevel@tonic-gate return (TRUE); 3067c478bd9Sstevel@tonic-gate } 30761961e0fSrobinson return (FALSE); 30861961e0fSrobinson } 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate /* 3117c478bd9Sstevel@tonic-gate * XDR an unsigned char 3127c478bd9Sstevel@tonic-gate */ 3137c478bd9Sstevel@tonic-gate bool_t 3147c478bd9Sstevel@tonic-gate xdr_u_char(XDR *xdrs, uchar_t *cp) 3157c478bd9Sstevel@tonic-gate { 3167c478bd9Sstevel@tonic-gate int i; 3177c478bd9Sstevel@tonic-gate 31861961e0fSrobinson switch (xdrs->x_op) { 31961961e0fSrobinson case XDR_ENCODE: 3207c478bd9Sstevel@tonic-gate i = (*cp); 32161961e0fSrobinson return (XDR_PUTINT32(xdrs, &i)); 32261961e0fSrobinson case XDR_DECODE: 32361961e0fSrobinson if (!XDR_GETINT32(xdrs, &i)) 3247c478bd9Sstevel@tonic-gate return (FALSE); 3257c478bd9Sstevel@tonic-gate *cp = (uchar_t)i; 32661961e0fSrobinson return (TRUE); 32761961e0fSrobinson case XDR_FREE: 3287c478bd9Sstevel@tonic-gate return (TRUE); 3297c478bd9Sstevel@tonic-gate } 33061961e0fSrobinson return (FALSE); 33161961e0fSrobinson } 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate /* 3347c478bd9Sstevel@tonic-gate * XDR booleans 3357c478bd9Sstevel@tonic-gate */ 3367c478bd9Sstevel@tonic-gate bool_t 3377c478bd9Sstevel@tonic-gate xdr_bool(XDR *xdrs, bool_t *bp) 3387c478bd9Sstevel@tonic-gate { 3397c478bd9Sstevel@tonic-gate int i; 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate switch (xdrs->x_op) { 3427c478bd9Sstevel@tonic-gate case XDR_ENCODE: 3437c478bd9Sstevel@tonic-gate i = *bp ? XDR_TRUE : XDR_FALSE; 34461961e0fSrobinson return (XDR_PUTINT32(xdrs, &i)); 3457c478bd9Sstevel@tonic-gate case XDR_DECODE: 34661961e0fSrobinson if (!XDR_GETINT32(xdrs, &i)) 3477c478bd9Sstevel@tonic-gate return (FALSE); 3487c478bd9Sstevel@tonic-gate *bp = (i == XDR_FALSE) ? FALSE : TRUE; 3497c478bd9Sstevel@tonic-gate return (TRUE); 3507c478bd9Sstevel@tonic-gate case XDR_FREE: 3517c478bd9Sstevel@tonic-gate return (TRUE); 3527c478bd9Sstevel@tonic-gate } 3537c478bd9Sstevel@tonic-gate return (FALSE); 3547c478bd9Sstevel@tonic-gate } 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate /* 3577c478bd9Sstevel@tonic-gate * XDR enumerations 3587c478bd9Sstevel@tonic-gate */ 3597c478bd9Sstevel@tonic-gate bool_t 3607c478bd9Sstevel@tonic-gate xdr_enum(XDR *xdrs, enum_t *ep) 3617c478bd9Sstevel@tonic-gate { 3627c478bd9Sstevel@tonic-gate enum sizecheck { SIZEVAL }; /* used to find the size of an enum */ 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate /* 3657c478bd9Sstevel@tonic-gate * enums are treated as ints 3667c478bd9Sstevel@tonic-gate */ 36761961e0fSrobinson /* CONSTCOND */ 36861961e0fSrobinson assert(sizeof (enum sizecheck) == sizeof (int32_t)); 36961961e0fSrobinson return (xdr_int(xdrs, (int *)ep)); 3707c478bd9Sstevel@tonic-gate } 3717c478bd9Sstevel@tonic-gate 3727c478bd9Sstevel@tonic-gate /* 3737c478bd9Sstevel@tonic-gate * XDR opaque data 3747c478bd9Sstevel@tonic-gate * Allows the specification of a fixed size sequence of opaque bytes. 3757c478bd9Sstevel@tonic-gate * cp points to the opaque object and cnt gives the byte length. 3767c478bd9Sstevel@tonic-gate */ 3777c478bd9Sstevel@tonic-gate bool_t 37861961e0fSrobinson xdr_opaque(XDR *xdrs, caddr_t cp, const uint_t cnt) 3797c478bd9Sstevel@tonic-gate { 38061961e0fSrobinson uint_t rndup; 3817c478bd9Sstevel@tonic-gate char crud[BYTES_PER_XDR_UNIT]; 3827c478bd9Sstevel@tonic-gate 3837c478bd9Sstevel@tonic-gate /* 3847c478bd9Sstevel@tonic-gate * round byte count to full xdr units 3857c478bd9Sstevel@tonic-gate */ 3867c478bd9Sstevel@tonic-gate rndup = cnt % BYTES_PER_XDR_UNIT; 3877c478bd9Sstevel@tonic-gate if ((int)rndup > 0) 3887c478bd9Sstevel@tonic-gate rndup = BYTES_PER_XDR_UNIT - rndup; 3897c478bd9Sstevel@tonic-gate 39061961e0fSrobinson switch (xdrs->x_op) { 39161961e0fSrobinson case XDR_DECODE: 39261961e0fSrobinson if (!XDR_GETBYTES(xdrs, cp, cnt)) 3937c478bd9Sstevel@tonic-gate return (FALSE); 39461961e0fSrobinson if (rndup == 0) 3957c478bd9Sstevel@tonic-gate return (TRUE); 39661961e0fSrobinson return (XDR_GETBYTES(xdrs, crud, rndup)); 39761961e0fSrobinson case XDR_ENCODE: 39861961e0fSrobinson if (!XDR_PUTBYTES(xdrs, cp, cnt)) 3997c478bd9Sstevel@tonic-gate return (FALSE); 40061961e0fSrobinson if (rndup == 0) 40161961e0fSrobinson return (TRUE); 40261961e0fSrobinson return (XDR_PUTBYTES(xdrs, (caddr_t)&xdr_zero[0], rndup)); 40361961e0fSrobinson case XDR_FREE: 4047c478bd9Sstevel@tonic-gate return (TRUE); 4057c478bd9Sstevel@tonic-gate } 4067c478bd9Sstevel@tonic-gate return (FALSE); 4077c478bd9Sstevel@tonic-gate } 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate /* 4107c478bd9Sstevel@tonic-gate * XDR counted bytes 4117c478bd9Sstevel@tonic-gate * *cpp is a pointer to the bytes, *sizep is the count. 4127c478bd9Sstevel@tonic-gate * If *cpp is NULL maxsize bytes are allocated 4137c478bd9Sstevel@tonic-gate */ 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate static const char xdr_err[] = "xdr_%s: out of memory"; 4167c478bd9Sstevel@tonic-gate 4177c478bd9Sstevel@tonic-gate bool_t 41861961e0fSrobinson xdr_bytes(XDR *xdrs, char **cpp, uint_t *sizep, const uint_t maxsize) 4197c478bd9Sstevel@tonic-gate { 42061961e0fSrobinson char *sp = *cpp; /* sp is the actual string pointer */ 42161961e0fSrobinson uint_t nodesize; 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate /* 4247c478bd9Sstevel@tonic-gate * first deal with the length since xdr bytes are counted 4257c478bd9Sstevel@tonic-gate * We decided not to use MACRO XDR_U_INT here, because the 4267c478bd9Sstevel@tonic-gate * advantages here will be miniscule compared to xdr_bytes. 4277c478bd9Sstevel@tonic-gate * This saved us 100 bytes in the library size. 4287c478bd9Sstevel@tonic-gate */ 42961961e0fSrobinson if (!xdr_u_int(xdrs, sizep)) 4307c478bd9Sstevel@tonic-gate return (FALSE); 4317c478bd9Sstevel@tonic-gate nodesize = *sizep; 43261961e0fSrobinson if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) 4337c478bd9Sstevel@tonic-gate return (FALSE); 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate /* 4367c478bd9Sstevel@tonic-gate * now deal with the actual bytes 4377c478bd9Sstevel@tonic-gate */ 4387c478bd9Sstevel@tonic-gate switch (xdrs->x_op) { 4397c478bd9Sstevel@tonic-gate case XDR_DECODE: 44061961e0fSrobinson if (nodesize == 0) 4417c478bd9Sstevel@tonic-gate return (TRUE); 44261961e0fSrobinson if (sp == NULL) 44361961e0fSrobinson *cpp = sp = malloc(nodesize); 4447c478bd9Sstevel@tonic-gate if (sp == NULL) { 4457c478bd9Sstevel@tonic-gate (void) syslog(LOG_ERR, xdr_err, (const char *)"bytes"); 4467c478bd9Sstevel@tonic-gate return (FALSE); 4477c478bd9Sstevel@tonic-gate } 4487c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 4497c478bd9Sstevel@tonic-gate case XDR_ENCODE: 45061961e0fSrobinson return (xdr_opaque(xdrs, sp, nodesize)); 4517c478bd9Sstevel@tonic-gate case XDR_FREE: 4527c478bd9Sstevel@tonic-gate if (sp != NULL) { 45361961e0fSrobinson free(sp); 4547c478bd9Sstevel@tonic-gate *cpp = NULL; 4557c478bd9Sstevel@tonic-gate } 4567c478bd9Sstevel@tonic-gate return (TRUE); 4577c478bd9Sstevel@tonic-gate } 4587c478bd9Sstevel@tonic-gate return (FALSE); 4597c478bd9Sstevel@tonic-gate } 4607c478bd9Sstevel@tonic-gate 4617c478bd9Sstevel@tonic-gate /* 4627c478bd9Sstevel@tonic-gate * Implemented here due to commonality of the object. 4637c478bd9Sstevel@tonic-gate */ 4647c478bd9Sstevel@tonic-gate bool_t 4657c478bd9Sstevel@tonic-gate xdr_netobj(XDR *xdrs, struct netobj *np) 4667c478bd9Sstevel@tonic-gate { 46761961e0fSrobinson return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ)); 4687c478bd9Sstevel@tonic-gate } 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate /* 4717c478bd9Sstevel@tonic-gate * XDR a descriminated union 4727c478bd9Sstevel@tonic-gate * Support routine for discriminated unions. 4737c478bd9Sstevel@tonic-gate * You create an array of xdrdiscrim structures, terminated with 4747c478bd9Sstevel@tonic-gate * an entry with a null procedure pointer. The routine gets 4757c478bd9Sstevel@tonic-gate * the discriminant value and then searches the array of xdrdiscrims 4767c478bd9Sstevel@tonic-gate * looking for that value. It calls the procedure given in the xdrdiscrim 4777c478bd9Sstevel@tonic-gate * to handle the discriminant. If there is no specific routine a default 4787c478bd9Sstevel@tonic-gate * routine may be called. 4797c478bd9Sstevel@tonic-gate * If there is no specific or default routine an error is returned. 4807c478bd9Sstevel@tonic-gate */ 4817c478bd9Sstevel@tonic-gate bool_t 4827c478bd9Sstevel@tonic-gate xdr_union(XDR *xdrs, enum_t *dscmp, char *unp, 48361961e0fSrobinson const struct xdr_discrim *choices, const xdrproc_t dfault) 4847c478bd9Sstevel@tonic-gate { 48561961e0fSrobinson enum_t dscm; 4867c478bd9Sstevel@tonic-gate 4877c478bd9Sstevel@tonic-gate /* 4887c478bd9Sstevel@tonic-gate * we deal with the discriminator; it's an enum 4897c478bd9Sstevel@tonic-gate */ 49061961e0fSrobinson if (!xdr_enum(xdrs, dscmp)) 4917c478bd9Sstevel@tonic-gate return (FALSE); 4927c478bd9Sstevel@tonic-gate dscm = *dscmp; 4937c478bd9Sstevel@tonic-gate 4947c478bd9Sstevel@tonic-gate /* 4957c478bd9Sstevel@tonic-gate * search choices for a value that matches the discriminator. 4967c478bd9Sstevel@tonic-gate * if we find one, execute the xdr routine for that value. 4977c478bd9Sstevel@tonic-gate */ 4987c478bd9Sstevel@tonic-gate for (; choices->proc != NULL_xdrproc_t; choices++) { 49961961e0fSrobinson if (choices->value == dscm) 50061961e0fSrobinson return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED)); 5017c478bd9Sstevel@tonic-gate } 5027c478bd9Sstevel@tonic-gate 5037c478bd9Sstevel@tonic-gate /* 5047c478bd9Sstevel@tonic-gate * no match - execute the default xdr routine if there is one 5057c478bd9Sstevel@tonic-gate */ 50661961e0fSrobinson return ((dfault == NULL_xdrproc_t) ? FALSE : 50761961e0fSrobinson (*dfault)(xdrs, unp, LASTUNSIGNED)); 5087c478bd9Sstevel@tonic-gate } 5097c478bd9Sstevel@tonic-gate 5107c478bd9Sstevel@tonic-gate 5117c478bd9Sstevel@tonic-gate /* 5127c478bd9Sstevel@tonic-gate * Non-portable xdr primitives. 5137c478bd9Sstevel@tonic-gate * Care should be taken when moving these routines to new architectures. 5147c478bd9Sstevel@tonic-gate */ 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate 5177c478bd9Sstevel@tonic-gate /* 5187c478bd9Sstevel@tonic-gate * XDR null terminated ASCII strings 5197c478bd9Sstevel@tonic-gate * xdr_string deals with "C strings" - arrays of bytes that are 5207c478bd9Sstevel@tonic-gate * terminated by a NULL character. The parameter cpp references a 5217c478bd9Sstevel@tonic-gate * pointer to storage; If the pointer is null, then the necessary 5227c478bd9Sstevel@tonic-gate * storage is allocated. The last parameter is the max allowed length 5237c478bd9Sstevel@tonic-gate * of the string as specified by a protocol. 5247c478bd9Sstevel@tonic-gate */ 5257c478bd9Sstevel@tonic-gate bool_t 52661961e0fSrobinson xdr_string(XDR *xdrs, char **cpp, const uint_t maxsize) 5277c478bd9Sstevel@tonic-gate { 52861961e0fSrobinson char *newsp, *sp = *cpp; /* sp is the actual string pointer */ 5297c478bd9Sstevel@tonic-gate uint_t size, block; 5307c478bd9Sstevel@tonic-gate uint64_t bytesread; 5317c478bd9Sstevel@tonic-gate 5327c478bd9Sstevel@tonic-gate /* 5337c478bd9Sstevel@tonic-gate * first deal with the length since xdr strings are counted-strings 5347c478bd9Sstevel@tonic-gate */ 5357c478bd9Sstevel@tonic-gate switch (xdrs->x_op) { 5367c478bd9Sstevel@tonic-gate case XDR_FREE: 53761961e0fSrobinson if (sp == NULL) 5387c478bd9Sstevel@tonic-gate return (TRUE); /* already free */ 5397c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 5407c478bd9Sstevel@tonic-gate case XDR_ENCODE: 5417c478bd9Sstevel@tonic-gate size = (sp != NULL) ? (uint_t)strlen(sp) : 0; 5427c478bd9Sstevel@tonic-gate break; 5437c478bd9Sstevel@tonic-gate } 5447c478bd9Sstevel@tonic-gate /* 5457c478bd9Sstevel@tonic-gate * We decided not to use MACRO XDR_U_INT here, because the 5467c478bd9Sstevel@tonic-gate * advantages here will be miniscule compared to xdr_string. 5477c478bd9Sstevel@tonic-gate * This saved us 100 bytes in the library size. 5487c478bd9Sstevel@tonic-gate */ 54961961e0fSrobinson if (!xdr_u_int(xdrs, &size)) 5507c478bd9Sstevel@tonic-gate return (FALSE); 55161961e0fSrobinson if (size > maxsize) 5527c478bd9Sstevel@tonic-gate return (FALSE); 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate /* 5557c478bd9Sstevel@tonic-gate * now deal with the actual bytes 5567c478bd9Sstevel@tonic-gate */ 5577c478bd9Sstevel@tonic-gate switch (xdrs->x_op) { 5587c478bd9Sstevel@tonic-gate case XDR_DECODE: 5597c478bd9Sstevel@tonic-gate /* if buffer is already given, call xdr_opaque() directly */ 5607c478bd9Sstevel@tonic-gate if (sp != NULL) { 56161961e0fSrobinson if (!xdr_opaque(xdrs, sp, size)) 56261961e0fSrobinson return (FALSE); 5637c478bd9Sstevel@tonic-gate sp[size] = 0; 56461961e0fSrobinson return (TRUE); 5657c478bd9Sstevel@tonic-gate } 5667c478bd9Sstevel@tonic-gate 5677c478bd9Sstevel@tonic-gate /* 5687c478bd9Sstevel@tonic-gate * We have to allocate a buffer of size 'size'. To avoid 5697c478bd9Sstevel@tonic-gate * malloc()ing one huge chunk, we'll read the bytes in max 5707c478bd9Sstevel@tonic-gate * FRAGMENT size blocks and keep realloc()ing. 'block' is 5717c478bd9Sstevel@tonic-gate * the number of bytes to read in each xdr_opaque() and 5727c478bd9Sstevel@tonic-gate * 'bytesread' is what we have already read. sp is NULL 5737c478bd9Sstevel@tonic-gate * when we are in the loop for the first time. 5747c478bd9Sstevel@tonic-gate */ 5757c478bd9Sstevel@tonic-gate bytesread = 0; 5767c478bd9Sstevel@tonic-gate do { 5777c478bd9Sstevel@tonic-gate block = MIN(size - bytesread, FRAGMENT); 5787c478bd9Sstevel@tonic-gate /* 5797c478bd9Sstevel@tonic-gate * allocate enough for 'bytesread + block' bytes and 5807c478bd9Sstevel@tonic-gate * one extra for the terminating NULL. 5817c478bd9Sstevel@tonic-gate */ 5827c478bd9Sstevel@tonic-gate newsp = realloc(sp, bytesread + block + 1); 5837c478bd9Sstevel@tonic-gate if (newsp == NULL) { 5847c478bd9Sstevel@tonic-gate if (sp != NULL) 5857c478bd9Sstevel@tonic-gate free(sp); 5867c478bd9Sstevel@tonic-gate return (FALSE); 5877c478bd9Sstevel@tonic-gate } 5887c478bd9Sstevel@tonic-gate sp = newsp; 5897c478bd9Sstevel@tonic-gate if (!xdr_opaque(xdrs, &sp[bytesread], block)) { 5907c478bd9Sstevel@tonic-gate free(sp); 5917c478bd9Sstevel@tonic-gate return (FALSE); 5927c478bd9Sstevel@tonic-gate } 5937c478bd9Sstevel@tonic-gate bytesread += block; 5947c478bd9Sstevel@tonic-gate } while (bytesread < size); 5957c478bd9Sstevel@tonic-gate 5967c478bd9Sstevel@tonic-gate sp[bytesread] = 0; /* terminate the string with a NULL */ 5977c478bd9Sstevel@tonic-gate *cpp = sp; 5987c478bd9Sstevel@tonic-gate return (TRUE); 5997c478bd9Sstevel@tonic-gate case XDR_ENCODE: 60061961e0fSrobinson return (xdr_opaque(xdrs, sp, size)); 6017c478bd9Sstevel@tonic-gate case XDR_FREE: 6027c478bd9Sstevel@tonic-gate free(sp); 6037c478bd9Sstevel@tonic-gate *cpp = NULL; 6047c478bd9Sstevel@tonic-gate return (TRUE); 6057c478bd9Sstevel@tonic-gate } 6067c478bd9Sstevel@tonic-gate return (FALSE); 6077c478bd9Sstevel@tonic-gate } 6087c478bd9Sstevel@tonic-gate 6097c478bd9Sstevel@tonic-gate bool_t 6107c478bd9Sstevel@tonic-gate xdr_hyper(XDR *xdrs, longlong_t *hp) 6117c478bd9Sstevel@tonic-gate { 612*cb6bbb52SMarcel Telka switch (xdrs->x_op) { 613*cb6bbb52SMarcel Telka case XDR_ENCODE: 6147c478bd9Sstevel@tonic-gate #if defined(_LONG_LONG_HTOL) 61561961e0fSrobinson if (XDR_PUTINT32(xdrs, (int *)hp) == TRUE) 61661961e0fSrobinson /* LINTED pointer cast */ 61761961e0fSrobinson return (XDR_PUTINT32(xdrs, (int *)((char *)hp + 61861961e0fSrobinson BYTES_PER_XDR_UNIT))); 6197c478bd9Sstevel@tonic-gate #else 62061961e0fSrobinson /* LINTED pointer cast */ 6217c478bd9Sstevel@tonic-gate if (XDR_PUTINT32(xdrs, (int *)((char *)hp + 62261961e0fSrobinson BYTES_PER_XDR_UNIT)) == TRUE) 62361961e0fSrobinson return (XDR_PUTINT32(xdrs, (int32_t *)hp)); 62461961e0fSrobinson #endif 62561961e0fSrobinson return (FALSE); 626*cb6bbb52SMarcel Telka case XDR_DECODE: 6277c478bd9Sstevel@tonic-gate #if defined(_LONG_LONG_HTOL) 6287c478bd9Sstevel@tonic-gate if (XDR_GETINT32(xdrs, (int *)hp) == FALSE || 62961961e0fSrobinson /* LINTED pointer cast */ 6307c478bd9Sstevel@tonic-gate (XDR_GETINT32(xdrs, (int *)((char *)hp + 63161961e0fSrobinson BYTES_PER_XDR_UNIT)) == FALSE)) 6327c478bd9Sstevel@tonic-gate return (FALSE); 6337c478bd9Sstevel@tonic-gate #else 63461961e0fSrobinson /* LINTED pointer cast */ 6357c478bd9Sstevel@tonic-gate if ((XDR_GETINT32(xdrs, (int *)((char *)hp + 6367c478bd9Sstevel@tonic-gate BYTES_PER_XDR_UNIT)) == FALSE) || 63761961e0fSrobinson (XDR_GETINT32(xdrs, (int *)hp) == FALSE)) 6387c478bd9Sstevel@tonic-gate return (FALSE); 6397c478bd9Sstevel@tonic-gate #endif 6407c478bd9Sstevel@tonic-gate return (TRUE); 641*cb6bbb52SMarcel Telka case XDR_FREE: 6427c478bd9Sstevel@tonic-gate return (TRUE); 6437c478bd9Sstevel@tonic-gate } 644*cb6bbb52SMarcel Telka return (FALSE); 645*cb6bbb52SMarcel Telka } 6467c478bd9Sstevel@tonic-gate 6477c478bd9Sstevel@tonic-gate bool_t 6487c478bd9Sstevel@tonic-gate xdr_u_hyper(XDR *xdrs, u_longlong_t *hp) 6497c478bd9Sstevel@tonic-gate { 65061961e0fSrobinson return (xdr_hyper(xdrs, (longlong_t *)hp)); 6517c478bd9Sstevel@tonic-gate } 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate bool_t 6547c478bd9Sstevel@tonic-gate xdr_longlong_t(XDR *xdrs, longlong_t *hp) 6557c478bd9Sstevel@tonic-gate { 65661961e0fSrobinson return (xdr_hyper(xdrs, hp)); 6577c478bd9Sstevel@tonic-gate } 6587c478bd9Sstevel@tonic-gate 6597c478bd9Sstevel@tonic-gate bool_t 6607c478bd9Sstevel@tonic-gate xdr_u_longlong_t(XDR *xdrs, u_longlong_t *hp) 6617c478bd9Sstevel@tonic-gate { 66261961e0fSrobinson return (xdr_hyper(xdrs, (longlong_t *)hp)); 6637c478bd9Sstevel@tonic-gate } 6647c478bd9Sstevel@tonic-gate 6657c478bd9Sstevel@tonic-gate /* 6667c478bd9Sstevel@tonic-gate * Wrapper for xdr_string that can be called directly from 6677c478bd9Sstevel@tonic-gate * routines like clnt_call 6687c478bd9Sstevel@tonic-gate */ 6697c478bd9Sstevel@tonic-gate bool_t 6707c478bd9Sstevel@tonic-gate xdr_wrapstring(XDR *xdrs, char **cpp) 6717c478bd9Sstevel@tonic-gate { 67261961e0fSrobinson return (xdr_string(xdrs, cpp, LASTUNSIGNED)); 6737c478bd9Sstevel@tonic-gate } 674