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