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