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