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