xref: /titanic_50/usr/src/uts/common/fs/nfs/nfs3_xdr.c (revision 554ff184129088135ad2643c1c9832174a17be88)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 #include <sys/param.h>
33 #include <sys/types.h>
34 #include <sys/systm.h>
35 #include <sys/user.h>
36 #include <sys/vnode.h>
37 #include <sys/file.h>
38 #include <sys/dirent.h>
39 #include <sys/vfs.h>
40 #include <sys/stream.h>
41 #include <sys/strsubr.h>
42 #include <sys/debug.h>
43 #include <sys/t_lock.h>
44 #include <sys/cmn_err.h>
45 #include <sys/dnlc.h>
46 #include <sys/cred.h>
47 #include <sys/time.h>
48 
49 #include <rpc/types.h>
50 #include <rpc/xdr.h>
51 
52 #include <nfs/nfs.h>
53 #include <nfs/rnode.h>
54 
55 /* Checks if the fh is 32 bytes and returns TRUE if it is, otherwise FALSE */
56 #define	XDR_CHECKFHSIZE(x, len, sz)	\
57 	(((int32_t)ntohl(len) == NFS3_CURFHSIZE) ? TRUE : \
58 	(xdr_rewind(x, sz), FALSE))
59 
60 /*
61  * These are the XDR routines used to serialize and deserialize
62  * the various structures passed as parameters across the network
63  * between NFS clients and servers.
64  */
65 
66 /*
67  * XDR null terminated ASCII strings
68  * xdr_string3 deals with "C strings" - arrays of bytes that are
69  * terminated by a NULL character.  The parameter cpp references a
70  * pointer to storage; If the pointer is null, then the necessary
71  * storage is allocated.  The last parameter is the max allowed length
72  * of the string as allowed by the system.  The NFS Version 3 protocol
73  * does not place limits on strings, but the implementation needs to
74  * place a reasonable limit to avoid problems.
75  */
76 bool_t
77 xdr_string3(XDR *xdrs, char **cpp, uint_t maxsize)
78 {
79 	char *sp;
80 	uint_t size;
81 	uint_t nodesize;
82 	bool_t mem_alloced = FALSE;
83 
84 	/*
85 	 * first deal with the length since xdr strings are counted-strings
86 	 */
87 	sp = *cpp;
88 	switch (xdrs->x_op) {
89 	case XDR_FREE:
90 		if (sp == NULL || sp == nfs3nametoolong)
91 			return (TRUE);	/* already free */
92 		/* FALLTHROUGH */
93 
94 	case XDR_ENCODE:
95 		size = (uint_t)strlen(sp);
96 		break;
97 
98 	case XDR_DECODE:
99 		break;
100 	}
101 
102 	if (!xdr_u_int(xdrs, &size))
103 		return (FALSE);
104 
105 	/*
106 	 * now deal with the actual bytes
107 	 */
108 	switch (xdrs->x_op) {
109 	case XDR_DECODE:
110 		if (size >= maxsize) {
111 			*cpp = nfs3nametoolong;
112 			if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &size))
113 				return (FALSE);
114 			return (TRUE);
115 		}
116 		nodesize = size + 1;
117 		if (nodesize == 0)
118 			return (TRUE);
119 		if (sp == NULL) {
120 			sp = kmem_alloc(nodesize, KM_NOSLEEP);
121 			*cpp = sp;
122 			if (sp == NULL)
123 				return (FALSE);
124 			mem_alloced = TRUE;
125 		}
126 		sp[size] = 0;
127 
128 		if (xdr_opaque(xdrs, sp, size)) {
129 			if (strlen(sp) != size) {
130 				if (mem_alloced)
131 					kmem_free(sp, nodesize);
132 				*cpp = NULL;
133 				return (FALSE);
134 			}
135 		} else {
136 			if (mem_alloced)
137 				kmem_free(sp, nodesize);
138 			*cpp = NULL;
139 			return (FALSE);
140 		}
141 		return (TRUE);
142 
143 	case XDR_ENCODE:
144 		return (xdr_opaque(xdrs, sp, size));
145 
146 	case XDR_FREE:
147 		nodesize = size + 1;
148 		kmem_free(sp, nodesize);
149 		*cpp = NULL;
150 		return (TRUE);
151 	}
152 
153 	return (FALSE);
154 }
155 
156 /*
157  * If the filehandle is not equal to NFS3_CURFHSIZE then
158  * rewind/set the pointer back to it's previous location prior to
159  * the call.
160  * Inlining is only being done for 32 byte fhandles since
161  * predominantly the size of the fh is 32 and thus
162  * optimizing only this case would be the best.
163  */
164 static void
165 xdr_rewind(register XDR *xdrs, uint_t inl_sz)
166 {
167 	uint_t curpos;
168 
169 	curpos = XDR_GETPOS(xdrs);
170 	(void) XDR_SETPOS(xdrs, curpos - inl_sz);
171 }
172 
173 bool_t
174 xdr_nfs_fh3(XDR *xdrs, nfs_fh3 *objp)
175 {
176 	int32_t *ptr;
177 	int32_t *fhp;
178 	uint_t len;
179 	uint_t in_size;
180 
181 	if (xdrs->x_op == XDR_FREE)
182 		return (TRUE);
183 
184 	in_size = RNDUP(sizeof (fhandle_t)) +	1 * BYTES_PER_XDR_UNIT;
185 
186 	ptr = XDR_INLINE(xdrs, in_size);
187 	if (ptr != NULL) {
188 		len = ((xdrs->x_op == XDR_DECODE) ? *ptr : objp->fh3_length);
189 
190 		if (XDR_CHECKFHSIZE(xdrs, len, in_size)) {
191 			fhp = (int32_t *)&(objp->fh3_u.data);
192 			if (xdrs->x_op == XDR_DECODE) {
193 				objp->fh3_length = IXDR_GET_U_INT32(ptr);
194 				*fhp++ = *ptr++;
195 				*fhp++ = *ptr++;
196 				*fhp++ = *ptr++;
197 				*fhp++ = *ptr++;
198 				*fhp++ = *ptr++;
199 				*fhp++ = *ptr++;
200 				*fhp++ = *ptr++;
201 				*fhp = *ptr;
202 			} else {
203 				IXDR_PUT_U_INT32(ptr, objp->fh3_length);
204 				*ptr++ = *fhp++;
205 				*ptr++ = *fhp++;
206 				*ptr++ = *fhp++;
207 				*ptr++ = *fhp++;
208 				*ptr++ = *fhp++;
209 				*ptr++ = *fhp++;
210 				*ptr++ = *fhp++;
211 				*ptr = *fhp;
212 			}
213 			return (TRUE);
214 		}
215 	}
216 
217 	if (!xdr_u_int(xdrs, &objp->fh3_length))
218 		return (FALSE);
219 
220 	if (objp->fh3_length > NFS3_FHSIZE)
221 		return (FALSE);
222 
223 	return (xdr_opaque(xdrs, objp->fh3_u.data, objp->fh3_length));
224 }
225 
226 /*
227  * Will only consider the DECODE case for the fast way
228  * since it does not require any additional allocation of
229  * memory and thus can just assign the objp to point to
230  * the data returned from XDR_INLINE
231  */
232 bool_t
233 xdr_fastnfs_fh3(register XDR *xdrs, nfs_fh3 **objp)
234 {
235 	int32_t *ptr;
236 	uint_t in_size;
237 
238 	if (xdrs->x_op != XDR_DECODE)
239 		return (FALSE);
240 
241 	in_size = RNDUP(sizeof (fhandle_t)) + 1 * BYTES_PER_XDR_UNIT;
242 
243 	ptr = XDR_INLINE(xdrs, in_size);
244 
245 	if ((ptr != NULL) && (XDR_CHECKFHSIZE(xdrs, *ptr, in_size))) {
246 #ifdef _LITTLE_ENDIAN
247 		/* Decode the length */
248 		*ptr = (int32_t)ntohl(*(uint32_t *)ptr);
249 #endif
250 		*objp = (nfs_fh3 *) ptr;
251 		return (TRUE);
252 	}
253 	return (FALSE);
254 }
255 
256 bool_t
257 xdr_diropargs3(XDR *xdrs, diropargs3 *objp)
258 {
259 	uint32_t size;
260 	int32_t *ptr;
261 	int32_t *fhp;
262 	uint32_t nodesize;
263 	uint32_t in_size;
264 	int rndup, i;
265 	char *cptr;
266 
267 	if (xdrs->x_op == XDR_DECODE) {
268 		objp->dirp = &objp->dir;
269 		/* includes: fh, length of fh, and length of name */
270 		in_size = RNDUP(sizeof (fhandle_t)) + 2 * BYTES_PER_XDR_UNIT;
271 
272 		ptr = XDR_INLINE(xdrs, in_size);
273 
274 		if (ptr != NULL) {
275 		    if (XDR_CHECKFHSIZE(xdrs, *ptr, in_size)) {
276 			    fhp = (int32_t *)(objp->dir.fh3_u.data);
277 			    /* Get length of fhandle and then fh. */
278 			    objp->dir.fh3_length = IXDR_GET_U_INT32(ptr);
279 			    *fhp++ = *ptr++;
280 			    *fhp++ = *ptr++;
281 			    *fhp++ = *ptr++;
282 			    *fhp++ = *ptr++;
283 			    *fhp++ = *ptr++;
284 			    *fhp++ = *ptr++;
285 			    *fhp++ = *ptr++;
286 			    *fhp = *ptr++;
287 
288 			    size = IXDR_GET_U_INT32(ptr);
289 
290 			    if (size >= MAXNAMELEN) {
291 				    objp->name = nfs3nametoolong;
292 				    if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES,
293 						&size))
294 					    return (FALSE);
295 				    return (TRUE);
296 			    }
297 			    nodesize = size+1;
298 			    if (nodesize == 0)
299 				    return (TRUE);
300 			    if (objp->name == NULL) {
301 				    objp->name = (char *)kmem_alloc(nodesize,
302 								    KM_NOSLEEP);
303 				    if (objp->name == NULL)
304 					    return (FALSE);
305 				    objp->flags |= DA_FREENAME;
306 			    }
307 			    ptr = XDR_INLINE(xdrs, RNDUP(size));
308 			    if (ptr == NULL) {
309 				if (! xdr_opaque(xdrs, objp->name, size)) {
310 					if (objp->flags & DA_FREENAME) {
311 						kmem_free(objp->name,
312 							nodesize);
313 						objp->name = NULL;
314 					}
315 					return (FALSE);
316 				}
317 				objp->name[size] = '\0';
318 				if (strlen(objp->name) != size) {
319 					if (objp->flags & DA_FREENAME) {
320 						kmem_free(objp->name,
321 							nodesize);
322 						objp->name = NULL;
323 					}
324 					return (FALSE);
325 				}
326 				return (TRUE);
327 			    }
328 			    bcopy((char *)ptr, objp->name, size);
329 			    objp->name[size] = '\0';
330 			    if (strlen(objp->name) != size) {
331 				    if (objp->flags & DA_FREENAME) {
332 					    kmem_free(objp->name,
333 						nodesize);
334 					    objp->name = NULL;
335 				    }
336 				    return (FALSE);
337 			    }
338 			    return (TRUE);
339 		    }
340 		}
341 		if (objp->name == NULL)
342 			objp->flags |= DA_FREENAME;
343 	}
344 
345 	if ((xdrs->x_op == XDR_ENCODE) &&
346 	    (objp->dirp->fh3_length == NFS3_CURFHSIZE)) {
347 		fhp = (int32_t *)(objp->dirp->fh3_u.data);
348 		size = strlen(objp->name);
349 		in_size = RNDUP(sizeof (fhandle_t)) +
350 			(2 * BYTES_PER_XDR_UNIT) + RNDUP(size);
351 
352 		ptr = XDR_INLINE(xdrs, in_size);
353 		if (ptr != NULL) {
354 			IXDR_PUT_U_INT32(ptr, objp->dirp->fh3_length);
355 			*ptr++ = *fhp++;
356 			*ptr++ = *fhp++;
357 			*ptr++ = *fhp++;
358 			*ptr++ = *fhp++;
359 			*ptr++ = *fhp++;
360 			*ptr++ = *fhp++;
361 			*ptr++ = *fhp++;
362 			*ptr++ = *fhp;
363 
364 			IXDR_PUT_U_INT32(ptr, (uint32_t)size);
365 
366 			bcopy(objp->name, (char *)ptr, size);
367 			rndup = BYTES_PER_XDR_UNIT -
368 				(size % BYTES_PER_XDR_UNIT);
369 			if (rndup != BYTES_PER_XDR_UNIT) {
370 				cptr = (char *)ptr + size;
371 				for (i = 0; i < rndup; i++)
372 					*cptr++ = '\0';
373 			}
374 			return (TRUE);
375 		}
376 	}
377 	if (xdrs->x_op == XDR_FREE) {
378 		if ((objp->name == NULL) || (objp->name == nfs3nametoolong))
379 			return (TRUE);
380 		size = strlen(objp->name);
381 		if (objp->flags & DA_FREENAME)
382 			kmem_free(objp->name, size + 1);
383 		objp->name = NULL;
384 		return (TRUE);
385 	}
386 	/* Normal case */
387 	if (!xdr_nfs_fh3(xdrs, objp->dirp))
388 		return (FALSE);
389 	return (xdr_string3(xdrs, &objp->name, MAXNAMELEN));
390 }
391 
392 bool_t
393 xdr_fastdiropargs3(XDR *xdrs, diropargs3 **objp)
394 {
395 	int32_t *ptr;
396 	uint_t size;
397 	uint_t nodesize;
398 	struct diropargs3 *da;
399 	uint_t in_size;
400 	uint_t skipsize;
401 
402 	if (xdrs->x_op != XDR_DECODE)
403 		return (FALSE);
404 
405 	in_size = RNDUP(sizeof (fhandle_t)) +	1 * BYTES_PER_XDR_UNIT;
406 
407 	/* includes the fh and fh length */
408 	ptr = XDR_INLINE(xdrs, in_size);
409 
410 	if ((ptr != NULL) && (XDR_CHECKFHSIZE(xdrs, *ptr, in_size))) {
411 		da = *objp;
412 #ifdef _LITTLE_ENDIAN
413 		*ptr = (int32_t)ntohl(*(uint32_t *)ptr);
414 #endif
415 		da->dirp = (nfs_fh3 *)ptr;
416 		da->name = NULL;
417 		da->flags = 0;
418 		if (!XDR_CONTROL(xdrs, XDR_PEEK, (void *)&size)) {
419 			da->flags |= DA_FREENAME;
420 			return (xdr_string3(xdrs, &da->name, MAXNAMELEN));
421 		}
422 		if (size >= MAXNAMELEN) {
423 			da->name = nfs3nametoolong;
424 			skipsize = RNDUP(size) + (1 * BYTES_PER_XDR_UNIT);
425 			if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &skipsize))
426 				return (FALSE);
427 			return (TRUE);
428 		}
429 		nodesize = size + 1;
430 		if (nodesize == 0)
431 			return (TRUE);
432 		ptr = XDR_INLINE(xdrs, 1 * BYTES_PER_XDR_UNIT + RNDUP(size));
433 		if (ptr != NULL) {
434 			if ((size % BYTES_PER_XDR_UNIT) != 0)
435 				/* Plus 1 skips the size */
436 				da->name = (char *)(ptr + 1);
437 			else {
438 				da->name = (char *)ptr;
439 				bcopy((char *)(ptr + 1), da->name, size);
440 			}
441 			da->name[size] = '\0';
442 			return (TRUE);
443 		}
444 		da->flags |= DA_FREENAME;
445 		return (xdr_string3(xdrs, &da->name, MAXNAMELEN));
446 	}
447 	return (FALSE);
448 }
449 
450 static bool_t
451 xdr_fattr3(XDR *xdrs, fattr3 *na)
452 {
453 	int32_t *ptr;
454 
455 	if (xdrs->x_op == XDR_FREE)
456 		return (TRUE);
457 
458 	ptr = XDR_INLINE(xdrs, NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT);
459 	if (ptr != NULL) {
460 		if (xdrs->x_op == XDR_DECODE) {
461 			na->type = IXDR_GET_ENUM(ptr, enum ftype3);
462 			na->mode = IXDR_GET_U_INT32(ptr);
463 			na->nlink = IXDR_GET_U_INT32(ptr);
464 			na->uid = IXDR_GET_U_INT32(ptr);
465 			na->gid = IXDR_GET_U_INT32(ptr);
466 			IXDR_GET_U_HYPER(ptr, na->size);
467 			IXDR_GET_U_HYPER(ptr, na->used);
468 			na->rdev.specdata1 = IXDR_GET_U_INT32(ptr);
469 			na->rdev.specdata2 = IXDR_GET_U_INT32(ptr);
470 			IXDR_GET_U_HYPER(ptr, na->fsid);
471 			IXDR_GET_U_HYPER(ptr, na->fileid);
472 			na->atime.seconds = IXDR_GET_U_INT32(ptr);
473 			na->atime.nseconds = IXDR_GET_U_INT32(ptr);
474 			na->mtime.seconds = IXDR_GET_U_INT32(ptr);
475 			na->mtime.nseconds = IXDR_GET_U_INT32(ptr);
476 			na->ctime.seconds = IXDR_GET_U_INT32(ptr);
477 			na->ctime.nseconds = IXDR_GET_U_INT32(ptr);
478 		} else {
479 			IXDR_PUT_ENUM(ptr, na->type);
480 			IXDR_PUT_U_INT32(ptr, na->mode);
481 			IXDR_PUT_U_INT32(ptr, na->nlink);
482 			IXDR_PUT_U_INT32(ptr, na->uid);
483 			IXDR_PUT_U_INT32(ptr, na->gid);
484 			IXDR_PUT_U_HYPER(ptr, na->size);
485 			IXDR_PUT_U_HYPER(ptr, na->used);
486 			IXDR_PUT_U_INT32(ptr, na->rdev.specdata1);
487 			IXDR_PUT_U_INT32(ptr, na->rdev.specdata2);
488 			IXDR_PUT_U_HYPER(ptr, na->fsid);
489 			IXDR_PUT_U_HYPER(ptr, na->fileid);
490 			IXDR_PUT_U_INT32(ptr, na->atime.seconds);
491 			IXDR_PUT_U_INT32(ptr, na->atime.nseconds);
492 			IXDR_PUT_U_INT32(ptr, na->mtime.seconds);
493 			IXDR_PUT_U_INT32(ptr, na->mtime.nseconds);
494 			IXDR_PUT_U_INT32(ptr, na->ctime.seconds);
495 			IXDR_PUT_U_INT32(ptr, na->ctime.nseconds);
496 		}
497 		return (TRUE);
498 	}
499 	if (!(xdr_enum(xdrs, (enum_t *)&na->type) &&
500 		xdr_u_int(xdrs, &na->mode) &&
501 		xdr_u_int(xdrs, &na->nlink) &&
502 		xdr_u_int(xdrs, &na->uid) &&
503 		xdr_u_int(xdrs, &na->gid) &&
504 		xdr_u_longlong_t(xdrs, &na->size) &&
505 		xdr_u_longlong_t(xdrs, &na->used) &&
506 		xdr_u_int(xdrs, &na->rdev.specdata1) &&
507 		xdr_u_int(xdrs, &na->rdev.specdata2) &&
508 		xdr_u_longlong_t(xdrs, &na->fsid) &&
509 		xdr_u_longlong_t(xdrs, &na->fileid) &&
510 		xdr_u_int(xdrs, &na->atime.seconds) &&
511 		xdr_u_int(xdrs, &na->atime.nseconds) &&
512 		xdr_u_int(xdrs, &na->mtime.seconds) &&
513 		xdr_u_int(xdrs, &na->mtime.nseconds) &&
514 		xdr_u_int(xdrs, &na->ctime.seconds) &&
515 		xdr_u_int(xdrs, &na->ctime.nseconds)))
516 			return (FALSE);
517 	return (TRUE);
518 }
519 
520 /*
521  * Fast decode of an fattr3 to a vattr
522  * Only return FALSE on decode error, all other fattr to vattr translation
523  * failures set status.
524  *
525  * Callers must catch the following errors:
526  *	EFBIG - file size will not fit in va_size
527  *	EOVERFLOW - time will not fit in va_*time
528  */
529 static bool_t
530 xdr_fattr3_to_vattr(XDR *xdrs, fattr3_res *objp)
531 {
532 	int32_t *ptr;
533 	size3 used;
534 	specdata3 rdev;
535 	uint32_t ntime;
536 	vattr_t *vap = objp->vap;
537 
538 	/*
539 	 * DECODE only
540 	 */
541 	ASSERT(xdrs->x_op == XDR_DECODE);
542 
543 	objp->status = 0;
544 	ptr = XDR_INLINE(xdrs, NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT);
545 	if (ptr != NULL) {
546 		/*
547 		 * Common case
548 		 */
549 		vap->va_type = IXDR_GET_ENUM(ptr, enum vtype);
550 		if (vap->va_type < NF3REG || vap->va_type > NF3FIFO)
551 			vap->va_type = VBAD;
552 		else
553 			vap->va_type = nf3_to_vt[vap->va_type];
554 		vap->va_mode = IXDR_GET_U_INT32(ptr);
555 		vap->va_nlink = IXDR_GET_U_INT32(ptr);
556 		vap->va_uid = (uid_t)IXDR_GET_U_INT32(ptr);
557 		if (vap->va_uid == NFS_UID_NOBODY)
558 			vap->va_uid = UID_NOBODY;
559 		vap->va_gid = (gid_t)IXDR_GET_U_INT32(ptr);
560 		if (vap->va_gid == NFS_GID_NOBODY)
561 			vap->va_gid = GID_NOBODY;
562 		IXDR_GET_U_HYPER(ptr, vap->va_size);
563 		/*
564 		 * If invalid size, stop decode, set status, and
565 		 * return TRUE, x_handy will be correct, caller must ignore vap.
566 		 */
567 		if (!NFS3_SIZE_OK(vap->va_size)) {
568 			objp->status = EFBIG;
569 			return (TRUE);
570 		}
571 		IXDR_GET_U_HYPER(ptr, used);
572 		rdev.specdata1 = IXDR_GET_U_INT32(ptr);
573 		rdev.specdata2 = IXDR_GET_U_INT32(ptr);
574 		/* fsid is ignored */
575 		ptr += 2;
576 		IXDR_GET_U_HYPER(ptr, vap->va_nodeid);
577 
578 		/*
579 		 * nfs protocol defines times as unsigned so don't
580 		 * extend sign, unless sysadmin set nfs_allow_preepoch_time.
581 		 * The inline macros do the equivilant of NFS_TIME_T_CONVERT
582 		 */
583 		if (nfs_allow_preepoch_time) {
584 			vap->va_atime.tv_sec = IXDR_GET_INT32(ptr);
585 			vap->va_atime.tv_nsec = IXDR_GET_U_INT32(ptr);
586 			vap->va_mtime.tv_sec = IXDR_GET_INT32(ptr);
587 			vap->va_mtime.tv_nsec = IXDR_GET_U_INT32(ptr);
588 			vap->va_ctime.tv_sec = IXDR_GET_INT32(ptr);
589 			vap->va_ctime.tv_nsec = IXDR_GET_U_INT32(ptr);
590 		} else {
591 			/*
592 			 * Check if the time would overflow on 32-bit
593 			 */
594 			ntime = IXDR_GET_U_INT32(ptr);
595 			/*CONSTCOND*/
596 			if (NFS3_TIME_OVERFLOW(ntime)) {
597 				objp->status = EOVERFLOW;
598 				return (TRUE);
599 			}
600 			vap->va_atime.tv_sec = ntime;
601 			vap->va_atime.tv_nsec = IXDR_GET_U_INT32(ptr);
602 
603 			ntime = IXDR_GET_U_INT32(ptr);
604 			/*CONSTCOND*/
605 			if (NFS3_TIME_OVERFLOW(ntime)) {
606 				objp->status = EOVERFLOW;
607 				return (TRUE);
608 			}
609 			vap->va_mtime.tv_sec = ntime;
610 			vap->va_mtime.tv_nsec = IXDR_GET_U_INT32(ptr);
611 
612 			ntime = IXDR_GET_U_INT32(ptr);
613 			/*CONSTCOND*/
614 			if (NFS3_TIME_OVERFLOW(ntime)) {
615 				objp->status = EOVERFLOW;
616 				return (TRUE);
617 			}
618 			vap->va_ctime.tv_sec = ntime;
619 			vap->va_ctime.tv_nsec = IXDR_GET_U_INT32(ptr);
620 		}
621 
622 	} else {
623 		uint64 fsid;
624 
625 		/*
626 		 * Slow path
627 		 */
628 		if (!(xdr_enum(xdrs, (enum_t *)&vap->va_type) &&
629 			xdr_u_int(xdrs, &vap->va_mode) &&
630 			xdr_u_int(xdrs, &vap->va_nlink) &&
631 			xdr_u_int(xdrs, (uint_t *)&vap->va_uid) &&
632 			xdr_u_int(xdrs, (uint_t *)&vap->va_gid) &&
633 			xdr_u_longlong_t(xdrs, &vap->va_size) &&
634 			xdr_u_longlong_t(xdrs, &used) &&
635 			xdr_u_int(xdrs, &rdev.specdata1) &&
636 			xdr_u_int(xdrs, &rdev.specdata2) &&
637 			xdr_u_longlong_t(xdrs, &fsid) &&	/* ignored */
638 			xdr_u_longlong_t(xdrs, &vap->va_nodeid)))
639 				return (FALSE);
640 
641 		if (nfs_allow_preepoch_time) {
642 			if (!xdr_u_int(xdrs, &ntime))
643 				return (FALSE);
644 			vap->va_atime.tv_sec = (int32_t)ntime;
645 			if (!xdr_u_int(xdrs, &ntime))
646 				return (FALSE);
647 			vap->va_atime.tv_nsec = ntime;
648 
649 			if (!xdr_u_int(xdrs, &ntime))
650 				return (FALSE);
651 			vap->va_mtime.tv_sec = (int32_t)ntime;
652 			if (!xdr_u_int(xdrs, &ntime))
653 				return (FALSE);
654 			vap->va_mtime.tv_nsec = ntime;
655 
656 			if (!xdr_u_int(xdrs, &ntime))
657 				return (FALSE);
658 			vap->va_ctime.tv_sec = (int32_t)ntime;
659 			if (!xdr_u_int(xdrs, &ntime))
660 				return (FALSE);
661 			vap->va_ctime.tv_nsec = ntime;
662 		} else {
663 			/*
664 			 * Check if the time would overflow on 32-bit
665 			 * Set status and keep decoding stream.
666 			 */
667 			if (!xdr_u_int(xdrs, &ntime))
668 				return (FALSE);
669 			/*CONSTCOND*/
670 			if (NFS3_TIME_OVERFLOW(ntime)) {
671 				objp->status = EOVERFLOW;
672 			}
673 			vap->va_atime.tv_sec = ntime;
674 			if (!xdr_u_int(xdrs, &ntime))
675 				return (FALSE);
676 			vap->va_atime.tv_nsec = ntime;
677 
678 			if (!xdr_u_int(xdrs, &ntime))
679 				return (FALSE);
680 			/*CONSTCOND*/
681 			if (NFS3_TIME_OVERFLOW(ntime)) {
682 				objp->status = EOVERFLOW;
683 			}
684 			vap->va_mtime.tv_sec = ntime;
685 			if (!xdr_u_int(xdrs, &ntime))
686 				return (FALSE);
687 			vap->va_mtime.tv_nsec = ntime;
688 
689 			if (!xdr_u_int(xdrs, &ntime))
690 				return (FALSE);
691 			/*CONSTCOND*/
692 			if (NFS3_TIME_OVERFLOW(ntime)) {
693 				objp->status = EOVERFLOW;
694 			}
695 			vap->va_ctime.tv_sec = ntime;
696 			if (!xdr_u_int(xdrs, &ntime))
697 				return (FALSE);
698 			vap->va_ctime.tv_nsec = ntime;
699 		}
700 
701 		/*
702 		 * Fixup as needed
703 		 */
704 		if (vap->va_type < NF3REG || vap->va_type > NF3FIFO)
705 			vap->va_type = VBAD;
706 		else
707 			vap->va_type = nf3_to_vt[vap->va_type];
708 		if (vap->va_uid == NFS_UID_NOBODY)
709 			vap->va_uid = UID_NOBODY;
710 		if (vap->va_gid == NFS_GID_NOBODY)
711 			vap->va_gid = GID_NOBODY;
712 		/*
713 		 * If invalid size, set status, and
714 		 * return TRUE, caller must ignore vap.
715 		 */
716 		if (!NFS3_SIZE_OK(vap->va_size)) {
717 			objp->status = EFBIG;
718 			return (TRUE);
719 		}
720 	}
721 
722 	/*
723 	 * Fill in derived fields
724 	 */
725 	vap->va_fsid = objp->vp->v_vfsp->vfs_dev;
726 	vap->va_seq = 0;
727 
728 	/*
729 	 * Common case values
730 	 */
731 	vap->va_rdev = 0;
732 	vap->va_blksize = MAXBSIZE;
733 	vap->va_nblocks = 0;
734 
735 	switch (vap->va_type) {
736 	case VREG:
737 	case VDIR:
738 	case VLNK:
739 		vap->va_nblocks = (u_longlong_t)
740 			((used + (size3)DEV_BSIZE - (size3)1) /
741 			(size3)DEV_BSIZE);
742 		break;
743 	case VBLK:
744 		vap->va_blksize = DEV_BSIZE;
745 		/* FALLTHRU */
746 	case VCHR:
747 		vap->va_rdev = makedevice(rdev.specdata1, rdev.specdata2);
748 		break;
749 	case VSOCK:
750 	case VFIFO:
751 	default:
752 		break;
753 	}
754 
755 	return (TRUE);
756 }
757 
758 static bool_t
759 xdr_post_op_vattr(XDR *xdrs, post_op_vattr *objp)
760 {
761 	/*
762 	 * DECODE only
763 	 */
764 	ASSERT(xdrs->x_op == XDR_DECODE);
765 
766 	if (!xdr_bool(xdrs, &objp->attributes))
767 		return (FALSE);
768 
769 	if (objp->attributes == FALSE)
770 		return (TRUE);
771 
772 	if (objp->attributes != TRUE)
773 		return (FALSE);
774 
775 	if (!xdr_fattr3_to_vattr(xdrs, &objp->fres))
776 		return (FALSE);
777 
778 	/*
779 	 * The file size may cause an EFBIG or the time values
780 	 * may cause EOVERFLOW, if so simply drop the attributes.
781 	 */
782 	if (objp->fres.status != NFS3_OK)
783 		objp->attributes = FALSE;
784 
785 	return (TRUE);
786 }
787 
788 bool_t
789 xdr_post_op_attr(XDR *xdrs, post_op_attr *objp)
790 {
791 	if (!xdr_bool(xdrs, &objp->attributes))
792 		return (FALSE);
793 
794 	if (objp->attributes == FALSE)
795 		return (TRUE);
796 
797 	if (objp->attributes != TRUE)
798 		return (FALSE);
799 
800 	if (!xdr_fattr3(xdrs, &objp->attr))
801 		return (FALSE);
802 
803 	/*
804 	 * Check that we don't get a file we can't handle through
805 	 *	existing interfaces (especially stat64()).
806 	 * Decode only check since on encode the data has
807 	 * been dealt with in the above call to xdr_fattr3().
808 	 */
809 	if (xdrs->x_op == XDR_DECODE) {
810 		/* Set attrs to false if invalid size or time */
811 		if (!NFS3_SIZE_OK(objp->attr.size)) {
812 			objp->attributes = FALSE;
813 			return (TRUE);
814 		}
815 #ifndef _LP64
816 		if (!NFS3_FATTR_TIME_OK(&objp->attr))
817 			objp->attributes = FALSE;
818 #endif
819 	}
820 	return (TRUE);
821 }
822 
823 static bool_t
824 xdr_wcc_data(XDR *xdrs, wcc_data *objp)
825 {
826 	int32_t *ptr;
827 	wcc_attr *attrp;
828 
829 	if (xdrs->x_op == XDR_FREE)
830 		return (TRUE);
831 
832 	if (xdrs->x_op == XDR_DECODE) {
833 		/* pre_op_attr */
834 		if (!xdr_bool(xdrs, &objp->before.attributes))
835 			return (FALSE);
836 
837 		switch (objp->before.attributes) {
838 		case TRUE:
839 			attrp = &objp->before.attr;
840 			ptr = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT);
841 			if (ptr != NULL) {
842 				IXDR_GET_U_HYPER(ptr, attrp->size);
843 				attrp->mtime.seconds = IXDR_GET_U_INT32(ptr);
844 				attrp->mtime.nseconds = IXDR_GET_U_INT32(ptr);
845 				attrp->ctime.seconds = IXDR_GET_U_INT32(ptr);
846 				attrp->ctime.nseconds = IXDR_GET_U_INT32(ptr);
847 			} else {
848 				if (!xdr_u_longlong_t(xdrs, &attrp->size))
849 					return (FALSE);
850 				if (!xdr_u_int(xdrs, &attrp->mtime.seconds))
851 					return (FALSE);
852 				if (!xdr_u_int(xdrs, &attrp->mtime.nseconds))
853 					return (FALSE);
854 				if (!xdr_u_int(xdrs, &attrp->ctime.seconds))
855 					return (FALSE);
856 				if (!xdr_u_int(xdrs, &attrp->ctime.nseconds))
857 					return (FALSE);
858 			}
859 
860 #ifndef _LP64
861 			/*
862 			 * check time overflow.
863 			 */
864 			if (!NFS3_TIME_OK(attrp->mtime.seconds) ||
865 			    !NFS3_TIME_OK(attrp->ctime.seconds))
866 				objp->before.attributes = FALSE;
867 #endif
868 			break;
869 		case FALSE:
870 			break;
871 		default:
872 			return (FALSE);
873 		}
874 	}
875 
876 	if (xdrs->x_op == XDR_ENCODE) {
877 		/* pre_op_attr */
878 		if (!xdr_bool(xdrs, &objp->before.attributes))
879 			return (FALSE);
880 
881 		switch (objp->before.attributes) {
882 		case TRUE:
883 			attrp = &objp->before.attr;
884 
885 			ptr = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT);
886 			if (ptr != NULL) {
887 				IXDR_PUT_U_HYPER(ptr, attrp->size);
888 				IXDR_PUT_U_INT32(ptr, attrp->mtime.seconds);
889 				IXDR_PUT_U_INT32(ptr, attrp->mtime.nseconds);
890 				IXDR_PUT_U_INT32(ptr, attrp->ctime.seconds);
891 				IXDR_PUT_U_INT32(ptr, attrp->ctime.nseconds);
892 			} else {
893 				if (!xdr_u_longlong_t(xdrs, &attrp->size))
894 					return (FALSE);
895 				if (!xdr_u_int(xdrs, &attrp->mtime.seconds))
896 					return (FALSE);
897 				if (!xdr_u_int(xdrs, &attrp->mtime.nseconds))
898 					return (FALSE);
899 				if (!xdr_u_int(xdrs, &attrp->ctime.seconds))
900 					return (FALSE);
901 				if (!xdr_u_int(xdrs, &attrp->ctime.nseconds))
902 					return (FALSE);
903 			}
904 			break;
905 		case FALSE:
906 			break;
907 		default:
908 			return (FALSE);
909 		}
910 	}
911 	return (xdr_post_op_attr(xdrs, &objp->after));
912 }
913 
914 bool_t
915 xdr_post_op_fh3(XDR *xdrs, post_op_fh3 *objp)
916 {
917 	if (!xdr_bool(xdrs, &objp->handle_follows))
918 		return (FALSE);
919 	switch (objp->handle_follows) {
920 	case TRUE:
921 		return (xdr_nfs_fh3(xdrs, &objp->handle));
922 	case FALSE:
923 		return (TRUE);
924 	default:
925 		return (FALSE);
926 	}
927 }
928 
929 static bool_t
930 xdr_sattr3(XDR *xdrs, sattr3 *objp)
931 {
932 	/* set_mode3 */
933 	if (!xdr_bool(xdrs, &objp->mode.set_it))
934 		return (FALSE);
935 	if (objp->mode.set_it)
936 		if (!xdr_u_int(xdrs, &objp->mode.mode))
937 			return (FALSE);
938 	/* set_uid3 */
939 	if (!xdr_bool(xdrs, &objp->uid.set_it))
940 		return (FALSE);
941 	if (objp->uid.set_it)
942 		if (!xdr_u_int(xdrs, &objp->uid.uid))
943 			return (FALSE);
944 	/* set_gid3 */
945 	if (!xdr_bool(xdrs, &objp->gid.set_it))
946 		return (FALSE);
947 	if (objp->gid.set_it)
948 		if (!xdr_u_int(xdrs, &objp->gid.gid))
949 			return (FALSE);
950 
951 	/* set_size3 */
952 	if (!xdr_bool(xdrs, &objp->size.set_it))
953 		return (FALSE);
954 	if (objp->size.set_it)
955 		if (!xdr_u_longlong_t(xdrs, &objp->size.size))
956 			return (FALSE);
957 
958 	/* set_atime */
959 	if (!xdr_enum(xdrs, (enum_t *)&objp->atime.set_it))
960 		return (FALSE);
961 	if (objp->atime.set_it == SET_TO_CLIENT_TIME) {
962 		if (!xdr_u_int(xdrs, &objp->atime.atime.seconds))
963 			return (FALSE);
964 		if (!xdr_u_int(xdrs, &objp->atime.atime.nseconds))
965 			return (FALSE);
966 	}
967 
968 	/* set_mtime */
969 	if (!xdr_enum(xdrs, (enum_t *)&objp->mtime.set_it))
970 		return (FALSE);
971 	if (objp->mtime.set_it == SET_TO_CLIENT_TIME) {
972 		if (!xdr_u_int(xdrs, &objp->mtime.mtime.seconds))
973 			return (FALSE);
974 		if (!xdr_u_int(xdrs, &objp->mtime.mtime.nseconds))
975 			return (FALSE);
976 	}
977 
978 	return (TRUE);
979 }
980 
981 bool_t
982 xdr_GETATTR3res(XDR *xdrs, GETATTR3res *objp)
983 {
984 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
985 		return (FALSE);
986 	if (objp->status != NFS3_OK)
987 		return (TRUE);
988 	/* xdr_GETATTR3resok */
989 	return (xdr_fattr3(xdrs, &objp->resok.obj_attributes));
990 }
991 
992 bool_t
993 xdr_GETATTR3vres(XDR *xdrs, GETATTR3vres *objp)
994 {
995 	/*
996 	 * DECODE or FREE only
997 	 */
998 	if (xdrs->x_op == XDR_FREE)
999 		return (TRUE);
1000 
1001 	if (xdrs->x_op != XDR_DECODE)
1002 		return (FALSE);
1003 
1004 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1005 		return (FALSE);
1006 
1007 	if (objp->status != NFS3_OK)
1008 		return (TRUE);
1009 
1010 	return (xdr_fattr3_to_vattr(xdrs, &objp->fres));
1011 }
1012 
1013 
1014 bool_t
1015 xdr_SETATTR3args(XDR *xdrs, SETATTR3args *objp)
1016 {
1017 	if (!xdr_nfs_fh3(xdrs, &objp->object))
1018 		return (FALSE);
1019 	if (!xdr_sattr3(xdrs, &objp->new_attributes))
1020 		return (FALSE);
1021 
1022 	/* sattrguard3 */
1023 	if (!xdr_bool(xdrs, &objp->guard.check))
1024 		return (FALSE);
1025 	switch (objp->guard.check) {
1026 	case TRUE:
1027 		if (!xdr_u_int(xdrs, &objp->guard.obj_ctime.seconds))
1028 			return (FALSE);
1029 		return (xdr_u_int(xdrs, &objp->guard.obj_ctime.nseconds));
1030 	case FALSE:
1031 		return (TRUE);
1032 	default:
1033 		return (FALSE);
1034 	}
1035 }
1036 
1037 bool_t
1038 xdr_SETATTR3res(XDR *xdrs, SETATTR3res *objp)
1039 {
1040 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1041 		return (FALSE);
1042 	switch (objp->status) {
1043 	case NFS3_OK:
1044 		return (xdr_wcc_data(xdrs, &objp->resok.obj_wcc));
1045 	default:
1046 		return (xdr_wcc_data(xdrs, &objp->resfail.obj_wcc));
1047 	}
1048 }
1049 
1050 bool_t
1051 xdr_LOOKUP3res(XDR *xdrs, LOOKUP3res *objp)
1052 {
1053 	LOOKUP3resok *resokp;
1054 
1055 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1056 		return (FALSE);
1057 
1058 	if (objp->status != NFS3_OK)
1059 		return (xdr_post_op_attr(xdrs, &objp->resfail.dir_attributes));
1060 
1061 	/* xdr_LOOKUP3resok */
1062 	resokp = &objp->resok;
1063 	if (!xdr_nfs_fh3(xdrs, &resokp->object))
1064 		return (FALSE);
1065 	if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
1066 		return (FALSE);
1067 	return (xdr_post_op_attr(xdrs, &resokp->dir_attributes));
1068 }
1069 
1070 bool_t
1071 xdr_LOOKUP3vres(XDR *xdrs, LOOKUP3vres *objp)
1072 {
1073 	/*
1074 	 * DECODE or FREE only
1075 	 */
1076 	if (xdrs->x_op == XDR_FREE)
1077 		return (TRUE);
1078 
1079 	if (xdrs->x_op != XDR_DECODE)
1080 		return (FALSE);
1081 
1082 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1083 		return (FALSE);
1084 
1085 	if (objp->status != NFS3_OK)
1086 		return (xdr_post_op_vattr(xdrs, &objp->dir_attributes));
1087 
1088 	if (!xdr_nfs_fh3(xdrs, &objp->object))
1089 		return (FALSE);
1090 	if (!xdr_post_op_vattr(xdrs, &objp->obj_attributes))
1091 		return (FALSE);
1092 	return (xdr_post_op_vattr(xdrs, &objp->dir_attributes));
1093 }
1094 
1095 bool_t
1096 xdr_ACCESS3args(XDR *xdrs, ACCESS3args *objp)
1097 {
1098 	int32_t *ptr;
1099 	int32_t *fhp;
1100 	int len;
1101 	uint_t in_size;
1102 
1103 	if (xdrs->x_op == XDR_FREE)
1104 		return (TRUE);
1105 
1106 	in_size = RNDUP(sizeof (fhandle_t)) +	2 * BYTES_PER_XDR_UNIT;
1107 	ptr = XDR_INLINE(xdrs, in_size);
1108 
1109 	if (ptr != NULL) {
1110 		len =  (xdrs->x_op == XDR_DECODE) ?
1111 			*ptr : objp->object.fh3_length;
1112 
1113 		if (XDR_CHECKFHSIZE(xdrs, len, in_size)) {
1114 			fhp = (int32_t *)&(objp->object.fh3_u.data);
1115 			if (xdrs->x_op == XDR_DECODE) {
1116 				objp->object.fh3_length = IXDR_GET_U_INT32(ptr);
1117 				*fhp++ = *ptr++;
1118 				*fhp++ = *ptr++;
1119 				*fhp++ = *ptr++;
1120 				*fhp++ = *ptr++;
1121 				*fhp++ = *ptr++;
1122 				*fhp++ = *ptr++;
1123 				*fhp++ = *ptr++;
1124 				*fhp = *ptr++;
1125 				objp->access = IXDR_GET_U_INT32(ptr);
1126 			} else {
1127 				IXDR_PUT_U_INT32(ptr, objp->object.fh3_length);
1128 				*ptr++ = *fhp++;
1129 				*ptr++ = *fhp++;
1130 				*ptr++ = *fhp++;
1131 				*ptr++ = *fhp++;
1132 				*ptr++ = *fhp++;
1133 				*ptr++ = *fhp++;
1134 				*ptr++ = *fhp++;
1135 				*ptr++ = *fhp;
1136 				IXDR_PUT_U_INT32(ptr, objp->access);
1137 			}
1138 			return (TRUE);
1139 		}
1140 	}
1141 
1142 	if (!xdr_nfs_fh3(xdrs, &objp->object))
1143 		return (FALSE);
1144 	return (xdr_u_int(xdrs, &objp->access));
1145 }
1146 
1147 
1148 bool_t
1149 xdr_ACCESS3res(XDR *xdrs, ACCESS3res *objp)
1150 {
1151 	ACCESS3resok *resokp;
1152 
1153 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1154 		return (FALSE);
1155 	if (objp->status != NFS3_OK)
1156 		return (xdr_post_op_attr(xdrs, &objp->resfail.obj_attributes));
1157 
1158 	/* xdr_ACCESS3resok */
1159 	resokp = &objp->resok;
1160 	if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
1161 		return (FALSE);
1162 	return (xdr_u_int(xdrs, &resokp->access));
1163 }
1164 
1165 bool_t
1166 xdr_READLINK3res(XDR *xdrs, READLINK3res *objp)
1167 {
1168 
1169 	READLINK3resok *resokp;
1170 
1171 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1172 		return (FALSE);
1173 	if (objp->status != NFS3_OK)
1174 		return (xdr_post_op_attr(xdrs,
1175 			&objp->resfail.symlink_attributes));
1176 
1177 	/* xdr_READLINK3resok */
1178 	resokp = &objp->resok;
1179 	if (!xdr_post_op_attr(xdrs, &resokp->symlink_attributes))
1180 		return (FALSE);
1181 	return (xdr_string3(xdrs, &resokp->data, MAXPATHLEN));
1182 }
1183 
1184 bool_t
1185 xdr_READ3args(XDR *xdrs, READ3args *objp)
1186 {
1187 	int32_t *ptr;
1188 	int32_t *fhp;
1189 	uint_t in_size;
1190 	int len;
1191 
1192 	if (xdrs->x_op == XDR_FREE)
1193 		return (TRUE);
1194 
1195 	in_size = RNDUP(sizeof (fhandle_t)) + 4 * BYTES_PER_XDR_UNIT;
1196 	ptr = XDR_INLINE(xdrs, in_size);
1197 	if (ptr != NULL) {
1198 		len = (xdrs->x_op == XDR_DECODE) ?
1199 			*ptr : objp->file.fh3_length;
1200 
1201 		if (XDR_CHECKFHSIZE(xdrs, len, in_size)) {
1202 			fhp = (int32_t *)& objp->file.fh3_u.data;
1203 			if (xdrs->x_op == XDR_DECODE) {
1204 				objp->file.fh3_length = IXDR_GET_U_INT32(ptr);
1205 				*fhp++ = *ptr++;
1206 				*fhp++ = *ptr++;
1207 				*fhp++ = *ptr++;
1208 				*fhp++ = *ptr++;
1209 				*fhp++ = *ptr++;
1210 				*fhp++ = *ptr++;
1211 				*fhp++ = *ptr++;
1212 				*fhp = *ptr++;
1213 				IXDR_GET_U_HYPER(ptr, objp->offset);
1214 				objp->count = IXDR_GET_U_INT32(ptr);
1215 			} else {
1216 				IXDR_PUT_U_INT32(ptr, objp->file.fh3_length);
1217 				*ptr++ = *fhp++;
1218 				*ptr++ = *fhp++;
1219 				*ptr++ = *fhp++;
1220 				*ptr++ = *fhp++;
1221 				*ptr++ = *fhp++;
1222 				*ptr++ = *fhp++;
1223 				*ptr++ = *fhp++;
1224 				*ptr++ = *fhp;
1225 				IXDR_PUT_U_HYPER(ptr, objp->offset);
1226 				IXDR_PUT_U_INT32(ptr, objp->count);
1227 			}
1228 			return (TRUE);
1229 		}
1230 	}
1231 
1232 	if (!xdr_nfs_fh3(xdrs, &objp->file))
1233 		return (FALSE);
1234 	if (!xdr_u_longlong_t(xdrs, &objp->offset))
1235 		return (FALSE);
1236 	return (xdr_u_int(xdrs, &objp->count));
1237 }
1238 
1239 bool_t
1240 xdr_READ3res(XDR *xdrs, READ3res *objp)
1241 {
1242 	READ3resok *resokp;
1243 	bool_t ret;
1244 	mblk_t *mp;
1245 
1246 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1247 		return (FALSE);
1248 
1249 	if (objp->status != NFS3_OK)
1250 		return (xdr_post_op_attr(xdrs, &objp->resfail.file_attributes));
1251 
1252 	resokp = &objp->resok;
1253 
1254 	if (xdr_post_op_attr(xdrs, &resokp->file_attributes) == FALSE ||
1255 	    xdr_u_int(xdrs, &resokp->count) == FALSE ||
1256 	    xdr_bool(xdrs, &resokp->eof) == FALSE) {
1257 		return (FALSE);
1258 	}
1259 
1260 	if (xdrs->x_op == XDR_ENCODE) {
1261 		int i, rndup;
1262 
1263 		mp = resokp->data.mp;
1264 		if (mp != NULL && xdrs->x_ops == &xdrmblk_ops) {
1265 			mp->b_wptr += resokp->count;
1266 			rndup = BYTES_PER_XDR_UNIT -
1267 				(resokp->data.data_len % BYTES_PER_XDR_UNIT);
1268 			if (rndup != BYTES_PER_XDR_UNIT)
1269 				for (i = 0; i < rndup; i++)
1270 					*mp->b_wptr++ = '\0';
1271 			if (xdrmblk_putmblk(xdrs, mp, resokp->count) == TRUE) {
1272 				resokp->data.mp = NULL;
1273 				return (TRUE);
1274 			}
1275 		}
1276 		/*
1277 		 * Fall thru for the xdr_bytes()
1278 		 *
1279 		 * note: the mblk will be freed in
1280 		 * rfs3_read_free.
1281 		 */
1282 	}
1283 
1284 	ret = xdr_bytes(xdrs, (char **)&resokp->data.data_val,
1285 	    &resokp->data.data_len, nfs3tsize());
1286 
1287 	return (ret);
1288 }
1289 
1290 bool_t
1291 xdr_READ3vres(XDR *xdrs, READ3vres *objp)
1292 {
1293 	/*
1294 	 * DECODE or FREE only
1295 	 */
1296 	if (xdrs->x_op == XDR_FREE)
1297 		return (TRUE);
1298 
1299 	if (xdrs->x_op != XDR_DECODE)
1300 		return (FALSE);
1301 
1302 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1303 		return (FALSE);
1304 
1305 	if (!xdr_post_op_vattr(xdrs, &objp->pov))
1306 		return (FALSE);
1307 
1308 	if (objp->status != NFS3_OK)
1309 		return (TRUE);
1310 
1311 	if (!xdr_u_int(xdrs, &objp->count))
1312 		return (FALSE);
1313 
1314 	if (!xdr_bool(xdrs, &objp->eof))
1315 		return (FALSE);
1316 
1317 	return (xdr_bytes(xdrs, (char **)&objp->data.data_val,
1318 	    &objp->data.data_len, nfs3tsize()));
1319 }
1320 
1321 bool_t
1322 xdr_READ3uiores(XDR *xdrs, READ3uiores *objp)
1323 {
1324 	bool_t attributes;
1325 	mblk_t *mp;
1326 	size_t n;
1327 	int error;
1328 	int size = (int)objp->size;
1329 	struct uio *uiop = objp->uiop;
1330 	int32_t fattr3_len = NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT;
1331 	int32_t *ptr;
1332 
1333 	/*
1334 	 * DECODE or FREE only
1335 	 */
1336 	if (xdrs->x_op == XDR_FREE)
1337 		return (TRUE);
1338 
1339 	if (xdrs->x_op != XDR_DECODE)
1340 		return (FALSE);
1341 
1342 	if (!XDR_GETINT32(xdrs, (int32_t *)&objp->status))
1343 		return (FALSE);
1344 
1345 	if (!XDR_GETINT32(xdrs, (int32_t *)&attributes))
1346 		return (FALSE);
1347 
1348 	/*
1349 	 * For directio we just skip over attributes if present
1350 	 */
1351 	switch (attributes) {
1352 	case TRUE:
1353 		if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &fattr3_len))
1354 			return (FALSE);
1355 		break;
1356 	case FALSE:
1357 		break;
1358 	default:
1359 		return (FALSE);
1360 	}
1361 
1362 	if (objp->status != NFS3_OK)
1363 		return (TRUE);
1364 
1365 	if (!XDR_GETINT32(xdrs, (int32_t *)&objp->count))
1366 		return (FALSE);
1367 
1368 	if (!XDR_GETINT32(xdrs, (int32_t *)&objp->eof))
1369 		return (FALSE);
1370 
1371 	if (xdrs->x_ops == &xdrmblk_ops) {
1372 		if (!xdrmblk_getmblk(xdrs, &mp, &objp->size))
1373 			return (FALSE);
1374 
1375 		if (objp->size == 0)
1376 			return (TRUE);
1377 
1378 		if (objp->size > size)
1379 			return (FALSE);
1380 
1381 		size = (int)objp->size;
1382 		do {
1383 			n = MIN(size, mp->b_wptr - mp->b_rptr);
1384 			if ((n = MIN(uiop->uio_resid, n)) != 0) {
1385 
1386 				error = uiomove((char *)mp->b_rptr, n, UIO_READ,
1387 						uiop);
1388 				if (error)
1389 					return (FALSE);
1390 				mp->b_rptr += n;
1391 				size -= n;
1392 			}
1393 
1394 			while (mp && (mp->b_rptr >= mp->b_wptr))
1395 				mp = mp->b_cont;
1396 		} while (mp && size > 0 && uiop->uio_resid > 0);
1397 
1398 		return (TRUE);
1399 	}
1400 
1401 	/*
1402 	 * This isn't an xdrmblk stream.   Handle the likely
1403 	 * case that it can be inlined (ex. xdrmem).
1404 	 */
1405 	if (!XDR_GETINT32(xdrs, (int32_t *)&objp->size))
1406 		return (FALSE);
1407 
1408 	if (objp->size == 0)
1409 		return (TRUE);
1410 
1411 	if (objp->size > size)
1412 		return (FALSE);
1413 
1414 	size = (int)objp->size;
1415 	if ((ptr = XDR_INLINE(xdrs, size)) != NULL)
1416 		return (uiomove(ptr, size, UIO_READ, uiop) ? FALSE : TRUE);
1417 
1418 	/*
1419 	 * Handle some other (unlikely) stream type that will need a copy.
1420 	 */
1421 	if ((ptr = kmem_alloc(size, KM_NOSLEEP)) == NULL)
1422 		return (FALSE);
1423 
1424 	if (!XDR_GETBYTES(xdrs, (caddr_t)ptr, size)) {
1425 		kmem_free(ptr, size);
1426 		return (FALSE);
1427 	}
1428 	error = uiomove(ptr, size, UIO_READ, uiop);
1429 	kmem_free(ptr, size);
1430 
1431 	return (error ? FALSE : TRUE);
1432 }
1433 
1434 bool_t
1435 xdr_WRITE3args(XDR *xdrs, WRITE3args *objp)
1436 {
1437 	int32_t *ptr;
1438 	int32_t *fhp;
1439 	uint_t in_size;
1440 	int len;
1441 
1442 	in_size = RNDUP(sizeof (fhandle_t)) + 5 * BYTES_PER_XDR_UNIT;
1443 	ptr = XDR_INLINE(xdrs, in_size);
1444 
1445 	if (ptr != NULL) {
1446 		len = (xdrs->x_op == XDR_DECODE) ? *ptr : objp->file.fh3_length;
1447 
1448 		if (XDR_CHECKFHSIZE(xdrs, len, in_size)) {
1449 			fhp = (int32_t *)&(objp->file.fh3_u.data);
1450 			if (xdrs->x_op == XDR_DECODE) {
1451 				objp->file.fh3_length = IXDR_GET_U_INT32(ptr);
1452 				*fhp++ = *ptr++;
1453 				*fhp++ = *ptr++;
1454 				*fhp++ = *ptr++;
1455 				*fhp++ = *ptr++;
1456 				*fhp++ = *ptr++;
1457 				*fhp++ = *ptr++;
1458 				*fhp++ = *ptr++;
1459 				*fhp = *ptr++;
1460 				IXDR_GET_U_HYPER(ptr, objp->offset);
1461 				objp->count = IXDR_GET_U_INT32(ptr);
1462 				objp->stable = IXDR_GET_ENUM(ptr,
1463 						enum stable_how);
1464 				if (xdrs->x_ops == &xdrmblk_ops)
1465 					return (xdrmblk_getmblk(xdrs,
1466 					&objp->mblk,
1467 					(uint_t *)&objp->data.data_len));
1468 				/*
1469 				 * It is just as efficient to xdr_bytes
1470 				 * an array of unknown length as to inline
1471 				 * copy it.
1472 				 */
1473 				return (xdr_bytes(xdrs, &objp->data.data_val,
1474 						(uint_t *)&objp->data.data_len,
1475 						nfs3tsize()));
1476 			}
1477 
1478 			if (xdrs->x_op == XDR_ENCODE) {
1479 				IXDR_PUT_U_INT32(ptr, objp->file.fh3_length);
1480 				*ptr++ = *fhp++;
1481 				*ptr++ = *fhp++;
1482 				*ptr++ = *fhp++;
1483 				*ptr++ = *fhp++;
1484 				*ptr++ = *fhp++;
1485 				*ptr++ = *fhp++;
1486 				*ptr++ = *fhp++;
1487 				*ptr++ = *fhp;
1488 				IXDR_PUT_U_HYPER(ptr, objp->offset);
1489 				IXDR_PUT_U_INT32(ptr, objp->count);
1490 				IXDR_PUT_ENUM(ptr, objp->stable);
1491 				return (xdr_bytes(xdrs,
1492 					(char **)&objp->data.data_val,
1493 					(uint_t *)&objp->data.data_len,
1494 					nfs3tsize()));
1495 			}
1496 
1497 			ASSERT(xdrs->x_op == XDR_FREE);
1498 			if (objp->data.data_val != NULL) {
1499 				kmem_free(objp->data.data_val,
1500 					(uint_t)objp->data.data_len);
1501 				objp->data.data_val = NULL;
1502 			}
1503 			return (TRUE);
1504 		}
1505 	}
1506 
1507 	if (!xdr_nfs_fh3(xdrs, &objp->file))
1508 		return (FALSE);
1509 	if (!xdr_u_longlong_t(xdrs, &objp->offset))
1510 		return (FALSE);
1511 	if (!xdr_u_int(xdrs, &objp->count))
1512 		return (FALSE);
1513 	if (!xdr_enum(xdrs, (enum_t *)&objp->stable))
1514 		return (FALSE);
1515 
1516 	if (xdrs->x_op == XDR_DECODE) {
1517 		if (xdrs->x_ops == &xdrmblk_ops) {
1518 			if (xdrmblk_getmblk(xdrs, &objp->mblk,
1519 			    &objp->data.data_len) == TRUE) {
1520 				objp->data.data_val = NULL;
1521 				return (TRUE);
1522 			}
1523 		}
1524 		objp->mblk = NULL;
1525 		/* Else fall thru for the xdr_bytes(). */
1526 	}
1527 
1528 	return (xdr_bytes(xdrs, (char **)&objp->data.data_val,
1529 	    &objp->data.data_len, nfs3tsize()));
1530 }
1531 
1532 bool_t
1533 xdr_WRITE3res(XDR *xdrs, WRITE3res *objp)
1534 {
1535 	WRITE3resok *resokp;
1536 
1537 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1538 		return (FALSE);
1539 	if (objp->status != NFS3_OK) /* xdr_WRITE3resfail */
1540 		return (xdr_wcc_data(xdrs, &objp->resfail.file_wcc));
1541 
1542 	/* xdr_WRITE3resok */
1543 	resokp = &objp->resok;
1544 	if (!xdr_wcc_data(xdrs, &resokp->file_wcc))
1545 		return (FALSE);
1546 	if (!xdr_u_int(xdrs, &resokp->count))
1547 		return (FALSE);
1548 	if (!xdr_enum(xdrs, (enum_t *)&resokp->committed))
1549 		return (FALSE);
1550 	/*
1551 	 * writeverf3 is really an opaque 8 byte
1552 	 * quantity, but we will treat it as a
1553 	 * hyper for efficiency, the cost of
1554 	 * a byteswap here saves bcopys elsewhere
1555 	 */
1556 	return (xdr_u_longlong_t(xdrs, &resokp->verf));
1557 }
1558 
1559 bool_t
1560 xdr_CREATE3args(XDR *xdrs, CREATE3args *objp)
1561 {
1562 	createhow3 *howp;
1563 
1564 	if (!xdr_diropargs3(xdrs, &objp->where))
1565 		return (FALSE);
1566 
1567 	/* xdr_createhow3 */
1568 	howp = &objp->how;
1569 
1570 	if (!xdr_enum(xdrs, (enum_t *)&howp->mode))
1571 		return (FALSE);
1572 	switch (howp->mode) {
1573 	case UNCHECKED:
1574 	case GUARDED:
1575 		return (xdr_sattr3(xdrs, &howp->createhow3_u.obj_attributes));
1576 	case EXCLUSIVE:
1577 		/*
1578 		 * createverf3 is really an opaque 8 byte
1579 		 * quantity, but we will treat it as a
1580 		 * hyper for efficiency, the cost of
1581 		 * a byteswap here saves bcopys elsewhere
1582 		 */
1583 		return (xdr_u_longlong_t(xdrs, &howp->createhow3_u.verf));
1584 	default:
1585 		return (FALSE);
1586 	}
1587 }
1588 
1589 bool_t
1590 xdr_CREATE3res(XDR *xdrs, CREATE3res *objp)
1591 {
1592 	CREATE3resok *resokp;
1593 
1594 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1595 		return (FALSE);
1596 	switch (objp->status) {
1597 	case NFS3_OK:
1598 		/* xdr_CREATE3resok */
1599 		resokp = &objp->resok;
1600 
1601 		if (!xdr_post_op_fh3(xdrs, &resokp->obj))
1602 			return (FALSE);
1603 		if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
1604 			return (FALSE);
1605 		return (xdr_wcc_data(xdrs, &resokp->dir_wcc));
1606 	default:
1607 		/* xdr_CREATE3resfail */
1608 		return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
1609 	}
1610 }
1611 
1612 bool_t
1613 xdr_MKDIR3args(XDR *xdrs, MKDIR3args *objp)
1614 {
1615 	if (!xdr_diropargs3(xdrs, &objp->where))
1616 		return (FALSE);
1617 	return (xdr_sattr3(xdrs, &objp->attributes));
1618 }
1619 
1620 bool_t
1621 xdr_MKDIR3res(XDR *xdrs, MKDIR3res *objp)
1622 {
1623 	MKDIR3resok *resokp;
1624 
1625 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1626 		return (FALSE);
1627 	switch (objp->status) {
1628 	case NFS3_OK:
1629 		/* xdr_MKDIR3resok */
1630 		resokp = &objp->resok;
1631 
1632 		if (!xdr_post_op_fh3(xdrs, &resokp->obj))
1633 			return (FALSE);
1634 		if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
1635 			return (FALSE);
1636 		return (xdr_wcc_data(xdrs, &resokp->dir_wcc));
1637 	default:
1638 		return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
1639 	}
1640 }
1641 
1642 bool_t
1643 xdr_SYMLINK3args(XDR *xdrs, SYMLINK3args *objp)
1644 {
1645 	if (!xdr_diropargs3(xdrs, &objp->where))
1646 		return (FALSE);
1647 	if (!xdr_sattr3(xdrs, &objp->symlink.symlink_attributes))
1648 		return (FALSE);
1649 	return (xdr_string3(xdrs, &objp->symlink.symlink_data, MAXPATHLEN));
1650 }
1651 
1652 bool_t
1653 xdr_SYMLINK3res(XDR *xdrs, SYMLINK3res *objp)
1654 {
1655 	SYMLINK3resok *resokp;
1656 
1657 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1658 		return (FALSE);
1659 	switch (objp->status) {
1660 	case NFS3_OK:
1661 		resokp = &objp->resok;
1662 		/* xdr_SYMLINK3resok */
1663 		if (!xdr_post_op_fh3(xdrs, &resokp->obj))
1664 			return (FALSE);
1665 		if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
1666 			return (FALSE);
1667 		return (xdr_wcc_data(xdrs, &resokp->dir_wcc));
1668 	default:
1669 		return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
1670 	}
1671 }
1672 
1673 bool_t
1674 xdr_MKNOD3args(XDR *xdrs, MKNOD3args *objp)
1675 {
1676 	mknoddata3 *whatp;
1677 	devicedata3 *nod_objp;
1678 
1679 	if (!xdr_diropargs3(xdrs, &objp->where))
1680 		return (FALSE);
1681 
1682 	whatp = &objp->what;
1683 	if (!xdr_enum(xdrs, (enum_t *)&whatp->type))
1684 		return (FALSE);
1685 	switch (whatp->type) {
1686 	case NF3CHR:
1687 	case NF3BLK:
1688 		/* xdr_devicedata3 */
1689 		nod_objp = &whatp->mknoddata3_u.device;
1690 		if (!xdr_sattr3(xdrs, &nod_objp->dev_attributes))
1691 			return (FALSE);
1692 		if (!xdr_u_int(xdrs, &nod_objp->spec.specdata1))
1693 			return (FALSE);
1694 		return (xdr_u_int(xdrs, &nod_objp->spec.specdata2));
1695 	case NF3SOCK:
1696 	case NF3FIFO:
1697 		return (xdr_sattr3(xdrs, &whatp->mknoddata3_u.pipe_attributes));
1698 	default:
1699 		break;
1700 	}
1701 	return (TRUE);
1702 }
1703 
1704 bool_t
1705 xdr_MKNOD3res(XDR *xdrs, MKNOD3res *objp)
1706 {
1707 	MKNOD3resok *resokp;
1708 
1709 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1710 		return (FALSE);
1711 	switch (objp->status) {
1712 	case NFS3_OK:
1713 		/* xdr_MKNOD3resok */
1714 		resokp = &objp->resok;
1715 		if (!xdr_post_op_fh3(xdrs, &resokp->obj))
1716 			return (FALSE);
1717 		if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
1718 			return (FALSE);
1719 		return (xdr_wcc_data(xdrs, &resokp->dir_wcc));
1720 	default:
1721 		return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
1722 	}
1723 }
1724 
1725 bool_t
1726 xdr_REMOVE3res(XDR *xdrs, REMOVE3res *objp)
1727 {
1728 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1729 		return (FALSE);
1730 	switch (objp->status) {
1731 	case NFS3_OK:
1732 		return (xdr_wcc_data(xdrs, &objp->resok.dir_wcc));
1733 	default:
1734 		return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
1735 	}
1736 }
1737 
1738 bool_t
1739 xdr_RMDIR3res(XDR *xdrs, RMDIR3res *objp)
1740 {
1741 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1742 		return (FALSE);
1743 	switch (objp->status) {
1744 	case NFS3_OK:
1745 		return (xdr_wcc_data(xdrs, &objp->resok.dir_wcc));
1746 	default:
1747 		return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
1748 	}
1749 }
1750 
1751 bool_t
1752 xdr_RENAME3args(XDR *xdrs, RENAME3args *objp)
1753 {
1754 	if (!xdr_diropargs3(xdrs, &objp->from))
1755 		return (FALSE);
1756 	return (xdr_diropargs3(xdrs, &objp->to));
1757 }
1758 
1759 bool_t
1760 xdr_RENAME3res(XDR *xdrs, RENAME3res *objp)
1761 {
1762 	RENAME3resok *resokp;
1763 	RENAME3resfail *resfailp;
1764 
1765 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1766 		return (FALSE);
1767 	switch (objp->status) {
1768 	case NFS3_OK:
1769 		/* xdr_RENAME3resok */
1770 		resokp = &objp->resok;
1771 
1772 		if (!xdr_wcc_data(xdrs, &resokp->fromdir_wcc))
1773 			return (FALSE);
1774 		return (xdr_wcc_data(xdrs, &resokp->todir_wcc));
1775 	default:
1776 		/* xdr_RENAME3resfail */
1777 		resfailp = &objp->resfail;
1778 		if (!xdr_wcc_data(xdrs, &resfailp->fromdir_wcc))
1779 			return (FALSE);
1780 		return (xdr_wcc_data(xdrs, &resfailp->todir_wcc));
1781 	}
1782 }
1783 
1784 bool_t
1785 xdr_LINK3args(XDR *xdrs, LINK3args *objp)
1786 {
1787 	if (!xdr_nfs_fh3(xdrs, &objp->file))
1788 		return (FALSE);
1789 	return (xdr_diropargs3(xdrs, &objp->link));
1790 }
1791 
1792 bool_t
1793 xdr_LINK3res(XDR *xdrs, LINK3res *objp)
1794 {
1795 	LINK3resok *resokp;
1796 	LINK3resfail *resfailp;
1797 
1798 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1799 		return (FALSE);
1800 	switch (objp->status) {
1801 	case NFS3_OK:
1802 		/* xdr_LINK3resok */
1803 		resokp = &objp->resok;
1804 		if (!xdr_post_op_attr(xdrs, &resokp->file_attributes))
1805 			return (FALSE);
1806 		return (xdr_wcc_data(xdrs, &resokp->linkdir_wcc));
1807 	default:
1808 		/* xdr_LINK3resfail */
1809 		resfailp = &objp->resfail;
1810 		if (!xdr_post_op_attr(xdrs, &resfailp->file_attributes))
1811 			return (FALSE);
1812 		return (xdr_wcc_data(xdrs, &resfailp->linkdir_wcc));
1813 	}
1814 }
1815 
1816 bool_t
1817 xdr_READDIR3args(XDR *xdrs, READDIR3args *objp)
1818 {
1819 	int32_t *ptr;
1820 	int32_t *fhp;
1821 	uint_t in_size;
1822 	int len;
1823 
1824 	if (xdrs->x_op == XDR_FREE)
1825 		return (TRUE);
1826 
1827 	in_size = RNDUP(sizeof (fhandle_t)) + NFS3_COOKIEVERFSIZE +
1828 		4 * BYTES_PER_XDR_UNIT;
1829 	ptr = XDR_INLINE(xdrs, in_size);
1830 
1831 	if (ptr != NULL) {
1832 		len = (xdrs->x_op == XDR_DECODE) ? *ptr : objp->dir.fh3_length;
1833 
1834 		if (XDR_CHECKFHSIZE(xdrs, len, in_size)) {
1835 
1836 			fhp = (int32_t *)&(objp->dir.fh3_u.data);
1837 
1838 			if (xdrs->x_op == XDR_DECODE) {
1839 				objp->dir.fh3_length = IXDR_GET_U_INT32(ptr);
1840 				*fhp++ = *ptr++;
1841 				*fhp++ = *ptr++;
1842 				*fhp++ = *ptr++;
1843 				*fhp++ = *ptr++;
1844 				*fhp++ = *ptr++;
1845 				*fhp++ = *ptr++;
1846 				*fhp++ = *ptr++;
1847 				*fhp = *ptr++;
1848 				IXDR_GET_U_HYPER(ptr, objp->cookie);
1849 				/*
1850 				 * cookieverf is really an opaque 8 byte
1851 				 * quantity, but we will treat it as a
1852 				 * hyper for efficiency, the cost of
1853 				 * a byteswap here saves bcopys elsewhere
1854 				 */
1855 				IXDR_GET_U_HYPER(ptr, objp->cookieverf);
1856 				objp->count = IXDR_GET_U_INT32(ptr);
1857 			} else {
1858 				IXDR_PUT_U_INT32(ptr, objp->dir.fh3_length);
1859 				*ptr++ = *fhp++;
1860 				*ptr++ = *fhp++;
1861 				*ptr++ = *fhp++;
1862 				*ptr++ = *fhp++;
1863 				*ptr++ = *fhp++;
1864 				*ptr++ = *fhp++;
1865 				*ptr++ = *fhp++;
1866 				*ptr++ = *fhp;
1867 				IXDR_PUT_U_HYPER(ptr, objp->cookie);
1868 				/*
1869 				 * cookieverf is really an opaque 8 byte
1870 				 * quantity, but we will treat it as a
1871 				 * hyper for efficiency, the cost of
1872 				 * a byteswap here saves bcopys elsewhere
1873 				 */
1874 				IXDR_PUT_U_HYPER(ptr, objp->cookieverf);
1875 				IXDR_PUT_U_INT32(ptr, objp->count);
1876 			}
1877 			return (TRUE);
1878 		}
1879 	}
1880 
1881 	if (!xdr_nfs_fh3(xdrs, &objp->dir))
1882 		return (FALSE);
1883 	if (!xdr_u_longlong_t(xdrs, &objp->cookie))
1884 		return (FALSE);
1885 	/*
1886 	 * cookieverf is really an opaque 8 byte
1887 	 * quantity, but we will treat it as a
1888 	 * hyper for efficiency, the cost of
1889 	 * a byteswap here saves bcopys elsewhere
1890 	 */
1891 	if (!xdr_u_longlong_t(xdrs, &objp->cookieverf))
1892 		return (FALSE);
1893 	return (xdr_u_int(xdrs, &objp->count));
1894 }
1895 
1896 #ifdef	nextdp
1897 #undef	nextdp
1898 #endif
1899 #define	nextdp(dp)	((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
1900 #ifdef	roundup
1901 #undef	roundup
1902 #endif
1903 #define	roundup(x, y)	((((x) + ((y) - 1)) / (y)) * (y))
1904 
1905 /*
1906  * ENCODE ONLY
1907  */
1908 static bool_t
1909 xdr_putdirlist(XDR *xdrs, READDIR3resok *objp)
1910 {
1911 	struct dirent64 *dp;
1912 	char *name;
1913 	int size;
1914 	int bufsize;
1915 	uint_t namlen;
1916 	bool_t true = TRUE;
1917 	bool_t false = FALSE;
1918 	int entrysz;
1919 	int tofit;
1920 	fileid3 fileid;
1921 	cookie3 cookie;
1922 
1923 	if (xdrs->x_op != XDR_ENCODE)
1924 		return (FALSE);
1925 
1926 	/*
1927 	 * bufsize is used to keep track of the size of the response.
1928 	 * It is primed with:
1929 	 *	1 for the status +
1930 	 *	1 for the dir_attributes.attributes boolean +
1931 	 *	2 for the cookie verifier
1932 	 * all times BYTES_PER_XDR_UNIT to convert from XDR units
1933 	 * to bytes.  If there are directory attributes to be
1934 	 * returned, then:
1935 	 *	NFS3_SIZEOF_FATTR3 for the dir_attributes.attr fattr3
1936 	 * time BYTES_PER_XDR_UNIT is added to account for them.
1937 	 */
1938 	bufsize = (1 + 1 + 2) * BYTES_PER_XDR_UNIT;
1939 	if (objp->dir_attributes.attributes)
1940 		bufsize += NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT;
1941 	for (size = objp->size, dp = (struct dirent64 *)objp->reply.entries;
1942 	    size > 0;
1943 	    size -= dp->d_reclen, dp = nextdp(dp)) {
1944 		if (dp->d_reclen == 0)
1945 			return (FALSE);
1946 		if (dp->d_ino == 0)
1947 			continue;
1948 		name = dp->d_name;
1949 		namlen = (uint_t)strlen(dp->d_name);
1950 		/*
1951 		 * An entry is composed of:
1952 		 *	1 for the true/false list indicator +
1953 		 *	2 for the fileid +
1954 		 *	1 for the length of the name +
1955 		 *	2 for the cookie +
1956 		 * all times BYTES_PER_XDR_UNIT to convert from
1957 		 * XDR units to bytes, plus the length of the name
1958 		 * rounded up to the nearest BYTES_PER_XDR_UNIT.
1959 		 */
1960 		entrysz = (1 + 2 + 1 + 2) * BYTES_PER_XDR_UNIT +
1961 		    roundup(namlen, BYTES_PER_XDR_UNIT);
1962 		/*
1963 		 * We need to check to see if the number of bytes left
1964 		 * to go into the buffer will actually fit into the
1965 		 * buffer.  This is calculated as the size of this
1966 		 * entry plus:
1967 		 *	1 for the true/false list indicator +
1968 		 *	1 for the eof indicator
1969 		 * times BYTES_PER_XDR_UNIT to convert from from
1970 		 * XDR units to bytes.
1971 		 */
1972 		tofit = entrysz + (1 + 1) * BYTES_PER_XDR_UNIT;
1973 		if (bufsize + tofit > objp->count) {
1974 			objp->reply.eof = FALSE;
1975 			break;
1976 		}
1977 		fileid = (fileid3)(dp->d_ino);
1978 		cookie = (cookie3)(dp->d_off);
1979 		if (!xdr_bool(xdrs, &true) ||
1980 		    !xdr_u_longlong_t(xdrs, &fileid) ||
1981 		    !xdr_bytes(xdrs, &name, &namlen, ~0) ||
1982 		    !xdr_u_longlong_t(xdrs, &cookie)) {
1983 			return (FALSE);
1984 		}
1985 		bufsize += entrysz;
1986 	}
1987 	if (!xdr_bool(xdrs, &false))
1988 		return (FALSE);
1989 	if (!xdr_bool(xdrs, &objp->reply.eof))
1990 		return (FALSE);
1991 	return (TRUE);
1992 }
1993 
1994 bool_t
1995 xdr_READDIR3res(XDR *xdrs, READDIR3res *objp)
1996 {
1997 	READDIR3resok *resokp;
1998 
1999 	/*
2000 	 * ENCODE or FREE only
2001 	 */
2002 	if (xdrs->x_op == XDR_DECODE)
2003 		return (FALSE);
2004 
2005 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
2006 		return (FALSE);
2007 	if (objp->status != NFS3_OK)
2008 		return (xdr_post_op_attr(xdrs, &objp->resfail.dir_attributes));
2009 
2010 	/* xdr_READDIR3resok */
2011 	resokp = &objp->resok;
2012 	if (!xdr_post_op_attr(xdrs, &resokp->dir_attributes))
2013 		return (FALSE);
2014 	if (xdrs->x_op != XDR_ENCODE)
2015 		return (TRUE);
2016 	/*
2017 	 * cookieverf is really an opaque 8 byte
2018 	 * quantity, but we will treat it as a
2019 	 * hyper for efficiency, the cost of
2020 	 * a byteswap here saves bcopys elsewhere
2021 	 */
2022 	if (!xdr_u_longlong_t(xdrs, &resokp->cookieverf))
2023 		return (FALSE);
2024 	return (xdr_putdirlist(xdrs, resokp));
2025 }
2026 
2027 bool_t
2028 xdr_READDIR3vres(XDR *xdrs, READDIR3vres *objp)
2029 {
2030 	dirent64_t *dp;
2031 	uint_t entries_size;
2032 	int outcount = 0;
2033 
2034 	/*
2035 	 * DECODE or FREE only
2036 	 */
2037 	if (xdrs->x_op == XDR_FREE)
2038 		return (TRUE);
2039 
2040 	if (xdrs->x_op != XDR_DECODE)
2041 		return (FALSE);
2042 
2043 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
2044 		return (FALSE);
2045 
2046 	if (!xdr_post_op_vattr(xdrs, &objp->dir_attributes))
2047 		return (FALSE);
2048 
2049 	if (objp->status != NFS3_OK)
2050 		return (TRUE);
2051 
2052 	/*
2053 	 * cookieverf is really an opaque 8 byte
2054 	 * quantity, but we will treat it as a
2055 	 * hyper for efficiency, the cost of
2056 	 * a byteswap here saves bcopys elsewhere
2057 	 */
2058 	if (!xdr_u_longlong_t(xdrs, &objp->cookieverf))
2059 		return (FALSE);
2060 
2061 	entries_size = objp->entries_size;
2062 	dp = objp->entries;
2063 
2064 	for (;;) {
2065 		uint_t this_reclen;
2066 		bool_t valid;
2067 		uint_t namlen;
2068 		ino64_t fileid;
2069 
2070 		if (!XDR_GETINT32(xdrs, (int32_t *)&valid))
2071 			return (FALSE);
2072 		if (!valid) {
2073 			/*
2074 			 * We have run out of entries, decode eof.
2075 			 */
2076 			if (!XDR_GETINT32(xdrs, (int32_t *)&objp->eof))
2077 				return (FALSE);
2078 
2079 			break;
2080 		}
2081 
2082 		/*
2083 		 * fileid3 fileid
2084 		 */
2085 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&fileid))
2086 			return (FALSE);
2087 
2088 		/*
2089 		 * filename3 name
2090 		 */
2091 		if (!XDR_GETINT32(xdrs, (int32_t *)&namlen))
2092 			return (FALSE);
2093 		this_reclen = DIRENT64_RECLEN(namlen);
2094 
2095 		/*
2096 		 * If this will overflow buffer, stop decoding
2097 		 */
2098 		if ((outcount + this_reclen) > entries_size) {
2099 			objp->eof = FALSE;
2100 			break;
2101 		}
2102 		dp->d_reclen = this_reclen;
2103 		dp->d_ino = fileid;
2104 
2105 		if (!xdr_opaque(xdrs, dp->d_name, namlen))
2106 			return (FALSE);
2107 		bzero(&dp->d_name[namlen],
2108 		    DIRENT64_NAMELEN(this_reclen) - namlen);
2109 
2110 		/*
2111 		 * cookie3 cookie
2112 		 */
2113 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&dp->d_off))
2114 			return (FALSE);
2115 		objp->loff = dp->d_off;
2116 
2117 		outcount += this_reclen;
2118 		dp = (dirent64_t *)((intptr_t)dp + this_reclen);
2119 	}
2120 
2121 	objp->size = outcount;
2122 	return (TRUE);
2123 }
2124 
2125 bool_t
2126 xdr_READDIRPLUS3args(XDR *xdrs, READDIRPLUS3args *objp)
2127 {
2128 	int32_t *ptr;
2129 	int32_t *fhp;
2130 	uint_t in_size;
2131 	int len;
2132 
2133 	if (xdrs->x_op == XDR_FREE)
2134 		return (TRUE);
2135 
2136 	in_size = RNDUP(sizeof (fhandle_t)) + NFS3_COOKIEVERFSIZE +
2137 		5 * BYTES_PER_XDR_UNIT;
2138 
2139 	ptr = XDR_INLINE(xdrs, in_size);
2140 	if (ptr != NULL) {
2141 		len = (xdrs->x_op == XDR_DECODE) ? *ptr : objp->dir.fh3_length;
2142 
2143 		if (XDR_CHECKFHSIZE(xdrs, len, in_size)) {
2144 
2145 			fhp = (int32_t *)&(objp->dir.fh3_u.data);
2146 
2147 			if (xdrs->x_op == XDR_DECODE) {
2148 				objp->dir.fh3_length = IXDR_GET_U_INT32(ptr);
2149 				*fhp++ = *ptr++;
2150 				*fhp++ = *ptr++;
2151 				*fhp++ = *ptr++;
2152 				*fhp++ = *ptr++;
2153 				*fhp++ = *ptr++;
2154 				*fhp++ = *ptr++;
2155 				*fhp++ = *ptr++;
2156 				*fhp = *ptr++;
2157 				IXDR_GET_U_HYPER(ptr, objp->cookie);
2158 				/*
2159 				 * cookieverf is really an opaque 8 byte
2160 				 * quantity, but we will treat it as a
2161 				 * hyper for efficiency, the cost of
2162 				 * a byteswap here saves bcopys elsewhere
2163 				 */
2164 				IXDR_GET_U_HYPER(ptr, objp->cookieverf);
2165 				objp->dircount = IXDR_GET_U_INT32(ptr);
2166 				objp->maxcount = IXDR_GET_U_INT32(ptr);
2167 			} else {
2168 				IXDR_PUT_U_INT32(ptr, objp->dir.fh3_length);
2169 				*ptr++ = *fhp++;
2170 				*ptr++ = *fhp++;
2171 				*ptr++ = *fhp++;
2172 				*ptr++ = *fhp++;
2173 				*ptr++ = *fhp++;
2174 				*ptr++ = *fhp++;
2175 				*ptr++ = *fhp++;
2176 				*ptr++ = *fhp;
2177 				IXDR_PUT_U_HYPER(ptr, objp->cookie);
2178 				/*
2179 				 * cookieverf is really an opaque 8 byte
2180 				 * quantity, but we will treat it as a
2181 				 * hyper for efficiency, the cost of
2182 				 * a byteswap here saves bcopys elsewhere
2183 				 */
2184 				IXDR_PUT_U_HYPER(ptr, objp->cookieverf);
2185 				IXDR_PUT_U_INT32(ptr, objp->dircount);
2186 				IXDR_PUT_U_INT32(ptr, objp->maxcount);
2187 			}
2188 			return (TRUE);
2189 		}
2190 	}
2191 
2192 	if (!xdr_nfs_fh3(xdrs, &objp->dir))
2193 		return (FALSE);
2194 	if (!xdr_u_longlong_t(xdrs, &objp->cookie))
2195 		return (FALSE);
2196 	/*
2197 	 * cookieverf is really an opaque 8 byte
2198 	 * quantity, but we will treat it as a
2199 	 * hyper for efficiency, the cost of
2200 	 * a byteswap here saves bcopys elsewhere
2201 	 */
2202 	if (!xdr_u_longlong_t(xdrs, &objp->cookieverf))
2203 		return (FALSE);
2204 	if (!xdr_u_int(xdrs, &objp->dircount))
2205 		return (FALSE);
2206 	return (xdr_u_int(xdrs, &objp->maxcount));
2207 
2208 }
2209 
2210 /*
2211  * ENCODE ONLY
2212  */
2213 static bool_t
2214 xdr_putdirpluslist(XDR *xdrs, READDIRPLUS3resok *objp)
2215 {
2216 	struct dirent64 *dp;
2217 	char *name;
2218 	int nents;
2219 	bool_t true = TRUE;
2220 	bool_t false = FALSE;
2221 	fileid3 fileid;
2222 	cookie3 cookie;
2223 	entryplus3_info *infop;
2224 
2225 	if (xdrs->x_op != XDR_ENCODE)
2226 		return (FALSE);
2227 
2228 	dp = (struct dirent64 *)objp->reply.entries;
2229 	nents = objp->size;
2230 	infop = objp->infop;
2231 
2232 	while (nents > 0) {
2233 		if (dp->d_reclen == 0)
2234 			return (FALSE);
2235 		if (dp->d_ino != 0) {
2236 			name = dp->d_name;
2237 			fileid = (fileid3)(dp->d_ino);
2238 			cookie = (cookie3)(dp->d_off);
2239 			if (!xdr_bool(xdrs, &true) ||
2240 			    !xdr_u_longlong_t(xdrs, &fileid) ||
2241 			    !xdr_bytes(xdrs, &name, &infop->namelen, ~0) ||
2242 			    !xdr_u_longlong_t(xdrs, &cookie) ||
2243 			    !xdr_post_op_attr(xdrs, &infop->attr) ||
2244 			    !xdr_post_op_fh3(xdrs, &infop->fh)) {
2245 				return (FALSE);
2246 			}
2247 		}
2248 		dp = nextdp(dp);
2249 		infop++;
2250 		nents--;
2251 	}
2252 
2253 	if (!xdr_bool(xdrs, &false))
2254 		return (FALSE);
2255 	if (!xdr_bool(xdrs, &objp->reply.eof))
2256 		return (FALSE);
2257 	return (TRUE);
2258 }
2259 
2260 bool_t
2261 xdr_READDIRPLUS3res(XDR *xdrs, READDIRPLUS3res *objp)
2262 {
2263 	READDIRPLUS3resok *resokp;
2264 
2265 	/*
2266 	 * ENCODE or FREE only
2267 	 */
2268 	if (xdrs->x_op == XDR_DECODE)
2269 		return (FALSE);
2270 
2271 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
2272 		return (FALSE);
2273 	switch (objp->status) {
2274 	case NFS3_OK:
2275 		/* xdr_READDIRPLUS3resok */
2276 		resokp = &objp->resok;
2277 		if (!xdr_post_op_attr(xdrs, &resokp->dir_attributes))
2278 			return (FALSE);
2279 		/*
2280 		 * cookieverf is really an opaque 8 byte
2281 		 * quantity, but we will treat it as a
2282 		 * hyper for efficiency, the cost of
2283 		 * a byteswap here saves bcopys elsewhere
2284 		 */
2285 		if (!xdr_u_longlong_t(xdrs, &resokp->cookieverf))
2286 			return (FALSE);
2287 		if (xdrs->x_op == XDR_ENCODE) {
2288 			if (!xdr_putdirpluslist(xdrs, resokp))
2289 				return (FALSE);
2290 		}
2291 		break;
2292 	default:
2293 		return (xdr_post_op_attr(xdrs, &objp->resfail.dir_attributes));
2294 	}
2295 	return (TRUE);
2296 }
2297 
2298 /*
2299  * Decode readdirplus directly into a dirent64_t and do the DNLC caching.
2300  */
2301 bool_t
2302 xdr_READDIRPLUS3vres(XDR *xdrs, READDIRPLUS3vres *objp)
2303 {
2304 	dirent64_t *dp;
2305 	vnode_t *dvp;
2306 	uint_t entries_size;
2307 	int outcount = 0;
2308 	vnode_t *nvp;
2309 	rnode_t *rp;
2310 	post_op_vattr pov;
2311 	vattr_t va;
2312 
2313 	/*
2314 	 * DECODE or FREE only
2315 	 */
2316 	if (xdrs->x_op == XDR_FREE)
2317 		return (TRUE);
2318 
2319 	if (xdrs->x_op != XDR_DECODE)
2320 		return (FALSE);
2321 
2322 	if (!XDR_GETINT32(xdrs, (int32_t *)&objp->status))
2323 		return (FALSE);
2324 
2325 	if (!xdr_post_op_vattr(xdrs, &objp->dir_attributes))
2326 		return (FALSE);
2327 
2328 	if (objp->status != NFS3_OK)
2329 		return (TRUE);
2330 
2331 	/*
2332 	 * cookieverf is really an opaque 8 byte
2333 	 * quantity, but we will treat it as a
2334 	 * hyper for efficiency, the cost of
2335 	 * a byteswap here saves bcopys elsewhere
2336 	 */
2337 	if (!xdr_u_longlong_t(xdrs, &objp->cookieverf))
2338 		return (FALSE);
2339 
2340 	dvp = objp->dir_attributes.fres.vp;
2341 	rp = VTOR(dvp);
2342 
2343 	pov.fres.vap = &va;
2344 	pov.fres.vp = dvp;
2345 
2346 	entries_size = objp->entries_size;
2347 	dp = objp->entries;
2348 
2349 	for (;;) {
2350 		uint_t this_reclen;
2351 		bool_t valid;
2352 		uint_t namlen;
2353 		nfs_fh3 fh;
2354 		int va_valid;
2355 		int fh_valid;
2356 		ino64_t fileid;
2357 
2358 		if (!XDR_GETINT32(xdrs, (int32_t *)&valid))
2359 			return (FALSE);
2360 		if (!valid) {
2361 			/*
2362 			 * We have run out of entries, decode eof.
2363 			 */
2364 			if (!XDR_GETINT32(xdrs, (int32_t *)&objp->eof))
2365 				return (FALSE);
2366 
2367 			break;
2368 		}
2369 
2370 		/*
2371 		 * fileid3 fileid
2372 		 */
2373 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&fileid))
2374 			return (FALSE);
2375 
2376 		/*
2377 		 * filename3 name
2378 		 */
2379 		if (!XDR_GETINT32(xdrs, (int32_t *)&namlen))
2380 			return (FALSE);
2381 		this_reclen = DIRENT64_RECLEN(namlen);
2382 
2383 		/*
2384 		 * If this will overflow buffer, stop decoding
2385 		 */
2386 		if ((outcount + this_reclen) > entries_size) {
2387 			objp->eof = FALSE;
2388 			break;
2389 		}
2390 		dp->d_reclen = this_reclen;
2391 		dp->d_ino = fileid;
2392 
2393 		if (!xdr_opaque(xdrs, dp->d_name, namlen))
2394 			return (FALSE);
2395 		bzero(&dp->d_name[namlen],
2396 		    DIRENT64_NAMELEN(this_reclen) - namlen);
2397 
2398 		/*
2399 		 * cookie3 cookie
2400 		 */
2401 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&dp->d_off))
2402 			return (FALSE);
2403 		objp->loff = dp->d_off;
2404 
2405 		/*
2406 		 * post_op_attr name_attributes
2407 		 */
2408 		if (!xdr_post_op_vattr(xdrs, &pov))
2409 			return (FALSE);
2410 
2411 		if (pov.attributes == TRUE &&
2412 				pov.fres.status == NFS3_OK)
2413 			va_valid = TRUE;
2414 		else
2415 			va_valid = FALSE;
2416 
2417 		/*
2418 		 * post_op_fh3 name_handle
2419 		 */
2420 		if (!XDR_GETINT32(xdrs, (int32_t *)&fh_valid))
2421 			return (FALSE);
2422 
2423 		/*
2424 		 * By definition of the standard fh_valid can be 0 (FALSE) or
2425 		 * 1 (TRUE), but we have to account for it being anything else
2426 		 * in case some other system didn't follow the standard.  Note
2427 		 * that this is why the else checks if the fh_valid variable
2428 		 * is != FALSE.
2429 		 */
2430 		if (fh_valid == TRUE) {
2431 			if (!xdr_nfs_fh3(xdrs, &fh))
2432 				return (FALSE);
2433 		} else {
2434 			if (fh_valid != FALSE)
2435 				return (FALSE);
2436 		}
2437 
2438 		/*
2439 		 * If the name is "." or there are no attributes,
2440 		 * don't polute the DNLC with "." entries or files
2441 		 * we cannot determine the type for.
2442 		 */
2443 		if (!(namlen == 1 && dp->d_name[0] == '.') &&
2444 			va_valid && fh_valid) {
2445 
2446 			/*
2447 			 * Do the DNLC caching
2448 			 */
2449 			nvp = makenfs3node_va(&fh, &va, dvp->v_vfsp,
2450 				objp->time, objp->credentials,
2451 				rp->r_path, dp->d_name);
2452 			dnlc_update(dvp, dp->d_name, nvp);
2453 			VN_RELE(nvp);
2454 		}
2455 
2456 		outcount += this_reclen;
2457 		dp = (dirent64_t *)((intptr_t)dp + this_reclen);
2458 	}
2459 
2460 	objp->size = outcount;
2461 	return (TRUE);
2462 }
2463 
2464 bool_t
2465 xdr_FSSTAT3res(XDR *xdrs, FSSTAT3res *objp)
2466 {
2467 	FSSTAT3resok *resokp;
2468 
2469 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
2470 		return (FALSE);
2471 	if (objp->status != NFS3_OK)
2472 		return (xdr_post_op_attr(xdrs, &objp->resfail.obj_attributes));
2473 
2474 	/* xdr_FSSTAT3resok */
2475 	resokp = &objp->resok;
2476 	if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
2477 		return (FALSE);
2478 	if (!xdr_u_longlong_t(xdrs, &resokp->tbytes))
2479 		return (FALSE);
2480 	if (!xdr_u_longlong_t(xdrs, &resokp->fbytes))
2481 		return (FALSE);
2482 	if (!xdr_u_longlong_t(xdrs, &resokp->abytes))
2483 		return (FALSE);
2484 	if (!xdr_u_longlong_t(xdrs, &resokp->tfiles))
2485 		return (FALSE);
2486 	if (!xdr_u_longlong_t(xdrs, &resokp->ffiles))
2487 		return (FALSE);
2488 	if (!xdr_u_longlong_t(xdrs, &resokp->afiles))
2489 		return (FALSE);
2490 	return (xdr_u_int(xdrs, &resokp->invarsec));
2491 }
2492 
2493 bool_t
2494 xdr_FSINFO3res(XDR *xdrs, FSINFO3res *objp)
2495 {
2496 	FSINFO3resok *resokp;
2497 
2498 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
2499 		return (FALSE);
2500 	if (objp->status != NFS3_OK) /* xdr_FSSTAT3resfail */
2501 		return (xdr_post_op_attr(xdrs, &objp->resfail.obj_attributes));
2502 
2503 	/* xdr_FSINFO3resok */
2504 	resokp = &objp->resok;
2505 	if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
2506 		return (FALSE);
2507 	if (!xdr_u_int(xdrs, &resokp->rtmax))
2508 		return (FALSE);
2509 	if (!xdr_u_int(xdrs, &resokp->rtpref))
2510 		return (FALSE);
2511 	if (!xdr_u_int(xdrs, &resokp->rtmult))
2512 		return (FALSE);
2513 	if (!xdr_u_int(xdrs, &resokp->wtmax))
2514 		return (FALSE);
2515 	if (!xdr_u_int(xdrs, &resokp->wtpref))
2516 		return (FALSE);
2517 	if (!xdr_u_int(xdrs, &resokp->wtmult))
2518 		return (FALSE);
2519 	if (!xdr_u_int(xdrs, &resokp->dtpref))
2520 		return (FALSE);
2521 	if (!xdr_u_longlong_t(xdrs, &resokp->maxfilesize))
2522 		return (FALSE);
2523 	if (!xdr_u_int(xdrs, &resokp->time_delta.seconds))
2524 		return (FALSE);
2525 	if (!xdr_u_int(xdrs, &resokp->time_delta.nseconds))
2526 		return (FALSE);
2527 	return (xdr_u_int(xdrs, &resokp->properties));
2528 }
2529 
2530 bool_t
2531 xdr_PATHCONF3res(XDR *xdrs, PATHCONF3res *objp)
2532 {
2533 	PATHCONF3resok *resokp;
2534 
2535 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
2536 		return (FALSE);
2537 	if (objp->status != NFS3_OK)
2538 		return (xdr_post_op_attr(xdrs, &objp->resfail.obj_attributes));
2539 
2540 	/* xdr_PATHCONF3resok */
2541 	resokp = &objp->resok;
2542 	if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
2543 		return (FALSE);
2544 	if (!xdr_u_int(xdrs, &resokp->info.link_max))
2545 		return (FALSE);
2546 	if (!xdr_u_int(xdrs, &resokp->info.name_max))
2547 		return (FALSE);
2548 	if (!xdr_bool(xdrs, &resokp->info.no_trunc))
2549 		return (FALSE);
2550 	if (!xdr_bool(xdrs, &resokp->info.chown_restricted))
2551 		return (FALSE);
2552 	if (!xdr_bool(xdrs, &resokp->info.case_insensitive))
2553 		return (FALSE);
2554 	return (xdr_bool(xdrs, &resokp->info.case_preserving));
2555 }
2556 
2557 bool_t
2558 xdr_COMMIT3args(XDR *xdrs, COMMIT3args *objp)
2559 {
2560 	int32_t *ptr;
2561 	int32_t *fhp;
2562 	int len;
2563 	uint_t in_size;
2564 
2565 	if (xdrs->x_op == XDR_FREE)
2566 		return (TRUE);
2567 
2568 	in_size = RNDUP(sizeof (fhandle_t)) +	4 * BYTES_PER_XDR_UNIT;
2569 	ptr = XDR_INLINE(xdrs, in_size);
2570 
2571 	if (ptr != NULL) {
2572 		len = (xdrs->x_op == XDR_DECODE) ? *ptr : objp->file.fh3_length;
2573 
2574 		if (XDR_CHECKFHSIZE(xdrs, len, in_size)) {
2575 			fhp = (int32_t *)&(objp->file.fh3_u.data);
2576 			if (xdrs->x_op == XDR_DECODE) {
2577 				objp->file.fh3_length = IXDR_GET_U_INT32(ptr);
2578 				*fhp++ = *ptr++;
2579 				*fhp++ = *ptr++;
2580 				*fhp++ = *ptr++;
2581 				*fhp++ = *ptr++;
2582 				*fhp++ = *ptr++;
2583 				*fhp++ = *ptr++;
2584 				*fhp++ = *ptr++;
2585 				*fhp = *ptr++;
2586 				IXDR_GET_U_HYPER(ptr, objp->offset);
2587 				objp->count = IXDR_GET_U_INT32(ptr);
2588 			} else {
2589 				IXDR_PUT_U_INT32(ptr, objp->file.fh3_length);
2590 				*ptr++ = *fhp++;
2591 				*ptr++ = *fhp++;
2592 				*ptr++ = *fhp++;
2593 				*ptr++ = *fhp++;
2594 				*ptr++ = *fhp++;
2595 				*ptr++ = *fhp++;
2596 				*ptr++ = *fhp++;
2597 				*ptr++ = *fhp;
2598 				IXDR_PUT_U_HYPER(ptr, objp->offset);
2599 				IXDR_PUT_U_INT32(ptr, objp->count);
2600 			}
2601 			return (TRUE);
2602 		}
2603 	}
2604 
2605 	if (!xdr_nfs_fh3(xdrs, &objp->file))
2606 		return (FALSE);
2607 	if (!xdr_u_longlong_t(xdrs, &objp->offset))
2608 		return (FALSE);
2609 	return (xdr_u_int(xdrs, &objp->count));
2610 }
2611 
2612 bool_t
2613 xdr_COMMIT3res(XDR *xdrs, COMMIT3res *objp)
2614 {
2615 	COMMIT3resok *resokp;
2616 
2617 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
2618 		return (FALSE);
2619 	if (objp->status != NFS3_OK)
2620 		return (xdr_wcc_data(xdrs, &objp->resfail.file_wcc));
2621 
2622 	/* xdr_COMMIT3resok */
2623 	resokp = &objp->resok;
2624 	if (!xdr_wcc_data(xdrs, &resokp->file_wcc))
2625 		return (FALSE);
2626 	/*
2627 	 * writeverf3 is really an opaque 8 byte
2628 	 * quantity, but we will treat it as a
2629 	 * hyper for efficiency, the cost of
2630 	 * a byteswap here saves bcopys elsewhere
2631 	 */
2632 	return (xdr_u_longlong_t(xdrs, &resokp->verf));
2633 }
2634