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