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