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