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