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