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