xref: /illumos-gate/usr/src/uts/common/fs/nfs/nfs4_xdr.c (revision f7877f5d)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
24  */
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, ug_cache_t *pug)
1548 {
1549 	int truefalse;
1550 	struct nfs4_ga_ext_res ges, *gesp;
1551 	vattr_t *vap = &garp->n4g_va;
1552 
1553 	if (garp->n4g_ext_res)
1554 		gesp = garp->n4g_ext_res;
1555 	else
1556 		gesp = &ges;
1557 
1558 	vap->va_mask = 0;
1559 
1560 	/* Check to see if the vattr should be pre-filled */
1561 	if (argbmap & NFS4_VATTR_MASK)
1562 		xdr_ga_prefill_vattr(garp, mi);
1563 
1564 	if (argbmap & NFS4_STATFS_ATTR_MASK)
1565 		xdr_ga_prefill_statvfs(gesp, mi);
1566 
1567 	if (resbmap &
1568 	    (FATTR4_SUPPORTED_ATTRS_MASK |
1569 	    FATTR4_TYPE_MASK |
1570 	    FATTR4_FH_EXPIRE_TYPE_MASK |
1571 	    FATTR4_CHANGE_MASK |
1572 	    FATTR4_SIZE_MASK |
1573 	    FATTR4_LINK_SUPPORT_MASK |
1574 	    FATTR4_SYMLINK_SUPPORT_MASK |
1575 	    FATTR4_NAMED_ATTR_MASK)) {
1576 
1577 		if (resbmap & FATTR4_SUPPORTED_ATTRS_MASK) {
1578 			gesp->n4g_suppattrs = xdr_get_bitmap4_inline(&ptr);
1579 		}
1580 		if (resbmap & FATTR4_TYPE_MASK) {
1581 			vap->va_type = IXDR_GET_U_INT32(ptr);
1582 
1583 			if ((nfs_ftype4)vap->va_type < NF4REG ||
1584 			    (nfs_ftype4)vap->va_type > NF4NAMEDATTR)
1585 				vap->va_type = VBAD;
1586 			else
1587 				vap->va_type = nf4_to_vt[vap->va_type];
1588 			if (vap->va_type == VBLK)
1589 				vap->va_blksize = DEV_BSIZE;
1590 
1591 			vap->va_mask |= AT_TYPE;
1592 		}
1593 		if (resbmap & FATTR4_FH_EXPIRE_TYPE_MASK) {
1594 			gesp->n4g_fet = IXDR_GET_U_INT32(ptr);
1595 		}
1596 		if (resbmap & FATTR4_CHANGE_MASK) {
1597 			IXDR_GET_U_HYPER(ptr, garp->n4g_change);
1598 			garp->n4g_change_valid = 1;
1599 		}
1600 		if (resbmap & FATTR4_SIZE_MASK) {
1601 			IXDR_GET_U_HYPER(ptr, vap->va_size);
1602 
1603 			if (!NFS4_SIZE_OK(vap->va_size)) {
1604 				garp->n4g_attrerr = EFBIG;
1605 				garp->n4g_attrwhy = NFS4_GETATTR_ATSIZE_ERR;
1606 			} else {
1607 				vap->va_mask |= AT_SIZE;
1608 			}
1609 		}
1610 		if (resbmap & FATTR4_LINK_SUPPORT_MASK) {
1611 			truefalse = IXDR_GET_U_INT32(ptr);
1612 			gesp->n4g_pc4.pc4_link_support =
1613 			    (truefalse ? TRUE : FALSE);
1614 		}
1615 		if (resbmap & FATTR4_SYMLINK_SUPPORT_MASK) {
1616 			truefalse = IXDR_GET_U_INT32(ptr);
1617 			gesp->n4g_pc4.pc4_symlink_support =
1618 			    (truefalse ? TRUE : FALSE);
1619 		}
1620 		if (resbmap & FATTR4_NAMED_ATTR_MASK) {
1621 			truefalse = IXDR_GET_U_INT32(ptr);
1622 			gesp->n4g_pc4.pc4_xattr_exists = TRUE;
1623 			gesp->n4g_pc4.pc4_xattr_exists =
1624 			    (truefalse ? TRUE : FALSE);
1625 		}
1626 	}
1627 	if (resbmap &
1628 	    (FATTR4_FSID_MASK |
1629 	    FATTR4_UNIQUE_HANDLES_MASK |
1630 	    FATTR4_LEASE_TIME_MASK |
1631 	    FATTR4_RDATTR_ERROR_MASK)) {
1632 
1633 		if (resbmap & FATTR4_FSID_MASK) {
1634 			IXDR_GET_U_HYPER(ptr, garp->n4g_fsid.major);
1635 			IXDR_GET_U_HYPER(ptr, garp->n4g_fsid.minor);
1636 			garp->n4g_fsid_valid = 1;
1637 		}
1638 		if (resbmap & FATTR4_UNIQUE_HANDLES_MASK) {
1639 			truefalse = IXDR_GET_U_INT32(ptr);
1640 			gesp->n4g_pc4.pc4_unique_handles =
1641 			    (truefalse ? TRUE : FALSE);
1642 		}
1643 		if (resbmap & FATTR4_LEASE_TIME_MASK) {
1644 			gesp->n4g_leasetime = IXDR_GET_U_INT32(ptr);
1645 		}
1646 		if (resbmap & FATTR4_RDATTR_ERROR_MASK) {
1647 			gesp->n4g_rdattr_error = IXDR_GET_U_INT32(ptr);
1648 		}
1649 	}
1650 	if (resbmap &
1651 	    (FATTR4_ACL_MASK |
1652 	    FATTR4_ACLSUPPORT_MASK |
1653 	    FATTR4_ARCHIVE_MASK |
1654 	    FATTR4_CANSETTIME_MASK)) {
1655 
1656 		if (resbmap & FATTR4_ACL_MASK) {
1657 			ASSERT(0);
1658 		}
1659 		if (resbmap & FATTR4_ACLSUPPORT_MASK) {
1660 			gesp->n4g_aclsupport = IXDR_GET_U_INT32(ptr);
1661 		}
1662 		if (resbmap & FATTR4_ARCHIVE_MASK) {
1663 			ASSERT(0);
1664 		}
1665 		if (resbmap & FATTR4_CANSETTIME_MASK) {
1666 			truefalse = IXDR_GET_U_INT32(ptr);
1667 			gesp->n4g_pc4.pc4_cansettime =
1668 			    (truefalse ? TRUE : FALSE);
1669 		}
1670 	}
1671 	if (resbmap &
1672 	    (FATTR4_CASE_INSENSITIVE_MASK |
1673 	    FATTR4_CASE_PRESERVING_MASK |
1674 	    FATTR4_CHOWN_RESTRICTED_MASK |
1675 	    FATTR4_FILEHANDLE_MASK |
1676 	    FATTR4_FILEID_MASK |
1677 	    FATTR4_FILES_AVAIL_MASK |
1678 	    FATTR4_FILES_FREE_MASK |
1679 	    FATTR4_FILES_TOTAL_MASK)) {
1680 
1681 		if (resbmap & FATTR4_CASE_INSENSITIVE_MASK) {
1682 			truefalse = IXDR_GET_U_INT32(ptr);
1683 			gesp->n4g_pc4.pc4_case_insensitive =
1684 			    (truefalse ? TRUE : FALSE);
1685 		}
1686 		if (resbmap & FATTR4_CASE_PRESERVING_MASK) {
1687 			truefalse = IXDR_GET_U_INT32(ptr);
1688 			gesp->n4g_pc4.pc4_case_preserving =
1689 			    (truefalse ? TRUE : FALSE);
1690 		}
1691 		if (resbmap & FATTR4_CHOWN_RESTRICTED_MASK) {
1692 			truefalse = IXDR_GET_U_INT32(ptr);
1693 			gesp->n4g_pc4.pc4_chown_restricted =
1694 			    (truefalse ? TRUE : FALSE);
1695 		}
1696 		if (resbmap & FATTR4_FILEHANDLE_MASK) {
1697 			int len = IXDR_GET_U_INT32(ptr);
1698 
1699 			gesp->n4g_fh_u.nfs_fh4_alt.len = 0;
1700 			gesp->n4g_fh_u.nfs_fh4_alt.val =
1701 			    gesp->n4g_fh_u.nfs_fh4_alt.data;
1702 			gesp->n4g_fh_u.n4g_fh.nfs_fh4_len = len;
1703 
1704 			bcopy(ptr, gesp->n4g_fh_u.n4g_fh.nfs_fh4_val, len);
1705 
1706 			ptr += RNDUP(len) / BYTES_PER_XDR_UNIT;
1707 		}
1708 		if (resbmap & FATTR4_FILEID_MASK) {
1709 			IXDR_GET_U_HYPER(ptr, vap->va_nodeid);
1710 			vap->va_mask |= AT_NODEID;
1711 		}
1712 		if (resbmap & FATTR4_FILES_AVAIL_MASK) {
1713 			IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_favail);
1714 		}
1715 		if (resbmap & FATTR4_FILES_FREE_MASK) {
1716 			IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_ffree);
1717 		}
1718 		if (resbmap & FATTR4_FILES_TOTAL_MASK) {
1719 			IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_files);
1720 		}
1721 	}
1722 	if (resbmap &
1723 	    (FATTR4_FS_LOCATIONS_MASK |
1724 	    FATTR4_HIDDEN_MASK |
1725 	    FATTR4_HOMOGENEOUS_MASK)) {
1726 
1727 		if (resbmap & FATTR4_FS_LOCATIONS_MASK) {
1728 			ASSERT(0);
1729 		}
1730 		if (resbmap & FATTR4_HIDDEN_MASK) {
1731 			ASSERT(0);
1732 		}
1733 		if (resbmap & FATTR4_HOMOGENEOUS_MASK) {
1734 			truefalse = IXDR_GET_U_INT32(ptr);
1735 			gesp->n4g_pc4.pc4_homogeneous =
1736 			    (truefalse ? TRUE : FALSE);
1737 		}
1738 	}
1739 	if (resbmap &
1740 	    (FATTR4_MAXFILESIZE_MASK |
1741 	    FATTR4_MAXLINK_MASK |
1742 	    FATTR4_MAXNAME_MASK |
1743 	    FATTR4_MAXREAD_MASK |
1744 	    FATTR4_MAXWRITE_MASK)) {
1745 
1746 		if (resbmap & FATTR4_MAXFILESIZE_MASK) {
1747 			IXDR_GET_U_HYPER(ptr, gesp->n4g_maxfilesize);
1748 		}
1749 		if (resbmap & FATTR4_MAXLINK_MASK) {
1750 			gesp->n4g_pc4.pc4_link_max = IXDR_GET_U_INT32(ptr);
1751 		}
1752 		if (resbmap & FATTR4_MAXNAME_MASK) {
1753 			gesp->n4g_pc4.pc4_name_max = IXDR_GET_U_INT32(ptr);
1754 			gesp->n4g_sb.f_namemax = gesp->n4g_pc4.pc4_name_max;
1755 		}
1756 		if (resbmap & FATTR4_MAXREAD_MASK) {
1757 			IXDR_GET_U_HYPER(ptr, gesp->n4g_maxread);
1758 		}
1759 		if (resbmap & FATTR4_MAXWRITE_MASK) {
1760 			IXDR_GET_U_HYPER(ptr, gesp->n4g_maxwrite);
1761 		}
1762 	}
1763 	if (resbmap &
1764 	    (FATTR4_MIMETYPE_MASK |
1765 	    FATTR4_MODE_MASK |
1766 	    FATTR4_NO_TRUNC_MASK |
1767 	    FATTR4_NUMLINKS_MASK)) {
1768 
1769 		if (resbmap & FATTR4_MIMETYPE_MASK) {
1770 			ASSERT(0);
1771 		}
1772 		if (resbmap & FATTR4_MODE_MASK) {
1773 			vap->va_mode = IXDR_GET_U_INT32(ptr);
1774 			vap->va_mask |= AT_MODE;
1775 		}
1776 		if (resbmap & FATTR4_NO_TRUNC_MASK) {
1777 			truefalse = IXDR_GET_U_INT32(ptr);
1778 			gesp->n4g_pc4.pc4_no_trunc =
1779 			    (truefalse ? TRUE : FALSE);
1780 		}
1781 		if (resbmap & FATTR4_NUMLINKS_MASK) {
1782 			vap->va_nlink = IXDR_GET_U_INT32(ptr);
1783 			vap->va_mask |= AT_NLINK;
1784 		}
1785 	}
1786 	if (resbmap &
1787 	    (FATTR4_OWNER_MASK |
1788 	    FATTR4_OWNER_GROUP_MASK |
1789 	    FATTR4_QUOTA_AVAIL_HARD_MASK |
1790 	    FATTR4_QUOTA_AVAIL_SOFT_MASK)) {
1791 
1792 		if (resbmap & FATTR4_OWNER_MASK) {
1793 			uint_t *owner_length, ol;
1794 			char *owner_val = NULL;
1795 			utf8string ov;
1796 			int error;
1797 
1798 			/* get the OWNER_LENGTH */
1799 			ol = IXDR_GET_U_INT32(ptr);
1800 
1801 			/* Manage the owner length location */
1802 			if (pug && ol <= MAX_OG_NAME) {
1803 				owner_length = &pug->u_curr.utf8string_len;
1804 				*owner_length = ol;
1805 			} else {
1806 				owner_length = &ol;
1807 			}
1808 
1809 			/* find memory to store the decode */
1810 			if (*owner_length > MAX_OG_NAME || pug == NULL)
1811 				owner_val = (char *)ptr;
1812 			else
1813 				owner_val = (char *)ptr;
1814 
1815 			/* Optimize for matching if called for */
1816 			if (pug &&
1817 			    *owner_length == pug->u_last.utf8string_len &&
1818 			    bcmp(owner_val, pug->u_last.utf8string_val,
1819 			    *owner_length) == 0) {
1820 				vap->va_uid = pug->uid;
1821 				vap->va_mask |= AT_UID;
1822 			} else {
1823 				uid_t uid;
1824 
1825 				ov.utf8string_len = *owner_length;
1826 				ov.utf8string_val = owner_val;
1827 				error = nfs_idmap_str_uid(&ov, &uid, FALSE);
1828 				/*
1829 				 * String was mapped, but to nobody because
1830 				 * we are nfsmapid, indicate it should not
1831 				 * be cached.
1832 				 */
1833 				if (error == ENOTSUP) {
1834 					error = 0;
1835 					garp->n4g_attrwhy =
1836 					    NFS4_GETATTR_NOCACHE_OK;
1837 				}
1838 
1839 				if (error) {
1840 					garp->n4g_attrerr = error;
1841 					garp->n4g_attrwhy =
1842 					    NFS4_GETATTR_ATUID_ERR;
1843 				} else {
1844 					vap->va_uid = uid;
1845 					vap->va_mask |= AT_UID;
1846 					/* save the results for next time */
1847 					if (pug && ol <= MAX_OG_NAME) {
1848 						pug->uid = uid;
1849 						pug->u_curr.utf8string_len =
1850 						    ov.utf8string_len;
1851 						bcopy(owner_val,
1852 						    pug->u_curr.utf8string_val,
1853 						    ol);
1854 						U_SWAP_CURR_LAST(pug);
1855 					}
1856 				}
1857 			}
1858 			ptr += RNDUP(ol) / BYTES_PER_XDR_UNIT;
1859 		}
1860 		if (resbmap & FATTR4_OWNER_GROUP_MASK) {
1861 			uint_t *group_length, gl;
1862 			char *group_val = NULL;
1863 			utf8string gv;
1864 			int error;
1865 
1866 			/* get the OWNER_GROUP_LENGTH */
1867 			gl = IXDR_GET_U_INT32(ptr);
1868 
1869 			/* Manage the group length location */
1870 			if (pug && gl <= MAX_OG_NAME) {
1871 				group_length = &pug->g_curr.utf8string_len;
1872 				*group_length = gl;
1873 			} else {
1874 				group_length = &gl;
1875 			}
1876 
1877 			/* find memory to store the decode */
1878 			if (*group_length > MAX_OG_NAME || pug == NULL)
1879 				group_val = (char *)ptr;
1880 			else
1881 				group_val = (char *)ptr;
1882 
1883 			/* Optimize for matching if called for */
1884 			if (pug &&
1885 			    *group_length == pug->g_last.utf8string_len &&
1886 			    bcmp(group_val, pug->g_last.utf8string_val,
1887 			    *group_length) == 0) {
1888 				vap->va_gid = pug->gid;
1889 				vap->va_mask |= AT_GID;
1890 			} else {
1891 				uid_t gid;
1892 
1893 				gv.utf8string_len = *group_length;
1894 				gv.utf8string_val = group_val;
1895 				error = nfs_idmap_str_gid(&gv, &gid, FALSE);
1896 				/*
1897 				 * String was mapped, but to nobody because
1898 				 * we are nfsmapid, indicate it should not
1899 				 * be cached.
1900 				 */
1901 				if (error == ENOTSUP) {
1902 					error = 0;
1903 					garp->n4g_attrwhy =
1904 					    NFS4_GETATTR_NOCACHE_OK;
1905 				}
1906 
1907 				if (error) {
1908 					garp->n4g_attrerr = error;
1909 					garp->n4g_attrwhy =
1910 					    NFS4_GETATTR_ATGID_ERR;
1911 				} else {
1912 					vap->va_gid = gid;
1913 					vap->va_mask |= AT_GID;
1914 					if (pug && gl <= MAX_OG_NAME) {
1915 						pug->gid = gid;
1916 						pug->g_curr.utf8string_len =
1917 						    gv.utf8string_len;
1918 						bcopy(group_val,
1919 						    pug->g_curr.utf8string_val,
1920 						    gl);
1921 						G_SWAP_CURR_LAST(pug);
1922 					}
1923 				}
1924 			}
1925 			ptr += RNDUP(gl) / BYTES_PER_XDR_UNIT;
1926 		}
1927 		if (resbmap & FATTR4_QUOTA_AVAIL_HARD_MASK) {
1928 			ASSERT(0);
1929 		}
1930 		if (resbmap & FATTR4_QUOTA_AVAIL_SOFT_MASK) {
1931 			ASSERT(0);
1932 		}
1933 	}
1934 	if (resbmap &
1935 	    (FATTR4_QUOTA_USED_MASK |
1936 	    FATTR4_SPACE_AVAIL_MASK |
1937 	    FATTR4_SPACE_FREE_MASK |
1938 	    FATTR4_SPACE_TOTAL_MASK |
1939 	    FATTR4_SPACE_USED_MASK |
1940 	    FATTR4_SYSTEM_MASK)) {
1941 
1942 		if (resbmap & FATTR4_QUOTA_USED_MASK) {
1943 			ASSERT(0);
1944 		}
1945 		if (resbmap & FATTR4_RAWDEV_MASK) {
1946 			fattr4_rawdev rawdev;
1947 
1948 			rawdev.specdata1 = IXDR_GET_U_INT32(ptr);
1949 			rawdev.specdata2 = IXDR_GET_U_INT32(ptr);
1950 
1951 			if (vap->va_type == VCHR || vap->va_type == VBLK) {
1952 				vap->va_rdev = makedevice(rawdev.specdata1,
1953 				    rawdev.specdata2);
1954 			} else {
1955 				vap->va_rdev = 0;
1956 			}
1957 			vap->va_mask |= AT_RDEV;
1958 		}
1959 		if (resbmap & FATTR4_SPACE_AVAIL_MASK) {
1960 			IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_bavail);
1961 			gesp->n4g_sb.f_bavail /= DEV_BSIZE;
1962 		}
1963 		if (resbmap & FATTR4_SPACE_FREE_MASK) {
1964 			IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_bfree);
1965 			gesp->n4g_sb.f_bfree /= DEV_BSIZE;
1966 		}
1967 		if (resbmap & FATTR4_SPACE_TOTAL_MASK) {
1968 			IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_blocks);
1969 			gesp->n4g_sb.f_blocks /= DEV_BSIZE;
1970 		}
1971 		if (resbmap & FATTR4_SPACE_USED_MASK) {
1972 			uint64_t space_used;
1973 			IXDR_GET_U_HYPER(ptr, space_used);
1974 
1975 			/* Compute space depending on device type */
1976 			ASSERT((vap->va_mask & AT_TYPE));
1977 			if (vap->va_type == VREG || vap->va_type == VDIR ||
1978 			    vap->va_type == VLNK) {
1979 				vap->va_nblocks = (u_longlong_t)
1980 				    ((space_used + (offset4)DEV_BSIZE -
1981 				    (offset4)1) / (offset4)DEV_BSIZE);
1982 			} else {
1983 				vap->va_nblocks = 0;
1984 			}
1985 			vap->va_mask |= AT_NBLOCKS;
1986 		}
1987 		if (resbmap & FATTR4_SYSTEM_MASK) {
1988 			ASSERT(0);
1989 		}
1990 	}
1991 	if (resbmap &
1992 	    (FATTR4_TIME_ACCESS_MASK |
1993 	    FATTR4_TIME_ACCESS_SET_MASK |
1994 	    FATTR4_TIME_BACKUP_MASK |
1995 	    FATTR4_TIME_CREATE_MASK |
1996 	    FATTR4_TIME_DELTA_MASK |
1997 	    FATTR4_TIME_METADATA_MASK |
1998 	    FATTR4_TIME_MODIFY_MASK |
1999 	    FATTR4_TIME_MODIFY_SET_MASK |
2000 	    FATTR4_MOUNTED_ON_FILEID_MASK)) {
2001 
2002 		if (resbmap & FATTR4_TIME_ACCESS_MASK) {
2003 			nfstime4 atime;
2004 			int error;
2005 
2006 			IXDR_GET_U_HYPER(ptr, atime.seconds);
2007 			atime.nseconds = IXDR_GET_U_INT32(ptr);
2008 
2009 			error = nfs4_time_ntov(&atime, &vap->va_atime);
2010 			if (error) {
2011 				garp->n4g_attrerr = error;
2012 				garp->n4g_attrwhy = NFS4_GETATTR_ATATIME_ERR;
2013 			}
2014 			vap->va_mask |= AT_ATIME;
2015 		}
2016 		if (resbmap & FATTR4_TIME_ACCESS_SET_MASK) {
2017 			ASSERT(0);
2018 		}
2019 		if (resbmap & FATTR4_TIME_BACKUP_MASK) {
2020 			ASSERT(0);
2021 		}
2022 		if (resbmap & FATTR4_TIME_CREATE_MASK) {
2023 			ASSERT(0);
2024 		}
2025 		if (resbmap & FATTR4_TIME_DELTA_MASK) {
2026 			IXDR_GET_U_HYPER(ptr, gesp->n4g_delta.seconds);
2027 			gesp->n4g_delta.nseconds = IXDR_GET_U_INT32(ptr);
2028 		}
2029 		if (resbmap & FATTR4_TIME_METADATA_MASK) {
2030 			nfstime4 mdt;
2031 			int error;
2032 
2033 			IXDR_GET_U_HYPER(ptr, mdt.seconds);
2034 			mdt.nseconds = IXDR_GET_U_INT32(ptr);
2035 
2036 			error = nfs4_time_ntov(&mdt, &vap->va_ctime);
2037 			if (error) {
2038 				garp->n4g_attrerr = error;
2039 				garp->n4g_attrwhy = NFS4_GETATTR_ATCTIME_ERR;
2040 			}
2041 			vap->va_mask |= AT_CTIME;
2042 		}
2043 		if (resbmap & FATTR4_TIME_MODIFY_MASK) {
2044 			nfstime4 mtime;
2045 			int error;
2046 
2047 			IXDR_GET_U_HYPER(ptr, mtime.seconds);
2048 			mtime.nseconds = IXDR_GET_U_INT32(ptr);
2049 
2050 			error = nfs4_time_ntov(&mtime, &vap->va_mtime);
2051 			if (error) {
2052 				garp->n4g_attrerr = error;
2053 				garp->n4g_attrwhy = NFS4_GETATTR_ATMTIME_ERR;
2054 			}
2055 			vap->va_mask |= AT_MTIME;
2056 		}
2057 		if (resbmap & FATTR4_TIME_MODIFY_SET_MASK) {
2058 			ASSERT(0);
2059 		}
2060 		if (resbmap & FATTR4_MOUNTED_ON_FILEID_MASK) {
2061 			IXDR_GET_U_HYPER(ptr, garp->n4g_mon_fid);
2062 			garp->n4g_mon_fid_valid = 1;
2063 		}
2064 	}
2065 
2066 	/*
2067 	 * FATTR4_ACL_MASK is not yet supported by this function, but
2068 	 * we check against it anyway, in case it ever is.
2069 	 */
2070 	if (resbmap & ~(NFS4_VATTR_MASK | FATTR4_ACL_MASK)) {
2071 		/* copy only if not provided */
2072 		if (garp->n4g_ext_res == NULL) {
2073 			garp->n4g_ext_res = kmem_alloc(sizeof (ges), KM_SLEEP);
2074 			bcopy(&ges, garp->n4g_ext_res, sizeof (ges));
2075 		}
2076 	}
2077 
2078 	return (TRUE);
2079 }
2080 
2081 
2082 /*
2083  * "." and ".." buffers for filling in on read and readdir
2084  * calls. Intialize the first time and fill in on every
2085  * call to to readdir.
2086  */
2087 char	*nfs4_dot_entries;
2088 char	*nfs4_dot_dot_entry;
2089 
2090 /*
2091  * Create the "." or ".." and pad the buffer once so they are
2092  * copied out as required into the user supplied buffer everytime.
2093  * DIRENT64_RECLEN(sizeof (".") - 1) = DIRENT64_RECLEN(1)
2094  * DIRENT64_RECLEN(sizeof ("..") - 1) = DIRENT64_RECLEN(2)
2095  */
2096 void
nfs4_init_dot_entries()2097 nfs4_init_dot_entries()
2098 {
2099 	struct dirent64 *odp;
2100 
2101 	/*
2102 	 * zalloc it so it zeros the buffer out. Need
2103 	 * to just do it once.
2104 	 */
2105 	nfs4_dot_entries = kmem_zalloc(DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2),
2106 	    KM_SLEEP);
2107 
2108 	odp = (struct dirent64 *)nfs4_dot_entries;
2109 	odp->d_off = 1; /* magic cookie for "." entry */
2110 	odp->d_reclen = DIRENT64_RECLEN(1);
2111 	odp->d_name[0] = '.';
2112 	odp->d_name[1] = '\0';
2113 
2114 	nfs4_dot_dot_entry = nfs4_dot_entries + DIRENT64_RECLEN(1);
2115 	odp = (struct dirent64 *)nfs4_dot_dot_entry;
2116 
2117 	odp->d_off = 2;
2118 	odp->d_reclen = DIRENT64_RECLEN(2);
2119 	odp->d_name[0] = '.';
2120 	odp->d_name[1] = '.';
2121 	odp->d_name[2] = '\0';
2122 }
2123 
2124 void
nfs4_destroy_dot_entries()2125 nfs4_destroy_dot_entries()
2126 {
2127 	if (nfs4_dot_entries)
2128 		kmem_free(nfs4_dot_entries, DIRENT64_RECLEN(1) +
2129 		    DIRENT64_RECLEN(2));
2130 
2131 	nfs4_dot_entries = nfs4_dot_dot_entry = NULL;
2132 }
2133 
2134 bool_t
xdr_READDIR4res_clnt(XDR * xdrs,READDIR4res_clnt * objp,READDIR4args * aobjp)2135 xdr_READDIR4res_clnt(XDR *xdrs, READDIR4res_clnt *objp, READDIR4args *aobjp)
2136 {
2137 	bool_t more_data;
2138 	rddir4_cache *rdc = aobjp->rdc;
2139 	dirent64_t *dp = NULL;
2140 	int entry_length = 0;
2141 	int space_left = 0;
2142 	bitmap4 resbmap;
2143 	uint32_t attrlen;
2144 	nfs4_ga_res_t gar;
2145 	struct nfs4_ga_ext_res ges;
2146 	uint64_t last_cookie = 0;
2147 	int skip_to_end;
2148 	ug_cache_t *pug = NULL;
2149 
2150 	ASSERT(xdrs->x_op == XDR_DECODE);
2151 	ASSERT(rdc->entries == NULL);
2152 	ASSERT(aobjp->dircount > 0);
2153 
2154 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
2155 		return (FALSE);
2156 	if (objp->status != NFS4_OK)
2157 		return (TRUE);
2158 
2159 	gar.n4g_va.va_mask = 0;
2160 	gar.n4g_change_valid = 0;
2161 	gar.n4g_mon_fid_valid = 0;
2162 	gar.n4g_fsid_valid = 0;
2163 	gar.n4g_vsa.vsa_mask = 0;
2164 	gar.n4g_attrwhy = NFS4_GETATTR_OP_OK;
2165 	ges.n4g_pc4.pc4_cache_valid = 0;
2166 	ges.n4g_pc4.pc4_xattr_valid = 0;
2167 	gar.n4g_ext_res = &ges;
2168 
2169 	/* READDIR4res_clnt_free needs to kmem_free this buffer */
2170 	rdc->entries = kmem_alloc(aobjp->dircount, KM_SLEEP);
2171 
2172 	dp = (dirent64_t *)rdc->entries;
2173 	rdc->entlen = rdc->buflen = space_left = aobjp->dircount;
2174 
2175 	/* Fill in dot and dot-dot if needed */
2176 	if (rdc->nfs4_cookie == (nfs_cookie4) 0 ||
2177 	    rdc->nfs4_cookie == (nfs_cookie4) 1) {
2178 
2179 		if (rdc->nfs4_cookie == (nfs_cookie4)0) {
2180 			bcopy(nfs4_dot_entries, rdc->entries,
2181 			    DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2));
2182 			objp->dotp = dp;
2183 			dp = (struct dirent64 *)(((char *)dp) +
2184 			    DIRENT64_RECLEN(1));
2185 			objp->dotdotp = dp;
2186 			dp = (struct dirent64 *)(((char *)dp) +
2187 			    DIRENT64_RECLEN(2));
2188 			space_left -= DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2);
2189 
2190 		} else	{	/* for ".." entry */
2191 			bcopy(nfs4_dot_dot_entry, rdc->entries,
2192 			    DIRENT64_RECLEN(2));
2193 			objp->dotp = NULL;
2194 			objp->dotdotp = dp;
2195 			dp = (struct dirent64 *)(((char *)dp) +
2196 			    DIRENT64_RECLEN(2));
2197 			space_left -= DIRENT64_RECLEN(2);
2198 		}
2199 		/* Magic NFSv4 number for entry after start */
2200 		last_cookie = 2;
2201 	}
2202 
2203 	/* Get the cookie VERIFIER */
2204 	if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cookieverf))
2205 		goto noentries;
2206 
2207 	/* Get the do-we-have-a-next-entry BOOL */
2208 	if (!xdr_bool(xdrs, &more_data))
2209 		goto noentries;
2210 
2211 	if (aobjp->attr_request & (FATTR4_OWNER_MASK | FATTR4_OWNER_GROUP_MASK))
2212 		pug = alloc_ugcache();
2213 
2214 	skip_to_end = 0;
2215 	while (more_data) {
2216 		uint_t namelen;
2217 		uint64_t cookie;
2218 
2219 		/* Get the COOKIE */
2220 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&cookie))
2221 			goto noentries;
2222 
2223 		/* Get the LENGTH of the entry name */
2224 		if (!xdr_u_int(xdrs, &namelen))
2225 			goto noentries;
2226 
2227 		if (!skip_to_end) {
2228 			/*
2229 			 * With the length of the directory entry name
2230 			 * in hand, figure out if there is room left
2231 			 * to encode it for the requestor.  If not,
2232 			 * that is okay, but the rest of the readdir
2233 			 * operation result must be decoded in the
2234 			 * case there are following operations
2235 			 * in the compound request.  Therefore, mark
2236 			 * the rest of the response as "skip" and
2237 			 * decode or skip the remaining data
2238 			 */
2239 			entry_length = DIRENT64_RECLEN(namelen);
2240 			if (space_left < entry_length)
2241 				skip_to_end = 1;
2242 		}
2243 
2244 		/* Get the NAME of the entry */
2245 		if (!skip_to_end) {
2246 			if (!xdr_opaque(xdrs, dp->d_name, namelen))
2247 				goto noentries;
2248 			bzero(&dp->d_name[namelen],
2249 			    DIRENT64_NAMELEN(entry_length) - namelen);
2250 			dp->d_off = last_cookie = cookie;
2251 			dp->d_reclen = entry_length;
2252 		} else {
2253 			if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &namelen))
2254 				goto noentries;
2255 		}
2256 
2257 		/* Get the attribute BITMAP */
2258 		if (!xdr_bitmap4(xdrs, &resbmap))
2259 			goto noentries;
2260 		/* Get the LENGTH of the attributes */
2261 		if (!xdr_u_int(xdrs, (uint_t *)&attrlen))
2262 			goto noentries;
2263 
2264 		/* Get the ATTRIBUTES */
2265 		if (!skip_to_end) {
2266 			uint32_t *ptr;
2267 
2268 			if (!(resbmap & FATTR4_ACL_MASK) &&
2269 			    (ptr = (uint32_t *)XDR_INLINE(xdrs, attrlen))
2270 			    != NULL) {
2271 				if (!xdr_ga_fattr_res_inline(ptr, &gar, resbmap,
2272 				    aobjp->attr_request, aobjp->mi, pug))
2273 					goto noentries;
2274 			} else {
2275 				if (!xdr_ga_fattr_res(xdrs, &gar, resbmap,
2276 				    aobjp->attr_request, aobjp->mi, pug))
2277 					goto noentries;
2278 			}
2279 
2280 			/* Fill in the d_ino per the server's fid values */
2281 			/*
2282 			 * Important to note that the mounted on fileid
2283 			 * is returned in d_ino if supported.  This is
2284 			 * expected, readdir returns the mounted on fileid
2285 			 * while stat() returns the fileid of the object
2286 			 * on "top" of the mount.
2287 			 */
2288 			if (gar.n4g_mon_fid_valid)
2289 				dp->d_ino = gar.n4g_mon_fid;
2290 			else if (gar.n4g_va.va_mask & AT_NODEID)
2291 				dp->d_ino = gar.n4g_va.va_nodeid;
2292 			else
2293 				dp->d_ino = 0;
2294 
2295 			/* See about creating an rnode for this entry */
2296 			if ((resbmap &
2297 			    (NFS4_VATTR_MASK | FATTR4_FILEHANDLE_MASK)) ==
2298 			    (NFS4_VATTR_MASK | FATTR4_FILEHANDLE_MASK)) {
2299 				nfs4_sharedfh_t *sfhp;
2300 				vnode_t *vp;
2301 
2302 				sfhp = sfh4_put(&ges.n4g_fh_u.n4g_fh,
2303 				    aobjp->mi, NULL);
2304 				vp = makenfs4node(sfhp, &gar,
2305 				    aobjp->dvp->v_vfsp,
2306 				    aobjp->t,
2307 				    aobjp->cr,
2308 				    aobjp->dvp,
2309 				    fn_get(VTOSV(aobjp->dvp)->sv_name,
2310 				    dp->d_name, sfhp));
2311 				sfh4_rele(&sfhp);
2312 				dnlc_update(aobjp->dvp, dp->d_name, vp);
2313 				VN_RELE(vp);
2314 			}
2315 
2316 			dp = (struct dirent64 *)(((caddr_t)dp) + dp->d_reclen);
2317 
2318 			space_left -= entry_length;
2319 
2320 		} else {
2321 			if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &attrlen))
2322 				goto noentries;
2323 		}
2324 
2325 		/* Get the do-we-have-a-next-entry BOOL */
2326 		if (!xdr_bool(xdrs, &more_data))
2327 			goto noentries;
2328 	}
2329 
2330 	if (pug) {
2331 		kmem_free(pug, sizeof (ug_cache_t));
2332 		pug = NULL;
2333 	}
2334 
2335 	/*
2336 	 * Finish up the rddir cache
2337 	 * If no entries were returned, free up buffer &
2338 	 * set ncookie to the starting cookie for this
2339 	 * readdir request so that the direof caching
2340 	 * will work properly.
2341 	 */
2342 	ASSERT(rdc->entries);
2343 	if (last_cookie == 0) {
2344 		kmem_free(rdc->entries, rdc->entlen);
2345 		rdc->entries = NULL;
2346 		last_cookie = rdc->nfs4_cookie;
2347 	}
2348 
2349 	rdc->actlen = rdc->entlen - space_left;
2350 	rdc->nfs4_ncookie = last_cookie;
2351 
2352 	/* Get the EOF marker */
2353 	if (!xdr_bool(xdrs, &objp->eof))
2354 		goto noentries;
2355 
2356 	/*
2357 	 * If the server returns eof and there were no
2358 	 * skipped entries, set eof
2359 	 */
2360 	rdc->eof = (objp->eof && !skip_to_end) ? TRUE : FALSE;
2361 
2362 	/*
2363 	 * If we encoded entries we are done
2364 	 */
2365 	if (rdc->entries) {
2366 		rdc->error = 0;
2367 		return (TRUE);
2368 	}
2369 
2370 	/*
2371 	 * If there were no entries and we skipped because
2372 	 * there was not enough space, return EINVAL
2373 	 */
2374 	if (skip_to_end) {
2375 		rdc->error = EINVAL;
2376 		return (TRUE);
2377 	}
2378 
2379 	/*
2380 	 * No entries, nothing skipped, and EOF, return OK.
2381 	 */
2382 	if (objp->eof == TRUE) {
2383 		rdc->error = 0;
2384 		return (TRUE);
2385 	}
2386 
2387 	/*
2388 	 * No entries, nothing skipped, and not EOF
2389 	 * probably a bad cookie, return ENOENT.
2390 	 */
2391 	rdc->error = ENOENT;
2392 	return (TRUE);
2393 
2394 noentries:
2395 	if (rdc->entries) {
2396 		kmem_free(rdc->entries, rdc->entlen);
2397 		rdc->entries = NULL;
2398 	}
2399 	if (pug)
2400 		kmem_free(pug, sizeof (ug_cache_t));
2401 	rdc->error = EIO;
2402 	return (FALSE);
2403 }
2404 
2405 /*
2406  * xdr_ga_res
2407  *
2408  * Returns: FALSE on raw data processing errors, TRUE otherwise.
2409  *
2410  * This function pre-processes the OP_GETATTR response, and then
2411  * calls common routines to process the GETATTR fattr4 results into
2412  * vnode attributes and other components that the client is interested
2413  * in. If an error other than an RPC error is encountered, the details
2414  * of the error are filled into objp, although the result of the
2415  * processing is set to TRUE.
2416  */
2417 static bool_t
xdr_ga_res(XDR * xdrs,GETATTR4res * objp,GETATTR4args * aobjp)2418 xdr_ga_res(XDR *xdrs, GETATTR4res *objp, GETATTR4args *aobjp)
2419 {
2420 #ifdef INLINE
2421 	uint32_t *ptr;
2422 #endif
2423 	bitmap4 resbmap;
2424 	uint32_t attrlen;
2425 
2426 	ASSERT(xdrs->x_op == XDR_DECODE);
2427 
2428 	/* Initialize objp attribute error values */
2429 	objp->ga_res.n4g_attrerr =
2430 	    objp->ga_res.n4g_attrwhy = NFS4_GETATTR_OP_OK;
2431 
2432 	if (!xdr_bitmap4(xdrs, &resbmap))
2433 		return (FALSE);
2434 
2435 	/* save the response bitmap for the caller */
2436 	objp->ga_res.n4g_resbmap = resbmap;
2437 
2438 	/* attrlen */
2439 	if (!XDR_GETINT32(xdrs, (int32_t *)&attrlen))
2440 		return (FALSE);
2441 
2442 	/*
2443 	 * Handle case where request and response bitmaps don't match.
2444 	 */
2445 	if (aobjp->attr_request && aobjp->attr_request != resbmap) {
2446 		bitmap4 deltabmap;
2447 
2448 		/*
2449 		 * Return error for case where server sent extra attributes
2450 		 * because the "unknown" attributes may be anywhere in the
2451 		 * xdr stream and can't be properly processed.
2452 		 */
2453 		deltabmap = ((aobjp->attr_request ^ resbmap) & resbmap);
2454 		if (deltabmap) {
2455 			objp->ga_res.n4g_attrerr = EINVAL;
2456 			objp->ga_res.n4g_attrwhy = NFS4_GETATTR_BITMAP_ERR;
2457 			return (TRUE);
2458 		}
2459 
2460 		/*
2461 		 * Return error for case where there is a mandatory
2462 		 * attribute missing in the server response. Note that
2463 		 * missing recommended attributes are evaluated in the
2464 		 * specific routines that decode the server response.
2465 		 */
2466 		deltabmap = ((aobjp->attr_request ^ resbmap)
2467 		    & aobjp->attr_request);
2468 		if ((deltabmap & FATTR4_MANDATTR_MASK)) {
2469 			objp->ga_res.n4g_attrerr = EINVAL;
2470 			objp->ga_res.n4g_attrwhy = NFS4_GETATTR_MANDATTR_ERR;
2471 			return (TRUE);
2472 		}
2473 	}
2474 
2475 	/* Check to see if the attrs can be inlined and go for it if so */
2476 #ifdef INLINE
2477 	if (!(resbmap & FATTR4_ACL_MASK) &&
2478 	    (ptr = (uint32_t *)XDR_INLINE(xdrs, attrlen)) != NULL)
2479 		return (xdr_ga_fattr_res_inline(ptr, &objp->ga_res,
2480 		    resbmap, aobjp->attr_request, aobjp->mi, NULL));
2481 	else
2482 #endif
2483 		return (xdr_ga_fattr_res(xdrs, &objp->ga_res,
2484 		    resbmap, aobjp->attr_request, aobjp->mi, NULL));
2485 }
2486 
2487 #if defined(DEBUG) && !defined(lint)
2488 /*
2489  * We assume that an enum is a 32-bit value, check it once
2490  */
2491 static enum szchk { SZVAL } szchkvar;
2492 #endif
2493 
2494 bool_t
xdr_settime4(XDR * xdrs,settime4 * objp)2495 xdr_settime4(XDR *xdrs, settime4 *objp)
2496 {
2497 #if defined(DEBUG) && !defined(lint)
2498 	ASSERT(sizeof (szchkvar) == sizeof (int32_t));
2499 #endif
2500 	if (xdrs->x_op == XDR_FREE)
2501 		return (TRUE);
2502 
2503 	if (!xdr_int(xdrs, (int *)&objp->set_it))
2504 		return (FALSE);
2505 	if (objp->set_it != SET_TO_CLIENT_TIME4)
2506 		return (TRUE);
2507 	/* xdr_nfstime4 */
2508 	if (!xdr_longlong_t(xdrs, (longlong_t *)&objp->time.seconds))
2509 		return (FALSE);
2510 	return (xdr_u_int(xdrs, &objp->time.nseconds));
2511 }
2512 
2513 static bool_t
xdr_fattr4(XDR * xdrs,fattr4 * objp)2514 xdr_fattr4(XDR *xdrs, fattr4 *objp)
2515 {
2516 	if (xdrs->x_op != XDR_FREE) {
2517 		if (!xdr_bitmap4(xdrs, &objp->attrmask))
2518 			return (FALSE);
2519 		return (xdr_bytes(xdrs, (char **)&objp->attrlist4,
2520 		    (uint_t *)&objp->attrlist4_len, NFS4_FATTR4_LIMIT));
2521 	}
2522 
2523 	/*
2524 	 * Optimized free case
2525 	 */
2526 	if (objp->attrlist4 != NULL)
2527 		kmem_free(objp->attrlist4, objp->attrlist4_len);
2528 	return (TRUE);
2529 }
2530 
2531 static bool_t
xdr_ACCESS4res(XDR * xdrs,ACCESS4res * objp)2532 xdr_ACCESS4res(XDR *xdrs, ACCESS4res *objp)
2533 {
2534 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
2535 		return (FALSE);
2536 	if (objp->status != NFS4_OK)
2537 		return (TRUE);
2538 	if (!xdr_u_int(xdrs, &objp->supported))
2539 		return (FALSE);
2540 	return (xdr_u_int(xdrs, &objp->access));
2541 }
2542 
2543 static bool_t
xdr_CLOSE4args(XDR * xdrs,CLOSE4args * objp)2544 xdr_CLOSE4args(XDR *xdrs, CLOSE4args *objp)
2545 {
2546 	if (!xdr_u_int(xdrs, &objp->seqid))
2547 		return (FALSE);
2548 	if (!xdr_u_int(xdrs, &objp->open_stateid.seqid))
2549 		return (FALSE);
2550 	return (xdr_opaque(xdrs, objp->open_stateid.other, NFS4_OTHER_SIZE));
2551 }
2552 
2553 static bool_t
xdr_CLOSE4res(XDR * xdrs,CLOSE4res * objp)2554 xdr_CLOSE4res(XDR *xdrs, CLOSE4res *objp)
2555 {
2556 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
2557 		return (FALSE);
2558 	if (objp->status != NFS4_OK)
2559 		return (TRUE);
2560 	if (!xdr_u_int(xdrs, &objp->open_stateid.seqid))
2561 		return (FALSE);
2562 	return (xdr_opaque(xdrs, objp->open_stateid.other, NFS4_OTHER_SIZE));
2563 }
2564 
2565 static bool_t
xdr_CREATE4args(XDR * xdrs,CREATE4args * objp)2566 xdr_CREATE4args(XDR *xdrs, CREATE4args *objp)
2567 {
2568 	if (xdrs->x_op != XDR_FREE) {
2569 		if (!xdr_int(xdrs, (int32_t *)&objp->type))
2570 			return (FALSE);
2571 		switch (objp->type) {
2572 		case NF4LNK:
2573 			if (!xdr_bytes(xdrs,
2574 			    (char **)&objp->ftype4_u.linkdata.linktext4_val,
2575 			    (uint_t *)&objp->ftype4_u.linkdata.linktext4_len,
2576 			    NFS4_MAX_UTF8STRING))
2577 				return (FALSE);
2578 			break;
2579 		case NF4BLK:
2580 		case NF4CHR:
2581 			if (!xdr_u_int(xdrs, &objp->ftype4_u.devdata.specdata1))
2582 				return (FALSE);
2583 			if (!xdr_u_int(xdrs, &objp->ftype4_u.devdata.specdata2))
2584 				return (FALSE);
2585 			break;
2586 		case NF4SOCK:
2587 		case NF4FIFO:
2588 		case NF4DIR:
2589 		default:
2590 			break;	/* server should return NFS4ERR_BADTYPE */
2591 		}
2592 		if (!xdr_bytes(xdrs, (char **)&objp->objname.utf8string_val,
2593 		    (uint_t *)&objp->objname.utf8string_len,
2594 		    NFS4_MAX_UTF8STRING))
2595 			return (FALSE);
2596 		return (xdr_fattr4(xdrs, &objp->createattrs));
2597 	}
2598 
2599 	/*
2600 	 * Optimized free case
2601 	 */
2602 	if (objp->type == NF4LNK) {
2603 		if (objp->ftype4_u.linkdata.linktext4_val != NULL)
2604 			kmem_free(objp->ftype4_u.linkdata.linktext4_val,
2605 			    objp->ftype4_u.linkdata.linktext4_len);
2606 	}
2607 	if (objp->objname.utf8string_val != NULL)
2608 		kmem_free(objp->objname.utf8string_val,
2609 		    objp->objname.utf8string_len);
2610 	return (xdr_fattr4(xdrs, &objp->createattrs));
2611 }
2612 
2613 static bool_t
xdr_CREATE4cargs(XDR * xdrs,CREATE4cargs * objp)2614 xdr_CREATE4cargs(XDR *xdrs, CREATE4cargs *objp)
2615 {
2616 	int len;
2617 
2618 	ASSERT(xdrs->x_op == XDR_ENCODE);
2619 
2620 	if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->type))
2621 		return (FALSE);
2622 	switch (objp->type) {
2623 	case NF4LNK:
2624 		len = strlen(objp->ftype4_u.clinkdata);
2625 		if (len > NFS4_MAX_UTF8STRING)
2626 			return (FALSE);
2627 		if (!XDR_PUTINT32(xdrs, &len))
2628 			return (FALSE);
2629 		if (!xdr_opaque(xdrs, objp->ftype4_u.clinkdata, len))
2630 			return (FALSE);
2631 		break;
2632 	case NF4BLK:
2633 	case NF4CHR:
2634 		if (!XDR_PUTINT32(xdrs,
2635 		    (int32_t *)&objp->ftype4_u.devdata.specdata1))
2636 			return (FALSE);
2637 		if (!XDR_PUTINT32(xdrs,
2638 		    (int32_t *)&objp->ftype4_u.devdata.specdata2))
2639 			return (FALSE);
2640 		break;
2641 	case NF4SOCK:
2642 	case NF4FIFO:
2643 	case NF4DIR:
2644 	default:
2645 		break;	/* server should return NFS4ERR_BADTYPE */
2646 	}
2647 
2648 	len = strlen(objp->cname);
2649 	if (len > NFS4_MAX_UTF8STRING)
2650 		return (FALSE);
2651 	if (!XDR_PUTINT32(xdrs, &len))
2652 		return (FALSE);
2653 	if (!xdr_opaque(xdrs, objp->cname, len))
2654 		return (FALSE);
2655 
2656 	return (xdr_fattr4(xdrs, &objp->createattrs));
2657 }
2658 
2659 static bool_t
xdr_CREATE4res(XDR * xdrs,CREATE4res * objp)2660 xdr_CREATE4res(XDR *xdrs, CREATE4res *objp)
2661 {
2662 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
2663 		return (FALSE);
2664 	if (objp->status != NFS4_OK)
2665 		return (TRUE);
2666 	if (!xdr_bool(xdrs, &objp->cinfo.atomic))
2667 		return (FALSE);
2668 	if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.before))
2669 		return (FALSE);
2670 	if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.after))
2671 		return (FALSE);
2672 	return (xdr_bitmap4(xdrs, &objp->attrset));
2673 }
2674 
2675 static bool_t
xdr_LINK4res(XDR * xdrs,LINK4res * objp)2676 xdr_LINK4res(XDR *xdrs, LINK4res *objp)
2677 {
2678 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
2679 		return (FALSE);
2680 	if (objp->status != NFS4_OK)
2681 		return (TRUE);
2682 	if (!xdr_bool(xdrs, &objp->cinfo.atomic))
2683 		return (FALSE);
2684 	if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.before))
2685 		return (FALSE);
2686 	return (xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.after));
2687 }
2688 
2689 static bool_t
xdr_LOCK4args(XDR * xdrs,LOCK4args * objp)2690 xdr_LOCK4args(XDR *xdrs, LOCK4args *objp)
2691 {
2692 	if (xdrs->x_op != XDR_FREE) {
2693 		if (!xdr_int(xdrs, (int *)&objp->locktype))
2694 			return (FALSE);
2695 		if (!xdr_bool(xdrs, &objp->reclaim))
2696 			return (FALSE);
2697 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset))
2698 			return (FALSE);
2699 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->length))
2700 			return (FALSE);
2701 		if (!xdr_bool(xdrs, &objp->locker.new_lock_owner))
2702 			return (FALSE);
2703 		if (objp->locker.new_lock_owner == TRUE) {
2704 			if (!xdr_u_int(xdrs, &objp->locker.locker4_u.open_owner.
2705 			    open_seqid))
2706 				return (FALSE);
2707 			if (!xdr_u_int(xdrs, &objp->locker.locker4_u.open_owner.
2708 			    open_stateid.seqid))
2709 				return (FALSE);
2710 			if (!xdr_opaque(xdrs, objp->locker.locker4_u.open_owner.
2711 			    open_stateid.other, NFS4_OTHER_SIZE))
2712 				return (FALSE);
2713 			if (!xdr_u_int(xdrs, &objp->locker.locker4_u.open_owner.
2714 			    lock_seqid))
2715 				return (FALSE);
2716 			if (!xdr_u_longlong_t(xdrs,
2717 			    (u_longlong_t *)&objp->locker.locker4_u.
2718 			    open_owner.lock_owner.clientid))
2719 				return (FALSE);
2720 			return (xdr_bytes(xdrs,
2721 			    (char **)&objp->locker.locker4_u.open_owner.
2722 			    lock_owner.owner_val,
2723 			    (uint_t *)&objp->locker.locker4_u.open_owner.
2724 			    lock_owner.owner_len,
2725 			    NFS4_OPAQUE_LIMIT));
2726 		}
2727 
2728 		if (objp->locker.new_lock_owner != FALSE)
2729 			return (FALSE);
2730 
2731 		if (!xdr_u_int(xdrs, &objp->locker.locker4_u.lock_owner.
2732 		    lock_stateid.seqid))
2733 			return (FALSE);
2734 		if (!xdr_opaque(xdrs, objp->locker.locker4_u.lock_owner.
2735 		    lock_stateid.other, NFS4_OTHER_SIZE))
2736 			return (FALSE);
2737 		return (xdr_u_int(xdrs, &objp->locker.locker4_u.lock_owner.
2738 		    lock_seqid));
2739 	}
2740 
2741 	/*
2742 	 * Optimized free case
2743 	 */
2744 	if (objp->locker.new_lock_owner == TRUE) {
2745 		if (objp->locker.locker4_u.open_owner.lock_owner.owner_val !=
2746 		    NULL) {
2747 			kmem_free(objp->locker.locker4_u.open_owner.lock_owner.
2748 			    owner_val,
2749 			    objp->locker.locker4_u.open_owner.lock_owner.
2750 			    owner_len);
2751 		}
2752 	}
2753 
2754 	return (TRUE);
2755 }
2756 
2757 static bool_t
xdr_LOCK4res(XDR * xdrs,LOCK4res * objp)2758 xdr_LOCK4res(XDR *xdrs, LOCK4res *objp)
2759 {
2760 	if (xdrs->x_op != XDR_FREE) {
2761 		if (!xdr_int(xdrs, (int32_t *)&objp->status))
2762 			return (FALSE);
2763 		if (objp->status == NFS4_OK) {
2764 			if (!xdr_u_int(xdrs,
2765 			    &objp->LOCK4res_u.lock_stateid.seqid))
2766 				return (FALSE);
2767 			return (xdr_opaque(xdrs,
2768 			    objp->LOCK4res_u.lock_stateid.other,
2769 			    NFS4_OTHER_SIZE));
2770 		}
2771 		if (objp->status != NFS4ERR_DENIED)
2772 			return (TRUE);
2773 
2774 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->LOCK4res_u.
2775 		    denied.offset))
2776 			return (FALSE);
2777 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->LOCK4res_u.
2778 		    denied.length))
2779 			return (FALSE);
2780 		if (!xdr_int(xdrs, (int *)&objp->LOCK4res_u.denied.locktype))
2781 			return (FALSE);
2782 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->LOCK4res_u.
2783 		    denied.owner.clientid))
2784 			return (FALSE);
2785 		return (xdr_bytes(xdrs,
2786 		    (char **)&objp->LOCK4res_u.denied.owner.owner_val,
2787 		    (uint_t *)&objp->LOCK4res_u.denied.owner.owner_len,
2788 		    NFS4_OPAQUE_LIMIT));
2789 	}
2790 
2791 	/*
2792 	 * Optimized free case
2793 	 */
2794 	if (objp->status == NFS4_OK || objp->status != NFS4ERR_DENIED)
2795 		return (TRUE);
2796 
2797 	if (objp->LOCK4res_u.denied.owner.owner_val != NULL)
2798 		kmem_free(objp->LOCK4res_u.denied.owner.owner_val,
2799 		    objp->LOCK4res_u.denied.owner.owner_len);
2800 	return (TRUE);
2801 }
2802 
2803 static bool_t
xdr_LOCKT4args(XDR * xdrs,LOCKT4args * objp)2804 xdr_LOCKT4args(XDR *xdrs, LOCKT4args *objp)
2805 {
2806 	if (xdrs->x_op != XDR_FREE) {
2807 		if (!xdr_int(xdrs, (int *)&objp->locktype))
2808 			return (FALSE);
2809 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset))
2810 			return (FALSE);
2811 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->length))
2812 			return (FALSE);
2813 		if (!xdr_u_longlong_t(xdrs,
2814 		    (u_longlong_t *)&objp->owner.clientid))
2815 			return (FALSE);
2816 		return (xdr_bytes(xdrs, (char **)&objp->owner.owner_val,
2817 		    (uint_t *)&objp->owner.owner_len,
2818 		    NFS4_OPAQUE_LIMIT));
2819 	}
2820 
2821 	/*
2822 	 * Optimized free case
2823 	 */
2824 	if (objp->owner.owner_val != NULL)
2825 		kmem_free(objp->owner.owner_val, objp->owner.owner_len);
2826 	return (TRUE);
2827 }
2828 
2829 static bool_t
xdr_LOCKT4res(XDR * xdrs,LOCKT4res * objp)2830 xdr_LOCKT4res(XDR *xdrs, LOCKT4res *objp)
2831 {
2832 	if (xdrs->x_op != XDR_FREE) {
2833 		if (!xdr_int(xdrs, (int32_t *)&objp->status))
2834 			return (FALSE);
2835 		if (objp->status == NFS4_OK)
2836 			return (TRUE);
2837 		if (objp->status != NFS4ERR_DENIED)
2838 			return (TRUE);
2839 		/* xdr_LOCK4denied */
2840 		if (!xdr_u_longlong_t(xdrs,
2841 		    (u_longlong_t *)&objp->denied.offset))
2842 			return (FALSE);
2843 		if (!xdr_u_longlong_t(xdrs,
2844 		    (u_longlong_t *)&objp->denied.length))
2845 			return (FALSE);
2846 		if (!xdr_int(xdrs, (int *)&objp->denied.locktype))
2847 			return (FALSE);
2848 		if (!xdr_u_longlong_t(xdrs,
2849 		    (u_longlong_t *)&objp->denied.owner.clientid))
2850 			return (FALSE);
2851 		return (xdr_bytes(xdrs,
2852 		    (char **)&objp->denied.owner.owner_val,
2853 		    (uint_t *)&objp->denied.owner.owner_len,
2854 		    NFS4_OPAQUE_LIMIT));
2855 	}
2856 
2857 	/*
2858 	 * Optimized free case
2859 	 */
2860 	if (objp->status == NFS4_OK || objp->status != NFS4ERR_DENIED)
2861 		return (TRUE);
2862 	if (objp->denied.owner.owner_val != NULL)
2863 		kmem_free(objp->denied.owner.owner_val,
2864 		    objp->denied.owner.owner_len);
2865 	return (TRUE);
2866 }
2867 
2868 static bool_t
xdr_LOCKU4args(XDR * xdrs,LOCKU4args * objp)2869 xdr_LOCKU4args(XDR *xdrs, LOCKU4args *objp)
2870 {
2871 	if (!xdr_int(xdrs, (int *)&objp->locktype))
2872 		return (FALSE);
2873 	if (!xdr_u_int(xdrs, &objp->seqid))
2874 		return (FALSE);
2875 	if (!xdr_u_int(xdrs, &objp->lock_stateid.seqid))
2876 		return (FALSE);
2877 	if (!xdr_opaque(xdrs, objp->lock_stateid.other, NFS4_OTHER_SIZE))
2878 		return (FALSE);
2879 	if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset))
2880 		return (FALSE);
2881 	return (xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->length));
2882 }
2883 
2884 static bool_t
xdr_OPEN4args(XDR * xdrs,OPEN4args * objp)2885 xdr_OPEN4args(XDR *xdrs, OPEN4args *objp)
2886 {
2887 	if (xdrs->x_op != XDR_FREE) {
2888 		if (!xdr_u_int(xdrs, &objp->seqid))
2889 			return (FALSE);
2890 		if (!xdr_u_int(xdrs, &objp->share_access))
2891 			return (FALSE);
2892 		if (!xdr_u_int(xdrs, &objp->share_deny))
2893 			return (FALSE);
2894 
2895 		/* xdr_open_owner4 */
2896 		if (!xdr_u_longlong_t(xdrs,
2897 		    (u_longlong_t *)&objp->owner.clientid))
2898 			return (FALSE);
2899 		if (!xdr_bytes(xdrs, (char **)&objp->owner.owner_val,
2900 		    (uint_t *)&objp->owner.owner_len,
2901 		    NFS4_OPAQUE_LIMIT))
2902 			return (FALSE);
2903 
2904 		/* xdr_openflag4 */
2905 		if (!xdr_int(xdrs, (int *)&objp->opentype))
2906 			return (FALSE);
2907 		if (objp->opentype == OPEN4_CREATE) {
2908 
2909 			/* xdr_createhow4 */
2910 			if (!xdr_int(xdrs, (int *)&objp->mode))
2911 				return (FALSE);
2912 			switch (objp->mode) {
2913 			case UNCHECKED4:
2914 			case GUARDED4:
2915 				if (!xdr_fattr4(xdrs,
2916 				    &objp->createhow4_u.createattrs))
2917 					return (FALSE);
2918 				break;
2919 			case EXCLUSIVE4:
2920 				if (!xdr_u_longlong_t(xdrs,
2921 				    (u_longlong_t *)&objp->createhow4_u.
2922 				    createverf))
2923 					return (FALSE);
2924 				break;
2925 			default:
2926 				return (FALSE);
2927 			}
2928 		}
2929 
2930 		/* xdr_open_claim4 */
2931 		if (!xdr_int(xdrs, (int *)&objp->claim))
2932 			return (FALSE);
2933 
2934 		switch (objp->claim) {
2935 		case CLAIM_NULL:
2936 			return (xdr_bytes(xdrs, (char **)&objp->open_claim4_u.
2937 			    file.utf8string_val,
2938 			    (uint_t *)&objp->open_claim4_u.file.
2939 			    utf8string_len,
2940 			    NFS4_MAX_UTF8STRING));
2941 		case CLAIM_PREVIOUS:
2942 			return (xdr_int(xdrs,
2943 			    (int *)&objp->open_claim4_u.delegate_type));
2944 		case CLAIM_DELEGATE_CUR:
2945 			if (!xdr_u_int(xdrs, (uint_t *)&objp->open_claim4_u.
2946 			    delegate_cur_info.delegate_stateid.seqid))
2947 				return (FALSE);
2948 			if (!xdr_opaque(xdrs, objp->open_claim4_u.
2949 			    delegate_cur_info.delegate_stateid.other,
2950 			    NFS4_OTHER_SIZE))
2951 				return (FALSE);
2952 			return (xdr_bytes(xdrs, (char **)&objp->open_claim4_u.
2953 			    delegate_cur_info.file.utf8string_val,
2954 			    (uint_t *)&objp->open_claim4_u.
2955 			    delegate_cur_info.file.utf8string_len,
2956 			    NFS4_MAX_UTF8STRING));
2957 		case CLAIM_DELEGATE_PREV:
2958 			return (xdr_bytes(xdrs, (char **)&objp->open_claim4_u.
2959 			    file_delegate_prev.utf8string_val,
2960 			    (uint_t *)&objp->open_claim4_u.
2961 			    file_delegate_prev.utf8string_len,
2962 			    NFS4_MAX_UTF8STRING));
2963 		default:
2964 			return (FALSE);
2965 		}
2966 	}
2967 
2968 	/*
2969 	 * Optimized free case
2970 	 */
2971 	if (objp->owner.owner_val != NULL)
2972 		kmem_free(objp->owner.owner_val, objp->owner.owner_len);
2973 
2974 	if (objp->opentype == OPEN4_CREATE) {
2975 		switch (objp->mode) {
2976 		case UNCHECKED4:
2977 		case GUARDED4:
2978 			(void) xdr_fattr4(xdrs,
2979 			    &objp->createhow4_u.createattrs);
2980 			break;
2981 		case EXCLUSIVE4:
2982 		default:
2983 			break;
2984 		}
2985 	}
2986 
2987 	switch (objp->claim) {
2988 	case CLAIM_NULL:
2989 		if (objp->open_claim4_u.file.utf8string_val != NULL)
2990 			kmem_free(objp->open_claim4_u.file.utf8string_val,
2991 			    objp->open_claim4_u.file.utf8string_len);
2992 		return (TRUE);
2993 	case CLAIM_PREVIOUS:
2994 		return (TRUE);
2995 	case CLAIM_DELEGATE_CUR:
2996 		if (objp->open_claim4_u.delegate_cur_info.file.utf8string_val !=
2997 		    NULL) {
2998 			kmem_free(objp->open_claim4_u.delegate_cur_info.file.
2999 			    utf8string_val,
3000 			    objp->open_claim4_u.delegate_cur_info.file.
3001 			    utf8string_len);
3002 		}
3003 		return (TRUE);
3004 	case CLAIM_DELEGATE_PREV:
3005 		if (objp->open_claim4_u.file_delegate_prev.utf8string_val !=
3006 		    NULL) {
3007 			kmem_free(objp->open_claim4_u.file_delegate_prev.
3008 			    utf8string_val,
3009 			    objp->open_claim4_u.file_delegate_prev.
3010 			    utf8string_len);
3011 		}
3012 		return (TRUE);
3013 	default:
3014 		return (TRUE);
3015 	}
3016 }
3017 
3018 static bool_t
xdr_OPEN4cargs(XDR * xdrs,OPEN4cargs * objp)3019 xdr_OPEN4cargs(XDR *xdrs, OPEN4cargs *objp)
3020 {
3021 	int op;
3022 	int len;
3023 	rpc_inline_t *ptr;
3024 
3025 	ASSERT(xdrs->x_op == XDR_ENCODE);
3026 
3027 	/*
3028 	 * We must always define the client's open_owner to be
3029 	 * 4 byte aligned and sized.
3030 	 */
3031 	ASSERT(objp->owner.owner_len <= NFS4_OPAQUE_LIMIT);
3032 	ASSERT(!(objp->owner.owner_len % BYTES_PER_XDR_UNIT));
3033 
3034 	len = objp->owner.owner_len;
3035 	if ((ptr = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT + len)) != NULL) {
3036 		int i;
3037 		int32_t *ip;
3038 
3039 		IXDR_PUT_U_INT32(ptr, OP_OPEN);
3040 		IXDR_PUT_U_INT32(ptr, objp->seqid);
3041 		IXDR_PUT_U_INT32(ptr, objp->share_access);
3042 		IXDR_PUT_U_INT32(ptr, objp->share_deny);
3043 
3044 		/* xdr_open_owner4 */
3045 		IXDR_PUT_HYPER(ptr, objp->owner.clientid);
3046 		IXDR_PUT_U_INT32(ptr, objp->owner.owner_len);
3047 		/* We know this is very short so don't bcopy */
3048 		ip = (int32_t *)objp->owner.owner_val;
3049 		len /= BYTES_PER_XDR_UNIT;
3050 		for (i = 0; i < len; i++)
3051 			*ptr++ = *ip++;
3052 
3053 		/* xdr_openflag4 */
3054 		IXDR_PUT_U_INT32(ptr, objp->opentype);
3055 	} else {
3056 		op = OP_OPEN;
3057 		if (!XDR_PUTINT32(xdrs, (int32_t *)&op))
3058 			return (FALSE);
3059 		if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->seqid))
3060 			return (FALSE);
3061 		if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->share_access))
3062 			return (FALSE);
3063 		if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->share_deny))
3064 			return (FALSE);
3065 
3066 		/* xdr_open_owner4 */
3067 		if (!xdr_u_longlong_t(xdrs,
3068 		    (u_longlong_t *)&objp->owner.clientid))
3069 			return (FALSE);
3070 		if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->owner.owner_len))
3071