Home | History | Annotate | Download | only in nfs
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
     27 /* All Rights Reserved */
     28 
     29 #include <sys/param.h>
     30 #include <sys/types.h>
     31 #include <sys/systm.h>
     32 #include <sys/user.h>
     33 #include <sys/vnode.h>
     34 #include <sys/file.h>
     35 #include <sys/dirent.h>
     36 #include <sys/vfs.h>
     37 #include <sys/stream.h>
     38 #include <sys/strsubr.h>
     39 #include <sys/debug.h>
     40 #include <sys/t_lock.h>
     41 #include <sys/cmn_err.h>
     42 #include <sys/dnlc.h>
     43 #include <sys/cred.h>
     44 #include <sys/time.h>
     45 #include <sys/sdt.h>
     46 
     47 #include <rpc/types.h>
     48 #include <rpc/xdr.h>
     49 
     50 #include <nfs/nfs.h>
     51 #include <nfs/rnode.h>
     52 #include <rpc/rpc_rdma.h>
     53 
     54 /*
     55  * These are the XDR routines used to serialize and deserialize
     56  * the various structures passed as parameters across the network
     57  * between NFS clients and servers.
     58  */
     59 
     60 /*
     61  * XDR null terminated ASCII strings
     62  * xdr_string3 deals with "C strings" - arrays of bytes that are
     63  * terminated by a NULL character.  The parameter cpp references a
     64  * pointer to storage; If the pointer is null, then the necessary
     65  * storage is allocated.  The last parameter is the max allowed length
     66  * of the string as allowed by the system.  The NFS Version 3 protocol
     67  * does not place limits on strings, but the implementation needs to
     68  * place a reasonable limit to avoid problems.
     69  */
     70 bool_t
     71 xdr_string3(XDR *xdrs, char **cpp, uint_t maxsize)
     72 {
     73 	char *sp;
     74 	uint_t size;
     75 	uint_t nodesize;
     76 	bool_t mem_alloced = FALSE;
     77 
     78 	/*
     79 	 * first deal with the length since xdr strings are counted-strings
     80 	 */
     81 	sp = *cpp;
     82 	switch (xdrs->x_op) {
     83 	case XDR_FREE:
     84 		if (sp == NULL || sp == nfs3nametoolong)
     85 			return (TRUE);	/* already free */
     86 		/* FALLTHROUGH */
     87 
     88 	case XDR_ENCODE:
     89 		size = (uint_t)strlen(sp);
     90 		break;
     91 
     92 	case XDR_DECODE:
     93 		break;
     94 	}
     95 
     96 	if (!xdr_u_int(xdrs, &size))
     97 		return (FALSE);
     98 
     99 	/*
    100 	 * now deal with the actual bytes
    101 	 */
    102 	switch (xdrs->x_op) {
    103 	case XDR_DECODE:
    104 		if (size >= maxsize) {
    105 			*cpp = nfs3nametoolong;
    106 			if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &size))
    107 				return (FALSE);
    108 			return (TRUE);
    109 		}
    110 		nodesize = size + 1;
    111 		if (nodesize == 0)
    112 			return (TRUE);
    113 		if (sp == NULL) {
    114 			sp = kmem_alloc(nodesize, KM_NOSLEEP);
    115 			*cpp = sp;
    116 			if (sp == NULL)
    117 				return (FALSE);
    118 			mem_alloced = TRUE;
    119 		}
    120 		sp[size] = 0;
    121 
    122 		if (xdr_opaque(xdrs, sp, size)) {
    123 			if (strlen(sp) != size) {
    124 				if (mem_alloced)
    125 					kmem_free(sp, nodesize);
    126 				*cpp = NULL;
    127 				return (FALSE);
    128 			}
    129 		} else {
    130 			if (mem_alloced)
    131 				kmem_free(sp, nodesize);
    132 			*cpp = NULL;
    133 			return (FALSE);
    134 		}
    135 		return (TRUE);
    136 
    137 	case XDR_ENCODE:
    138 		return (xdr_opaque(xdrs, sp, size));
    139 
    140 	case XDR_FREE:
    141 		nodesize = size + 1;
    142 		kmem_free(sp, nodesize);
    143 		*cpp = NULL;
    144 		return (TRUE);
    145 	}
    146 
    147 	return (FALSE);
    148 }
    149 
    150 /*
    151  * XDR_INLINE decode a filehandle.
    152  */
    153 bool_t
    154 xdr_inline_decode_nfs_fh3(uint32_t *ptr, nfs_fh3 *fhp, uint32_t fhsize)
    155 {
    156 	uchar_t *bp = (uchar_t *)ptr;
    157 	uchar_t *cp;
    158 	uint32_t dsize;
    159 	uintptr_t resid;
    160 
    161 	/*
    162 	 * Check to see if what the client sent us is bigger or smaller
    163 	 * than what we can ever possibly send out. NFS_FHMAXDATA is
    164 	 * unfortunately badly named as it is no longer the max and is
    165 	 * really the min of what is sent over the wire.
    166 	 */
    167 	if (fhsize > sizeof (fhandle3_t) || fhsize < (sizeof (fsid_t) +
    168 	    sizeof (ushort_t) + NFS_FHMAXDATA +
    169 	    sizeof (ushort_t) + NFS_FHMAXDATA)) {
    170 		return (FALSE);
    171 	}
    172 
    173 	/*
    174 	 * All internal parts of a filehandle are in native byte order.
    175 	 *
    176 	 * Decode what should be fh3_fsid, it is aligned.
    177 	 */
    178 	fhp->fh3_fsid.val[0] = *(uint32_t *)bp;
    179 	bp += BYTES_PER_XDR_UNIT;
    180 	fhp->fh3_fsid.val[1] = *(uint32_t *)bp;
    181 	bp += BYTES_PER_XDR_UNIT;
    182 
    183 	/*
    184 	 * Decode what should be fh3_len.  fh3_len is two bytes, so we're
    185 	 * unaligned now.
    186 	 */
    187 	cp = (uchar_t *)&fhp->fh3_len;
    188 	*cp++ = *bp++;
    189 	*cp++ = *bp++;
    190 	fhsize -= 2 * BYTES_PER_XDR_UNIT + sizeof (ushort_t);
    191 
    192 	/*
    193 	 * For backwards compatability, the fid length may be less than
    194 	 * NFS_FHMAXDATA, but it was always encoded as NFS_FHMAXDATA bytes.
    195 	 */
    196 	dsize = fhp->fh3_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh3_len;
    197 
    198 	/*
    199 	 * Make sure the client isn't sending us a bogus length for fh3x_data.
    200 	 */
    201 	if (fhsize < dsize)
    202 		return (FALSE);
    203 	bcopy(bp, fhp->fh3_data, dsize);
    204 	bp += dsize;
    205 	fhsize -= dsize;
    206 
    207 	if (fhsize < sizeof (ushort_t))
    208 		return (FALSE);
    209 	cp = (uchar_t *)&fhp->fh3_xlen;
    210 	*cp++ = *bp++;
    211 	*cp++ = *bp++;
    212 	fhsize -= sizeof (ushort_t);
    213 
    214 	dsize = fhp->fh3_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh3_xlen;
    215 
    216 	/*
    217 	 * Make sure the client isn't sending us a bogus length for fh3x_xdata.
    218 	 */
    219 	if (fhsize < dsize)
    220 		return (FALSE);
    221 	bcopy(bp, fhp->fh3_xdata, dsize);
    222 	fhsize -= dsize;
    223 	bp += dsize;
    224 
    225 	/*
    226 	 * We realign things on purpose, so skip any padding
    227 	 */
    228 	resid = (uintptr_t)bp % BYTES_PER_XDR_UNIT;
    229 	if (resid != 0) {
    230 		if (fhsize < (BYTES_PER_XDR_UNIT - resid))
    231 			return (FALSE);
    232 		bp += BYTES_PER_XDR_UNIT - resid;
    233 		fhsize -= BYTES_PER_XDR_UNIT - resid;
    234 	}
    235 
    236 	/*
    237 	 * Make sure client didn't send extra bytes
    238 	 */
    239 	if (fhsize != 0)
    240 		return (FALSE);
    241 	return (TRUE);
    242 }
    243 
    244 static bool_t
    245 xdr_decode_nfs_fh3(XDR *xdrs, nfs_fh3 *objp)
    246 {
    247 	uint32_t fhsize;		/* filehandle size */
    248 	uint32_t bufsize;
    249 	rpc_inline_t *ptr;
    250 	uchar_t *bp;
    251 
    252 	ASSERT(xdrs->x_op == XDR_DECODE);
    253 
    254 	/*
    255 	 * Retrieve the filehandle length.
    256 	 */
    257 	if (!XDR_GETINT32(xdrs, (int32_t *)&fhsize))
    258 		return (FALSE);
    259 
    260 	bzero(objp->fh3_u.data, sizeof (objp->fh3_u.data));
    261 	objp->fh3_length = 0;
    262 
    263 	/*
    264 	 * Check to see if what the client sent us is bigger or smaller
    265 	 * than what we can ever possibly send out. NFS_FHMAXDATA is
    266 	 * unfortunately badly named as it is no longer the max and is
    267 	 * really the min of what is sent over the wire.
    268 	 */
    269 	if (fhsize > sizeof (fhandle3_t) || fhsize < (sizeof (fsid_t) +
    270 	    sizeof (ushort_t) + NFS_FHMAXDATA +
    271 	    sizeof (ushort_t) + NFS_FHMAXDATA)) {
    272 		if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &fhsize))
    273 			return (FALSE);
    274 		return (TRUE);
    275 	}
    276 
    277 	/*
    278 	 * bring in fhsize plus any padding
    279 	 */
    280 	bufsize = RNDUP(fhsize);
    281 	ptr = XDR_INLINE(xdrs, bufsize);
    282 	bp = (uchar_t *)ptr;
    283 	if (ptr == NULL) {
    284 		bp = kmem_alloc(bufsize, KM_SLEEP);
    285 		if (!xdr_opaque(xdrs, (char *)bp, bufsize)) {
    286 			kmem_free(bp, bufsize);
    287 			return (FALSE);
    288 		}
    289 	}
    290 
    291 	objp->fh3_length = sizeof (fhandle3_t);
    292 
    293 	if (xdr_inline_decode_nfs_fh3((uint32_t *)bp, objp, fhsize) == FALSE) {
    294 		/*
    295 		 * If in the process of decoding we find the file handle
    296 		 * is not correctly formed, we need to continue decoding
    297 		 * and trigger an NFS layer error. Set the nfs_fh3_len to
    298 		 * zero so it gets caught as a bad length.
    299 		 */
    300 		bzero(objp->fh3_u.data, sizeof (objp->fh3_u.data));
    301 		objp->fh3_length = 0;
    302 	}
    303 
    304 	if (ptr == NULL)
    305 		kmem_free(bp, bufsize);
    306 	return (TRUE);
    307 }
    308 
    309 /*
    310  * XDR_INLINE encode a filehandle.
    311  */
    312 bool_t
    313 xdr_inline_encode_nfs_fh3(uint32_t **ptrp, uint32_t *ptr_redzone,
    314 	nfs_fh3 *fhp)
    315 {
    316 	uint32_t *ptr = *ptrp;
    317 	uchar_t *cp;
    318 	uint_t otw_len, fsize, xsize;   /* otw, file, and export sizes */
    319 	uint32_t padword;
    320 
    321 	fsize = fhp->fh3_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh3_len;
    322 	xsize = fhp->fh3_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh3_xlen;
    323 
    324 	/*
    325 	 * First get the initial and variable sized part of the filehandle.
    326 	 */
    327 	otw_len = sizeof (fhp->fh3_fsid) +
    328 	    sizeof (fhp->fh3_len) + fsize +
    329 	    sizeof (fhp->fh3_xlen) + xsize;
    330 
    331 	/*
    332 	 * Round out to a full word.
    333 	 */
    334 	otw_len = RNDUP(otw_len);
    335 	padword = (otw_len / BYTES_PER_XDR_UNIT);	/* includes fhlen */
    336 
    337 	/*
    338 	 * Make sure we don't exceed our buffer.
    339 	 */
    340 	if ((ptr + (otw_len / BYTES_PER_XDR_UNIT) + 1) > ptr_redzone)
    341 		return (FALSE);
    342 
    343 	/*
    344 	 * Zero out the pading.
    345 	 */
    346 	ptr[padword] = 0;
    347 
    348 	IXDR_PUT_U_INT32(ptr, otw_len);
    349 
    350 	/*
    351 	 * The rest of the filehandle is in native byteorder
    352 	 */
    353 	/* fh3_fsid */
    354 	*ptr++ = (uint32_t)fhp->fh3_fsid.val[0];
    355 	*ptr++ = (uint32_t)fhp->fh3_fsid.val[1];
    356 
    357 	/*
    358 	 * Since the next pieces are unaligned, we need to
    359 	 * do bytewise copies.
    360 	 */
    361 	cp = (uchar_t *)ptr;
    362 
    363 	/* fh3_len + fh3_data */
    364 	bcopy(&fhp->fh3_len, cp, sizeof (fhp->fh3_len) + fsize);
    365 	cp += sizeof (fhp->fh3_len) + fsize;
    366 
    367 	/* fh3_xlen + fh3_xdata */
    368 	bcopy(&fhp->fh3_xlen, cp, sizeof (fhp->fh3_xlen) + xsize);
    369 	cp += sizeof (fhp->fh3_xlen) + xsize;
    370 
    371 	/* do necessary rounding/padding */
    372 	cp = (uchar_t *)RNDUP((uintptr_t)cp);
    373 	ptr = (uint32_t *)cp;
    374 
    375 	/*
    376 	 * With the above padding, we're word aligned again.
    377 	 */
    378 	ASSERT(((uintptr_t)ptr % BYTES_PER_XDR_UNIT) == 0);
    379 
    380 	*ptrp = ptr;
    381 
    382 	return (TRUE);
    383 }
    384 
    385 static bool_t
    386 xdr_encode_nfs_fh3(XDR *xdrs, nfs_fh3 *objp)
    387 {
    388 	uint_t otw_len, fsize, xsize;   /* otw, file, and export sizes */
    389 	bool_t ret;
    390 	rpc_inline_t *ptr;
    391 	rpc_inline_t *buf = NULL;
    392 	uint32_t *ptr_redzone;
    393 
    394 	ASSERT(xdrs->x_op == XDR_ENCODE);
    395 
    396 	fsize = objp->fh3_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : objp->fh3_len;
    397 	xsize = objp->fh3_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : objp->fh3_xlen;
    398 
    399 	/*
    400 	 * First get the over the wire size, it is the 4 bytes
    401 	 * for the length, plus the combined size of the
    402 	 * file handle components.
    403 	 */
    404 	otw_len = BYTES_PER_XDR_UNIT + sizeof (objp->fh3_fsid) +
    405 	    sizeof (objp->fh3_len) + fsize +
    406 	    sizeof (objp->fh3_xlen) + xsize;
    407 	/*
    408 	 * Round out to a full word.
    409 	 */
    410 	otw_len = RNDUP(otw_len);
    411 
    412 	/*
    413 	 * Next try to inline the XDR stream, if that fails (rare)
    414 	 * allocate a buffer to encode the file handle and then
    415 	 * copy it using xdr_opaque and free the buffer.
    416 	 */
    417 	ptr = XDR_INLINE(xdrs, otw_len);
    418 	if (ptr == NULL)
    419 		ptr = buf = kmem_alloc(otw_len, KM_SLEEP);
    420 
    421 	ptr_redzone = (uint32_t *)(ptr + (otw_len / BYTES_PER_XDR_UNIT));
    422 	ret = xdr_inline_encode_nfs_fh3((uint32_t **)&ptr, ptr_redzone, objp);
    423 
    424 	if (buf != NULL) {
    425 		if (ret == TRUE)
    426 			ret = xdr_opaque(xdrs, (char *)buf, otw_len);
    427 		kmem_free(buf, otw_len);
    428 	}
    429 	return (ret);
    430 }
    431 
    432 /*
    433  * XDR a NFSv3 filehandle the naive way.
    434  */
    435 bool_t
    436 xdr_nfs_fh3(XDR *xdrs, nfs_fh3 *objp)
    437 {
    438 	if (xdrs->x_op == XDR_FREE)
    439 		return (TRUE);
    440 
    441 	if (!xdr_u_int(xdrs, &objp->fh3_length))
    442 		return (FALSE);
    443 
    444 	if (objp->fh3_length > NFS3_FHSIZE)
    445 		return (FALSE);
    446 
    447 	return (xdr_opaque(xdrs, objp->fh3_u.data, objp->fh3_length));
    448 }
    449 
    450 /*
    451  * XDR a NFSv3 filehandle with intelligence on the server.
    452  * Encoding goes from our in-memory structure to wire format.
    453  * Decoding goes from wire format to our in-memory structure.
    454  */
    455 bool_t
    456 xdr_nfs_fh3_server(XDR *xdrs, nfs_fh3 *objp)
    457 {
    458 	switch (xdrs->x_op) {
    459 	case XDR_ENCODE:
    460 		if (objp->fh3_flags & FH_WEBNFS)
    461 			return (xdr_nfs_fh3(xdrs, objp));
    462 		else
    463 			return (xdr_encode_nfs_fh3(xdrs, objp));
    464 	case XDR_DECODE:
    465 		return (xdr_decode_nfs_fh3(xdrs, objp));
    466 	case XDR_FREE:
    467 		if (objp->fh3_u.data != NULL)
    468 			bzero(objp->fh3_u.data, sizeof (objp->fh3_u.data));
    469 		return (TRUE);
    470 	}
    471 	return (FALSE);
    472 }
    473 
    474 bool_t
    475 xdr_diropargs3(XDR *xdrs, diropargs3 *objp)
    476 {
    477 	switch (xdrs->x_op) {
    478 	case XDR_FREE:
    479 	case XDR_ENCODE:
    480 		if (!xdr_nfs_fh3(xdrs, objp->dirp))
    481 			return (FALSE);
    482 		break;
    483 	case XDR_DECODE:
    484 		if (!xdr_nfs_fh3_server(xdrs, &objp->dir))
    485 			return (FALSE);
    486 		break;
    487 	}
    488 	return (xdr_string3(xdrs, &objp->name, MAXNAMELEN));
    489 }
    490 
    491 static bool_t
    492 xdr_fattr3(XDR *xdrs, fattr3 *na)
    493 {
    494 	int32_t *ptr;
    495 
    496 	if (xdrs->x_op == XDR_FREE)
    497 		return (TRUE);
    498 
    499 	ptr = XDR_INLINE(xdrs, NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT);
    500 	if (ptr != NULL) {
    501 		if (xdrs->x_op == XDR_DECODE) {
    502 			na->type = IXDR_GET_ENUM(ptr, enum ftype3);
    503 			na->mode = IXDR_GET_U_INT32(ptr);
    504 			na->nlink = IXDR_GET_U_INT32(ptr);
    505 			na->uid = IXDR_GET_U_INT32(ptr);
    506 			na->gid = IXDR_GET_U_INT32(ptr);
    507 			IXDR_GET_U_HYPER(ptr, na->size);
    508 			IXDR_GET_U_HYPER(ptr, na->used);
    509 			na->rdev.specdata1 = IXDR_GET_U_INT32(ptr);
    510 			na->rdev.specdata2 = IXDR_GET_U_INT32(ptr);
    511 			IXDR_GET_U_HYPER(ptr, na->fsid);
    512 			IXDR_GET_U_HYPER(ptr, na->fileid);
    513 			na->atime.seconds = IXDR_GET_U_INT32(ptr);
    514 			na->atime.nseconds = IXDR_GET_U_INT32(ptr);
    515 			na->mtime.seconds = IXDR_GET_U_INT32(ptr);
    516 			na->mtime.nseconds = IXDR_GET_U_INT32(ptr);
    517 			na->ctime.seconds = IXDR_GET_U_INT32(ptr);
    518 			na->ctime.nseconds = IXDR_GET_U_INT32(ptr);
    519 		} else {
    520 			IXDR_PUT_ENUM(ptr, na->type);
    521 			IXDR_PUT_U_INT32(ptr, na->mode);
    522 			IXDR_PUT_U_INT32(ptr, na->nlink);
    523 			IXDR_PUT_U_INT32(ptr, na->uid);
    524 			IXDR_PUT_U_INT32(ptr, na->gid);
    525 			IXDR_PUT_U_HYPER(ptr, na->size);
    526 			IXDR_PUT_U_HYPER(ptr, na->used);
    527 			IXDR_PUT_U_INT32(ptr, na->rdev.specdata1);
    528 			IXDR_PUT_U_INT32(ptr, na->rdev.specdata2);
    529 			IXDR_PUT_U_HYPER(ptr, na->fsid);
    530 			IXDR_PUT_U_HYPER(ptr, na->fileid);
    531 			IXDR_PUT_U_INT32(ptr, na->atime.seconds);
    532 			IXDR_PUT_U_INT32(ptr, na->atime.nseconds);
    533 			IXDR_PUT_U_INT32(ptr, na->mtime.seconds);
    534 			IXDR_PUT_U_INT32(ptr, na->mtime.nseconds);
    535 			IXDR_PUT_U_INT32(ptr, na->ctime.seconds);
    536 			IXDR_PUT_U_INT32(ptr, na->ctime.nseconds);
    537 		}
    538 		return (TRUE);
    539 	}
    540 	if (!(xdr_enum(xdrs, (enum_t *)&na->type) &&
    541 	    xdr_u_int(xdrs, &na->mode) &&
    542 	    xdr_u_int(xdrs, &na->nlink) &&
    543 	    xdr_u_int(xdrs, &na->uid) &&
    544 	    xdr_u_int(xdrs, &na->gid) &&
    545 	    xdr_u_longlong_t(xdrs, &na->size) &&
    546 	    xdr_u_longlong_t(xdrs, &na->used) &&
    547 	    xdr_u_int(xdrs, &na->rdev.specdata1) &&
    548 	    xdr_u_int(xdrs, &na->rdev.specdata2) &&
    549 	    xdr_u_longlong_t(xdrs, &na->fsid) &&
    550 	    xdr_u_longlong_t(xdrs, &na->fileid) &&
    551 	    xdr_u_int(xdrs, &na->atime.seconds) &&
    552 	    xdr_u_int(xdrs, &na->atime.nseconds) &&
    553 	    xdr_u_int(xdrs, &na->mtime.seconds) &&
    554 	    xdr_u_int(xdrs, &na->mtime.nseconds) &&
    555 	    xdr_u_int(xdrs, &na->ctime.seconds) &&
    556 	    xdr_u_int(xdrs, &na->ctime.nseconds)))
    557 			return (FALSE);
    558 	return (TRUE);
    559 }
    560 
    561 /*
    562  * Fast decode of an fattr3 to a vattr
    563  * Only return FALSE on decode error, all other fattr to vattr translation
    564  * failures set status.
    565  *
    566  * Callers must catch the following errors:
    567  *	EFBIG - file size will not fit in va_size
    568  *	EOVERFLOW - time will not fit in va_*time
    569  */
    570 static bool_t
    571 xdr_fattr3_to_vattr(XDR *xdrs, fattr3_res *objp)
    572 {
    573 	int32_t *ptr;
    574 	size3 used;
    575 	specdata3 rdev;
    576 	uint32_t ntime;
    577 	vattr_t *vap = objp->vap;
    578 
    579 	/*
    580 	 * DECODE only
    581 	 */
    582 	ASSERT(xdrs->x_op == XDR_DECODE);
    583 
    584 	/* On success, all attributes will be decoded */
    585 	vap->va_mask = AT_ALL;
    586 
    587 	objp->status = 0;
    588 	ptr = XDR_INLINE(xdrs, NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT);
    589 	if (ptr != NULL) {
    590 		/*
    591 		 * Common case
    592 		 */
    593 		vap->va_type = IXDR_GET_ENUM(ptr, enum vtype);
    594 		if (vap->va_type < NF3REG || vap->va_type > NF3FIFO)
    595 			vap->va_type = VBAD;
    596 		else
    597 			vap->va_type = nf3_to_vt[vap->va_type];
    598 		vap->va_mode = IXDR_GET_U_INT32(ptr);
    599 		vap->va_nlink = IXDR_GET_U_INT32(ptr);
    600 		vap->va_uid = (uid_t)IXDR_GET_U_INT32(ptr);
    601 		if (vap->va_uid == NFS_UID_NOBODY)
    602 			vap->va_uid = UID_NOBODY;
    603 		vap->va_gid = (gid_t)IXDR_GET_U_INT32(ptr);
    604 		if (vap->va_gid == NFS_GID_NOBODY)
    605 			vap->va_gid = GID_NOBODY;
    606 		IXDR_GET_U_HYPER(ptr, vap->va_size);
    607 		/*
    608 		 * If invalid size, stop decode, set status, and
    609 		 * return TRUE, x_handy will be correct, caller must ignore vap.
    610 		 */
    611 		if (!NFS3_SIZE_OK(vap->va_size)) {
    612 			objp->status = EFBIG;
    613 			return (TRUE);
    614 		}
    615 		IXDR_GET_U_HYPER(ptr, used);
    616 		rdev.specdata1 = IXDR_GET_U_INT32(ptr);
    617 		rdev.specdata2 = IXDR_GET_U_INT32(ptr);
    618 		/* fsid is ignored */
    619 		ptr += 2;
    620 		IXDR_GET_U_HYPER(ptr, vap->va_nodeid);
    621 
    622 		/*
    623 		 * nfs protocol defines times as unsigned so don't
    624 		 * extend sign, unless sysadmin set nfs_allow_preepoch_time.
    625 		 * The inline macros do the equivilant of NFS_TIME_T_CONVERT
    626 		 */
    627 		if (nfs_allow_preepoch_time) {
    628 			vap->va_atime.tv_sec = IXDR_GET_INT32(ptr);
    629 			vap->va_atime.tv_nsec = IXDR_GET_U_INT32(ptr);
    630 			vap->va_mtime.tv_sec = IXDR_GET_INT32(ptr);
    631 			vap->va_mtime.tv_nsec = IXDR_GET_U_INT32(ptr);
    632 			vap->va_ctime.tv_sec = IXDR_GET_INT32(ptr);
    633 			vap->va_ctime.tv_nsec = IXDR_GET_U_INT32(ptr);
    634 		} else {
    635 			/*
    636 			 * Check if the time would overflow on 32-bit
    637 			 */
    638 			ntime = IXDR_GET_U_INT32(ptr);
    639 			/*CONSTCOND*/
    640 			if (NFS3_TIME_OVERFLOW(ntime)) {
    641 				objp->status = EOVERFLOW;
    642 				return (TRUE);
    643 			}
    644 			vap->va_atime.tv_sec = ntime;
    645 			vap->va_atime.tv_nsec = IXDR_GET_U_INT32(ptr);
    646 
    647 			ntime = IXDR_GET_U_INT32(ptr);
    648 			/*CONSTCOND*/
    649 			if (NFS3_TIME_OVERFLOW(ntime)) {
    650 				objp->status = EOVERFLOW;
    651 				return (TRUE);
    652 			}
    653 			vap->va_mtime.tv_sec = ntime;
    654 			vap->va_mtime.tv_nsec = IXDR_GET_U_INT32(ptr);
    655 
    656 			ntime = IXDR_GET_U_INT32(ptr);
    657 			/*CONSTCOND*/
    658 			if (NFS3_TIME_OVERFLOW(ntime)) {
    659 				objp->status = EOVERFLOW;
    660 				return (TRUE);
    661 			}
    662 			vap->va_ctime.tv_sec = ntime;
    663 			vap->va_ctime.tv_nsec = IXDR_GET_U_INT32(ptr);
    664 		}
    665 
    666 	} else {
    667 		uint64 fsid;
    668 
    669 		/*
    670 		 * Slow path
    671 		 */
    672 		if (!(xdr_enum(xdrs, (enum_t *)&vap->va_type) &&
    673 		    xdr_u_int(xdrs, &vap->va_mode) &&
    674 		    xdr_u_int(xdrs, &vap->va_nlink) &&
    675 		    xdr_u_int(xdrs, (uint_t *)&vap->va_uid) &&
    676 		    xdr_u_int(xdrs, (uint_t *)&vap->va_gid) &&
    677 		    xdr_u_longlong_t(xdrs, &vap->va_size) &&
    678 		    xdr_u_longlong_t(xdrs, &used) &&
    679 		    xdr_u_int(xdrs, &rdev.specdata1) &&
    680 		    xdr_u_int(xdrs, &rdev.specdata2) &&
    681 		    xdr_u_longlong_t(xdrs, &fsid) &&	/* ignored */
    682 		    xdr_u_longlong_t(xdrs, &vap->va_nodeid)))
    683 				return (FALSE);
    684 
    685 		if (nfs_allow_preepoch_time) {
    686 			if (!xdr_u_int(xdrs, &ntime))
    687 				return (FALSE);
    688 			vap->va_atime.tv_sec = (int32_t)ntime;
    689 			if (!xdr_u_int(xdrs, &ntime))
    690 				return (FALSE);
    691 			vap->va_atime.tv_nsec = ntime;
    692 
    693 			if (!xdr_u_int(xdrs, &ntime))
    694 				return (FALSE);
    695 			vap->va_mtime.tv_sec = (int32_t)ntime;
    696 			if (!xdr_u_int(xdrs, &ntime))
    697 				return (FALSE);
    698 			vap->va_mtime.tv_nsec = ntime;
    699 
    700 			if (!xdr_u_int(xdrs, &ntime))
    701 				return (FALSE);
    702 			vap->va_ctime.tv_sec = (int32_t)ntime;
    703 			if (!xdr_u_int(xdrs, &ntime))
    704 				return (FALSE);
    705 			vap->va_ctime.tv_nsec = ntime;
    706 		} else {
    707 			/*
    708 			 * Check if the time would overflow on 32-bit
    709 			 * Set status and keep decoding stream.
    710 			 */
    711 			if (!xdr_u_int(xdrs, &ntime))
    712 				return (FALSE);
    713 			/*CONSTCOND*/
    714 			if (NFS3_TIME_OVERFLOW(ntime)) {
    715 				objp->status = EOVERFLOW;
    716 			}
    717 			vap->va_atime.tv_sec = ntime;
    718 			if (!xdr_u_int(xdrs, &ntime))
    719 				return (FALSE);
    720 			vap->va_atime.tv_nsec = ntime;
    721 
    722 			if (!xdr_u_int(xdrs, &ntime))
    723 				return (FALSE);
    724 			/*CONSTCOND*/
    725 			if (NFS3_TIME_OVERFLOW(ntime)) {
    726 				objp->status = EOVERFLOW;
    727 			}
    728 			vap->va_mtime.tv_sec = ntime;
    729 			if (!xdr_u_int(xdrs, &ntime))
    730 				return (FALSE);
    731 			vap->va_mtime.tv_nsec = ntime;
    732 
    733 			if (!xdr_u_int(xdrs, &ntime))
    734 				return (FALSE);
    735 			/*CONSTCOND*/
    736 			if (NFS3_TIME_OVERFLOW(ntime)) {
    737 				objp->status = EOVERFLOW;
    738 			}
    739 			vap->va_ctime.tv_sec = ntime;
    740 			if (!xdr_u_int(xdrs, &ntime))
    741 				return (FALSE);
    742 			vap->va_ctime.tv_nsec = ntime;
    743 		}
    744 
    745 		/*
    746 		 * Fixup as needed
    747 		 */
    748 		if (vap->va_type < NF3REG || vap->va_type > NF3FIFO)
    749 			vap->va_type = VBAD;
    750 		else
    751 			vap->va_type = nf3_to_vt[vap->va_type];
    752 		if (vap->va_uid == NFS_UID_NOBODY)
    753 			vap->va_uid = UID_NOBODY;
    754 		if (vap->va_gid == NFS_GID_NOBODY)
    755 			vap->va_gid = GID_NOBODY;
    756 		/*
    757 		 * If invalid size, set status, and
    758 		 * return TRUE, caller must ignore vap.
    759 		 */
    760 		if (!NFS3_SIZE_OK(vap->va_size)) {
    761 			objp->status = EFBIG;
    762 			return (TRUE);
    763 		}
    764 	}
    765 
    766 	/*
    767 	 * Fill in derived fields
    768 	 */
    769 	vap->va_fsid = objp->vp->v_vfsp->vfs_dev;
    770 	vap->va_seq = 0;
    771 
    772 	/*
    773 	 * Common case values
    774 	 */
    775 	vap->va_rdev = 0;
    776 	vap->va_blksize = MAXBSIZE;
    777 	vap->va_nblocks = 0;
    778 
    779 	switch (vap->va_type) {
    780 	case VREG:
    781 	case VDIR:
    782 	case VLNK:
    783 		vap->va_nblocks = (u_longlong_t)
    784 		    ((used + (size3)DEV_BSIZE - (size3)1) /
    785 		    (size3)DEV_BSIZE);
    786 		break;
    787 	case VBLK:
    788 		vap->va_blksize = DEV_BSIZE;
    789 		/* FALLTHRU */
    790 	case VCHR:
    791 		vap->va_rdev = makedevice(rdev.specdata1, rdev.specdata2);
    792 		break;
    793 	case VSOCK:
    794 	case VFIFO:
    795 	default:
    796 		break;
    797 	}
    798 
    799 	return (TRUE);
    800 }
    801 
    802 static bool_t
    803 xdr_post_op_vattr(XDR *xdrs, post_op_vattr *objp)
    804 {
    805 	/*
    806 	 * DECODE only
    807 	 */
    808 	ASSERT(xdrs->x_op == XDR_DECODE);
    809 
    810 	if (!xdr_bool(xdrs, &objp->attributes))
    811 		return (FALSE);
    812 
    813 	if (objp->attributes == FALSE)
    814 		return (TRUE);
    815 
    816 	if (objp->attributes != TRUE)
    817 		return (FALSE);
    818 
    819 	if (!xdr_fattr3_to_vattr(xdrs, &objp->fres))
    820 		return (FALSE);
    821 
    822 	/*
    823 	 * The file size may cause an EFBIG or the time values
    824 	 * may cause EOVERFLOW, if so simply drop the attributes.
    825 	 */
    826 	if (objp->fres.status != NFS3_OK)
    827 		objp->attributes = FALSE;
    828 
    829 	return (TRUE);
    830 }
    831 
    832 bool_t
    833 xdr_post_op_attr(XDR *xdrs, post_op_attr *objp)
    834 {
    835 	if (!xdr_bool(xdrs, &objp->attributes))
    836 		return (FALSE);
    837 
    838 	if (objp->attributes == FALSE)
    839 		return (TRUE);
    840 
    841 	if (objp->attributes != TRUE)
    842 		return (FALSE);
    843 
    844 	if (!xdr_fattr3(xdrs, &objp->attr))
    845 		return (FALSE);
    846 
    847 	/*
    848 	 * Check that we don't get a file we can't handle through
    849 	 *	existing interfaces (especially stat64()).
    850 	 * Decode only check since on encode the data has
    851 	 * been dealt with in the above call to xdr_fattr3().
    852 	 */
    853 	if (xdrs->x_op == XDR_DECODE) {
    854 		/* Set attrs to false if invalid size or time */
    855 		if (!NFS3_SIZE_OK(objp->attr.size)) {
    856 			objp->attributes = FALSE;
    857 			return (TRUE);
    858 		}
    859 #ifndef _LP64
    860 		if (!NFS3_FATTR_TIME_OK(&objp->attr))
    861 			objp->attributes = FALSE;
    862 #endif
    863 	}
    864 	return (TRUE);
    865 }
    866 
    867 static bool_t
    868 xdr_wcc_data(XDR *xdrs, wcc_data *objp)
    869 {
    870 	int32_t *ptr;
    871 	wcc_attr *attrp;
    872 
    873 	if (xdrs->x_op == XDR_FREE)
    874 		return (TRUE);
    875 
    876 	if (xdrs->x_op == XDR_DECODE) {
    877 		/* pre_op_attr */
    878 		if (!xdr_bool(xdrs, &objp->before.attributes))
    879 			return (FALSE);
    880 
    881 		switch (objp->before.attributes) {
    882 		case TRUE:
    883 			attrp = &objp->before.attr;
    884 			ptr = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT);
    885 			if (ptr != NULL) {
    886 				IXDR_GET_U_HYPER(ptr, attrp->size);
    887 				attrp->mtime.seconds = IXDR_GET_U_INT32(ptr);
    888 				attrp->mtime.nseconds = IXDR_GET_U_INT32(ptr);
    889 				attrp->ctime.seconds = IXDR_GET_U_INT32(ptr);
    890 				attrp->ctime.nseconds = IXDR_GET_U_INT32(ptr);
    891 			} else {
    892 				if (!xdr_u_longlong_t(xdrs, &attrp->size))
    893 					return (FALSE);
    894 				if (!xdr_u_int(xdrs, &attrp->mtime.seconds))
    895 					return (FALSE);
    896 				if (!xdr_u_int(xdrs, &attrp->mtime.nseconds))
    897 					return (FALSE);
    898 				if (!xdr_u_int(xdrs, &attrp->ctime.seconds))
    899 					return (FALSE);
    900 				if (!xdr_u_int(xdrs, &attrp->ctime.nseconds))
    901 					return (FALSE);
    902 			}
    903 
    904 #ifndef _LP64
    905 			/*
    906 			 * check time overflow.
    907 			 */
    908 			if (!NFS3_TIME_OK(attrp->mtime.seconds) ||
    909 			    !NFS3_TIME_OK(attrp->ctime.seconds))
    910 				objp->before.attributes = FALSE;
    911 #endif
    912 			break;
    913 		case FALSE:
    914 			break;
    915 		default:
    916 			return (FALSE);
    917 		}
    918 	}
    919 
    920 	if (xdrs->x_op == XDR_ENCODE) {
    921 		/* pre_op_attr */
    922 		if (!xdr_bool(xdrs, &objp->before.attributes))
    923 			return (FALSE);
    924 
    925 		switch (objp->before.attributes) {
    926 		case TRUE:
    927 			attrp = &objp->before.attr;
    928 
    929 			ptr = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT);
    930 			if (ptr != NULL) {
    931 				IXDR_PUT_U_HYPER(ptr, attrp->size);
    932 				IXDR_PUT_U_INT32(ptr, attrp->mtime.seconds);
    933 				IXDR_PUT_U_INT32(ptr, attrp->mtime.nseconds);
    934 				IXDR_PUT_U_INT32(ptr, attrp->ctime.seconds);
    935 				IXDR_PUT_U_INT32(ptr, attrp->ctime.nseconds);
    936 			} else {
    937 				if (!xdr_u_longlong_t(xdrs, &attrp->size))
    938 					return (FALSE);
    939 				if (!xdr_u_int(xdrs, &attrp->mtime.seconds))
    940 					return (FALSE);
    941 				if (!xdr_u_int(xdrs, &attrp->mtime.nseconds))
    942 					return (FALSE);
    943 				if (!xdr_u_int(xdrs, &attrp->ctime.seconds))
    944 					return (FALSE);
    945 				if (!xdr_u_int(xdrs, &attrp->ctime.nseconds))
    946 					return (FALSE);
    947 			}
    948 			break;
    949 		case FALSE:
    950 			break;
    951 		default:
    952 			return (FALSE);
    953 		}
    954 	}
    955 	return (xdr_post_op_attr(xdrs, &objp->after));
    956 }
    957 
    958 bool_t
    959 xdr_post_op_fh3(XDR *xdrs, post_op_fh3 *objp)
    960 {
    961 	if (!xdr_bool(xdrs, &objp->handle_follows))
    962 		return (FALSE);
    963 	switch (objp->handle_follows) {
    964 	case TRUE:
    965 		switch (xdrs->x_op) {
    966 		case XDR_ENCODE:
    967 			if (!xdr_nfs_fh3_server(xdrs, &objp->handle))
    968 				return (FALSE);
    969 			break;
    970 		case XDR_FREE:
    971 		case XDR_DECODE:
    972 			if (!xdr_nfs_fh3(xdrs, &objp->handle))
    973 				return (FALSE);
    974 			break;
    975 		}
    976 		return (TRUE);
    977 	case FALSE:
    978 		return (TRUE);
    979 	default:
    980 		return (FALSE);
    981 	}
    982 }
    983 
    984 static bool_t
    985 xdr_sattr3(XDR *xdrs, sattr3 *objp)
    986 {
    987 	/* set_mode3 */
    988 	if (!xdr_bool(xdrs, &objp->mode.set_it))
    989 		return (FALSE);
    990 	if (objp->mode.set_it)
    991 		if (!xdr_u_int(xdrs, &objp->mode.mode))
    992 			return (FALSE);
    993 	/* set_uid3 */
    994 	if (!xdr_bool(xdrs, &objp->uid.set_it))
    995 		return (FALSE);
    996 	if (objp->uid.set_it)
    997 		if (!xdr_u_int(xdrs, &objp->uid.uid))
    998 			return (FALSE);
    999 	/* set_gid3 */
   1000 	if (!xdr_bool(xdrs, &objp->gid.set_it))
   1001 		return (FALSE);
   1002 	if (objp->gid.set_it)
   1003 		if (!xdr_u_int(xdrs, &objp->gid.gid))
   1004 			return (FALSE);
   1005 
   1006 	/* set_size3 */
   1007 	if (!xdr_bool(xdrs, &objp->size.set_it))
   1008 		return (FALSE);
   1009 	if (objp->size.set_it)
   1010 		if (!xdr_u_longlong_t(xdrs, &objp->size.size))
   1011 			return (FALSE);
   1012 
   1013 	/* set_atime */
   1014 	if (!xdr_enum(xdrs, (enum_t *)&objp->atime.set_it))
   1015 		return (FALSE);
   1016 	if (objp->atime.set_it == SET_TO_CLIENT_TIME) {
   1017 		if (!xdr_u_int(xdrs, &objp->atime.atime.seconds))
   1018 			return (FALSE);
   1019 		if (!xdr_u_int(xdrs, &objp->atime.atime.nseconds))
   1020 			return (FALSE);
   1021 	}
   1022 
   1023 	/* set_mtime */
   1024 	if (!xdr_enum(xdrs, (enum_t *)&objp->mtime.set_it))
   1025 		return (FALSE);
   1026 	if (objp->mtime.set_it == SET_TO_CLIENT_TIME) {
   1027 		if (!xdr_u_int(xdrs, &objp->mtime.mtime.seconds))
   1028 			return (FALSE);
   1029 		if (!xdr_u_int(xdrs, &objp->mtime.mtime.nseconds))
   1030 			return (FALSE);
   1031 	}
   1032 
   1033 	return (TRUE);
   1034 }
   1035 
   1036 bool_t
   1037 xdr_GETATTR3res(XDR *xdrs, GETATTR3res *objp)
   1038 {
   1039 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
   1040 		return (FALSE);
   1041 	if (objp->status != NFS3_OK)
   1042 		return (TRUE);
   1043 	/* xdr_GETATTR3resok */
   1044 	return (xdr_fattr3(xdrs, &objp->resok.obj_attributes));
   1045 }
   1046 
   1047 bool_t
   1048 xdr_GETATTR3vres(XDR *xdrs, GETATTR3vres *objp)
   1049 {
   1050 	/*
   1051 	 * DECODE or FREE only
   1052 	 */
   1053 	if (xdrs->x_op == XDR_FREE)
   1054 		return (TRUE);
   1055 
   1056 	if (xdrs->x_op != XDR_DECODE)
   1057 		return (FALSE);
   1058 
   1059 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
   1060 		return (FALSE);
   1061 
   1062 	if (objp->status != NFS3_OK)
   1063 		return (TRUE);
   1064 
   1065 	return (xdr_fattr3_to_vattr(xdrs, &objp->fres));
   1066 }
   1067 
   1068 
   1069 bool_t
   1070 xdr_SETATTR3args(XDR *xdrs, SETATTR3args *objp)
   1071 {
   1072 	switch (xdrs->x_op) {
   1073 	case XDR_FREE:
   1074 	case XDR_ENCODE:
   1075 		if (!xdr_nfs_fh3(xdrs, &objp->object))
   1076 			return (FALSE);
   1077 		break;
   1078 	case XDR_DECODE:
   1079 		if (!xdr_nfs_fh3_server(xdrs, &objp->object))
   1080 			return (FALSE);
   1081 		break;
   1082 	}
   1083 	if (!xdr_sattr3(xdrs, &objp->new_attributes))
   1084 		return (FALSE);
   1085 
   1086 	/* sattrguard3 */
   1087 	if (!xdr_bool(xdrs, &objp->guard.check))
   1088 		return (FALSE);
   1089 	switch (objp->guard.check) {
   1090 	case TRUE:
   1091 		if (!xdr_u_int(xdrs, &objp->guard.obj_ctime.seconds))
   1092 			return (FALSE);
   1093 		return (xdr_u_int(xdrs, &objp->guard.obj_ctime.nseconds));
   1094 	case FALSE:
   1095 		return (TRUE);
   1096 	default:
   1097 		return (FALSE);
   1098 	}
   1099 }
   1100 
   1101 bool_t
   1102 xdr_SETATTR3res(XDR *xdrs, SETATTR3res *objp)
   1103 {
   1104 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
   1105 		return (FALSE);
   1106 	switch (objp->status) {
   1107 	case NFS3_OK:
   1108 		return (xdr_wcc_data(xdrs, &objp->resok.obj_wcc));
   1109 	default:
   1110 		return (xdr_wcc_data(xdrs, &objp->resfail.obj_wcc));
   1111 	}
   1112 }
   1113 
   1114 bool_t
   1115 xdr_LOOKUP3res(XDR *xdrs, LOOKUP3res *objp)
   1116 {
   1117 	LOOKUP3resok *resokp;
   1118 
   1119 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
   1120 		return (FALSE);
   1121 
   1122 	if (objp->status != NFS3_OK)
   1123 		return (xdr_post_op_attr(xdrs, &objp->resfail.dir_attributes));
   1124 
   1125 	/* xdr_LOOKUP3resok */
   1126 	resokp = &objp->resok;
   1127 	switch (xdrs->x_op) {
   1128 	case XDR_ENCODE:
   1129 		if (!xdr_nfs_fh3_server(xdrs, &resokp->object))
   1130 			return (FALSE);
   1131 		break;
   1132 	case XDR_FREE:
   1133 	case XDR_DECODE:
   1134 		if (!xdr_nfs_fh3(xdrs, &resokp->object))
   1135 			return (FALSE);
   1136 		break;
   1137 	}
   1138 	if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
   1139 		return (FALSE);
   1140 	return (xdr_post_op_attr(xdrs, &resokp->dir_attributes));
   1141 }
   1142 
   1143 bool_t
   1144 xdr_LOOKUP3vres(XDR *xdrs, LOOKUP3vres *objp)
   1145 {
   1146 	/*
   1147 	 * DECODE or FREE only
   1148 	 */
   1149 	if (xdrs->x_op == XDR_FREE)
   1150 		return (TRUE);
   1151 
   1152 	if (xdrs->x_op != XDR_DECODE)
   1153 		return (FALSE);
   1154 
   1155 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
   1156 		return (FALSE);
   1157 
   1158 	if (objp->status != NFS3_OK)
   1159 		return (xdr_post_op_vattr(xdrs, &objp->dir_attributes));
   1160 
   1161 	if (!xdr_nfs_fh3(xdrs, &objp->object))
   1162 		return (FALSE);
   1163 	if (!xdr_post_op_vattr(xdrs, &objp->obj_attributes))
   1164 		return (FALSE);
   1165 	return (xdr_post_op_vattr(xdrs, &objp->dir_attributes));
   1166 }
   1167 
   1168 bool_t
   1169 xdr_ACCESS3args(XDR *xdrs, ACCESS3args *objp)
   1170 {
   1171 	switch (xdrs->x_op) {
   1172 	case XDR_FREE:
   1173 	case XDR_ENCODE:
   1174 		if (!xdr_nfs_fh3(xdrs, &objp->object))
   1175 			return (FALSE);
   1176 		break;
   1177 	case XDR_DECODE:
   1178 		if (!xdr_nfs_fh3_server(xdrs, &objp->object))
   1179 			return (FALSE);
   1180 		break;
   1181 	}
   1182 	return (xdr_u_int(xdrs, &objp->access));
   1183 }
   1184 
   1185 
   1186 bool_t
   1187 xdr_ACCESS3res(XDR *xdrs, ACCESS3res *objp)
   1188 {
   1189 	ACCESS3resok *resokp;
   1190 
   1191 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
   1192 		return (FALSE);
   1193 	if (objp->status != NFS3_OK)
   1194 		return (xdr_post_op_attr(xdrs, &objp->resfail.obj_attributes));
   1195 
   1196 	/* xdr_ACCESS3resok */
   1197 	resokp = &objp->resok;
   1198 	if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
   1199 		return (FALSE);
   1200 	return (xdr_u_int(xdrs, &resokp->access));
   1201 }
   1202 
   1203 bool_t
   1204 xdr_READLINK3args(XDR *xdrs,  READLINK3args *objp)
   1205 {
   1206 	rdma_chunkinfo_t rci;
   1207 	struct xdr_ops *xops = xdrrdma_xops();
   1208 
   1209 	if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
   1210 	    xdrs->x_op == XDR_ENCODE) {
   1211 		rci.rci_type = RCI_REPLY_CHUNK;
   1212 		rci.rci_len = MAXPATHLEN;
   1213 		XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
   1214 	}
   1215 	if (!xdr_nfs_fh3(xdrs, (nfs_fh3 *)objp))
   1216 		return (FALSE);
   1217 	return (TRUE);
   1218 }
   1219 
   1220 bool_t
   1221 xdr_READLINK3res(XDR *xdrs, READLINK3res *objp)
   1222 {
   1223 
   1224 	READLINK3resok *resokp;
   1225 
   1226 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
   1227 		return (FALSE);
   1228 	if (objp->status != NFS3_OK)
   1229 		return (xdr_post_op_attr(xdrs,
   1230 		    &objp->resfail.symlink_attributes));
   1231 
   1232 	/* xdr_READLINK3resok */
   1233 	resokp = &objp->resok;
   1234 	if (!xdr_post_op_attr(xdrs, &resokp->symlink_attributes))
   1235 		return (FALSE);
   1236 	return (xdr_string3(xdrs, &resokp->data, MAXPATHLEN));
   1237 }
   1238 
   1239 bool_t
   1240 xdr_READ3args(XDR *xdrs, READ3args *objp)
   1241 {
   1242 	rdma_chunkinfo_t rci;
   1243 	rdma_wlist_conn_info_t rwci;
   1244 	struct xdr_ops *xops = xdrrdma_xops();
   1245 
   1246 	switch (xdrs->x_op) {
   1247 	case XDR_FREE:
   1248 	case XDR_ENCODE:
   1249 		if (!xdr_nfs_fh3(xdrs, &objp->file))
   1250 			return (FALSE);
   1251 		break;
   1252 	case XDR_DECODE:
   1253 		if (!xdr_nfs_fh3_server(xdrs, &objp->file))
   1254 			return (FALSE);
   1255 		break;
   1256 	}
   1257 	if (!xdr_u_longlong_t(xdrs, &objp->offset))
   1258 		return (FALSE);
   1259 	if (!xdr_u_int(xdrs, &objp->count))
   1260 		return (FALSE);
   1261 
   1262 	DTRACE_PROBE1(xdr__i__read3_buf_len, int, objp->count);
   1263 
   1264 	objp->wlist = NULL;
   1265 
   1266 	/* if xdrrdma_sizeof in progress, then store the size */
   1267 	if (xdrs->x_ops == xops && xdrs->x_op == XDR_ENCODE) {
   1268 		rci.rci_type = RCI_WRITE_ADDR_CHUNK;
   1269 		rci.rci_len = objp->count;
   1270 		(void) XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
   1271 	}
   1272 
   1273 	if (xdrs->x_ops != &xdrrdma_ops || xdrs->x_op == XDR_FREE)
   1274 		return (TRUE);
   1275 
   1276 	if (xdrs->x_op == XDR_ENCODE) {
   1277 
   1278 		if (objp->res_uiop != NULL) {
   1279 			rci.rci_type = RCI_WRITE_UIO_CHUNK;
   1280 			rci.rci_a.rci_uiop = objp->res_uiop;
   1281 			rci.rci_len = objp->count;
   1282 			rci.rci_clpp = &objp->wlist;
   1283 		} else {
   1284 			rci.rci_type = RCI_WRITE_ADDR_CHUNK;
   1285 			rci.rci_a.rci_addr = objp->res_data_val_alt;
   1286 			rci.rci_len = objp->count;
   1287 			rci.rci_clpp = &objp->wlist;
   1288 		}
   1289 
   1290 		return (XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci));
   1291 	}
   1292 
   1293 	/* XDR_DECODE case */
   1294 	(void) XDR_CONTROL(xdrs, XDR_RDMA_GET_WCINFO, &rwci);
   1295 	objp->wlist = rwci.rwci_wlist;
   1296 	objp->conn = rwci.rwci_conn;
   1297 
   1298 	return (TRUE);
   1299 }
   1300 
   1301 bool_t
   1302 xdr_READ3res(XDR *xdrs, READ3res *objp)
   1303 {
   1304 	READ3resok *resokp;
   1305 	bool_t ret;
   1306 	mblk_t *mp;
   1307 
   1308 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
   1309 		return (FALSE);
   1310 
   1311 	if (objp->status != NFS3_OK)
   1312 		return (xdr_post_op_attr(xdrs, &objp->resfail.file_attributes));
   1313 
   1314 	resokp = &objp->resok;
   1315 
   1316 	if (xdr_post_op_attr(xdrs, &resokp->file_attributes) == FALSE ||
   1317 	    xdr_u_int(xdrs, &resokp->count) == FALSE ||
   1318 	    xdr_bool(xdrs, &resokp->eof) == FALSE) {
   1319 		return (FALSE);
   1320 	}
   1321 
   1322 	if (xdrs->x_op == XDR_ENCODE) {
   1323 
   1324 		mp = resokp->data.mp;
   1325 		if (mp != NULL && xdrs->x_ops == &xdrmblk_ops) {
   1326 			if (xdrmblk_putmblk(xdrs, mp, resokp->count) == TRUE) {
   1327 				resokp->data.mp = NULL;
   1328 				return (TRUE);
   1329 			}
   1330 		} else if (mp == NULL) {
   1331 			if (xdr_u_int(xdrs, &resokp->count) == FALSE) {
   1332 				return (FALSE);
   1333 			}
   1334 			/*
   1335 			 * If read data sent by wlist (RDMA_WRITE), don't do
   1336 			 * xdr_bytes() below.   RDMA_WRITE transfers the data.
   1337 			 * Note: this is encode-only because the client code
   1338 			 * uses xdr_READ3vres/xdr_READ3uiores to decode results.
   1339 			 */
   1340 			if (resokp->wlist) {
   1341 				if (resokp->count != 0) {
   1342 					return (xdrrdma_send_read_data(
   1343 					    xdrs, resokp->count,
   1344 					    resokp->wlist));
   1345 				}
   1346 				return (TRUE);
   1347 			}
   1348 		}
   1349 		/*
   1350 		 * Fall thru for the xdr_bytes()
   1351 		 *
   1352 		 * note: the mblk will be freed in
   1353 		 * rfs3_read_free.
   1354 		 */
   1355 	}
   1356 
   1357 	/* no RDMA_WRITE transfer -- send data inline */
   1358 
   1359 	ret = xdr_bytes(xdrs, (char **)&resokp->data.data_val,
   1360 	    &resokp->data.data_len, nfs3tsize());
   1361 
   1362 	return (ret);
   1363 }
   1364 
   1365 bool_t
   1366 xdr_READ3vres(XDR *xdrs, READ3vres *objp)
   1367 {
   1368 	count3 ocount;
   1369 	/*
   1370 	 * DECODE or FREE only
   1371 	 */
   1372 	if (xdrs->x_op == XDR_FREE)
   1373 		return (TRUE);
   1374 
   1375 	if (xdrs->x_op != XDR_DECODE)
   1376 		return (FALSE);
   1377 
   1378 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
   1379 		return (FALSE);
   1380 
   1381 	if (!xdr_post_op_vattr(xdrs, &objp->pov))
   1382 		return (FALSE);
   1383 
   1384 	if (objp->status != NFS3_OK)
   1385 		return (TRUE);
   1386 
   1387 	if (!xdr_u_int(xdrs, &objp->count))
   1388 		return (FALSE);
   1389 
   1390 	if (!xdr_bool(xdrs, &objp->eof))
   1391 		return (FALSE);
   1392 
   1393 	/*
   1394 	 * If read data received via RDMA_WRITE, don't do xdr_bytes().
   1395 	 * RDMA_WRITE already moved the data so decode length of RDMA_WRITE.
   1396 	 */
   1397 	if (xdrs->x_ops == &xdrrdma_ops) {
   1398 		struct clist *cl;
   1399 
   1400 		XDR_CONTROL(xdrs, XDR_RDMA_GET_WLIST, &cl);
   1401 
   1402 		if (cl) {
   1403 			if (!xdr_u_int(xdrs, &ocount)) {
   1404 				return (FALSE);
   1405 			}
   1406 			if (ocount != objp->count) {
   1407 				DTRACE_PROBE2(xdr__e__read3vres_fail,
   1408 				    int, ocount, int, objp->count);
   1409 				objp->wlist = NULL;
   1410 				return (FALSE);
   1411 			}
   1412 
   1413 			objp->wlist_len = clist_len(cl);
   1414 			objp->data.data_len = ocount;
   1415 
   1416 			if (objp->wlist_len !=
   1417 			    roundup(objp->data.data_len, BYTES_PER_XDR_UNIT)) {
   1418 				DTRACE_PROBE2(
   1419 				    xdr__e__read3vres_fail,
   1420 				    int, ocount,
   1421 				    int, objp->data.data_len);
   1422 				objp->wlist = NULL;
   1423 				return (FALSE);
   1424 			}
   1425 			return (TRUE);
   1426 		}
   1427 	}
   1428 
   1429 	return (xdr_bytes(xdrs, (char **)&objp->data.data_val,
   1430 	    &objp->data.data_len, nfs3tsize()));
   1431 }
   1432 
   1433 bool_t
   1434 xdr_READ3uiores(XDR *xdrs, READ3uiores *objp)
   1435 {
   1436 	count3 ocount;
   1437 	bool_t attributes;
   1438 	mblk_t *mp;
   1439 	size_t n;
   1440 	int error;
   1441 	int size = (int)objp->size;
   1442 	struct uio *uiop = objp->uiop;
   1443 	int32_t fattr3_len = NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT;
   1444 	int32_t *ptr;
   1445 
   1446 	/*
   1447 	 * DECODE or FREE only
   1448 	 */
   1449 	if (xdrs->x_op == XDR_FREE)
   1450 		return (TRUE);
   1451 
   1452 	if (xdrs->x_op != XDR_DECODE)
   1453 		return (FALSE);
   1454 
   1455 	if (!XDR_GETINT32(xdrs, (int32_t *)&objp->status))
   1456 		return (FALSE);
   1457 
   1458 	if (!XDR_GETINT32(xdrs, (int32_t *)&attributes))
   1459 		return (FALSE);
   1460 
   1461 	/*
   1462 	 * For directio we just skip over attributes if present
   1463 	 */
   1464 	switch (attributes) {
   1465 	case TRUE:
   1466 		if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &fattr3_len))
   1467 			return (FALSE);
   1468 		break;
   1469 	case FALSE:
   1470 		break;
   1471 	default:
   1472 		return (FALSE);
   1473 	}
   1474 
   1475 	if (objp->status != NFS3_OK)
   1476 		return (TRUE);
   1477 
   1478 	if (!XDR_GETINT32(xdrs, (int32_t *)&objp->count))
   1479 		return (FALSE);
   1480 
   1481 	if (!XDR_GETINT32(xdrs, (int32_t *)&objp->eof))
   1482 		return (FALSE);
   1483 
   1484 	if (xdrs->x_ops == &xdrmblk_ops) {
   1485 		if (!xdrmblk_getmblk(xdrs, &mp, &objp->size))
   1486 			return (FALSE);
   1487 
   1488 		if (objp->size == 0)
   1489 			return (TRUE);
   1490 
   1491 		if (objp->size > size)
   1492 			return (FALSE);
   1493 
   1494 		size = (int)objp->size;
   1495 		do {
   1496 			n = MIN(size, mp->b_wptr - mp->b_rptr);
   1497 			if ((n = MIN(uiop->uio_resid, n)) != 0) {
   1498 
   1499 				error = uiomove((char *)mp->b_rptr, n, UIO_READ,
   1500 				    uiop);
   1501 				if (error)
   1502 					return (FALSE);
   1503 				mp->b_rptr += n;
   1504 				size -= n;
   1505 			}
   1506 
   1507 			while (mp && (mp->b_rptr >= mp->b_wptr))
   1508 				mp = mp->b_cont;
   1509 		} while (mp && size > 0 && uiop->uio_resid > 0);
   1510 
   1511 		return (TRUE);
   1512 	}
   1513 
   1514 	if (xdrs->x_ops == &xdrrdma_ops) {
   1515 		struct clist *cl;
   1516 
   1517 		XDR_CONTROL(xdrs, XDR_RDMA_GET_WLIST, &cl);
   1518 
   1519 		objp->wlist = cl;
   1520 
   1521 		if (objp->wlist) {
   1522 			if (!xdr_u_int(xdrs, &ocount)) {
   1523 				objp->wlist = NULL;
   1524 				return (FALSE);
   1525 			}
   1526 
   1527 			if (ocount != objp->count) {
   1528 				DTRACE_PROBE2(xdr__e__read3uiores_fail,
   1529 				    int, ocount, int, objp->count);
   1530 				objp->wlist = NULL;
   1531 				return (FALSE);
   1532 			}
   1533 
   1534 			objp->wlist_len = clist_len(cl);
   1535 
   1536 			uiop->uio_resid -= objp->count;
   1537 			uiop->uio_iov->iov_len -= objp->count;
   1538 			uiop->uio_iov->iov_base += objp->count;
   1539 			uiop->uio_loffset += objp->count;
   1540 
   1541 			/*
   1542 			 * XXX: Assume 1 iov, needs to be changed.
   1543 			 */
   1544 			objp->size = objp->count;
   1545 
   1546 			return (TRUE);
   1547 		}
   1548 	}
   1549 
   1550 	/*
   1551 	 * This isn't an xdrmblk stream nor RDMA.
   1552 	 * Handle the likely case that it can be
   1553 	 * inlined (ex. xdrmem).
   1554 	 */
   1555 	if (!XDR_GETINT32(xdrs, (int32_t *)&objp->size))
   1556 		return (FALSE);
   1557 
   1558 	if (objp->size == 0)
   1559 		return (TRUE);
   1560 
   1561 	if (objp->size > size)
   1562 		return (FALSE);
   1563 
   1564 	size = (int)objp->size;
   1565 	if ((ptr = XDR_INLINE(xdrs, size)) != NULL)
   1566 		return (uiomove(ptr, size, UIO_READ, uiop) ? FALSE : TRUE);
   1567 
   1568 	/*
   1569 	 * Handle some other (unlikely) stream type that will need a copy.
   1570 	 */
   1571 	if ((ptr = kmem_alloc(size, KM_NOSLEEP)) == NULL)
   1572 		return (FALSE);
   1573 
   1574 	if (!XDR_GETBYTES(xdrs, (caddr_t)ptr, size)) {
   1575 		kmem_free(ptr, size);
   1576 		return (FALSE);
   1577 	}
   1578 	error = uiomove(ptr, size, UIO_READ, uiop);
   1579 	kmem_free(ptr, size);
   1580 
   1581 	return (error ? FALSE : TRUE);
   1582 }
   1583 
   1584 bool_t
   1585 xdr_WRITE3args(XDR *xdrs, WRITE3args *objp)
   1586 {
   1587 	switch (xdrs->x_op) {
   1588 	case XDR_FREE:
   1589 	case XDR_ENCODE:
   1590 		if (!xdr_nfs_fh3(xdrs, &objp->file))
   1591 			return (FALSE);
   1592 		break;
   1593 	case XDR_DECODE:
   1594 		if (!xdr_nfs_fh3_server(xdrs, &objp->file))
   1595 			return (FALSE);
   1596 		break;
   1597 	}
   1598 	if (!xdr_u_longlong_t(xdrs, &objp->offset))
   1599 		return (FALSE);
   1600 	if (!xdr_u_int(xdrs, &objp->count))
   1601 		return (FALSE);
   1602 	if (!xdr_enum(xdrs, (enum_t *)&objp->stable))
   1603 		return (FALSE);
   1604 
   1605 	if (xdrs->x_op == XDR_DECODE) {
   1606 		if (xdrs->x_ops == &xdrmblk_ops) {
   1607 			if (xdrmblk_getmblk(xdrs, &objp->mblk,
   1608 			    &objp->data.data_len) == TRUE) {
   1609 				objp->data.data_val = NULL;
   1610 				return (TRUE);
   1611 			}
   1612 		}
   1613 		objp->mblk = NULL;
   1614 
   1615 		if (xdrs->x_ops == &xdrrdmablk_ops) {
   1616 			if (xdrrdma_getrdmablk(xdrs, &objp->rlist,
   1617 			    &objp->data.data_len,
   1618 			    &objp->conn, nfs3tsize()) == TRUE) {
   1619 				objp->data.data_val = NULL;
   1620 				if (xdrrdma_read_from_client(
   1621 				    objp->rlist,
   1622 				    &objp->conn,
   1623 				    objp->count) == FALSE) {
   1624 					return (FALSE);
   1625 				}
   1626 				return (TRUE);
   1627 			}
   1628 		}
   1629 		objp->rlist = NULL;
   1630 
   1631 		/* Else fall thru for the xdr_bytes(). */
   1632 	}
   1633 
   1634 	if (xdrs->x_op == XDR_FREE) {
   1635 		if (objp->rlist != NULL) {
   1636 			(void) xdrrdma_free_clist(objp->conn, objp->rlist);
   1637 			objp->rlist = NULL;
   1638 			objp->data.data_val = NULL;
   1639 			return (TRUE);
   1640 		}
   1641 	}
   1642 
   1643 	DTRACE_PROBE1(xdr__i__write3_buf_len,
   1644 	    int, objp->data.data_len);
   1645 
   1646 	return (xdr_bytes(xdrs, (char **)&objp->data.data_val,
   1647 	    &objp->data.data_len, nfs3tsize()));
   1648 }
   1649 
   1650 bool_t
   1651 xdr_WRITE3res(XDR *xdrs, WRITE3res *objp)
   1652 {
   1653 	WRITE3resok *resokp;
   1654 
   1655 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
   1656 		return (FALSE);
   1657 	if (objp->status != NFS3_OK) /* xdr_WRITE3resfail */
   1658 		return (xdr_wcc_data(xdrs, &objp->resfail.file_wcc));
   1659 
   1660 	/* xdr_WRITE3resok */
   1661 	resokp = &objp->resok;
   1662 	if (!xdr_wcc_data(xdrs, &resokp->file_wcc))
   1663 		return (FALSE);
   1664 	if (!xdr_u_int(xdrs, &resokp->count))
   1665 		return (FALSE);
   1666 	if (!xdr_enum(xdrs, (enum_t *)&resokp->committed))
   1667 		return (FALSE);
   1668 	/*
   1669 	 * writeverf3 is really an opaque 8 byte
   1670 	 * quantity, but we will treat it as a
   1671 	 * hyper for efficiency, the cost of
   1672 	 * a byteswap here saves bcopys elsewhere
   1673 	 */
   1674 	return (xdr_u_longlong_t(xdrs, &resokp->verf));
   1675 }
   1676 
   1677 bool_t
   1678 xdr_CREATE3args(XDR *xdrs, CREATE3args *objp)
   1679 {
   1680 	createhow3 *howp;
   1681 
   1682 	if (!xdr_diropargs3(xdrs, &objp->where))
   1683 		return (FALSE);
   1684 
   1685 	/* xdr_createhow3 */
   1686 	howp = &objp->how;
   1687 
   1688 	if (!xdr_enum(xdrs, (enum_t *)&howp->mode))
   1689 		return (FALSE);
   1690 	switch (howp->mode) {
   1691 	case UNCHECKED:
   1692 	case GUARDED:
   1693 		return (xdr_sattr3(xdrs, &howp->createhow3_u.obj_attributes));
   1694 	case EXCLUSIVE:
   1695 		/*
   1696 		 * createverf3 is really an opaque 8 byte
   1697 		 * quantity, but we will treat it as a
   1698 		 * hyper for efficiency, the cost of
   1699 		 * a byteswap here saves bcopys elsewhere
   1700 		 */
   1701 		return (xdr_u_longlong_t(xdrs, &howp->createhow3_u.verf));
   1702 	default:
   1703 		return (FALSE);
   1704 	}
   1705 }
   1706 
   1707 bool_t
   1708 xdr_CREATE3res(XDR *xdrs, CREATE3res *objp)
   1709 {
   1710 	CREATE3resok *resokp;
   1711 
   1712 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
   1713 		return (FALSE);
   1714 	switch (objp->status) {
   1715 	case NFS3_OK:
   1716 		/* xdr_CREATE3resok */
   1717 		resokp = &objp->resok;
   1718 
   1719 		if (!xdr_post_op_fh3(xdrs, &resokp->obj))
   1720 			return (FALSE);
   1721 		if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
   1722 			return (FALSE);
   1723 		return (xdr_wcc_data(xdrs, &resokp->dir_wcc));
   1724 	default:
   1725 		/* xdr_CREATE3resfail */
   1726 		return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
   1727 	}
   1728 }
   1729 
   1730 bool_t
   1731 xdr_MKDIR3args(XDR *xdrs, MKDIR3args *objp)
   1732 {
   1733 	if (!xdr_diropargs3(xdrs, &objp->where))
   1734 		return (FALSE);
   1735 	return (xdr_sattr3(xdrs, &objp->attributes));
   1736 }
   1737 
   1738 bool_t
   1739 xdr_MKDIR3res(XDR *xdrs, MKDIR3res *objp)
   1740 {
   1741 	MKDIR3resok *resokp;
   1742 
   1743 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
   1744 		return (FALSE);
   1745 	switch (objp->status) {
   1746 	case NFS3_OK:
   1747 		/* xdr_MKDIR3resok */
   1748 		resokp = &objp->resok;
   1749 
   1750 		if (!xdr_post_op_fh3(xdrs, &resokp->obj))
   1751 			return (FALSE);
   1752 		if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
   1753 			return (FALSE);
   1754 		return (xdr_wcc_data(xdrs, &resokp->dir_wcc));
   1755 	default:
   1756 		return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
   1757 	}
   1758 }
   1759 
   1760 bool_t
   1761 xdr_SYMLINK3args(XDR *xdrs, SYMLINK3args *objp)
   1762 {
   1763 	if (!xdr_diropargs3(xdrs, &objp->where))
   1764 		return (FALSE);
   1765 	if (!xdr_sattr3(xdrs, &objp->symlink.symlink_attributes))
   1766 		return (FALSE);
   1767 	return (xdr_string3(xdrs, &objp->symlink.symlink_data, MAXPATHLEN));
   1768 }
   1769 
   1770 bool_t
   1771 xdr_SYMLINK3res(XDR *xdrs, SYMLINK3res *objp)
   1772 {
   1773 	SYMLINK3resok *resokp;
   1774 
   1775 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
   1776 		return (FALSE);
   1777 	switch (objp->status) {
   1778 	case NFS3_OK:
   1779 		resokp = &objp->resok;
   1780 		/* xdr_SYMLINK3resok */
   1781 		if (!xdr_post_op_fh3(xdrs, &resokp->obj))
   1782 			return (FALSE);
   1783 		if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
   1784 			return (FALSE);
   1785 		return (xdr_wcc_data(xdrs, &resokp->dir_wcc));
   1786 	default:
   1787 		return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
   1788 	}
   1789 }
   1790 
   1791 bool_t
   1792 xdr_MKNOD3args(XDR *xdrs, MKNOD3args *objp)
   1793 {
   1794 	mknoddata3 *whatp;
   1795 	devicedata3 *nod_objp;
   1796 
   1797 	if (!xdr_diropargs3(xdrs, &objp->where))
   1798 		return (FALSE);
   1799 
   1800 	whatp = &objp->what;
   1801 	if (!xdr_enum(xdrs, (enum_t *)&whatp->type))
   1802 		return (FALSE);
   1803 	switch (whatp->type) {
   1804 	case NF3CHR:
   1805 	case NF3BLK:
   1806 		/* xdr_devicedata3 */
   1807 		nod_objp = &whatp->mknoddata3_u.device;
   1808 		if (!xdr_sattr3(xdrs, &nod_objp->dev_attributes))
   1809 			return (FALSE);
   1810 		if (!xdr_u_int(xdrs, &nod_objp->spec.specdata1))
   1811 			return (FALSE);
   1812 		return (xdr_u_int(xdrs, &nod_objp->spec.specdata2));
   1813 	case NF3SOCK:
   1814 	case NF3FIFO:
   1815 		return (xdr_sattr3(xdrs, &whatp->mknoddata3_u.pipe_attributes));
   1816 	default:
   1817 		break;
   1818 	}
   1819 	return (TRUE);
   1820 }
   1821 
   1822 bool_t
   1823 xdr_MKNOD3res(XDR *xdrs, MKNOD3res *objp)
   1824 {
   1825 	MKNOD3resok *resokp;
   1826 
   1827 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
   1828 		return (FALSE);
   1829 	switch (objp->status) {
   1830 	case NFS3_OK:
   1831 		/* xdr_MKNOD3resok */
   1832 		resokp = &objp->resok;
   1833 		if (!xdr_post_op_fh3(xdrs, &resokp->obj))
   1834 			return (FALSE);
   1835 		if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
   1836 			return (FALSE);
   1837 		return (xdr_wcc_data(xdrs, &resokp->dir_wcc));
   1838 	default:
   1839 		return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
   1840 	}
   1841 }
   1842 
   1843 bool_t
   1844 xdr_REMOVE3res(XDR *xdrs, REMOVE3res *objp)
   1845 {
   1846 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
   1847 		return (FALSE);
   1848 	switch (objp->status) {
   1849 	case NFS3_OK:
   1850 		return (xdr_wcc_data(xdrs, &objp->resok.dir_wcc));
   1851 	default:
   1852 		return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
   1853 	}
   1854 }
   1855 
   1856 bool_t
   1857 xdr_RMDIR3res(XDR *xdrs, RMDIR3res *objp)
   1858 {
   1859 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
   1860 		return (FALSE);
   1861 	switch (objp->status) {
   1862 	case NFS3_OK:
   1863 		return (xdr_wcc_data(xdrs, &objp->resok.dir_wcc));
   1864 	default:
   1865 		return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
   1866 	}
   1867 }
   1868 
   1869 bool_t
   1870 xdr_RENAME3args(XDR *xdrs, RENAME3args *objp)
   1871 {
   1872 	if (!xdr_diropargs3(xdrs, &objp->from))
   1873 		return (FALSE);
   1874 	return (xdr_diropargs3(xdrs, &objp->to));
   1875 }
   1876 
   1877 bool_t
   1878 xdr_RENAME3res(XDR *xdrs, RENAME3res *objp)
   1879 {
   1880 	RENAME3resok *resokp;
   1881 	RENAME3resfail *resfailp;
   1882 
   1883 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
   1884 		return (FALSE);
   1885 	switch (objp->status) {
   1886 	case NFS3_OK:
   1887 		/* xdr_RENAME3resok */
   1888 		resokp = &objp->resok;
   1889 
   1890 		if (!xdr_wcc_data(xdrs, &resokp->fromdir_wcc))
   1891 			return (FALSE);
   1892 		return (xdr_wcc_data(xdrs, &resokp->todir_wcc));
   1893 	default:
   1894 		/* xdr_RENAME3resfail */
   1895 		resfailp = &objp->resfail;
   1896 		if (!xdr_wcc_data(xdrs, &resfailp->fromdir_wcc))
   1897 			return (FALSE);
   1898 		return (xdr_wcc_data(xdrs, &resfailp->todir_wcc));
   1899 	}
   1900 }
   1901 
   1902 bool_t
   1903 xdr_LINK3args(XDR *xdrs, LINK3args *objp)
   1904 {
   1905 	switch (xdrs->x_op) {
   1906 	case XDR_FREE:
   1907 	case XDR_ENCODE:
   1908 		if (!xdr_nfs_fh3(xdrs, &objp->file))
   1909 			return (FALSE);
   1910 		break;
   1911 	case XDR_DECODE:
   1912 		if (!xdr_nfs_fh3_server(xdrs, &objp->file))
   1913 			return (FALSE);
   1914 		break;
   1915 	}
   1916 	return (xdr_diropargs3(xdrs, &objp->link));
   1917 }
   1918 
   1919 bool_t
   1920 xdr_LINK3res(XDR *xdrs, LINK3res *objp)
   1921 {
   1922 	LINK3resok *resokp;
   1923 	LINK3resfail *resfailp;
   1924 
   1925 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
   1926 		return (FALSE);
   1927 	switch (objp->status) {
   1928 	case NFS3_OK:
   1929 		/* xdr_LINK3resok */
   1930 		resokp = &objp->resok;
   1931 		if (!xdr_post_op_attr(xdrs, &resokp->file_attributes))
   1932 			return (FALSE);
   1933 		return (xdr_wcc_data(xdrs, &resokp->linkdir_wcc));
   1934 	default:
   1935 		/* xdr_LINK3resfail */
   1936 		resfailp = &objp->resfail;
   1937 		if (!xdr_post_op_attr(xdrs, &resfailp->file_attributes))
   1938 			return (FALSE);
   1939 		return (xdr_wcc_data(xdrs, &resfailp->linkdir_wcc));
   1940 	}
   1941 }
   1942 
   1943 bool_t
   1944 xdr_READDIR3args(XDR *xdrs, READDIR3args *objp)
   1945 {
   1946 	rdma_chunkinfo_t rci;
   1947 	struct xdr_ops *xops = xdrrdma_xops();
   1948 
   1949 	if (xdrs->x_op == XDR_FREE)
   1950 		return (TRUE);
   1951 
   1952 	switch (xdrs->x_op) {
   1953 	case XDR_FREE:
   1954 	case XDR_ENCODE:
   1955 		if (!xdr_nfs_fh3(xdrs, &objp->dir))
   1956 			return (FALSE);
   1957 		break;
   1958 	case XDR_DECODE:
   1959 		if (!xdr_nfs_fh3_server(xdrs, &objp->dir))
   1960 			return (FALSE);
   1961 		break;
   1962 	}
   1963 	if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
   1964 	    xdrs->x_op == XDR_ENCODE) {
   1965 		rci.rci_type = RCI_REPLY_CHUNK;
   1966 		rci.rci_len = objp->count;
   1967 		XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
   1968 	}
   1969 
   1970 	if (!xdr_u_longlong_t(xdrs, &objp->cookie))
   1971 		return (FALSE);
   1972 	/*
   1973 	 * cookieverf is really an opaque 8 byte
   1974 	 * quantity, but we will treat it as a
   1975 	 * hyper for efficiency, the cost of
   1976 	 * a byteswap here saves bcopys elsewhere
   1977 	 */
   1978 	if (!xdr_u_longlong_t(xdrs, &objp->cookieverf))
   1979 		return (FALSE);
   1980 	return (xdr_u_int(xdrs, &objp->count));
   1981 }
   1982 
   1983 #ifdef	nextdp
   1984 #undef	nextdp
   1985 #endif
   1986 #define	nextdp(dp)	((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
   1987 #ifdef	roundup
   1988 #undef	roundup
   1989 #endif
   1990 #define	roundup(x, y)	((((x) + ((y) - 1)) / (y)) * (y))
   1991 
   1992 /*
   1993  * ENCODE ONLY
   1994  */
   1995 static bool_t
   1996 xdr_putdirlist(XDR *xdrs, READDIR3resok *objp)
   1997 {
   1998 	struct dirent64 *dp;
   1999 	char *name;
   2000 	int size;
   2001 	int bufsize;
   2002 	uint_t namlen;
   2003 	bool_t true = TRUE;
   2004 	bool_t false = FALSE;
   2005 	int entrysz;
   2006 	int tofit;
   2007 	fileid3 fileid;
   2008 	cookie3 cookie;
   2009 
   2010 	if (xdrs->x_op != XDR_ENCODE)
   2011 		return (FALSE);
   2012 
   2013 	/*
   2014 	 * bufsize is used to keep track of the size of the response.
   2015 	 * It is primed with:
   2016 	 *	1 for the status +
   2017 	 *	1 for the dir_attributes.attributes boolean +
   2018 	 *	2 for the cookie verifier
   2019 	 * all times BYTES_PER_XDR_UNIT to convert from XDR units
   2020 	 * to bytes.  If there are directory attributes to be
   2021 	 * returned, then:
   2022 	 *	NFS3_SIZEOF_FATTR3 for the dir_attributes.attr fattr3
   2023 	 * time BYTES_PER_XDR_UNIT is added to account for them.
   2024 	 */
   2025 	bufsize = (1 + 1 + 2) * BYTES_PER_XDR_UNIT;
   2026 	if (objp->dir_attributes.attributes)
   2027 		bufsize += NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT;
   2028 	for (size = objp->size, dp = (struct dirent64 *)objp->reply.entries;
   2029 	    size > 0;
   2030 	    size -= dp->d_reclen, dp = nextdp(dp)) {
   2031 		if (dp->d_reclen == 0)
   2032 			return (FALSE);
   2033 		if (dp->d_ino == 0)
   2034 			continue;
   2035 		name = dp->d_name;
   2036 		namlen = (uint_t)strlen(dp->d_name);
   2037 		/*
   2038 		 * An entry is composed of:
   2039 		 *	1 for the true/false list indicator +
   2040 		 *	2 for the fileid +
   2041 		 *	1 for the length of the name +
   2042 		 *	2 for the cookie +
   2043 		 * all times BYTES_PER_XDR_UNIT to convert from
   2044 		 * XDR units to bytes, plus the length of the name
   2045 		 * rounded up to the nearest BYTES_PER_XDR_UNIT.
   2046 		 */
   2047 		entrysz = (1 + 2 + 1 + 2) * BYTES_PER_XDR_UNIT +
   2048 		    roundup(namlen, BYTES_PER_XDR_UNIT);
   2049 		/*
   2050 		 * We need to check to see if the number of bytes left
   2051 		 * to go into the buffer will actually fit into the
   2052 		 * buffer.  This is calculated as the size of this
   2053 		 * entry plus:
   2054 		 *	1 for the true/false list indicator +
   2055 		 *	1 for the eof indicator
   2056 		 * times BYTES_PER_XDR_UNIT to convert from from
   2057 		 * XDR units to bytes.
   2058 		 */
   2059 		tofit = entrysz + (1 + 1) * BYTES_PER_XDR_UNIT;
   2060 		if (bufsize + tofit > objp->count) {
   2061 			objp->reply.eof = FALSE;
   2062 			break;
   2063 		}
   2064 		fileid = (fileid3)(dp->d_ino);
   2065 		cookie = (cookie3)(dp->d_off);
   2066 		if (!xdr_bool(xdrs, &true) ||
   2067 		    !xdr_u_longlong_t(xdrs, &fileid) ||
   2068 		    !xdr_bytes(xdrs, &name, &namlen, ~0) ||
   2069 		    !xdr_u_longlong_t(xdrs, &cookie)) {
   2070 			return (FALSE);
   2071 		}
   2072 		bufsize += entrysz;
   2073 	}
   2074 	if (!xdr_bool(xdrs, &false))
   2075 		return (FALSE);
   2076 	if (!xdr_bool(xdrs, &objp->reply.eof))
   2077 		return (FALSE);
   2078 	return (TRUE);
   2079 }
   2080 
   2081 bool_t
   2082 xdr_READDIR3res(XDR *xdrs, READDIR3res *objp)
   2083 {
   2084 	READDIR3resok *resokp;
   2085 
   2086 	/*
   2087 	 * ENCODE or FREE only
   2088 	 */
   2089 	if (xdrs->x_op == XDR_DECODE)
   2090 		return (FALSE);
   2091 
   2092 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
   2093 		return (FALSE);
   2094 	if (objp->status != NFS3_OK)
   2095 		return (xdr_post_op_attr(xdrs, &objp->resfail.dir_attributes));
   2096 
   2097 	/* xdr_READDIR3resok */
   2098 	resokp = &objp->resok;
   2099 	if (!xdr_post_op_attr(xdrs, &resokp->dir_attributes))
   2100 		return (FALSE);
   2101 	if (xdrs->x_op != XDR_ENCODE)
   2102 		return (TRUE);
   2103 	/*
   2104 	 * cookieverf is really an opaque 8 byte
   2105 	 * quantity, but we will treat it as a
   2106 	 * hyper for efficiency, the cost of
   2107 	 * a byteswap here saves bcopys elsewhere
   2108 	 */
   2109 	if (!xdr_u_longlong_t(xdrs, &resokp->cookieverf))
   2110 		return (FALSE);
   2111 	return (xdr_putdirlist(xdrs, resokp));
   2112 }
   2113 
   2114 bool_t
   2115 xdr_READDIR3vres(XDR *xdrs, READDIR3vres *objp)
   2116 {
   2117 	dirent64_t *dp;
   2118 	uint_t entries_size;
   2119 	int outcount = 0;
   2120 
   2121 	/*
   2122 	 * DECODE or FREE only
   2123 	 */
   2124 	if (xdrs->x_op == XDR_FREE)
   2125 		return (TRUE);
   2126 
   2127 	if (xdrs->x_op != XDR_DECODE)
   2128 		return (FALSE);
   2129 
   2130 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
   2131 		return (FALSE);
   2132 
   2133 	if (!xdr_post_op_vattr(xdrs, &objp->dir_attributes))
   2134 		return (FALSE);
   2135 
   2136 	if (objp->status != NFS3_OK)
   2137 		return (TRUE);
   2138 
   2139 	/*
   2140 	 * cookieverf is really an opaque 8 byte
   2141 	 * quantity, but we will treat it as a
   2142 	 * hyper for efficiency, the cost of
   2143 	 * a byteswap here saves bcopys elsewhere
   2144 	 */
   2145 	if (!xdr_u_longlong_t(xdrs, &objp->cookieverf))
   2146 		return (FALSE);
   2147 
   2148 	entries_size = objp->entries_size;
   2149 	dp = objp->entries;
   2150 
   2151 	for (;;) {
   2152 		uint_t this_reclen;
   2153 		bool_t valid;
   2154 		uint_t namlen;
   2155 		ino64_t fileid;
   2156 
   2157 		if (!XDR_GETINT32(xdrs, (int32_t *)&valid))
   2158 			return (FALSE);
   2159 		if (!valid) {
   2160 			/*
   2161 			 * We have run out of entries, decode eof.
   2162 			 */
   2163 			if (!XDR_GETINT32(xdrs, (int32_t *)&objp->eof))
   2164 				return (FALSE);
   2165 
   2166 			break;
   2167 		}
   2168 
   2169 		/*
   2170 		 * fileid3 fileid
   2171 		 */
   2172 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&fileid))
   2173 			return (FALSE);
   2174 
   2175 		/*
   2176 		 * filename3 name
   2177 		 */
   2178 		if (!XDR_GETINT32(xdrs, (int32_t *)&namlen))
   2179 			return (FALSE);
   2180 		this_reclen = DIRENT64_RECLEN(namlen);
   2181 
   2182 		/*
   2183 		 * If this will overflow buffer, stop decoding
   2184 		 */
   2185 		if ((outcount + this_reclen) > entries_size) {
   2186 			objp->eof = FALSE;
   2187 			break;
   2188 		}
   2189 		dp->d_reclen = this_reclen;
   2190 		dp->d_ino = fileid;
   2191 
   2192 		if (!xdr_opaque(xdrs, dp->d_name, namlen))
   2193 			return (FALSE);
   2194 		bzero(&dp->d_name[namlen],
   2195 		    DIRENT64_NAMELEN(this_reclen) - namlen);
   2196 
   2197 		/*
   2198 		 * cookie3 cookie
   2199 		 */
   2200 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&dp->d_off))
   2201 			return (FALSE);
   2202 		objp->loff = dp->d_off;
   2203 
   2204 		outcount += this_reclen;
   2205 		dp = (dirent64_t *)((intptr_t)dp + this_reclen);
   2206 	}
   2207 
   2208 	objp->size = outcount;
   2209 	return (TRUE);
   2210 }
   2211 
   2212 bool_t
   2213 xdr_READDIRPLUS3args(XDR *xdrs, READDIRPLUS3args *objp)
   2214 {
   2215 	rdma_chunkinfo_t rci;
   2216 	struct xdr_ops *xops = xdrrdma_xops();
   2217 
   2218 	if (xdrs->x_op == XDR_FREE)
   2219 		return (TRUE);
   2220 
   2221 	switch (xdrs->x_op) {
   2222 	case XDR_FREE:
   2223 	case XDR_ENCODE:
   2224 		if (!xdr_nfs_fh3(xdrs, &objp->dir))
   2225 			return (FALSE);
   2226 		break;
   2227 	case XDR_DECODE:
   2228 		if (!xdr_nfs_fh3_server(xdrs, &objp->dir))
   2229 			return (FALSE);
   2230 		break;
   2231 	}
   2232 	if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
   2233 	    xdrs->x_op == XDR_ENCODE) {
   2234 		rci.rci_type = RCI_REPLY_CHUNK;
   2235 		rci.rci_len = objp->maxcount;
   2236 		XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
   2237 	}
   2238 
   2239 	if (!xdr_u_longlong_t(xdrs, &objp->cookie))
   2240 		return (FALSE);
   2241 	/*
   2242 	 * cookieverf is really an opaque 8 byte
   2243 	 * quantity, but we will treat it as a
   2244 	 * hyper for efficiency, the cost of
   2245 	 * a byteswap here saves bcopys elsewhere
   2246 	 */
   2247 	if (!xdr_u_longlong_t(xdrs, &objp->cookieverf))
   2248 		return (FALSE);
   2249 	if (!xdr_u_int(xdrs, &objp->dircount))
   2250 		return (FALSE);
   2251 	return (xdr_u_int(xdrs, &objp->maxcount));
   2252 }
   2253 
   2254 /*
   2255  * ENCODE ONLY
   2256  */
   2257 static bool_t
   2258 xdr_putdirpluslist(XDR *xdrs, READDIRPLUS3resok *objp)
   2259 {
   2260 	struct dirent64 *dp;
   2261 	char *name;
   2262 	int nents;
   2263 	bool_t true = TRUE;
   2264 	bool_t false = FALSE;
   2265 	fileid3 fileid;
   2266 	cookie3 cookie;
   2267 	entryplus3_info *infop;
   2268 
   2269 	if (xdrs->x_op != XDR_ENCODE)
   2270 		return (FALSE);
   2271 
   2272 	dp = (struct dirent64 *)objp->reply.entries;
   2273 	nents = objp->size;
   2274 	infop = objp->infop;
   2275 
   2276 	while (nents > 0) {
   2277 		if (dp->d_reclen == 0)
   2278 			return (FALSE);
   2279 		if (dp->d_ino != 0) {
   2280 			name = dp->d_name;
   2281 			fileid = (fileid3)(dp->d_ino);
   2282 			cookie = (cookie3)(dp->d_off);
   2283 			if (!xdr_bool(xdrs, &true) ||
   2284 			    !xdr_u_longlong_t(xdrs, &fileid) ||
   2285 			    !xdr_bytes(xdrs, &name, &infop->namelen, ~0) ||
   2286 			    !xdr_u_longlong_t(xdrs, &cookie) ||
   2287 			    !xdr_post_op_attr(xdrs, &infop->attr) ||
   2288 			    !xdr_post_op_fh3(xdrs, &infop->fh)) {
   2289 				return (FALSE);
   2290 			}
   2291 		}
   2292 		dp = nextdp(dp);
   2293 		infop++;
   2294 		nents--;
   2295 	}
   2296 
   2297 	if (!xdr_bool(xdrs, &false))
   2298 		return (FALSE);
   2299 	if (!xdr_bool(xdrs, &objp->reply.eof))
   2300 		return (FALSE);
   2301 	return (TRUE);
   2302 }
   2303 
   2304 bool_t
   2305 xdr_READDIRPLUS3res(XDR *xdrs, READDIRPLUS3res *objp)
   2306 {
   2307 	READDIRPLUS3resok *resokp;
   2308 
   2309 	/*
   2310 	 * ENCODE or FREE only
   2311 	 */
   2312 	if (xdrs->x_op == XDR_DECODE)
   2313 		return (FALSE);
   2314 
   2315 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
   2316 		return (FALSE);
   2317 	switch (objp->status) {
   2318 	case NFS3_OK:
   2319 		/* xdr_READDIRPLUS3resok */
   2320 		resokp = &objp->resok;
   2321 		if (!xdr_post_op_attr(xdrs, &resokp->dir_attributes))
   2322 			return (FALSE);
   2323 		/*
   2324 		 * cookieverf is really an opaque 8 byte
   2325 		 * quantity, but we will treat it as a
   2326 		 * hyper for efficiency, the cost of
   2327 		 * a byteswap here saves bcopys elsewhere
   2328 		 */
   2329 		if (!xdr_u_longlong_t(xdrs, &resokp->cookieverf))
   2330 			return (FALSE);
   2331 		if (xdrs->x_op == XDR_ENCODE) {
   2332 			if (!xdr_putdirpluslist(xdrs, resokp))
   2333 				return (FALSE);
   2334 		}
   2335 		break;
   2336 	default:
   2337 		return (xdr_post_op_attr(xdrs, &objp->resfail.dir_attributes));
   2338 	}
   2339 	return (TRUE);
   2340 }
   2341 
   2342 /*
   2343  * Decode readdirplus directly into a dirent64_t and do the DNLC caching.
   2344  */
   2345 bool_t
   2346 xdr_READDIRPLUS3vres(XDR *xdrs, READDIRPLUS3vres *objp)
   2347 {
   2348 	dirent64_t *dp;
   2349 	vnode_t *dvp;
   2350 	uint_t entries_size;
   2351 	int outcount = 0;
   2352 	vnode_t *nvp;
   2353 	rnode_t *rp;
   2354 	post_op_vattr pov;
   2355 	vattr_t va;
   2356 
   2357 	/*
   2358 	 * DECODE or FREE only
   2359 	 */
   2360 	if (xdrs->x_op == XDR_FREE)
   2361 		return (TRUE);
   2362 
   2363 	if (xdrs->x_op != XDR_DECODE)
   2364 		return (FALSE);
   2365 
   2366 	if (!XDR_GETINT32(xdrs, (int32_t *)&objp->status))
   2367 		return (FALSE);
   2368 
   2369 	if (!xdr_post_op_vattr(xdrs, &objp->dir_attributes))
   2370 		return (FALSE);
   2371 
   2372 	if (objp->status != NFS3_OK)
   2373 		return (TRUE);
   2374 
   2375 	/*
   2376 	 * cookieverf is really an opaque 8 byte
   2377 	 * quantity, but we will treat it as a
   2378 	 * hyper for efficiency, the cost of
   2379 	 * a byteswap here saves bcopys elsewhere
   2380 	 */
   2381 	if (!xdr_u_longlong_t(xdrs, &objp->cookieverf))
   2382 		return (FALSE);
   2383 
   2384 	dvp = objp->dir_attributes.fres.vp;
   2385 	rp = VTOR(dvp);
   2386 
   2387 	pov.fres.vap = &va;
   2388 	pov.fres.vp = dvp;
   2389 
   2390 	entries_size = objp->entries_size;
   2391 	dp = objp->entries;
   2392 
   2393 	for (;;) {
   2394 		uint_t this_reclen;
   2395 		bool_t valid;
   2396 		uint_t namlen;
   2397 		nfs_fh3 fh;
   2398 		int va_valid;
   2399 		int fh_valid;
   2400 		ino64_t fileid;
   2401 
   2402 		if (!XDR_GETINT32(xdrs, (int32_t *)&valid))
   2403 			return (FALSE);
   2404 		if (!valid) {
   2405 			/*
   2406 			 * We have run out of entries, decode eof.
   2407 			 */
   2408 			if (!XDR_GETINT32(xdrs, (int32_t *)&objp->eof))
   2409 				return (FALSE);
   2410 
   2411 			break;
   2412 		}
   2413 
   2414 		/*
   2415 		 * fileid3 fileid
   2416 		 */
   2417 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&fileid))
   2418 			return (FALSE);
   2419 
   2420 		/*
   2421 		 * filename3 name
   2422 		 */
   2423 		if (!XDR_GETINT32(xdrs, (int32_t *)&namlen))
   2424 			return (FALSE);
   2425 		this_reclen = DIRENT64_RECLEN(namlen);
   2426 
   2427 		/*
   2428 		 * If this will overflow buffer, stop decoding
   2429 		 */
   2430 		if ((outcount + this_reclen) > entries_size) {
   2431 			objp->eof = FALSE;
   2432 			break;
   2433 		}
   2434 		dp->d_reclen = this_reclen;
   2435 		dp->d_ino = fileid;
   2436 
   2437 		if (!xdr_opaque(xdrs, dp->d_name, namlen))
   2438 			return (FALSE);
   2439 		bzero(&dp->d_name[namlen],
   2440 		    DIRENT64_NAMELEN(this_reclen) - namlen);
   2441 
   2442 		/*
   2443 		 * cookie3 cookie
   2444 		 */
   2445 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&dp->d_off))
   2446 			return (FALSE);
   2447 		objp->loff = dp->d_off;
   2448 
   2449 		/*
   2450 		 * post_op_attr name_attributes
   2451 		 */
   2452 		if (!xdr_post_op_vattr(xdrs, &pov))
   2453 			return (FALSE);
   2454 
   2455 		if (pov.attributes == TRUE &&
   2456 		    pov.fres.status == NFS3_OK)
   2457 			va_valid = TRUE;
   2458 		else
   2459 			va_valid = FALSE;
   2460 
   2461 		/*
   2462 		 * post_op_fh3 name_handle
   2463 		 */
   2464 		if (!XDR_GETINT32(xdrs, (int32_t *)&fh_valid))
   2465 			return (FALSE);
   2466 
   2467 		/*
   2468 		 * By definition of the standard fh_valid can be 0 (FALSE) or
   2469 		 * 1 (TRUE), but we have to account for it being anything else
   2470 		 * in case some other system didn't follow the standard.  Note
   2471 		 * that this is why the else checks if the fh_valid variable
   2472 		 * is != FALSE.
   2473 		 */
   2474 		if (fh_valid == TRUE) {
   2475 			if (!xdr_nfs_fh3(xdrs, &fh))
   2476 				return (FALSE);
   2477 		} else {
   2478 			if (fh_valid != FALSE)
   2479 				return (FALSE);
   2480 		}
   2481 
   2482 		/*
   2483 		 * If the name is "." or there are no attributes,
   2484 		 * don't polute the DNLC with "." entries or files
   2485 		 * we cannot determine the type for.
   2486 		 */
   2487 		if (!(namlen == 1 && dp->d_name[0] == '.') &&
   2488 		    va_valid && fh_valid) {
   2489 
   2490 			/*
   2491 			 * Do the DNLC caching
   2492 			 */
   2493 			nvp = makenfs3node_va(&fh, &va, dvp->v_vfsp,
   2494 			    objp->time, objp->credentials,
   2495 			    rp->r_path, dp->d_name);
   2496 			dnlc_update(dvp, dp->d_name, nvp);
   2497 			VN_RELE(nvp);
   2498 		}
   2499 
   2500 		outcount += this_reclen;
   2501 		dp = (dirent64_t *)((intptr_t)dp + this_reclen);
   2502 	}
   2503 
   2504 	objp->size = outcount;
   2505 	return (TRUE);
   2506 }
   2507 
   2508 bool_t
   2509 xdr_FSSTAT3res(XDR *xdrs, FSSTAT3res *objp)
   2510 {
   2511 	FSSTAT3resok *resokp;
   2512 
   2513 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
   2514 		return (FALSE);
   2515 	if (objp->status != NFS3_OK)
   2516 		return (xdr_post_op_attr(xdrs, &objp->resfail.obj_attributes));
   2517 
   2518 	/* xdr_FSSTAT3resok */
   2519 	resokp = &objp->resok;
   2520 	if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
   2521 		return (FALSE);
   2522 	if (!xdr_u_longlong_t(xdrs, &resokp->tbytes))
   2523 		return (FALSE);
   2524 	if (!xdr_u_longlong_t(xdrs, &resokp->fbytes))
   2525 		return (FALSE);
   2526 	if (!xdr_u_longlong_t(xdrs, &resokp->abytes))
   2527 		return (FALSE);
   2528 	if (!xdr_u_longlong_t(xdrs, &resokp->tfiles))
   2529 		return (FALSE);
   2530 	if (!xdr_u_longlong_t(xdrs, &resokp->ffiles))
   2531 		return (FALSE);
   2532 	if (!xdr_u_longlong_t(xdrs, &resokp->afiles))
   2533 		return (FALSE);
   2534 	return (xdr_u_int(xdrs, &resokp->invarsec));
   2535 }
   2536 
   2537 bool_t
   2538 xdr_FSINFO3res(XDR *xdrs, FSINFO3res *objp)
   2539 {
   2540 	FSINFO3resok *resokp;
   2541 
   2542 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
   2543 		return (FALSE);
   2544 	if (objp->status != NFS3_OK) /* xdr_FSSTAT3resfail */
   2545 		return (xdr_post_op_attr(xdrs, &objp->resfail.obj_attributes));
   2546 
   2547 	/* xdr_FSINFO3resok */
   2548 	resokp = &objp->resok;
   2549 	if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
   2550 		return (FALSE);
   2551 	if (!xdr_u_int(xdrs, &resokp->rtmax))
   2552 		return (FALSE);
   2553 	if (!xdr_u_int(xdrs, &resokp->rtpref))
   2554 		return (FALSE);
   2555 	if (!xdr_u_int(xdrs, &resokp->rtmult))
   2556 		return (FALSE);
   2557 	if (!xdr_u_int(xdrs, &resokp->wtmax))
   2558 		return (FALSE);
   2559 	if (!xdr_u_int(xdrs, &resokp->wtpref))
   2560 		return (FALSE);
   2561 	if (!xdr_u_int(xdrs, &resokp->wtmult))
   2562 		return (FALSE);
   2563 	if (!xdr_u_int(xdrs, &resokp->dtpref))
   2564 		return (FALSE);
   2565 	if (!xdr_u_longlong_t(xdrs, &resokp->maxfilesize))
   2566 		return (FALSE);
   2567 	if (!xdr_u_int(xdrs, &resokp->time_delta.seconds))
   2568 		return (FALSE);
   2569 	if (!xdr_u_int(xdrs, &resokp->time_delta.nseconds))
   2570 		return (FALSE);
   2571 	return (xdr_u_int(xdrs, &resokp->properties));
   2572 }
   2573 
   2574 bool_t
   2575 xdr_PATHCONF3res(XDR *xdrs, PATHCONF3res *objp)
   2576 {
   2577 	PATHCONF3resok *resokp;
   2578 
   2579 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
   2580 		return (FALSE);
   2581 	if (objp->status != NFS3_OK)
   2582 		return (xdr_post_op_attr(xdrs, &objp->resfail.obj_attributes));
   2583 
   2584 	/* xdr_PATHCONF3resok */
   2585 	resokp = &objp->resok;
   2586 	if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
   2587 		return (FALSE);
   2588 	if (!xdr_u_int(xdrs, &resokp->info.link_max))
   2589 		return (FALSE);
   2590 	if (!xdr_u_int(xdrs, &resokp->info.name_max))
   2591 		return (FALSE);
   2592 	if (!xdr_bool(xdrs, &resokp->info.no_trunc))
   2593 		return (FALSE);
   2594 	if (!xdr_bool(xdrs, &resokp->info.chown_restricted))
   2595 		return (FALSE);
   2596 	if (!xdr_bool(xdrs, &resokp->info.case_insensitive))
   2597 		return (FALSE);
   2598 	return (xdr_bool(xdrs, &resokp->info.case_preserving));
   2599 }
   2600 
   2601 bool_t
   2602 xdr_COMMIT3args(XDR *xdrs, COMMIT3args *objp)
   2603 {
   2604 	if (xdrs->x_op == XDR_FREE)
   2605 		return (TRUE);
   2606 
   2607 	switch (xdrs->x_op) {
   2608 	case XDR_FREE:
   2609 	case XDR_ENCODE:
   2610 		if (!xdr_nfs_fh3(xdrs, &objp->file))
   2611 			return (FALSE);
   2612 		break;
   2613 	case XDR_DECODE:
   2614 		if (!xdr_nfs_fh3_server(xdrs, &objp->file))
   2615 			return (FALSE);
   2616 		break;
   2617 	}
   2618 	if (!xdr_u_longlong_t(xdrs, &objp->offset))
   2619 		return (FALSE);
   2620 	return (xdr_u_int(xdrs, &objp->count));
   2621 }
   2622 
   2623 bool_t
   2624 xdr_COMMIT3res(XDR *xdrs, COMMIT3res *objp)
   2625 {
   2626 	COMMIT3resok *resokp;
   2627 
   2628 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
   2629 		return (FALSE);
   2630 	if (objp->status != NFS3_OK)
   2631 		return (xdr_wcc_data(xdrs, &objp->resfail.file_wcc));
   2632 
   2633 	/* xdr_COMMIT3resok */
   2634 	resokp = &objp->resok;
   2635 	if (!xdr_wcc_data(xdrs, &resokp->file_wcc))
   2636 		return (FALSE);
   2637 	/*
   2638 	 * writeverf3 is really an opaque 8 byte
   2639 	 * quantity, but we will treat it as a
   2640 	 * hyper for efficiency, the cost of
   2641 	 * a byteswap here saves bcopys elsewhere
   2642 	 */
   2643 	return (xdr_u_longlong_t(xdrs, &resokp->verf));
   2644 }
   2645