/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
#include <sys/param.h>
#include <sys/types.h>
#include <sys/systm.h>
#include <sys/user.h>
#include <sys/vnode.h>
#include <sys/file.h>
#include <sys/dirent.h>
#include <sys/vfs.h>
#include <sys/stream.h>
#include <sys/strsubr.h>
#include <sys/debug.h>
#include <sys/t_lock.h>
#include <sys/sdt.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <nfs/nfs.h>
#include <vm/hat.h>
#include <vm/as.h>
#include <vm/seg.h>
#include <vm/seg_map.h>
#include <vm/seg_kmem.h>
static bool_t xdr_fastshorten(XDR *, uint_t);
/*
* These are the XDR routines used to serialize and deserialize
* the various structures passed as parameters accross the network
* between NFS clients and servers.
*/
/*
* File access handle
* The fhandle struct is treated a opaque data on the wire
*/
bool_t
xdr_fhandle(XDR *xdrs, fhandle_t *fh)
{
int32_t *ptr;
int32_t *fhp;
if (xdrs->x_op == XDR_FREE)
return (TRUE);
ptr = XDR_INLINE(xdrs, RNDUP(sizeof (fhandle_t)));
if (ptr != NULL) {
fhp = (int32_t *)fh;
if (xdrs->x_op == XDR_DECODE) {
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp = *ptr;
} else {
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr = *fhp;
}
return (TRUE);
}
return (xdr_opaque(xdrs, (caddr_t)fh, NFS_FHSIZE));
}
bool_t
xdr_fastfhandle(XDR *xdrs, fhandle_t **fh)
{
int32_t *ptr;
if (xdrs->x_op != XDR_DECODE)
return (FALSE);
ptr = XDR_INLINE(xdrs, RNDUP(sizeof (fhandle_t)));
if (ptr != NULL) {
*fh = (fhandle_t *)ptr;
return (TRUE);
}
return (FALSE);
}
/*
* Arguments to remote write and writecache
*/
bool_t
xdr_writeargs(XDR *xdrs, struct nfswriteargs *wa)
{
int32_t *ptr;
int32_t *fhp;
switch (xdrs->x_op) {
case XDR_DECODE:
wa->wa_args = &wa->wa_args_buf;
ptr = XDR_INLINE(xdrs, RNDUP(sizeof (fhandle_t)) +
3 * BYTES_PER_XDR_UNIT);
if (ptr != NULL) {
fhp = (int32_t *)&wa->wa_fhandle;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp = *ptr++;
wa->wa_begoff = IXDR_GET_U_INT32(ptr);
wa->wa_offset = IXDR_GET_U_INT32(ptr);
wa->wa_totcount = IXDR_GET_U_INT32(ptr);
wa->wa_mblk = NULL;
wa->wa_data = NULL;
wa->wa_rlist = NULL;
wa->wa_conn = NULL;
if (xdrs->x_ops == &xdrmblk_ops) {
return (xdrmblk_getmblk(xdrs, &wa->wa_mblk,
&wa->wa_count));
} else {
if (xdrs->x_ops == &xdrrdmablk_ops) {
if (xdrrdma_getrdmablk(xdrs,
&wa->wa_rlist,
&wa->wa_count,
&wa->wa_conn,
NFS_MAXDATA) == TRUE)
return (xdrrdma_read_from_client(
wa->wa_rlist,
&wa->wa_conn,
wa->wa_count));
wa->wa_rlist = NULL;
wa->wa_conn = NULL;
}
}
/*
* It is just as efficient to xdr_bytes
* an array of unknown length as to inline copy it.
*/
return (xdr_bytes(xdrs, &wa->wa_data,
&wa->wa_count, NFS_MAXDATA));
}
if (xdr_fhandle(xdrs, &wa->wa_fhandle) &&
xdr_u_int(xdrs, &wa->wa_begoff) &&
xdr_u_int(xdrs, &wa->wa_offset) &&
xdr_u_int(xdrs, &wa->wa_totcount)) {
/* deal with the variety of data transfer types */
wa->wa_mblk = NULL;
wa->wa_data = NULL;
wa->wa_rlist = NULL;
wa->wa_conn = NULL;
if (xdrs->x_ops == &xdrmblk_ops) {
if (xdrmblk_getmblk(xdrs, &wa->wa_mblk,
&wa->wa_count) == TRUE)
return (TRUE);
} else {
if (xdrs->x_ops == &xdrrdmablk_ops) {
if (xdrrdma_getrdmablk(xdrs,
&wa->wa_rlist,
&wa->wa_count,
&wa->wa_conn,
NFS_MAXDATA) == TRUE)
return (xdrrdma_read_from_client(
wa->wa_rlist,
&wa->wa_conn,
wa->wa_count));
wa->wa_rlist = NULL;
wa->wa_conn = NULL;
}
}
return (xdr_bytes(xdrs, &wa->wa_data,
&wa->wa_count, NFS_MAXDATA));
}
return (FALSE);
case XDR_ENCODE:
ptr = XDR_INLINE(xdrs, RNDUP(sizeof (fhandle_t)) +
3 * BYTES_PER_XDR_UNIT);
if (ptr != NULL) {
fhp = (int32_t *)&wa->wa_fhandle;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp;
IXDR_PUT_U_INT32(ptr, wa->wa_begoff);
IXDR_PUT_U_INT32(ptr, wa->wa_offset);
IXDR_PUT_U_INT32(ptr, wa->wa_totcount);
} else {
if (!(xdr_fhandle(xdrs, &wa->wa_fhandle) &&
xdr_u_int(xdrs, &wa->wa_begoff) &&
xdr_u_int(xdrs, &wa->wa_offset) &&
xdr_u_int(xdrs, &wa->wa_totcount)))
return (FALSE);
}
return (xdr_bytes(xdrs, &wa->wa_data, &wa->wa_count,
NFS_MAXDATA));
case XDR_FREE:
if (wa->wa_rlist) {
(void) xdrrdma_free_clist(wa->wa_conn, wa->wa_rlist);
wa->wa_rlist = NULL;
}
if (wa->wa_data != NULL) {
kmem_free(wa->wa_data, wa->wa_count);
wa->wa_data = NULL;
}
return (TRUE);
}
return (FALSE);
}
/*
* File attributes
*/
bool_t
xdr_fattr(XDR *xdrs, struct nfsfattr *na)
{
int32_t *ptr;
if (xdrs->x_op == XDR_FREE)
return (TRUE);
ptr = XDR_INLINE(xdrs, 17 * BYTES_PER_XDR_UNIT);
if (ptr != NULL) {
if (xdrs->x_op == XDR_DECODE) {
na->na_type = IXDR_GET_ENUM(ptr, enum nfsftype);
na->na_mode = IXDR_GET_U_INT32(ptr);
na->na_nlink = IXDR_GET_U_INT32(ptr);
na->na_uid = IXDR_GET_U_INT32(ptr);
na->na_gid = IXDR_GET_U_INT32(ptr);
na->na_size = IXDR_GET_U_INT32(ptr);
na->na_blocksize = IXDR_GET_U_INT32(ptr);
na->na_rdev = IXDR_GET_U_INT32(ptr);
na->na_blocks = IXDR_GET_U_INT32(ptr);
na->na_fsid = IXDR_GET_U_INT32(ptr);
na->na_nodeid = IXDR_GET_U_INT32(ptr);
na->na_atime.tv_sec = IXDR_GET_U_INT32(ptr);
na->na_atime.tv_usec = IXDR_GET_U_INT32(ptr);
na->na_mtime.tv_sec = IXDR_GET_U_INT32(ptr);
na->na_mtime.tv_usec = IXDR_GET_U_INT32(ptr);
na->na_ctime.tv_sec = IXDR_GET_U_INT32(ptr);
na->na_ctime.tv_usec = IXDR_GET_U_INT32(ptr);
} else {
IXDR_PUT_ENUM(ptr, na->na_type);
IXDR_PUT_U_INT32(ptr, na->na_mode);
IXDR_PUT_U_INT32(ptr, na->na_nlink);
IXDR_PUT_U_INT32(ptr, na->na_uid);
IXDR_PUT_U_INT32(ptr, na->na_gid);
IXDR_PUT_U_INT32(ptr, na->na_size);
IXDR_PUT_U_INT32(ptr, na->na_blocksize);
IXDR_PUT_U_INT32(ptr, na->na_rdev);
IXDR_PUT_U_INT32(ptr, na->na_blocks);
IXDR_PUT_U_INT32(ptr, na->na_fsid);
IXDR_PUT_U_INT32(ptr, na->na_nodeid);
IXDR_PUT_U_INT32(ptr, na->na_atime.tv_sec);
IXDR_PUT_U_INT32(ptr, na->na_atime.tv_usec);
IXDR_PUT_U_INT32(ptr, na->na_mtime.tv_sec);
IXDR_PUT_U_INT32(ptr, na->na_mtime.tv_usec);
IXDR_PUT_U_INT32(ptr, na->na_ctime.tv_sec);
IXDR_PUT_U_INT32(ptr, na->na_ctime.tv_usec);
}
return (TRUE);
}
if (xdr_enum(xdrs, (enum_t *)&na->na_type) &&
xdr_u_int(xdrs, &na->na_mode) &&
xdr_u_int(xdrs, &na->na_nlink) &&
xdr_u_int(xdrs, &na->na_uid) &&
xdr_u_int(xdrs, &na->na_gid) &&
xdr_u_int(xdrs, &na->na_size) &&
xdr_u_int(xdrs, &na->na_blocksize) &&
xdr_u_int(xdrs, &na->na_rdev) &&
xdr_u_int(xdrs, &na->na_blocks) &&
xdr_u_int(xdrs, &na->na_fsid) &&
xdr_u_int(xdrs, &na->na_nodeid) &&
xdr_nfs2_timeval(xdrs, &na->na_atime) &&
xdr_nfs2_timeval(xdrs, &na->na_mtime) &&
xdr_nfs2_timeval(xdrs, &na->na_ctime)) {
return (TRUE);
}
return (FALSE);
}
#ifdef _LITTLE_ENDIAN
bool_t
xdr_fastfattr(XDR *xdrs, struct nfsfattr *na)
{
if (xdrs->x_op == XDR_FREE)
return (TRUE);
if (xdrs->x_op == XDR_DECODE)
return (FALSE);
na->na_type = htonl(na->na_type);
na->na_mode = htonl(na->na_mode);
na->na_nlink = htonl(na->na_nlink);
na->na_uid = htonl(na->na_uid);
na->na_gid = htonl(na->na_gid);
na->na_size = htonl(na->na_size);
na->na_blocksize = htonl(na->na_blocksize);
na->na_rdev = htonl(na->na_rdev);
na->na_blocks = htonl(na->na_blocks);
na->na_fsid = htonl(na->na_fsid);
na->na_nodeid = htonl(na->na_nodeid);
na->na_atime.tv_sec = htonl(na->na_atime.tv_sec);
na->na_atime.tv_usec = htonl(na->na_atime.tv_usec);
na->na_mtime.tv_sec = htonl(na->na_mtime.tv_sec);
na->na_mtime.tv_usec = htonl(na->na_mtime.tv_usec);
na->na_ctime.tv_sec = htonl(na->na_ctime.tv_sec);
na->na_ctime.tv_usec = htonl(na->na_ctime.tv_usec);
return (TRUE);
}
#endif
bool_t
xdr_readlink(XDR *xdrs, fhandle_t *fh)
{
rdma_chunkinfo_t rci;
struct xdr_ops *xops = xdrrdma_xops();
if (xdr_fhandle(xdrs, fh)) {
if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
xdrs->x_op == XDR_ENCODE) {
rci.rci_type = RCI_REPLY_CHUNK;
rci.rci_len = MAXPATHLEN;
XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
}
return (TRUE);
}
return (FALSE);
}
/*
* Arguments to remote read
*/
bool_t
xdr_readargs(XDR *xdrs, struct nfsreadargs *ra)
{
int32_t *ptr;
int32_t *fhp;
rdma_chunkinfo_t rci;
rdma_wlist_conn_info_t rwci;
struct xdr_ops *xops = xdrrdma_xops();
if (xdrs->x_op == XDR_FREE)
return (TRUE);
ptr = XDR_INLINE(xdrs,
RNDUP(sizeof (fhandle_t)) + 3 * BYTES_PER_XDR_UNIT);
if (ptr != NULL) {
if (xdrs->x_op == XDR_DECODE) {
fhp = (int32_t *)&ra->ra_fhandle;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp = *ptr++;
ra->ra_offset = IXDR_GET_INT32(ptr);
ra->ra_count = IXDR_GET_INT32(ptr);
ra->ra_totcount = IXDR_GET_INT32(ptr);
} else {
fhp = (int32_t *)&ra->ra_fhandle;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp;
IXDR_PUT_INT32(ptr, ra->ra_offset);
IXDR_PUT_INT32(ptr, ra->ra_count);
IXDR_PUT_INT32(ptr, ra->ra_totcount);
}
} else {
if (!xdr_fhandle(xdrs, &ra->ra_fhandle) ||
!xdr_u_int(xdrs, &ra->ra_offset) ||
!xdr_u_int(xdrs, &ra->ra_count) ||
!xdr_u_int(xdrs, &ra->ra_totcount)) {
return (FALSE);
}
}
if (ra->ra_count > NFS_MAXDATA)
return (FALSE);
ra->ra_wlist = NULL;
ra->ra_conn = NULL;
/* If this is xdrrdma_sizeof, record the expect response size */
if (xdrs->x_ops == xops && xdrs->x_op == XDR_ENCODE) {
rci.rci_type = RCI_WRITE_ADDR_CHUNK;
rci.rci_len = ra->ra_count;
(void) XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
}
/* Nothing special to do, return */
if (xdrs->x_ops != &xdrrdma_ops || xdrs->x_op == XDR_FREE)
return (TRUE);
if (xdrs->x_op == XDR_ENCODE) {
/* Place the target data location into the RDMA header */
rci.rci_type = RCI_WRITE_ADDR_CHUNK;
rci.rci_a.rci_addr = ra->ra_data;
rci.rci_len = ra->ra_count;
rci.rci_clpp = &ra->ra_wlist;
return (XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci));
}
/* XDR_DECODE case */
(void) XDR_CONTROL(xdrs, XDR_RDMA_GET_WCINFO, &rwci);
ra->ra_wlist = rwci.rwci_wlist;
ra->ra_conn = rwci.rwci_conn;
return (TRUE);
}
/*
* Status OK portion of remote read reply
*/
bool_t
xdr_rrok(XDR *xdrs, struct nfsrrok *rrok)
{
bool_t ret;
mblk_t *mp;
struct xdr_ops *xops = xdrrdma_xops();
if (xdr_fattr(xdrs, &rrok->rrok_attr) == FALSE)
return (FALSE);
/* deal with RDMA separately */
if (xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) {
if (xdrs->x_op == XDR_ENCODE &&
rrok->rrok_mp != NULL) {
ret = xdr_bytes(xdrs, (char **)&rrok->rrok_data,
&rrok->rrok_count, NFS_MAXDATA);
return (ret);
}
if (xdrs->x_op == XDR_ENCODE) {
if (xdr_u_int(xdrs, &rrok->rrok_count) == FALSE) {
return (FALSE);
}
/*
* If read data sent by wlist (RDMA_WRITE), don't do
* xdr_bytes() below. RDMA_WRITE transfers the data.
*/
if (rrok->rrok_wlist) {
if (rrok->rrok_count != 0) {
return (xdrrdma_send_read_data(
xdrs, rrok->rrok_count,
rrok->rrok_wlist));
}
return (TRUE);
}
if (rrok->rrok_count == 0) {
return (TRUE);
}
} else {
struct clist *cl;
uint32_t count;
XDR_CONTROL(xdrs, XDR_RDMA_GET_WLIST, &cl);
if (cl) {
if (!xdr_u_int(xdrs, &count))
return (FALSE);
if (count == 0) {
rrok->rrok_wlist_len = 0;
rrok->rrok_count = 0;
} else {
rrok->rrok_wlist_len = clist_len(cl);
if (rrok->rrok_wlist_len !=
roundup(count,
BYTES_PER_XDR_UNIT)) {
rrok->rrok_wlist_len = 0;
rrok->rrok_count = 0;
return (FALSE);
}
rrok->rrok_count = count;
}
return (TRUE);
}
}
ret = xdr_bytes(xdrs, (char **)&rrok->rrok_data,
&rrok->rrok_count, NFS_MAXDATA);
return (ret);
}
if (xdrs->x_op == XDR_ENCODE) {
int i, rndup;
mp = rrok->rrok_mp;
if (mp != NULL && xdrs->x_ops == &xdrmblk_ops) {
mp->b_wptr += rrok->rrok_count;
rndup = BYTES_PER_XDR_UNIT -
(rrok->rrok_count % BYTES_PER_XDR_UNIT);
if (rndup != BYTES_PER_XDR_UNIT)
for (i = 0; i < rndup; i++)
*mp->b_wptr++ = '\0';
if (xdrmblk_putmblk(xdrs, mp,
rrok->rrok_count) == TRUE) {
rrok->rrok_mp = NULL;
return (TRUE);
}
}
/*
* Fall thru for the xdr_bytes()
*
* Note: the mblk mp will be freed in rfs_rdfree
*/
}
ret = xdr_bytes(xdrs, (char **)&rrok->rrok_data,
&rrok->rrok_count, NFS_MAXDATA);
return (ret);
}
static struct xdr_discrim rdres_discrim[2] = {
{ NFS_OK, xdr_rrok },
{ __dontcare__, NULL_xdrproc_t }
};
/*
* Reply from remote read
*/
bool_t
xdr_rdresult(XDR *xdrs, struct nfsrdresult *rr)
{
return (xdr_union(xdrs, (enum_t *)&(rr->rr_status),
(caddr_t)&(rr->rr_ok), rdres_discrim, xdr_void));
}
/*
* File attributes which can be set
*/
bool_t
xdr_sattr(XDR *xdrs, struct nfssattr *sa)
{
if (xdr_u_int(xdrs, &sa->sa_mode) &&
xdr_u_int(xdrs, &sa->sa_uid) &&
xdr_u_int(xdrs, &sa->sa_gid) &&
xdr_u_int(xdrs, &sa->sa_size) &&
xdr_nfs2_timeval(xdrs, &sa->sa_atime) &&
xdr_nfs2_timeval(xdrs, &sa->sa_mtime)) {
return (TRUE);
}
return (FALSE);
}
static struct xdr_discrim attrstat_discrim[2] = {
{ (int)NFS_OK, xdr_fattr },
{ __dontcare__, NULL_xdrproc_t }
};
/*
* Reply status with file attributes
*/
bool_t
xdr_attrstat(XDR *xdrs, struct nfsattrstat *ns)
{
return (xdr_union(xdrs, (enum_t *)&(ns->ns_status),
(caddr_t)&(ns->ns_attr), attrstat_discrim, xdr_void));
}
/*
* Fast reply status with file attributes
*/
bool_t
xdr_fastattrstat(XDR *xdrs, struct nfsattrstat *ns)
{
#if defined(_LITTLE_ENDIAN)
/*
* we deal with the discriminator; it's an enum
*/
if (!xdr_fastenum(xdrs, (enum_t *)&ns->ns_status))
return (FALSE);
if (ns->ns_status == NFS_OK)
return (xdr_fastfattr(xdrs, &ns->ns_attr));
#elif defined(_BIG_ENDIAN)
if (ns->ns_status == NFS_OK)
return (TRUE);
#endif
return (xdr_fastshorten(xdrs, sizeof (*ns)));
}
/*
* NFS_OK part of read sym link reply union
*/
bool_t
xdr_srok(XDR *xdrs, struct nfssrok *srok)
{
/*
* It is just as efficient to xdr_bytes
* an array of unknown length as to inline copy it.
*/
return (xdr_bytes(xdrs, &srok->srok_data, &srok->srok_count,
NFS_MAXPATHLEN));
}
static struct xdr_discrim rdlnres_discrim[2] = {
{ (int)NFS_OK, xdr_srok },
{ __dontcare__, NULL_xdrproc_t }
};
/*
* Result of reading symbolic link
*/
bool_t
xdr_rdlnres(XDR *xdrs, struct nfsrdlnres *rl)
{
return (xdr_union(xdrs, (enum_t *)&(rl->rl_status),
(caddr_t)&(rl->rl_srok), rdlnres_discrim, xdr_void));
}
/*
* Arguments to readdir
*/
bool_t
xdr_rddirargs(XDR *xdrs, struct nfsrddirargs *rda)
{
int32_t *ptr;
int32_t *fhp;
rdma_chunkinfo_t rci;
struct xdr_ops *xops = xdrrdma_xops();
if (xdrs->x_op == XDR_FREE)
return (TRUE);
ptr = XDR_INLINE(xdrs,
RNDUP(sizeof (fhandle_t)) + 2 * BYTES_PER_XDR_UNIT);
if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
xdrs->x_op == XDR_ENCODE) {
rci.rci_type = RCI_REPLY_CHUNK;
rci.rci_len = rda->rda_count;
XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
}
if (ptr != NULL) {
if (xdrs->x_op == XDR_DECODE) {
fhp = (int32_t *)&rda->rda_fh;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp = *ptr++;
rda->rda_offset = IXDR_GET_U_INT32(ptr);
rda->rda_count = IXDR_GET_U_INT32(ptr);
} else {
fhp = (int32_t *)&rda->rda_fh;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp;
IXDR_PUT_U_INT32(ptr, rda->rda_offset);
IXDR_PUT_U_INT32(ptr, rda->rda_count);
}
return (TRUE);
}
if (xdr_fhandle(xdrs, &rda->rda_fh) &&
xdr_u_int(xdrs, &rda->rda_offset) &&
xdr_u_int(xdrs, &rda->rda_count)) {
return (TRUE);
}
return (FALSE);
}
/*
* Directory read reply:
* union (enum status) {
* NFS_OK: entlist;
* boolean eof;
* default:
* }
*
* Directory entries
* struct direct {
* off_t d_off; * offset of next entry *
* u_int d_fileno; * inode number of entry *
* u_short d_reclen; * length of this record *
* u_short d_namlen; * length of string in d_name *
* char d_name[MAXNAMLEN + 1]; * name no longer than this *
* };
* are on the wire as:
* union entlist (boolean valid) {
* TRUE: struct otw_dirent;
* u_int nxtoffset;
* union entlist;
* FALSE:
* }
* where otw_dirent is:
* struct dirent {
* u_int de_fid;
* string de_name<NFS_MAXNAMELEN>;
* }
*/
#ifdef nextdp
#undef nextdp
#endif
#define nextdp(dp) ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
#ifdef roundup
#undef roundup
#endif
#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
/*
* ENCODE ONLY
*/
bool_t
xdr_putrddirres(XDR *xdrs, struct nfsrddirres *rd)
{
struct dirent64 *dp;
char *name;
int size;
uint_t namlen;
bool_t true = TRUE;
bool_t false = FALSE;
int entrysz;
int tofit;
int bufsize;
uint32_t ino, off;
if (xdrs->x_op != XDR_ENCODE)
return (FALSE);
if (!xdr_enum(xdrs, (enum_t *)&rd->rd_status))
return (FALSE);
if (rd->rd_status != NFS_OK)
return (TRUE);
bufsize = 1 * BYTES_PER_XDR_UNIT;
for (size = rd->rd_size, dp = rd->rd_entries;
size > 0;
size -= dp->d_reclen, dp = nextdp(dp)) {
if (dp->d_reclen == 0 /* || DIRSIZ(dp) > dp->d_reclen */)
return (FALSE);
if (dp->d_ino == 0)
continue;
ino = (uint32_t)dp->d_ino; /* for LP64 we clip the bits */
if (dp->d_ino != (ino64_t)ino) /* and they better be zeros */
return (FALSE);
off = (uint32_t)dp->d_off;
name = dp->d_name;
namlen = (uint_t)strlen(name);
entrysz = (1 + 1 + 1 + 1) * BYTES_PER_XDR_UNIT +
roundup(namlen, BYTES_PER_XDR_UNIT);
tofit = entrysz + 2 * BYTES_PER_XDR_UNIT;
if (bufsize + tofit > rd->rd_bufsize) {
rd->rd_eof = FALSE;
break;
}
if (!xdr_bool(xdrs, &true) ||
!xdr_u_int(xdrs, &ino) ||
!xdr_bytes(xdrs, &name, &namlen, NFS_MAXNAMLEN) ||
!xdr_u_int(xdrs, &off)) {
return (FALSE);
}
bufsize += entrysz;
}
if (!xdr_bool(xdrs, &false))
return (FALSE);
if (!xdr_bool(xdrs, &rd->rd_eof))
return (FALSE);
return (TRUE);
}
/*
* DECODE ONLY
*/
bool_t
xdr_getrddirres(XDR *xdrs, struct nfsrddirres *rd)
{
struct dirent64 *dp;
uint_t namlen;
int size;
bool_t valid;
uint32_t offset;
uint_t fileid, this_reclen;
if (xdrs->x_op != XDR_DECODE)
return (FALSE);
if (!xdr_enum(xdrs, (enum_t *)&rd->rd_status))
return (FALSE);
if (rd->rd_status != NFS_OK)
return (TRUE);
size = rd->rd_size;
dp = rd->rd_entries;
offset = rd->rd_offset;
for (;;) {
if (!xdr_bool(xdrs, &valid))
return (FALSE);
if (!valid)
break;
if (!xdr_u_int(xdrs, &fileid) ||
!xdr_u_int(xdrs, &namlen))
return (FALSE);
this_reclen = DIRENT64_RECLEN(namlen);
if (this_reclen > size) {
rd->rd_eof = FALSE;
goto bufovflw;
}
if (!xdr_opaque(xdrs, dp->d_name, namlen)||
!xdr_u_int(xdrs, &offset)) {
return (FALSE);
}
bzero(&dp->d_name[namlen],
DIRENT64_NAMELEN(this_reclen) - namlen);
dp->d_ino = (ino64_t)fileid;
dp->d_reclen = this_reclen;
dp->d_off = (off64_t)offset;
size -= dp->d_reclen;
dp = nextdp(dp);
}
if (!xdr_bool(xdrs, &rd->rd_eof))
return (FALSE);
bufovflw:
rd->rd_size = (uint32_t)((char *)dp - (char *)(rd->rd_entries));
rd->rd_offset = offset;
return (TRUE);
}
/*
* Arguments for directory operations
*/
bool_t
xdr_diropargs(XDR *xdrs, struct nfsdiropargs *da)
{
int32_t *ptr;
int32_t *fhp;
uint32_t size;
uint32_t nodesize;
int i;
int rndup;
char *cptr;
if (xdrs->x_op == XDR_DECODE) {
da->da_fhandle = &da->da_fhandle_buf;
ptr = XDR_INLINE(xdrs, RNDUP(sizeof (fhandle_t)) +
1 * BYTES_PER_XDR_UNIT);
if (ptr != NULL) {
fhp = (int32_t *)da->da_fhandle;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp = *ptr++;
size = IXDR_GET_U_INT32(ptr);
if (size > NFS_MAXNAMLEN)
return (FALSE);
nodesize = size + 1;
if (nodesize == 0)
return (TRUE);
if (da->da_name == NULL) {
da->da_name = kmem_alloc(nodesize, KM_NOSLEEP);
if (da->da_name == NULL)
return (FALSE);
da->da_flags |= DA_FREENAME;
}
ptr = XDR_INLINE(xdrs, RNDUP(size));
if (ptr == NULL) {
if (!xdr_opaque(xdrs, da->da_name, size)) {
if (da->da_flags & DA_FREENAME) {
kmem_free(da->da_name,
nodesize);
da->da_name = NULL;
}
return (FALSE);
}
da->da_name[size] = '\0';
if (strlen(da->da_name) != size) {
if (da->da_flags & DA_FREENAME) {
kmem_free(da->da_name,
nodesize);
da->da_name = NULL;
}
return (FALSE);
}
return (TRUE);
}
bcopy(ptr, da->da_name, size);
da->da_name[size] = '\0';
if (strlen(da->da_name) != size) {
if (da->da_flags & DA_FREENAME) {
kmem_free(da->da_name, nodesize);
da->da_name = NULL;
}
return (FALSE);
}
return (TRUE);
}
if (da->da_name == NULL)
da->da_flags |= DA_FREENAME;
}
if (xdrs->x_op == XDR_ENCODE) {
size = (uint32_t)strlen(da->da_name);
if (size > NFS_MAXNAMLEN)
return (FALSE);
ptr = XDR_INLINE(xdrs, (int)(RNDUP(sizeof (fhandle_t)) +
1 * BYTES_PER_XDR_UNIT + RNDUP(size)));
if (ptr != NULL) {
fhp = (int32_t *)da->da_fhandle;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp;
IXDR_PUT_U_INT32(ptr, (uint32_t)size);
bcopy(da->da_name, ptr, size);
rndup = BYTES_PER_XDR_UNIT -
(size % BYTES_PER_XDR_UNIT);
if (rndup != BYTES_PER_XDR_UNIT) {
cptr = (char *)ptr + size;
for (i = 0; i < rndup; i++)
*cptr++ = '\0';
}
return (TRUE);
}
}
if (xdrs->x_op == XDR_FREE) {
if (da->da_name == NULL)
return (TRUE);
size = (uint32_t)strlen(da->da_name);
if (size > NFS_MAXNAMLEN)
return (FALSE);
if (da->da_flags & DA_FREENAME)
kmem_free(da->da_name, size + 1);
da->da_name = NULL;
return (TRUE);
}
if (xdr_fhandle(xdrs, da->da_fhandle) &&
xdr_string(xdrs, &da->da_name, NFS_MAXNAMLEN)) {
return (TRUE);
}
return (FALSE);
}
/*
* NFS_OK part of directory operation result
*/
bool_t
xdr_drok(XDR *xdrs, struct nfsdrok *drok)
{
int32_t *ptr;
int32_t *fhp;
struct nfsfattr *na;
if (xdrs->x_op == XDR_FREE)
return (TRUE);
ptr = XDR_INLINE(xdrs,
RNDUP(sizeof (fhandle_t)) + 17 * BYTES_PER_XDR_UNIT);
if (ptr != NULL) {
if (xdrs->x_op == XDR_DECODE) {
fhp = (int32_t *)&drok->drok_fhandle;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp++ = *ptr++;
*fhp = *ptr++;
na = &drok->drok_attr;
na->na_type = IXDR_GET_ENUM(ptr, enum nfsftype);
na->na_mode = IXDR_GET_U_INT32(ptr);
na->na_nlink = IXDR_GET_U_INT32(ptr);
na->na_uid = IXDR_GET_U_INT32(ptr);
na->na_gid = IXDR_GET_U_INT32(ptr);
na->na_size = IXDR_GET_U_INT32(ptr);
na->na_blocksize = IXDR_GET_U_INT32(ptr);
na->na_rdev = IXDR_GET_U_INT32(ptr);
na->na_blocks = IXDR_GET_U_INT32(ptr);
na->na_fsid = IXDR_GET_U_INT32(ptr);
na->na_nodeid = IXDR_GET_U_INT32(ptr);
na->na_atime.tv_sec = IXDR_GET_U_INT32(ptr);
na->na_atime.tv_usec = IXDR_GET_U_INT32(ptr);
na->na_mtime.tv_sec = IXDR_GET_U_INT32(ptr);
na->na_mtime.tv_usec = IXDR_GET_U_INT32(ptr);
na->na_ctime.tv_sec = IXDR_GET_U_INT32(ptr);
na->na_ctime.tv_usec = IXDR_GET_U_INT32(ptr);
} else {
fhp = (int32_t *)&drok->drok_fhandle;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp++;
*ptr++ = *fhp;
na = &drok->drok_attr;
IXDR_PUT_ENUM(ptr, na->na_type);
IXDR_PUT_U_INT32(ptr, na->na_mode);
IXDR_PUT_U_INT32(ptr, na->na_nlink);
IXDR_PUT_U_INT32(ptr, na->na_uid);
IXDR_PUT_U_INT32(ptr, na->na_gid);
IXDR_PUT_U_INT32(ptr, na->na_size);
IXDR_PUT_U_INT32(ptr, na->na_blocksize);
IXDR_PUT_U_INT32(ptr, na->na_rdev);
IXDR_PUT_U_INT32(ptr, na->na_blocks);
IXDR_PUT_U_INT32(ptr, na->na_fsid);
IXDR_PUT_U_INT32(ptr, na->na_nodeid);
IXDR_PUT_U_INT32(ptr, na->na_atime.tv_sec);
IXDR_PUT_U_INT32(ptr, na->na_atime.tv_usec);
IXDR_PUT_U_INT32(ptr, na->na_mtime.tv_sec);
IXDR_PUT_U_INT32(ptr, na->na_mtime.tv_usec);
IXDR_PUT_U_INT32(ptr, na->na_ctime.tv_sec);
IXDR_PUT_U_INT32(ptr, na->na_ctime.tv_usec);
}
return (TRUE);
}
if (xdr_fhandle(xdrs, &drok->drok_fhandle) &&
xdr_fattr(xdrs, &drok->drok_attr)) {
return (TRUE);
}
return (FALSE);
}
#ifdef _LITTLE_ENDIAN
bool_t
xdr_fastdrok(XDR *xdrs, struct nfsdrok *drok)
{
struct nfsfattr *na;
if (xdrs->x_op == XDR_FREE)
return (TRUE);
if (xdrs->x_op == XDR_DECODE)
return (FALSE);
na = &drok->drok_attr;
na->na_type = (enum nfsftype)htonl(na->na_type);
na->na_mode = (uint32_t)htonl(na->na_mode);
na->na_nlink = (uint32_t)htonl(na->na_nlink);
na->na_uid = (uint32_t)htonl(na->na_uid);
na->na_gid = (uint32_t)htonl(na->na_gid);
na->na_size = (uint32_t)htonl(na->na_size);
na->na_blocksize = (uint32_t)htonl(na->na_blocksize);
na->na_rdev = (uint32_t)htonl(na->na_rdev);
na->na_blocks = (uint32_t)htonl(na->na_blocks);
na->na_fsid = (uint32_t)htonl(na->na_fsid);
na->na_nodeid = (uint32_t)htonl(na->na_nodeid);
na->na_atime.tv_sec = htonl(na->na_atime.tv_sec);
na->na_atime.tv_usec = htonl(na->na_atime.tv_usec);
na->na_mtime.tv_sec = htonl(na->na_mtime.tv_sec);
na->na_mtime.tv_usec = htonl(na->na_mtime.tv_usec);
na->na_ctime.tv_sec = htonl(na->na_ctime.tv_sec);
na->na_ctime.tv_usec = htonl(na->na_ctime.tv_usec);
return (TRUE);
}
#endif
static struct xdr_discrim diropres_discrim[2] = {
{ NFS_OK, xdr_drok },
{ __dontcare__, NULL_xdrproc_t }
};
/*
* Results from directory operation
*/
bool_t
xdr_diropres(XDR *xdrs, struct nfsdiropres *dr)
{
return (xdr_union(xdrs, (enum_t *)&(dr->dr_status),
(caddr_t)&(dr->dr_drok), diropres_discrim, xdr_void));
}
/*
* Results from directory operation
*/
bool_t
xdr_fastdiropres(XDR *xdrs, struct nfsdiropres *dr)
{
#if defined(_LITTLE_ENDIAN)
/*
* we deal with the discriminator; it's an enum
*/
if (!xdr_fastenum(xdrs, (enum_t *)&dr->dr_status))
return (FALSE);
if (dr->dr_status == NFS_OK)
return (xdr_fastdrok(xdrs, &dr->dr_drok));
#elif defined(_BIG_ENDIAN)
if (dr->dr_status == NFS_OK)
return (TRUE);
#endif
return (xdr_fastshorten(xdrs, sizeof (*dr)));
}
/*
* Time Structure, unsigned
*/
bool_t
xdr_nfs2_timeval(XDR *xdrs, struct nfs2_timeval *tv)
{
if (xdr_u_int(xdrs, &tv->tv_sec) &&
xdr_u_int(xdrs, &tv->tv_usec))
return (TRUE);
return (FALSE);
}
/*
* arguments to setattr
*/
bool_t
xdr_saargs(XDR *xdrs, struct nfssaargs *argp)
{
int32_t *ptr;
int32_t *arg;
struct nfssattr *sa;
if (xdrs->x_op == XDR_FREE)
return (TRUE);
ptr = XDR_INLINE(xdrs,
RNDUP(sizeof (fhandle_t)) + 8 * BYTES_PER_XDR_UNIT);
if (ptr != NULL) {
if (xdrs->x_op == XDR_DECODE) {
arg = (int32_t *)&argp->saa_fh;
*arg++ = *ptr++;
*arg++ = *ptr++;
*arg++ = *ptr++;
*arg++ = *ptr++;
*arg++ = *ptr++;
*arg++ = *ptr++;
*arg++ = *ptr++;
*arg = *ptr++;
sa = &argp->saa_sa;
sa->sa_mode = IXDR_GET_U_INT32(ptr);
sa->sa_uid = IXDR_GET_U_INT32(ptr);
sa->sa_gid = IXDR_GET_U_INT32(ptr);
sa->sa_size = IXDR_GET_U_INT32(ptr);
sa->sa_atime.tv_sec = IXDR_GET_U_INT32(ptr);
sa->sa_atime.tv_usec = IXDR_GET_U_INT32(ptr);
sa->sa_mtime.tv_sec = IXDR_GET_U_INT32(ptr);
sa->sa_mtime.tv_usec = IXDR_GET_U_INT32(ptr);
} else {
arg = (int32_t *)&argp->saa_fh;
*ptr++ = *arg++;
*ptr++ = *arg++;
*ptr++ = *arg++;
*ptr++ = *arg++;
*ptr++ = *arg++;
*ptr++ = *arg++;
*ptr++ = *arg++;
*ptr++ = *arg;
sa = &argp->saa_sa;
IXDR_PUT_U_INT32(ptr, sa->sa_mode);
IXDR_PUT_U_INT32(ptr, sa->sa_uid);
IXDR_PUT_U_INT32(ptr, sa->sa_gid);
IXDR_PUT_U_INT32(ptr, sa->sa_size);
IXDR_PUT_U_INT32(ptr, sa->sa_atime.tv_sec);
IXDR_PUT_U_INT32(ptr, sa->sa_atime.tv_usec);
IXDR_PUT_U_INT32(ptr, sa->sa_mtime.tv_sec);
IXDR_PUT_U_INT32(ptr, sa->sa_mtime.tv_usec);
}
return (TRUE);
}
if (xdr_fhandle(xdrs, &argp->saa_fh) &&
xdr_sattr(xdrs, &argp->saa_sa)) {
return (TRUE);
}
return (FALSE);
}
/*
* arguments to create and mkdir
*/
bool_t
xdr_creatargs(XDR *xdrs, struct nfscreatargs *argp)
{
argp->ca_sa = &argp->ca_sa_buf;
if (xdrs->x_op == XDR_DECODE)
argp->ca_sa = &argp->ca_sa_buf;
if (xdr_diropargs(xdrs, &argp->ca_da) &&
xdr_sattr(xdrs, argp->ca_sa)) {
return (TRUE);
}
return (FALSE);
}
/*
* arguments to link
*/
bool_t
xdr_linkargs(XDR *xdrs, struct nfslinkargs *argp)
{
if (xdrs->x_op == XDR_DECODE)
argp->la_from = &argp->la_from_buf;
if (xdr_fhandle(xdrs, argp->la_from) &&
xdr_diropargs(xdrs, &argp->la_to)) {
return (TRUE);
}
return (FALSE);
}
/*
* arguments to rename
*/
bool_t
xdr_rnmargs(XDR *xdrs, struct nfsrnmargs *argp)
{
if (xdr_diropargs(xdrs, &argp->rna_from) &&
xdr_diropargs(xdrs, &argp->rna_to))
return (TRUE);
return (FALSE);
}
/*
* arguments to symlink
*/
bool_t
xdr_slargs(XDR *xdrs, struct nfsslargs *argp)
{
if (xdrs->x_op == XDR_FREE) {
if (!xdr_diropargs(xdrs, &argp->sla_from))
return (FALSE);
if ((argp->sla_tnm_flags & SLA_FREETNM) &&
!xdr_string(xdrs, &argp->sla_tnm, (uint_t)NFS_MAXPATHLEN))
return (FALSE);
return (TRUE);
}
if (xdrs->x_op == XDR_DECODE) {
argp->sla_sa = &argp->sla_sa_buf;
if (argp->sla_tnm == NULL)
argp->sla_tnm_flags |= SLA_FREETNM;
}
if (xdr_diropargs(xdrs, &argp->sla_from) &&
xdr_string(xdrs, &argp->sla_tnm, (uint_t)NFS_MAXPATHLEN) &&
xdr_sattr(xdrs, argp->sla_sa)) {
return (TRUE);
}
return (FALSE);
}
/*
* NFS_OK part of statfs operation
*/
bool_t
xdr_fsok(XDR *xdrs, struct nfsstatfsok *fsok)
{
int32_t *ptr;
if (xdrs->x_op == XDR_FREE)
return (TRUE);
ptr = XDR_INLINE(xdrs, 5 * BYTES_PER_XDR_UNIT);
if (ptr != NULL) {
if (xdrs->x_op == XDR_DECODE) {
fsok->fsok_tsize = IXDR_GET_INT32(ptr);
fsok->fsok_bsize = IXDR_GET_INT32(ptr);
fsok->fsok_blocks = IXDR_GET_INT32(ptr);
fsok->fsok_bfree = IXDR_GET_INT32(ptr);
fsok->fsok_bavail = IXDR_GET_INT32(ptr);
} else {
IXDR_PUT_INT32(ptr, fsok->fsok_tsize);
IXDR_PUT_INT32(ptr, fsok->fsok_bsize);
IXDR_PUT_INT32(ptr, fsok->fsok_blocks);
IXDR_PUT_INT32(ptr, fsok->fsok_bfree);
IXDR_PUT_INT32(ptr, fsok->fsok_bavail);
}
return (TRUE);
}
if (xdr_u_int(xdrs, &fsok->fsok_tsize) &&
xdr_u_int(xdrs, &fsok->fsok_bsize) &&
xdr_u_int(xdrs, &fsok->fsok_blocks) &&
xdr_u_int(xdrs, &fsok->fsok_bfree) &&
xdr_u_int(xdrs, &fsok->fsok_bavail)) {
return (TRUE);
}
return (FALSE);
}
#ifdef _LITTLE_ENDIAN
bool_t
xdr_fastfsok(XDR *xdrs, struct nfsstatfsok *fsok)
{
if (xdrs->x_op == XDR_FREE)
return (TRUE);
if (xdrs->x_op == XDR_DECODE)
return (FALSE);
fsok->fsok_tsize = htonl(fsok->fsok_tsize);
fsok->fsok_bsize = htonl(fsok->fsok_bsize);
fsok->fsok_blocks = htonl(fsok->fsok_blocks);
fsok->fsok_bfree = htonl(fsok->fsok_bfree);
fsok->fsok_bavail = htonl(fsok->fsok_bavail);
return (TRUE);
}
#endif
static struct xdr_discrim statfs_discrim[2] = {
{ NFS_OK, xdr_fsok },
{ __dontcare__, NULL_xdrproc_t }
};
/*
* Results of statfs operation
*/
bool_t
xdr_statfs(XDR *xdrs, struct nfsstatfs *fs)
{
return (xdr_union(xdrs, (enum_t *)&(fs->fs_status),
(caddr_t)&(fs->fs_fsok), statfs_discrim, xdr_void));
}
/*
* Results of statfs operation
*/
bool_t
xdr_faststatfs(XDR *xdrs, struct nfsstatfs *fs)
{
#if defined(_LITTLE_ENDIAN)
/*
* we deal with the discriminator; it's an enum
*/
if (!xdr_fastenum(xdrs, (enum_t *)&fs->fs_status))
return (FALSE);
if (fs->fs_status == NFS_OK)
return (xdr_fastfsok(xdrs, &fs->fs_fsok));
#elif defined(_BIG_ENDIAN)
if (fs->fs_status == NFS_OK)
return (TRUE);
#endif
return (xdr_fastshorten(xdrs, sizeof (*fs)));
}
#ifdef _LITTLE_ENDIAN
/*
* XDR enumerations
*/
#ifndef lint
static enum sizecheck { SIZEVAL } sizecheckvar; /* used to find the size of */
/* an enum */
#endif
bool_t
xdr_fastenum(XDR *xdrs, enum_t *ep)
{
if (xdrs->x_op == XDR_FREE)
return (TRUE);
if (xdrs->x_op == XDR_DECODE)
return (FALSE);
#ifndef lint
/*
* enums are treated as ints
*/
if (sizeof (sizecheckvar) == sizeof (int32_t)) {
*ep = (enum_t)htonl((int32_t)(*ep));
} else if (sizeof (sizecheckvar) == sizeof (short)) {
*ep = (enum_t)htons((short)(*ep));
} else {
return (FALSE);
}
return (TRUE);
#else
(void) (xdr_short(xdrs, (short *)ep));
return (xdr_int(xdrs, (int *)ep));
#endif
}
#endif
static bool_t
xdr_fastshorten(XDR *xdrs, uint_t ressize)
{
uint_t curpos;
curpos = XDR_GETPOS(xdrs);
ressize -= BYTES_PER_XDR_UNIT;
curpos -= ressize;
return (XDR_SETPOS(xdrs, curpos));
}