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