xref: /titanic_41/usr/src/uts/common/fs/nfs/nfs4_xdr.c (revision dfb96a4f56fb431b915bc67e5d9d5c8d4f4f6679)
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 2006 Sun Microsystems, Inc.
23  *	All rights reserved.  Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * A handcoded version based on the original rpcgen code.
30  *
31  * Note: All future NFS4 protocol changes should be added by hand
32  * to this file.
33  *
34  * CAUTION: All protocol changes must also be propagated to:
35  *     usr/src/cmd/cmd-inet/usr.sbin/snoop/nfs4_xdr.c
36  */
37 
38 #include <sys/types.h>
39 #include <sys/sunddi.h>
40 #include <sys/dnlc.h>
41 #include <nfs/nfs.h>
42 #include <nfs/nfs4_kprot.h>
43 #include <nfs/rnode4.h>
44 #include <nfs/nfs4.h>
45 #include <nfs/nfs4_clnt.h>
46 #include <sys/sdt.h>
47 #include <rpc/rpc_rdma.h>
48 
49 bool_t
50 xdr_bitmap4(XDR *xdrs, bitmap4 *objp)
51 {
52 	int32_t len, size;
53 
54 	if (xdrs->x_op == XDR_FREE)
55 		return (TRUE);
56 
57 	/*
58 	 * Simplified bitmap4 processing, always encode from uint64_t
59 	 * to 2 uint32_t's, always decode first 2 uint32_t's into a
60 	 * uint64_t and ignore all of the rest.
61 	 */
62 	if (xdrs->x_op == XDR_ENCODE) {
63 		len = 2;
64 
65 		if (!XDR_PUTINT32(xdrs, &len))
66 			return (FALSE);
67 
68 #if defined(_LITTLE_ENDIAN)
69 		if (XDR_PUTINT32(xdrs, (int32_t *)((char *)objp +
70 						BYTES_PER_XDR_UNIT)) == TRUE) {
71 			return (XDR_PUTINT32(xdrs, (int32_t *)objp));
72 		}
73 #elif defined(_BIG_ENDIAN)
74 		if (XDR_PUTINT32(xdrs, (int32_t *)objp) == TRUE) {
75 			return (XDR_PUTINT32(xdrs, (int32_t *)((char *)objp +
76 						BYTES_PER_XDR_UNIT)));
77 		}
78 #endif
79 		return (FALSE);
80 	}
81 
82 	if (!XDR_GETINT32(xdrs, &len))
83 		return (FALSE);
84 
85 	/*
86 	 * Common fast DECODE cases
87 	 */
88 	if (len == 2) {
89 #if defined(_LITTLE_ENDIAN)
90 		if (XDR_GETINT32(xdrs, (int32_t *)((char *)objp +
91 					BYTES_PER_XDR_UNIT)) == TRUE) {
92 			return (XDR_GETINT32(xdrs, (int32_t *)objp));
93 		}
94 #elif defined(_BIG_ENDIAN)
95 		if (XDR_GETINT32(xdrs, (int32_t *)objp) == TRUE) {
96 			return (XDR_GETINT32(xdrs, (int32_t *)((char *)objp +
97 					BYTES_PER_XDR_UNIT)));
98 		}
99 #endif
100 		return (FALSE);
101 	}
102 
103 	*objp = 0;
104 	if (len == 0)
105 		return (TRUE);
106 
107 	/*
108 	 * The not so common DECODE cases, len == 1 || len > 2
109 	 */
110 #if defined(_LITTLE_ENDIAN)
111 	if (!XDR_GETINT32(xdrs, (int32_t *)((char *)objp + BYTES_PER_XDR_UNIT)))
112 		return (FALSE);
113 	if (--len == 0)
114 		return (TRUE);
115 	if (!XDR_GETINT32(xdrs, (int32_t *)objp))
116 		return (FALSE);
117 #elif defined(_BIG_ENDIAN)
118 	if (!XDR_GETINT32(xdrs, (int32_t *)objp))
119 		return (FALSE);
120 	if (--len == 0)
121 		return (TRUE);
122 	if (!XDR_GETINT32(xdrs, (int32_t *)((char *)objp + BYTES_PER_XDR_UNIT)))
123 		return (FALSE);
124 #else
125 	return (FALSE);
126 #endif
127 
128 	if (--len == 0)
129 		return (TRUE);
130 
131 	size = len * BYTES_PER_XDR_UNIT;
132 	return (XDR_CONTROL(xdrs, XDR_SKIPBYTES, &size));
133 }
134 
135 /* Called by xdr_array, nfsid_map_xdr */
136 bool_t
137 xdr_utf8string(XDR *xdrs, utf8string *objp)
138 {
139 	if (xdrs->x_op != XDR_FREE)
140 		return (xdr_bytes(xdrs, (char **)&objp->utf8string_val,
141 			(uint_t *)&objp->utf8string_len, NFS4_MAX_UTF8STRING));
142 
143 	if (objp->utf8string_val != NULL) {
144 		kmem_free(objp->utf8string_val, objp->utf8string_len);
145 		objp->utf8string_val = NULL;
146 	}
147 	return (TRUE);
148 }
149 
150 /*
151  * XDR_INLINE decode a filehandle.
152  */
153 bool_t
154 xdr_inline_decode_nfs_fh4(uint32_t *ptr, nfs_fh4_fmt_t *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 (nfs_fh4_fmt_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 fh4_fsid, it is aligned.
177 	 */
178 	fhp->fh4_fsid.val[0] = *(uint32_t *)bp;
179 	bp += BYTES_PER_XDR_UNIT;
180 	fhp->fh4_fsid.val[1] = *(uint32_t *)bp;
181 	bp += BYTES_PER_XDR_UNIT;
182 
183 	/*
184 	 * Decode what should be fh4_len.  fh4_len is two bytes, so we're
185 	 * unaligned now.
186 	 */
187 	cp = (uchar_t *)&fhp->fh4_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->fh4_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_len;
197 
198 	/*
199 	 * Make sure the client isn't sending us a bogus length for fh4_data.
200 	 */
201 	if (fhsize < dsize)
202 		return (FALSE);
203 	bcopy(bp, fhp->fh4_data, dsize);
204 	bp += dsize;
205 	fhsize -= dsize;
206 
207 	if (fhsize < sizeof (ushort_t))
208 		return (FALSE);
209 	cp = (uchar_t *)&fhp->fh4_xlen;
210 	*cp++ = *bp++;
211 	*cp++ = *bp++;
212 	fhsize -= sizeof (ushort_t);
213 
214 	dsize = fhp->fh4_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_xlen;
215 
216 	/*
217 	 * Make sure the client isn't sending us a bogus length for fh4_xdata.
218 	 */
219 	if (fhsize < dsize)
220 		return (FALSE);
221 	bcopy(bp, fhp->fh4_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 	if (fhsize < BYTES_PER_XDR_UNIT)
237 		return (FALSE);
238 	fhp->fh4_flag = *(uint32_t *)bp;
239 	bp += BYTES_PER_XDR_UNIT;
240 	fhsize -= BYTES_PER_XDR_UNIT;
241 
242 #ifdef VOLATILE_FH_TEST
243 	if (fhsize < BYTES_PER_XDR_UNIT)
244 		return (FALSE);
245 	fhp->fh4_volatile_id = *(uint32_t *)bp;
246 	bp += BYTES_PER_XDR_UNIT;
247 	fhsize -= BYTES_PER_XDR_UNIT;
248 #endif
249 	/*
250 	 * Make sure client didn't send extra bytes
251 	 */
252 	if (fhsize != 0)
253 		return (FALSE);
254 	return (TRUE);
255 }
256 
257 static bool_t
258 xdr_decode_nfs_fh4(XDR *xdrs, nfs_fh4 *objp)
259 {
260 	uint32_t fhsize;		/* filehandle size */
261 	uint32_t bufsize;
262 	rpc_inline_t *ptr;
263 	uchar_t *bp;
264 
265 	ASSERT(xdrs->x_op == XDR_DECODE);
266 
267 	/*
268 	 * Retrieve the filehandle length.
269 	 */
270 	if (!XDR_GETINT32(xdrs, (int32_t *)&fhsize))
271 		return (FALSE);
272 
273 	objp->nfs_fh4_val = NULL;
274 	objp->nfs_fh4_len = 0;
275 
276 	/*
277 	 * Check to see if what the client sent us is bigger or smaller
278 	 * than what we can ever possibly send out. NFS_FHMAXDATA is
279 	 * unfortunately badly named as it is no longer the max and is
280 	 * really the min of what is sent over the wire.
281 	 */
282 	if (fhsize > sizeof (nfs_fh4_fmt_t) || fhsize < (sizeof (fsid_t) +
283 	    sizeof (ushort_t) + NFS_FHMAXDATA +
284 	    sizeof (ushort_t) + NFS_FHMAXDATA)) {
285 		if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &fhsize))
286 			return (FALSE);
287 		return (TRUE);
288 	}
289 
290 	/*
291 	 * bring in fhsize plus any padding
292 	 */
293 	bufsize = RNDUP(fhsize);
294 	ptr = XDR_INLINE(xdrs, bufsize);
295 	bp = (uchar_t *)ptr;
296 	if (ptr == NULL) {
297 		bp = kmem_alloc(bufsize, KM_SLEEP);
298 		if (!xdr_opaque(xdrs, (char *)bp, bufsize)) {
299 			kmem_free(bp, bufsize);
300 			return (FALSE);
301 		}
302 	}
303 
304 	objp->nfs_fh4_val = kmem_zalloc(sizeof (nfs_fh4_fmt_t), KM_SLEEP);
305 	objp->nfs_fh4_len = sizeof (nfs_fh4_fmt_t);
306 
307 	if (xdr_inline_decode_nfs_fh4((uint32_t *)bp,
308 	    (nfs_fh4_fmt_t *)objp->nfs_fh4_val, fhsize) == FALSE) {
309 		/*
310 		 * If in the process of decoding we find the file handle
311 		 * is not correctly formed, we need to continue decoding
312 		 * and trigger an NFS layer error. Set the nfs_fh4_len to
313 		 * zero so it gets caught as a bad length.
314 		 */
315 		kmem_free(objp->nfs_fh4_val, objp->nfs_fh4_len);
316 		objp->nfs_fh4_val = NULL;
317 		objp->nfs_fh4_len = 0;
318 	}
319 
320 	if (ptr == NULL)
321 		kmem_free(bp, bufsize);
322 	return (TRUE);
323 }
324 
325 /*
326  * XDR_INLINE encode a filehandle.
327  */
328 bool_t
329 xdr_inline_encode_nfs_fh4(uint32_t **ptrp, uint32_t *ptr_redzone,
330 	nfs_fh4_fmt_t *fhp)
331 {
332 	uint32_t *ptr = *ptrp;
333 	uchar_t *cp;
334 	uint_t otw_len, fsize, xsize;   /* otw, file, and export sizes */
335 	uint32_t padword;
336 
337 	fsize = fhp->fh4_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_len;
338 	xsize = fhp->fh4_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_xlen;
339 
340 	/*
341 	 * First get the initial and variable sized part of the filehandle.
342 	 */
343 	otw_len = sizeof (fhp->fh4_fsid) +
344 	    sizeof (fhp->fh4_len) + fsize +
345 	    sizeof (fhp->fh4_xlen) + xsize;
346 
347 	/*
348 	 * Round out to a full word.
349 	 */
350 	otw_len = RNDUP(otw_len);
351 	padword = (otw_len / BYTES_PER_XDR_UNIT);	/* includes fhlen */
352 
353 	/*
354 	 * Add in the fixed sized pieces.
355 	 */
356 	otw_len += sizeof (fhp->fh4_flag);
357 #ifdef VOLATILE_FH_TEST
358 	otw_len += sizeof (fhp->fh4_volatile_id);
359 #endif
360 
361 	/*
362 	 * Make sure we don't exceed our buffer.
363 	 */
364 	if ((ptr + (otw_len / BYTES_PER_XDR_UNIT) + 1) > ptr_redzone)
365 		return (FALSE);
366 
367 	/*
368 	 * Zero out the padding.
369 	 */
370 	ptr[padword] = 0;
371 
372 	IXDR_PUT_U_INT32(ptr, otw_len);
373 
374 	/*
375 	 * The rest of the filehandle is in native byteorder
376 	 */
377 	/* fh4_fsid */
378 	*ptr++ = (uint32_t)fhp->fh4_fsid.val[0];
379 	*ptr++ = (uint32_t)fhp->fh4_fsid.val[1];
380 
381 	/*
382 	 * Since the next pieces are unaligned, we need to
383 	 * do bytewise copies.
384 	 */
385 	cp = (uchar_t *)ptr;
386 
387 	/* fh4_len + fh4_data */
388 	bcopy(&fhp->fh4_len, cp, sizeof (fhp->fh4_len) + fsize);
389 	cp += sizeof (fhp->fh4_len) + fsize;
390 
391 	/* fh4_xlen + fh4_xdata */
392 	bcopy(&fhp->fh4_xlen, cp, sizeof (fhp->fh4_xlen) + xsize);
393 	cp += sizeof (fhp->fh4_xlen) + xsize;
394 
395 	/* do necessary rounding/padding */
396 	cp = (uchar_t *)RNDUP((uintptr_t)cp);
397 	ptr = (uint32_t *)cp;
398 
399 	/*
400 	 * With the above padding, we're word aligned again.
401 	 */
402 	ASSERT(((uintptr_t)ptr % BYTES_PER_XDR_UNIT) == 0);
403 
404 	/* fh4_flag */
405 	*ptr++ = (uint32_t)fhp->fh4_flag;
406 
407 #ifdef VOLATILE_FH_TEST
408 	/* fh4_volatile_id */
409 	*ptr++ = (uint32_t)fhp->fh4_volatile_id;
410 #endif
411 	*ptrp = ptr;
412 
413 	return (TRUE);
414 }
415 
416 static bool_t
417 xdr_encode_nfs_fh4(XDR *xdrs, nfs_fh4 *objp)
418 {
419 	uint_t otw_len, fsize, xsize;   /* otw, file, and export sizes */
420 	bool_t ret;
421 	rpc_inline_t *ptr;
422 	rpc_inline_t *buf = NULL;
423 	uint32_t *ptr_redzone;
424 	nfs_fh4_fmt_t *fhp;
425 
426 	ASSERT(xdrs->x_op == XDR_ENCODE);
427 
428 	fhp = (nfs_fh4_fmt_t *)objp->nfs_fh4_val;
429 	fsize = fhp->fh4_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_len;
430 	xsize = fhp->fh4_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_xlen;
431 
432 	/*
433 	 * First get the over the wire size, it is the 4 bytes
434 	 * for the length, plus the combined size of the
435 	 * file handle components.
436 	 */
437 	otw_len = BYTES_PER_XDR_UNIT + sizeof (fhp->fh4_fsid) +
438 	    sizeof (fhp->fh4_len) + fsize +
439 	    sizeof (fhp->fh4_xlen) + xsize +
440 	    sizeof (fhp->fh4_flag);
441 #ifdef VOLATILE_FH_TEST
442 	otw_len += sizeof (fhp->fh4_volatile_id);
443 #endif
444 	/*
445 	 * Round out to a full word.
446 	 */
447 	otw_len = RNDUP(otw_len);
448 
449 	/*
450 	 * Next try to inline the XDR stream, if that fails (rare)
451 	 * allocate a buffer to encode the file handle and then
452 	 * copy it using xdr_opaque and free the buffer.
453 	 */
454 	ptr = XDR_INLINE(xdrs, otw_len);
455 	if (ptr == NULL)
456 		ptr = buf = kmem_alloc(otw_len, KM_SLEEP);
457 
458 	ptr_redzone = (uint32_t *)(ptr + (otw_len / BYTES_PER_XDR_UNIT));
459 	ret = xdr_inline_encode_nfs_fh4((uint32_t **)&ptr, ptr_redzone, fhp);
460 
461 	if (buf != NULL) {
462 		if (ret == TRUE)
463 			ret = xdr_opaque(xdrs, (char *)buf, otw_len);
464 		kmem_free(buf, otw_len);
465 	}
466 	return (ret);
467 }
468 
469 /*
470  * XDR a NFSv4 filehandle.
471  * Encoding interprets the contents (server).
472  * Decoding the contents are opaque (client).
473  */
474 bool_t
475 xdr_nfs_fh4(XDR *xdrs, nfs_fh4 *objp)
476 {
477 	switch (xdrs->x_op) {
478 	case XDR_ENCODE:
479 		return (xdr_encode_nfs_fh4(xdrs, objp));
480 	case XDR_DECODE:
481 		return (xdr_bytes(xdrs, (char **)&objp->nfs_fh4_val,
482 		    (uint_t *)&objp->nfs_fh4_len, NFS4_FHSIZE));
483 	case XDR_FREE:
484 		if (objp->nfs_fh4_val != NULL) {
485 			kmem_free(objp->nfs_fh4_val, objp->nfs_fh4_len);
486 			objp->nfs_fh4_val = NULL;
487 		}
488 		return (TRUE);
489 	}
490 	return (FALSE);
491 }
492 
493 /* Called by xdr_array */
494 static bool_t
495 xdr_fs_location4(XDR *xdrs, fs_location4 *objp)
496 {
497 	if (!xdr_array(xdrs, (char **)&objp->server_val,
498 			(uint_t *)&objp->server_len, NFS4_FS_LOCATIONS_LIMIT,
499 			sizeof (utf8string), (xdrproc_t)xdr_utf8string))
500 		return (FALSE);
501 	return (xdr_array(xdrs, (char **)&objp->rootpath.pathname4_val,
502 			(uint_t *)&objp->rootpath.pathname4_len,
503 			NFS4_MAX_PATHNAME4,
504 			sizeof (utf8string), (xdrproc_t)xdr_utf8string));
505 }
506 
507 /* Called by xdr_array */
508 static bool_t
509 xdr_nfsace4(XDR *xdrs, nfsace4 *objp)
510 {
511 	if (xdrs->x_op != XDR_FREE) {
512 		if (!xdr_u_int(xdrs, &objp->type))
513 			return (FALSE);
514 		if (!xdr_u_int(xdrs, &objp->flag))
515 			return (FALSE);
516 		if (!xdr_u_int(xdrs, &objp->access_mask))
517 			return (FALSE);
518 
519 		if (xdrs->x_op == XDR_DECODE) {
520 			objp->who.utf8string_val = NULL;
521 			objp->who.utf8string_len = 0;
522 		}
523 
524 		return (xdr_bytes(xdrs, (char **)&objp->who.utf8string_val,
525 			(uint_t *)&objp->who.utf8string_len,
526 			NFS4_MAX_UTF8STRING));
527 	}
528 
529 	/*
530 	 * Optimized free case
531 	 */
532 	if (objp->who.utf8string_val != NULL) {
533 		kmem_free(objp->who.utf8string_val, objp->who.utf8string_len);
534 		objp->who.utf8string_val = NULL;
535 	}
536 	return (TRUE);
537 }
538 
539 /*
540  * These functions are called out of nfs4_attr.c
541  */
542 bool_t
543 xdr_fattr4_fsid(XDR *xdrs, fattr4_fsid *objp)
544 {
545 	if (xdrs->x_op == XDR_FREE)
546 		return (TRUE);
547 
548 	if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->major))
549 		return (FALSE);
550 	return (xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->minor));
551 }
552 
553 
554 bool_t
555 xdr_fattr4_acl(XDR *xdrs, fattr4_acl *objp)
556 {
557 	return (xdr_array(xdrs, (char **)&objp->fattr4_acl_val,
558 			(uint_t *)&objp->fattr4_acl_len, NFS4_ACL_LIMIT,
559 			sizeof (nfsace4), (xdrproc_t)xdr_nfsace4));
560 }
561 
562 bool_t
563 xdr_fattr4_fs_locations(XDR *xdrs, fattr4_fs_locations *objp)
564 {
565 	if (!xdr_array(xdrs, (char **)&objp->fs_root.pathname4_val,
566 			(uint_t *)&objp->fs_root.pathname4_len,
567 			NFS4_MAX_PATHNAME4,
568 			sizeof (utf8string), (xdrproc_t)xdr_utf8string))
569 		return (FALSE);
570 	return (xdr_array(xdrs, (char **)&objp->locations_val,
571 			(uint_t *)&objp->locations_len, NFS4_FS_LOCATIONS_LIMIT,
572 			sizeof (fs_location4), (xdrproc_t)xdr_fs_location4));
573 }
574 
575 bool_t
576 xdr_fattr4_rawdev(XDR *xdrs, fattr4_rawdev *objp)
577 {
578 	if (xdrs->x_op == XDR_FREE)
579 		return (TRUE);
580 
581 	if (!xdr_u_int(xdrs, &objp->specdata1))
582 		return (FALSE);
583 	return (xdr_u_int(xdrs, &objp->specdata2));
584 }
585 
586 bool_t
587 xdr_nfstime4(XDR *xdrs, nfstime4 *objp)
588 {
589 	if (xdrs->x_op == XDR_FREE)
590 		return (TRUE);
591 
592 	if (!xdr_longlong_t(xdrs, (longlong_t *)&objp->seconds))
593 		return (FALSE);
594 	return (xdr_u_int(xdrs, &objp->nseconds));
595 }
596 
597 
598 /*
599  * structured used for calls into xdr_ga_fattr_res() as a means
600  * to do an immediate/short-term cache of owner/group strings
601  * for callers like the readdir processing.  In the case of readdir,
602  * it is likely that the directory objects will be owned by the same
603  * owner/group and if so there is no need to call into the uid/gid
604  * mapping code.  While the uid/gid interfaces have their own cache
605  * having one here will reduct pathlength further.
606  */
607 #define	MAX_OG_NAME 100
608 typedef struct ug_cache
609 {
610 	uid_t	uid;
611 	gid_t	gid;
612 	utf8string u_curr, u_last;
613 	utf8string g_curr, g_last;
614 	char	u_buf1[MAX_OG_NAME];
615 	char	u_buf2[MAX_OG_NAME];
616 	char	g_buf1[MAX_OG_NAME];
617 	char	g_buf2[MAX_OG_NAME];
618 } ug_cache_t;
619 
620 #define	U_SWAP_CURR_LAST(ug) \
621 	(ug)->u_last.utf8string_len = (ug)->u_curr.utf8string_len;	\
622 	if ((ug)->u_last.utf8string_val == (ug)->u_buf1) {		\
623 		(ug)->u_last.utf8string_val = (ug)->u_buf2;		\
624 		(ug)->u_curr.utf8string_val = (ug)->u_buf1;		\
625 	} else {							\
626 		(ug)->u_last.utf8string_val = (ug)->u_buf1;		\
627 		(ug)->u_curr.utf8string_val = (ug)->u_buf2;		\
628 	}
629 
630 #define	G_SWAP_CURR_LAST(ug) \
631 	(ug)->g_last.utf8string_len = (ug)->g_curr.utf8string_len;	\
632 	if ((ug)->g_last.utf8string_val == (ug)->g_buf1) {		\
633 		(ug)->g_last.utf8string_val = (ug)->g_buf2;		\
634 		(ug)->g_curr.utf8string_val = (ug)->g_buf1;		\
635 	} else {							\
636 		(ug)->g_last.utf8string_val = (ug)->g_buf1;		\
637 		(ug)->g_curr.utf8string_val = (ug)->g_buf2;		\
638 	}
639 
640 static ug_cache_t *
641 alloc_ugcache()
642 {
643 	ug_cache_t *pug = kmem_alloc(sizeof (ug_cache_t), KM_SLEEP);
644 
645 	pug->uid = pug->gid = 0;
646 	pug->u_curr.utf8string_len = 0;
647 	pug->u_last.utf8string_len = 0;
648 	pug->g_curr.utf8string_len = 0;
649 	pug->g_last.utf8string_len = 0;
650 	pug->u_curr.utf8string_val = pug->u_buf1;
651 	pug->u_last.utf8string_val = pug->u_buf2;
652 	pug->g_curr.utf8string_val = pug->g_buf1;
653 	pug->g_last.utf8string_val = pug->g_buf2;
654 
655 	return (pug);
656 }
657 
658 static void
659 xdr_ga_prefill_vattr(struct nfs4_ga_res *garp, struct mntinfo4 *mi)
660 {
661 	static vattr_t s_vattr = {
662 		AT_ALL,		/* va_mask */
663 		VNON,		/* va_type */
664 		0777,		/* va_mode */
665 		UID_NOBODY,	/* va_uid */
666 		GID_NOBODY,	/* va_gid */
667 		0,		/* va_fsid */
668 		0,		/* va_nodeid */
669 		1,		/* va_nlink */
670 		0,		/* va_size */
671 		{0, 0},		/* va_atime */
672 		{0, 0},		/* va_mtime */
673 		{0, 0},		/* va_ctime */
674 		0,		/* va_rdev */
675 		MAXBSIZE,	/* va_blksize */
676 		0,		/* va_nblocks */
677 		0		/* va_seq */
678 	};
679 
680 
681 	garp->n4g_va = s_vattr;
682 	garp->n4g_va.va_fsid = mi->mi_vfsp->vfs_dev;
683 	hrt2ts(gethrtime(), &garp->n4g_va.va_atime);
684 	garp->n4g_va.va_mtime = garp->n4g_va.va_ctime = garp->n4g_va.va_atime;
685 }
686 
687 static void
688 xdr_ga_prefill_statvfs(struct nfs4_ga_ext_res *gesp, struct mntinfo4 *mi)
689 {
690 	static statvfs64_t s_sb = {
691 		MAXBSIZE,	/* f_bsize */
692 		DEV_BSIZE,	/* f_frsize */
693 		(fsfilcnt64_t)-1, /* f_blocks */
694 		(fsfilcnt64_t)-1, /* f_bfree */
695 		(fsfilcnt64_t)-1, /* f_bavail */
696 		(fsfilcnt64_t)-1, /* f_files */
697 		(fsfilcnt64_t)-1, /* f_ffree */
698 		(fsfilcnt64_t)-1, /* f_favail */
699 		0,		/* f_fsid */
700 		"\0",		/* f_basetype */
701 		0,		/* f_flag */
702 		MAXNAMELEN,	/* f_namemax */
703 		"\0",		/* f_fstr */
704 	};
705 
706 	gesp->n4g_sb = s_sb;
707 	gesp->n4g_sb.f_fsid = mi->mi_vfsp->vfs_fsid.val[0];
708 }
709 
710 static bool_t
711 xdr_ga_fattr_res(XDR *xdrs, struct nfs4_ga_res *garp, bitmap4 resbmap,
712 		bitmap4 argbmap, struct mntinfo4 *mi, ug_cache_t *pug)
713 {
714 	int truefalse;
715 	struct nfs4_ga_ext_res ges, *gesp;
716 	vattr_t *vap = &garp->n4g_va;
717 	vsecattr_t *vsap = &garp->n4g_vsa;
718 
719 	ASSERT(xdrs->x_op == XDR_DECODE);
720 
721 	if (garp->n4g_ext_res)
722 		gesp = garp->n4g_ext_res;
723 	else
724 		gesp = &ges;
725 
726 	vap->va_mask = 0;
727 
728 	/* Check to see if the vattr should be pre-filled */
729 	if (argbmap & NFS4_VATTR_MASK)
730 		xdr_ga_prefill_vattr(garp, mi);
731 
732 	if (argbmap & NFS4_STATFS_ATTR_MASK)
733 		xdr_ga_prefill_statvfs(gesp, mi);
734 
735 	if (resbmap &
736 	    (FATTR4_SUPPORTED_ATTRS_MASK |
737 	    FATTR4_TYPE_MASK |
738 	    FATTR4_FH_EXPIRE_TYPE_MASK |
739 	    FATTR4_CHANGE_MASK |
740 	    FATTR4_SIZE_MASK |
741 	    FATTR4_LINK_SUPPORT_MASK |
742 	    FATTR4_SYMLINK_SUPPORT_MASK |
743 	    FATTR4_NAMED_ATTR_MASK)) {
744 
745 		if (resbmap & FATTR4_SUPPORTED_ATTRS_MASK) {
746 			if (!xdr_bitmap4(xdrs, &gesp->n4g_suppattrs))
747 				return (FALSE);
748 		}
749 		if (resbmap & FATTR4_TYPE_MASK) {
750 			if (!XDR_GETINT32(xdrs, (int *)&vap->va_type))
751 				return (FALSE);
752 
753 			if (vap->va_type < NF4REG ||
754 			    vap->va_type > NF4NAMEDATTR)
755 				vap->va_type = VBAD;
756 			else
757 				vap->va_type = nf4_to_vt[vap->va_type];
758 			if (vap->va_type == VBLK)
759 				vap->va_blksize = DEV_BSIZE;
760 
761 			vap->va_mask |= AT_TYPE;
762 		}
763 		if (resbmap & FATTR4_FH_EXPIRE_TYPE_MASK) {
764 			if (!XDR_GETINT32(xdrs, (int *)&gesp->n4g_fet))
765 				return (FALSE);
766 		}
767 		if (resbmap & FATTR4_CHANGE_MASK) {
768 			if (!xdr_u_longlong_t(xdrs,
769 				(u_longlong_t *)&garp->n4g_change))
770 				return (FALSE);
771 			garp->n4g_change_valid = 1;
772 		}
773 		if (resbmap & FATTR4_SIZE_MASK) {
774 			if (!xdr_u_longlong_t(xdrs,
775 					(u_longlong_t *)&vap->va_size))
776 				return (FALSE);
777 			if (!NFS4_SIZE_OK(vap->va_size)) {
778 				garp->n4g_attrerr = EFBIG;
779 				garp->n4g_attrwhy = NFS4_GETATTR_ATSIZE_ERR;
780 			} else {
781 				vap->va_mask |= AT_SIZE;
782 			}
783 		}
784 		if (resbmap & FATTR4_LINK_SUPPORT_MASK) {
785 			if (!XDR_GETINT32(xdrs, (int *)&truefalse))
786 				return (FALSE);
787 			gesp->n4g_pc4.pc4_link_support =
788 				(truefalse ? TRUE : FALSE);
789 		}
790 		if (resbmap & FATTR4_SYMLINK_SUPPORT_MASK) {
791 			if (!XDR_GETINT32(xdrs, (int *)&truefalse))
792 				return (FALSE);
793 			gesp->n4g_pc4.pc4_symlink_support =
794 				(truefalse ? TRUE : FALSE);
795 		}
796 		if (resbmap & FATTR4_NAMED_ATTR_MASK) {
797 			if (!XDR_GETINT32(xdrs, (int *)&truefalse))
798 				return (FALSE);
799 			gesp->n4g_pc4.pc4_xattr_exists = TRUE;
800 			gesp->n4g_pc4.pc4_xattr_exists =
801 				(truefalse ? TRUE : FALSE);
802 		}
803 	}
804 	if (resbmap &
805 	    (FATTR4_FSID_MASK |
806 	    FATTR4_UNIQUE_HANDLES_MASK |
807 	    FATTR4_LEASE_TIME_MASK |
808 	    FATTR4_RDATTR_ERROR_MASK)) {
809 
810 		if (resbmap & FATTR4_FSID_MASK) {
811 		    if ((!xdr_u_longlong_t(xdrs,
812 				(u_longlong_t *)&garp->n4g_fsid.major)) ||
813 			(!xdr_u_longlong_t(xdrs,
814 				(u_longlong_t *)&garp->n4g_fsid.minor)))
815 				return (FALSE);
816 		    garp->n4g_fsid_valid = 1;
817 		}
818 		if (resbmap & FATTR4_UNIQUE_HANDLES_MASK) {
819 			if (!XDR_GETINT32(xdrs, (int *)&truefalse))
820 				return (FALSE);
821 			gesp->n4g_pc4.pc4_unique_handles =
822 				(truefalse ? TRUE : FALSE);
823 		}
824 		if (resbmap & FATTR4_LEASE_TIME_MASK) {
825 			if (!XDR_GETINT32(xdrs, (int *)&gesp->n4g_leasetime))
826 				return (FALSE);
827 		}
828 		if (resbmap & FATTR4_RDATTR_ERROR_MASK) {
829 			if (!XDR_GETINT32(xdrs,
830 					(int *)&gesp->n4g_rdattr_error))
831 				return (FALSE);
832 		}
833 	}
834 	if (resbmap &
835 	    (FATTR4_ACL_MASK |
836 	    FATTR4_ACLSUPPORT_MASK |
837 	    FATTR4_ARCHIVE_MASK |
838 	    FATTR4_CANSETTIME_MASK)) {
839 
840 		if (resbmap & FATTR4_ACL_MASK) {
841 			fattr4_acl	acl;
842 
843 			acl.fattr4_acl_val = NULL;
844 			acl.fattr4_acl_len = 0;
845 
846 			if (!xdr_fattr4_acl(xdrs, &acl))
847 				return (FALSE);
848 
849 			vsap->vsa_aclcnt = acl.fattr4_acl_len;
850 			vsap->vsa_aclentp = acl.fattr4_acl_val;
851 			vsap->vsa_mask = VSA_ACE | VSA_ACECNT;
852 
853 		}
854 		if (resbmap & FATTR4_ACLSUPPORT_MASK) {
855 			if (!XDR_GETINT32(xdrs, (int *)&gesp->n4g_aclsupport))
856 				return (FALSE);
857 		}
858 		if (resbmap & FATTR4_ARCHIVE_MASK) {
859 			ASSERT(0);
860 		}
861 		if (resbmap & FATTR4_CANSETTIME_MASK) {
862 			if (!XDR_GETINT32(xdrs, (int *)&truefalse))
863 				return (FALSE);
864 			gesp->n4g_pc4.pc4_cansettime =
865 				(truefalse ? TRUE : FALSE);
866 		}
867 	}
868 	if (resbmap &
869 	    (FATTR4_CASE_INSENSITIVE_MASK |
870 	    FATTR4_CASE_PRESERVING_MASK |
871 	    FATTR4_CHOWN_RESTRICTED_MASK |
872 	    FATTR4_FILEHANDLE_MASK |
873 	    FATTR4_FILEID_MASK |
874 	    FATTR4_FILES_AVAIL_MASK |
875 	    FATTR4_FILES_FREE_MASK |
876 	    FATTR4_FILES_TOTAL_MASK)) {
877 
878 		if (resbmap & FATTR4_CASE_INSENSITIVE_MASK) {
879 			if (!XDR_GETINT32(xdrs, (int *)&truefalse))
880 				return (FALSE);
881 			gesp->n4g_pc4.pc4_case_insensitive =
882 				(truefalse ? TRUE : FALSE);
883 		}
884 		if (resbmap & FATTR4_CASE_PRESERVING_MASK) {
885 			if (!XDR_GETINT32(xdrs, (int *)&truefalse))
886 				return (FALSE);
887 			gesp->n4g_pc4.pc4_case_preserving =
888 				(truefalse ? TRUE : FALSE);
889 		}
890 		if (resbmap & FATTR4_CHOWN_RESTRICTED_MASK) {
891 			if (!XDR_GETINT32(xdrs, (int *)&truefalse))
892 				return (FALSE);
893 			gesp->n4g_pc4.pc4_chown_restricted =
894 				(truefalse ? TRUE : FALSE);
895 		}
896 		if (resbmap & FATTR4_FILEHANDLE_MASK) {
897 			gesp->n4g_fh_u.nfs_fh4_alt.len = 0;
898 			gesp->n4g_fh_u.nfs_fh4_alt.val =
899 				gesp->n4g_fh_u.nfs_fh4_alt.data;
900 			if (!xdr_bytes(xdrs,
901 			    (char **)&gesp->n4g_fh_u.n4g_fh.nfs_fh4_val,
902 			    (uint_t *)&gesp->n4g_fh_u.n4g_fh.nfs_fh4_len,
903 			    NFS4_FHSIZE))
904 				return (FALSE);
905 		}
906 		if (resbmap & FATTR4_FILEID_MASK) {
907 			if (!xdr_u_longlong_t(xdrs,
908 					(u_longlong_t *)&vap->va_nodeid))
909 				return (FALSE);
910 			vap->va_mask |= AT_NODEID;
911 		}
912 		if (resbmap & FATTR4_FILES_AVAIL_MASK) {
913 			if (!xdr_u_longlong_t(xdrs,
914 				(u_longlong_t *)&gesp->n4g_sb.f_favail))
915 				return (FALSE);
916 		}
917 		if (resbmap & FATTR4_FILES_FREE_MASK) {
918 			if (!xdr_u_longlong_t(xdrs,
919 				(u_longlong_t *)&gesp->n4g_sb.f_ffree))
920 				return (FALSE);
921 		}
922 		if (resbmap & FATTR4_FILES_TOTAL_MASK) {
923 			if (!xdr_u_longlong_t(xdrs,
924 				(u_longlong_t *)&gesp->n4g_sb.f_files))
925 				return (FALSE);
926 		}
927 	}
928 	if (resbmap &
929 	    (FATTR4_FS_LOCATIONS_MASK |
930 	    FATTR4_HIDDEN_MASK |
931 	    FATTR4_HOMOGENEOUS_MASK)) {
932 
933 		if (resbmap & FATTR4_FS_LOCATIONS_MASK) {
934 			ASSERT(0);
935 		}
936 		if (resbmap & FATTR4_HIDDEN_MASK) {
937 			ASSERT(0);
938 		}
939 		if (resbmap & FATTR4_HOMOGENEOUS_MASK) {
940 			if (!XDR_GETINT32(xdrs, (int *)&truefalse))
941 				return (FALSE);
942 			gesp->n4g_pc4.pc4_homogeneous =
943 				(truefalse ? TRUE : FALSE);
944 		}
945 	}
946 	if (resbmap &
947 	    (FATTR4_MAXFILESIZE_MASK |
948 	    FATTR4_MAXLINK_MASK |
949 	    FATTR4_MAXNAME_MASK |
950 	    FATTR4_MAXREAD_MASK |
951 	    FATTR4_MAXWRITE_MASK)) {
952 
953 		if (resbmap & FATTR4_MAXFILESIZE_MASK) {
954 			if (!xdr_u_longlong_t(xdrs,
955 				(u_longlong_t *)&gesp->n4g_maxfilesize))
956 				return (FALSE);
957 		}
958 		if (resbmap & FATTR4_MAXLINK_MASK) {
959 			if (!XDR_GETINT32(xdrs,
960 					(int *)&gesp->n4g_pc4.pc4_link_max))
961 				return (FALSE);
962 		}
963 		if (resbmap & FATTR4_MAXNAME_MASK) {
964 			if (!XDR_GETINT32(xdrs,
965 					(int *)&gesp->n4g_pc4.pc4_name_max))
966 				return (FALSE);
967 			gesp->n4g_sb.f_namemax = gesp->n4g_pc4.pc4_name_max;
968 		}
969 		if (resbmap & FATTR4_MAXREAD_MASK) {
970 			if (!xdr_u_longlong_t(xdrs,
971 				(u_longlong_t *)&gesp->n4g_maxread))
972 				return (FALSE);
973 		}
974 		if (resbmap & FATTR4_MAXWRITE_MASK) {
975 			if (!xdr_u_longlong_t(xdrs,
976 				(u_longlong_t *)&gesp->n4g_maxwrite))
977 				return (FALSE);
978 		}
979 	}
980 	if (resbmap &
981 	    (FATTR4_MIMETYPE_MASK |
982 	    FATTR4_MODE_MASK |
983 	    FATTR4_NO_TRUNC_MASK |
984 	    FATTR4_NUMLINKS_MASK)) {
985 
986 		if (resbmap & FATTR4_MIMETYPE_MASK) {
987 			ASSERT(0);
988 		}
989 		if (resbmap & FATTR4_MODE_MASK) {
990 			if (!XDR_GETINT32(xdrs, (int *)&vap->va_mode))
991 				return (FALSE);
992 			vap->va_mask |= AT_MODE;
993 		}
994 		if (resbmap & FATTR4_NO_TRUNC_MASK) {
995 			if (!XDR_GETINT32(xdrs, (int *)&truefalse))
996 				return (FALSE);
997 			gesp->n4g_pc4.pc4_no_trunc =
998 				(truefalse ? TRUE : FALSE);
999 		}
1000 		if (resbmap & FATTR4_NUMLINKS_MASK) {
1001 			if (!XDR_GETINT32(xdrs, (int *)&vap->va_nlink))
1002 				return (FALSE);
1003 			vap->va_mask |= AT_NLINK;
1004 		}
1005 	}
1006 	if (resbmap &
1007 	    (FATTR4_OWNER_MASK |
1008 	    FATTR4_OWNER_GROUP_MASK |
1009 	    FATTR4_QUOTA_AVAIL_HARD_MASK |
1010 	    FATTR4_QUOTA_AVAIL_SOFT_MASK)) {
1011 
1012 		if (resbmap & FATTR4_OWNER_MASK) {
1013 			uint_t *owner_length, ol;
1014 			char *owner_val = NULL;
1015 			char *owner_alloc = NULL;
1016 			utf8string ov;
1017 			int error;
1018 
1019 			/* get the OWNER_LENGTH */
1020 			if (!xdr_u_int(xdrs, &ol))
1021 				return (FALSE);
1022 
1023 			/* Manage the owner length location */
1024 			if (pug && ol <= MAX_OG_NAME) {
1025 				owner_length = &pug->u_curr.utf8string_len;
1026 				*owner_length = ol;
1027 			} else {
1028 				owner_length = &ol;
1029 			}
1030 
1031 			/* find memory to store the decode */
1032 			if (*owner_length > MAX_OG_NAME || pug == NULL)
1033 				owner_val = owner_alloc =
1034 					kmem_alloc(*owner_length, KM_SLEEP);
1035 			else
1036 				owner_val = pug->u_curr.utf8string_val;
1037 
1038 			/* get the OWNER string */
1039 			if (!xdr_opaque(xdrs, owner_val, *owner_length)) {
1040 				if (owner_alloc)
1041 					kmem_free(owner_alloc, *owner_length);
1042 				return (FALSE);
1043 			}
1044 
1045 			/* Optimize for matching if called for */
1046 			if (pug &&
1047 			    *owner_length == pug->u_last.utf8string_len &&
1048 			    bcmp(owner_val, pug->u_last.utf8string_val,
1049 					*owner_length) == 0) {
1050 				vap->va_uid = pug->uid;
1051 				vap->va_mask |= AT_UID;
1052 			} else {
1053 				uid_t uid;
1054 
1055 				ov.utf8string_len = *owner_length;
1056 				ov.utf8string_val = owner_val;
1057 				error = nfs_idmap_str_uid(&ov, &uid, FALSE);
1058 				/*
1059 				 * String was mapped, but to nobody because
1060 				 * we are nfsmapid, indicate it should not
1061 				 * be cached.
1062 				 */
1063 				if (error == ENOTSUP) {
1064 					error = 0;
1065 					garp->n4g_attrwhy =
1066 						NFS4_GETATTR_NOCACHE_OK;
1067 				}
1068 
1069 				if (error) {
1070 					garp->n4g_attrerr = error;
1071 					garp->n4g_attrwhy =
1072 						NFS4_GETATTR_ATUID_ERR;
1073 				} else {
1074 					vap->va_uid = uid;
1075 					vap->va_mask |= AT_UID;
1076 					if (pug && ol <= MAX_OG_NAME) {
1077 						pug->uid = uid;
1078 						U_SWAP_CURR_LAST(pug);
1079 					}
1080 				}
1081 				if (owner_alloc)
1082 					kmem_free(owner_alloc, *owner_length);
1083 			}
1084 		}
1085 		if (resbmap & FATTR4_OWNER_GROUP_MASK) {
1086 			uint_t *group_length, gl;
1087 			char *group_val = NULL;
1088 			char *group_alloc = NULL;
1089 			utf8string gv;
1090 			int error;
1091 
1092 			/* get the OWNER_GROUP_LENGTH */
1093 			if (!xdr_u_int(xdrs, &gl))
1094 				return (FALSE);
1095 
1096 			/* Manage the group length location */
1097 			if (pug && gl <= MAX_OG_NAME) {
1098 				group_length = &pug->g_curr.utf8string_len;
1099 				*group_length = gl;
1100 			} else {
1101 				group_length = &gl;
1102 			}
1103 
1104 			/* find memory to store the decode */
1105 			if (*group_length > MAX_OG_NAME || pug == NULL)
1106 				group_val = group_alloc =
1107 					kmem_alloc(*group_length, KM_SLEEP);
1108 			else
1109 				group_val = pug->g_curr.utf8string_val;
1110 
1111 			/* get the OWNER_GROUP string */
1112 			if (!xdr_opaque(xdrs, group_val, *group_length)) {
1113 				if (group_alloc)
1114 					kmem_free(group_alloc, *group_length);
1115 				return (FALSE);
1116 			}
1117 
1118 			/* Optimize for matching if called for */
1119 			if (pug &&
1120 			    *group_length == pug->g_last.utf8string_len &&
1121 			    bcmp(group_val, pug->g_last.utf8string_val,
1122 					*group_length) == 0) {
1123 				vap->va_gid = pug->gid;
1124 				vap->va_mask |= AT_GID;
1125 			} else {
1126 				uid_t gid;
1127 
1128 				gv.utf8string_len = *group_length;
1129 				gv.utf8string_val = group_val;
1130 				error = nfs_idmap_str_gid(&gv, &gid, FALSE);
1131 				/*
1132 				 * String was mapped, but to nobody because
1133 				 * we are nfsmapid, indicate it should not
1134 				 * be cached.
1135 				 */
1136 				if (error == ENOTSUP) {
1137 					error = 0;
1138 					garp->n4g_attrwhy =
1139 						NFS4_GETATTR_NOCACHE_OK;
1140 				}
1141 
1142 				if (error) {
1143 					garp->n4g_attrerr = error;
1144 					garp->n4g_attrwhy =
1145 						NFS4_GETATTR_ATGID_ERR;
1146 				} else {
1147 					vap->va_gid = gid;
1148 					vap->va_mask |= AT_GID;
1149 					if (pug && gl <= MAX_OG_NAME) {
1150 						pug->gid = gid;
1151 						G_SWAP_CURR_LAST(pug);
1152 					}
1153 				}
1154 				if (group_alloc) {
1155 					kmem_free(group_alloc, *group_length);
1156 				}
1157 			}
1158 		}
1159 		if (resbmap & FATTR4_QUOTA_AVAIL_HARD_MASK) {
1160 			ASSERT(0);
1161 		}
1162 		if (resbmap & FATTR4_QUOTA_AVAIL_SOFT_MASK) {
1163 			ASSERT(0);
1164 		}
1165 	}
1166 	if (resbmap &
1167 	    (FATTR4_QUOTA_USED_MASK |
1168 	    FATTR4_SPACE_AVAIL_MASK |
1169 	    FATTR4_SPACE_FREE_MASK |
1170 	    FATTR4_SPACE_TOTAL_MASK |
1171 	    FATTR4_SPACE_USED_MASK |
1172 	    FATTR4_SYSTEM_MASK)) {
1173 
1174 		if (resbmap & FATTR4_QUOTA_USED_MASK) {
1175 			ASSERT(0);
1176 		}
1177 		if (resbmap & FATTR4_RAWDEV_MASK) {
1178 			fattr4_rawdev rawdev;
1179 			if (!xdr_fattr4_rawdev(xdrs, &rawdev))
1180 				return (FALSE);
1181 
1182 			if (vap->va_type == VCHR || vap->va_type == VBLK) {
1183 				vap->va_rdev = makedevice(rawdev.specdata1,
1184 							rawdev.specdata2);
1185 			} else {
1186 				vap->va_rdev = 0;
1187 			}
1188 			vap->va_mask |= AT_RDEV;
1189 		}
1190 		if (resbmap & FATTR4_SPACE_AVAIL_MASK) {
1191 			if (!xdr_u_longlong_t(xdrs,
1192 				(u_longlong_t *)&gesp->n4g_sb.f_bavail))
1193 				return (FALSE);
1194 			gesp->n4g_sb.f_bavail /= DEV_BSIZE;
1195 		}
1196 		if (resbmap & FATTR4_SPACE_FREE_MASK) {
1197 			if (!xdr_u_longlong_t(xdrs,
1198 				(u_longlong_t *)&gesp->n4g_sb.f_bfree))
1199 				return (FALSE);
1200 			gesp->n4g_sb.f_bfree /= DEV_BSIZE;
1201 		}
1202 		if (resbmap & FATTR4_SPACE_TOTAL_MASK) {
1203 			if (!xdr_u_longlong_t(xdrs,
1204 				(u_longlong_t *)&gesp->n4g_sb.f_blocks))
1205 				return (FALSE);
1206 			gesp->n4g_sb.f_blocks /= DEV_BSIZE;
1207 		}
1208 		if (resbmap & FATTR4_SPACE_USED_MASK) {
1209 			uint64_t space_used;
1210 			if (!xdr_u_longlong_t(xdrs,
1211 						(u_longlong_t *)&space_used))
1212 				return (FALSE);
1213 
1214 			/* Compute space depending on device type */
1215 			ASSERT((vap->va_mask & AT_TYPE));
1216 			if (vap->va_type == VREG || vap->va_type == VDIR ||
1217 			    vap->va_type == VLNK) {
1218 				vap->va_nblocks = (u_longlong_t)
1219 					((space_used + (offset4)DEV_BSIZE -
1220 					(offset4)1) / (offset4)DEV_BSIZE);
1221 			} else {
1222 				vap->va_nblocks = 0;
1223 			}
1224 			vap->va_mask |= AT_NBLOCKS;
1225 		}
1226 		if (resbmap & FATTR4_SYSTEM_MASK) {
1227 			ASSERT(0);
1228 		}
1229 	}
1230 	if (resbmap &
1231 	    (FATTR4_TIME_ACCESS_MASK |
1232 	    FATTR4_TIME_ACCESS_SET_MASK |
1233 	    FATTR4_TIME_BACKUP_MASK |
1234 	    FATTR4_TIME_CREATE_MASK |
1235 	    FATTR4_TIME_DELTA_MASK |
1236 	    FATTR4_TIME_METADATA_MASK |
1237 	    FATTR4_TIME_MODIFY_MASK |
1238 	    FATTR4_TIME_MODIFY_SET_MASK |
1239 	    FATTR4_MOUNTED_ON_FILEID_MASK)) {
1240 
1241 		if (resbmap & FATTR4_TIME_ACCESS_MASK) {
1242 			nfstime4 atime;
1243 			int error;
1244 
1245 			if (!xdr_longlong_t(xdrs,
1246 					    (longlong_t *)&atime.seconds))
1247 				return (FALSE);
1248 			if (!XDR_GETINT32(xdrs, (int *)&atime.nseconds))
1249 				return (FALSE);
1250 			error = nfs4_time_ntov(&atime, &vap->va_atime);
1251 			if (error) {
1252 				garp->n4g_attrerr = error;
1253 				garp->n4g_attrwhy = NFS4_GETATTR_ATATIME_ERR;
1254 			}
1255 			vap->va_mask |= AT_ATIME;
1256 		}
1257 		if (resbmap & FATTR4_TIME_ACCESS_SET_MASK) {
1258 			ASSERT(0);
1259 		}
1260 		if (resbmap & FATTR4_TIME_BACKUP_MASK) {
1261 			ASSERT(0);
1262 		}
1263 		if (resbmap & FATTR4_TIME_CREATE_MASK) {
1264 			ASSERT(0);
1265 		}
1266 		if (resbmap & FATTR4_TIME_DELTA_MASK) {
1267 			if ((!xdr_u_longlong_t(xdrs,
1268 			    (u_longlong_t *)&gesp->n4g_delta.seconds)) ||
1269 			    (!xdr_u_int(xdrs, &gesp->n4g_delta.nseconds)))
1270 				return (FALSE);
1271 		}
1272 		if (resbmap & FATTR4_TIME_METADATA_MASK) {
1273 			nfstime4 mdt;
1274 			int error;
1275 
1276 			if (!xdr_longlong_t(xdrs, (longlong_t *)&mdt.seconds))
1277 				return (FALSE);
1278 			if (!XDR_GETINT32(xdrs, (int32_t *)&mdt.nseconds))
1279 				return (FALSE);
1280 			error = nfs4_time_ntov(&mdt, &vap->va_ctime);
1281 			if (error) {
1282 				garp->n4g_attrerr = error;
1283 				garp->n4g_attrwhy = NFS4_GETATTR_ATCTIME_ERR;
1284 			}
1285 			vap->va_mask |= AT_CTIME;
1286 		}
1287 		if (resbmap & FATTR4_TIME_MODIFY_MASK) {
1288 			nfstime4 mtime;
1289 			int error;
1290 
1291 			if (!xdr_longlong_t(xdrs,
1292 					    (longlong_t *)&mtime.seconds))
1293 				return (FALSE);
1294 			if (!XDR_GETINT32(xdrs, (int32_t *)&mtime.nseconds))
1295 				return (FALSE);
1296 			error = nfs4_time_ntov(&mtime, &vap->va_mtime);
1297 			if (error) {
1298 				garp->n4g_attrerr = error;
1299 				garp->n4g_attrwhy = NFS4_GETATTR_ATMTIME_ERR;
1300 			}
1301 			vap->va_mask |= AT_MTIME;
1302 		}
1303 		if (resbmap & FATTR4_TIME_MODIFY_SET_MASK) {
1304 			ASSERT(0);
1305 		}
1306 		if (resbmap & FATTR4_MOUNTED_ON_FILEID_MASK) {
1307 			if (!xdr_u_longlong_t(xdrs,
1308 					(u_longlong_t *)&garp->n4g_mon_fid))
1309 				return (FALSE);
1310 			garp->n4g_mon_fid_valid = 1;
1311 		}
1312 	}
1313 
1314 	if (resbmap & ~(NFS4_VATTR_MASK | FATTR4_ACL_MASK)) {
1315 		/* copy only if not provided */
1316 		if (garp->n4g_ext_res == NULL) {
1317 			garp->n4g_ext_res = kmem_alloc(sizeof (ges), KM_SLEEP);
1318 			bcopy(&ges, garp->n4g_ext_res, sizeof (ges));
1319 		}
1320 	}
1321 
1322 	return (TRUE);
1323 }
1324 
1325 /*
1326  * Inlined version of get_bitmap4 processing
1327  */
1328 bitmap4
1329 xdr_get_bitmap4_inline(uint32_t **iptr)
1330 {
1331 	uint32_t resbmaplen;
1332 	bitmap4 bm;
1333 	uint32_t *ptr = *iptr;
1334 
1335 	/* bitmap LENGTH */
1336 	resbmaplen = IXDR_GET_U_INT32(ptr);
1337 
1338 	/* Inline the bitmap and attrlen for common case of two word map */
1339 	if (resbmaplen == 2) {
1340 		IXDR_GET_HYPER(ptr, bm);
1341 		*iptr = ptr;
1342 		return (bm);
1343 	}
1344 
1345 #if defined(_LITTLE_ENDIAN)
1346 	bm = IXDR_GET_U_INT32(ptr);
1347 	if (--resbmaplen == 0) {
1348 		*iptr = ptr;
1349 		return (bm);
1350 	}
1351 	*((uint32_t *)&bm) |= IXDR_GET_U_INT32(ptr);
1352 	if (--resbmaplen == 0) {
1353 		*iptr = ptr;
1354 		return (bm);
1355 	}
1356 	ptr += resbmaplen;
1357 	*iptr = ptr;
1358 	return (bm);
1359 #elif defined(_BIG_ENDIAN)
1360 	*((uint32_t *)&bm) = IXDR_GET_U_INT32(ptr);
1361 	if (--resbmaplen == 0) {
1362 		*iptr = ptr;
1363 		return (bm);
1364 	}
1365 	bm |= IXDR_GET_U_INT32(ptr);
1366 	if (--resbmaplen == 0) {
1367 		*iptr = ptr;
1368 		return (bm);
1369 	}
1370 	ptr += resbmaplen;
1371 	*iptr = ptr;
1372 	return (bm);
1373 #else
1374 	ASSERT(0);
1375 	ptr += resbmaplen;
1376 	*iptr = ptr;
1377 	return (0);
1378 #endif
1379 }
1380 
1381 static bool_t
1382 xdr_ga_fattr_res_inline(uint32_t *ptr, struct nfs4_ga_res *garp,
1383 			bitmap4 resbmap, bitmap4 argbmap, struct mntinfo4 *mi,
1384 			ug_cache_t *pug)
1385 {
1386 	int truefalse;
1387 	struct nfs4_ga_ext_res ges, *gesp;
1388 	vattr_t *vap = &garp->n4g_va;
1389 
1390 	if (garp->n4g_ext_res)
1391 		gesp = garp->n4g_ext_res;
1392 	else
1393 		gesp = &ges;
1394 
1395 	vap->va_mask = 0;
1396 
1397 	/* Check to see if the vattr should be pre-filled */
1398 	if (argbmap & NFS4_VATTR_MASK)
1399 		xdr_ga_prefill_vattr(garp, mi);
1400 
1401 	if (argbmap & NFS4_STATFS_ATTR_MASK)
1402 		xdr_ga_prefill_statvfs(gesp, mi);
1403 
1404 	if (resbmap &
1405 	    (FATTR4_SUPPORTED_ATTRS_MASK |
1406 	    FATTR4_TYPE_MASK |
1407 	    FATTR4_FH_EXPIRE_TYPE_MASK |
1408 	    FATTR4_CHANGE_MASK |
1409 	    FATTR4_SIZE_MASK |
1410 	    FATTR4_LINK_SUPPORT_MASK |
1411 	    FATTR4_SYMLINK_SUPPORT_MASK |
1412 	    FATTR4_NAMED_ATTR_MASK)) {
1413 
1414 		if (resbmap & FATTR4_SUPPORTED_ATTRS_MASK) {
1415 			gesp->n4g_suppattrs = xdr_get_bitmap4_inline(&ptr);
1416 		}
1417 		if (resbmap & FATTR4_TYPE_MASK) {
1418 			vap->va_type = IXDR_GET_U_INT32(ptr);
1419 
1420 			if (vap->va_type < NF4REG ||
1421 			    vap->va_type > NF4NAMEDATTR)
1422 				vap->va_type = VBAD;
1423 			else
1424 				vap->va_type = nf4_to_vt[vap->va_type];
1425 			if (vap->va_type == VBLK)
1426 				vap->va_blksize = DEV_BSIZE;
1427 
1428 			vap->va_mask |= AT_TYPE;
1429 		}
1430 		if (resbmap & FATTR4_FH_EXPIRE_TYPE_MASK) {
1431 			gesp->n4g_fet = IXDR_GET_U_INT32(ptr);
1432 		}
1433 		if (resbmap & FATTR4_CHANGE_MASK) {
1434 			IXDR_GET_U_HYPER(ptr, garp->n4g_change);
1435 			garp->n4g_change_valid = 1;
1436 		}
1437 		if (resbmap & FATTR4_SIZE_MASK) {
1438 			IXDR_GET_U_HYPER(ptr, vap->va_size);
1439 
1440 			if (!NFS4_SIZE_OK(vap->va_size)) {
1441 				garp->n4g_attrerr = EFBIG;
1442 				garp->n4g_attrwhy = NFS4_GETATTR_ATSIZE_ERR;
1443 			} else {
1444 				vap->va_mask |= AT_SIZE;
1445 			}
1446 		}
1447 		if (resbmap & FATTR4_LINK_SUPPORT_MASK) {
1448 			truefalse = IXDR_GET_U_INT32(ptr);
1449 			gesp->n4g_pc4.pc4_link_support =
1450 				(truefalse ? TRUE : FALSE);
1451 		}
1452 		if (resbmap & FATTR4_SYMLINK_SUPPORT_MASK) {
1453 			truefalse = IXDR_GET_U_INT32(ptr);
1454 			gesp->n4g_pc4.pc4_symlink_support =
1455 				(truefalse ? TRUE : FALSE);
1456 		}
1457 		if (resbmap & FATTR4_NAMED_ATTR_MASK) {
1458 			truefalse = IXDR_GET_U_INT32(ptr);
1459 			gesp->n4g_pc4.pc4_xattr_exists = TRUE;
1460 			gesp->n4g_pc4.pc4_xattr_exists =
1461 				(truefalse ? TRUE : FALSE);
1462 		}
1463 	}
1464 	if (resbmap &
1465 	    (FATTR4_FSID_MASK |
1466 	    FATTR4_UNIQUE_HANDLES_MASK |
1467 	    FATTR4_LEASE_TIME_MASK |
1468 	    FATTR4_RDATTR_ERROR_MASK)) {
1469 
1470 		if (resbmap & FATTR4_FSID_MASK) {
1471 			IXDR_GET_U_HYPER(ptr, garp->n4g_fsid.major);
1472 			IXDR_GET_U_HYPER(ptr, garp->n4g_fsid.minor);
1473 			garp->n4g_fsid_valid = 1;
1474 		}
1475 		if (resbmap & FATTR4_UNIQUE_HANDLES_MASK) {
1476 			truefalse = IXDR_GET_U_INT32(ptr);
1477 			gesp->n4g_pc4.pc4_unique_handles =
1478 				(truefalse ? TRUE : FALSE);
1479 		}
1480 		if (resbmap & FATTR4_LEASE_TIME_MASK) {
1481 			gesp->n4g_leasetime = IXDR_GET_U_INT32(ptr);
1482 		}
1483 		if (resbmap & FATTR4_RDATTR_ERROR_MASK) {
1484 			gesp->n4g_rdattr_error = IXDR_GET_U_INT32(ptr);
1485 		}
1486 	}
1487 	if (resbmap &
1488 	    (FATTR4_ACL_MASK |
1489 	    FATTR4_ACLSUPPORT_MASK |
1490 	    FATTR4_ARCHIVE_MASK |
1491 	    FATTR4_CANSETTIME_MASK)) {
1492 
1493 		if (resbmap & FATTR4_ACL_MASK) {
1494 			ASSERT(0);
1495 		}
1496 		if (resbmap & FATTR4_ACLSUPPORT_MASK) {
1497 			gesp->n4g_aclsupport = IXDR_GET_U_INT32(ptr);
1498 		}
1499 		if (resbmap & FATTR4_ARCHIVE_MASK) {
1500 			ASSERT(0);
1501 		}
1502 		if (resbmap & FATTR4_CANSETTIME_MASK) {
1503 			truefalse = IXDR_GET_U_INT32(ptr);
1504 			gesp->n4g_pc4.pc4_cansettime =
1505 				(truefalse ? TRUE : FALSE);
1506 		}
1507 	}
1508 	if (resbmap &
1509 	    (FATTR4_CASE_INSENSITIVE_MASK |
1510 	    FATTR4_CASE_PRESERVING_MASK |
1511 	    FATTR4_CHOWN_RESTRICTED_MASK |
1512 	    FATTR4_FILEHANDLE_MASK |
1513 	    FATTR4_FILEID_MASK |
1514 	    FATTR4_FILES_AVAIL_MASK |
1515 	    FATTR4_FILES_FREE_MASK |
1516 	    FATTR4_FILES_TOTAL_MASK)) {
1517 
1518 		if (resbmap & FATTR4_CASE_INSENSITIVE_MASK) {
1519 			truefalse = IXDR_GET_U_INT32(ptr);
1520 			gesp->n4g_pc4.pc4_case_insensitive =
1521 				(truefalse ? TRUE : FALSE);
1522 		}
1523 		if (resbmap & FATTR4_CASE_PRESERVING_MASK) {
1524 			truefalse = IXDR_GET_U_INT32(ptr);
1525 			gesp->n4g_pc4.pc4_case_preserving =
1526 				(truefalse ? TRUE : FALSE);
1527 		}
1528 		if (resbmap & FATTR4_CHOWN_RESTRICTED_MASK) {
1529 			truefalse = IXDR_GET_U_INT32(ptr);
1530 			gesp->n4g_pc4.pc4_chown_restricted =
1531 				(truefalse ? TRUE : FALSE);
1532 		}
1533 		if (resbmap & FATTR4_FILEHANDLE_MASK) {
1534 			int len = IXDR_GET_U_INT32(ptr);
1535 
1536 			gesp->n4g_fh_u.nfs_fh4_alt.len = 0;
1537 			gesp->n4g_fh_u.nfs_fh4_alt.val =
1538 				gesp->n4g_fh_u.nfs_fh4_alt.data;
1539 			gesp->n4g_fh_u.n4g_fh.nfs_fh4_len = len;
1540 
1541 			bcopy(ptr, gesp->n4g_fh_u.n4g_fh.nfs_fh4_val, len);
1542 
1543 			ptr += RNDUP(len) / BYTES_PER_XDR_UNIT;
1544 		}
1545 		if (resbmap & FATTR4_FILEID_MASK) {
1546 			IXDR_GET_U_HYPER(ptr, vap->va_nodeid);
1547 			vap->va_mask |= AT_NODEID;
1548 		}
1549 		if (resbmap & FATTR4_FILES_AVAIL_MASK) {
1550 			IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_favail);
1551 		}
1552 		if (resbmap & FATTR4_FILES_FREE_MASK) {
1553 			IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_ffree);
1554 		}
1555 		if (resbmap & FATTR4_FILES_TOTAL_MASK) {
1556 			IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_files);
1557 		}
1558 	}
1559 	if (resbmap &
1560 	    (FATTR4_FS_LOCATIONS_MASK |
1561 	    FATTR4_HIDDEN_MASK |
1562 	    FATTR4_HOMOGENEOUS_MASK)) {
1563 
1564 		if (resbmap & FATTR4_FS_LOCATIONS_MASK) {
1565 			ASSERT(0);
1566 		}
1567 		if (resbmap & FATTR4_HIDDEN_MASK) {
1568 			ASSERT(0);
1569 		}
1570 		if (resbmap & FATTR4_HOMOGENEOUS_MASK) {
1571 			truefalse = IXDR_GET_U_INT32(ptr);
1572 			gesp->n4g_pc4.pc4_homogeneous =
1573 				(truefalse ? TRUE : FALSE);
1574 		}
1575 	}
1576 	if (resbmap &
1577 	    (FATTR4_MAXFILESIZE_MASK |
1578 	    FATTR4_MAXLINK_MASK |
1579 	    FATTR4_MAXNAME_MASK |
1580 	    FATTR4_MAXREAD_MASK |
1581 	    FATTR4_MAXWRITE_MASK)) {
1582 
1583 		if (resbmap & FATTR4_MAXFILESIZE_MASK) {
1584 			IXDR_GET_U_HYPER(ptr, gesp->n4g_maxfilesize);
1585 		}
1586 		if (resbmap & FATTR4_MAXLINK_MASK) {
1587 			gesp->n4g_pc4.pc4_link_max = IXDR_GET_U_INT32(ptr);
1588 		}
1589 		if (resbmap & FATTR4_MAXNAME_MASK) {
1590 			gesp->n4g_pc4.pc4_name_max = IXDR_GET_U_INT32(ptr);
1591 			gesp->n4g_sb.f_namemax = gesp->n4g_pc4.pc4_name_max;
1592 		}
1593 		if (resbmap & FATTR4_MAXREAD_MASK) {
1594 			IXDR_GET_U_HYPER(ptr, gesp->n4g_maxread);
1595 		}
1596 		if (resbmap & FATTR4_MAXWRITE_MASK) {
1597 			IXDR_GET_U_HYPER(ptr, gesp->n4g_maxwrite);
1598 		}
1599 	}
1600 	if (resbmap &
1601 	    (FATTR4_MIMETYPE_MASK |
1602 	    FATTR4_MODE_MASK |
1603 	    FATTR4_NO_TRUNC_MASK |
1604 	    FATTR4_NUMLINKS_MASK)) {
1605 
1606 		if (resbmap & FATTR4_MIMETYPE_MASK) {
1607 			ASSERT(0);
1608 		}
1609 		if (resbmap & FATTR4_MODE_MASK) {
1610 			vap->va_mode = IXDR_GET_U_INT32(ptr);
1611 			vap->va_mask |= AT_MODE;
1612 		}
1613 		if (resbmap & FATTR4_NO_TRUNC_MASK) {
1614 			truefalse = IXDR_GET_U_INT32(ptr);
1615 			gesp->n4g_pc4.pc4_no_trunc =
1616 				(truefalse ? TRUE : FALSE);
1617 		}
1618 		if (resbmap & FATTR4_NUMLINKS_MASK) {
1619 			vap->va_nlink = IXDR_GET_U_INT32(ptr);
1620 			vap->va_mask |= AT_NLINK;
1621 		}
1622 	}
1623 	if (resbmap &
1624 	    (FATTR4_OWNER_MASK |
1625 	    FATTR4_OWNER_GROUP_MASK |
1626 	    FATTR4_QUOTA_AVAIL_HARD_MASK |
1627 	    FATTR4_QUOTA_AVAIL_SOFT_MASK)) {
1628 
1629 		if (resbmap & FATTR4_OWNER_MASK) {
1630 			uint_t *owner_length, ol;
1631 			char *owner_val = NULL;
1632 			utf8string ov;
1633 			int error;
1634 
1635 			/* get the OWNER_LENGTH */
1636 			ol = IXDR_GET_U_INT32(ptr);
1637 
1638 			/* Manage the owner length location */
1639 			if (pug && ol <= MAX_OG_NAME) {
1640 				owner_length = &pug->u_curr.utf8string_len;
1641 				*owner_length = ol;
1642 			} else {
1643 				owner_length = &ol;
1644 			}
1645 
1646 			/* find memory to store the decode */
1647 			if (*owner_length > MAX_OG_NAME || pug == NULL)
1648 				owner_val = (char *)ptr;
1649 			else
1650 				owner_val = (char *)ptr;
1651 
1652 			/* Optimize for matching if called for */
1653 			if (pug &&
1654 			    *owner_length == pug->u_last.utf8string_len &&
1655 			    bcmp(owner_val, pug->u_last.utf8string_val,
1656 					*owner_length) == 0) {
1657 				vap->va_uid = pug->uid;
1658 				vap->va_mask |= AT_UID;
1659 			} else {
1660 				uid_t uid;
1661 
1662 				ov.utf8string_len = *owner_length;
1663 				ov.utf8string_val = owner_val;
1664 				error = nfs_idmap_str_uid(&ov, &uid, FALSE);
1665 				/*
1666 				 * String was mapped, but to nobody because
1667 				 * we are nfsmapid, indicate it should not
1668 				 * be cached.
1669 				 */
1670 				if (error == ENOTSUP) {
1671 					error = 0;
1672 					garp->n4g_attrwhy =
1673 						NFS4_GETATTR_NOCACHE_OK;
1674 				}
1675 
1676 				if (error) {
1677 					garp->n4g_attrerr = error;
1678 					garp->n4g_attrwhy =
1679 						NFS4_GETATTR_ATUID_ERR;
1680 				} else {
1681 					vap->va_uid = uid;
1682 					vap->va_mask |= AT_UID;
1683 					/* save the results for next time */
1684 					if (pug && ol <= MAX_OG_NAME) {
1685 						pug->uid = uid;
1686 						pug->u_curr.utf8string_len =
1687 							ov.utf8string_len;
1688 						bcopy(owner_val,
1689 						pug->u_curr.utf8string_val, ol);
1690 						U_SWAP_CURR_LAST(pug);
1691 					}
1692 				}
1693 			}
1694 			ptr += RNDUP(ol) / BYTES_PER_XDR_UNIT;
1695 		}
1696 		if (resbmap & FATTR4_OWNER_GROUP_MASK) {
1697 			uint_t *group_length, gl;
1698 			char *group_val = NULL;
1699 			utf8string gv;
1700 			int error;
1701 
1702 			/* get the OWNER_GROUP_LENGTH */
1703 			gl = IXDR_GET_U_INT32(ptr);
1704 
1705 			/* Manage the group length location */
1706 			if (pug && gl <= MAX_OG_NAME) {
1707 				group_length = &pug->g_curr.utf8string_len;
1708 				*group_length = gl;
1709 			} else {
1710 				group_length = &gl;
1711 			}
1712 
1713 			/* find memory to store the decode */
1714 			if (*group_length > MAX_OG_NAME || pug == NULL)
1715 				group_val = (char *)ptr;
1716 			else
1717 				group_val = (char *)ptr;
1718 
1719 			/* Optimize for matching if called for */
1720 			if (pug &&
1721 			    *group_length == pug->g_last.utf8string_len &&
1722 			    bcmp(group_val, pug->g_last.utf8string_val,
1723 					*group_length) == 0) {
1724 				vap->va_gid = pug->gid;
1725 				vap->va_mask |= AT_GID;
1726 			} else {
1727 				uid_t gid;
1728 
1729 				gv.utf8string_len = *group_length;
1730 				gv.utf8string_val = group_val;
1731 				error = nfs_idmap_str_gid(&gv, &gid, FALSE);
1732 				/*
1733 				 * String was mapped, but to nobody because
1734 				 * we are nfsmapid, indicate it should not
1735 				 * be cached.
1736 				 */
1737 				if (error == ENOTSUP) {
1738 					error = 0;
1739 					garp->n4g_attrwhy =
1740 						NFS4_GETATTR_NOCACHE_OK;
1741 				}
1742 
1743 				if (error) {
1744 					garp->n4g_attrerr = error;
1745 					garp->n4g_attrwhy =
1746 						NFS4_GETATTR_ATGID_ERR;
1747 				} else {
1748 					vap->va_gid = gid;
1749 					vap->va_mask |= AT_GID;
1750 					if (pug && gl <= MAX_OG_NAME) {
1751 						pug->gid = gid;
1752 						pug->g_curr.utf8string_len =
1753 							gv.utf8string_len;
1754 						bcopy(group_val,
1755 						    pug->g_curr.utf8string_val,
1756 						    gl);
1757 						G_SWAP_CURR_LAST(pug);
1758 					}
1759 				}
1760 			}
1761 			ptr += RNDUP(gl) / BYTES_PER_XDR_UNIT;
1762 		}
1763 		if (resbmap & FATTR4_QUOTA_AVAIL_HARD_MASK) {
1764 			ASSERT(0);
1765 		}
1766 		if (resbmap & FATTR4_QUOTA_AVAIL_SOFT_MASK) {
1767 			ASSERT(0);
1768 		}
1769 	}
1770 	if (resbmap &
1771 	    (FATTR4_QUOTA_USED_MASK |
1772 	    FATTR4_SPACE_AVAIL_MASK |
1773 	    FATTR4_SPACE_FREE_MASK |
1774 	    FATTR4_SPACE_TOTAL_MASK |
1775 	    FATTR4_SPACE_USED_MASK |
1776 	    FATTR4_SYSTEM_MASK)) {
1777 
1778 		if (resbmap & FATTR4_QUOTA_USED_MASK) {
1779 			ASSERT(0);
1780 		}
1781 		if (resbmap & FATTR4_RAWDEV_MASK) {
1782 			fattr4_rawdev rawdev;
1783 
1784 			rawdev.specdata1 = IXDR_GET_U_INT32(ptr);
1785 			rawdev.specdata2 = IXDR_GET_U_INT32(ptr);
1786 
1787 			if (vap->va_type == VCHR || vap->va_type == VBLK) {
1788 				vap->va_rdev = makedevice(rawdev.specdata1,
1789 							rawdev.specdata2);
1790 			} else {
1791 				vap->va_rdev = 0;
1792 			}
1793 			vap->va_mask |= AT_RDEV;
1794 		}
1795 		if (resbmap & FATTR4_SPACE_AVAIL_MASK) {
1796 			IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_bavail);
1797 			gesp->n4g_sb.f_bavail /= DEV_BSIZE;
1798 		}
1799 		if (resbmap & FATTR4_SPACE_FREE_MASK) {
1800 			IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_bfree);
1801 			gesp->n4g_sb.f_bfree /= DEV_BSIZE;
1802 		}
1803 		if (resbmap & FATTR4_SPACE_TOTAL_MASK) {
1804 			IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_blocks);
1805 			gesp->n4g_sb.f_blocks /= DEV_BSIZE;
1806 		}
1807 		if (resbmap & FATTR4_SPACE_USED_MASK) {
1808 			uint64_t space_used;
1809 			IXDR_GET_U_HYPER(ptr, space_used);
1810 
1811 			/* Compute space depending on device type */
1812 			ASSERT((vap->va_mask & AT_TYPE));
1813 			if (vap->va_type == VREG || vap->va_type == VDIR ||
1814 			    vap->va_type == VLNK) {
1815 				vap->va_nblocks = (u_longlong_t)
1816 					((space_used + (offset4)DEV_BSIZE -
1817 					(offset4)1) / (offset4)DEV_BSIZE);
1818 			} else {
1819 				vap->va_nblocks = 0;
1820 			}
1821 			vap->va_mask |= AT_NBLOCKS;
1822 		}
1823 		if (resbmap & FATTR4_SYSTEM_MASK) {
1824 			ASSERT(0);
1825 		}
1826 	}
1827 	if (resbmap &
1828 	    (FATTR4_TIME_ACCESS_MASK |
1829 	    FATTR4_TIME_ACCESS_SET_MASK |
1830 	    FATTR4_TIME_BACKUP_MASK |
1831 	    FATTR4_TIME_CREATE_MASK |
1832 	    FATTR4_TIME_DELTA_MASK |
1833 	    FATTR4_TIME_METADATA_MASK |
1834 	    FATTR4_TIME_MODIFY_MASK |
1835 	    FATTR4_TIME_MODIFY_SET_MASK |
1836 	    FATTR4_MOUNTED_ON_FILEID_MASK)) {
1837 
1838 		if (resbmap & FATTR4_TIME_ACCESS_MASK) {
1839 			nfstime4 atime;
1840 			int error;
1841 
1842 			IXDR_GET_U_HYPER(ptr, atime.seconds);
1843 			atime.nseconds = IXDR_GET_U_INT32(ptr);
1844 
1845 			error = nfs4_time_ntov(&atime, &vap->va_atime);
1846 			if (error) {
1847 				garp->n4g_attrerr = error;
1848 				garp->n4g_attrwhy = NFS4_GETATTR_ATATIME_ERR;
1849 			}
1850 			vap->va_mask |= AT_ATIME;
1851 		}
1852 		if (resbmap & FATTR4_TIME_ACCESS_SET_MASK) {
1853 			ASSERT(0);
1854 		}
1855 		if (resbmap & FATTR4_TIME_BACKUP_MASK) {
1856 			ASSERT(0);
1857 		}
1858 		if (resbmap & FATTR4_TIME_CREATE_MASK) {
1859 			ASSERT(0);
1860 		}
1861 		if (resbmap & FATTR4_TIME_DELTA_MASK) {
1862 			IXDR_GET_U_HYPER(ptr, gesp->n4g_delta.seconds);
1863 			gesp->n4g_delta.nseconds = IXDR_GET_U_INT32(ptr);
1864 		}
1865 		if (resbmap & FATTR4_TIME_METADATA_MASK) {
1866 			nfstime4 mdt;
1867 			int error;
1868 
1869 			IXDR_GET_U_HYPER(ptr, mdt.seconds);
1870 			mdt.nseconds = IXDR_GET_U_INT32(ptr);
1871 
1872 			error = nfs4_time_ntov(&mdt, &vap->va_ctime);
1873 			if (error) {
1874 				garp->n4g_attrerr = error;
1875 				garp->n4g_attrwhy = NFS4_GETATTR_ATCTIME_ERR;
1876 			}
1877 			vap->va_mask |= AT_CTIME;
1878 		}
1879 		if (resbmap & FATTR4_TIME_MODIFY_MASK) {
1880 			nfstime4 mtime;
1881 			int error;
1882 
1883 			IXDR_GET_U_HYPER(ptr, mtime.seconds);
1884 			mtime.nseconds = IXDR_GET_U_INT32(ptr);
1885 
1886 			error = nfs4_time_ntov(&mtime, &vap->va_mtime);
1887 			if (error) {
1888 				garp->n4g_attrerr = error;
1889 				garp->n4g_attrwhy = NFS4_GETATTR_ATMTIME_ERR;
1890 			}
1891 			vap->va_mask |= AT_MTIME;
1892 		}
1893 		if (resbmap & FATTR4_TIME_MODIFY_SET_MASK) {
1894 			ASSERT(0);
1895 		}
1896 		if (resbmap & FATTR4_MOUNTED_ON_FILEID_MASK) {
1897 			IXDR_GET_U_HYPER(ptr, garp->n4g_mon_fid);
1898 			garp->n4g_mon_fid_valid = 1;
1899 		}
1900 	}
1901 
1902 	/*
1903 	 * FATTR4_ACL_MASK is not yet supported by this function, but
1904 	 * we check against it anyway, in case it ever is.
1905 	 */
1906 	if (resbmap & ~(NFS4_VATTR_MASK | FATTR4_ACL_MASK)) {
1907 		/* copy only if not provided */
1908 		if (garp->n4g_ext_res == NULL) {
1909 			garp->n4g_ext_res = kmem_alloc(sizeof (ges), KM_SLEEP);
1910 			bcopy(&ges, garp->n4g_ext_res, sizeof (ges));
1911 		}
1912 	}
1913 
1914 	return (TRUE);
1915 }
1916 
1917 
1918 /*
1919  * "." and ".." buffers for filling in on read and readdir
1920  * calls. Intialize the first time and fill in on every
1921  * call to to readdir.
1922  */
1923 char	*nfs4_dot_entries;
1924 char	*nfs4_dot_dot_entry;
1925 
1926 /*
1927  * Create the "." or ".." and pad the buffer once so they are
1928  * copied out as required into the user supplied buffer everytime.
1929  * DIRENT64_RECLEN(sizeof (".") - 1) = DIRENT64_RECLEN(1)
1930  * DIRENT64_RECLEN(sizeof ("..") - 1) = DIRENT64_RECLEN(2)
1931  */
1932 void
1933 nfs4_init_dot_entries()
1934 {
1935 	struct dirent64 *odp;
1936 
1937 	/*
1938 	 * zalloc it so it zeros the buffer out. Need
1939 	 * to just do it once.
1940 	 */
1941 	nfs4_dot_entries = kmem_zalloc(DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2),
1942 	    KM_SLEEP);
1943 
1944 	odp = (struct dirent64 *)nfs4_dot_entries;
1945 	odp->d_off = 1; /* magic cookie for "." entry */
1946 	odp->d_reclen = DIRENT64_RECLEN(1);
1947 	odp->d_name[0] = '.';
1948 	odp->d_name[1] = '\0';
1949 
1950 	nfs4_dot_dot_entry = nfs4_dot_entries + DIRENT64_RECLEN(1);
1951 	odp = (struct dirent64 *)nfs4_dot_dot_entry;
1952 
1953 	odp->d_off = 2;
1954 	odp->d_reclen = DIRENT64_RECLEN(2);
1955 	odp->d_name[0] = '.';
1956 	odp->d_name[1] = '.';
1957 	odp->d_name[2] = '\0';
1958 }
1959 
1960 void
1961 nfs4_destroy_dot_entries()
1962 {
1963 	if (nfs4_dot_entries)
1964 		kmem_free(nfs4_dot_entries, DIRENT64_RECLEN(1) +
1965 		    DIRENT64_RECLEN(2));
1966 
1967 	nfs4_dot_entries = nfs4_dot_dot_entry = NULL;
1968 }
1969 
1970 bool_t
1971 xdr_READDIR4res_clnt(XDR *xdrs, READDIR4res_clnt *objp, READDIR4args *aobjp)
1972 {
1973 	bool_t more_data;
1974 	rddir4_cache *rdc = aobjp->rdc;
1975 	dirent64_t *dp = NULL;
1976 	int entry_length = 0;
1977 	int space_left = 0;
1978 	bitmap4 resbmap;
1979 	uint32_t attrlen;
1980 	nfs4_ga_res_t gar;
1981 	struct nfs4_ga_ext_res ges;
1982 	uint64_t last_cookie = 0;
1983 	int skip_to_end;
1984 	ug_cache_t *pug = NULL;
1985 
1986 	ASSERT(xdrs->x_op == XDR_DECODE);
1987 	ASSERT(rdc->entries == NULL);
1988 	ASSERT(aobjp->dircount > 0);
1989 
1990 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
1991 		return (FALSE);
1992 	if (objp->status != NFS4_OK)
1993 		return (TRUE);
1994 
1995 	gar.n4g_va.va_mask = 0;
1996 	gar.n4g_change_valid = 0;
1997 	gar.n4g_mon_fid_valid = 0;
1998 	gar.n4g_fsid_valid = 0;
1999 	gar.n4g_vsa.vsa_mask = 0;
2000 	gar.n4g_attrwhy = NFS4_GETATTR_OP_OK;
2001 	ges.n4g_pc4.pc4_cache_valid = 0;
2002 	ges.n4g_pc4.pc4_xattr_valid = 0;
2003 	gar.n4g_ext_res = &ges;
2004 
2005 	/* READDIR4res_clnt_free needs to kmem_free this buffer */
2006 	rdc->entries = kmem_alloc(aobjp->dircount, KM_SLEEP);
2007 
2008 	dp = (dirent64_t *)rdc->entries;
2009 	rdc->entlen = rdc->buflen = space_left = aobjp->dircount;
2010 
2011 	/* Fill in dot and dot-dot if needed */
2012 	if (rdc->nfs4_cookie == (nfs_cookie4) 0 ||
2013 		    rdc->nfs4_cookie == (nfs_cookie4) 1) {
2014 
2015 		if (rdc->nfs4_cookie == (nfs_cookie4)0) {
2016 			bcopy(nfs4_dot_entries, rdc->entries,
2017 				    DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2));
2018 			objp->dotp = dp;
2019 			dp = (struct dirent64 *)(((char *)dp) +
2020 							DIRENT64_RECLEN(1));
2021 			objp->dotdotp = dp;
2022 			dp = (struct dirent64 *)(((char *)dp) +
2023 							DIRENT64_RECLEN(2));
2024 			space_left -= DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2);
2025 
2026 		} else	{	/* for ".." entry */
2027 			bcopy(nfs4_dot_dot_entry, rdc->entries,
2028 						DIRENT64_RECLEN(2));
2029 			objp->dotp = NULL;
2030 			objp->dotdotp = dp;
2031 			dp = (struct dirent64 *)(((char *)dp) +
2032 							DIRENT64_RECLEN(2));
2033 			space_left -= DIRENT64_RECLEN(2);
2034 		}
2035 		/* Magic NFSv4 number for entry after start */
2036 		last_cookie = 2;
2037 	}
2038 
2039 	/* Get the cookie VERIFIER */
2040 	if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cookieverf))
2041 		goto noentries;
2042 
2043 	/* Get the do-we-have-a-next-entry BOOL */
2044 	if (!xdr_bool(xdrs, &more_data))
2045 		goto noentries;
2046 
2047 	if (aobjp->attr_request & (FATTR4_OWNER_MASK | FATTR4_OWNER_GROUP_MASK))
2048 		pug = alloc_ugcache();
2049 
2050 	skip_to_end = 0;
2051 	while (more_data) {
2052 		uint_t namelen;
2053 		uint64_t cookie;
2054 
2055 		/* Get the COOKIE */
2056 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&cookie))
2057 			goto noentries;
2058 
2059 		/* Get the LENGTH of the entry name */
2060 		if (!xdr_u_int(xdrs, &namelen))
2061 			goto noentries;
2062 
2063 		if (!skip_to_end) {
2064 			/*
2065 			 * With the length of the directory entry name
2066 			 * in hand, figure out if there is room left
2067 			 * to encode it for the requestor.  If not,
2068 			 * that is okay, but the rest of the readdir
2069 			 * operation result must be decoded in the
2070 			 * case there are following operations
2071 			 * in the compound request.  Therefore, mark
2072 			 * the rest of the response as "skip" and
2073 			 * decode or skip the remaining data
2074 			 */
2075 			entry_length = DIRENT64_RECLEN(namelen);
2076 			if (space_left < entry_length)
2077 				skip_to_end = 1;
2078 		}
2079 
2080 		/* Get the NAME of the entry */
2081 		if (!skip_to_end) {
2082 			if (!xdr_opaque(xdrs, dp->d_name, namelen))
2083 				goto noentries;
2084 			bzero(&dp->d_name[namelen],
2085 				DIRENT64_NAMELEN(entry_length) - namelen);
2086 			dp->d_off = last_cookie = cookie;
2087 			dp->d_reclen = entry_length;
2088 		} else {
2089 			if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &namelen))
2090 				goto noentries;
2091 		}
2092 
2093 		/* Get the attribute BITMAP */
2094 		if (!xdr_bitmap4(xdrs, &resbmap))
2095 			goto noentries;
2096 		/* Get the LENGTH of the attributes */
2097 		if (!xdr_u_int(xdrs, (uint_t *)&attrlen))
2098 			goto noentries;
2099 
2100 		/* Get the ATTRIBUTES */
2101 		if (!skip_to_end) {
2102 			uint32_t *ptr;
2103 
2104 			if (!(resbmap & FATTR4_ACL_MASK) &&
2105 			    (ptr = (uint32_t *)XDR_INLINE(xdrs, attrlen))
2106 			    != NULL) {
2107 				if (!xdr_ga_fattr_res_inline(ptr, &gar, resbmap,
2108 							aobjp->attr_request,
2109 							aobjp->mi, pug))
2110 					goto noentries;
2111 			} else {
2112 				if (!xdr_ga_fattr_res(xdrs, &gar, resbmap,
2113 							aobjp->attr_request,
2114 							aobjp->mi, pug))
2115 					goto noentries;
2116 			}
2117 
2118 			/* Fill in the d_ino per the server's fid values */
2119 			/*
2120 			 * Important to note that the mounted on fileid
2121 			 * is returned in d_ino if supported.  This is
2122 			 * expected, readdir returns the mounted on fileid
2123 			 * while stat() returns the fileid of the object
2124 			 * on "top" of the mount.
2125 			 */
2126 			if (gar.n4g_mon_fid_valid)
2127 				dp->d_ino = gar.n4g_mon_fid;
2128 			else if (gar.n4g_va.va_mask & AT_NODEID)
2129 				dp->d_ino = gar.n4g_va.va_nodeid;
2130 			else
2131 				dp->d_ino = 0;
2132 
2133 			/* See about creating an rnode for this entry */
2134 			if ((resbmap &
2135 			    (NFS4_VATTR_MASK | FATTR4_FILEHANDLE_MASK)) ==
2136 			    (NFS4_VATTR_MASK | FATTR4_FILEHANDLE_MASK)) {
2137 				nfs4_sharedfh_t *sfhp;
2138 				vnode_t *vp;
2139 
2140 				sfhp = sfh4_put(&ges.n4g_fh_u.n4g_fh,
2141 							aobjp->mi, NULL);
2142 				vp = makenfs4node(sfhp, &gar,
2143 					aobjp->dvp->v_vfsp,
2144 					aobjp->t,
2145 					aobjp->cr,
2146 					aobjp->dvp,
2147 					fn_get(VTOSV(aobjp->dvp)->sv_name,
2148 						dp->d_name));
2149 				sfh4_rele(&sfhp);
2150 				dnlc_update(aobjp->dvp, dp->d_name, vp);
2151 				VN_RELE(vp);
2152 			}
2153 
2154 			dp = (struct dirent64 *)(((caddr_t)dp) + dp->d_reclen);
2155 
2156 			space_left -= entry_length;
2157 
2158 		} else {
2159 			if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &attrlen))
2160 				goto noentries;
2161 		}
2162 
2163 		/* Get the do-we-have-a-next-entry BOOL */
2164 		if (!xdr_bool(xdrs, &more_data))
2165 			goto noentries;
2166 	}
2167 
2168 	if (pug) {
2169 		kmem_free(pug, sizeof (ug_cache_t));
2170 		pug = NULL;
2171 	}
2172 
2173 	/*
2174 	 * Finish up the rddir cache
2175 	 * If no entries were returned, free up buffer &
2176 	 * set ncookie to the starting cookie for this
2177 	 * readdir request so that the direof caching
2178 	 * will work properly.
2179 	 */
2180 	ASSERT(rdc->entries);
2181 	if (last_cookie == 0) {
2182 		kmem_free(rdc->entries, rdc->entlen);
2183 		rdc->entries = NULL;
2184 		last_cookie = rdc->nfs4_cookie;
2185 	}
2186 
2187 	rdc->actlen = rdc->entlen - space_left;
2188 	rdc->nfs4_ncookie = last_cookie;
2189 
2190 	/* Get the EOF marker */
2191 	if (!xdr_bool(xdrs, &objp->eof))
2192 		goto noentries;
2193 
2194 	/*
2195 	 * If the server returns eof and there were no
2196 	 * skipped entries, set eof
2197 	 */
2198 	rdc->eof = (objp->eof && !skip_to_end) ? TRUE : FALSE;
2199 
2200 	/*
2201 	 * If we encoded entries we are done
2202 	 */
2203 	if (rdc->entries) {
2204 		rdc->error = 0;
2205 		return (TRUE);
2206 	}
2207 
2208 	/*
2209 	 * If there were no entries and we skipped because
2210 	 * there was not enough space, return EINVAL
2211 	 */
2212 	if (skip_to_end) {
2213 		rdc->error = EINVAL;
2214 		return (TRUE);
2215 	}
2216 
2217 	/*
2218 	 * No entries, nothing skipped, and EOF, return OK.
2219 	 */
2220 	if (objp->eof == TRUE) {
2221 		rdc->error = 0;
2222 		return (TRUE);
2223 	}
2224 
2225 	/*
2226 	 * No entries, nothing skipped, and not EOF
2227 	 * probably a bad cookie, return ENOENT.
2228 	 */
2229 	rdc->error = ENOENT;
2230 	return (TRUE);
2231 
2232 noentries:
2233 	if (rdc->entries) {
2234 		kmem_free(rdc->entries, rdc->entlen);
2235 		rdc->entries = NULL;
2236 	}
2237 	if (pug)
2238 		kmem_free(pug, sizeof (ug_cache_t));
2239 	rdc->error = EIO;
2240 	return (FALSE);
2241 }
2242 
2243 /*
2244  * xdr_ga_res
2245  *
2246  * Returns: FALSE on raw data processing errors, TRUE otherwise.
2247  *
2248  * This function pre-processes the OP_GETATTR response, and then
2249  * calls common routines to process the GETATTR fattr4 results into
2250  * vnode attributes and other components that the client is interested
2251  * in. If an error other than an RPC error is encountered, the details
2252  * of the error are filled into objp, although the result of the
2253  * processing is set to TRUE.
2254  */
2255 static bool_t
2256 xdr_ga_res(XDR *xdrs, GETATTR4res *objp, GETATTR4args *aobjp)
2257 {
2258 	uint32_t *ptr;
2259 	bitmap4 resbmap;
2260 	uint32_t attrlen;
2261 
2262 	ASSERT(xdrs->x_op == XDR_DECODE);
2263 
2264 	/* Initialize objp attribute error values */
2265 	objp->ga_res.n4g_attrerr =
2266 		objp->ga_res.n4g_attrwhy = NFS4_GETATTR_OP_OK;
2267 
2268 	if (!xdr_bitmap4(xdrs, &resbmap))
2269 		return (FALSE);
2270 
2271 	/* save the response bitmap for the caller */
2272 	objp->ga_res.n4g_resbmap = resbmap;
2273 
2274 	/* attrlen */
2275 	if (!XDR_GETINT32(xdrs, (int32_t *)&attrlen))
2276 		return (FALSE);
2277 
2278 	/*
2279 	 * Handle case where request and response bitmaps don't match.
2280 	 */
2281 	if (aobjp->attr_request && aobjp->attr_request != resbmap) {
2282 		bitmap4 deltabmap;
2283 
2284 		/*
2285 		 * Return error for case where server sent extra attributes
2286 		 * because the "unknown" attributes may be anywhere in the
2287 		 * xdr stream and can't be properly processed.
2288 		 */
2289 		deltabmap = ((aobjp->attr_request ^ resbmap) & resbmap);
2290 		if (deltabmap) {
2291 			objp->ga_res.n4g_attrerr = EINVAL;
2292 			objp->ga_res.n4g_attrwhy = NFS4_GETATTR_BITMAP_ERR;
2293 			return (TRUE);
2294 		}
2295 
2296 		/*
2297 		 * Return error for case where there is a mandatory
2298 		 * attribute missing in the server response. Note that
2299 		 * missing recommended attributes are evaluated in the
2300 		 * specific routines that decode the server response.
2301 		 */
2302 		deltabmap = ((aobjp->attr_request ^ resbmap)
2303 				& aobjp->attr_request);
2304 		if ((deltabmap & FATTR4_MANDATTR_MASK)) {
2305 			objp->ga_res.n4g_attrerr = EINVAL;
2306 			objp->ga_res.n4g_attrwhy = NFS4_GETATTR_MANDATTR_ERR;
2307 			return (TRUE);
2308 		}
2309 	}
2310 
2311 	/* Check to see if the attrs can be inlined and go for it if so */
2312 	if (!(resbmap & FATTR4_ACL_MASK) &&
2313 	    (ptr = (uint32_t *)XDR_INLINE(xdrs, attrlen)) != NULL)
2314 		return (xdr_ga_fattr_res_inline(ptr, &objp->ga_res,
2315 					resbmap, aobjp->attr_request,
2316 					aobjp->mi, NULL));
2317 	else
2318 		return (xdr_ga_fattr_res(xdrs, &objp->ga_res,
2319 					resbmap, aobjp->attr_request,
2320 					aobjp->mi, NULL));
2321 }
2322 
2323 #if defined(DEBUG) && !defined(lint)
2324 /*
2325  * We assume that an enum is a 32-bit value, check it once
2326  */
2327 static enum szchk { SZVAL } szchkvar;
2328 #endif
2329 
2330 bool_t
2331 xdr_settime4(XDR *xdrs, settime4 *objp)
2332 {
2333 #if defined(DEBUG) && !defined(lint)
2334 	ASSERT(sizeof (szchkvar) == sizeof (int32_t));
2335 #endif
2336 	if (xdrs->x_op == XDR_FREE)
2337 		return (TRUE);
2338 
2339 	if (!xdr_int(xdrs, (int *)&objp->set_it))
2340 		return (FALSE);
2341 	if (objp->set_it != SET_TO_CLIENT_TIME4)
2342 		return (TRUE);
2343 	/* xdr_nfstime4 */
2344 	if (!xdr_longlong_t(xdrs, (longlong_t *)&objp->time.seconds))
2345 		return (FALSE);
2346 	return (xdr_u_int(xdrs, &objp->time.nseconds));
2347 }
2348 
2349 static bool_t
2350 xdr_fattr4(XDR *xdrs, fattr4 *objp)
2351 {
2352 	if (xdrs->x_op != XDR_FREE) {
2353 		if (!xdr_bitmap4(xdrs, &objp->attrmask))
2354 			return (FALSE);
2355 		return (xdr_bytes(xdrs, (char **)&objp->attrlist4,
2356 			(uint_t *)&objp->attrlist4_len, NFS4_FATTR4_LIMIT));
2357 	}
2358 
2359 	/*
2360 	 * Optimized free case
2361 	 */
2362 	if (objp->attrlist4 != NULL)
2363 		kmem_free(objp->attrlist4, objp->attrlist4_len);
2364 	return (TRUE);
2365 }
2366 
2367 static bool_t
2368 xdr_ACCESS4res(XDR *xdrs, ACCESS4res *objp)
2369 {
2370 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
2371 		return (FALSE);
2372 	if (objp->status != NFS4_OK)
2373 		return (TRUE);
2374 	if (!xdr_u_int(xdrs, &objp->supported))
2375 		return (FALSE);
2376 	return (xdr_u_int(xdrs, &objp->access));
2377 }
2378 
2379 static bool_t
2380 xdr_CLOSE4args(XDR *xdrs, CLOSE4args *objp)
2381 {
2382 	if (!xdr_u_int(xdrs, &objp->seqid))
2383 		return (FALSE);
2384 	if (!xdr_u_int(xdrs, &objp->open_stateid.seqid))
2385 		return (FALSE);
2386 	return (xdr_opaque(xdrs, objp->open_stateid.other, 12));
2387 }
2388 
2389 static bool_t
2390 xdr_CLOSE4res(XDR *xdrs, CLOSE4res *objp)
2391 {
2392 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
2393 		return (FALSE);
2394 	if (objp->status != NFS4_OK)
2395 		return (TRUE);
2396 	if (!xdr_u_int(xdrs, &objp->open_stateid.seqid))
2397 		return (FALSE);
2398 	return (xdr_opaque(xdrs, objp->open_stateid.other, 12));
2399 }
2400 
2401 static bool_t
2402 xdr_CREATE4args(XDR *xdrs, CREATE4args *objp)
2403 {
2404 	if (xdrs->x_op != XDR_FREE) {
2405 		if (!xdr_int(xdrs, (int32_t *)&objp->type))
2406 			return (FALSE);
2407 		switch (objp->type) {
2408 		case NF4LNK:
2409 			if (!xdr_bytes(xdrs,
2410 			    (char **)&objp->ftype4_u.linkdata.utf8string_val,
2411 			    (uint_t *)&objp->ftype4_u.linkdata.utf8string_len,
2412 			    NFS4_MAX_UTF8STRING))
2413 				return (FALSE);
2414 			break;
2415 		case NF4BLK:
2416 		case NF4CHR:
2417 			if (!xdr_u_int(xdrs, &objp->ftype4_u.devdata.specdata1))
2418 				return (FALSE);
2419 			if (!xdr_u_int(xdrs, &objp->ftype4_u.devdata.specdata2))
2420 				return (FALSE);
2421 			break;
2422 		case NF4SOCK:
2423 		case NF4FIFO:
2424 		case NF4DIR:
2425 		default:
2426 			break;	/* server should return NFS4ERR_BADTYPE */
2427 		}
2428 		if (!xdr_bytes(xdrs, (char **)&objp->objname.utf8string_val,
2429 				(uint_t *)&objp->objname.utf8string_len,
2430 				NFS4_MAX_UTF8STRING))
2431 			return (FALSE);
2432 		return (xdr_fattr4(xdrs, &objp->createattrs));
2433 	}
2434 
2435 	/*
2436 	 * Optimized free case
2437 	 */
2438 	if (objp->type == NF4LNK) {
2439 		if (objp->ftype4_u.linkdata.utf8string_val != NULL)
2440 			kmem_free(objp->ftype4_u.linkdata.utf8string_val,
2441 				objp->ftype4_u.linkdata.utf8string_len);
2442 	}
2443 	if (objp->objname.utf8string_val != NULL)
2444 		kmem_free(objp->objname.utf8string_val,
2445 			objp->objname.utf8string_len);
2446 	return (xdr_fattr4(xdrs, &objp->createattrs));
2447 }
2448 
2449 static bool_t
2450 xdr_CREATE4cargs(XDR *xdrs, CREATE4cargs *objp)
2451 {
2452 	int len;
2453 
2454 	ASSERT(xdrs->x_op == XDR_ENCODE);
2455 
2456 	if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->type))
2457 		return (FALSE);
2458 	switch (objp->type) {
2459 	case NF4LNK:
2460 		len = strlen(objp->ftype4_u.clinkdata);
2461 		if (len > NFS4_MAX_UTF8STRING)
2462 			return (FALSE);
2463 		if (!XDR_PUTINT32(xdrs, &len))
2464 			return (FALSE);
2465 		if (!xdr_opaque(xdrs, objp->ftype4_u.clinkdata, len))
2466 			return (FALSE);
2467 		break;
2468 	case NF4BLK:
2469 	case NF4CHR:
2470 		if (!XDR_PUTINT32(xdrs,
2471 				(int32_t *)&objp->ftype4_u.devdata.specdata1))
2472 			return (FALSE);
2473 		if (!XDR_PUTINT32(xdrs,
2474 				(int32_t *)&objp->ftype4_u.devdata.specdata2))
2475 			return (FALSE);
2476 		break;
2477 	case NF4SOCK:
2478 	case NF4FIFO:
2479 	case NF4DIR:
2480 	default:
2481 		break;	/* server should return NFS4ERR_BADTYPE */
2482 	}
2483 
2484 	len = strlen(objp->cname);
2485 	if (len > NFS4_MAX_UTF8STRING)
2486 		return (FALSE);
2487 	if (!XDR_PUTINT32(xdrs, &len))
2488 		return (FALSE);
2489 	if (!xdr_opaque(xdrs, objp->cname, len))
2490 		return (FALSE);
2491 
2492 	return (xdr_fattr4(xdrs, &objp->createattrs));
2493 }
2494 
2495 static bool_t
2496 xdr_CREATE4res(XDR *xdrs, CREATE4res *objp)
2497 {
2498 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
2499 		return (FALSE);
2500 	if (objp->status != NFS4_OK)
2501 		return (TRUE);
2502 	if (!xdr_bool(xdrs, &objp->cinfo.atomic))
2503 		return (FALSE);
2504 	if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.before))
2505 		return (FALSE);
2506 	if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.after))
2507 		return (FALSE);
2508 	return (xdr_bitmap4(xdrs, &objp->attrset));
2509 }
2510 
2511 static bool_t
2512 xdr_LINK4res(XDR *xdrs, LINK4res *objp)
2513 {
2514 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
2515 		return (FALSE);
2516 	if (objp->status != NFS4_OK)
2517 		return (TRUE);
2518 	if (!xdr_bool(xdrs, &objp->cinfo.atomic))
2519 		return (FALSE);
2520 	if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.before))
2521 		return (FALSE);
2522 	return (xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.after));
2523 }
2524 
2525 static bool_t
2526 xdr_LOCK4args(XDR *xdrs, LOCK4args *objp)
2527 {
2528 	if (xdrs->x_op != XDR_FREE) {
2529 		if (!xdr_int(xdrs, (int *)&objp->locktype))
2530 			return (FALSE);
2531 		if (!xdr_bool(xdrs, &objp->reclaim))
2532 			return (FALSE);
2533 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset))
2534 			return (FALSE);
2535 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->length))
2536 			return (FALSE);
2537 		if (!xdr_bool(xdrs, &objp->locker.new_lock_owner))
2538 			return (FALSE);
2539 		if (objp->locker.new_lock_owner == TRUE) {
2540 			if (!xdr_u_int(xdrs, &objp->locker.locker4_u.open_owner.
2541 							open_seqid))
2542 				return (FALSE);
2543 			if (!xdr_u_int(xdrs, &objp->locker.locker4_u.open_owner.
2544 							open_stateid.seqid))
2545 				return (FALSE);
2546 			if (!xdr_opaque(xdrs, objp->locker.locker4_u.open_owner.
2547 							open_stateid.other,
2548 				    12))
2549 				return (FALSE);
2550 			if (!xdr_u_int(xdrs, &objp->locker.locker4_u.open_owner.
2551 							lock_seqid))
2552 				return (FALSE);
2553 			if (!xdr_u_longlong_t(xdrs,
2554 				    (u_longlong_t *)&objp->locker.locker4_u.
2555 					open_owner.lock_owner.clientid))
2556 				return (FALSE);
2557 			return (xdr_bytes(xdrs,
2558 				(char **)&objp->locker.locker4_u.open_owner.
2559 				    lock_owner.owner_val,
2560 				(uint_t *)&objp->locker.locker4_u.open_owner.
2561 				    lock_owner.owner_len,
2562 				NFS4_OPAQUE_LIMIT));
2563 		}
2564 
2565 		if (objp->locker.new_lock_owner != FALSE)
2566 			return (FALSE);
2567 
2568 		if (!xdr_u_int(xdrs, &objp->locker.locker4_u.lock_owner.
2569 							lock_stateid.seqid))
2570 			return (FALSE);
2571 		if (!xdr_opaque(xdrs, objp->locker.locker4_u.lock_owner.
2572 							lock_stateid.other,
2573 			    12))
2574 			return (FALSE);
2575 		return (xdr_u_int(xdrs, &objp->locker.locker4_u.lock_owner.
2576 							lock_seqid));
2577 	}
2578 
2579 	/*
2580 	 * Optimized free case
2581 	 */
2582 	if (objp->locker.new_lock_owner == TRUE) {
2583 		if (objp->locker.locker4_u.open_owner.lock_owner.owner_val !=
2584 								NULL) {
2585 			kmem_free(objp->locker.locker4_u.open_owner.lock_owner.
2586 							owner_val,
2587 				objp->locker.locker4_u.open_owner.lock_owner.
2588 							owner_len);
2589 		}
2590 	}
2591 
2592 	return (TRUE);
2593 }
2594 
2595 static bool_t
2596 xdr_LOCK4res(XDR *xdrs, LOCK4res *objp)
2597 {
2598 	if (xdrs->x_op != XDR_FREE) {
2599 		if (!xdr_int(xdrs, (int32_t *)&objp->status))
2600 			return (FALSE);
2601 		if (objp->status == NFS4_OK) {
2602 			if (!xdr_u_int(xdrs,
2603 					&objp->LOCK4res_u.lock_stateid.seqid))
2604 				return (FALSE);
2605 			return (xdr_opaque(xdrs,
2606 				objp->LOCK4res_u.lock_stateid.other, 12));
2607 		}
2608 		if (objp->status != NFS4ERR_DENIED)
2609 			return (TRUE);
2610 
2611 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->LOCK4res_u.
2612 				denied.offset))
2613 			return (FALSE);
2614 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->LOCK4res_u.
2615 				denied.length))
2616 			return (FALSE);
2617 		if (!xdr_int(xdrs, (int *)&objp->LOCK4res_u.denied.locktype))
2618 			return (FALSE);
2619 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->LOCK4res_u.
2620 				denied.owner.clientid))
2621 			return (FALSE);
2622 		return (xdr_bytes(xdrs,
2623 			    (char **)&objp->LOCK4res_u.denied.owner.owner_val,
2624 			    (uint_t *)&objp->LOCK4res_u.denied.owner.owner_len,
2625 			    NFS4_OPAQUE_LIMIT));
2626 	}
2627 
2628 	/*
2629 	 * Optimized free case
2630 	 */
2631 	if (objp->status == NFS4_OK || objp->status != NFS4ERR_DENIED)
2632 		return (TRUE);
2633 
2634 	if (objp->LOCK4res_u.denied.owner.owner_val != NULL)
2635 		kmem_free(objp->LOCK4res_u.denied.owner.owner_val,
2636 			objp->LOCK4res_u.denied.owner.owner_len);
2637 	return (TRUE);
2638 }
2639 
2640 static bool_t
2641 xdr_LOCKT4args(XDR *xdrs, LOCKT4args *objp)
2642 {
2643 	if (xdrs->x_op != XDR_FREE) {
2644 		if (!xdr_int(xdrs, (int *)&objp->locktype))
2645 			return (FALSE);
2646 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset))
2647 			return (FALSE);
2648 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->length))
2649 			return (FALSE);
2650 		if (!xdr_u_longlong_t(xdrs,
2651 					(u_longlong_t *)&objp->owner.clientid))
2652 			return (FALSE);
2653 		return (xdr_bytes(xdrs, (char **)&objp->owner.owner_val,
2654 			(uint_t *)&objp->owner.owner_len,
2655 			NFS4_OPAQUE_LIMIT));
2656 	}
2657 
2658 	/*
2659 	 * Optimized free case
2660 	 */
2661 	if (objp->owner.owner_val != NULL)
2662 		kmem_free(objp->owner.owner_val, objp->owner.owner_len);
2663 	return (TRUE);
2664 }
2665 
2666 static bool_t
2667 xdr_LOCKT4res(XDR *xdrs, LOCKT4res *objp)
2668 {
2669 	if (xdrs->x_op != XDR_FREE) {
2670 		if (!xdr_int(xdrs, (int32_t *)&objp->status))
2671 			return (FALSE);
2672 		if (objp->status == NFS4_OK)
2673 			return (TRUE);
2674 		if (objp->status != NFS4ERR_DENIED)
2675 			return (TRUE);
2676 		/* xdr_LOCK4denied */
2677 		if (!xdr_u_longlong_t(xdrs,
2678 					(u_longlong_t *)&objp->denied.offset))
2679 			return (FALSE);
2680 		if (!xdr_u_longlong_t(xdrs,
2681 					(u_longlong_t *)&objp->denied.length))
2682 			return (FALSE);
2683 		if (!xdr_int(xdrs, (int *)&objp->denied.locktype))
2684 			return (FALSE);
2685 		if (!xdr_u_longlong_t(xdrs,
2686 				(u_longlong_t *)&objp->denied.owner.clientid))
2687 			return (FALSE);
2688 		return (xdr_bytes(xdrs,
2689 		    (char **)&objp->denied.owner.owner_val,
2690 		    (uint_t *)&objp->denied.owner.owner_len,
2691 		    NFS4_OPAQUE_LIMIT));
2692 	}
2693 
2694 	/*
2695 	 * Optimized free case
2696 	 */
2697 	if (objp->status == NFS4_OK || objp->status != NFS4ERR_DENIED)
2698 		return (TRUE);
2699 	if (objp->denied.owner.owner_val != NULL)
2700 		kmem_free(objp->denied.owner.owner_val,
2701 				objp->denied.owner.owner_len);
2702 	return (TRUE);
2703 }
2704 
2705 static bool_t
2706 xdr_LOCKU4args(XDR *xdrs, LOCKU4args *objp)
2707 {
2708 	if (!xdr_int(xdrs, (int *)&objp->locktype))
2709 		return (FALSE);
2710 	if (!xdr_u_int(xdrs, &objp->seqid))
2711 		return (FALSE);
2712 	if (!xdr_u_int(xdrs, &objp->lock_stateid.seqid))
2713 		return (FALSE);
2714 	if (!xdr_opaque(xdrs, objp->lock_stateid.other, 12))
2715 		return (FALSE);
2716 	if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset))
2717 		return (FALSE);
2718 	return (xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->length));
2719 }
2720 
2721 static bool_t
2722 xdr_OPEN4args(XDR *xdrs, OPEN4args *objp)
2723 {
2724 	if (xdrs->x_op != XDR_FREE) {
2725 		if (!xdr_u_int(xdrs, &objp->seqid))
2726 			return (FALSE);
2727 		if (!xdr_u_int(xdrs, &objp->share_access))
2728 			return (FALSE);
2729 		if (!xdr_u_int(xdrs, &objp->share_deny))
2730 			return (FALSE);
2731 
2732 		/* xdr_open_owner4 */
2733 		if (!xdr_u_longlong_t(xdrs,
2734 					(u_longlong_t *)&objp->owner.clientid))
2735 			return (FALSE);
2736 		if (!xdr_bytes(xdrs, (char **)&objp->owner.owner_val,
2737 				(uint_t *)&objp->owner.owner_len,
2738 				NFS4_OPAQUE_LIMIT))
2739 			return (FALSE);
2740 
2741 		/* xdr_openflag4 */
2742 		if (!xdr_int(xdrs, (int *)&objp->opentype))
2743 			return (FALSE);
2744 		if (objp->opentype == OPEN4_CREATE) {
2745 
2746 			/* xdr_createhow4 */
2747 			if (!xdr_int(xdrs, (int *)&objp->mode))
2748 				return (FALSE);
2749 			switch (objp->mode) {
2750 			case UNCHECKED4:
2751 			case GUARDED4:
2752 				if (!xdr_fattr4(xdrs,
2753 					    &objp->createhow4_u.createattrs))
2754 					return (FALSE);
2755 				break;
2756 			case EXCLUSIVE4:
2757 				if (!xdr_u_longlong_t(xdrs,
2758 				    (u_longlong_t *)&objp->createhow4_u.
2759 				    createverf))
2760 					return (FALSE);
2761 				break;
2762 			default:
2763 				return (FALSE);
2764 			}
2765 		}
2766 
2767 		/* xdr_open_claim4 */
2768 		if (!xdr_int(xdrs, (int *)&objp->claim))
2769 			return (FALSE);
2770 
2771 		switch (objp->claim) {
2772 		case CLAIM_NULL:
2773 			return (xdr_bytes(xdrs, (char **)&objp->open_claim4_u.
2774 					file.utf8string_val,
2775 				(uint_t *)&objp->open_claim4_u.file.
2776 					utf8string_len,
2777 				NFS4_MAX_UTF8STRING));
2778 		case CLAIM_PREVIOUS:
2779 			return (xdr_int(xdrs,
2780 				(int *)&objp->open_claim4_u.delegate_type));
2781 		case CLAIM_DELEGATE_CUR:
2782 			if (!xdr_u_int(xdrs, (uint_t *)&objp->open_claim4_u.
2783 				    delegate_cur_info.delegate_stateid.seqid))
2784 				return (FALSE);
2785 			if (!xdr_opaque(xdrs, objp->open_claim4_u.
2786 				    delegate_cur_info.delegate_stateid.other,
2787 				    12))
2788 				return (FALSE);
2789 			return (xdr_bytes(xdrs, (char **)&objp->open_claim4_u.
2790 				delegate_cur_info.file.utf8string_val,
2791 			    (uint_t *)&objp->open_claim4_u.
2792 				delegate_cur_info.file.utf8string_len,
2793 			    NFS4_MAX_UTF8STRING));
2794 		case CLAIM_DELEGATE_PREV:
2795 			return (xdr_bytes(xdrs, (char **)&objp->open_claim4_u.
2796 				file_delegate_prev.utf8string_val,
2797 			    (uint_t *)&objp->open_claim4_u.
2798 				file_delegate_prev.utf8string_len,
2799 			    NFS4_MAX_UTF8STRING));
2800 		default:
2801 			return (FALSE);
2802 		}
2803 	}
2804 
2805 	/*
2806 	 * Optimized free case
2807 	 */
2808 	if (objp->owner.owner_val != NULL)
2809 		kmem_free(objp->owner.owner_val, objp->owner.owner_len);
2810 
2811 	if (objp->opentype == OPEN4_CREATE) {
2812 		switch (objp->mode) {
2813 		case UNCHECKED4:
2814 		case GUARDED4:
2815 			(void) xdr_fattr4(xdrs,
2816 					&objp->createhow4_u.createattrs);
2817 			break;
2818 		case EXCLUSIVE4:
2819 		default:
2820 			break;
2821 		}
2822 	}
2823 
2824 	switch (objp->claim) {
2825 	case CLAIM_NULL:
2826 		if (objp->open_claim4_u.file.utf8string_val != NULL)
2827 			kmem_free(objp->open_claim4_u.file.utf8string_val,
2828 				objp->open_claim4_u.file.utf8string_len);
2829 		return (TRUE);
2830 	case CLAIM_PREVIOUS:
2831 		return (TRUE);
2832 	case CLAIM_DELEGATE_CUR:
2833 		if (objp->open_claim4_u.delegate_cur_info.file.utf8string_val !=
2834 								NULL) {
2835 			kmem_free(objp->open_claim4_u.delegate_cur_info.file.
2836 							utf8string_val,
2837 				objp->open_claim4_u.delegate_cur_info.file.
2838 							utf8string_len);
2839 		}
2840 		return (TRUE);
2841 	case CLAIM_DELEGATE_PREV:
2842 		if (objp->open_claim4_u.file_delegate_prev.utf8string_val !=
2843 								NULL) {
2844 			kmem_free(objp->open_claim4_u.file_delegate_prev.
2845 							utf8string_val,
2846 				objp->open_claim4_u.file_delegate_prev.
2847 							utf8string_len);
2848 		}
2849 		return (TRUE);
2850 	default:
2851 		return (TRUE);
2852 	}
2853 }
2854 
2855 static bool_t
2856 xdr_OPEN4cargs(XDR *xdrs, OPEN4cargs *objp)
2857 {
2858 	int op;
2859 	int len;
2860 	rpc_inline_t *ptr;
2861 
2862 	ASSERT(xdrs->x_op == XDR_ENCODE);
2863 
2864 	/*
2865 	 * We must always define the client's open_owner to be
2866 	 * 4 byte aligned and sized.
2867 	 */
2868 	ASSERT(objp->owner.owner_len <= NFS4_OPAQUE_LIMIT);
2869 	ASSERT(!(objp->owner.owner_len % BYTES_PER_XDR_UNIT));
2870 
2871 	len = objp->owner.owner_len;
2872 	if ((ptr = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT + len)) != NULL) {
2873 		int i;
2874 		int32_t *ip;
2875 
2876 		IXDR_PUT_U_INT32(ptr, OP_OPEN);
2877 		IXDR_PUT_U_INT32(ptr, objp->seqid);
2878 		IXDR_PUT_U_INT32(ptr, objp->share_access);
2879 		IXDR_PUT_U_INT32(ptr, objp->share_deny);
2880 
2881 		/* xdr_open_owner4 */
2882 		IXDR_PUT_HYPER(ptr, objp->owner.clientid);
2883 		IXDR_PUT_U_INT32(ptr, objp->owner.owner_len);
2884 		/* We know this is very short so don't bcopy */
2885 		ip = (int32_t *)objp->owner.owner_val;
2886 		len /= BYTES_PER_XDR_UNIT;
2887 		for (i = 0; i < len; i++)
2888 			*ptr++ = *ip++;
2889 
2890 		/* xdr_openflag4 */
2891 		IXDR_PUT_U_INT32(ptr, objp->opentype);
2892 	} else {
2893 		op = OP_OPEN;
2894 		if (!XDR_PUTINT32(xdrs, (int32_t *)&op))
2895 			return (FALSE);
2896 		if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->seqid))
2897 			return (FALSE);
2898 		if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->share_access))
2899 			return (FALSE);
2900 		if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->share_deny))
2901 			return (FALSE);
2902 
2903 		/* xdr_open_owner4 */
2904 		if (!xdr_u_longlong_t(xdrs,
2905 				(u_longlong_t *)&objp->owner.clientid))
2906 			return (FALSE);
2907 		if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->owner.owner_len))
2908 			return (FALSE);
2909 		if (!xdr_opaque(xdrs, objp->owner.owner_val,
2910 				objp->owner.owner_len))
2911 			return (FALSE);
2912 
2913 		/* xdr_openflag4 */
2914 		if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->opentype))
2915 			return (FALSE);
2916 	}
2917 
2918 	if (objp->opentype == OPEN4_CREATE) {
2919 		/* xdr_createhow4 */
2920 		if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->mode))
2921 			return (FALSE);
2922 		switch (objp->mode) {
2923 		case UNCHECKED4:
2924 		case GUARDED4:
2925 			if (!xdr_fattr4(xdrs,
2926 				    &objp->createhow4_u.createattrs))
2927 				return (FALSE);
2928 			break;
2929 		case EXCLUSIVE4:
2930 			if (!xdr_u_longlong_t(xdrs,
2931 			    (u_longlong_t *)&objp->createhow4_u.
2932 			    createverf))
2933 				return (FALSE);
2934 			break;
2935 		default:
2936 			return (FALSE);
2937 		}
2938 	}
2939 
2940 	/* xdr_open_claim4 */
2941 	if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->claim))
2942 		return (FALSE);
2943 
2944 	switch (objp->claim) {
2945 	case CLAIM_NULL:
2946 		len = strlen(objp->open_claim4_u.cfile);
2947 		if (len > NFS4_MAX_UTF8STRING)
2948 			return (FALSE);
2949 		if (XDR_PUTINT32(xdrs, &len)) {
2950 			return (xdr_opaque(xdrs,
2951 				objp->open_claim4_u.cfile, len));
2952 		}
2953 		return (FALSE);
2954 	case CLAIM_PREVIOUS:
2955 		return (XDR_PUTINT32(xdrs,
2956 			(int32_t *)&objp->open_claim4_u.delegate_type));
2957 	case CLAIM_DELEGATE_CUR:
2958 		if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->open_claim4_u.
2959 				delegate_cur_info.delegate_stateid.seqid))
2960 			return (FALSE);
2961 		if (!xdr_opaque(xdrs, objp->open_claim4_u.
2962 				delegate_cur_info.delegate_stateid.other,
2963 				12))
2964 			return (FALSE);
2965 		len = strlen(objp->open_claim4_u.delegate_cur_info.cfile);
2966 		if (len > NFS4_MAX_UTF8STRING)
2967 			return (FALSE);
2968 		if (XDR_PUTINT32(xdrs, &len)) {
2969 			return (xdr_opaque(xdrs,
2970 				objp->open_claim4_u.delegate_cur_info.cfile,
2971 				len));
2972 		}
2973 		return (FALSE);
2974 	case CLAIM_DELEGATE_PREV:
2975 		len = strlen(objp->open_claim4_u.cfile_delegate_prev);
2976 		if (len > NFS4_MAX_UTF8STRING)
2977 			return (FALSE);
2978 		if (XDR_PUTINT32(xdrs, &len)) {
2979 			return (xdr_opaque(xdrs,
2980 				objp->open_claim4_u.cfile_delegate_prev, len));
2981 		}
2982 		return (FALSE);
2983 	default:
2984 		return (FALSE);
2985 	}
2986 }
2987 
2988 static bool_t
2989 xdr_OPEN4res(XDR *xdrs, OPEN4res *objp)
2990 {
2991 	if (xdrs->x_op != XDR_FREE) {
2992 		if (!xdr_int(xdrs, (int32_t *)&objp->status))
2993 			return (FALSE);
2994 		if (objp->status != NFS4_OK)
2995 			return (TRUE);
2996 		if (!xdr_u_int(xdrs, &objp->stateid.seqid))
2997 			return (FALSE);
2998 		if (!xdr_opaque(xdrs, objp->stateid.other, 12))
2999 			return (FALSE);
3000 		if (!xdr_bool(xdrs, &objp->cinfo.atomic))
3001 			return (FALSE);
3002 		if (!xdr_u_longlong_t(xdrs,
3003 				(u_longlong_t *)&objp->cinfo.before))
3004 			return (FALSE);
3005 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.after))
3006 			return (FALSE);
3007 		if (!xdr_u_int(xdrs, &objp->rflags))
3008 			return (FALSE);
3009 		if (!xdr_bitmap4(xdrs, &objp->attrset))
3010 			return (FALSE);
3011 		if (!xdr_int(xdrs,
3012 			    (int *)&objp->delegation.delegation_type))
3013 			return (FALSE);
3014 		switch (objp->delegation.delegation_type) {
3015 		case OPEN_DELEGATE_NONE:
3016 			return (TRUE);
3017 		case OPEN_DELEGATE_READ:
3018 			if (!xdr_u_int(xdrs, &objp->delegation.
3019 					open_delegation4_u.read.stateid.seqid))
3020 				return (FALSE);
3021 			if (!xdr_opaque(xdrs, objp->delegation.
3022 					open_delegation4_u.read.stateid.other,
3023 					12))
3024 				return (FALSE);
3025 			if (!xdr_bool(xdrs, &objp->delegation.
3026 					open_delegation4_u.read.recall))
3027 				return (FALSE);
3028 			return (xdr_nfsace4(xdrs, &objp->delegation.
3029 					open_delegation4_u.read.permissions));
3030 		case OPEN_DELEGATE_WRITE:
3031 			if (!xdr_u_int(xdrs, &objp->delegation.
3032 					open_delegation4_u.write.stateid.seqid))
3033 				return (FALSE);
3034 			if (!xdr_opaque(xdrs, objp->delegation.
3035 					open_delegation4_u.write.stateid.other,
3036 					12))
3037 				return (FALSE);
3038 			if (!xdr_bool(xdrs, &objp->delegation.
3039 					open_delegation4_u.write.recall))
3040 				return (FALSE);
3041 			if (!xdr_int(xdrs, (int *)&objp->delegation.
3042 					open_delegation4_u.write.space_limit.
3043 					limitby))
3044 				return (FALSE);
3045 			switch (objp->delegation.
3046 					open_delegation4_u.write.space_limit.
3047 					limitby) {
3048 			case NFS_LIMIT_SIZE:
3049 				if (!xdr_u_longlong_t(xdrs,
3050 				    (u_longlong_t *)&objp->delegation.
3051 				    open_delegation4_u.write.space_limit.
3052 				    nfs_space_limit4_u.filesize))
3053 					return (FALSE);
3054 				break;
3055 			case NFS_LIMIT_BLOCKS:
3056 				if (!xdr_u_int(xdrs,
3057 				    &objp->delegation.open_delegation4_u.write.
3058 				    space_limit.nfs_space_limit4_u.
3059 				    mod_blocks.num_blocks))
3060 					return (FALSE);
3061 				if (!xdr_u_int(xdrs, &objp->delegation.
3062 				    open_delegation4_u.write.space_limit.
3063 				    nfs_space_limit4_u.mod_blocks.
3064 				    bytes_per_block))
3065 					return (FALSE);
3066 				break;
3067 			default:
3068 				return (FALSE);
3069 			}
3070 			return (xdr_nfsace4(xdrs, &objp->delegation.
3071 			    open_delegation4_u.write.permissions));
3072 		}
3073 		return (FALSE);
3074 	}
3075 
3076 	/*
3077 	 * Optimized free case
3078 	 */
3079 	if (objp->status != NFS4_OK)
3080 		return (TRUE);
3081 
3082 	switch (objp->delegation.delegation_type) {
3083 	case OPEN_DELEGATE_NONE:
3084 		return (TRUE);
3085 	case OPEN_DELEGATE_READ:
3086 		return (xdr_nfsace4(xdrs, &objp->delegation.
3087 					open_delegation4_u.read.permissions));
3088 	case OPEN_DELEGATE_WRITE:
3089 		switch (objp->delegation.
3090 				open_delegation4_u.write.space_limit.limitby) {
3091 		case NFS_LIMIT_SIZE:
3092 		case NFS_LIMIT_BLOCKS:
3093 			break;
3094 		default:
3095 			return (FALSE);
3096 		}
3097 		return (xdr_nfsace4(xdrs, &objp->delegation.
3098 				open_delegation4_u.write.permissions));
3099 	}
3100 	return (FALSE);
3101 }
3102 
3103 static bool_t
3104 xdr_OPEN_CONFIRM4res(XDR *xdrs, OPEN_CONFIRM4res *objp)
3105 {
3106 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
3107 		return (FALSE);
3108 	if (objp->status != NFS4_OK)
3109 		return (TRUE);
3110 	if (!xdr_u_int(xdrs, &objp->open_stateid.seqid))
3111 		return (FALSE);
3112 	return (xdr_opaque(xdrs, objp->open_stateid.other, 12));
3113 }
3114 
3115 static bool_t
3116 xdr_OPEN_DOWNGRADE4args(XDR *xdrs, OPEN_DOWNGRADE4args *objp)
3117 {
3118 	if (!xdr_u_int(xdrs, &objp->open_stateid.seqid))
3119 		return (FALSE);
3120 	if (!xdr_opaque(xdrs, objp->open_stateid.other, 12))
3121 		return (FALSE);
3122 	if (!xdr_u_int(xdrs, &objp->seqid))
3123 		return (FALSE);
3124 	if (!xdr_u_int(xdrs, &objp->share_access))
3125 		return (FALSE);
3126 	return (xdr_u_int(xdrs, &objp->share_deny));
3127 }
3128 
3129 static bool_t
3130 xdr_OPEN_DOWNGRADE4res(XDR *xdrs, OPEN_DOWNGRADE4res *objp)
3131 {
3132 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
3133 		return (FALSE);
3134 	if (objp->status != NFS4_OK)
3135 		return (TRUE);
3136 	if (!xdr_u_int(xdrs, &objp->open_stateid.seqid))
3137 		return (FALSE);
3138 	return (xdr_opaque(xdrs, objp->open_stateid.other, 12));
3139 }
3140 
3141 static bool_t
3142 xdr_READ4args(XDR *xdrs, READ4args *objp)
3143 {
3144 	if (!xdr_u_int(xdrs, &objp->stateid.seqid))
3145 		return (FALSE);
3146 	if (!xdr_opaque(xdrs, objp->stateid.other, 12))
3147 		return (FALSE);
3148 	if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset))
3149 		return (FALSE);
3150 	return (xdr_u_int(xdrs, &objp->count));
3151 }
3152 
3153 static bool_t
3154 xdr_READ4res(XDR *xdrs, READ4res *objp)
3155 {
3156 	int i, rndup;
3157 	mblk_t *mp;
3158 
3159 	if (xdrs->x_op == XDR_DECODE)
3160 		return (FALSE);
3161 
3162 	if (xdrs->x_op == XDR_FREE) {
3163 		/*
3164 		 * Optimized free case
3165 		 */
3166 		if (objp->status != NFS4_OK)
3167 			return (TRUE);
3168 		if (objp->data_val != NULL)
3169 			kmem_free(objp->data_val, objp->data_len);
3170 		return (TRUE);
3171 	}
3172 
3173 	/* on with ENCODE paths */
3174 	if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->status))
3175 		return (FALSE);
3176 	if (objp->status != NFS4_OK)
3177 		return (TRUE);
3178 
3179 	if (!XDR_PUTINT32(xdrs, &objp->eof))
3180 		return (FALSE);
3181 
3182 	mp = objp->mblk;
3183 	if (mp != NULL && xdrs->x_ops == &xdrmblk_ops) {
3184 		mp->b_wptr += objp->data_len;
3185 		rndup = BYTES_PER_XDR_UNIT -
3186 			(objp->data_len % BYTES_PER_XDR_UNIT);
3187 		if (rndup != BYTES_PER_XDR_UNIT)
3188 			for (i = 0; i < rndup; i++)
3189 				*mp->b_wptr++ = '\0';
3190 		if (xdrmblk_putmblk(xdrs, mp, objp->data_len) == TRUE) {
3191 			objp->mblk = NULL;
3192 			return (TRUE);
3193 		}
3194 	}
3195 	return (xdr_bytes(xdrs, (char **)&objp->data_val,
3196 			(uint_t *)&objp->data_len,
3197 			objp->data_len));
3198 }
3199 
3200 static bool_t
3201 xdr_READ4res_clnt(XDR *xdrs, READ4res *objp, READ4args *aobjp)
3202 {
3203 	mblk_t *mp;
3204 	size_t n;
3205 	int error;
3206 	uint_t size = aobjp->res_maxsize;
3207 
3208 	if (xdrs->x_op == XDR_ENCODE)
3209 		return (FALSE);
3210 
3211 	if (xdrs->x_op == XDR_FREE) {
3212 		/*
3213 		 * Optimized free case
3214 		 */
3215 		if (objp->status != NFS4_OK)
3216 			return (TRUE);
3217 		if (objp->data_val != NULL)
3218 			kmem_free(objp->data_val, objp->data_len);
3219 		return (TRUE);
3220 	}
3221 
3222 	if (!XDR_GETINT32(xdrs, (int32_t *)&objp->status))
3223 		return (FALSE);
3224 	if (objp->status != NFS4_OK)
3225 		return (TRUE);
3226 
3227 	if (!XDR_GETINT32(xdrs, &objp->eof))
3228 		return (FALSE);
3229 
3230 
3231 	/*
3232 	 * This is a special case such that the caller is providing a
3233 	 * uio as a guide to eventual data location; this is used for
3234 	 * handling DIRECTIO reads.
3235 	 */
3236 	if (aobjp->res_uiop != NULL) {
3237 		struct uio *uiop = aobjp->res_uiop;
3238 		int32_t *ptr;
3239 
3240 		if (xdrs->x_ops == &xdrmblk_ops) {
3241 			if (!xdrmblk_getmblk(xdrs, &mp, &objp->data_len))
3242 				return (FALSE);
3243 
3244 			if (objp->data_len == 0)
3245 				return (TRUE);
3246 
3247 			if (objp->data_len > size)
3248 				return (FALSE);
3249 
3250 			size = objp->data_len;
3251 			do {
3252 				n = MIN(size, mp->b_wptr - mp->b_rptr);
3253 				if ((n = MIN(uiop->uio_resid, n)) != 0) {
3254 
3255 					error =	uiomove((char *)mp->b_rptr, n,
3256 							UIO_READ, uiop);
3257 					if (error)
3258 						return (FALSE);
3259 					mp->b_rptr += n;
3260 					size -= n;
3261 				}
3262 
3263 				while (mp && (mp->b_rptr >= mp->b_wptr))
3264 					mp = mp->b_cont;
3265 			} while (mp && size > 0 && uiop->uio_resid > 0);
3266 
3267 			return (TRUE);
3268 		}
3269 
3270 		/*
3271 		 * This isn't an xdrmblk stream.   Handle the likely
3272 		 * case that it can be inlined (ex. xdrmem).
3273 		 */
3274 		if (!XDR_GETINT32(xdrs, (int32_t *)&objp->data_len))
3275 			return (FALSE);
3276 
3277 		if (objp->data_len == 0)
3278 			return (TRUE);
3279 
3280 		if (objp->data_len > size)
3281 			return (FALSE);
3282 
3283 		size = (int)objp->data_len;
3284 		if ((ptr = XDR_INLINE(xdrs, size)) != NULL)
3285 			return (uiomove(ptr, size, UIO_READ, uiop) ?
3286 				FALSE : TRUE);
3287 
3288 		/*
3289 		 * Handle some other (unlikely) stream type that will
3290 		 * need a copy.
3291 		 */
3292 		if ((ptr = kmem_alloc(size, KM_NOSLEEP)) == NULL)
3293 			return (FALSE);
3294 
3295 		if (!XDR_GETBYTES(xdrs, (caddr_t)ptr, size)) {
3296 			kmem_free(ptr, size);
3297 			return (FALSE);
3298 		}
3299 		error = uiomove(ptr, size, UIO_READ, uiop);
3300 		kmem_free(ptr, size);
3301 
3302 		return (error ? FALSE : TRUE);
3303 	}
3304 
3305 	/*
3306 	 * Check for the other special case of the caller providing
3307 	 * the target area for the data.
3308 	 */
3309 	if (aobjp->res_data_val_alt)
3310 		return (xdr_bytes(xdrs, (char **)&aobjp->res_data_val_alt,
3311 				(uint_t *)&objp->data_len,
3312 				aobjp->res_maxsize));
3313 
3314 	/* caller didn't set things up right if we got this far */
3315 	return (FALSE);
3316 }
3317 
3318 static bool_t
3319 xdr_READDIR4args(XDR *xdrs, READDIR4args *objp)
3320 {
3321 	if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cookie))
3322 		return (FALSE);
3323 	if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cookieverf))
3324 		return (FALSE);
3325 	if (!xdr_u_int(xdrs, &objp->dircount))
3326 		return (FALSE);
3327 	if (!xdr_u_int(xdrs, &objp->maxcount))
3328 		return (FALSE);
3329 	return (xdr_bitmap4(xdrs, &objp->attr_request));
3330 }
3331 
3332 /* ARGSUSED */
3333 static bool_t
3334 xdrmblk_putmblk_rd(XDR *xdrs, mblk_t *m)
3335 {
3336 	if (((m->b_wptr - m->b_rptr) % BYTES_PER_XDR_UNIT) != 0)
3337 		return (FALSE);
3338 
3339 	/* LINTED pointer alignment */
3340 	((mblk_t *)xdrs->x_base)->b_cont = m;
3341 	xdrs->x_base = (caddr_t)m;
3342 	xdrs->x_handy = 0;
3343 	return (TRUE);
3344 }
3345 
3346 bool_t
3347 xdr_READDIR4res(XDR *xdrs, READDIR4res *objp)
3348 {
3349 	mblk_t *mp = objp->mblk;
3350 	bool_t ret_val;
3351 	uint_t flags = 0;
3352 
3353 	ASSERT(xdrs->x_op == XDR_ENCODE);
3354 
3355 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
3356 		return (FALSE);
3357 	if (objp->status != NFS4_OK)
3358 		return (TRUE);
3359 	if (mp == NULL)
3360 		return (FALSE);
3361 
3362 	if (xdrs->x_ops == &xdrmblk_ops) {
3363 		if (xdrmblk_putmblk_rd(xdrs, mp)
3364 				    == TRUE) {
3365 			/* mblk successfully inserted into outgoing chain */
3366 			objp->mblk = NULL;
3367 			return (TRUE);
3368 		}
3369 	}
3370 
3371 	ASSERT(mp->b_cont == NULL);
3372 
3373 	/*
3374 	 * If running over RDMA, the pre-encoded m_blk needs to be moved
3375 	 * without being chunked.
3376 	 * Check if chunking is disabled for this xdr stream. If not disable
3377 	 * it for this op and then enable it back on.
3378 	 */
3379 	XDR_CONTROL(xdrs, XDR_RDMAGET, &flags);
3380 	if (flags & RDMA_NOCHUNK)
3381 		return (xdr_opaque(xdrs, (char *)mp->b_rptr, objp->data_len));
3382 
3383 	flags |= RDMA_NOCHUNK;
3384 	(void) XDR_CONTROL(xdrs, XDR_RDMASET, &flags);
3385 	ret_val = xdr_opaque(xdrs, (char *)mp->b_rptr, objp->data_len);
3386 	flags &= ~RDMA_NOCHUNK;
3387 	(void) XDR_CONTROL(xdrs, XDR_RDMASET, &flags);
3388 	return (ret_val);
3389 }
3390 
3391 static bool_t
3392 xdr_READLINK4res(XDR *xdrs, READLINK4res *objp)
3393 {
3394 	if (xdrs->x_op != XDR_FREE) {
3395 		if (!xdr_int(xdrs, (int32_t *)&objp->status))
3396 			return (FALSE);
3397 		if (objp->status != NFS4_OK)
3398 			return (TRUE);
3399 		return (xdr_bytes(xdrs, (char **)&objp->link.utf8string_val,
3400 			(uint_t *)&objp->link.utf8string_len,
3401 			NFS4_MAX_UTF8STRING));
3402 	}
3403 
3404 	/*
3405 	 * Optimized free case
3406 	 */
3407 	if (objp->status != NFS4_OK)
3408 		return (TRUE);
3409 	if (objp->link.utf8string_val != NULL)
3410 		kmem_free(objp->link.utf8string_val, objp->link.utf8string_len);
3411 	return (TRUE);
3412 }
3413 
3414 static bool_t
3415 xdr_REMOVE4res(XDR *xdrs, REMOVE4res *objp)
3416 {
3417 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
3418 		return (FALSE);
3419 	if (objp->status != NFS4_OK)
3420 		return (TRUE);
3421 	if (!xdr_bool(xdrs, &objp->cinfo.atomic))
3422 		return (FALSE);
3423 	if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.before))
3424 		return (FALSE);
3425 	return (xdr_u_longlong_t(xdrs,
3426 		(u_longlong_t *)&objp->cinfo.after));
3427 }
3428 
3429 static bool_t
3430 xdr_RENAME4res(XDR *xdrs, RENAME4res *objp)
3431 {
3432 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
3433 		return (FALSE);
3434 	if (objp->status != NFS4_OK)
3435 		return (TRUE);
3436 	if (!xdr_bool(xdrs, &objp->source_cinfo.atomic))
3437 		return (FALSE);
3438 	if (!xdr_u_longlong_t(xdrs,
3439 	    (u_longlong_t *)&objp->source_cinfo.before))
3440 		return (FALSE);
3441 	if (!xdr_u_longlong_t(xdrs,
3442 	    (u_longlong_t *)&objp->source_cinfo.after))
3443 		return (FALSE);
3444 	if (!xdr_bool(xdrs, &objp->target_cinfo.atomic))
3445 		return (FALSE);
3446 	if (!xdr_u_longlong_t(xdrs,
3447 	    (u_longlong_t *)&objp->target_cinfo.before))
3448 		return (FALSE);
3449 	return (xdr_u_longlong_t(xdrs,
3450 		(u_longlong_t *)&objp->target_cinfo.after));
3451 }
3452 
3453 static bool_t
3454 xdr_secinfo4(XDR *xdrs, secinfo4 *objp)
3455 {
3456 	if (xdrs->x_op != XDR_FREE) {
3457 		if (!xdr_u_int(xdrs, &objp->flavor))
3458 			return (FALSE);
3459 		if (objp->flavor != RPCSEC_GSS)
3460 			return (TRUE);
3461 		if (!xdr_bytes(xdrs,
3462 			    (char **)&objp->flavor_info.oid.sec_oid4_val,
3463 			    (uint_t *)&objp->flavor_info.oid.sec_oid4_len,
3464 			    NFS4_MAX_SECOID4))
3465 			return (FALSE);
3466 		if (!xdr_u_int(xdrs, &objp->flavor_info.qop))
3467 			return (FALSE);
3468 		return (xdr_int(xdrs, (int *)&objp->flavor_info.service));
3469 	}
3470 
3471 	/*
3472 	 * Optimized free path
3473 	 */
3474 	if (objp->flavor != RPCSEC_GSS)
3475 		return (TRUE);
3476 
3477 	if (objp->flavor_info.oid.sec_oid4_val != NULL)
3478 		kmem_free(objp->flavor_info.oid.sec_oid4_val,
3479 			objp->flavor_info.oid.sec_oid4_len);
3480 	return (TRUE);
3481 }
3482 
3483 static bool_t
3484 xdr_SETCLIENTID4args(XDR *xdrs, SETCLIENTID4args *objp)
3485 {
3486 	if (xdrs->x_op != XDR_FREE) {
3487 		if (!xdr_u_longlong_t(xdrs,
3488 					(u_longlong_t *)&objp->client.verifier))
3489 			return (FALSE);
3490 		if (!xdr_bytes(xdrs, (char **)&objp->client.id_val,
3491 			    (uint_t *)&objp->client.id_len, NFS4_OPAQUE_LIMIT))
3492 			return (FALSE);
3493 		if (!xdr_u_int(xdrs, &objp->callback.cb_program))
3494 			return (FALSE);
3495 		if (!xdr_string(xdrs, &objp->callback.cb_location.r_netid,
3496 						NFS4_OPAQUE_LIMIT))
3497 			return (FALSE);
3498 		if (!xdr_string(xdrs, &objp->callback.cb_location.r_addr,
3499 						NFS4_OPAQUE_LIMIT))
3500 			return (FALSE);
3501 		return (xdr_u_int(xdrs, &objp->callback_ident));
3502 	}
3503 
3504 	/*
3505 	 * Optimized free case
3506 	 */
3507 	if (objp->client.id_val != NULL)
3508 		kmem_free(objp->client.id_val, objp->client.id_len);
3509 	(void) xdr_string(xdrs, &objp->callback.cb_location.r_netid,
3510 							NFS4_OPAQUE_LIMIT);
3511 	return (xdr_string(xdrs, &objp->callback.cb_location.r_addr,
3512 							NFS4_OPAQUE_LIMIT));
3513 }
3514 
3515 static bool_t
3516 xdr_SETCLIENTID4res(XDR *xdrs, SETCLIENTID4res *objp)
3517 {
3518 	if (xdrs->x_op != XDR_FREE) {
3519 		if (!xdr_int(xdrs, (int32_t *)&objp->status))
3520 			return (FALSE);
3521 		switch (objp->status) {
3522 		case NFS4_OK:
3523 			if (!xdr_u_longlong_t(xdrs,
3524 			    (u_longlong_t *)&objp->SETCLIENTID4res_u.resok4.
3525 			    clientid))
3526 				return (FALSE);
3527 			return (xdr_u_longlong_t(xdrs,
3528 			    (u_longlong_t *)&objp->SETCLIENTID4res_u.
3529 						resok4.setclientid_confirm));
3530 		case NFS4ERR_CLID_INUSE:
3531 			if (!xdr_string(xdrs,
3532 				    &objp->SETCLIENTID4res_u.client_using.
3533 				    r_netid, NFS4_OPAQUE_LIMIT))
3534 				return (FALSE);
3535 			return (xdr_string(xdrs,
3536 				    &objp->SETCLIENTID4res_u.client_using.
3537 				    r_addr, NFS4_OPAQUE_LIMIT));
3538 		}
3539 		return (TRUE);
3540 	}
3541 
3542 	/*
3543 	 * Optimized free case
3544 	 */
3545 	if (objp->status != NFS4ERR_CLID_INUSE)
3546 		return (TRUE);
3547 
3548 	if (!xdr_string(xdrs, &objp->SETCLIENTID4res_u.client_using.r_netid,
3549 							NFS4_OPAQUE_LIMIT))
3550 		return (FALSE);
3551 	return (xdr_string(xdrs, &objp->SETCLIENTID4res_u.client_using.r_addr,
3552 							NFS4_OPAQUE_LIMIT));
3553 }
3554 
3555 static bool_t
3556 xdr_WRITE4args(XDR *xdrs, WRITE4args *objp)
3557 {
3558 	if (xdrs->x_op != XDR_FREE) {
3559 		if (!xdr_u_int(xdrs, &objp->stateid.seqid))
3560 			return (FALSE);
3561 		if (!xdr_opaque(xdrs, objp->stateid.other, 12))
3562 			return (FALSE);
3563 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset))
3564 			return (FALSE);
3565 		if (!xdr_int(xdrs, (int *)&objp->stable))
3566 			return (FALSE);
3567 		if (xdrs->x_op == XDR_DECODE) {
3568 			if (xdrs->x_ops == &xdrmblk_ops) {
3569 				objp->data_val = NULL;
3570 				return (xdrmblk_getmblk(xdrs, &objp->mblk,
3571 							&objp->data_len));
3572 			}
3573 			/* Else fall thru for the xdr_bytes(). */
3574 			objp->mblk = NULL;
3575 		}
3576 		return (xdr_bytes(xdrs, (char **)&objp->data_val,
3577 				(uint_t *)&objp->data_len, NFS4_DATA_LIMIT));
3578 	}
3579 
3580 	/*
3581 	 * Optimized free case
3582 	 */
3583 	if (objp->data_val != NULL)
3584 		kmem_free(objp->data_val, objp->data_len);
3585 	return (TRUE);
3586 }
3587 
3588 static bool_t
3589 xdr_WRITE4res(XDR *xdrs, WRITE4res *objp)
3590 {
3591 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
3592 		return (FALSE);
3593 	if (objp->status != NFS4_OK)
3594 		return (TRUE);
3595 	if (!xdr_u_int(xdrs, &objp->count))
3596 		return (FALSE);
3597 	if (!xdr_int(xdrs, (int *)&objp->committed))
3598 		return (FALSE);
3599 	return (xdr_u_longlong_t(xdrs,
3600 			(u_longlong_t *)&objp->writeverf));
3601 }
3602 
3603 static bool_t
3604 xdr_snfs_argop4_free(XDR *xdrs, nfs_argop4 **arrayp, int len)
3605 {
3606 	int i;
3607 	nfs_argop4 *array = *arrayp;
3608 
3609 	/*
3610 	 * Optimized XDR_FREE only args array
3611 	 */
3612 	ASSERT(xdrs->x_op == XDR_FREE);
3613 
3614 	/*
3615 	 * Nothing to do?
3616 	 */
3617 	if (array == NULL)
3618 		return (TRUE);
3619 
3620 	for (i = 0; i < len; i++) {
3621 		/*
3622 		 * These should be ordered by frequency of use
3623 		 */
3624 		switch (array[i].argop) {
3625 		case OP_PUTFH:
3626 			if (array[i].nfs_argop4_u.opputfh.object.nfs_fh4_val !=
3627 								NULL) {
3628 				kmem_free(array[i].nfs_argop4_u.opputfh.object.
3629 								nfs_fh4_val,
3630 					array[i].nfs_argop4_u.opputfh.object.
3631 								nfs_fh4_len);
3632 			}
3633 			continue;
3634 		case OP_GETATTR:
3635 		case OP_GETFH:
3636 			continue;
3637 		case OP_LOOKUP:
3638 			if (array[i].nfs_argop4_u.oplookup.objname.
3639 						utf8string_val != NULL) {
3640 				kmem_free(array[i].nfs_argop4_u.oplookup.
3641 						objname.utf8string_val,
3642 					array[i].nfs_argop4_u.oplookup.
3643 						objname.utf8string_len);
3644 			}
3645 			continue;
3646 		case OP_OPEN:
3647 			(void) xdr_OPEN4args(xdrs,
3648 						&array[i].nfs_argop4_u.opopen);
3649 			continue;
3650 		case OP_CLOSE:
3651 		case OP_ACCESS:
3652 		case OP_READ:
3653 			continue;
3654 		case OP_WRITE:
3655 			(void) xdr_WRITE4args(xdrs,
3656 						&array[i].nfs_argop4_u.opwrite);
3657 			continue;
3658 		case OP_DELEGRETURN:
3659 		case OP_LOOKUPP:
3660 		case OP_READDIR:
3661 			continue;
3662 		case OP_REMOVE:
3663 			if (array[i].nfs_argop4_u.opremove.target.
3664 						utf8string_val != NULL) {
3665 				kmem_free(array[i].nfs_argop4_u.opremove.target.
3666 							utf8string_val,
3667 					array[i].nfs_argop4_u.opremove.target.
3668 							utf8string_len);
3669 			}
3670 			continue;
3671 		case OP_COMMIT:
3672 			continue;
3673 		case OP_CREATE:
3674 			(void) xdr_CREATE4args(xdrs,
3675 					&array[i].nfs_argop4_u.opcreate);
3676 			continue;
3677 		case OP_DELEGPURGE:
3678 			continue;
3679 		case OP_LINK:
3680 			if (array[i].nfs_argop4_u.oplink.newname.
3681 						utf8string_val != NULL) {
3682 				kmem_free(array[i].nfs_argop4_u.oplink.newname.
3683 							utf8string_val,
3684 					array[i].nfs_argop4_u.oplink.newname.
3685 							utf8string_len);
3686 			}
3687 			continue;
3688 		case OP_LOCK:
3689 			(void) xdr_LOCK4args(xdrs,
3690 						&array[i].nfs_argop4_u.oplock);
3691 			continue;
3692 		case OP_LOCKT:
3693 			(void) xdr_LOCKT4args(xdrs,
3694 						&array[i].nfs_argop4_u.oplockt);
3695 			continue;
3696 		case OP_LOCKU:
3697 			continue;
3698 		case OP_NVERIFY:
3699 			(void) xdr_fattr4(xdrs,
3700 			    &array[i].nfs_argop4_u.opnverify.obj_attributes);
3701 			continue;
3702 		case OP_OPENATTR:
3703 		case OP_OPEN_CONFIRM:
3704 		case OP_OPEN_DOWNGRADE:
3705 		case OP_PUTPUBFH:
3706 		case OP_PUTROOTFH:
3707 		case OP_READLINK:
3708 			continue;
3709 		case OP_RENAME:
3710 			if (array[i].nfs_argop4_u.oprename.oldname.
3711 						utf8string_val != NULL) {
3712 				kmem_free(array[i].nfs_argop4_u.oprename.
3713 						oldname.utf8string_val,
3714 					array[i].nfs_argop4_u.oprename.
3715 						oldname.utf8string_len);
3716 			}
3717 			if (array[i].nfs_argop4_u.oprename.newname.
3718 						utf8string_val != NULL) {
3719 				kmem_free(array[i].nfs_argop4_u.oprename.
3720 						newname.utf8string_val,
3721 					array[i].nfs_argop4_u.oprename.
3722 						newname.utf8string_len);
3723 			}
3724 			continue;
3725 		case OP_RENEW:
3726 		case OP_RESTOREFH:
3727 		case OP_SAVEFH:
3728 			continue;
3729 		case OP_SECINFO:
3730 			if (array[i].nfs_argop4_u.opsecinfo.name.
3731 						utf8string_val != NULL) {
3732 				kmem_free(array[i].nfs_argop4_u.opsecinfo.name.
3733 							utf8string_val,
3734 					array[i].nfs_argop4_u.opsecinfo.name.
3735 							utf8string_len);
3736 			}
3737 			continue;
3738 		case OP_SETATTR:
3739 			(void) xdr_fattr4(xdrs,
3740 			    &array[i].nfs_argop4_u.opsetattr.obj_attributes);
3741 			continue;
3742 		case OP_SETCLIENTID:
3743 			(void) xdr_SETCLIENTID4args(xdrs,
3744 					&array[i].nfs_argop4_u.opsetclientid);
3745 			continue;
3746 		case OP_SETCLIENTID_CONFIRM:
3747 			continue;
3748 		case OP_VERIFY:
3749 			(void) xdr_fattr4(xdrs,
3750 				&array[i].nfs_argop4_u.opverify.obj_attributes);
3751 			continue;
3752 		case OP_RELEASE_LOCKOWNER:
3753 			if (array[i].nfs_argop4_u.oprelease_lockowner.
3754 						lock_owner.owner_val != NULL) {
3755 				kmem_free(array[i].nfs_argop4_u.
3756 				    oprelease_lockowner.lock_owner.owner_val,
3757 					array[i].nfs_argop4_u.
3758 				    oprelease_lockowner.lock_owner.owner_len);
3759 			}
3760 			continue;
3761 		case OP_ILLEGAL:
3762 			continue;
3763 		default:
3764 			/*
3765 			 * An invalid op is a coding error, it should never
3766 			 * have been decoded.
3767 			 * Don't error because the caller cannot finish
3768 			 * freeing the residual memory of the array.
3769 			 */
3770 			continue;
3771 		}
3772 	}
3773 
3774 	kmem_free(*arrayp, len * sizeof (nfs_argop4));
3775 	*arrayp = NULL;
3776 	return (TRUE);
3777 }
3778 
3779 static bool_t
3780 xdr_nfs_argop4(XDR *xdrs, nfs_argop4 *objp)
3781 {
3782 	/*
3783 	 * These should be ordered by frequency of use
3784 	 */
3785 	switch (objp->argop) {
3786 	case OP_PUTFH:
3787 		return (xdr_bytes(xdrs,
3788 		    (char **)&objp->nfs_argop4_u.opputfh.object.nfs_fh4_val,
3789 		    (uint_t *)&objp->nfs_argop4_u.opputfh.object.nfs_fh4_len,
3790 		    NFS4_FHSIZE));
3791 	case OP_GETATTR:
3792 		return (xdr_bitmap4(xdrs,
3793 				&objp->nfs_argop4_u.opgetattr.attr_request));
3794 	case OP_GETFH:
3795 		return (TRUE);
3796 	case OP_LOOKUP:
3797 		return (xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.oplookup.
3798 				objname.utf8string_val,
3799 			(uint_t *)&objp->nfs_argop4_u.oplookup.
3800 				objname.utf8string_len,
3801 			NFS4_MAX_UTF8STRING));
3802 	case OP_OPEN:
3803 		return (xdr_OPEN4args(xdrs, &objp->nfs_argop4_u.opopen));
3804 	case OP_CLOSE:
3805 		return (xdr_CLOSE4args(xdrs, &objp->nfs_argop4_u.opclose));
3806 	case OP_ACCESS:
3807 		return (xdr_u_int(xdrs,
3808 				&objp->nfs_argop4_u.opaccess.access));
3809 	case OP_READ:
3810 		return (xdr_READ4args(xdrs, &objp->nfs_argop4_u.opread));
3811 	case OP_WRITE:
3812 		return (xdr_WRITE4args(xdrs, &objp->nfs_argop4_u.opwrite));
3813 	case OP_DELEGRETURN:
3814 		if (!xdr_u_int(xdrs,
3815 		    &objp->nfs_argop4_u.opdelegreturn.deleg_stateid.seqid))
3816 			return (FALSE);
3817 		return (xdr_opaque(xdrs,
3818 		    objp->nfs_argop4_u.opdelegreturn.deleg_stateid.other, 12));
3819 	case OP_LOOKUPP:
3820 		return (TRUE);
3821 	case OP_READDIR:
3822 		return (xdr_READDIR4args(xdrs, &objp->nfs_argop4_u.opreaddir));
3823 	case OP_REMOVE:
3824 		return (xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.opremove.
3825 				target.utf8string_val,
3826 			(uint_t *)&objp->nfs_argop4_u.opremove.
3827 				target.utf8string_len,
3828 			NFS4_MAX_UTF8STRING));
3829 	case OP_COMMIT:
3830 		if (!xdr_u_longlong_t(xdrs,
3831 		    (u_longlong_t *)&objp->nfs_argop4_u.opcommit.offset))
3832 			return (FALSE);
3833 		return (xdr_u_int(xdrs, &objp->nfs_argop4_u.opcommit.count));
3834 	case OP_CREATE:
3835 		return (xdr_CREATE4args(xdrs, &objp->nfs_argop4_u.opcreate));
3836 	case OP_DELEGPURGE:
3837 		return (xdr_u_longlong_t(xdrs,
3838 		    (u_longlong_t *)&objp->nfs_argop4_u.opdelegpurge.clientid));
3839 	case OP_LINK:
3840 		return (xdr_bytes(xdrs,
3841 		    (char **)&objp->nfs_argop4_u.oplink.newname.utf8string_val,
3842 		    (uint_t *)&objp->nfs_argop4_u.oplink.newname.utf8string_len,
3843 		    NFS4_MAX_UTF8STRING));
3844 	case OP_LOCK:
3845 		return (xdr_LOCK4args(xdrs, &objp->nfs_argop4_u.oplock));
3846 	case OP_LOCKT:
3847 		return (xdr_LOCKT4args(xdrs, &objp->nfs_argop4_u.oplockt));
3848 	case OP_LOCKU:
3849 		return (xdr_LOCKU4args(xdrs, &objp->nfs_argop4_u.oplocku));
3850 	case OP_NVERIFY:
3851 		return (xdr_fattr4(xdrs,
3852 				&objp->nfs_argop4_u.opnverify.obj_attributes));
3853 	case OP_OPENATTR:
3854 		return (xdr_bool(xdrs,
3855 				&objp->nfs_argop4_u.opopenattr.createdir));
3856 	case OP_OPEN_CONFIRM:
3857 		if (!xdr_u_int(xdrs, &objp->nfs_argop4_u.opopen_confirm.
3858 						open_stateid.seqid))
3859 			return (FALSE);
3860 		if (!xdr_opaque(xdrs, objp->nfs_argop4_u.opopen_confirm.
3861 						open_stateid.other, 12))
3862 			return (FALSE);
3863 		return (xdr_u_int(xdrs, &objp->nfs_argop4_u.opopen_confirm.
3864 						seqid));
3865 	case OP_OPEN_DOWNGRADE:
3866 		return (xdr_OPEN_DOWNGRADE4args(xdrs,
3867 				&objp->nfs_argop4_u.opopen_downgrade));
3868 	case OP_PUTPUBFH:
3869 		return (TRUE);
3870 	case OP_PUTROOTFH:
3871 		return (TRUE);
3872 	case OP_READLINK:
3873 		return (TRUE);
3874 	case OP_RENAME:
3875 		if (!xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.oprename.
3876 						oldname.utf8string_val,
3877 			    (uint_t *)&objp->nfs_argop4_u.oprename.
3878 						oldname.utf8string_len,
3879 			    NFS4_MAX_UTF8STRING))
3880 			return (FALSE);
3881 		return (xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.oprename.
3882 						newname.utf8string_val,
3883 			    (uint_t *)&objp->nfs_argop4_u.oprename.
3884 						newname.utf8string_len,
3885 			    NFS4_MAX_UTF8STRING));
3886 	case OP_RENEW:
3887 		return (xdr_u_longlong_t(xdrs,
3888 			(u_longlong_t *)&objp->nfs_argop4_u.oprenew.clientid));
3889 	case OP_RESTOREFH:
3890 		return (TRUE);
3891 	case OP_SAVEFH:
3892 		return (TRUE);
3893 	case OP_SECINFO:
3894 		return (xdr_bytes(xdrs,
3895 		    (char **)&objp->nfs_argop4_u.opsecinfo.name.utf8string_val,
3896 		    (uint_t *)&objp->nfs_argop4_u.opsecinfo.name.utf8string_len,
3897 		    NFS4_MAX_UTF8STRING));
3898 	case OP_SETATTR:
3899 		if (!xdr_u_int(xdrs, &objp->nfs_argop4_u.opsetattr.
3900 						stateid.seqid))
3901 			return (FALSE);
3902 		if (!xdr_opaque(xdrs, objp->nfs_argop4_u.opsetattr.
3903 						stateid.other, 12))
3904 			return (FALSE);
3905 		return (xdr_fattr4(xdrs, &objp->nfs_argop4_u.opsetattr.
3906 						obj_attributes));
3907 	case OP_SETCLIENTID:
3908 		return (xdr_SETCLIENTID4args(xdrs,
3909 				&objp->nfs_argop4_u.opsetclientid));
3910 	case OP_SETCLIENTID_CONFIRM:
3911 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->nfs_argop4_u.
3912 				opsetclientid_confirm.clientid))
3913 			return (FALSE);
3914 		return (xdr_u_longlong_t(xdrs,
3915 				(u_longlong_t *)&objp->nfs_argop4_u.
3916 				opsetclientid_confirm.setclientid_confirm));
3917 	case OP_VERIFY:
3918 		return (xdr_fattr4(xdrs,
3919 				&objp->nfs_argop4_u.opverify.obj_attributes));
3920 	case OP_RELEASE_LOCKOWNER:
3921 		if (!xdr_u_longlong_t(xdrs,
3922 			    (u_longlong_t *)&objp->nfs_argop4_u.
3923 				oprelease_lockowner.lock_owner.clientid))
3924 			return (FALSE);
3925 		return (xdr_bytes(xdrs,
3926 			(char **)&objp->nfs_argop4_u.oprelease_lockowner.
3927 				lock_owner.owner_val,
3928 			(uint_t *)&objp->nfs_argop4_u.oprelease_lockowner.
3929 				lock_owner.owner_len, NFS4_OPAQUE_LIMIT));
3930 	case OP_ILLEGAL:
3931 		return (TRUE);
3932 	}
3933 	return (FALSE);
3934 }
3935 
3936 static bool_t
3937 xdr_cnfs_argop4_wrap(XDR *xdrs, nfs_argop4 *objp)
3938 {
3939 	if (!xdr_int(xdrs, (int *)&objp->argop))
3940 		return (FALSE);
3941 
3942 	return (xdr_nfs_argop4(xdrs, objp));
3943 }
3944 
3945 static bool_t
3946 xdr_snfs_argop4(XDR *xdrs, nfs_argop4 *objp)
3947 {
3948 	if (!xdr_int(xdrs, (int *)&objp->argop))
3949 		return (FALSE);
3950 
3951 	switch (objp->argop) {
3952 	case OP_PUTFH:
3953 		return (xdr_decode_nfs_fh4(xdrs,
3954 			&objp->nfs_argop4_u.opputfh.object));
3955 	default:
3956 		return (xdr_nfs_argop4(xdrs, objp));
3957 	}
3958 }
3959 
3960 /*
3961  * Client side encode only arg op processing
3962  */
3963 static bool_t
3964 xdr_cnfs_argop4(XDR *xdrs, nfs_argop4 *objp)
3965 {
3966 	int len;
3967 	int op;
3968 	nfs4_sharedfh_t *sfh;
3969 	mntinfo4_t *mi;
3970 	rpc_inline_t *ptr;
3971 
3972 	ASSERT(xdrs->x_op == XDR_ENCODE);
3973 
3974 	/*
3975 	 * Special case the private pseudo ops
3976 	 */
3977 	if (!(objp->argop & SUNW_PRIVATE_OP))
3978 		return (xdr_cnfs_argop4_wrap(xdrs, objp));
3979 
3980 	/*
3981 	 * These should be ordered by frequency of use
3982 	 */
3983 	switch (objp->argop) {
3984 	case OP_CPUTFH:
3985 		/*
3986 		 * We are passed in the file handle as a nfs4_sharedfh_t *
3987 		 * We need to acquire the correct locks so we can copy it out.
3988 		 */
3989 		sfh = (nfs4_sharedfh_t *)objp->nfs_argop4_u.opcputfh.sfh;
3990 		mi = sfh->sfh_mi;
3991 		(void) nfs_rw_enter_sig(&mi->mi_fh_lock, RW_READER, 0);
3992 
3993 		len = sfh->sfh_fh.nfs_fh4_len;
3994 		ASSERT(len <= NFS4_FHSIZE);
3995 
3996 		/*
3997 		 * First try and inline the copy
3998 		 * Must first be a multiple of BYTES_PER_XDR_UNIT
3999 		 */
4000 		if (!(len % BYTES_PER_XDR_UNIT) &&
4001 		    (ptr = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT + len)) !=
4002 									NULL) {
4003 			IXDR_PUT_U_INT32(ptr, OP_PUTFH);
4004 			IXDR_PUT_U_INT32(ptr, len);
4005 			bcopy(sfh->sfh_fh.nfs_fh4_val, ptr, len);
4006 			nfs_rw_exit(&mi->mi_fh_lock);
4007 			return (TRUE);
4008 		}
4009 
4010 		op = OP_PUTFH;
4011 		if (!XDR_PUTINT32(xdrs, &op)) {
4012 			nfs_rw_exit(&mi->mi_fh_lock);
4013 			return (FALSE);
4014 		}
4015 		if (!XDR_PUTINT32(xdrs, &len)) {
4016 			nfs_rw_exit(&mi->mi_fh_lock);
4017 			return (FALSE);
4018 		}
4019 		if (!(len % BYTES_PER_XDR_UNIT)) {
4020 			if (XDR_PUTBYTES(xdrs, sfh->sfh_fh.nfs_fh4_val, len)) {
4021 				nfs_rw_exit(&mi->mi_fh_lock);
4022 				return (TRUE);
4023 			}
4024 		} else if (xdr_opaque(xdrs, sfh->sfh_fh.nfs_fh4_val, len)) {
4025 			nfs_rw_exit(&mi->mi_fh_lock);
4026 			return (TRUE);
4027 		}
4028 		nfs_rw_exit(&mi->mi_fh_lock);
4029 		return (FALSE);
4030 	case OP_CLOOKUP:
4031 		len = strlen(objp->nfs_argop4_u.opclookup.cname);
4032 		if (len > NFS4_MAX_UTF8STRING)
4033 			return (FALSE);
4034 		op = OP_LOOKUP;
4035 		if (XDR_PUTINT32(xdrs, &op)) {
4036 			if (XDR_PUTINT32(xdrs, &len)) {
4037 				return (xdr_opaque(xdrs,
4038 					objp->nfs_argop4_u.opclookup.cname,
4039 					len));
4040 			}
4041 		}
4042 		return (FALSE);
4043 	case OP_COPEN:
4044 		/* op processing inlined in xdr_OPEN4cargs */
4045 		return (xdr_OPEN4cargs(xdrs, &objp->nfs_argop4_u.opcopen));
4046 	case OP_CREMOVE:
4047 		len = strlen(objp->nfs_argop4_u.opcremove.ctarget);
4048 		if (len > NFS4_MAX_UTF8STRING)
4049 			return (FALSE);
4050 		op = OP_REMOVE;
4051 		if (XDR_PUTINT32(xdrs, &op)) {
4052 			if (XDR_PUTINT32(xdrs, &len)) {
4053 				return (xdr_opaque(xdrs,
4054 					objp->nfs_argop4_u.opcremove.ctarget,
4055 					len));
4056 			}
4057 		}
4058 		return (FALSE);
4059 	case OP_CCREATE:
4060 		op = OP_CREATE;
4061 		if (!XDR_PUTINT32(xdrs, &op))
4062 			return (FALSE);
4063 		return (xdr_CREATE4cargs(xdrs, &objp->nfs_argop4_u.opccreate));
4064 	case OP_CLINK:
4065 		len = strlen(objp->nfs_argop4_u.opclink.cnewname);
4066 		if (len > NFS4_MAX_UTF8STRING)
4067 			return (FALSE);
4068 		op = OP_LINK;
4069 		if (XDR_PUTINT32(xdrs, &op)) {
4070 			if (XDR_PUTINT32(xdrs, &len)) {
4071 				return (xdr_opaque(xdrs,
4072 					objp->nfs_argop4_u.opclink.cnewname,
4073 					len));
4074 			}
4075 		}
4076 		return (FALSE);
4077 	case OP_CRENAME:
4078 		len = strlen(objp->nfs_argop4_u.opcrename.coldname);
4079 		if (len > NFS4_MAX_UTF8STRING)
4080 			return (FALSE);
4081 		op = OP_RENAME;
4082 		if (!XDR_PUTINT32(xdrs, &op))
4083 			return (FALSE);
4084 		if (!XDR_PUTINT32(xdrs, &len))
4085 			return (FALSE);
4086 		if (!xdr_opaque(xdrs,
4087 				objp->nfs_argop4_u.opcrename.coldname, len))
4088 			return (FALSE);
4089 		len = strlen(objp->nfs_argop4_u.opcrename.cnewname);
4090 		if (len > NFS4_MAX_UTF8STRING)
4091 			return (FALSE);
4092 		if (XDR_PUTINT32(xdrs, &len)) {
4093 			return (xdr_opaque(xdrs,
4094 				objp->nfs_argop4_u.opcrename.cnewname, len));
4095 		}
4096 		return (FALSE);
4097 	case OP_CSECINFO:
4098 		len = strlen(objp->nfs_argop4_u.opcsecinfo.cname);
4099 		if (len > NFS4_MAX_UTF8STRING)
4100 			return (FALSE);
4101 		op = OP_SECINFO;
4102 		if (XDR_PUTINT32(xdrs, &op)) {
4103 			if (XDR_PUTINT32(xdrs, &len)) {
4104 				return (xdr_opaque(xdrs,
4105 					objp->nfs_argop4_u.opcsecinfo.cname,
4106 					len));
4107 			}
4108 		}
4109 		return (FALSE);
4110 	}
4111 	return (FALSE);
4112 }
4113 
4114 /*
4115  * Note that the len and decode_len will only be different in the case
4116  * of the client's use of this free function.  If the server is
4117  * freeing results, then the len/decode_len will always match.
4118  */
4119 static bool_t
4120 xdr_nfs_resop4_free(XDR *xdrs, nfs_resop4 **arrayp, int len, int decode_len)
4121 {
4122 	int i;
4123 	nfs_resop4 *array = *arrayp;
4124 
4125 	/*
4126 	 * Optimized XDR_FREE only results array
4127 	 */
4128 	ASSERT(xdrs->x_op == XDR_FREE);
4129 
4130 	if (array == NULL)
4131 		return (TRUE);
4132 
4133 	for (i = 0; i < decode_len; i++) {
4134 		/*
4135 		 * These should be ordered by frequency of use
4136 		 */
4137 		switch (array[i].resop) {
4138 		case OP_PUTFH:
4139 			continue;
4140 		case OP_GETATTR:
4141 			if (array[i].nfs_resop4_u.opgetattr.status != NFS4_OK)
4142 				continue;
4143 			if (array[i].nfs_resop4_u.opgetattr.ga_res.n4g_ext_res)
4144 				kmem_free(array[i].nfs_resop4_u.opgetattr.
4145 					ga_res.n4g_ext_res,
4146 					sizeof (struct nfs4_ga_ext_res));
4147 			continue;
4148 		case OP_GETFH:
4149 			if (array[i].nfs_resop4_u.opgetfh.status != NFS4_OK)
4150 				continue;
4151 			if (array[i].nfs_resop4_u.opgetfh.object.nfs_fh4_val !=
4152 							NULL) {
4153 				kmem_free(array[i].nfs_resop4_u.opgetfh.object.
4154 							nfs_fh4_val,
4155 					array[i].nfs_resop4_u.opgetfh.object.
4156 							nfs_fh4_len);
4157 			}
4158 			continue;
4159 		case OP_LOOKUP:
4160 			continue;
4161 		case OP_OPEN:
4162 			(void) xdr_OPEN4res(xdrs, &array[i].nfs_resop4_u.
4163 								opopen);
4164 			continue;
4165 		case OP_CLOSE:
4166 		case OP_ACCESS:
4167 			continue;
4168 		case OP_READ:
4169 			(void) xdr_READ4res(xdrs,
4170 					    &array[i].nfs_resop4_u.
4171 								opread);
4172 			continue;
4173 		case OP_WRITE:
4174 		case OP_DELEGRETURN:
4175 		case OP_LOOKUPP:
4176 		case OP_READDIR:
4177 		case OP_REMOVE:
4178 		case OP_COMMIT:
4179 		case OP_CREATE:
4180 		case OP_DELEGPURGE:
4181 		case OP_LINK:
4182 			continue;
4183 		case OP_LOCK:
4184 			(void) xdr_LOCK4res(xdrs, &array[i].nfs_resop4_u.
4185 								oplock);
4186 			continue;
4187 		case OP_LOCKT:
4188 			(void) xdr_LOCKT4res(xdrs, &array[i].nfs_resop4_u.
4189 								oplockt);
4190 			continue;
4191 		case OP_LOCKU:
4192 		case OP_NVERIFY:
4193 		case OP_OPENATTR:
4194 		case OP_OPEN_CONFIRM:
4195 		case OP_OPEN_DOWNGRADE:
4196 		case OP_PUTPUBFH:
4197 		case OP_PUTROOTFH:
4198 		case OP_RENAME:
4199 		case OP_RENEW:
4200 		case OP_RESTOREFH:
4201 		case OP_SAVEFH:
4202 			continue;
4203 		case OP_READLINK:
4204 			(void) xdr_READLINK4res(xdrs, &array[i].nfs_resop4_u.
4205 								opreadlink);
4206 			continue;
4207 		case OP_SECINFO:
4208 			(void) xdr_array(xdrs,
4209 				(char **)&array[i].nfs_resop4_u.opsecinfo.
4210 					SECINFO4resok_val,
4211 				(uint_t *)&array[i].nfs_resop4_u.opsecinfo.
4212 					SECINFO4resok_len,
4213 				NFS4_SECINFO_LIMIT, sizeof (secinfo4),
4214 				(xdrproc_t)xdr_secinfo4);
4215 			continue;
4216 		case OP_SETCLIENTID:
4217 			(void) xdr_SETCLIENTID4res(xdrs,
4218 					&array[i].nfs_resop4_u.opsetclientid);
4219 			continue;
4220 		case OP_SETATTR:
4221 		case OP_SETCLIENTID_CONFIRM:
4222 		case OP_VERIFY:
4223 		case OP_RELEASE_LOCKOWNER:
4224 		case OP_ILLEGAL:
4225 			continue;
4226 		default:
4227 			/*
4228 			 * An invalid op is a coding error, it should never
4229 			 * have been decoded.
4230 			 * Don't error because the caller cannot finish
4231 			 * freeing the residual memory of the array.
4232 			 */
4233 			continue;
4234 		}
4235 	}
4236 
4237 	kmem_free(*arrayp, len * sizeof (nfs_resop4));
4238 	*arrayp = NULL;
4239 	return (TRUE);
4240 }
4241 
4242 static bool_t
4243 xdr_snfs_resop4_free(XDR *xdrs, nfs_resop4 **arrayp, int len, int decode_len)
4244 {
4245 	return (xdr_nfs_resop4_free(xdrs, arrayp, len, decode_len));
4246 }
4247 
4248 static bool_t
4249 xdr_nfs_resop4(XDR *xdrs, nfs_resop4 *objp)
4250 {
4251 	/*
4252 	 * These should be ordered by frequency of use
4253 	 */
4254 	switch (objp->resop) {
4255 	case OP_PUTFH:
4256 		return (xdr_int(xdrs,
4257 				(int32_t *)&objp->nfs_resop4_u.opputfh.status));
4258 	case OP_GETATTR:
4259 		if (!xdr_int(xdrs,
4260 			    (int32_t *)&objp->nfs_resop4_u.opgetattr.status))
4261 			return (FALSE);
4262 		if (objp->nfs_resop4_u.opgetattr.status != NFS4_OK)
4263 			return (TRUE);
4264 		return (xdr_fattr4(xdrs,
4265 			    &objp->nfs_resop4_u.opgetattr.obj_attributes));
4266 	case OP_GETFH:
4267 		if (!xdr_int(xdrs,
4268 				(int32_t *)&objp->nfs_resop4_u.opgetfh.status))
4269 			return (FALSE);
4270 		if (objp->nfs_resop4_u.opgetfh.status != NFS4_OK)
4271 			return (TRUE);
4272 		return (xdr_bytes(xdrs,
4273 		    (char **)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_val,
4274 		    (uint_t *)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_len,
4275 		    NFS4_FHSIZE));
4276 	case OP_LOOKUP:
4277 		return (xdr_int(xdrs,
4278 			(int32_t *)&objp->nfs_resop4_u.oplookup.status));
4279 	case OP_OPEN:
4280 		return (xdr_OPEN4res(xdrs, &objp->nfs_resop4_u.opopen));
4281 	case OP_CLOSE:
4282 		return (xdr_CLOSE4res(xdrs, &objp->nfs_resop4_u.opclose));
4283 	case OP_ACCESS:
4284 		return (xdr_ACCESS4res(xdrs, &objp->nfs_resop4_u.opaccess));
4285 	case OP_READ:
4286 		return (xdr_READ4res(xdrs, &objp->nfs_resop4_u.opread));
4287 	case OP_WRITE:
4288 		return (xdr_WRITE4res(xdrs, &objp->nfs_resop4_u.opwrite));
4289 	case OP_DELEGRETURN:
4290 		return (xdr_int(xdrs,
4291 			(int32_t *)&objp->nfs_resop4_u.opdelegreturn.status));
4292 	case OP_LOOKUPP:
4293 		return (xdr_int(xdrs,
4294 			(int32_t *)&objp->nfs_resop4_u.oplookupp.status));
4295 	case OP_READDIR:
4296 		return (xdr_READDIR4res(xdrs, &objp->nfs_resop4_u.opreaddir));
4297 	case OP_REMOVE:
4298 		return (xdr_REMOVE4res(xdrs, &objp->nfs_resop4_u.opremove));
4299 
4300 	case OP_COMMIT:
4301 		if (!xdr_int(xdrs,
4302 			    (int32_t *)&objp->nfs_resop4_u.opcommit.status))
4303 			return (FALSE);
4304 		if (objp->nfs_resop4_u.opcommit.status != NFS4_OK)
4305 			return (TRUE);
4306 		return (xdr_u_longlong_t(xdrs,
4307 				(u_longlong_t *)&objp->nfs_resop4_u.opcommit.
4308 						writeverf));
4309 	case OP_CREATE:
4310 		return (xdr_CREATE4res(xdrs, &objp->nfs_resop4_u.opcreate));
4311 	case OP_DELEGPURGE:
4312 		return (xdr_int(xdrs,
4313 			(int32_t *)&objp->nfs_resop4_u.opdelegpurge.status));
4314 	case OP_LINK:
4315 		return (xdr_LINK4res(xdrs, &objp->nfs_resop4_u.oplink));
4316 	case OP_LOCK:
4317 		return (xdr_LOCK4res(xdrs, &objp->nfs_resop4_u.oplock));
4318 	case OP_LOCKT:
4319 		return (xdr_LOCKT4res(xdrs, &objp->nfs_resop4_u.oplockt));
4320 	case OP_LOCKU:
4321 		if (!xdr_int(xdrs,
4322 				(int32_t *)&objp->nfs_resop4_u.oplocku.status))
4323 			return (FALSE);
4324 		if (objp->nfs_resop4_u.oplocku.status != NFS4_OK)
4325 			return (TRUE);
4326 		if (!xdr_u_int(xdrs,
4327 		    &objp->nfs_resop4_u.oplocku.lock_stateid.seqid))
4328 			return (FALSE);
4329 		return (xdr_opaque(xdrs,
4330 		    objp->nfs_resop4_u.oplocku.lock_stateid.other,
4331 		    12));
4332 	case OP_NVERIFY:
4333 		return (xdr_int(xdrs,
4334 			(int32_t *)&objp->nfs_resop4_u.opnverify.status));
4335 	case OP_OPENATTR:
4336 		return (xdr_int(xdrs,
4337 			(int32_t *)&objp->nfs_resop4_u.opopenattr.status));
4338 	case OP_OPEN_CONFIRM:
4339 		return (xdr_OPEN_CONFIRM4res(xdrs,
4340 				&objp->nfs_resop4_u.opopen_confirm));
4341 	case OP_OPEN_DOWNGRADE:
4342 		return (xdr_OPEN_DOWNGRADE4res(xdrs,
4343 				&objp->nfs_resop4_u.opopen_downgrade));
4344 	case OP_PUTPUBFH:
4345 		return (xdr_int(xdrs,
4346 			(int32_t *)&objp->nfs_resop4_u.opputpubfh.status));
4347 	case OP_PUTROOTFH:
4348 		return (xdr_int(xdrs,
4349 			(int32_t *)&objp->nfs_resop4_u.opputrootfh.status));
4350 	case OP_READLINK:
4351 		return (xdr_READLINK4res(xdrs, &objp->nfs_resop4_u.opreadlink));
4352 	case OP_RENAME:
4353 		return (xdr_RENAME4res(xdrs, &objp->nfs_resop4_u.oprename));
4354 	case OP_RENEW:
4355 		return (xdr_int(xdrs,
4356 				(int32_t *)&objp->nfs_resop4_u.oprenew.status));
4357 	case OP_RESTOREFH:
4358 		return (xdr_int(xdrs,
4359 			(int32_t *)&objp->nfs_resop4_u.oprestorefh.status));
4360 	case OP_SAVEFH:
4361 		return (xdr_int(xdrs,
4362 			(int32_t *)&objp->nfs_resop4_u.opsavefh.status));
4363 	case OP_SECINFO:
4364 		if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsecinfo.
4365 					status))
4366 			return (FALSE);
4367 		if (objp->nfs_resop4_u.opsecinfo.status != NFS4_OK)
4368 			return (TRUE);
4369 		return (xdr_array(xdrs, (char **)&objp->nfs_resop4_u.opsecinfo.
4370 					SECINFO4resok_val,
4371 			(uint_t *)&objp->nfs_resop4_u.opsecinfo.
4372 					SECINFO4resok_len,
4373 			NFS4_SECINFO_LIMIT, sizeof (secinfo4),
4374 			(xdrproc_t)xdr_secinfo4));
4375 	case OP_SETATTR:
4376 		if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsetattr.
4377 						status))
4378 			return (FALSE);
4379 		return (xdr_bitmap4(xdrs,
4380 				&objp->nfs_resop4_u.opsetattr.attrsset));
4381 	case OP_SETCLIENTID:
4382 		return (xdr_SETCLIENTID4res(xdrs,
4383 				&objp->nfs_resop4_u.opsetclientid));
4384 	case OP_SETCLIENTID_CONFIRM:
4385 		return (xdr_int(xdrs,
4386 			(int32_t *)&objp->nfs_resop4_u.opsetclientid_confirm.
4387 					status));
4388 	case OP_VERIFY:
4389 		return (xdr_int(xdrs,
4390 			(int32_t *)&objp->nfs_resop4_u.opverify.status));
4391 	case OP_RELEASE_LOCKOWNER:
4392 		return (xdr_int(xdrs,
4393 		    (int32_t *)&objp->nfs_resop4_u.oprelease_lockowner.status));
4394 	case OP_ILLEGAL:
4395 		return (xdr_int(xdrs,
4396 			(int32_t *)&objp->nfs_resop4_u.opillegal.status));
4397 	}
4398 	return (FALSE);
4399 }
4400 
4401 static bool_t
4402 xdr_snfs_resop4(XDR *xdrs, nfs_resop4 *objp)
4403 {
4404 	if (!xdr_int(xdrs, (int *)&objp->resop))
4405 		return (FALSE);
4406 
4407 	switch (objp->resop) {
4408 	case OP_GETFH:
4409 		if (!XDR_PUTINT32(xdrs,
4410 		    (int32_t *)&objp->nfs_resop4_u.opgetfh.status))
4411 			return (FALSE);
4412 		if (objp->nfs_resop4_u.opgetfh.status != NFS4_OK)
4413 			return (TRUE);
4414 		return (xdr_encode_nfs_fh4(xdrs,
4415 		    &objp->nfs_resop4_u.opgetfh.object));
4416 	default:
4417 		return (xdr_nfs_resop4(xdrs, objp));
4418 	}
4419 }
4420 
4421 static bool_t
4422 xdr_nfs_resop4_clnt(XDR *xdrs, nfs_resop4 *objp, nfs_argop4 *aobjp)
4423 {
4424 	if (!xdr_int(xdrs, (int *)&objp->resop))
4425 		return (FALSE);
4426 	/*
4427 	 * These should be ordered by frequency of use
4428 	 */
4429 	switch (objp->resop) {
4430 	case OP_PUTFH:
4431 		return (xdr_int(xdrs,
4432 				(int32_t *)&objp->nfs_resop4_u.opputfh.status));
4433 	case OP_GETATTR:
4434 		if (!xdr_int(xdrs,
4435 			    (int32_t *)&objp->nfs_resop4_u.opgetattr.status))
4436 			return (FALSE);
4437 		if (objp->nfs_resop4_u.opgetattr.status != NFS4_OK)
4438 			return (TRUE);
4439 		return (xdr_ga_res(xdrs,
4440 				(GETATTR4res *)&objp->nfs_resop4_u.opgetattr,
4441 				&aobjp->nfs_argop4_u.opgetattr));
4442 	case OP_GETFH:
4443 		if (!xdr_int(xdrs,
4444 				(int32_t *)&objp->nfs_resop4_u.opgetfh.status))
4445 			return (FALSE);
4446 		if (objp->nfs_resop4_u.opgetfh.status != NFS4_OK)
4447 			return (TRUE);
4448 		return (xdr_bytes(xdrs,
4449 		    (char **)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_val,
4450 		    (uint_t *)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_len,
4451 		    NFS4_FHSIZE));
4452 	case OP_LOOKUP:
4453 		return (xdr_int(xdrs,
4454 			(int32_t *)&objp->nfs_resop4_u.oplookup.status));
4455 	case OP_NVERIFY:
4456 		return (xdr_int(xdrs,
4457 			(int32_t *)&objp->nfs_resop4_u.opnverify.status));
4458 	case OP_OPEN:
4459 		return (xdr_OPEN4res(xdrs, &objp->nfs_resop4_u.opopen));
4460 	case OP_CLOSE:
4461 		return (xdr_CLOSE4res(xdrs, &objp->nfs_resop4_u.opclose));
4462 	case OP_ACCESS:
4463 		return (xdr_ACCESS4res(xdrs, &objp->nfs_resop4_u.opaccess));
4464 	case OP_READ:
4465 		return (xdr_READ4res_clnt(xdrs, &objp->nfs_resop4_u.opread,
4466 					&aobjp->nfs_argop4_u.opread));
4467 	case OP_WRITE:
4468 		return (xdr_WRITE4res(xdrs, &objp->nfs_resop4_u.opwrite));
4469 	case OP_DELEGRETURN:
4470 		return (xdr_int(xdrs,
4471 			(int32_t *)&objp->nfs_resop4_u.opdelegreturn.status));
4472 	case OP_LOOKUPP:
4473 		return (xdr_int(xdrs,
4474 			(int32_t *)&objp->nfs_resop4_u.oplookupp.status));
4475 	case OP_READDIR:
4476 		return (xdr_READDIR4res_clnt(xdrs,
4477 				&objp->nfs_resop4_u.opreaddirclnt,
4478 				&aobjp->nfs_argop4_u.opreaddir));
4479 	case OP_REMOVE:
4480 		return (xdr_REMOVE4res(xdrs, &objp->nfs_resop4_u.opremove));
4481 
4482 	case OP_COMMIT:
4483 		if (!xdr_int(xdrs,
4484 			    (int32_t *)&objp->nfs_resop4_u.opcommit.status))
4485 			return (FALSE);
4486 		if (objp->nfs_resop4_u.opcommit.status != NFS4_OK)
4487 			return (TRUE);
4488 		return (xdr_u_longlong_t(xdrs,
4489 				(u_longlong_t *)&objp->nfs_resop4_u.opcommit.
4490 						writeverf));
4491 	case OP_CREATE:
4492 		return (xdr_CREATE4res(xdrs, &objp->nfs_resop4_u.opcreate));
4493 	case OP_DELEGPURGE:
4494 		return (xdr_int(xdrs,
4495 			(int32_t *)&objp->nfs_resop4_u.opdelegpurge.status));
4496 	case OP_LINK:
4497 		return (xdr_LINK4res(xdrs, &objp->nfs_resop4_u.oplink));
4498 	case OP_LOCK:
4499 		return (xdr_LOCK4res(xdrs, &objp->nfs_resop4_u.oplock));
4500 	case OP_LOCKT:
4501 		return (xdr_LOCKT4res(xdrs, &objp->nfs_resop4_u.oplockt));
4502 	case OP_LOCKU:
4503 		if (!xdr_int(xdrs,
4504 				(int32_t *)&objp->nfs_resop4_u.oplocku.status))
4505 			return (FALSE);
4506 		if (objp->nfs_resop4_u.oplocku.status != NFS4_OK)
4507 			return (TRUE);
4508 		if (!xdr_u_int(xdrs,
4509 		    &objp->nfs_resop4_u.oplocku.lock_stateid.seqid))
4510 			return (FALSE);
4511 		return (xdr_opaque(xdrs,
4512 		    objp->nfs_resop4_u.oplocku.lock_stateid.other,
4513 		    12));
4514 	case OP_OPENATTR:
4515 		return (xdr_int(xdrs,
4516 			(int32_t *)&objp->nfs_resop4_u.opopenattr.status));
4517 	case OP_OPEN_CONFIRM:
4518 		return (xdr_OPEN_CONFIRM4res(xdrs,
4519 				&objp->nfs_resop4_u.opopen_confirm));
4520 	case OP_OPEN_DOWNGRADE:
4521 		return (xdr_OPEN_DOWNGRADE4res(xdrs,
4522 				&objp->nfs_resop4_u.opopen_downgrade));
4523 	case OP_PUTPUBFH:
4524 		return (xdr_int(xdrs,
4525 			(int32_t *)&objp->nfs_resop4_u.opputpubfh.status));
4526 	case OP_PUTROOTFH:
4527 		return (xdr_int(xdrs,
4528 			(int32_t *)&objp->nfs_resop4_u.opputrootfh.status));
4529 	case OP_READLINK:
4530 		return (xdr_READLINK4res(xdrs, &objp->nfs_resop4_u.opreadlink));
4531 	case OP_RENAME:
4532 		return (xdr_RENAME4res(xdrs, &objp->nfs_resop4_u.oprename));
4533 	case OP_RENEW:
4534 		return (xdr_int(xdrs,
4535 				(int32_t *)&objp->nfs_resop4_u.oprenew.status));
4536 	case OP_RESTOREFH:
4537 		return (xdr_int(xdrs,
4538 			(int32_t *)&objp->nfs_resop4_u.oprestorefh.status));
4539 	case OP_SAVEFH:
4540 		return (xdr_int(xdrs,
4541 			(int32_t *)&objp->nfs_resop4_u.opsavefh.status));
4542 	case OP_SECINFO:
4543 		if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsecinfo.
4544 					status))
4545 			return (FALSE);
4546 		if (objp->nfs_resop4_u.opsecinfo.status != NFS4_OK)
4547 			return (TRUE);
4548 		return (xdr_array(xdrs, (char **)&objp->nfs_resop4_u.opsecinfo.
4549 					SECINFO4resok_val,
4550 			(uint_t *)&objp->nfs_resop4_u.opsecinfo.
4551 					SECINFO4resok_len,
4552 			~0, sizeof (secinfo4), (xdrproc_t)xdr_secinfo4));
4553 	case OP_SETATTR:
4554 		if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsetattr.
4555 						status))
4556 			return (FALSE);
4557 		return (xdr_bitmap4(xdrs,
4558 				&objp->nfs_resop4_u.opsetattr.attrsset));
4559 	case OP_SETCLIENTID:
4560 		return (xdr_SETCLIENTID4res(xdrs,
4561 				&objp->nfs_resop4_u.opsetclientid));
4562 	case OP_SETCLIENTID_CONFIRM:
4563 		return (xdr_int(xdrs,
4564 			(int32_t *)&objp->nfs_resop4_u.opsetclientid_confirm.
4565 					status));
4566 	case OP_VERIFY:
4567 		return (xdr_int(xdrs,
4568 			(int32_t *)&objp->nfs_resop4_u.opverify.status));
4569 	case OP_RELEASE_LOCKOWNER:
4570 		return (xdr_int(xdrs,
4571 		    (int32_t *)&objp->nfs_resop4_u.oprelease_lockowner.status));
4572 	case OP_ILLEGAL:
4573 		return (xdr_int(xdrs,
4574 			(int32_t *)&objp->nfs_resop4_u.opillegal.status));
4575 	}
4576 	return (FALSE);
4577 }
4578 
4579 bool_t
4580 xdr_COMPOUND4args_clnt(XDR *xdrs, COMPOUND4args_clnt *objp)
4581 {
4582 	static int32_t twelve = 12;
4583 	static int32_t minorversion = NFS4_MINORVERSION;
4584 	uint32_t *ctagp;
4585 	rpc_inline_t *ptr;
4586 
4587 	/*
4588 	 * XDR_ENCODE only
4589 	 */
4590 	if (xdrs->x_op == XDR_FREE)
4591 		return (TRUE);
4592 	if (xdrs->x_op == XDR_DECODE)
4593 		return (FALSE);
4594 
4595 	ctagp = (uint32_t *)&nfs4_ctags[objp->ctag].ct_tag;
4596 
4597 	if ((ptr = XDR_INLINE(xdrs, 5 * BYTES_PER_XDR_UNIT)) != NULL) {
4598 		/*
4599 		 * Efficiently encode fixed length tags, could be longlongs
4600 		 * but 8 byte XDR alignment not assured
4601 		 */
4602 		IXDR_PUT_U_INT32(ptr, 12);
4603 		IXDR_PUT_U_INT32(ptr, ctagp[0]);
4604 		IXDR_PUT_U_INT32(ptr, ctagp[1]);
4605 		IXDR_PUT_U_INT32(ptr, ctagp[2]);
4606 
4607 		/*
4608 		 * Fixed minor version for now
4609 		 */
4610 		IXDR_PUT_U_INT32(ptr, NFS4_MINORVERSION);
4611 	} else {
4612 		if (!XDR_PUTINT32(xdrs, &twelve))
4613 			return (FALSE);
4614 		if (!XDR_PUTINT32(xdrs, (int32_t *)&ctagp[0]))
4615 			return (FALSE);
4616 		if (!XDR_PUTINT32(xdrs, (int32_t *)&ctagp[1]))
4617 			return (FALSE);
4618 		if (!XDR_PUTINT32(xdrs, (int32_t *)&ctagp[2]))
4619 			return (FALSE);
4620 		if (!XDR_PUTINT32(xdrs, (int32_t *)&minorversion))
4621 			return (FALSE);
4622 	}
4623 
4624 	return (xdr_array(xdrs, (char **)&objp->array,
4625 			(uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
4626 			sizeof (nfs_argop4), (xdrproc_t)xdr_cnfs_argop4));
4627 }
4628 
4629 bool_t
4630 xdr_COMPOUND4args_srv(XDR *xdrs, COMPOUND4args *objp)
4631 {
4632 	if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val,
4633 			(uint_t *)&objp->tag.utf8string_len,
4634 			NFS4_MAX_UTF8STRING))
4635 		return (FALSE);
4636 	if (!xdr_u_int(xdrs, &objp->minorversion))
4637 		return (FALSE);
4638 	if (xdrs->x_op != XDR_FREE)
4639 		return (xdr_array(xdrs, (char **)&objp->array,
4640 			(uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
4641 			sizeof (nfs_argop4), (xdrproc_t)xdr_snfs_argop4));
4642 
4643 	return (xdr_snfs_argop4_free(xdrs, &objp->array, objp->array_len));
4644 }
4645 
4646 bool_t
4647 xdr_COMPOUND4res_clnt(XDR *xdrs, COMPOUND4res_clnt *objp)
4648 {
4649 	uint32_t len;
4650 	int32_t *ptr;
4651 	nfs_argop4 *argop;
4652 	nfs_resop4 *resop;
4653 
4654 	/*
4655 	 * No XDR_ENCODE
4656 	 */
4657 	if (xdrs->x_op == XDR_ENCODE)
4658 		return (FALSE);
4659 
4660 	if (xdrs->x_op != XDR_FREE) {
4661 		if ((ptr = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT)) != NULL) {
4662 			objp->status = IXDR_GET_U_INT32(ptr);
4663 			len = IXDR_GET_U_INT32(ptr);
4664 		} else {
4665 			if (!xdr_int(xdrs, (int32_t *)&objp->status))
4666 				return (FALSE);
4667 			if (!xdr_u_int(xdrs, (uint32_t *)&len))
4668 				return (FALSE);
4669 		}
4670 		if (len > NFS4_MAX_UTF8STRING)
4671 			return (FALSE);
4672 		/*
4673 		 * Ignore the tag
4674 		 */
4675 		if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &len))
4676 			return (FALSE);
4677 
4678 		if (!xdr_int(xdrs, (int32_t *)&objp->array_len))
4679 			return (FALSE);
4680 
4681 		if (objp->array_len > objp->argsp->array_len)
4682 			return (FALSE);
4683 
4684 		if (objp->status == NFS_OK &&
4685 		    objp->array_len != objp->argsp->array_len)
4686 			return (FALSE);
4687 
4688 		/* Alloc the results array */
4689 		argop = objp->argsp->array;
4690 		len = objp->array_len * sizeof (nfs_resop4);
4691 		objp->decode_len = 0;
4692 		objp->array = resop = kmem_zalloc(len, KM_SLEEP);
4693 
4694 		for (len = 0; len < objp->array_len;
4695 			len++, resop++, argop++, objp->decode_len++) {
4696 			if (!xdr_nfs_resop4_clnt(xdrs, resop, argop)) {
4697 				/*
4698 				 * Make sure to free anything that may
4699 				 * have been allocated along the way.
4700 				 */
4701 				xdrs->x_op = XDR_FREE;
4702 				(void) xdr_nfs_resop4_free(xdrs, &objp->array,
4703 							    objp->array_len,
4704 							    objp->decode_len);
4705 				return (FALSE);
4706 			}
4707 		}
4708 		return (TRUE);
4709 	}
4710 	return (xdr_nfs_resop4_free(xdrs, &objp->array,
4711 				    objp->array_len, objp->decode_len));
4712 }
4713 
4714 bool_t
4715 xdr_COMPOUND4res_srv(XDR *xdrs, COMPOUND4res *objp)
4716 {
4717 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
4718 		return (FALSE);
4719 	if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val,
4720 			(uint_t *)&objp->tag.utf8string_len,
4721 			NFS4_MAX_UTF8STRING))
4722 		return (FALSE);
4723 
4724 	if (xdrs->x_op != XDR_FREE)
4725 		return (xdr_array(xdrs, (char **)&objp->array,
4726 			(uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
4727 			sizeof (nfs_resop4), (xdrproc_t)xdr_snfs_resop4));
4728 
4729 	return (xdr_snfs_resop4_free(xdrs, &objp->array,
4730 				    objp->array_len, objp->array_len));
4731 }
4732 
4733 /*
4734  * NFS server side callback, initiating the callback request so it
4735  * is the RPC client. Must convert from server's internal filehandle
4736  * format to wire format.
4737  */
4738 static bool_t
4739 xdr_snfs_cb_argop4(XDR *xdrs, nfs_cb_argop4 *objp)
4740 {
4741 	CB_GETATTR4args *gargs;
4742 	CB_RECALL4args *rargs;
4743 
4744 	ASSERT(xdrs->x_op == XDR_ENCODE);
4745 
4746 	if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->argop))
4747 		return (FALSE);
4748 
4749 	switch (objp->argop) {
4750 	case OP_CB_GETATTR:
4751 		gargs = &objp->nfs_cb_argop4_u.opcbgetattr;
4752 
4753 		if (!xdr_encode_nfs_fh4(xdrs, &gargs->fh))
4754 			return (FALSE);
4755 		return (xdr_bitmap4(xdrs, &gargs->attr_request));
4756 	case OP_CB_RECALL:
4757 		rargs = &objp->nfs_cb_argop4_u.opcbrecall;
4758 
4759 		if (!XDR_PUTINT32(xdrs, (int32_t *)&rargs->stateid.seqid))
4760 			return (FALSE);
4761 		if (!xdr_opaque(xdrs, rargs->stateid.other, 12))
4762 			return (FALSE);
4763 		if (!XDR_PUTINT32(xdrs, (int32_t *)&rargs->truncate))
4764 			return (FALSE);
4765 		return (xdr_encode_nfs_fh4(xdrs, &rargs->fh));
4766 	case OP_CB_ILLEGAL:
4767 		return (TRUE);
4768 	}
4769 	return (FALSE);
4770 }
4771 
4772 /*
4773  * NFS client side callback, receiving the callback request so it
4774  * is the RPC server. Must treat the file handles as opaque.
4775  */
4776 static bool_t
4777 xdr_cnfs_cb_argop4(XDR *xdrs, nfs_cb_argop4 *objp)
4778 {
4779 	CB_GETATTR4args *gargs;
4780 	CB_RECALL4args *rargs;
4781 
4782 	ASSERT(xdrs->x_op != XDR_ENCODE);
4783 
4784 	if (!xdr_u_int(xdrs, &objp->argop))
4785 		return (FALSE);
4786 	switch (objp->argop) {
4787 	case OP_CB_GETATTR:
4788 		gargs = &objp->nfs_cb_argop4_u.opcbgetattr;
4789 
4790 		if (!xdr_bytes(xdrs, (char **)&gargs->fh.nfs_fh4_val,
4791 		    (uint_t *)&gargs->fh.nfs_fh4_len, NFS4_FHSIZE))
4792 			return (FALSE);
4793 		return (xdr_bitmap4(xdrs, &gargs->attr_request));
4794 	case OP_CB_RECALL:
4795 		rargs = &objp->nfs_cb_argop4_u.opcbrecall;
4796 
4797 		if (!xdr_u_int(xdrs, &rargs->stateid.seqid))
4798 			return (FALSE);
4799 		if (!xdr_opaque(xdrs, rargs->stateid.other, 12))
4800 			return (FALSE);
4801 		if (!xdr_bool(xdrs, &rargs->truncate))
4802 			return (FALSE);
4803 		return (xdr_bytes(xdrs, (char **)&rargs->fh.nfs_fh4_val,
4804 		    (uint_t *)&rargs->fh.nfs_fh4_len, NFS4_FHSIZE));
4805 	case OP_CB_ILLEGAL:
4806 		return (TRUE);
4807 	}
4808 	return (FALSE);
4809 }
4810 
4811 static bool_t
4812 xdr_nfs_cb_resop4(XDR *xdrs, nfs_cb_resop4 *objp)
4813 {
4814 	if (!xdr_u_int(xdrs, &objp->resop))
4815 		return (FALSE);
4816 	switch (objp->resop) {
4817 	case OP_CB_GETATTR:
4818 		if (!xdr_int(xdrs,
4819 				(int32_t *)&objp->nfs_cb_resop4_u.opcbgetattr.
4820 				    status))
4821 			return (FALSE);
4822 		if (objp->nfs_cb_resop4_u.opcbgetattr.status != NFS4_OK)
4823 			return (TRUE);
4824 		return (xdr_fattr4(xdrs,
4825 				&objp->nfs_cb_resop4_u.opcbgetattr.
4826 				    obj_attributes));
4827 	case OP_CB_RECALL:
4828 		return (xdr_int(xdrs,
4829 			(int32_t *)&objp->nfs_cb_resop4_u.opcbrecall.status));
4830 	case OP_CB_ILLEGAL:
4831 		return (xdr_int(xdrs,
4832 			(int32_t *)&objp->nfs_cb_resop4_u.opcbillegal.status));
4833 	}
4834 	return (FALSE);
4835 }
4836 
4837 /*
4838  * The NFS client side callback, RPC server
4839  */
4840 bool_t
4841 xdr_CB_COMPOUND4args_clnt(XDR *xdrs, CB_COMPOUND4args *objp)
4842 {
4843 	if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val,
4844 			(uint_t *)&objp->tag.utf8string_len,
4845 			NFS4_MAX_UTF8STRING))
4846 		return (FALSE);
4847 	if (!xdr_u_int(xdrs, &objp->minorversion))
4848 		return (FALSE);
4849 	if (!xdr_u_int(xdrs, &objp->callback_ident))
4850 		return (FALSE);
4851 	return (xdr_array(xdrs, (char **)&objp->array,
4852 			(uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
4853 			sizeof (nfs_cb_argop4), (xdrproc_t)xdr_cnfs_cb_argop4));
4854 }
4855 
4856 /*
4857  * The NFS server side callback, RPC client
4858  */
4859 bool_t
4860 xdr_CB_COMPOUND4args_srv(XDR *xdrs, CB_COMPOUND4args *objp)
4861 {
4862 	if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val,
4863 			(uint_t *)&objp->tag.utf8string_len,
4864 			NFS4_MAX_UTF8STRING))
4865 		return (FALSE);
4866 	if (!xdr_u_int(xdrs, &objp->minorversion))
4867 		return (FALSE);
4868 	if (!xdr_u_int(xdrs, &objp->callback_ident))
4869 		return (FALSE);
4870 	return (xdr_array(xdrs, (char **)&objp->array,
4871 			(uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
4872 			sizeof (nfs_cb_argop4), (xdrproc_t)xdr_snfs_cb_argop4));
4873 }
4874 
4875 bool_t
4876 xdr_CB_COMPOUND4res(XDR *xdrs, CB_COMPOUND4res *objp)
4877 {
4878 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
4879 		return (FALSE);
4880 	if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val,
4881 			(uint_t *)&objp->tag.utf8string_len,
4882 			NFS4_MAX_UTF8STRING))
4883 		return (FALSE);
4884 	return (xdr_array(xdrs, (char **)&objp->array,
4885 			(uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
4886 			sizeof (nfs_cb_resop4), (xdrproc_t)xdr_nfs_cb_resop4));
4887 }
4888