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