xref: /illumos-gate/usr/src/uts/common/fs/nfs/nfs4_xdr.c (revision 453b03d5)
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 	switch (xdrs->x_op) {
2964 	case XDR_DECODE:
2965 		if (!xdr_u_int(xdrs, &w))
2966 			break;
2967 
2968 		*share_access = w & OPEN4_SHARE_ACCESS_MASK;
2969 		*deleg_want = w & OPEN4_SHARE_WANT_MASK;
2970 		return (TRUE);
2971 
2972 	case XDR_ENCODE:
2973 		return (xdr_u_int(xdrs, share_access));
2974 
2975 	case XDR_FREE:
2976 		return (TRUE);
2977 	}
2978 
2979 	return (FALSE);
2980 }
2981 
2982 static bool_t
xdr_OPEN4args(XDR * xdrs,OPEN4args * objp)2983 xdr_OPEN4args(XDR *xdrs, OPEN4args *objp)
2984 {
2985 	if (xdrs->x_op != XDR_FREE) {
2986 		if (!xdr_u_int(xdrs, &objp->seqid))
2987 			return (FALSE);
2988 		if (!xdr_share_access(xdrs, &objp->share_access,
2989 		    &objp->deleg_want))
2990 			return (FALSE);
2991 		if (!xdr_u_int(xdrs, &objp->share_deny))
2992 			return (FALSE);
2993 
2994 		/* xdr_open_owner4 */
2995 		if (!xdr_u_longlong_t(xdrs,
2996 		    (u_longlong_t *)&objp->owner.clientid))
2997 			return (FALSE);
2998 		if (!xdr_bytes(xdrs, (char **)&objp->owner.owner_val,
2999 		    (uint_t *)&objp->owner.owner_len,
3000 		    NFS4_OPAQUE_LIMIT))
3001 			return (FALSE);
3002 
3003 		/* xdr_openflag4 */
3004 		if (!xdr_int(xdrs, (int *)&objp->opentype))
3005 			return (FALSE);
3006 		if (objp->opentype == OPEN4_CREATE) {
3007 
3008 			/* xdr_createhow4 */
3009 			if (!xdr_int(xdrs, (int *)&objp->mode))
3010 				return (FALSE);
3011 			switch (objp->mode) {
3012 			case UNCHECKED4:
3013 			case GUARDED4:
3014 				if (!xdr_fattr4(xdrs,
3015 				    &objp->createhow4_u.createattrs))
3016 					return (FALSE);
3017 				break;
3018 			case EXCLUSIVE4:
3019 				if (!xdr_u_longlong_t(xdrs,
3020 				    (u_longlong_t *)&objp->createhow4_u.
3021 				    createverf))
3022 					return (FALSE);
3023 				break;
3024 			case EXCLUSIVE4_1:
3025 				if (!xdr_creatverfattr(xdrs,
3026 				    &objp->createhow4_u.ch_createboth))
3027 					return (FALSE);
3028 				break;
3029 			default:
3030 				return (FALSE);
3031 			}
3032 		}
3033 
3034 		/* xdr_open_claim4 */
3035 		if (!xdr_open_claim4(xdrs, &objp->claim))
3036 			return (FALSE);
3037 
3038 		return (TRUE);
3039 	}
3040 
3041 	/*
3042 	 * Optimized free case
3043 	 */
3044 	if (objp->owner.owner_val != NULL)
3045 		kmem_free(objp->owner.owner_val, objp->owner.owner_len);
3046 
3047 	if (objp->opentype == OPEN4_CREATE) {
3048 		switch (objp->mode) {
3049 		case UNCHECKED4:
3050 		case GUARDED4:
3051 			(void) xdr_fattr4(xdrs,
3052 			    &objp->createhow4_u.createattrs);
3053 			break;
3054 		case EXCLUSIVE4:
3055 		default:
3056 			break;
3057 		}
3058 	}
3059 
3060 	(void) xdr_open_claim4(xdrs, &objp->claim);
3061 	return (TRUE);
3062 }
3063 
3064 static bool_t
xdr_OPEN4cargs(XDR * xdrs,OPEN4cargs * objp)3065 xdr_OPEN4cargs(XDR *xdrs, OPEN4cargs *objp)
3066 {
3067 	int op;
3068 	int len;
3069 	rpc_inline_t *ptr;
3070 
3071 	ASSERT(xdrs->x_op == XDR_ENCODE);
3072 
3073 	/*
3074 	 * We must always define the client's open_owner to be
3075 	 * 4 byte aligned and sized.
3076 	 */
3077 	ASSERT(objp->owner.owner_len <= NFS4_OPAQUE_LIMIT);
3078 	ASSERT(!(objp->owner.owner_len % BYTES_PER_XDR_UNIT));
3079 
3080 	len = objp->owner.owner_len;
3081 	if ((ptr = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT + len)) != NULL) {
3082 		int i;
3083 		int32_t *ip;
3084 
3085 		IXDR_PUT_U_INT32(ptr, OP_OPEN);
3086 		IXDR_PUT_U_INT32(ptr, objp->seqid);
3087 		IXDR_PUT_U_INT32(ptr, objp->share_access);
3088 		IXDR_PUT_U_INT32(ptr, objp->share_deny);
3089 
3090 		/* xdr_open_owner4 */
3091 		IXDR_PUT_HYPER(ptr, objp->owner.clientid);
3092 		IXDR_PUT_U_INT32(ptr, objp->owner.owner_len);
3093 		/* We know this is very short so don't bcopy */
3094 		ip = (int32_t *)objp->owner.owner_val;
3095 		len /= BYTES_PER_XDR_UNIT;
3096 		for (i = 0; i < len; i++)
3097 			*ptr++ = *ip++;
3098 
3099 		/* xdr_openflag4 */
3100 		IXDR_PUT_U_INT32(ptr, objp->opentype);
3101 	} else {
3102 		op = OP_OPEN;
3103 		if (!XDR_PUTINT32(xdrs, (int32_t *)&op))
3104 			return (FALSE);
3105 		if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->seqid))
3106 			return (FALSE);
3107 		if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->share_access))
3108 			return (FALSE);
3109 		if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->share_deny))
3110 			return (FALSE);
3111 
3112 		/* xdr_open_owner4 */
3113 		if (!xdr_u_longlong_t(xdrs,
3114 		    (u_longlong_t *)&objp->owner.clientid))
3115 			return (FALSE);
3116 		if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->owner.owner_len))
3117 			return (FALSE);
3118 		if (!xdr_opaque(xdrs, objp->owner.owner_val,
3119 		    objp->owner.owner_len))
3120 			return (FALSE);
3121 
3122 		/* xdr_openflag4 */
3123 		if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->opentype))
3124 			return (FALSE);
3125 	}
3126 
3127 	if (objp->opentype == OPEN4_CREATE) {
3128 		/* xdr_createhow4 */
3129 		if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->mode))
3130 			return (FALSE);
3131 		switch (objp->mode) {
3132 		case UNCHECKED4:
3133 		case GUARDED4:
3134 			if (!xdr_fattr4(xdrs,
3135 			    &objp->createhow4_u.createattrs))
3136 				return (FALSE);
3137 			break;
3138 		case EXCLUSIVE4:
3139 			if (!xdr_u_longlong_t(xdrs,
3140 			    (u_longlong_t *)&objp->createhow4_u.
3141 			    createverf))
3142 				return (FALSE);
3143 			break;
3144 		default:
3145 			return (FALSE);
3146 		}
3147 	}
3148 
3149 	/* xdr_open_claim4 */
3150 	if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->claim))
3151 		return (FALSE);
3152 
3153 	switch (objp->claim) {
3154 	case CLAIM_NULL:
3155 		len = strlen(objp->open_claim4_u.cfile);
3156 		if (len > NFS4_MAX_UTF8STRING)
3157 			return (FALSE);
3158 		if (XDR_PUTINT32(xdrs, &len)) {
3159 			return (xdr_opaque(xdrs,
3160 			    objp->open_claim4_u.cfile, len));
3161 		}
3162 		return (FALSE);
3163 	case CLAIM_PREVIOUS:
3164 		return (XDR_PUTINT32(xdrs,
3165 		    (int32_t *)&objp->open_claim4_u.delegate_type));
3166 	case CLAIM_DELEGATE_CUR:
3167 		if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->open_claim4_u.
3168 		    delegate_cur_info.delegate_stateid.seqid))
3169 			return (FALSE);
3170 		if (!xdr_opaque(xdrs, objp->open_claim4_u.
3171 		    delegate_cur_info.delegate_stateid.other,
3172 		    NFS4_OTHER_SIZE))
3173 			return (FALSE);
3174 		len = strlen(objp->open_claim4_u.delegate_cur_info.cfile);
3175 		if (len > NFS4_MAX_UTF8STRING)
3176 			return (FALSE);
3177 		if (XDR_PUTINT32(xdrs, &len)) {
3178 			return (xdr_opaque(xdrs,
3179 			    objp->open_claim4_u.delegate_cur_info.cfile,
3180 			    len));
3181 		}
3182 		return (FALSE);
3183 	case CLAIM_DELEGATE_PREV:
3184 		len = strlen(objp->open_claim4_u.cfile_delegate_prev);
3185 		if (len > NFS4_MAX_UTF8STRING)
3186 			return (FALSE);
3187 		if (XDR_PUTINT32(xdrs, &len)) {
3188 			return (xdr_opaque(xdrs,
3189 			    objp->open_claim4_u.cfile_delegate_prev, len));
3190 		}
3191 		return (FALSE);
3192 	default:
3193 		return (FALSE);
3194 	}
3195 }
3196 
3197 static bool_t
xdr_OPEN4res(XDR * xdrs,OPEN4res * objp)3198 xdr_OPEN4res(XDR *xdrs, OPEN4res *objp)
3199 {
3200 	if (xdrs->x_op != XDR_FREE) {
3201 		if (!xdr_int(xdrs, (int32_t *)&objp->status))
3202 			return (FALSE);
3203 		if (objp->status != NFS4_OK)
3204 			return (TRUE);
3205 		if (!xdr_u_int(xdrs, &objp->stateid.seqid))
3206 			return (FALSE);
3207 		if (!xdr_opaque(xdrs, objp->stateid.other, NFS4_OTHER_SIZE))
3208 			return (FALSE);
3209 		if (!xdr_bool(xdrs, &objp->cinfo.atomic))
3210 			return (FALSE);
3211 		if (!xdr_u_longlong_t(xdrs,
3212 		    (u_longlong_t *)&objp->cinfo.before))
3213 			return (FALSE);
3214 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.after))
3215 			return (FALSE);
3216 		if (!xdr_u_int(xdrs, &objp->rflags))
3217 			return (FALSE);
3218 		if (!xdr_bitmap4(xdrs, &objp->attrset))
3219 			return (FALSE);
3220 		if (!xdr_int(xdrs,
3221 		    (int *)&objp->delegation.delegation_type))
3222 			return (FALSE);
3223 		switch (objp->delegation.delegation_type) {
3224 		case OPEN_DELEGATE_NONE:
3225 			return (TRUE);
3226 		case OPEN_DELEGATE_READ:
3227 			if (!xdr_u_int(xdrs, &objp->delegation.
3228 			    open_delegation4_u.read.stateid.seqid))
3229 				return (FALSE);
3230 			if (!xdr_opaque(xdrs, objp->delegation.
3231 			    open_delegation4_u.read.stateid.other,
3232 			    NFS4_OTHER_SIZE))
3233 				return (FALSE);
3234 			if (!xdr_bool(xdrs, &objp->delegation.
3235 			    open_delegation4_u.read.recall))
3236 				return (FALSE);
3237 			return (xdr_nfsace4(xdrs, &objp->delegation.
3238 			    open_delegation4_u.read.permissions));
3239 		case OPEN_DELEGATE_WRITE:
3240 			if (!xdr_u_int(xdrs, &objp->delegation.
3241 			    open_delegation4_u.write.stateid.seqid))
3242 				return (FALSE);
3243 			if (!xdr_opaque(xdrs, objp->delegation.
3244 			    open_delegation4_u.write.stateid.other,
3245 			    NFS4_OTHER_SIZE))
3246 				return (FALSE);
3247 			if (!xdr_bool(xdrs, &objp->delegation.
3248 			    open_delegation4_u.write.recall))
3249 				return (FALSE);
3250 			if (!xdr_int(xdrs, (int *)&objp->delegation.
3251 			    open_delegation4_u.write.space_limit.
3252 			    limitby))
3253 				return (FALSE);
3254 			switch (objp->delegation.
3255 			    open_delegation4_u.write.space_limit.
3256 			    limitby) {
3257 			case NFS_LIMIT_SIZE:
3258 				if (!xdr_u_longlong_t(xdrs,
3259 				    (u_longlong_t *)&objp->delegation.
3260 				    open_delegation4_u.write.space_limit.
3261 				    nfs_space_limit4_u.filesize))
3262 					return (FALSE);
3263 				break;
3264 			case NFS_LIMIT_BLOCKS:
3265 				if (!xdr_u_int(xdrs,
3266 				    &objp->delegation.open_delegation4_u.write.
3267 				    space_limit.nfs_space_limit4_u.
3268 				    mod_blocks.num_blocks))
3269 					return (FALSE);
3270 				if (!xdr_u_int(xdrs, &objp->delegation.
3271 				    open_delegation4_u.write.space_limit.
3272 				    nfs_space_limit4_u.mod_blocks.
3273 				    bytes_per_block))
3274 					return (FALSE);
3275 				break;
3276 			default:
3277 				return (FALSE);
3278 			}
3279 			return (xdr_nfsace4(xdrs, &objp->delegation.
3280 			    open_delegation4_u.write.permissions));
3281 		}
3282 		return (FALSE);
3283 	}
3284 
3285 	/*
3286 	 * Optimized free case
3287 	 */
3288 	if (objp->status != NFS4_OK)
3289 		return (TRUE);
3290 
3291 	switch (objp->delegation.delegation_type) {
3292 	case OPEN_DELEGATE_NONE:
3293 		return (TRUE);
3294 	case OPEN_DELEGATE_READ:
3295 		return (xdr_nfsace4(xdrs, &objp->delegation.
3296 		    open_delegation4_u.read.permissions));
3297 	case OPEN_DELEGATE_WRITE:
3298 		switch (objp->delegation.
3299 		    open_delegation4_u.write.space_limit.limitby) {
3300 		case NFS_LIMIT_SIZE:
3301 		case NFS_LIMIT_BLOCKS:
3302 			break;
3303 		default:
3304 			return (FALSE);
3305 		}
3306 		return (xdr_nfsace4(xdrs, &objp->delegation.
3307 		    open_delegation4_u.write.permissions));
3308 	}
3309 	return (FALSE);
3310 }
3311 
3312 static bool_t
xdr_OPEN_CONFIRM4res(XDR * xdrs,OPEN_CONFIRM4res * objp)3313 xdr_OPEN_CONFIRM4res(XDR *xdrs, OPEN_CONFIRM4res *objp)
3314 {
3315 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
3316 		return (FALSE);
3317 	if (objp->status != NFS4_OK)
3318 		return (TRUE);
3319 	if (!xdr_u_int(xdrs, &objp->open_stateid.seqid))
3320 		return (FALSE);
3321 	return (xdr_opaque(xdrs, objp->open_stateid.other, NFS4_OTHER_SIZE));
3322 }
3323 
3324 static bool_t
xdr_OPEN_DOWNGRADE4args(XDR * xdrs,OPEN_DOWNGRADE4args * objp)3325 xdr_OPEN_DOWNGRADE4args(XDR *xdrs, OPEN_DOWNGRADE4args *objp)
3326 {
3327 	if (!xdr_u_int(xdrs, &objp->open_stateid.seqid))
3328 		return (FALSE);
3329 	if (!xdr_opaque(xdrs, objp->open_stateid.other, NFS4_OTHER_SIZE))
3330 		return (FALSE);
3331 	if (!xdr_u_int(xdrs, &objp->seqid))
3332 		return (FALSE);
3333 	if (!xdr_share_access(xdrs, &objp->share_access, &objp->deleg_want))
3334 		return (FALSE);
3335 	return (xdr_u_int(xdrs, &objp->share_deny));
3336 }
3337 
3338 static bool_t
xdr_OPEN_DOWNGRADE4res(XDR * xdrs,OPEN_DOWNGRADE4res * objp)3339 xdr_OPEN_DOWNGRADE4res(XDR *xdrs, OPEN_DOWNGRADE4res *objp)
3340 {
3341 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
3342 		return (FALSE);
3343 	if (objp->status != NFS4_OK)
3344 		return (TRUE);
3345 	if (!xdr_u_int(xdrs, &objp->open_stateid.seqid))
3346 		return (FALSE);
3347 	return (xdr_opaque(xdrs, objp->open_stateid.other, NFS4_OTHER_SIZE));
3348 }
3349 
3350 static bool_t
xdr_READ4args(XDR * xdrs,READ4args * objp)3351 xdr_READ4args(XDR *xdrs, READ4args *objp)
3352 {
3353 	rdma_chunkinfo_t rci;
3354 	rdma_wlist_conn_info_t rwci;
3355 	struct xdr_ops *xops = xdrrdma_xops();
3356 
3357 	if (!xdr_u_int(xdrs, &objp->stateid.seqid))
3358 		return (FALSE);
3359 	if (!xdr_opaque(xdrs, objp->stateid.other, NFS4_OTHER_SIZE))
3360 		return (FALSE);
3361 	if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset))
3362 		return (FALSE);
3363 	if (!xdr_u_int(xdrs, &objp->count))
3364 		return (FALSE);
3365 
3366 	DTRACE_PROBE1(xdr__i__read4args_buf_len,
3367 	    int, objp->count);
3368 
3369 	objp->wlist = NULL;
3370 
3371 	if (xdrs->x_ops == xops && xdrs->x_op == XDR_ENCODE) {
3372 		rci.rci_type = RCI_WRITE_ADDR_CHUNK;
3373 		rci.rci_len = objp->count;
3374 		(void) XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
3375 	}
3376 
3377 	if (xdrs->x_ops != &xdrrdma_ops || xdrs->x_op == XDR_FREE)
3378 		return (TRUE);
3379 
3380 	if (xdrs->x_op == XDR_ENCODE) {
3381 		if (objp->res_uiop != NULL) {
3382 			rci.rci_type = RCI_WRITE_UIO_CHUNK;
3383 			rci.rci_a.rci_uiop = objp->res_uiop;
3384 			rci.rci_len = objp->count;
3385 			rci.rci_clpp = &objp->wlist;
3386 		} else {
3387 			rci.rci_type = RCI_WRITE_ADDR_CHUNK;
3388 			rci.rci_a.rci_addr = objp->res_data_val_alt;
3389 			rci.rci_len = objp->count;
3390 			rci.rci_clpp = &objp->wlist;
3391 		}
3392 
3393 		return (XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci));
3394 	}
3395 
3396 	/* XDR_DECODE case */
3397 	(void) XDR_CONTROL(xdrs, XDR_RDMA_GET_WCINFO, &rwci);
3398 	objp->wlist = rwci.rwci_wlist;
3399 	objp->conn = rwci.rwci_conn;
3400 
3401 	return (TRUE);
3402 }
3403 
3404 static bool_t
xdr_READ4res(XDR * xdrs,READ4res * objp)3405 xdr_READ4res(XDR *xdrs, READ4res *objp)
3406 {
3407 	mblk_t *mp;
3408 
3409 	if (xdrs->x_op == XDR_DECODE)
3410 		return (FALSE);
3411 
3412 	if (xdrs->x_op == XDR_FREE) {
3413 		/*
3414 		 * Optimized free case
3415 		 */
3416 		if (objp->status != NFS4_OK)
3417 			return (TRUE);
3418 		if (objp->data_val != NULL)
3419 			kmem_free(objp->data_val, objp->data_len);
3420 		return (TRUE);
3421 	}
3422 
3423 	/* on with ENCODE paths */
3424 	if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->status))
3425 		return (FALSE);
3426 	if (objp->status != NFS4_OK)
3427 		return (TRUE);
3428 
3429 	if (!XDR_PUTINT32(xdrs, &objp->eof))
3430 		return (FALSE);
3431 
3432 	mp = objp->mblk;
3433 	if (mp != NULL) {
3434 		if (xdrs->x_ops == &xdrmblk_ops) {
3435 			if (xdrmblk_putmblk(xdrs, mp, objp->data_len)) {
3436 				objp->mblk = NULL;
3437 				return (TRUE);
3438 			} else {
3439 				return (FALSE);
3440 			}
3441 		} else if (mp->b_cont != NULL) {
3442 			/*
3443 			 * See xdr_READ3res() for an explanation of why we need
3444 			 * to do a pullup here.
3445 			 */
3446 			if (pullupmsg(mp, -1) == 0)
3447 				return (FALSE);
3448 			objp->data_val = (caddr_t)mp->b_rptr;
3449 		}
3450 	} else {
3451 		if (xdr_u_int(xdrs, &objp->data_len) == FALSE) {
3452 			return (FALSE);
3453 		}
3454 		/*
3455 		 * If read data sent by wlist (RDMA_WRITE), don't do
3456 		 * xdr_bytes() below.   RDMA_WRITE transfers the data.
3457 		 * Note: this is encode-only because the client code
3458 		 * uses xdr_READ4res_clnt to decode results.
3459 		 */
3460 		if (objp->wlist) {
3461 			if (objp->data_len != 0) {
3462 				return (xdrrdma_send_read_data(
3463 				    xdrs, objp->data_len, objp->wlist));
3464 			}
3465 			return (TRUE);
3466 		}
3467 	}
3468 
3469 	return (xdr_bytes(xdrs, (char **)&objp->data_val,
3470 	    (uint_t *)&objp->data_len,
3471 	    objp->data_len));
3472 }
3473 
3474 static bool_t
xdr_READ4res_clnt(XDR * xdrs,READ4res * objp,READ4args * aobjp)3475 xdr_READ4res_clnt(XDR *xdrs, READ4res *objp, READ4args *aobjp)
3476 {
3477 	mblk_t *mp;
3478 	size_t n;
3479 	int error;
3480 	uint_t size = aobjp->res_maxsize;
3481 	count4 ocount;
3482 
3483 	if (xdrs->x_op == XDR_ENCODE)
3484 		return (FALSE);
3485 
3486 	if (xdrs->x_op == XDR_FREE) {
3487 		/*
3488 		 * Optimized free case
3489 		 */
3490 		if (objp->status != NFS4_OK)
3491 			return (TRUE);
3492 		if (objp->data_val != NULL)
3493 			kmem_free(objp->data_val, objp->data_len);
3494 		return (TRUE);
3495 	}
3496 
3497 	if (!XDR_GETINT32(xdrs, (int32_t *)&objp->status))
3498 		return (FALSE);
3499 	if (objp->status != NFS4_OK)
3500 		return (TRUE);
3501 
3502 	if (!XDR_GETINT32(xdrs, &objp->eof))
3503 		return (FALSE);
3504 
3505 
3506 	/*
3507 	 * This is a special case such that the caller is providing a
3508 	 * uio as a guide to eventual data location; this is used for
3509 	 * handling DIRECTIO reads.
3510 	 */
3511 	if (aobjp->res_uiop != NULL) {
3512 		struct uio *uiop = aobjp->res_uiop;
3513 		int32_t *ptr;
3514 
3515 		if (xdrs->x_ops == &xdrmblk_ops) {
3516 			if (!xdrmblk_getmblk(xdrs, &mp, &objp->data_len))
3517 				return (FALSE);
3518 
3519 			if (objp->data_len == 0)
3520 				return (TRUE);
3521 
3522 			if (objp->data_len > size)
3523 				return (FALSE);
3524 
3525 			size = objp->data_len;
3526 			do {
3527 				n = MIN(size, mp->b_wptr - mp->b_rptr);
3528 				if ((n = MIN(uiop->uio_resid, n)) != 0) {
3529 
3530 					error =	uiomove((char *)mp->b_rptr, n,
3531 					    UIO_READ, uiop);
3532 					if (error)
3533 						return (FALSE);
3534 					mp->b_rptr += n;
3535 					size -= n;
3536 				}
3537 
3538 				while (mp && (mp->b_rptr >= mp->b_wptr))
3539 					mp = mp->b_cont;
3540 			} while (mp && size > 0 && uiop->uio_resid > 0);
3541 
3542 			return (TRUE);
3543 		}
3544 
3545 		if (xdrs->x_ops == &xdrrdma_ops) {
3546 			struct clist *cl;
3547 
3548 			XDR_CONTROL(xdrs, XDR_RDMA_GET_WLIST, &cl);
3549 
3550 			objp->wlist = cl;
3551 
3552 			if (objp->wlist) {
3553 				/* opaque count */
3554 				if (!xdr_u_int(xdrs, &ocount)) {
3555 					objp->wlist = NULL;
3556 					return (FALSE);
3557 				}
3558 
3559 				objp->wlist_len = clist_len(cl);
3560 				objp->data_len = ocount;
3561 
3562 				if (objp->wlist_len !=
3563 				    roundup(
3564 				    objp->data_len, BYTES_PER_XDR_UNIT)) {
3565 					DTRACE_PROBE2(
3566 					    xdr__e__read4resuio_clnt_fail,
3567 					    int, ocount,
3568 					    int, objp->data_len);
3569 					objp->wlist = NULL;
3570 					return (FALSE);
3571 				}
3572 
3573 				uiop->uio_resid -= objp->data_len;
3574 				uiop->uio_iov->iov_len -= objp->data_len;
3575 				uiop->uio_iov->iov_base += objp->data_len;
3576 				uiop->uio_loffset += objp->data_len;
3577 
3578 				objp->wlist = NULL;
3579 				return (TRUE);
3580 			}
3581 		}
3582 
3583 		/*
3584 		 * This isn't an xdrmblk stream nor RDMA.
3585 		 * Handle the likely case that it can be
3586 		 * inlined (ex. xdrmem).
3587 		 */
3588 		if (!XDR_GETINT32(xdrs, (int32_t *)&objp->data_len))
3589 			return (FALSE);
3590 
3591 		if (objp->data_len == 0)
3592 			return (TRUE);
3593 
3594 		if (objp->data_len > size)
3595 			return (FALSE);
3596 
3597 		size = (int)objp->data_len;
3598 		if ((ptr = XDR_INLINE(xdrs, size)) != NULL)
3599 			return (uiomove(ptr, size, UIO_READ, uiop) ?
3600 			    FALSE : TRUE);
3601 
3602 		/*
3603 		 * Handle some other (unlikely) stream type that will
3604 		 * need a copy.
3605 		 */
3606 		if ((ptr = kmem_alloc(size, KM_NOSLEEP)) == NULL)
3607 			return (FALSE);
3608 
3609 		if (!XDR_GETBYTES(xdrs, (caddr_t)ptr, size)) {
3610 			kmem_free(ptr, size);
3611 			return (FALSE);
3612 		}
3613 		error = uiomove(ptr, size, UIO_READ, uiop);
3614 		kmem_free(ptr, size);
3615 
3616 		return (error ? FALSE : TRUE);
3617 	}
3618 
3619 	/*
3620 	 * Check for the other special case of the caller providing
3621 	 * the target area for the data.
3622 	 */
3623 	if (aobjp->res_data_val_alt == NULL)
3624 		return (FALSE);
3625 
3626 	/*
3627 	 * If read data received via RDMA_WRITE, don't do xdr_bytes().
3628 	 * RDMA_WRITE already moved the data so decode length of
3629 	 * RDMA_WRITE.
3630 	 */
3631 	if (xdrs->x_ops == &xdrrdma_ops) {
3632 		struct clist *cl;
3633 
3634 		XDR_CONTROL(xdrs, XDR_RDMA_GET_WLIST, &cl);
3635 
3636 		objp->wlist = cl;
3637 
3638 		/*
3639 		 * Data transferred through inline if
3640 		 * objp->wlist == NULL
3641 		 */
3642 		if (objp->wlist) {
3643 			/* opaque count */
3644 			if (!xdr_u_int(xdrs, &ocount)) {
3645 				objp->wlist = NULL;
3646 				return (FALSE);
3647 			}
3648 
3649 			objp->wlist_len = clist_len(cl);
3650 			objp->data_len = ocount;
3651 
3652 			if (objp->wlist_len !=
3653 			    roundup(
3654 			    objp->data_len, BYTES_PER_XDR_UNIT)) {
3655 				DTRACE_PROBE2(
3656 				    xdr__e__read4res_clnt_fail,
3657 				    int, ocount,
3658 				    int, objp->data_len);
3659 				objp->wlist = NULL;
3660 				return (FALSE);
3661 			}
3662 
3663 			objp->wlist = NULL;
3664 			return (TRUE);
3665 		}
3666 	}
3667 
3668 	return (xdr_bytes(xdrs, (char **)&aobjp->res_data_val_alt,
3669 	    (uint_t *)&objp->data_len,
3670 	    aobjp->res_maxsize));
3671 }
3672 
3673 static bool_t
xdr_READDIR4args(XDR * xdrs,READDIR4args * objp)3674 xdr_READDIR4args(XDR *xdrs, READDIR4args *objp)
3675 {
3676 	rdma_chunkinfo_t rci;
3677 	struct xdr_ops *xops = xdrrdma_xops();
3678 
3679 	if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
3680 	    xdrs->x_op == XDR_ENCODE) {
3681 		rci.rci_type = RCI_REPLY_CHUNK;
3682 		rci.rci_len = objp->maxcount;
3683 		XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
3684 	}
3685 
3686 	if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cookie))
3687 		return (FALSE);
3688 	if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cookieverf))
3689 		return (FALSE);
3690 	if (!xdr_u_int(xdrs, &objp->dircount))
3691 		return (FALSE);
3692 	if (!xdr_u_int(xdrs, &objp->maxcount))
3693 		return (FALSE);
3694 	return (xdr_bitmap4(xdrs, &objp->attr_request));
3695 }
3696 
3697 bool_t
xdr_READDIR4res(XDR * xdrs,READDIR4res * objp)3698 xdr_READDIR4res(XDR *xdrs, READDIR4res *objp)
3699 {
3700 	mblk_t *mp = objp->mblk;
3701 	bool_t ret_val;
3702 	uint_t flags = 0;
3703 
3704 	ASSERT(xdrs->x_op == XDR_ENCODE);
3705 
3706 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
3707 		return (FALSE);
3708 	if (objp->status != NFS4_OK)
3709 		return (TRUE);
3710 	if (mp == NULL)
3711 		return (FALSE);
3712 
3713 	if (xdrs->x_ops == &xdrmblk_ops) {
3714 		if (xdrmblk_putmblk_raw(xdrs, mp)
3715 		    == TRUE) {
3716 			/* mblk successfully inserted into outgoing chain */
3717 			objp->mblk = NULL;
3718 			return (TRUE);
3719 		}
3720 	}
3721 
3722 	ASSERT(mp->b_cont == NULL);
3723 
3724 	/*
3725 	 * If transport is RDMA, the pre-encoded m_blk needs to be moved
3726 	 * without being chunked.
3727 	 * Check if chunking is enabled for the xdr stream.
3728 	 * If it is enabled, disable it temporarily for this op,
3729 	 * then re-enable.
3730 	 */
3731 	XDR_CONTROL(xdrs, XDR_RDMA_GET_FLAGS, &flags);
3732 
3733 	if (!(flags & XDR_RDMA_CHUNK))
3734 		return (xdr_opaque(xdrs, (char *)mp->b_rptr, objp->data_len));
3735 
3736 	flags &= ~XDR_RDMA_CHUNK;
3737 
3738 	(void) XDR_CONTROL(xdrs, XDR_RDMA_SET_FLAGS, &flags);
3739 
3740 	ret_val = xdr_opaque(xdrs, (char *)mp->b_rptr, objp->data_len);
3741 
3742 	flags |= XDR_RDMA_CHUNK;
3743 
3744 	(void) XDR_CONTROL(xdrs, XDR_RDMA_SET_FLAGS, &flags);
3745 
3746 	return (ret_val);
3747 }
3748 
3749 static bool_t
xdr_READLINK4res(XDR * xdrs,READLINK4res * objp)3750 xdr_READLINK4res(XDR *xdrs, READLINK4res *objp)
3751 {
3752 	if (xdrs->x_op != XDR_FREE) {
3753 		if (!xdr_int(xdrs, (int32_t *)&objp->status))
3754 			return (FALSE);
3755 		if (objp->status != NFS4_OK)
3756 			return (TRUE);
3757 		return (xdr_bytes(xdrs, (char **)&objp->link.linktext4_val,
3758 		    (uint_t *)&objp->link.linktext4_len,
3759 		    NFS4_MAX_UTF8STRING));
3760 	}
3761 
3762 	/*
3763 	 * Optimized free case
3764 	 */
3765 	if (objp->status != NFS4_OK)
3766 		return (TRUE);
3767 	if (objp->link.linktext4_val != NULL)
3768 		kmem_free(objp->link.linktext4_val, objp->link.linktext4_len);
3769 	return (TRUE);
3770 }
3771 
3772 static bool_t
xdr_REMOVE4res(XDR * xdrs,REMOVE4res * objp)3773 xdr_REMOVE4res(XDR *xdrs, REMOVE4res *objp)
3774 {
3775 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
3776 		return (FALSE);
3777 	if (objp->status != NFS4_OK)
3778 		return (TRUE);
3779 	if (!xdr_bool(xdrs, &objp->cinfo.atomic))
3780 		return (FALSE);
3781 	if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.before))
3782 		return (FALSE);
3783 	return (xdr_u_longlong_t(xdrs,
3784 	    (u_longlong_t *)&objp->cinfo.after));
3785 }
3786 
3787 static bool_t
xdr_RENAME4res(XDR * xdrs,RENAME4res * objp)3788 xdr_RENAME4res(XDR *xdrs, RENAME4res *objp)
3789 {
3790 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
3791 		return (FALSE);
3792 	if (objp->status != NFS4_OK)
3793 		return (TRUE);
3794 	if (!xdr_bool(xdrs, &objp->source_cinfo.atomic))
3795 		return (FALSE);
3796 	if (!xdr_u_longlong_t(xdrs,
3797 	    (u_longlong_t *)&objp->source_cinfo.before))
3798 		return (FALSE);
3799 	if (!xdr_u_longlong_t(xdrs,
3800 	    (u_longlong_t *)&objp->source_cinfo.after))
3801 		return (FALSE);
3802 	if (!xdr_bool(xdrs, &objp->target_cinfo.atomic))
3803 		return (FALSE);
3804 	if (!xdr_u_longlong_t(xdrs,
3805 	    (u_longlong_t *)&objp->target_cinfo.before))
3806 		return (FALSE);
3807 	return (xdr_u_longlong_t(xdrs,
3808 	    (u_longlong_t *)&objp->target_cinfo.after));
3809 }
3810 
3811 static bool_t
xdr_secinfo4(XDR * xdrs,secinfo4 * objp)3812 xdr_secinfo4(XDR *xdrs, secinfo4 *objp)
3813 {
3814 	if (xdrs->x_op != XDR_FREE) {
3815 		if (!xdr_u_int(xdrs, &objp->flavor))
3816 			return (FALSE);
3817 		if (objp->flavor != RPCSEC_GSS)
3818 			return (TRUE);
3819 		if (!xdr_bytes(xdrs,
3820 		    (char **)&objp->flavor_info.oid.sec_oid4_val,
3821 		    (uint_t *)&objp->flavor_info.oid.sec_oid4_len,
3822 		    NFS4_MAX_SECOID4))
3823 			return (FALSE);
3824 		if (!xdr_u_int(xdrs, &objp->flavor_info.qop))
3825 			return (FALSE);
3826 		return (xdr_int(xdrs, (int *)&objp->flavor_info.service));
3827 	}
3828 
3829 	/*
3830 	 * Optimized free path
3831 	 */
3832 	if (objp->flavor != RPCSEC_GSS)
3833 		return (TRUE);
3834 
3835 	if (objp->flavor_info.oid.sec_oid4_val != NULL)
3836 		kmem_free(objp->flavor_info.oid.sec_oid4_val,
3837 		    objp->flavor_info.oid.sec_oid4_len);
3838 	return (TRUE);
3839 }
3840 
3841 bool_t
xdr_SECINFO4res(XDR * xdrs,SECINFO4res * objp)3842 xdr_SECINFO4res(XDR *xdrs, SECINFO4res *objp)
3843 {
3844 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
3845 		return (FALSE);
3846 	if (objp->status != NFS4_OK)
3847 		return (TRUE);
3848 	return (xdr_array(xdrs, (char **)&objp->SECINFO4resok_val,
3849 	    (uint_t *)&objp->SECINFO4resok_len, ~0, sizeof (secinfo4),
3850 	    (xdrproc_t)xdr_secinfo4));
3851 }
3852 
3853 static bool_t
xdr_SETCLIENTID4args(XDR * xdrs,SETCLIENTID4args * objp)3854 xdr_SETCLIENTID4args(XDR *xdrs, SETCLIENTID4args *objp)
3855 {
3856 	if (xdrs->x_op != XDR_FREE) {
3857 		if (!xdr_u_longlong_t(xdrs,
3858 		    (u_longlong_t *)&objp->client.verifier))
3859 			return (FALSE);
3860 		if (!xdr_bytes(xdrs, (char **)&objp->client.id_val,
3861 		    (uint_t *)&objp->client.id_len, NFS4_OPAQUE_LIMIT))
3862 			return (FALSE);
3863 		if (!xdr_u_int(xdrs, &objp->callback.cb_program))
3864 			return (FALSE);
3865 		if (!xdr_string(xdrs, &objp->callback.cb_location.r_netid,
3866 		    NFS4_OPAQUE_LIMIT))
3867 			return (FALSE);
3868 		if (!xdr_string(xdrs, &objp->callback.cb_location.r_addr,
3869 		    NFS4_OPAQUE_LIMIT))
3870 			return (FALSE);
3871 		return (xdr_u_int(xdrs, &objp->callback_ident));
3872 	}
3873 
3874 	/*
3875 	 * Optimized free case
3876 	 */
3877 	if (objp->client.id_val != NULL)
3878 		kmem_free(objp->client.id_val, objp->client.id_len);
3879 	(void) xdr_string(xdrs, &objp->callback.cb_location.r_netid,
3880 	    NFS4_OPAQUE_LIMIT);
3881 	return (xdr_string(xdrs, &objp->callback.cb_location.r_addr,
3882 	    NFS4_OPAQUE_LIMIT));
3883 }
3884 
3885 static bool_t
xdr_SETCLIENTID4res(XDR * xdrs,SETCLIENTID4res * objp)3886 xdr_SETCLIENTID4res(XDR *xdrs, SETCLIENTID4res *objp)
3887 {
3888 	if (xdrs->x_op != XDR_FREE) {
3889 		if (!xdr_int(xdrs, (int32_t *)&objp->status))
3890 			return (FALSE);
3891 		switch (objp->status) {
3892 		case NFS4_OK:
3893 			if (!xdr_u_longlong_t(xdrs,
3894 			    (u_longlong_t *)&objp->SETCLIENTID4res_u.resok4.
3895 			    clientid))
3896 				return (FALSE);
3897 			return (xdr_u_longlong_t(xdrs,
3898 			    (u_longlong_t *)&objp->SETCLIENTID4res_u.
3899 			    resok4.setclientid_confirm));
3900 		case NFS4ERR_CLID_INUSE:
3901 			if (!xdr_string(xdrs,
3902 			    &objp->SETCLIENTID4res_u.client_using.
3903 			    r_netid, NFS4_OPAQUE_LIMIT))
3904 				return (FALSE);
3905 			return (xdr_string(xdrs,
3906 			    &objp->SETCLIENTID4res_u.client_using.
3907 			    r_addr, NFS4_OPAQUE_LIMIT));
3908 		}
3909 		return (TRUE);
3910 	}
3911 
3912 	/*
3913 	 * Optimized free case
3914 	 */
3915 	if (objp->status != NFS4ERR_CLID_INUSE)
3916 		return (TRUE);
3917 
3918 	if (!xdr_string(xdrs, &objp->SETCLIENTID4res_u.client_using.r_netid,
3919 	    NFS4_OPAQUE_LIMIT))
3920 		return (FALSE);
3921 	return (xdr_string(xdrs, &objp->SETCLIENTID4res_u.client_using.r_addr,
3922 	    NFS4_OPAQUE_LIMIT));
3923 }
3924 
3925 static bool_t
xdr_WRITE4args(XDR * xdrs,WRITE4args * objp)3926 xdr_WRITE4args(XDR *xdrs, WRITE4args *objp)
3927 {
3928 	if (xdrs->x_op != XDR_FREE) {
3929 		if (!xdr_u_int(xdrs, &objp->stateid.seqid))
3930 			return (FALSE);
3931 		if (!xdr_opaque(xdrs, objp->stateid.other, NFS4_OTHER_SIZE))
3932 			return (FALSE);
3933 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset))
3934 			return (FALSE);
3935 		if (!xdr_int(xdrs, (int *)&objp->stable))
3936 			return (FALSE);
3937 		if (xdrs->x_op == XDR_DECODE) {
3938 			if (xdrs->x_ops == &xdrmblk_ops) {
3939 				objp->data_val = NULL;
3940 				return (xdrmblk_getmblk(xdrs, &objp->mblk,
3941 				    &objp->data_len));
3942 			}
3943 			objp->mblk = NULL;
3944 			if (xdrs->x_ops == &xdrrdmablk_ops) {
3945 				int retval;
3946 				retval = xdrrdma_getrdmablk(xdrs,
3947 				    &objp->rlist,
3948 				    &objp->data_len,
3949 				    &objp->conn, NFS4_DATA_LIMIT);
3950 				if (retval == FALSE)
3951 					return (FALSE);
3952 				return (xdrrdma_read_from_client(objp->rlist,
3953 				    &objp->conn, objp->data_len));
3954 			}
3955 		}
3956 		/* Else fall thru for the xdr_bytes(). */
3957 		return (xdr_bytes(xdrs, (char **)&objp->data_val,
3958 		    (uint_t *)&objp->data_len, NFS4_DATA_LIMIT));
3959 	}
3960 	if (objp->rlist != NULL) {
3961 		(void) xdrrdma_free_clist(objp->conn, objp->rlist);
3962 		objp->rlist = NULL;
3963 		objp->data_val = NULL;
3964 
3965 		return (TRUE);
3966 	}
3967 
3968 	/*
3969 	 * Optimized free case
3970 	 */
3971 	if (objp->data_val != NULL)
3972 		kmem_free(objp->data_val, objp->data_len);
3973 	return (TRUE);
3974 }
3975 
3976 static bool_t
xdr_WRITE4res(XDR * xdrs,WRITE4res * objp)3977 xdr_WRITE4res(XDR *xdrs, WRITE4res *objp)
3978 {
3979 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
3980 		return (FALSE);
3981 	if (objp->status != NFS4_OK)
3982 		return (TRUE);
3983 	if (!xdr_u_int(xdrs, &objp->count))
3984 		return (FALSE);
3985 	if (!xdr_int(xdrs, (int *)&objp->committed))
3986 		return (FALSE);
3987 	return (xdr_u_longlong_t(xdrs,
3988 	    (u_longlong_t *)&objp->writeverf));
3989 }
3990 
3991 static bool_t
xdr_snfs_argop4_free(XDR * xdrs,nfs_argop4 ** arrayp,int len)3992 xdr_snfs_argop4_free(XDR *xdrs, nfs_argop4 **arrayp, int len)
3993 {
3994 	int i;
3995 	nfs_argop4 *array = *arrayp;
3996 
3997 	/*
3998 	 * Optimized XDR_FREE only args array
3999 	 */
4000 	ASSERT(xdrs->x_op == XDR_FREE);
4001 
4002 	/*
4003 	 * Nothing to do?
4004 	 */
4005 	if (array == NULL)
4006 		return (TRUE);
4007 
4008 	for (i = 0; i < len; i++) {
4009 		/* Freeing for nfs4.x */
4010 		if (array[i].argop >= OP_BACKCHANNEL_CTL &&
4011 		    array[i].argop != OP_ILLEGAL) {
4012 			xdr_nfs4x_argop4(xdrs, &array[i]);
4013 			continue;
4014 		}
4015 
4016 		/*
4017 		 * These should be ordered by frequency of use
4018 		 */
4019 		switch (array[i].argop) {
4020 		case OP_PUTFH: {
4021 			nfs_fh4 *objp = &array[i].nfs_argop4_u.opputfh.object;
4022 
4023 			if (objp->nfs_fh4_val != NULL) {
4024 				kmem_free(objp->nfs_fh4_val, objp->nfs_fh4_len);
4025 			}
4026 			continue;
4027 		}
4028 		case OP_GETATTR:
4029 		case OP_GETFH:
4030 			continue;
4031 		case OP_LOOKUP:
4032 			if (array[i].nfs_argop4_u.oplookup.objname.
4033 			    utf8string_val != NULL) {
4034 				kmem_free(array[i].nfs_argop4_u.oplookup.
4035 				    objname.utf8string_val,
4036 				    array[i].nfs_argop4_u.oplookup.
4037 				    objname.utf8string_len);
4038 			}
4039 			continue;
4040 		case OP_OPEN:
4041 			(void) xdr_OPEN4args(xdrs,
4042 			    &array[i].nfs_argop4_u.opopen);
4043 			continue;
4044 		case OP_CLOSE:
4045 		case OP_ACCESS:
4046 		case OP_READ:
4047 			continue;
4048 		case OP_WRITE:
4049 			(void) xdr_WRITE4args(xdrs,
4050 			    &array[i].nfs_argop4_u.opwrite);
4051 			continue;
4052 		case OP_DELEGRETURN:
4053 		case OP_LOOKUPP:
4054 		case OP_READDIR:
4055 			continue;
4056 		case OP_REMOVE:
4057 			if (array[i].nfs_argop4_u.opremove.target.
4058 			    utf8string_val != NULL) {
4059 				kmem_free(array[i].nfs_argop4_u.opremove.target.
4060 				    utf8string_val,
4061 				    array[i].nfs_argop4_u.opremove.target.
4062 				    utf8string_len);
4063 			}
4064 			continue;
4065 		case OP_COMMIT:
4066 			continue;
4067 		case OP_CREATE:
4068 			(void) xdr_CREATE4args(xdrs,
4069 			    &array[i].nfs_argop4_u.opcreate);
4070 			continue;
4071 		case OP_DELEGPURGE:
4072 			continue;
4073 		case OP_LINK:
4074 			if (array[i].nfs_argop4_u.oplink.newname.
4075 			    utf8string_val != NULL) {
4076 				kmem_free(array[i].nfs_argop4_u.oplink.newname.
4077 				    utf8string_val,
4078 				    array[i].nfs_argop4_u.oplink.newname.
4079 				    utf8string_len);
4080 			}
4081 			continue;
4082 		case OP_LOCK:
4083 			(void) xdr_LOCK4args(xdrs,
4084 			    &array[i].nfs_argop4_u.oplock);
4085 			continue;
4086 		case OP_LOCKT:
4087 			(void) xdr_LOCKT4args(xdrs,
4088 			    &array[i].nfs_argop4_u.oplockt);
4089 			continue;
4090 		case OP_LOCKU:
4091 			continue;
4092 		case OP_NVERIFY:
4093 			(void) xdr_fattr4(xdrs,
4094 			    &array[i].nfs_argop4_u.opnverify.obj_attributes);
4095 			continue;
4096 		case OP_OPENATTR:
4097 		case OP_OPEN_CONFIRM:
4098 		case OP_OPEN_DOWNGRADE:
4099 		case OP_PUTPUBFH:
4100 		case OP_PUTROOTFH:
4101 		case OP_READLINK:
4102 			continue;
4103 		case OP_RENAME:
4104 			if (array[i].nfs_argop4_u.oprename.oldname.
4105 			    utf8string_val != NULL) {
4106 				kmem_free(array[i].nfs_argop4_u.oprename.
4107 				    oldname.utf8string_val,
4108 				    array[i].nfs_argop4_u.oprename.
4109 				    oldname.utf8string_len);
4110 			}
4111 			if (array[i].nfs_argop4_u.oprename.newname.
4112 			    utf8string_val != NULL) {
4113 				kmem_free(array[i].nfs_argop4_u.oprename.
4114 				    newname.utf8string_val,
4115 				    array[i].nfs_argop4_u.oprename.
4116 				    newname.utf8string_len);
4117 			}
4118 			continue;
4119 		case OP_RENEW:
4120 		case OP_RESTOREFH:
4121 		case OP_SAVEFH:
4122 			continue;
4123 		case OP_SECINFO:
4124 			if (array[i].nfs_argop4_u.opsecinfo.name.
4125 			    utf8string_val != NULL) {
4126 				kmem_free(array[i].nfs_argop4_u.opsecinfo.name.
4127 				    utf8string_val,
4128 				    array[i].nfs_argop4_u.opsecinfo.name.
4129 				    utf8string_len);
4130 			}
4131 			continue;
4132 		case OP_SETATTR:
4133 			(void) xdr_fattr4(xdrs,
4134 			    &array[i].nfs_argop4_u.opsetattr.obj_attributes);
4135 			continue;
4136 		case OP_SETCLIENTID:
4137 			(void) xdr_SETCLIENTID4args(xdrs,
4138 			    &array[i].nfs_argop4_u.opsetclientid);
4139 			continue;
4140 		case OP_SETCLIENTID_CONFIRM:
4141 			continue;
4142 		case OP_VERIFY:
4143 			(void) xdr_fattr4(xdrs,
4144 			    &array[i].nfs_argop4_u.opverify.obj_attributes);
4145 			continue;
4146 		case OP_RELEASE_LOCKOWNER:
4147 			if (array[i].nfs_argop4_u.oprelease_lockowner.
4148 			    lock_owner.owner_val != NULL) {
4149 				kmem_free(array[i].nfs_argop4_u.
4150 				    oprelease_lockowner.lock_owner.owner_val,
4151 				    array[i].nfs_argop4_u.
4152 				    oprelease_lockowner.lock_owner.owner_len);
4153 			}
4154 			continue;
4155 		case OP_ILLEGAL:
4156 			continue;
4157 		default:
4158 			/*
4159 			 * An invalid op is a coding error, it should never
4160 			 * have been decoded.
4161 			 * Don't error because the caller cannot finish
4162 			 * freeing the residual memory of the array.
4163 			 */
4164 			continue;
4165 		}
4166 	}
4167 
4168 	kmem_free(*arrayp, len * sizeof (nfs_argop4));
4169 	*arrayp = NULL;
4170 	return (TRUE);
4171 }
4172 
4173 static bool_t
xdr_nfs_argop4(XDR * xdrs,nfs_argop4 * objp)4174 xdr_nfs_argop4(XDR *xdrs, nfs_argop4 *objp)
4175 {
4176 	rdma_chunkinfo_t rci;
4177 	struct xdr_ops *xops = xdrrdma_xops();
4178 
4179 	/*
4180 	 * These should be ordered by frequency of use
4181 	 */
4182 	switch (objp->argop) {
4183 	case OP_PUTFH:
4184 		return (xdr_bytes(xdrs,
4185 		    (char **)&objp->nfs_argop4_u.opputfh.object.nfs_fh4_val,
4186 		    (uint_t *)&objp->nfs_argop4_u.opputfh.object.nfs_fh4_len,
4187 		    NFS4_FHSIZE));
4188 	case OP_GETATTR:
4189 		/*
4190 		 * ACLs can become relatively large ( > 8K) and the default
4191 		 * 8K reply chunk of RDMA may not suffice. Check for
4192 		 * get ACL bit and if it's RDMA, add a chunk equal the size
4193 		 * of the transfer size to the reply chunk list.
4194 		 */
4195 		if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
4196 		    (xdrs->x_op == XDR_ENCODE) &&
4197 		    (objp->nfs_argop4_u.opgetattr.attr_request &
4198 		    FATTR4_ACL_MASK)) {
4199 			rci.rci_type = RCI_REPLY_CHUNK;
4200 			rci.rci_len = objp->nfs_argop4_u.opgetattr.mi->mi_tsize;
4201 			XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
4202 
4203 			DTRACE_PROBE1(xdr__i__argop4__getattr, int,
4204 			    rci.rci_len);
4205 		}
4206 		return (xdr_bitmap4(xdrs,
4207 		    &objp->nfs_argop4_u.opgetattr.attr_request));
4208 	case OP_GETFH:
4209 		return (TRUE);
4210 	case OP_LOOKUP:
4211 		return (xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.oplookup.
4212 		    objname.utf8string_val,
4213 		    (uint_t *)&objp->nfs_argop4_u.oplookup.
4214 		    objname.utf8string_len,
4215 		    NFS4_MAX_UTF8STRING));
4216 	case OP_OPEN:
4217 		return (xdr_OPEN4args(xdrs, &objp->nfs_argop4_u.opopen));
4218 	case OP_CLOSE:
4219 		return (xdr_CLOSE4args(xdrs, &objp->nfs_argop4_u.opclose));
4220 	case OP_ACCESS:
4221 		return (xdr_u_int(xdrs,
4222 		    &objp->nfs_argop4_u.opaccess.access));
4223 	case OP_READ:
4224 		return (xdr_READ4args(xdrs, &objp->nfs_argop4_u.opread));
4225 	case OP_WRITE:
4226 		return (xdr_WRITE4args(xdrs, &objp->nfs_argop4_u.opwrite));
4227 	case OP_DELEGRETURN:
4228 		if (!xdr_u_int(xdrs,
4229 		    &objp->nfs_argop4_u.opdelegreturn.deleg_stateid.seqid))
4230 			return (FALSE);
4231 		return (xdr_opaque(xdrs,
4232 		    objp->nfs_argop4_u.opdelegreturn.deleg_stateid.other,
4233 		    NFS4_OTHER_SIZE));
4234 	case OP_LOOKUPP:
4235 		return (TRUE);
4236 	case OP_READDIR:
4237 		return (xdr_READDIR4args(xdrs, &objp->nfs_argop4_u.opreaddir));
4238 	case OP_REMOVE:
4239 		return (xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.opremove.
4240 		    target.utf8string_val,
4241 		    (uint_t *)&objp->nfs_argop4_u.opremove.
4242 		    target.utf8string_len,
4243 		    NFS4_MAX_UTF8STRING));
4244 	case OP_COMMIT:
4245 		if (!xdr_u_longlong_t(xdrs,
4246 		    (u_longlong_t *)&objp->nfs_argop4_u.opcommit.offset))
4247 			return (FALSE);
4248 		return (xdr_u_int(xdrs, &objp->nfs_argop4_u.opcommit.count));
4249 	case OP_CREATE:
4250 		return (xdr_CREATE4args(xdrs, &objp->nfs_argop4_u.opcreate));
4251 	case OP_DELEGPURGE:
4252 		return (xdr_u_longlong_t(xdrs,
4253 		    (u_longlong_t *)&objp->nfs_argop4_u.opdelegpurge.clientid));
4254 	case OP_LINK:
4255 		return (xdr_bytes(xdrs,
4256 		    (char **)&objp->nfs_argop4_u.oplink.newname.utf8string_val,
4257 		    (uint_t *)&objp->nfs_argop4_u.oplink.newname.utf8string_len,
4258 		    NFS4_MAX_UTF8STRING));
4259 	case OP_LOCK:
4260 		return (xdr_LOCK4args(xdrs, &objp->nfs_argop4_u.oplock));
4261 	case OP_LOCKT:
4262 		return (xdr_LOCKT4args(xdrs, &objp->nfs_argop4_u.oplockt));
4263 	case OP_LOCKU:
4264 		return (xdr_LOCKU4args(xdrs, &objp->nfs_argop4_u.oplocku));
4265 	case OP_NVERIFY:
4266 		return (xdr_fattr4(xdrs,
4267 		    &objp->nfs_argop4_u.opnverify.obj_attributes));
4268 	case OP_OPENATTR:
4269 		return (xdr_bool(xdrs,
4270 		    &objp->nfs_argop4_u.opopenattr.createdir));
4271 	case OP_OPEN_CONFIRM:
4272 		if (!xdr_u_int(xdrs, &objp->nfs_argop4_u.opopen_confirm.
4273 		    open_stateid.seqid))
4274 			return (FALSE);
4275 		if (!xdr_opaque(xdrs, objp->nfs_argop4_u.opopen_confirm.
4276 		    open_stateid.other, NFS4_OTHER_SIZE))
4277 			return (FALSE);
4278 		return (xdr_u_int(xdrs, &objp->nfs_argop4_u.opopen_confirm.
4279 		    seqid));
4280 	case OP_OPEN_DOWNGRADE:
4281 		return (xdr_OPEN_DOWNGRADE4args(xdrs,
4282 		    &objp->nfs_argop4_u.opopen_downgrade));
4283 	case OP_PUTPUBFH:
4284 		return (TRUE);
4285 	case OP_PUTROOTFH:
4286 		return (TRUE);
4287 	case OP_READLINK:
4288 		if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
4289 		    xdrs->x_op == XDR_ENCODE) {
4290 			rci.rci_type = RCI_REPLY_CHUNK;
4291 			rci.rci_len = MAXPATHLEN;
4292 			XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
4293 		}
4294 		return (TRUE);
4295 	case OP_RENAME:
4296 		if (!xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.oprename.
4297 		    oldname.utf8string_val,
4298 		    (uint_t *)&objp->nfs_argop4_u.oprename.
4299 		    oldname.utf8string_len,
4300 		    NFS4_MAX_UTF8STRING))
4301 			return (FALSE);
4302 		return (xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.oprename.
4303 		    newname.utf8string_val,
4304 		    (uint_t *)&objp->nfs_argop4_u.oprename.
4305 		    newname.utf8string_len,
4306 		    NFS4_MAX_UTF8STRING));
4307 	case OP_RENEW:
4308 		return (xdr_u_longlong_t(xdrs,
4309 		    (u_longlong_t *)&objp->nfs_argop4_u.oprenew.clientid));
4310 	case OP_RESTOREFH:
4311 		return (TRUE);
4312 	case OP_SAVEFH:
4313 		return (TRUE);
4314 	case OP_SECINFO:
4315 		return (xdr_bytes(xdrs,
4316 		    (char **)&objp->nfs_argop4_u.opsecinfo.name.utf8string_val,
4317 		    (uint_t *)&objp->nfs_argop4_u.opsecinfo.name.utf8string_len,
4318 		    NFS4_MAX_UTF8STRING));
4319 	case OP_SETATTR:
4320 		if (!xdr_u_int(xdrs, &objp->nfs_argop4_u.opsetattr.
4321 		    stateid.seqid))
4322 			return (FALSE);
4323 		if (!xdr_opaque(xdrs, objp->nfs_argop4_u.opsetattr.
4324 		    stateid.other, NFS4_OTHER_SIZE))
4325 			return (FALSE);
4326 		return (xdr_fattr4(xdrs, &objp->nfs_argop4_u.opsetattr.
4327 		    obj_attributes));
4328 	case OP_SETCLIENTID:
4329 		return (xdr_SETCLIENTID4args(xdrs,
4330 		    &objp->nfs_argop4_u.opsetclientid));
4331 	case OP_SETCLIENTID_CONFIRM:
4332 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->nfs_argop4_u.
4333 		    opsetclientid_confirm.clientid))
4334 			return (FALSE);
4335 		return (xdr_u_longlong_t(xdrs,
4336 		    (u_longlong_t *)&objp->nfs_argop4_u.
4337 		    opsetclientid_confirm.setclientid_confirm));
4338 	case OP_VERIFY:
4339 		return (xdr_fattr4(xdrs,
4340 		    &objp->nfs_argop4_u.opverify.obj_attributes));
4341 	case OP_RELEASE_LOCKOWNER:
4342 		if (!xdr_u_longlong_t(xdrs,
4343 		    (u_longlong_t *)&objp->nfs_argop4_u.
4344 		    oprelease_lockowner.lock_owner.clientid))
4345 			return (FALSE);
4346 		return (xdr_bytes(xdrs,
4347 		    (char **)&objp->nfs_argop4_u.oprelease_lockowner.
4348 		    lock_owner.owner_val,
4349 		    (uint_t *)&objp->nfs_argop4_u.oprelease_lockowner.
4350 		    lock_owner.owner_len, NFS4_OPAQUE_LIMIT));
4351 	case OP_ILLEGAL:
4352 		return (TRUE);
4353 	}
4354 	return (FALSE);
4355 }
4356 
4357 static bool_t
xdr_cnfs_argop4_wrap(XDR * xdrs,nfs_argop4 * objp)4358 xdr_cnfs_argop4_wrap(XDR *xdrs, nfs_argop4 *objp)
4359 {
4360 	if (!xdr_int(xdrs, (int *)&objp->argop))
4361 		return (FALSE);
4362 
4363 	return (xdr_nfs_argop4(xdrs, objp));
4364 }
4365 
4366 static bool_t
xdr_snfs_argop4(XDR * xdrs,nfs_argop4 * objp)4367 xdr_snfs_argop4(XDR *xdrs, nfs_argop4 *objp)
4368 {
4369 	if (!xdr_int(xdrs, (int *)&objp->argop))
4370 		return (FALSE);
4371 
4372 	switch (objp->argop) {
4373 	case OP_PUTFH:
4374 		return (xdr_decode_nfs_fh4(xdrs,
4375 		    &objp->nfs_argop4_u.opputfh.object));
4376 	default:
4377 		if (objp->argop >= OP_BACKCHANNEL_CTL &&
4378 		    objp->argop != OP_ILLEGAL)
4379 			return (xdr_nfs4x_argop4(xdrs, objp));
4380 
4381 		return (xdr_nfs_argop4(xdrs, objp));
4382 	}
4383 }
4384 
4385 /*
4386  * Client side encode only arg op processing
4387  */
4388 static bool_t
xdr_cnfs_argop4(XDR * xdrs,nfs_argop4 * objp)4389 xdr_cnfs_argop4(XDR *xdrs, nfs_argop4 *objp)
4390 {
4391 	int len;
4392 	int op;
4393 	nfs4_sharedfh_t *sfh;
4394 	mntinfo4_t *mi;
4395 	rpc_inline_t *ptr;
4396 
4397 	ASSERT(xdrs->x_op == XDR_ENCODE);
4398 
4399 	/*
4400 	 * Special case the private pseudo ops
4401 	 */
4402 	if (!(objp->argop & SUNW_PRIVATE_OP))
4403 		return (xdr_cnfs_argop4_wrap(xdrs, objp));
4404 
4405 	/*
4406 	 * These should be ordered by frequency of use
4407 	 */
4408 	switch (objp->argop) {
4409 	case OP_CPUTFH:
4410 		/*
4411 		 * We are passed in the file handle as a nfs4_sharedfh_t *
4412 		 * We need to acquire the correct locks so we can copy it out.
4413 		 */
4414 		sfh = (nfs4_sharedfh_t *)objp->nfs_argop4_u.opcputfh.sfh;
4415 		mi = sfh->sfh_mi;
4416 		(void) nfs_rw_enter_sig(&mi->mi_fh_lock, RW_READER, 0);
4417 
4418 		len = sfh->sfh_fh.nfs_fh4_len;
4419 		ASSERT(len <= NFS4_FHSIZE);
4420 
4421 		/*
4422 		 * First try and inline the copy
4423 		 * Must first be a multiple of BYTES_PER_XDR_UNIT
4424 		 */
4425 		if (!(len % BYTES_PER_XDR_UNIT) &&
4426 		    (ptr = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT + len)) !=
4427 		    NULL) {
4428 			IXDR_PUT_U_INT32(ptr, OP_PUTFH);
4429 			IXDR_PUT_U_INT32(ptr, len);
4430 			bcopy(sfh->sfh_fh.nfs_fh4_val, ptr, len);
4431 			nfs_rw_exit(&mi->mi_fh_lock);
4432 			return (TRUE);
4433 		}
4434 
4435 		op = OP_PUTFH;
4436 		if (!XDR_PUTINT32(xdrs, &op)) {
4437 			nfs_rw_exit(&mi->mi_fh_lock);
4438 			return (FALSE);
4439 		}
4440 		if (!XDR_PUTINT32(xdrs, &len)) {
4441 			nfs_rw_exit(&mi->mi_fh_lock);
4442 			return (FALSE);
4443 		}
4444 		if (!(len % BYTES_PER_XDR_UNIT)) {
4445 			if (XDR_PUTBYTES(xdrs, sfh->sfh_fh.nfs_fh4_val, len)) {
4446 				nfs_rw_exit(&mi->mi_fh_lock);
4447 				return (TRUE);
4448 			}
4449 		} else if (xdr_opaque(xdrs, sfh->sfh_fh.nfs_fh4_val, len)) {
4450 			nfs_rw_exit(&mi->mi_fh_lock);
4451 			return (TRUE);
4452 		}
4453 		nfs_rw_exit(&mi->mi_fh_lock);
4454 		return (FALSE);
4455 	case OP_CLOOKUP:
4456 		len = strlen(objp->nfs_argop4_u.opclookup.cname);
4457 		if (len > NFS4_MAX_UTF8STRING)
4458 			return (FALSE);
4459 		op = OP_LOOKUP;
4460 		if (XDR_PUTINT32(xdrs, &op)) {
4461 			if (XDR_PUTINT32(xdrs, &len)) {
4462 				return (xdr_opaque(xdrs,
4463 				    objp->nfs_argop4_u.opclookup.cname,
4464 				    len));
4465 			}
4466 		}
4467 		return (FALSE);
4468 	case OP_COPEN:
4469 		/* op processing inlined in xdr_OPEN4cargs */
4470 		return (xdr_OPEN4cargs(xdrs, &objp->nfs_argop4_u.opcopen));
4471 	case OP_CREMOVE:
4472 		len = strlen(objp->nfs_argop4_u.opcremove.ctarget);
4473 		if (len > NFS4_MAX_UTF8STRING)
4474 			return (FALSE);
4475 		op = OP_REMOVE;
4476 		if (XDR_PUTINT32(xdrs, &op)) {
4477 			if (XDR_PUTINT32(xdrs, &len)) {
4478 				return (xdr_opaque(xdrs,
4479 				    objp->nfs_argop4_u.opcremove.ctarget,
4480 				    len));
4481 			}
4482 		}
4483 		return (FALSE);
4484 	case OP_CCREATE:
4485 		op = OP_CREATE;
4486 		if (!XDR_PUTINT32(xdrs, &op))
4487 			return (FALSE);
4488 		return (xdr_CREATE4cargs(xdrs, &objp->nfs_argop4_u.opccreate));
4489 	case OP_CLINK:
4490 		len = strlen(objp->nfs_argop4_u.opclink.cnewname);
4491 		if (len > NFS4_MAX_UTF8STRING)
4492 			return (FALSE);
4493 		op = OP_LINK;
4494 		if (XDR_PUTINT32(xdrs, &op)) {
4495 			if (XDR_PUTINT32(xdrs, &len)) {
4496 				return (xdr_opaque(xdrs,
4497 				    objp->nfs_argop4_u.opclink.cnewname,
4498 				    len));
4499 			}
4500 		}
4501 		return (FALSE);
4502 	case OP_CRENAME:
4503 		len = strlen(objp->nfs_argop4_u.opcrename.coldname);
4504 		if (len > NFS4_MAX_UTF8STRING)
4505 			return (FALSE);
4506 		op = OP_RENAME;
4507 		if (!XDR_PUTINT32(xdrs, &op))
4508 			return (FALSE);
4509 		if (!XDR_PUTINT32(xdrs, &len))
4510 			return (FALSE);
4511 		if (!xdr_opaque(xdrs,
4512 		    objp->nfs_argop4_u.opcrename.coldname, len))
4513 			return (FALSE);
4514 		len = strlen(objp->nfs_argop4_u.opcrename.cnewname);
4515 		if (len > NFS4_MAX_UTF8STRING)
4516 			return (FALSE);
4517 		if (XDR_PUTINT32(xdrs, &len)) {
4518 			return (xdr_opaque(xdrs,
4519 			    objp->nfs_argop4_u.opcrename.cnewname, len));
4520 		}
4521 		return (FALSE);
4522 	case OP_CSECINFO:
4523 		len = strlen(objp->nfs_argop4_u.opcsecinfo.cname);
4524 		if (len > NFS4_MAX_UTF8STRING)
4525 			return (FALSE);
4526 		op = OP_SECINFO;
4527 		if (XDR_PUTINT32(xdrs, &op)) {
4528 			if (XDR_PUTINT32(xdrs, &len)) {
4529 				return (xdr_opaque(xdrs,
4530 				    objp->nfs_argop4_u.opcsecinfo.cname,
4531 				    len));
4532 			}
4533 		}
4534 		return (FALSE);
4535 	}
4536 	return (FALSE);
4537 }
4538 
4539 /*
4540  * Note that the len and decode_len will only be different in the case
4541  * of the client's use of this free function.  If the server is
4542  * freeing results, then the len/decode_len will always match.
4543  */
4544 static bool_t
xdr_nfs_resop4_free(XDR * xdrs,nfs_resop4 ** arrayp,int len,int decode_len)4545 xdr_nfs_resop4_free(XDR *xdrs, nfs_resop4 **arrayp, int len, int decode_len)
4546 {
4547 	int i;
4548 	nfs_resop4 *array = *arrayp;
4549 	nfs4_ga_res_t *gr;
4550 
4551 	/*
4552 	 * Optimized XDR_FREE only results array
4553 	 */
4554 	ASSERT(xdrs->x_op == XDR_FREE);
4555 
4556 	if (array == NULL)
4557 		return (TRUE);
4558 
4559 	for (i = 0; i < decode_len; i++) {
4560 		/*
4561 		 * These should be ordered by frequency of use
4562 		 */
4563 		switch (array[i].resop) {
4564 		case OP_PUTFH:
4565 			continue;
4566 		case OP_GETATTR:
4567 			if (array[i].nfs_resop4_u.opgetattr.status != NFS4_OK)
4568 				continue;
4569 
4570 			gr = &array[i].nfs_resop4_u.opgetattr.ga_res;
4571 			if (gr->n4g_ext_res) {
4572 				if (gr->n4g_resbmap & FATTR4_FS_LOCATIONS_MASK)
4573 					(void) xdr_fattr4_fs_locations(xdrs,
4574 					    &gr->n4g_ext_res->n4g_fslocations);
4575 				kmem_free(gr->n4g_ext_res,
4576 				    sizeof (struct nfs4_ga_ext_res));
4577 			}
4578 			continue;
4579 		case OP_GETFH:
4580 			if (array[i].nfs_resop4_u.opgetfh.status != NFS4_OK)
4581 				continue;
4582 			if (array[i].nfs_resop4_u.opgetfh.object.nfs_fh4_val !=
4583 			    NULL) {
4584 				kmem_free(array[i].nfs_resop4_u.opgetfh.object.
4585 				    nfs_fh4_val,
4586 				    array[i].nfs_resop4_u.opgetfh.object.
4587 				    nfs_fh4_len);
4588 			}
4589 			continue;
4590 		case OP_LOOKUP:
4591 			continue;
4592 		case OP_OPEN:
4593 			(void) xdr_OPEN4res(xdrs, &array[i].nfs_resop4_u.
4594 			    opopen);
4595 			continue;
4596 		case OP_CLOSE:
4597 		case OP_ACCESS:
4598 			continue;
4599 		case OP_READ:
4600 			(void) xdr_READ4res(xdrs,
4601 			    &array[i].nfs_resop4_u.opread);
4602 			continue;
4603 		case OP_WRITE:
4604 		case OP_DELEGRETURN:
4605 		case OP_LOOKUPP:
4606 		case OP_READDIR:
4607 		case OP_REMOVE:
4608 		case OP_COMMIT:
4609 		case OP_CREATE:
4610 		case OP_DELEGPURGE:
4611 		case OP_LINK:
4612 			continue;
4613 		case OP_LOCK:
4614 			(void) xdr_LOCK4res(xdrs, &array[i].nfs_resop4_u.
4615 			    oplock);
4616 			continue;
4617 		case OP_LOCKT:
4618 			(void) xdr_LOCKT4res(xdrs, &array[i].nfs_resop4_u.
4619 			    oplockt);
4620 			continue;
4621 		case OP_LOCKU:
4622 		case OP_NVERIFY:
4623 		case OP_OPENATTR:
4624 		case OP_OPEN_CONFIRM:
4625 		case OP_OPEN_DOWNGRADE:
4626 		case OP_PUTPUBFH:
4627 		case OP_PUTROOTFH:
4628 		case OP_RENAME:
4629 		case OP_RENEW:
4630 		case OP_RESTOREFH:
4631 		case OP_SAVEFH:
4632 			continue;
4633 		case OP_READLINK:
4634 			(void) xdr_READLINK4res(xdrs, &array[i].nfs_resop4_u.
4635 			    opreadlink);
4636 			continue;
4637 		case OP_SECINFO:
4638 			(void) xdr_array(xdrs,
4639 			    (char **)&array[i].nfs_resop4_u.opsecinfo.
4640 			    SECINFO4resok_val,
4641 			    (uint_t *)&array[i].nfs_resop4_u.opsecinfo.
4642 			    SECINFO4resok_len,
4643 			    NFS4_SECINFO_LIMIT, sizeof (secinfo4),
4644 			    (xdrproc_t)xdr_secinfo4);
4645 			continue;
4646 		case OP_SETCLIENTID:
4647 			(void) xdr_SETCLIENTID4res(xdrs,
4648 			    &array[i].nfs_resop4_u.opsetclientid);
4649 			continue;
4650 		case OP_SETATTR:
4651 		case OP_SETCLIENTID_CONFIRM:
4652 		case OP_VERIFY:
4653 		case OP_RELEASE_LOCKOWNER:
4654 		case OP_ILLEGAL:
4655 			continue;
4656 		default:
4657 			/*
4658 			 * An invalid op is a coding error, it should never
4659 			 * have been decoded.
4660 			 * Don't error because the caller cannot finish
4661 			 * freeing the residual memory of the array.
4662 			 */
4663 			continue;
4664 		}
4665 	}
4666 
4667 	kmem_free(*arrayp, len * sizeof (nfs_resop4));
4668 	*arrayp = NULL;
4669 	return (TRUE);
4670 }
4671 
4672 static bool_t
xdr_snfs_resop4_free(XDR * xdrs,nfs_resop4 ** arrayp,int len,int decode_len)4673 xdr_snfs_resop4_free(XDR *xdrs, nfs_resop4 **arrayp, int len, int decode_len)
4674 {
4675 	return (xdr_nfs_resop4_free(xdrs, arrayp, len, decode_len));
4676 }
4677 
4678 static bool_t
xdr_nfs_resop4(XDR * xdrs,nfs_resop4 * objp)4679 xdr_nfs_resop4(XDR *xdrs, nfs_resop4 *objp)
4680 {
4681 	/*
4682 	 * These should be ordered by frequency of use
4683 	 */
4684 	switch (objp->resop) {
4685 	case OP_PUTFH:
4686 		return (xdr_int(xdrs,
4687 		    (int32_t *)&objp->nfs_resop4_u.opputfh.status));
4688 	case OP_GETATTR:
4689 		if (!xdr_int(xdrs,
4690 		    (int32_t *)&objp->nfs_resop4_u.opgetattr.status))
4691 			return (FALSE);
4692 		if (objp->nfs_resop4_u.opgetattr.status != NFS4_OK)
4693 			return (TRUE);
4694 		return (xdr_fattr4(xdrs,
4695 		    &objp->nfs_resop4_u.opgetattr.obj_attributes));
4696 	case OP_GETFH:
4697 		if (!xdr_int(xdrs,
4698 		    (int32_t *)&objp->nfs_resop4_u.opgetfh.status))
4699 			return (FALSE);
4700 		if (objp->nfs_resop4_u.opgetfh.status != NFS4_OK)
4701 			return (TRUE);
4702 		return (xdr_bytes(xdrs,
4703 		    (char **)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_val,
4704 		    (uint_t *)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_len,
4705 		    NFS4_FHSIZE));
4706 	case OP_LOOKUP:
4707 		return (xdr_int(xdrs,
4708 		    (int32_t *)&objp->nfs_resop4_u.oplookup.status));
4709 	case OP_OPEN:
4710 		return (xdr_OPEN4res(xdrs, &objp->nfs_resop4_u.opopen));
4711 	case OP_CLOSE:
4712 		return (xdr_CLOSE4res(xdrs, &objp->nfs_resop4_u.opclose));
4713 	case OP_ACCESS:
4714 		return (xdr_ACCESS4res(xdrs, &objp->nfs_resop4_u.opaccess));
4715 	case OP_READ:
4716 		return (xdr_READ4res(xdrs, &objp->nfs_resop4_u.opread));
4717 	case OP_WRITE:
4718 		return (xdr_WRITE4res(xdrs, &objp->nfs_resop4_u.opwrite));
4719 	case OP_DELEGRETURN:
4720 		return (xdr_int(xdrs,
4721 		    (int32_t *)&objp->nfs_resop4_u.opdelegreturn.status));
4722 	case OP_LOOKUPP:
4723 		return (xdr_int(xdrs,
4724 		    (int32_t *)&objp->nfs_resop4_u.oplookupp.status));
4725 	case OP_READDIR:
4726 		return (xdr_READDIR4res(xdrs, &objp->nfs_resop4_u.opreaddir));
4727 	case OP_REMOVE:
4728 		return (xdr_REMOVE4res(xdrs, &objp->nfs_resop4_u.opremove));
4729 
4730 	case OP_COMMIT:
4731 		if (!xdr_int(xdrs,
4732 		    (int32_t *)&objp->nfs_resop4_u.opcommit.status))
4733 			return (FALSE);
4734 		if (objp->nfs_resop4_u.opcommit.status != NFS4_OK)
4735 			return (TRUE);
4736 		return (xdr_u_longlong_t(xdrs,
4737 		    (u_longlong_t *)&objp->nfs_resop4_u.opcommit.
4738 		    writeverf));
4739 	case OP_CREATE:
4740 		return (xdr_CREATE4res(xdrs, &objp->nfs_resop4_u.opcreate));
4741 	case OP_DELEGPURGE:
4742 		return (xdr_int(xdrs,
4743 		    (int32_t *)&objp->nfs_resop4_u.opdelegpurge.status));
4744 	case OP_LINK:
4745 		return (xdr_LINK4res(xdrs, &objp->nfs_resop4_u.oplink));
4746 	case OP_LOCK:
4747 		return (xdr_LOCK4res(xdrs, &objp->nfs_resop4_u.oplock));
4748 	case OP_LOCKT:
4749 		return (xdr_LOCKT4res(xdrs, &objp->nfs_resop4_u.oplockt));
4750 	case OP_LOCKU:
4751 		if (!xdr_int(xdrs,
4752 		    (int32_t *)&objp->nfs_resop4_u.oplocku.status))
4753 			return (FALSE);
4754 		if (objp->nfs_resop4_u.oplocku.status != NFS4_OK)
4755 			return (TRUE);
4756 		if (!xdr_u_int(xdrs,
4757 		    &objp->nfs_resop4_u.oplocku.lock_stateid.seqid))
4758 			return (FALSE);
4759 		return (xdr_opaque(xdrs,
4760 		    objp->nfs_resop4_u.oplocku.lock_stateid.other,
4761 		    NFS4_OTHER_SIZE));
4762 	case OP_NVERIFY:
4763 		return (xdr_int(xdrs,
4764 		    (int32_t *)&objp->nfs_resop4_u.opnverify.status));
4765 	case OP_OPENATTR:
4766 		return (xdr_int(xdrs,
4767 		    (int32_t *)&objp->nfs_resop4_u.opopenattr.status));
4768 	case OP_OPEN_CONFIRM:
4769 		return (xdr_OPEN_CONFIRM4res(xdrs,
4770 		    &objp->nfs_resop4_u.opopen_confirm));
4771 	case OP_OPEN_DOWNGRADE:
4772 		return (xdr_OPEN_DOWNGRADE4res(xdrs,
4773 		    &objp->nfs_resop4_u.opopen_downgrade));
4774 	case OP_PUTPUBFH:
4775 		return (xdr_int(xdrs,
4776 		    (int32_t *)&objp->nfs_resop4_u.opputpubfh.status));
4777 	case OP_PUTROOTFH:
4778 		return (xdr_int(xdrs,
4779 		    (int32_t *)&objp->nfs_resop4_u.opputrootfh.status));
4780 	case OP_READLINK:
4781 		return (xdr_READLINK4res(xdrs, &objp->nfs_resop4_u.opreadlink));
4782 	case OP_RENAME:
4783 		return (xdr_RENAME4res(xdrs, &objp->nfs_resop4_u.oprename));
4784 	case OP_RENEW:
4785 		return (xdr_int(xdrs,
4786 		    (int32_t *)&objp->nfs_resop4_u.oprenew.status));
4787 	case OP_RESTOREFH:
4788 		return (xdr_int(xdrs,
4789 		    (int32_t *)&objp->nfs_resop4_u.oprestorefh.status));
4790 	case OP_SAVEFH:
4791 		return (xdr_int(xdrs,
4792 		    (int32_t *)&objp->nfs_resop4_u.opsavefh.status));
4793 	case OP_SECINFO:
4794 		if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsecinfo.
4795 		    status))
4796 			return (FALSE);
4797 		if (objp->nfs_resop4_u.opsecinfo.status != NFS4_OK)
4798 			return (TRUE);
4799 		return (xdr_array(xdrs, (char **)&objp->nfs_resop4_u.opsecinfo.
4800 		    SECINFO4resok_val,
4801 		    (uint_t *)&objp->nfs_resop4_u.opsecinfo.
4802 		    SECINFO4resok_len,
4803 		    NFS4_SECINFO_LIMIT, sizeof (secinfo4),
4804 		    (xdrproc_t)xdr_secinfo4));
4805 	case OP_SETATTR:
4806 		if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsetattr.
4807 		    status))
4808 			return (FALSE);
4809 		return (xdr_bitmap4(xdrs,
4810 		    &objp->nfs_resop4_u.opsetattr.attrsset));
4811 	case OP_SETCLIENTID:
4812 		return (xdr_SETCLIENTID4res(xdrs,
4813 		    &objp->nfs_resop4_u.opsetclientid));
4814 	case OP_SETCLIENTID_CONFIRM:
4815 		return (xdr_int(xdrs,
4816 		    (int32_t *)&objp->nfs_resop4_u.opsetclientid_confirm.
4817 		    status));
4818 	case OP_VERIFY:
4819 		return (xdr_int(xdrs,
4820 		    (int32_t *)&objp->nfs_resop4_u.opverify.status));
4821 	case OP_RELEASE_LOCKOWNER:
4822 		return (xdr_int(xdrs,
4823 		    (int32_t *)&objp->nfs_resop4_u.oprelease_lockowner.status));
4824 	case OP_ILLEGAL:
4825 		return (xdr_int(xdrs,
4826 		    (int32_t *)&objp->nfs_resop4_u.opillegal.status));
4827 	}
4828 	return (FALSE);
4829 }
4830 
4831 static bool_t
xdr_snfs_resop4(XDR * xdrs,nfs_resop4 * objp)4832 xdr_snfs_resop4(XDR *xdrs, nfs_resop4 *objp)
4833 {
4834 	if (!xdr_int(xdrs, (int *)&objp->resop))
4835 		return (FALSE);
4836 
4837 	switch (objp->resop) {
4838 	case OP_GETFH:
4839 		if (!XDR_PUTINT32(xdrs,
4840 		    (int32_t *)&objp->nfs_resop4_u.opgetfh.status))
4841 			return (FALSE);
4842 		if (objp->nfs_resop4_u.opgetfh.status != NFS4_OK)
4843 			return (TRUE);
4844 		return (xdr_encode_nfs_fh4(xdrs,
4845 		    &objp->nfs_resop4_u.opgetfh.object));
4846 	default:
4847 		if (objp->resop >= OP_BACKCHANNEL_CTL &&
4848 		    objp->resop != OP_ILLEGAL)
4849 			return (xdr_nfs4x_resop4(xdrs, objp));
4850 
4851 		return (xdr_nfs_resop4(xdrs, objp));
4852 	}
4853 }
4854 
4855 static bool_t
xdr_nfs_resop4_clnt(XDR * xdrs,nfs_resop4 * objp,nfs_argop4 * aobjp)4856 xdr_nfs_resop4_clnt(XDR *xdrs, nfs_resop4 *objp, nfs_argop4 *aobjp)
4857 {
4858 	if (!xdr_int(xdrs, (int *)&objp->resop))
4859 		return (FALSE);
4860 	/*
4861 	 * These should be ordered by frequency of use
4862 	 */
4863 	switch (objp->resop) {
4864 	case OP_PUTFH:
4865 		return (xdr_int(xdrs,
4866 		    (int32_t *)&objp->nfs_resop4_u.opputfh.status));
4867 	case OP_GETATTR:
4868 		if (!xdr_int(xdrs,
4869 		    (int32_t *)&objp->nfs_resop4_u.opgetattr.status))
4870 			return (FALSE);
4871 		if (objp->nfs_resop4_u.opgetattr.status != NFS4_OK)
4872 			return (TRUE);
4873 		return (xdr_ga_res(xdrs,
4874 		    (GETATTR4res *)&objp->nfs_resop4_u.opgetattr,
4875 		    &aobjp->nfs_argop4_u.opgetattr));
4876 	case OP_GETFH:
4877 		if (!xdr_int(xdrs,
4878 		    (int32_t *)&objp->nfs_resop4_u.opgetfh.status))
4879 			return (FALSE);
4880 		if (objp->nfs_resop4_u.opgetfh.status != NFS4_OK)
4881 			return (TRUE);
4882 		return (xdr_bytes(xdrs,
4883 		    (char **)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_val,
4884 		    (uint_t *)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_len,
4885 		    NFS4_FHSIZE));
4886 	case OP_LOOKUP:
4887 		return (xdr_int(xdrs,
4888 		    (int32_t *)&objp->nfs_resop4_u.oplookup.status));
4889 	case OP_NVERIFY:
4890 		return (xdr_int(xdrs,
4891 		    (int32_t *)&objp->nfs_resop4_u.opnverify.status));
4892 	case OP_OPEN:
4893 		return (xdr_OPEN4res(xdrs, &objp->nfs_resop4_u.opopen));
4894 	case OP_CLOSE:
4895 		return (xdr_CLOSE4res(xdrs, &objp->nfs_resop4_u.opclose));
4896 	case OP_ACCESS:
4897 		return (xdr_ACCESS4res(xdrs, &objp->nfs_resop4_u.opaccess));
4898 	case OP_READ:
4899 		return (xdr_READ4res_clnt(xdrs, &objp->nfs_resop4_u.opread,
4900 		    &aobjp->nfs_argop4_u.opread));
4901 	case OP_WRITE:
4902 		return (xdr_WRITE4res(xdrs, &objp->nfs_resop4_u.opwrite));
4903 	case OP_DELEGRETURN:
4904 		return (xdr_int(xdrs,
4905 		    (int32_t *)&objp->nfs_resop4_u.opdelegreturn.status));
4906 	case OP_LOOKUPP:
4907 		return (xdr_int(xdrs,
4908 		    (int32_t *)&objp->nfs_resop4_u.oplookupp.status));
4909 	case OP_READDIR:
4910 		return (xdr_READDIR4res_clnt(xdrs,
4911 		    &objp->nfs_resop4_u.opreaddirclnt,
4912 		    &aobjp->nfs_argop4_u.opreaddir));
4913 	case OP_REMOVE:
4914 		return (xdr_REMOVE4res(xdrs, &objp->nfs_resop4_u.opremove));
4915 
4916 	case OP_COMMIT:
4917 		if (!xdr_int(xdrs,
4918 		    (int32_t *)&objp->nfs_resop4_u.opcommit.status))
4919 			return (FALSE);
4920 		if (objp->nfs_resop4_u.opcommit.status != NFS4_OK)
4921 			return (TRUE);
4922 		return (xdr_u_longlong_t(xdrs,
4923 		    (u_longlong_t *)&objp->nfs_resop4_u.opcommit.
4924 		    writeverf));
4925 	case OP_CREATE:
4926 		return (xdr_CREATE4res(xdrs, &objp->nfs_resop4_u.opcreate));
4927 	case OP_DELEGPURGE:
4928 		return (xdr_int(xdrs,
4929 		    (int32_t *)&objp->nfs_resop4_u.opdelegpurge.status));
4930 	case OP_LINK:
4931 		return (xdr_LINK4res(xdrs, &objp->nfs_resop4_u.oplink));
4932 	case OP_LOCK:
4933 		return (xdr_LOCK4res(xdrs, &objp->nfs_resop4_u.oplock));
4934 	case OP_LOCKT:
4935 		return (xdr_LOCKT4res(xdrs, &objp->nfs_resop4_u.oplockt));
4936 	case OP_LOCKU:
4937 		if (!xdr_int(xdrs,
4938 		    (int32_t *)&objp->nfs_resop4_u.oplocku.status))
4939 			return (FALSE);
4940 		if (objp->nfs_resop4_u.oplocku.status != NFS4_OK)
4941 			return (TRUE);
4942 		if (!xdr_u_int(xdrs,
4943 		    &objp->nfs_resop4_u.oplocku.lock_stateid.seqid))
4944 			return (FALSE);
4945 		return (xdr_opaque(xdrs,
4946 		    objp->nfs_resop4_u.oplocku.lock_stateid.other,
4947 		    NFS4_OTHER_SIZE));
4948 	case OP_OPENATTR:
4949 		return (xdr_int(xdrs,
4950 		    (int32_t *)&objp->nfs_resop4_u.opopenattr.status));
4951 	case OP_OPEN_CONFIRM:
4952 		return (xdr_OPEN_CONFIRM4res(xdrs,
4953 		    &objp->nfs_resop4_u.opopen_confirm));
4954 	case OP_OPEN_DOWNGRADE:
4955 		return (xdr_OPEN_DOWNGRADE4res(xdrs,
4956 		    &objp->nfs_resop4_u.opopen_downgrade));
4957 	case OP_PUTPUBFH:
4958 		return (xdr_int(xdrs,
4959 		    (int32_t *)&objp->nfs_resop4_u.opputpubfh.status));
4960 	case OP_PUTROOTFH:
4961 		return (xdr_int(xdrs,
4962 		    (int32_t *)&objp->nfs_resop4_u.opputrootfh.status));
4963 	case OP_READLINK:
4964 		return (xdr_READLINK4res(xdrs, &objp->nfs_resop4_u.opreadlink));
4965 	case OP_RENAME:
4966 		return (xdr_RENAME4res(xdrs, &objp->nfs_resop4_u.oprename));
4967 	case OP_RENEW:
4968 		return (xdr_int(xdrs,
4969 		    (int32_t *)&objp->nfs_resop4_u.oprenew.status));
4970 	case OP_RESTOREFH:
4971 		return (xdr_int(xdrs,
4972 		    (int32_t *)&objp->nfs_resop4_u.oprestorefh.status));
4973 	case OP_SAVEFH:
4974 		return (xdr_int(xdrs,
4975 		    (int32_t *)&objp->nfs_resop4_u.opsavefh.status));
4976 	case OP_SECINFO:
4977 		if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsecinfo.
4978 		    status))
4979 			return (FALSE);
4980 		if (objp->nfs_resop4_u.opsecinfo.status != NFS4_OK)
4981 			return (TRUE);
4982 		return (xdr_array(xdrs, (char **)&objp->nfs_resop4_u.opsecinfo.
4983 		    SECINFO4resok_val,
4984 		    (uint_t *)&objp->nfs_resop4_u.opsecinfo.
4985 		    SECINFO4resok_len,
4986 		    ~0, sizeof (secinfo4), (xdrproc_t)xdr_secinfo4));
4987 	case OP_SETATTR:
4988 		if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsetattr.
4989 		    status))
4990 			return (FALSE);
4991 		return (xdr_bitmap4(xdrs,
4992 		    &objp->nfs_resop4_u.opsetattr.attrsset));
4993 	case OP_SETCLIENTID:
4994 		return (xdr_SETCLIENTID4res(xdrs,
4995 		    &objp->nfs_resop4_u.opsetclientid));
4996 	case OP_SETCLIENTID_CONFIRM:
4997 		return (xdr_int(xdrs,
4998 		    (int32_t *)&objp->nfs_resop4_u.opsetclientid_confirm.
4999 		    status));
5000 	case OP_VERIFY:
5001 		return (xdr_int(xdrs,
5002 		    (int32_t *)&objp->nfs_resop4_u.opverify.status));
5003 	case OP_RELEASE_LOCKOWNER:
5004 		return (xdr_int(xdrs,
5005 		    (int32_t *)&objp->nfs_resop4_u.oprelease_lockowner.status));
5006 	case OP_ILLEGAL:
5007 		return (xdr_int(xdrs,
5008 		    (int32_t *)&objp->nfs_resop4_u.opillegal.status));
5009 	}
5010 	return (FALSE);
5011 }
5012 
5013 bool_t
xdr_COMPOUND4args_clnt(XDR * xdrs,COMPOUND4args_clnt * objp)5014 xdr_COMPOUND4args_clnt(XDR *xdrs, COMPOUND4args_clnt *objp)
5015 {
5016 	static int32_t twelve = 12;
5017 	static int32_t minorversion = NFS4_MINORVERSION;
5018 	uint32_t *ctagp;
5019 	rpc_inline_t *ptr;
5020 	rdma_chunkinfo_t rci;
5021 	struct xdr_ops *xops = xdrrdma_xops();
5022 
5023 	/*
5024 	 * XDR_ENCODE only
5025 	 */
5026 	if (xdrs->x_op == XDR_FREE)
5027 		return (TRUE);
5028 	if (xdrs->x_op == XDR_DECODE)
5029 		return (FALSE);
5030 
5031 	ctagp = (uint32_t *)&nfs4_ctags[objp->ctag].ct_tag;
5032 
5033 	if ((ptr = XDR_INLINE(xdrs, 5 * BYTES_PER_XDR_UNIT)) != NULL) {
5034 		/*
5035 		 * Efficiently encode fixed length tags, could be longlongs
5036 		 * but 8 byte XDR alignment not assured
5037 		 */
5038 		IXDR_PUT_U_INT32(ptr, 12);
5039 		IXDR_PUT_U_INT32(ptr, ctagp[0]);
5040 		IXDR_PUT_U_INT32(ptr, ctagp[1]);
5041 		IXDR_PUT_U_INT32(ptr, ctagp[2]);
5042 
5043 		/*
5044 		 * Fixed minor version for now
5045 		 */
5046 		IXDR_PUT_U_INT32(ptr, NFS4_MINORVERSION);
5047 	} else {
5048 		if (!XDR_PUTINT32(xdrs, &twelve))
5049 			return (FALSE);
5050 		if (!XDR_PUTINT32(xdrs, (int32_t *)&ctagp[0]))
5051 			return (FALSE);
5052 		if (!XDR_PUTINT32(xdrs, (int32_t *)&ctagp[1]))
5053 			return (FALSE);
5054 		if (!XDR_PUTINT32(xdrs, (int32_t *)&ctagp[2]))
5055 			return (FALSE);
5056 		if (!XDR_PUTINT32(xdrs, (int32_t *)&minorversion))
5057 			return (FALSE);
5058 	}
5059 	if (xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) {
5060 		rci.rci_type = RCI_REPLY_CHUNK;
5061 		rci.rci_len = MAXPATHLEN * 2;
5062 		XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
5063 	}
5064 
5065 	return (xdr_array(xdrs, (char **)&objp->array,
5066 	    (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
5067 	    sizeof (nfs_argop4), (xdrproc_t)xdr_cnfs_argop4));
5068 }
5069 
5070 bool_t
xdr_COMPOUND4args_srv(XDR * xdrs,COMPOUND4args * objp)5071 xdr_COMPOUND4args_srv(XDR *xdrs, COMPOUND4args *objp)
5072 {
5073 	if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val,
5074 	    (uint_t *)&objp->tag.utf8string_len,
5075 	    NFS4_MAX_UTF8STRING))
5076 		return (FALSE);
5077 	if (!xdr_u_int(xdrs, &objp->minorversion))
5078 		return (FALSE);
5079 	if (xdrs->x_op != XDR_FREE)
5080 		return (xdr_array(xdrs, (char **)&objp->array,
5081 		    (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
5082 		    sizeof (nfs_argop4), (xdrproc_t)xdr_snfs_argop4));
5083 
5084 	return (xdr_snfs_argop4_free(xdrs, &objp->array, objp->array_len));
5085 }
5086 
5087 bool_t
xdr_COMPOUND4res_clnt(XDR * xdrs,COMPOUND4res_clnt * objp)5088 xdr_COMPOUND4res_clnt(XDR *xdrs, COMPOUND4res_clnt *objp)
5089 {
5090 	uint32_t len;
5091 	int32_t *ptr;
5092 	nfs_argop4 *argop;
5093 	nfs_resop4 *resop;
5094 
5095 	/*
5096 	 * No XDR_ENCODE
5097 	 */
5098 	if (xdrs->x_op == XDR_ENCODE)
5099 		return (FALSE);
5100 
5101 	if (xdrs->x_op != XDR_FREE) {
5102 		if ((ptr = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT)) != NULL) {
5103 			objp->status = IXDR_GET_U_INT32(ptr);
5104 			len = IXDR_GET_U_INT32(ptr);
5105 		} else {
5106 			if (!xdr_int(xdrs, (int32_t *)&objp->status))
5107 				return (FALSE);
5108 			if (!xdr_u_int(xdrs, (uint32_t *)&len))
5109 				return (FALSE);
5110 		}
5111 		if (len > NFS4_MAX_UTF8STRING)
5112 			return (FALSE);
5113 		/*
5114 		 * Ignore the tag
5115 		 */
5116 		if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &len))
5117 			return (FALSE);
5118 
5119 		if (!xdr_int(xdrs, (int32_t *)&objp->array_len))
5120 			return (FALSE);
5121 
5122 		if (objp->array_len > objp->argsp->array_len)
5123 			return (FALSE);
5124 
5125 		if (objp->status == NFS4_OK &&
5126 		    objp->array_len != objp->argsp->array_len)
5127 			return (FALSE);
5128 
5129 		/* Alloc the results array */
5130 		argop = objp->argsp->array;
5131 		len = objp->array_len * sizeof (nfs_resop4);
5132 		objp->decode_len = 0;
5133 		objp->array = resop = kmem_zalloc(len, KM_SLEEP);
5134 
5135 		for (len = 0; len < objp->array_len;
5136 		    len++, resop++, argop++, objp->decode_len++) {
5137 			if (!xdr_nfs_resop4_clnt(xdrs, resop, argop)) {
5138 				/*
5139 				 * Make sure to free anything that may
5140 				 * have been allocated along the way.
5141 				 */
5142 				xdrs->x_op = XDR_FREE;
5143 				(void) xdr_nfs_resop4_free(xdrs, &objp->array,
5144 				    objp->array_len,
5145 				    objp->decode_len);
5146 				return (FALSE);
5147 			}
5148 		}
5149 		return (TRUE);
5150 	}
5151 	return (xdr_nfs_resop4_free(xdrs, &objp->array,
5152 	    objp->array_len, objp->decode_len));
5153 }
5154 
5155 bool_t
xdr_COMPOUND4res_srv(XDR * xdrs,COMPOUND4res * objp)5156 xdr_COMPOUND4res_srv(XDR *xdrs, COMPOUND4res *objp)
5157 {
5158 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
5159 		return (FALSE);
5160 	if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val,
5161 	    (uint_t *)&objp->tag.utf8string_len,
5162 	    NFS4_MAX_UTF8STRING))
5163 		return (FALSE);
5164 
5165 	if (xdrs->x_op != XDR_FREE)
5166 		return (xdr_array(xdrs, (char **)&objp->array,
5167 		    (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
5168 		    sizeof (nfs_resop4), (xdrproc_t)xdr_snfs_resop4));
5169 
5170 	return (xdr_snfs_resop4_free(xdrs, &objp->array,
5171 	    objp->array_len, objp->array_len));
5172 }
5173 
5174 /*
5175  * NFS server side callback, initiating the callback request so it
5176  * is the RPC client. Must convert from server's internal filehandle
5177  * format to wire format.
5178  */
5179 static bool_t
xdr_snfs_cb_argop4(XDR * xdrs,nfs_cb_argop4 * objp)5180 xdr_snfs_cb_argop4(XDR *xdrs, nfs_cb_argop4 *objp)
5181 {
5182 	CB_GETATTR4args *gargs;
5183 	CB_RECALL4args *rargs;
5184 
5185 	ASSERT(xdrs->x_op == XDR_ENCODE);
5186 
5187 	if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->argop))
5188 		return (FALSE);
5189 
5190 	switch (objp->argop) {
5191 	case OP_CB_GETATTR:
5192 		gargs = &objp->nfs_cb_argop4_u.opcbgetattr;
5193 
5194 		if (!xdr_encode_nfs_fh4(xdrs, &gargs->fh))
5195 			return (FALSE);
5196 		return (xdr_bitmap4(xdrs, &gargs->attr_request));
5197 	case OP_CB_RECALL:
5198 		rargs = &objp->nfs_cb_argop4_u.opcbrecall;
5199 
5200 		if (!XDR_PUTINT32(xdrs, (int32_t *)&rargs->stateid.seqid))
5201 			return (FALSE);
5202 		if (!xdr_opaque(xdrs, rargs->stateid.other, NFS4_OTHER_SIZE))
5203 			return (FALSE);
5204 		if (!XDR_PUTINT32(xdrs, (int32_t *)&rargs->truncate))
5205 			return (FALSE);
5206 		return (xdr_encode_nfs_fh4(xdrs, &rargs->fh));
5207 	case OP_CB_ILLEGAL:
5208 		return (TRUE);
5209 	}
5210 	return (FALSE);
5211 }
5212 
5213 /*
5214  * NFS client side callback, receiving the callback request so it
5215  * is the RPC server. Must treat the file handles as opaque.
5216  */
5217 static bool_t
xdr_cnfs_cb_argop4(XDR * xdrs,nfs_cb_argop4 * objp)5218 xdr_cnfs_cb_argop4(XDR *xdrs, nfs_cb_argop4 *objp)
5219 {
5220 	CB_GETATTR4args *gargs;
5221 	CB_RECALL4args *rargs;
5222 
5223 	ASSERT(xdrs->x_op != XDR_ENCODE);
5224 
5225 	if (!xdr_u_int(xdrs, &objp->argop))
5226 		return (FALSE);
5227 	switch (objp->argop) {
5228 	case OP_CB_GETATTR:
5229 		gargs = &objp->nfs_cb_argop4_u.opcbgetattr;
5230 
5231 		if (!xdr_bytes(xdrs, (char **)&gargs->fh.nfs_fh4_val,
5232 		    (uint_t *)&gargs->fh.nfs_fh4_len, NFS4_FHSIZE))
5233 			return (FALSE);
5234 		return (xdr_bitmap4(xdrs, &gargs->attr_request));
5235 	case OP_CB_RECALL:
5236 		rargs = &objp->nfs_cb_argop4_u.opcbrecall;
5237 
5238 		if (!xdr_u_int(xdrs, &rargs->stateid.seqid))
5239 			return (FALSE);
5240 		if (!xdr_opaque(xdrs, rargs->stateid.other, NFS4_OTHER_SIZE))
5241 			return (FALSE);
5242 		if (!xdr_bool(xdrs, &rargs->truncate))
5243 			return (FALSE);
5244 		return (xdr_bytes(xdrs, (char **)&rargs->fh.nfs_fh4_val,
5245 		    (uint_t *)&rargs->fh.nfs_fh4_len, NFS4_FHSIZE));
5246 	case OP_CB_ILLEGAL:
5247 		return (TRUE);
5248 	}
5249 	return (FALSE);
5250 }
5251 
5252 /*
5253  * The NFS client side callback, RPC server
5254  */
5255 bool_t
xdr_CB_COMPOUND4args_clnt(XDR * xdrs,CB_COMPOUND4args * objp)5256 xdr_CB_COMPOUND4args_clnt(XDR *xdrs, CB_COMPOUND4args *objp)
5257 {
5258 	if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val,
5259 	    (uint_t *)&objp->tag.utf8string_len,
5260 	    NFS4_MAX_UTF8STRING))
5261 		return (FALSE);
5262 	if (!xdr_u_int(xdrs, &objp->minorversion))
5263 		return (FALSE);
5264 	if (!xdr_u_int(xdrs, &objp->callback_ident))
5265 		return (FALSE);
5266 	return (xdr_array(xdrs, (char **)&objp->array,
5267 	    (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
5268 	    sizeof (nfs_cb_argop4), (xdrproc_t)xdr_cnfs_cb_argop4));
5269 }
5270 
5271 /*
5272  * The NFS server side callback, RPC client
5273  */
5274 bool_t
xdr_CB_COMPOUND4args_srv(XDR * xdrs,CB_COMPOUND4args * objp)5275 xdr_CB_COMPOUND4args_srv(XDR *xdrs, CB_COMPOUND4args *objp)
5276 {
5277 	if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val,
5278 	    (uint_t *)&objp->tag.utf8string_len,
5279 	    NFS4_MAX_UTF8STRING))
5280 		return (FALSE);
5281 	if (!xdr_u_int(xdrs, &objp->minorversion))
5282 		return (FALSE);
5283 	if (!xdr_u_int(xdrs, &objp->callback_ident))
5284 		return (FALSE);
5285 	return (xdr_array(xdrs, (char **)&objp->array,
5286 	    (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
5287 	    sizeof (nfs_cb_argop4), (xdrproc_t)xdr_snfs_cb_argop4));
5288 }
5289 
5290 bool_t
xdr_CB_COMPOUND4res(XDR * xdrs,CB_COMPOUND4res * objp)5291 xdr_CB_COMPOUND4res(XDR *xdrs, CB_COMPOUND4res *objp)
5292 {
5293 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
5294 		return (FALSE);
5295 	if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val,
5296 	    (uint_t *)&objp->tag.utf8string_len,
5297 	    NFS4_MAX_UTF8STRING))
5298 		return (FALSE);
5299 	return (xdr_array(xdrs, (char **)&objp->array,
5300 	    (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
5301 	    sizeof (nfs_cb_resop4), (xdrproc_t)xdr_nfs_cb_resop4));
5302 }
5303