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