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