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