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