1 /*
  2  * CDDL HEADER START
  3  *
  4  * The contents of this file are subject to the terms of the
  5  * Common Development and Distribution License, Version 1.0 only
  6  * (the "License").  You may not use this file except in compliance
  7  * with the License.
  8  *
  9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 10  * or http://www.opensolaris.org/os/licensing.
 11  * See the License for the specific language governing permissions
 12  * and limitations under the License.
 13  *
 14  * When distributing Covered Code, include this CDDL HEADER in each
 15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 16  * If applicable, add the following below this CDDL HEADER, with the
 17  * fields enclosed by brackets "[]" replaced with your own identifying
 18  * information: Portions Copyright [yyyy] [name of copyright owner]
 19  *
 20  * CDDL HEADER END
 21  */
 22 /*
 23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
 24  * Use is subject to license terms.
 25  */
 26 
 27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
 28 /* All Rights Reserved */
 29 












 30 #pragma ident   "@(#)nfs3_xdr.c 1.62    05/06/08 SMI"
 31 
 32 #include <sys/param.h>
 33 #include <sys/types.h>
 34 #include <sys/systm.h>
 35 #include <sys/user.h>
 36 #include <sys/vnode.h>
 37 #include <sys/file.h>
 38 #include <sys/dirent.h>
 39 #include <sys/vfs.h>
 40 #include <sys/stream.h>
 41 #include <sys/strsubr.h>
 42 #include <sys/debug.h>
 43 #include <sys/t_lock.h>
 44 #include <sys/cmn_err.h>
 45 #include <sys/dnlc.h>
 46 #include <sys/cred.h>
 47 #include <sys/time.h>
 48 
 49 #include <rpc/types.h>
 50 #include <rpc/xdr.h>
 51 
 52 #include <nfs/nfs.h>
 53 #include <nfs/rnode.h>

 54 
 55 /* Checks if the fh is 32 bytes and returns TRUE if it is, otherwise FALSE */
 56 #define XDR_CHECKFHSIZE(x, len, sz)     \
 57         (((int32_t)ntohl(len) == NFS3_CURFHSIZE) ? TRUE : \
 58         (xdr_rewind(x, sz), FALSE))
 59 
 60 /*
 61  * These are the XDR routines used to serialize and deserialize
 62  * the various structures passed as parameters across the network
 63  * between NFS clients and servers.
 64  */
 65 
 66 /*
 67  * XDR null terminated ASCII strings
 68  * xdr_string3 deals with "C strings" - arrays of bytes that are
 69  * terminated by a NULL character.  The parameter cpp references a
 70  * pointer to storage; If the pointer is null, then the necessary
 71  * storage is allocated.  The last parameter is the max allowed length
 72  * of the string as allowed by the system.  The NFS Version 3 protocol
 73  * does not place limits on strings, but the implementation needs to
 74  * place a reasonable limit to avoid problems.
 75  */
 76 bool_t
 77 xdr_string3(XDR *xdrs, char **cpp, uint_t maxsize)
 78 {
 79         char *sp;
 80         uint_t size;
 81         uint_t nodesize;
 82         bool_t mem_alloced = FALSE;
 83 
 84         /*
 85          * first deal with the length since xdr strings are counted-strings
 86          */
 87         sp = *cpp;
 88         switch (xdrs->x_op) {
 89         case XDR_FREE:
 90                 if (sp == NULL || sp == nfs3nametoolong)
 91                         return (TRUE);  /* already free */
 92                 /* FALLTHROUGH */
 93 
 94         case XDR_ENCODE:
 95                 size = (uint_t)strlen(sp);
 96                 break;
 97 
 98         case XDR_DECODE:
 99                 break;
100         }
101 
102         if (!xdr_u_int(xdrs, &size))
103                 return (FALSE);
104 
105         /*
106          * now deal with the actual bytes
107          */
108         switch (xdrs->x_op) {
109         case XDR_DECODE:
110                 if (size >= maxsize) {
111                         *cpp = nfs3nametoolong;
112                         if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &size))
113                                 return (FALSE);
114                         return (TRUE);
115                 }
116                 nodesize = size + 1;
117                 if (nodesize == 0)
118                         return (TRUE);
119                 if (sp == NULL) {
120                         sp = kmem_alloc(nodesize, KM_NOSLEEP);
121                         *cpp = sp;
122                         if (sp == NULL)
123                                 return (FALSE);
124                         mem_alloced = TRUE;
125                 }
126                 sp[size] = 0;
127 
128                 if (xdr_opaque(xdrs, sp, size)) {
129                         if (strlen(sp) != size) {
130                                 if (mem_alloced)
131                                         kmem_free(sp, nodesize);
132                                 *cpp = NULL;
133                                 return (FALSE);
134                         }
135                 } else {
136                         if (mem_alloced)
137                                 kmem_free(sp, nodesize);
138                         *cpp = NULL;
139                         return (FALSE);
140                 }
141                 return (TRUE);
142 
143         case XDR_ENCODE:
144                 return (xdr_opaque(xdrs, sp, size));
145 
146         case XDR_FREE:
147                 nodesize = size + 1;
148                 kmem_free(sp, nodesize);
149                 *cpp = NULL;
150                 return (TRUE);
151         }
152 
153         return (FALSE);
154 }
155 
156 /*
157  * If the filehandle is not equal to NFS3_CURFHSIZE then
158  * rewind/set the pointer back to it's previous location prior to
159  * the call.
160  * Inlining is only being done for 32 byte fhandles since
161  * predominantly the size of the fh is 32 and thus
162  * optimizing only this case would be the best.
163  */
164 static void
165 xdr_rewind(register XDR *xdrs, uint_t inl_sz)
166 {
167         uint_t curpos;
168 
169         curpos = XDR_GETPOS(xdrs);
170         (void) XDR_SETPOS(xdrs, curpos - inl_sz);
171 }
172 
173 bool_t
174 xdr_nfs_fh3(XDR *xdrs, nfs_fh3 *objp)
175 {
176         int32_t *ptr;
177         int32_t *fhp;
178         uint_t len;
179         uint_t in_size;
180 
181         if (xdrs->x_op == XDR_FREE)
182                 return (TRUE);
183 
184         in_size = RNDUP(sizeof (fhandle_t)) +   1 * BYTES_PER_XDR_UNIT;
185 
186         ptr = XDR_INLINE(xdrs, in_size);
187         if (ptr != NULL) {
188                 len = ((xdrs->x_op == XDR_DECODE) ? *ptr : objp->fh3_length);
189 
190                 if (XDR_CHECKFHSIZE(xdrs, len, in_size)) {
191                         fhp = (int32_t *)&(objp->fh3_u.data);
192                         if (xdrs->x_op == XDR_DECODE) {
193                                 objp->fh3_length = IXDR_GET_U_INT32(ptr);
194                                 *fhp++ = *ptr++;
195                                 *fhp++ = *ptr++;
196                                 *fhp++ = *ptr++;
197                                 *fhp++ = *ptr++;
198                                 *fhp++ = *ptr++;
199                                 *fhp++ = *ptr++;
200                                 *fhp++ = *ptr++;
201                                 *fhp = *ptr;
202                         } else {
203                                 IXDR_PUT_U_INT32(ptr, objp->fh3_length);
204                                 *ptr++ = *fhp++;
205                                 *ptr++ = *fhp++;
206                                 *ptr++ = *fhp++;
207                                 *ptr++ = *fhp++;
208                                 *ptr++ = *fhp++;
209                                 *ptr++ = *fhp++;
210                                 *ptr++ = *fhp++;
211                                 *ptr = *fhp;
212                         }
213                         return (TRUE);
214                 }
215         }
216 
217         if (!xdr_u_int(xdrs, &objp->fh3_length))
218                 return (FALSE);
219 
220         if (objp->fh3_length > NFS3_FHSIZE)
221                 return (FALSE);
222 
223         return (xdr_opaque(xdrs, objp->fh3_u.data, objp->fh3_length));
224 }
225 
226 /*
227  * Will only consider the DECODE case for the fast way
228  * since it does not require any additional allocation of
229  * memory and thus can just assign the objp to point to
230  * the data returned from XDR_INLINE
231  */
232 bool_t
233 xdr_fastnfs_fh3(register XDR *xdrs, nfs_fh3 **objp)
234 {
235         int32_t *ptr;
236         uint_t in_size;
237 
238         if (xdrs->x_op != XDR_DECODE)
239                 return (FALSE);
240 
241         in_size = RNDUP(sizeof (fhandle_t)) + 1 * BYTES_PER_XDR_UNIT;
242 
243         ptr = XDR_INLINE(xdrs, in_size);
244 
245         if ((ptr != NULL) && (XDR_CHECKFHSIZE(xdrs, *ptr, in_size))) {
246 #ifdef _LITTLE_ENDIAN
247                 /* Decode the length */
248                 *ptr = (int32_t)ntohl(*(uint32_t *)ptr);
249 #endif
250                 *objp = (nfs_fh3 *) ptr;
251                 return (TRUE);
252         }
253         return (FALSE);
254 }
255 
256 bool_t
257 xdr_diropargs3(XDR *xdrs, diropargs3 *objp)
258 {
259         uint32_t size;
260         int32_t *ptr;
261         int32_t *fhp;
262         uint32_t nodesize;
263         uint32_t in_size;
264         int rndup, i;
265         char *cptr;
266 
267         if (xdrs->x_op == XDR_DECODE) {
268                 objp->dirp = &objp->dir;
269                 /* includes: fh, length of fh, and length of name */
270                 in_size = RNDUP(sizeof (fhandle_t)) + 2 * BYTES_PER_XDR_UNIT;
271 
272                 ptr = XDR_INLINE(xdrs, in_size);
273 
274                 if (ptr != NULL) {
275                     if (XDR_CHECKFHSIZE(xdrs, *ptr, in_size)) {
276                             fhp = (int32_t *)(objp->dir.fh3_u.data);
277                             /* Get length of fhandle and then fh. */
278                             objp->dir.fh3_length = IXDR_GET_U_INT32(ptr);
279                             *fhp++ = *ptr++;
280                             *fhp++ = *ptr++;
281                             *fhp++ = *ptr++;
282                             *fhp++ = *ptr++;
283                             *fhp++ = *ptr++;
284                             *fhp++ = *ptr++;
285                             *fhp++ = *ptr++;
286                             *fhp = *ptr++;
287 
288                             size = IXDR_GET_U_INT32(ptr);
289 
290                             if (size >= MAXNAMELEN) {
291                                     objp->name = nfs3nametoolong;
292                                     if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES,
293                                                 &size))
294                                             return (FALSE);
295                                     return (TRUE);
296                             }
297                             nodesize = size+1;
298                             if (nodesize == 0)
299                                     return (TRUE);
300                             if (objp->name == NULL) {
301                                     objp->name = (char *)kmem_alloc(nodesize,
302                                                                     KM_NOSLEEP);
303                                     if (objp->name == NULL)
304                                             return (FALSE);
305                                     objp->flags |= DA_FREENAME;
306                             }
307                             ptr = XDR_INLINE(xdrs, RNDUP(size));
308                             if (ptr == NULL) {
309                                 if (! xdr_opaque(xdrs, objp->name, size)) {
310                                         if (objp->flags & DA_FREENAME) {
311                                                 kmem_free(objp->name,
312                                                         nodesize);
313                                                 objp->name = NULL;
314                                         }
315                                         return (FALSE);
316                                 }
317                                 objp->name[size] = '\0';
318                                 if (strlen(objp->name) != size) {
319                                         if (objp->flags & DA_FREENAME) {
320                                                 kmem_free(objp->name,
321                                                         nodesize);
322                                                 objp->name = NULL;
323                                         }
324                                         return (FALSE);
325                                 }
326                                 return (TRUE);
327                             }
328                             bcopy((char *)ptr, objp->name, size);
329                             objp->name[size] = '\0';
330                             if (strlen(objp->name) != size) {
331                                     if (objp->flags & DA_FREENAME) {
332                                             kmem_free(objp->name,
333                                                 nodesize);
334                                             objp->name = NULL;
335                                     }
336                                     return (FALSE);
337                             }
338                             return (TRUE);
339                     }
340                 }
341                 if (objp->name == NULL)
342                         objp->flags |= DA_FREENAME;
343         }
344 
345         if ((xdrs->x_op == XDR_ENCODE) &&
346             (objp->dirp->fh3_length == NFS3_CURFHSIZE)) {
347                 fhp = (int32_t *)(objp->dirp->fh3_u.data);
348                 size = strlen(objp->name);
349                 in_size = RNDUP(sizeof (fhandle_t)) +
350                         (2 * BYTES_PER_XDR_UNIT) + RNDUP(size);
351 
352                 ptr = XDR_INLINE(xdrs, in_size);
353                 if (ptr != NULL) {
354                         IXDR_PUT_U_INT32(ptr, objp->dirp->fh3_length);
355                         *ptr++ = *fhp++;
356                         *ptr++ = *fhp++;
357                         *ptr++ = *fhp++;
358                         *ptr++ = *fhp++;
359                         *ptr++ = *fhp++;
360                         *ptr++ = *fhp++;
361                         *ptr++ = *fhp++;
362                         *ptr++ = *fhp;
363 
364                         IXDR_PUT_U_INT32(ptr, (uint32_t)size);
365 
366                         bcopy(objp->name, (char *)ptr, size);
367                         rndup = BYTES_PER_XDR_UNIT -
368                                 (size % BYTES_PER_XDR_UNIT);
369                         if (rndup != BYTES_PER_XDR_UNIT) {
370                                 cptr = (char *)ptr + size;
371                                 for (i = 0; i < rndup; i++)
372                                         *cptr++ = '\0';
373                         }
374                         return (TRUE);
375                 }
376         }
377         if (xdrs->x_op == XDR_FREE) {
378                 if ((objp->name == NULL) || (objp->name == nfs3nametoolong))
379                         return (TRUE);
380                 size = strlen(objp->name);
381                 if (objp->flags & DA_FREENAME)
382                         kmem_free(objp->name, size + 1);
383                 objp->name = NULL;
384                 return (TRUE);
385         }
386         /* Normal case */
387         if (!xdr_nfs_fh3(xdrs, objp->dirp))
388                 return (FALSE);
389         return (xdr_string3(xdrs, &objp->name, MAXNAMELEN));
390 }
391 
392 bool_t
393 xdr_fastdiropargs3(XDR *xdrs, diropargs3 **objp)
394 {
395         int32_t *ptr;
396         uint_t size;
397         uint_t nodesize;
398         struct diropargs3 *da;
399         uint_t in_size;
400         uint_t skipsize;
401 
402         if (xdrs->x_op != XDR_DECODE)
403                 return (FALSE);
404 
405         in_size = RNDUP(sizeof (fhandle_t)) +   1 * BYTES_PER_XDR_UNIT;
406 
407         /* includes the fh and fh length */
408         ptr = XDR_INLINE(xdrs, in_size);
409 
410         if ((ptr != NULL) && (XDR_CHECKFHSIZE(xdrs, *ptr, in_size))) {
411                 da = *objp;
412 #ifdef _LITTLE_ENDIAN
413                 *ptr = (int32_t)ntohl(*(uint32_t *)ptr);
414 #endif
415                 da->dirp = (nfs_fh3 *)ptr;
416                 da->name = NULL;
417                 da->flags = 0;
418                 if (!XDR_CONTROL(xdrs, XDR_PEEK, (void *)&size)) {
419                         da->flags |= DA_FREENAME;
420                         return (xdr_string3(xdrs, &da->name, MAXNAMELEN));
421                 }
422                 if (size >= MAXNAMELEN) {
423                         da->name = nfs3nametoolong;
424                         skipsize = RNDUP(size) + (1 * BYTES_PER_XDR_UNIT);
425                         if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &skipsize))
426                                 return (FALSE);
427                         return (TRUE);
428                 }
429                 nodesize = size + 1;
430                 if (nodesize == 0)
431                         return (TRUE);
432                 ptr = XDR_INLINE(xdrs, 1 * BYTES_PER_XDR_UNIT + RNDUP(size));
433                 if (ptr != NULL) {
434                         if ((size % BYTES_PER_XDR_UNIT) != 0)
435                                 /* Plus 1 skips the size */
436                                 da->name = (char *)(ptr + 1);
437                         else {
438                                 da->name = (char *)ptr;
439                                 bcopy((char *)(ptr + 1), da->name, size);
440                         }
441                         da->name[size] = '\0';
442                         return (TRUE);
443                 }
444                 da->flags |= DA_FREENAME;
445                 return (xdr_string3(xdrs, &da->name, MAXNAMELEN));
446         }
447         return (FALSE);
448 }
449 
450 static bool_t
451 xdr_fattr3(XDR *xdrs, fattr3 *na)
452 {
453         int32_t *ptr;
454 
455         if (xdrs->x_op == XDR_FREE)
456                 return (TRUE);
457 
458         ptr = XDR_INLINE(xdrs, NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT);
459         if (ptr != NULL) {
460                 if (xdrs->x_op == XDR_DECODE) {
461                         na->type = IXDR_GET_ENUM(ptr, enum ftype3);
462                         na->mode = IXDR_GET_U_INT32(ptr);
463                         na->nlink = IXDR_GET_U_INT32(ptr);
464                         na->uid = IXDR_GET_U_INT32(ptr);
465                         na->gid = IXDR_GET_U_INT32(ptr);
466                         IXDR_GET_U_HYPER(ptr, na->size);
467                         IXDR_GET_U_HYPER(ptr, na->used);
468                         na->rdev.specdata1 = IXDR_GET_U_INT32(ptr);
469                         na->rdev.specdata2 = IXDR_GET_U_INT32(ptr);
470                         IXDR_GET_U_HYPER(ptr, na->fsid);
471                         IXDR_GET_U_HYPER(ptr, na->fileid);
472                         na->atime.seconds = IXDR_GET_U_INT32(ptr);
473                         na->atime.nseconds = IXDR_GET_U_INT32(ptr);
474                         na->mtime.seconds = IXDR_GET_U_INT32(ptr);
475                         na->mtime.nseconds = IXDR_GET_U_INT32(ptr);
476                         na->ctime.seconds = IXDR_GET_U_INT32(ptr);
477                         na->ctime.nseconds = IXDR_GET_U_INT32(ptr);
478                 } else {
479                         IXDR_PUT_ENUM(ptr, na->type);
480                         IXDR_PUT_U_INT32(ptr, na->mode);
481                         IXDR_PUT_U_INT32(ptr, na->nlink);
482                         IXDR_PUT_U_INT32(ptr, na->uid);
483                         IXDR_PUT_U_INT32(ptr, na->gid);
484                         IXDR_PUT_U_HYPER(ptr, na->size);
485                         IXDR_PUT_U_HYPER(ptr, na->used);
486                         IXDR_PUT_U_INT32(ptr, na->rdev.specdata1);
487                         IXDR_PUT_U_INT32(ptr, na->rdev.specdata2);
488                         IXDR_PUT_U_HYPER(ptr, na->fsid);
489                         IXDR_PUT_U_HYPER(ptr, na->fileid);
490                         IXDR_PUT_U_INT32(ptr, na->atime.seconds);
491                         IXDR_PUT_U_INT32(ptr, na->atime.nseconds);
492                         IXDR_PUT_U_INT32(ptr, na->mtime.seconds);
493                         IXDR_PUT_U_INT32(ptr, na->mtime.nseconds);
494                         IXDR_PUT_U_INT32(ptr, na->ctime.seconds);
495                         IXDR_PUT_U_INT32(ptr, na->ctime.nseconds);
496                 }
497                 return (TRUE);
498         }
499         if (!(xdr_enum(xdrs, (enum_t *)&na->type) &&
500                 xdr_u_int(xdrs, &na->mode) &&
501                 xdr_u_int(xdrs, &na->nlink) &&
502                 xdr_u_int(xdrs, &na->uid) &&
503                 xdr_u_int(xdrs, &na->gid) &&
504                 xdr_u_longlong_t(xdrs, &na->size) &&
505                 xdr_u_longlong_t(xdrs, &na->used) &&
506                 xdr_u_int(xdrs, &na->rdev.specdata1) &&
507                 xdr_u_int(xdrs, &na->rdev.specdata2) &&
508                 xdr_u_longlong_t(xdrs, &na->fsid) &&
509                 xdr_u_longlong_t(xdrs, &na->fileid) &&
510                 xdr_u_int(xdrs, &na->atime.seconds) &&
511                 xdr_u_int(xdrs, &na->atime.nseconds) &&
512                 xdr_u_int(xdrs, &na->mtime.seconds) &&
513                 xdr_u_int(xdrs, &na->mtime.nseconds) &&
514                 xdr_u_int(xdrs, &na->ctime.seconds) &&
515                 xdr_u_int(xdrs, &na->ctime.nseconds)))
516                         return (FALSE);
517         return (TRUE);
518 }
519 
520 /*
521  * Fast decode of an fattr3 to a vattr
522  * Only return FALSE on decode error, all other fattr to vattr translation
523  * failures set status.
524  *
525  * Callers must catch the following errors:
526  *      EFBIG - file size will not fit in va_size
527  *      EOVERFLOW - time will not fit in va_*time
528  */
529 static bool_t
530 xdr_fattr3_to_vattr(XDR *xdrs, fattr3_res *objp)
531 {
532         int32_t *ptr;
533         size3 used;
534         specdata3 rdev;
535         uint32_t ntime;
536         vattr_t *vap = objp->vap;
537 
538         /*
539          * DECODE only
540          */
541         ASSERT(xdrs->x_op == XDR_DECODE);
542 
543         objp->status = 0;
544         ptr = XDR_INLINE(xdrs, NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT);
545         if (ptr != NULL) {
546                 /*
547                  * Common case
548                  */
549                 vap->va_type = IXDR_GET_ENUM(ptr, enum vtype);
550                 if (vap->va_type < NF3REG || vap->va_type > NF3FIFO)
551                         vap->va_type = VBAD;
552                 else
553                         vap->va_type = nf3_to_vt[vap->va_type];
554                 vap->va_mode = IXDR_GET_U_INT32(ptr);
555                 vap->va_nlink = IXDR_GET_U_INT32(ptr);
556                 vap->va_uid = (uid_t)IXDR_GET_U_INT32(ptr);
557                 if (vap->va_uid == NFS_UID_NOBODY)
558                         vap->va_uid = UID_NOBODY;
559                 vap->va_gid = (gid_t)IXDR_GET_U_INT32(ptr);
560                 if (vap->va_gid == NFS_GID_NOBODY)
561                         vap->va_gid = GID_NOBODY;
562                 IXDR_GET_U_HYPER(ptr, vap->va_size);
563                 /*
564                  * If invalid size, stop decode, set status, and
565                  * return TRUE, x_handy will be correct, caller must ignore vap.
566                  */
567                 if (!NFS3_SIZE_OK(vap->va_size)) {
568                         objp->status = EFBIG;
569                         return (TRUE);
570                 }
571                 IXDR_GET_U_HYPER(ptr, used);
572                 rdev.specdata1 = IXDR_GET_U_INT32(ptr);
573                 rdev.specdata2 = IXDR_GET_U_INT32(ptr);
574                 /* fsid is ignored */
575                 ptr += 2;
576                 IXDR_GET_U_HYPER(ptr, vap->va_nodeid);
577 
578                 /*
579                  * nfs protocol defines times as unsigned so don't
580                  * extend sign, unless sysadmin set nfs_allow_preepoch_time.
581                  * The inline macros do the equivilant of NFS_TIME_T_CONVERT
582                  */
583                 if (nfs_allow_preepoch_time) {
584                         vap->va_atime.tv_sec = IXDR_GET_INT32(ptr);
585                         vap->va_atime.tv_nsec = IXDR_GET_U_INT32(ptr);
586                         vap->va_mtime.tv_sec = IXDR_GET_INT32(ptr);
587                         vap->va_mtime.tv_nsec = IXDR_GET_U_INT32(ptr);
588                         vap->va_ctime.tv_sec = IXDR_GET_INT32(ptr);
589                         vap->va_ctime.tv_nsec = IXDR_GET_U_INT32(ptr);
590                 } else {
591                         /*
592                          * Check if the time would overflow on 32-bit
593                          */
594                         ntime = IXDR_GET_U_INT32(ptr);
595                         /*CONSTCOND*/
596                         if (NFS3_TIME_OVERFLOW(ntime)) {
597                                 objp->status = EOVERFLOW;
598                                 return (TRUE);
599                         }
600                         vap->va_atime.tv_sec = ntime;
601                         vap->va_atime.tv_nsec = IXDR_GET_U_INT32(ptr);
602 
603                         ntime = IXDR_GET_U_INT32(ptr);
604                         /*CONSTCOND*/
605                         if (NFS3_TIME_OVERFLOW(ntime)) {
606                                 objp->status = EOVERFLOW;
607                                 return (TRUE);
608                         }
609                         vap->va_mtime.tv_sec = ntime;
610                         vap->va_mtime.tv_nsec = IXDR_GET_U_INT32(ptr);
611 
612                         ntime = IXDR_GET_U_INT32(ptr);
613                         /*CONSTCOND*/
614                         if (NFS3_TIME_OVERFLOW(ntime)) {
615                                 objp->status = EOVERFLOW;
616                                 return (TRUE);
617                         }
618                         vap->va_ctime.tv_sec = ntime;
619                         vap->va_ctime.tv_nsec = IXDR_GET_U_INT32(ptr);
620                 }
621 
622         } else {
623                 uint64 fsid;
624 
625                 /*
626                  * Slow path
627                  */
628                 if (!(xdr_enum(xdrs, (enum_t *)&vap->va_type) &&
629                         xdr_u_int(xdrs, &vap->va_mode) &&
630                         xdr_u_int(xdrs, &vap->va_nlink) &&
631                         xdr_u_int(xdrs, (uint_t *)&vap->va_uid) &&
632                         xdr_u_int(xdrs, (uint_t *)&vap->va_gid) &&
633                         xdr_u_longlong_t(xdrs, &vap->va_size) &&
634                         xdr_u_longlong_t(xdrs, &used) &&
635                         xdr_u_int(xdrs, &rdev.specdata1) &&
636                         xdr_u_int(xdrs, &rdev.specdata2) &&
637                         xdr_u_longlong_t(xdrs, &fsid) &&    /* ignored */
638                         xdr_u_longlong_t(xdrs, &vap->va_nodeid)))
639                                 return (FALSE);
640 
641                 if (nfs_allow_preepoch_time) {
642                         if (!xdr_u_int(xdrs, &ntime))
643                                 return (FALSE);
644                         vap->va_atime.tv_sec = (int32_t)ntime;
645                         if (!xdr_u_int(xdrs, &ntime))
646                                 return (FALSE);
647                         vap->va_atime.tv_nsec = ntime;
648 
649                         if (!xdr_u_int(xdrs, &ntime))
650                                 return (FALSE);
651                         vap->va_mtime.tv_sec = (int32_t)ntime;
652                         if (!xdr_u_int(xdrs, &ntime))
653                                 return (FALSE);
654                         vap->va_mtime.tv_nsec = ntime;
655 
656                         if (!xdr_u_int(xdrs, &ntime))
657                                 return (FALSE);
658                         vap->va_ctime.tv_sec = (int32_t)ntime;
659                         if (!xdr_u_int(xdrs, &ntime))
660                                 return (FALSE);
661                         vap->va_ctime.tv_nsec = ntime;
662                 } else {
663                         /*
664                          * Check if the time would overflow on 32-bit
665                          * Set status and keep decoding stream.
666                          */
667                         if (!xdr_u_int(xdrs, &ntime))
668                                 return (FALSE);
669                         /*CONSTCOND*/
670                         if (NFS3_TIME_OVERFLOW(ntime)) {
671                                 objp->status = EOVERFLOW;
672                         }
673                         vap->va_atime.tv_sec = ntime;
674                         if (!xdr_u_int(xdrs, &ntime))
675                                 return (FALSE);
676                         vap->va_atime.tv_nsec = ntime;
677 
678                         if (!xdr_u_int(xdrs, &ntime))
679                                 return (FALSE);
680                         /*CONSTCOND*/
681                         if (NFS3_TIME_OVERFLOW(ntime)) {
682                                 objp->status = EOVERFLOW;
683                         }
684                         vap->va_mtime.tv_sec = ntime;
685                         if (!xdr_u_int(xdrs, &ntime))
686                                 return (FALSE);
687                         vap->va_mtime.tv_nsec = ntime;
688 
689                         if (!xdr_u_int(xdrs, &ntime))
690                                 return (FALSE);
691                         /*CONSTCOND*/
692                         if (NFS3_TIME_OVERFLOW(ntime)) {
693                                 objp->status = EOVERFLOW;
694                         }
695                         vap->va_ctime.tv_sec = ntime;
696                         if (!xdr_u_int(xdrs, &ntime))
697                                 return (FALSE);
698                         vap->va_ctime.tv_nsec = ntime;
699                 }
700 
701                 /*
702                  * Fixup as needed
703                  */
704                 if (vap->va_type < NF3REG || vap->va_type > NF3FIFO)
705                         vap->va_type = VBAD;
706                 else
707                         vap->va_type = nf3_to_vt[vap->va_type];
708                 if (vap->va_uid == NFS_UID_NOBODY)
709                         vap->va_uid = UID_NOBODY;
710                 if (vap->va_gid == NFS_GID_NOBODY)
711                         vap->va_gid = GID_NOBODY;
712                 /*
713                  * If invalid size, set status, and
714                  * return TRUE, caller must ignore vap.
715                  */
716                 if (!NFS3_SIZE_OK(vap->va_size)) {
717                         objp->status = EFBIG;
718                         return (TRUE);
719                 }
720         }
721 
722         /*
723          * Fill in derived fields
724          */
725         vap->va_fsid = objp->vp->v_vfsp->vfs_dev;
726         vap->va_seq = 0;
727 
728         /*
729          * Common case values
730          */
731         vap->va_rdev = 0;
732         vap->va_blksize = MAXBSIZE;
733         vap->va_nblocks = 0;
734 
735         switch (vap->va_type) {
736         case VREG:
737         case VDIR:
738         case VLNK:
739                 vap->va_nblocks = (u_longlong_t)
740                         ((used + (size3)DEV_BSIZE - (size3)1) /
741                         (size3)DEV_BSIZE);
742                 break;
743         case VBLK:
744                 vap->va_blksize = DEV_BSIZE;
745                 /* FALLTHRU */
746         case VCHR:
747                 vap->va_rdev = makedevice(rdev.specdata1, rdev.specdata2);
748                 break;
749         case VSOCK:
750         case VFIFO:
751         default:
752                 break;
753         }
754 
755         return (TRUE);
756 }
757 
758 static bool_t
759 xdr_post_op_vattr(XDR *xdrs, post_op_vattr *objp)
760 {
761         /*
762          * DECODE only
763          */
764         ASSERT(xdrs->x_op == XDR_DECODE);
765 
766         if (!xdr_bool(xdrs, &objp->attributes))
767                 return (FALSE);
768 
769         if (objp->attributes == FALSE)
770                 return (TRUE);
771 
772         if (objp->attributes != TRUE)
773                 return (FALSE);
774 
775         if (!xdr_fattr3_to_vattr(xdrs, &objp->fres))
776                 return (FALSE);
777 
778         /*
779          * The file size may cause an EFBIG or the time values
780          * may cause EOVERFLOW, if so simply drop the attributes.
781          */
782         if (objp->fres.status != NFS3_OK)
783                 objp->attributes = FALSE;
784 
785         return (TRUE);
786 }
787 
788 bool_t
789 xdr_post_op_attr(XDR *xdrs, post_op_attr *objp)
790 {
791         if (!xdr_bool(xdrs, &objp->attributes))
792                 return (FALSE);
793 
794         if (objp->attributes == FALSE)
795                 return (TRUE);
796 
797         if (objp->attributes != TRUE)
798                 return (FALSE);
799 
800         if (!xdr_fattr3(xdrs, &objp->attr))
801                 return (FALSE);
802 
803         /*
804          * Check that we don't get a file we can't handle through
805          *      existing interfaces (especially stat64()).
806          * Decode only check since on encode the data has
807          * been dealt with in the above call to xdr_fattr3().
808          */
809         if (xdrs->x_op == XDR_DECODE) {
810                 /* Set attrs to false if invalid size or time */
811                 if (!NFS3_SIZE_OK(objp->attr.size)) {
812                         objp->attributes = FALSE;
813                         return (TRUE);
814                 }
815 #ifndef _LP64
816                 if (!NFS3_FATTR_TIME_OK(&objp->attr))
817                         objp->attributes = FALSE;
818 #endif
819         }
820         return (TRUE);
821 }
822 
823 static bool_t
824 xdr_wcc_data(XDR *xdrs, wcc_data *objp)
825 {
826         int32_t *ptr;
827         wcc_attr *attrp;
828 
829         if (xdrs->x_op == XDR_FREE)
830                 return (TRUE);
831 
832         if (xdrs->x_op == XDR_DECODE) {
833                 /* pre_op_attr */
834                 if (!xdr_bool(xdrs, &objp->before.attributes))
835                         return (FALSE);
836 
837                 switch (objp->before.attributes) {
838                 case TRUE:
839                         attrp = &objp->before.attr;
840                         ptr = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT);
841                         if (ptr != NULL) {
842                                 IXDR_GET_U_HYPER(ptr, attrp->size);
843                                 attrp->mtime.seconds = IXDR_GET_U_INT32(ptr);
844                                 attrp->mtime.nseconds = IXDR_GET_U_INT32(ptr);
845                                 attrp->ctime.seconds = IXDR_GET_U_INT32(ptr);
846                                 attrp->ctime.nseconds = IXDR_GET_U_INT32(ptr);
847                         } else {
848                                 if (!xdr_u_longlong_t(xdrs, &attrp->size))
849                                         return (FALSE);
850                                 if (!xdr_u_int(xdrs, &attrp->mtime.seconds))
851                                         return (FALSE);
852                                 if (!xdr_u_int(xdrs, &attrp->mtime.nseconds))
853                                         return (FALSE);
854                                 if (!xdr_u_int(xdrs, &attrp->ctime.seconds))
855                                         return (FALSE);
856                                 if (!xdr_u_int(xdrs, &attrp->ctime.nseconds))
857                                         return (FALSE);
858                         }
859 
860 #ifndef _LP64
861                         /*
862                          * check time overflow.
863                          */
864                         if (!NFS3_TIME_OK(attrp->mtime.seconds) ||
865                             !NFS3_TIME_OK(attrp->ctime.seconds))
866                                 objp->before.attributes = FALSE;
867 #endif
868                         break;
869                 case FALSE:
870                         break;
871                 default:
872                         return (FALSE);
873                 }
874         }
875 
876         if (xdrs->x_op == XDR_ENCODE) {
877                 /* pre_op_attr */
878                 if (!xdr_bool(xdrs, &objp->before.attributes))
879                         return (FALSE);
880 
881                 switch (objp->before.attributes) {
882                 case TRUE:
883                         attrp = &objp->before.attr;
884 
885                         ptr = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT);
886                         if (ptr != NULL) {
887                                 IXDR_PUT_U_HYPER(ptr, attrp->size);
888                                 IXDR_PUT_U_INT32(ptr, attrp->mtime.seconds);
889                                 IXDR_PUT_U_INT32(ptr, attrp->mtime.nseconds);
890                                 IXDR_PUT_U_INT32(ptr, attrp->ctime.seconds);
891                                 IXDR_PUT_U_INT32(ptr, attrp->ctime.nseconds);
892                         } else {
893                                 if (!xdr_u_longlong_t(xdrs, &attrp->size))
894                                         return (FALSE);
895                                 if (!xdr_u_int(xdrs, &attrp->mtime.seconds))
896                                         return (FALSE);
897                                 if (!xdr_u_int(xdrs, &attrp->mtime.nseconds))
898                                         return (FALSE);
899                                 if (!xdr_u_int(xdrs, &attrp->ctime.seconds))
900                                         return (FALSE);
901                                 if (!xdr_u_int(xdrs, &attrp->ctime.nseconds))
902                                         return (FALSE);
903                         }
904                         break;
905                 case FALSE:
906                         break;
907                 default:
908                         return (FALSE);
909                 }
910         }
911         return (xdr_post_op_attr(xdrs, &objp->after));
912 }
913 
914 bool_t
915 xdr_post_op_fh3(XDR *xdrs, post_op_fh3 *objp)
916 {
917         if (!xdr_bool(xdrs, &objp->handle_follows))
918                 return (FALSE);
919         switch (objp->handle_follows) {
920         case TRUE:
921                 return (xdr_nfs_fh3(xdrs, &objp->handle));
922         case FALSE:
923                 return (TRUE);
924         default:
925                 return (FALSE);
926         }
927 }
928 
929 static bool_t
930 xdr_sattr3(XDR *xdrs, sattr3 *objp)
931 {
932         /* set_mode3 */
933         if (!xdr_bool(xdrs, &objp->mode.set_it))
934                 return (FALSE);
935         if (objp->mode.set_it)
936                 if (!xdr_u_int(xdrs, &objp->mode.mode))
937                         return (FALSE);
938         /* set_uid3 */
939         if (!xdr_bool(xdrs, &objp->uid.set_it))
940                 return (FALSE);
941         if (objp->uid.set_it)
942                 if (!xdr_u_int(xdrs, &objp->uid.uid))
943                         return (FALSE);
944         /* set_gid3 */
945         if (!xdr_bool(xdrs, &objp->gid.set_it))
946                 return (FALSE);
947         if (objp->gid.set_it)
948                 if (!xdr_u_int(xdrs, &objp->gid.gid))
949                         return (FALSE);
950 
951         /* set_size3 */
952         if (!xdr_bool(xdrs, &objp->size.set_it))
953                 return (FALSE);
954         if (objp->size.set_it)
955                 if (!xdr_u_longlong_t(xdrs, &objp->size.size))
956                         return (FALSE);
957 
958         /* set_atime */
959         if (!xdr_enum(xdrs, (enum_t *)&objp->atime.set_it))
960                 return (FALSE);
961         if (objp->atime.set_it == SET_TO_CLIENT_TIME) {
962                 if (!xdr_u_int(xdrs, &objp->atime.atime.seconds))
963                         return (FALSE);
964                 if (!xdr_u_int(xdrs, &objp->atime.atime.nseconds))
965                         return (FALSE);
966         }
967 
968         /* set_mtime */
969         if (!xdr_enum(xdrs, (enum_t *)&objp->mtime.set_it))
970                 return (FALSE);
971         if (objp->mtime.set_it == SET_TO_CLIENT_TIME) {
972                 if (!xdr_u_int(xdrs, &objp->mtime.mtime.seconds))
973                         return (FALSE);
974                 if (!xdr_u_int(xdrs, &objp->mtime.mtime.nseconds))
975                         return (FALSE);
976         }
977 
978         return (TRUE);
979 }
980 
981 bool_t
982 xdr_GETATTR3res(XDR *xdrs, GETATTR3res *objp)
983 {
984         if (!xdr_enum(xdrs, (enum_t *)&objp->status))
985                 return (FALSE);
986         if (objp->status != NFS3_OK)
987                 return (TRUE);
988         /* xdr_GETATTR3resok */
989         return (xdr_fattr3(xdrs, &objp->resok.obj_attributes));
990 }
991 
992 bool_t
993 xdr_GETATTR3vres(XDR *xdrs, GETATTR3vres *objp)
994 {
995         /*
996          * DECODE or FREE only
997          */
998         if (xdrs->x_op == XDR_FREE)
999                 return (TRUE);
1000 
1001         if (xdrs->x_op != XDR_DECODE)
1002                 return (FALSE);
1003 
1004         if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1005                 return (FALSE);
1006 
1007         if (objp->status != NFS3_OK)
1008                 return (TRUE);
1009 
1010         return (xdr_fattr3_to_vattr(xdrs, &objp->fres));
1011 }
1012 
1013 
1014 bool_t
1015 xdr_SETATTR3args(XDR *xdrs, SETATTR3args *objp)
1016 {
1017         if (!xdr_nfs_fh3(xdrs, &objp->object))
1018                 return (FALSE);
1019         if (!xdr_sattr3(xdrs, &objp->new_attributes))
1020                 return (FALSE);
1021 
1022         /* sattrguard3 */
1023         if (!xdr_bool(xdrs, &objp->guard.check))
1024                 return (FALSE);
1025         switch (objp->guard.check) {
1026         case TRUE:
1027                 if (!xdr_u_int(xdrs, &objp->guard.obj_ctime.seconds))
1028                         return (FALSE);
1029                 return (xdr_u_int(xdrs, &objp->guard.obj_ctime.nseconds));
1030         case FALSE:
1031                 return (TRUE);
1032         default:
1033                 return (FALSE);
1034         }
1035 }
1036 
1037 bool_t
1038 xdr_SETATTR3res(XDR *xdrs, SETATTR3res *objp)
1039 {
1040         if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1041                 return (FALSE);
1042         switch (objp->status) {
1043         case NFS3_OK:
1044                 return (xdr_wcc_data(xdrs, &objp->resok.obj_wcc));
1045         default:
1046                 return (xdr_wcc_data(xdrs, &objp->resfail.obj_wcc));
1047         }
1048 }
1049 
1050 bool_t
1051 xdr_LOOKUP3res(XDR *xdrs, LOOKUP3res *objp)
1052 {
1053         LOOKUP3resok *resokp;
1054 
1055         if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1056                 return (FALSE);
1057 
1058         if (objp->status != NFS3_OK)
1059                 return (xdr_post_op_attr(xdrs, &objp->resfail.dir_attributes));
1060 
1061         /* xdr_LOOKUP3resok */
1062         resokp = &objp->resok;
1063         if (!xdr_nfs_fh3(xdrs, &resokp->object))
1064                 return (FALSE);
1065         if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
1066                 return (FALSE);
1067         return (xdr_post_op_attr(xdrs, &resokp->dir_attributes));
1068 }
1069 
1070 bool_t
1071 xdr_LOOKUP3vres(XDR *xdrs, LOOKUP3vres *objp)
1072 {
1073         /*
1074          * DECODE or FREE only
1075          */
1076         if (xdrs->x_op == XDR_FREE)
1077                 return (TRUE);
1078 
1079         if (xdrs->x_op != XDR_DECODE)
1080                 return (FALSE);
1081 
1082         if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1083                 return (FALSE);
1084 
1085         if (objp->status != NFS3_OK)
1086                 return (xdr_post_op_vattr(xdrs, &objp->dir_attributes));
1087 
1088         if (!xdr_nfs_fh3(xdrs, &objp->object))
1089                 return (FALSE);
1090         if (!xdr_post_op_vattr(xdrs, &objp->obj_attributes))
1091                 return (FALSE);
1092         return (xdr_post_op_vattr(xdrs, &objp->dir_attributes));
1093 }
1094 
1095 bool_t
1096 xdr_ACCESS3args(XDR *xdrs, ACCESS3args *objp)
1097 {
1098         int32_t *ptr;
1099         int32_t *fhp;
1100         int len;
1101         uint_t in_size;
1102 
1103         if (xdrs->x_op == XDR_FREE)
1104                 return (TRUE);
1105 
1106         in_size = RNDUP(sizeof (fhandle_t)) +   2 * BYTES_PER_XDR_UNIT;
1107         ptr = XDR_INLINE(xdrs, in_size);
1108 
1109         if (ptr != NULL) {
1110                 len =  (xdrs->x_op == XDR_DECODE) ?
1111                         *ptr : objp->object.fh3_length;
1112 
1113                 if (XDR_CHECKFHSIZE(xdrs, len, in_size)) {
1114                         fhp = (int32_t *)&(objp->object.fh3_u.data);
1115                         if (xdrs->x_op == XDR_DECODE) {
1116                                 objp->object.fh3_length = IXDR_GET_U_INT32(ptr);
1117                                 *fhp++ = *ptr++;
1118                                 *fhp++ = *ptr++;
1119                                 *fhp++ = *ptr++;
1120                                 *fhp++ = *ptr++;
1121                                 *fhp++ = *ptr++;
1122                                 *fhp++ = *ptr++;
1123                                 *fhp++ = *ptr++;
1124                                 *fhp = *ptr++;
1125                                 objp->access = IXDR_GET_U_INT32(ptr);
1126                         } else {
1127                                 IXDR_PUT_U_INT32(ptr, objp->object.fh3_length);
1128                                 *ptr++ = *fhp++;
1129                                 *ptr++ = *fhp++;
1130                                 *ptr++ = *fhp++;
1131                                 *ptr++ = *fhp++;
1132                                 *ptr++ = *fhp++;
1133                                 *ptr++ = *fhp++;
1134                                 *ptr++ = *fhp++;
1135                                 *ptr++ = *fhp;
1136                                 IXDR_PUT_U_INT32(ptr, objp->access);
1137                         }
1138                         return (TRUE);
1139                 }
1140         }
1141 
1142         if (!xdr_nfs_fh3(xdrs, &objp->object))
1143                 return (FALSE);
1144         return (xdr_u_int(xdrs, &objp->access));
1145 }
1146 
1147 
1148 bool_t
1149 xdr_ACCESS3res(XDR *xdrs, ACCESS3res *objp)
1150 {
1151         ACCESS3resok *resokp;
1152 
1153         if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1154                 return (FALSE);
1155         if (objp->status != NFS3_OK)
1156                 return (xdr_post_op_attr(xdrs, &objp->resfail.obj_attributes));
1157 
1158         /* xdr_ACCESS3resok */
1159         resokp = &objp->resok;
1160         if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
1161                 return (FALSE);
1162         return (xdr_u_int(xdrs, &resokp->access));
1163 }
1164 
1165 bool_t
1166 xdr_READLINK3res(XDR *xdrs, READLINK3res *objp)
1167 {
1168 
1169         READLINK3resok *resokp;
1170 
1171         if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1172                 return (FALSE);
1173         if (objp->status != NFS3_OK)
1174                 return (xdr_post_op_attr(xdrs,
1175                         &objp->resfail.symlink_attributes));
1176 
1177         /* xdr_READLINK3resok */
1178         resokp = &objp->resok;
1179         if (!xdr_post_op_attr(xdrs, &resokp->symlink_attributes))
1180                 return (FALSE);
1181         return (xdr_string3(xdrs, &resokp->data, MAXPATHLEN));
1182 }
1183 
1184 bool_t
1185 xdr_READ3args(XDR *xdrs, READ3args *objp)
1186 {
1187         int32_t *ptr;
1188         int32_t *fhp;
1189         uint_t in_size;
1190         int len;
1191 
1192         if (xdrs->x_op == XDR_FREE)
1193                 return (TRUE);
1194 
1195         in_size = RNDUP(sizeof (fhandle_t)) + 4 * BYTES_PER_XDR_UNIT;
1196         ptr = XDR_INLINE(xdrs, in_size);
1197         if (ptr != NULL) {
1198                 len = (xdrs->x_op == XDR_DECODE) ?
1199                         *ptr : objp->file.fh3_length;
1200 
1201                 if (XDR_CHECKFHSIZE(xdrs, len, in_size)) {
1202                         fhp = (int32_t *)& objp->file.fh3_u.data;
1203                         if (xdrs->x_op == XDR_DECODE) {
1204                                 objp->file.fh3_length = IXDR_GET_U_INT32(ptr);
1205                                 *fhp++ = *ptr++;
1206                                 *fhp++ = *ptr++;
1207                                 *fhp++ = *ptr++;
1208                                 *fhp++ = *ptr++;
1209                                 *fhp++ = *ptr++;
1210                                 *fhp++ = *ptr++;
1211                                 *fhp++ = *ptr++;
1212                                 *fhp = *ptr++;
1213                                 IXDR_GET_U_HYPER(ptr, objp->offset);
1214                                 objp->count = IXDR_GET_U_INT32(ptr);
1215                         } else {
1216                                 IXDR_PUT_U_INT32(ptr, objp->file.fh3_length);
1217                                 *ptr++ = *fhp++;
1218                                 *ptr++ = *fhp++;
1219                                 *ptr++ = *fhp++;
1220                                 *ptr++ = *fhp++;
1221                                 *ptr++ = *fhp++;
1222                                 *ptr++ = *fhp++;
1223                                 *ptr++ = *fhp++;
1224                                 *ptr++ = *fhp;
1225                                 IXDR_PUT_U_HYPER(ptr, objp->offset);
1226                                 IXDR_PUT_U_INT32(ptr, objp->count);
1227                         }
1228                         return (TRUE);
1229                 }
1230         }
1231 
1232         if (!xdr_nfs_fh3(xdrs, &objp->file))
1233                 return (FALSE);
1234         if (!xdr_u_longlong_t(xdrs, &objp->offset))
1235                 return (FALSE);
1236         return (xdr_u_int(xdrs, &objp->count));
1237 }
1238 
1239 bool_t
1240 xdr_READ3res(XDR *xdrs, READ3res *objp)
1241 {
1242         READ3resok *resokp;
1243         bool_t ret;
1244         mblk_t *mp;
1245 
1246         if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1247                 return (FALSE);
1248 
1249         if (objp->status != NFS3_OK)
1250                 return (xdr_post_op_attr(xdrs, &objp->resfail.file_attributes));
1251 
1252         resokp = &objp->resok;
1253 
1254         if (xdr_post_op_attr(xdrs, &resokp->file_attributes) == FALSE ||
1255             xdr_u_int(xdrs, &resokp->count) == FALSE ||
1256             xdr_bool(xdrs, &resokp->eof) == FALSE) {
1257                 return (FALSE);
1258         }
1259 
1260         if (xdrs->x_op == XDR_ENCODE) {
1261                 int i, rndup;
1262 
1263                 mp = resokp->data.mp;
1264                 if (mp != NULL && xdrs->x_ops == &xdrmblk_ops) {
1265                         mp->b_wptr += resokp->count;
1266                         rndup = BYTES_PER_XDR_UNIT -
1267                                 (resokp->data.data_len % BYTES_PER_XDR_UNIT);
1268                         if (rndup != BYTES_PER_XDR_UNIT)
1269                                 for (i = 0; i < rndup; i++)
1270                                         *mp->b_wptr++ = '\0';
1271                         if (xdrmblk_putmblk(xdrs, mp, resokp->count) == TRUE) {
1272                                 resokp->data.mp = NULL;
1273                                 return (TRUE);
1274                         }




1275                 }
1276                 /*












1277                  * Fall thru for the xdr_bytes()
1278                  *
1279                  * note: the mblk will be freed in
1280                  * rfs3_read_free.
1281                  */
1282         }
1283 


1284         ret = xdr_bytes(xdrs, (char **)&resokp->data.data_val,
1285             &resokp->data.data_len, nfs3tsize());
1286  
1287         return (ret);
1288 }
1289 
1290 bool_t
1291 xdr_READ3vres(XDR *xdrs, READ3vres *objp)
1292 {

1293         /*
1294          * DECODE or FREE only
1295          */
1296         if (xdrs->x_op == XDR_FREE)
1297                 return (TRUE);
1298 
1299         if (xdrs->x_op != XDR_DECODE)
1300                 return (FALSE);
1301 
1302         if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1303                 return (FALSE);
1304 
1305         if (!xdr_post_op_vattr(xdrs, &objp->pov))
1306                 return (FALSE);
1307 
1308         if (objp->status != NFS3_OK)
1309                 return (TRUE);
1310 
1311         if (!xdr_u_int(xdrs, &objp->count))
1312                 return (FALSE);
1313 
1314         if (!xdr_bool(xdrs, &objp->eof))
1315                 return (FALSE);
1316 
















1317         return (xdr_bytes(xdrs, (char **)&objp->data.data_val,
1318             &objp->data.data_len, nfs3tsize()));
1319 }
1320 
1321 bool_t
1322 xdr_READ3uiores(XDR *xdrs, READ3uiores *objp)
1323 {

1324         bool_t attributes;
1325         mblk_t *mp;
1326         size_t n;
1327         int error;
1328         int size = (int)objp->size;
1329         struct uio *uiop = objp->uiop;
1330         int32_t fattr3_len = NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT;
1331         int32_t *ptr;
1332 
1333         /*
1334          * DECODE or FREE only
1335          */
1336         if (xdrs->x_op == XDR_FREE)
1337                 return (TRUE);
1338 
1339         if (xdrs->x_op != XDR_DECODE)
1340                 return (FALSE);
1341 
1342         if (!XDR_GETINT32(xdrs, (int32_t *)&objp->status))
1343                 return (FALSE);
1344 
1345         if (!XDR_GETINT32(xdrs, (int32_t *)&attributes))
1346                 return (FALSE);
1347 
1348         /*
1349          * For directio we just skip over attributes if present
1350          */
1351         switch (attributes) {
1352         case TRUE:
1353                 if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &fattr3_len))
1354                         return (FALSE);
1355                 break;
1356         case FALSE:
1357                 break;
1358         default:
1359                 return (FALSE);
1360         }
1361 
1362         if (objp->status != NFS3_OK)
1363                 return (TRUE);
1364 
1365         if (!XDR_GETINT32(xdrs, (int32_t *)&objp->count))
1366                 return (FALSE);
1367 
1368         if (!XDR_GETINT32(xdrs, (int32_t *)&objp->eof))
1369                 return (FALSE);
1370 
1371         if (xdrs->x_ops == &xdrmblk_ops) {
1372                 if (!xdrmblk_getmblk(xdrs, &mp, &objp->size))
1373                         return (FALSE);
1374 
1375                 if (objp->size == 0)
1376                         return (TRUE);
1377 
1378                 if (objp->size > size)
1379                         return (FALSE);
1380 
1381                 size = (int)objp->size;
1382                 do {
1383                         n = MIN(size, mp->b_wptr - mp->b_rptr);
1384                         if ((n = MIN(uiop->uio_resid, n)) != 0) {
1385 
1386                                 error = uiomove((char *)mp->b_rptr, n, UIO_READ,
1387                                                 uiop);
1388                                 if (error)
1389                                         return (FALSE);
1390                                 mp->b_rptr += n;
1391                                 size -= n;
1392                         }
1393 
1394                         while (mp && (mp->b_rptr >= mp->b_wptr))
1395                                 mp = mp->b_cont;
1396                 } while (mp && size > 0 && uiop->uio_resid > 0);
1397 
1398                 return (TRUE);




















1399         }
1400 
1401         /*
1402          * This isn't an xdrmblk stream.   Handle the likely
1403          * case that it can be inlined (ex. xdrmem).
1404          */
1405         if (!XDR_GETINT32(xdrs, (int32_t *)&objp->size))
1406                 return (FALSE);
1407 
1408         if (objp->size == 0)
1409                 return (TRUE);
1410 
1411         if (objp->size > size)
1412                 return (FALSE);
1413 
1414         size = (int)objp->size;
1415         if ((ptr = XDR_INLINE(xdrs, size)) != NULL)
1416                 return (uiomove(ptr, size, UIO_READ, uiop) ? FALSE : TRUE);
1417 
1418         /*
1419          * Handle some other (unlikely) stream type that will need a copy.
1420          */
1421         if ((ptr = kmem_alloc(size, KM_NOSLEEP)) == NULL)
1422                 return (FALSE);
1423 
1424         if (!XDR_GETBYTES(xdrs, (caddr_t)ptr, size)) {
1425                 kmem_free(ptr, size);
1426                 return (FALSE);
1427         }
1428         error = uiomove(ptr, size, UIO_READ, uiop);
1429         kmem_free(ptr, size);
1430 
1431         return (error ? FALSE : TRUE);
1432 }
1433 
1434 bool_t
1435 xdr_WRITE3args(XDR *xdrs, WRITE3args *objp)
1436 {
1437         int32_t *ptr;
1438         int32_t *fhp;
1439         uint_t in_size;
1440         int len;
1441 
1442         in_size = RNDUP(sizeof (fhandle_t)) + 5 * BYTES_PER_XDR_UNIT;
1443         ptr = XDR_INLINE(xdrs, in_size);
1444 
1445         if (ptr != NULL) {
1446                 len = (xdrs->x_op == XDR_DECODE) ? *ptr : objp->file.fh3_length;
1447 
1448                 if (XDR_CHECKFHSIZE(xdrs, len, in_size)) {
1449                         fhp = (int32_t *)&(objp->file.fh3_u.data);
1450                         if (xdrs->x_op == XDR_DECODE) {
1451                                 objp->file.fh3_length = IXDR_GET_U_INT32(ptr);
1452                                 *fhp++ = *ptr++;
1453                                 *fhp++ = *ptr++;
1454                                 *fhp++ = *ptr++;
1455                                 *fhp++ = *ptr++;
1456                                 *fhp++ = *ptr++;
1457                                 *fhp++ = *ptr++;
1458                                 *fhp++ = *ptr++;
1459                                 *fhp = *ptr++;
1460                                 IXDR_GET_U_HYPER(ptr, objp->offset);
1461                                 objp->count = IXDR_GET_U_INT32(ptr);
1462                                 objp->stable = IXDR_GET_ENUM(ptr,
1463                                                 enum stable_how);
1464                                 if (xdrs->x_ops == &xdrmblk_ops)
1465                                         return (xdrmblk_getmblk(xdrs,
1466                                         &objp->mblk,
1467                                         (uint_t *)&objp->data.data_len));
1468                                 /*
1469                                  * It is just as efficient to xdr_bytes
1470                                  * an array of unknown length as to inline
1471                                  * copy it.
1472                                  */
1473                                 return (xdr_bytes(xdrs, &objp->data.data_val,
1474                                                 (uint_t *)&objp->data.data_len,
1475                                                 nfs3tsize()));
1476                         }
1477 
1478                         if (xdrs->x_op == XDR_ENCODE) {
1479                                 IXDR_PUT_U_INT32(ptr, objp->file.fh3_length);
1480                                 *ptr++ = *fhp++;
1481                                 *ptr++ = *fhp++;
1482                                 *ptr++ = *fhp++;
1483                                 *ptr++ = *fhp++;
1484                                 *ptr++ = *fhp++;
1485                                 *ptr++ = *fhp++;
1486                                 *ptr++ = *fhp++;
1487                                 *ptr++ = *fhp;
1488                                 IXDR_PUT_U_HYPER(ptr, objp->offset);
1489                                 IXDR_PUT_U_INT32(ptr, objp->count);
1490                                 IXDR_PUT_ENUM(ptr, objp->stable);
1491                                 return (xdr_bytes(xdrs,
1492                                         (char **)&objp->data.data_val,
1493                                         (uint_t *)&objp->data.data_len,
1494                                         nfs3tsize()));
1495                         }
1496 
1497                         ASSERT(xdrs->x_op == XDR_FREE);
1498                         if (objp->data.data_val != NULL) {
1499                                 kmem_free(objp->data.data_val,
1500                                         (uint_t)objp->data.data_len);
1501                                 objp->data.data_val = NULL;
1502                         }
1503                         return (TRUE);
1504                 }
1505         }
1506 
1507         if (!xdr_nfs_fh3(xdrs, &objp->file))
1508                 return (FALSE);
1509         if (!xdr_u_longlong_t(xdrs, &objp->offset))
1510                 return (FALSE);
1511         if (!xdr_u_int(xdrs, &objp->count))
1512                 return (FALSE);
1513         if (!xdr_enum(xdrs, (enum_t *)&objp->stable))
1514                 return (FALSE);
1515 
1516         if (xdrs->x_op == XDR_DECODE) {
1517                 if (xdrs->x_ops == &xdrmblk_ops) {
1518                         if (xdrmblk_getmblk(xdrs, &objp->mblk,
1519                             &objp->data.data_len) == TRUE) {
1520                                 objp->data.data_val = NULL;
1521                                 return (TRUE);
1522                         }
1523                 }
1524                 objp->mblk = NULL;
1525                 /* Else fall thru for the xdr_bytes(). */
1526         }
1527 
1528         return (xdr_bytes(xdrs, (char **)&objp->data.data_val,
1529             &objp->data.data_len, nfs3tsize()));
1530 }
1531 
1532 bool_t
1533 xdr_WRITE3res(XDR *xdrs, WRITE3res *objp)
1534 {
1535         WRITE3resok *resokp;
1536 
1537         if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1538                 return (FALSE);
1539         if (objp->status != NFS3_OK) /* xdr_WRITE3resfail */
1540                 return (xdr_wcc_data(xdrs, &objp->resfail.file_wcc));
1541 
1542         /* xdr_WRITE3resok */
1543         resokp = &objp->resok;
1544         if (!xdr_wcc_data(xdrs, &resokp->file_wcc))
1545                 return (FALSE);
1546         if (!xdr_u_int(xdrs, &resokp->count))
1547                 return (FALSE);
1548         if (!xdr_enum(xdrs, (enum_t *)&resokp->committed))
1549                 return (FALSE);
1550         /*
1551          * writeverf3 is really an opaque 8 byte
1552          * quantity, but we will treat it as a
1553          * hyper for efficiency, the cost of
1554          * a byteswap here saves bcopys elsewhere
1555          */
1556         return (xdr_u_longlong_t(xdrs, &resokp->verf));
1557 }
1558 
1559 bool_t
1560 xdr_CREATE3args(XDR *xdrs, CREATE3args *objp)
1561 {
1562         createhow3 *howp;
1563 
1564         if (!xdr_diropargs3(xdrs, &objp->where))
1565                 return (FALSE);
1566 
1567         /* xdr_createhow3 */
1568         howp = &objp->how;
1569 
1570         if (!xdr_enum(xdrs, (enum_t *)&howp->mode))
1571                 return (FALSE);
1572         switch (howp->mode) {
1573         case UNCHECKED:
1574         case GUARDED:
1575                 return (xdr_sattr3(xdrs, &howp->createhow3_u.obj_attributes));
1576         case EXCLUSIVE:
1577                 /*
1578                  * createverf3 is really an opaque 8 byte
1579                  * quantity, but we will treat it as a
1580                  * hyper for efficiency, the cost of
1581                  * a byteswap here saves bcopys elsewhere
1582                  */
1583                 return (xdr_u_longlong_t(xdrs, &howp->createhow3_u.verf));
1584         default:
1585                 return (FALSE);
1586         }
1587 }
1588 
1589 bool_t
1590 xdr_CREATE3res(XDR *xdrs, CREATE3res *objp)
1591 {
1592         CREATE3resok *resokp;
1593 
1594         if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1595                 return (FALSE);
1596         switch (objp->status) {
1597         case NFS3_OK:
1598                 /* xdr_CREATE3resok */
1599                 resokp = &objp->resok;
1600 
1601                 if (!xdr_post_op_fh3(xdrs, &resokp->obj))
1602                         return (FALSE);
1603                 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
1604                         return (FALSE);
1605                 return (xdr_wcc_data(xdrs, &resokp->dir_wcc));
1606         default:
1607                 /* xdr_CREATE3resfail */
1608                 return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
1609         }
1610 }
1611 
1612 bool_t
1613 xdr_MKDIR3args(XDR *xdrs, MKDIR3args *objp)
1614 {
1615         if (!xdr_diropargs3(xdrs, &objp->where))
1616                 return (FALSE);
1617         return (xdr_sattr3(xdrs, &objp->attributes));
1618 }
1619 
1620 bool_t
1621 xdr_MKDIR3res(XDR *xdrs, MKDIR3res *objp)
1622 {
1623         MKDIR3resok *resokp;
1624 
1625         if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1626                 return (FALSE);
1627         switch (objp->status) {
1628         case NFS3_OK:
1629                 /* xdr_MKDIR3resok */
1630                 resokp = &objp->resok;
1631 
1632                 if (!xdr_post_op_fh3(xdrs, &resokp->obj))
1633                         return (FALSE);
1634                 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
1635                         return (FALSE);
1636                 return (xdr_wcc_data(xdrs, &resokp->dir_wcc));
1637         default:
1638                 return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
1639         }
1640 }
1641 
1642 bool_t
1643 xdr_SYMLINK3args(XDR *xdrs, SYMLINK3args *objp)
1644 {
1645         if (!xdr_diropargs3(xdrs, &objp->where))
1646                 return (FALSE);
1647         if (!xdr_sattr3(xdrs, &objp->symlink.symlink_attributes))
1648                 return (FALSE);
1649         return (xdr_string3(xdrs, &objp->symlink.symlink_data, MAXPATHLEN));
1650 }
1651 
1652 bool_t
1653 xdr_SYMLINK3res(XDR *xdrs, SYMLINK3res *objp)
1654 {
1655         SYMLINK3resok *resokp;
1656 
1657         if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1658                 return (FALSE);
1659         switch (objp->status) {
1660         case NFS3_OK:
1661                 resokp = &objp->resok;
1662                 /* xdr_SYMLINK3resok */
1663                 if (!xdr_post_op_fh3(xdrs, &resokp->obj))
1664                         return (FALSE);
1665                 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
1666                         return (FALSE);
1667                 return (xdr_wcc_data(xdrs, &resokp->dir_wcc));
1668         default:
1669                 return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
1670         }
1671 }
1672 
1673 bool_t
1674 xdr_MKNOD3args(XDR *xdrs, MKNOD3args *objp)
1675 {
1676         mknoddata3 *whatp;
1677         devicedata3 *nod_objp;
1678 
1679         if (!xdr_diropargs3(xdrs, &objp->where))
1680                 return (FALSE);
1681 
1682         whatp = &objp->what;
1683         if (!xdr_enum(xdrs, (enum_t *)&whatp->type))
1684                 return (FALSE);
1685         switch (whatp->type) {
1686         case NF3CHR:
1687         case NF3BLK:
1688                 /* xdr_devicedata3 */
1689                 nod_objp = &whatp->mknoddata3_u.device;
1690                 if (!xdr_sattr3(xdrs, &nod_objp->dev_attributes))
1691                         return (FALSE);
1692                 if (!xdr_u_int(xdrs, &nod_objp->spec.specdata1))
1693                         return (FALSE);
1694                 return (xdr_u_int(xdrs, &nod_objp->spec.specdata2));
1695         case NF3SOCK:
1696         case NF3FIFO:
1697                 return (xdr_sattr3(xdrs, &whatp->mknoddata3_u.pipe_attributes));
1698         default:
1699                 break;
1700         }
1701         return (TRUE);
1702 }
1703 
1704 bool_t
1705 xdr_MKNOD3res(XDR *xdrs, MKNOD3res *objp)
1706 {
1707         MKNOD3resok *resokp;
1708 
1709         if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1710                 return (FALSE);
1711         switch (objp->status) {
1712         case NFS3_OK:
1713                 /* xdr_MKNOD3resok */
1714                 resokp = &objp->resok;
1715                 if (!xdr_post_op_fh3(xdrs, &resokp->obj))
1716                         return (FALSE);
1717                 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
1718                         return (FALSE);
1719                 return (xdr_wcc_data(xdrs, &resokp->dir_wcc));
1720         default:
1721                 return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
1722         }
1723 }
1724 
1725 bool_t
1726 xdr_REMOVE3res(XDR *xdrs, REMOVE3res *objp)
1727 {
1728         if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1729                 return (FALSE);
1730         switch (objp->status) {
1731         case NFS3_OK:
1732                 return (xdr_wcc_data(xdrs, &objp->resok.dir_wcc));
1733         default:
1734                 return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
1735         }
1736 }
1737 
1738 bool_t
1739 xdr_RMDIR3res(XDR *xdrs, RMDIR3res *objp)
1740 {
1741         if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1742                 return (FALSE);
1743         switch (objp->status) {
1744         case NFS3_OK:
1745                 return (xdr_wcc_data(xdrs, &objp->resok.dir_wcc));
1746         default:
1747                 return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
1748         }
1749 }
1750 
1751 bool_t
1752 xdr_RENAME3args(XDR *xdrs, RENAME3args *objp)
1753 {
1754         if (!xdr_diropargs3(xdrs, &objp->from))
1755                 return (FALSE);
1756         return (xdr_diropargs3(xdrs, &objp->to));
1757 }
1758 
1759 bool_t
1760 xdr_RENAME3res(XDR *xdrs, RENAME3res *objp)
1761 {
1762         RENAME3resok *resokp;
1763         RENAME3resfail *resfailp;
1764 
1765         if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1766                 return (FALSE);
1767         switch (objp->status) {
1768         case NFS3_OK:
1769                 /* xdr_RENAME3resok */
1770                 resokp = &objp->resok;
1771 
1772                 if (!xdr_wcc_data(xdrs, &resokp->fromdir_wcc))
1773                         return (FALSE);
1774                 return (xdr_wcc_data(xdrs, &resokp->todir_wcc));
1775         default:
1776                 /* xdr_RENAME3resfail */
1777                 resfailp = &objp->resfail;
1778                 if (!xdr_wcc_data(xdrs, &resfailp->fromdir_wcc))
1779                         return (FALSE);
1780                 return (xdr_wcc_data(xdrs, &resfailp->todir_wcc));
1781         }
1782 }
1783 
1784 bool_t
1785 xdr_LINK3args(XDR *xdrs, LINK3args *objp)
1786 {
1787         if (!xdr_nfs_fh3(xdrs, &objp->file))
1788                 return (FALSE);
1789         return (xdr_diropargs3(xdrs, &objp->link));
1790 }
1791 
1792 bool_t
1793 xdr_LINK3res(XDR *xdrs, LINK3res *objp)
1794 {
1795         LINK3resok *resokp;
1796         LINK3resfail *resfailp;
1797 
1798         if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1799                 return (FALSE);
1800         switch (objp->status) {
1801         case NFS3_OK:
1802                 /* xdr_LINK3resok */
1803                 resokp = &objp->resok;
1804                 if (!xdr_post_op_attr(xdrs, &resokp->file_attributes))
1805                         return (FALSE);
1806                 return (xdr_wcc_data(xdrs, &resokp->linkdir_wcc));
1807         default:
1808                 /* xdr_LINK3resfail */
1809                 resfailp = &objp->resfail;
1810                 if (!xdr_post_op_attr(xdrs, &resfailp->file_attributes))
1811                         return (FALSE);
1812                 return (xdr_wcc_data(xdrs, &resfailp->linkdir_wcc));
1813         }
1814 }
1815 
1816 bool_t
1817 xdr_READDIR3args(XDR *xdrs, READDIR3args *objp)
1818 {
1819         int32_t *ptr;
1820         int32_t *fhp;
1821         uint_t in_size;
1822         int len;
1823 
1824         if (xdrs->x_op == XDR_FREE)
1825                 return (TRUE);
1826 
1827         in_size = RNDUP(sizeof (fhandle_t)) + NFS3_COOKIEVERFSIZE +
1828                 4 * BYTES_PER_XDR_UNIT;
1829         ptr = XDR_INLINE(xdrs, in_size);
1830 
1831         if (ptr != NULL) {
1832                 len = (xdrs->x_op == XDR_DECODE) ? *ptr : objp->dir.fh3_length;
1833 
1834                 if (XDR_CHECKFHSIZE(xdrs, len, in_size)) {
1835 
1836                         fhp = (int32_t *)&(objp->dir.fh3_u.data);
1837 
1838                         if (xdrs->x_op == XDR_DECODE) {
1839                                 objp->dir.fh3_length = IXDR_GET_U_INT32(ptr);
1840                                 *fhp++ = *ptr++;
1841                                 *fhp++ = *ptr++;
1842                                 *fhp++ = *ptr++;
1843                                 *fhp++ = *ptr++;
1844                                 *fhp++ = *ptr++;
1845                                 *fhp++ = *ptr++;
1846                                 *fhp++ = *ptr++;
1847                                 *fhp = *ptr++;
1848                                 IXDR_GET_U_HYPER(ptr, objp->cookie);
1849                                 /*
1850                                  * cookieverf is really an opaque 8 byte
1851                                  * quantity, but we will treat it as a
1852                                  * hyper for efficiency, the cost of
1853                                  * a byteswap here saves bcopys elsewhere
1854                                  */
1855                                 IXDR_GET_U_HYPER(ptr, objp->cookieverf);
1856                                 objp->count = IXDR_GET_U_INT32(ptr);
1857                         } else {
1858                                 IXDR_PUT_U_INT32(ptr, objp->dir.fh3_length);
1859                                 *ptr++ = *fhp++;
1860                                 *ptr++ = *fhp++;
1861                                 *ptr++ = *fhp++;
1862                                 *ptr++ = *fhp++;
1863                                 *ptr++ = *fhp++;
1864                                 *ptr++ = *fhp++;
1865                                 *ptr++ = *fhp++;
1866                                 *ptr++ = *fhp;
1867                                 IXDR_PUT_U_HYPER(ptr, objp->cookie);
1868                                 /*
1869                                  * cookieverf is really an opaque 8 byte
1870                                  * quantity, but we will treat it as a
1871                                  * hyper for efficiency, the cost of
1872                                  * a byteswap here saves bcopys elsewhere
1873                                  */
1874                                 IXDR_PUT_U_HYPER(ptr, objp->cookieverf);
1875                                 IXDR_PUT_U_INT32(ptr, objp->count);
1876                         }
1877                         return (TRUE);
1878                 }
1879         }
1880 
1881         if (!xdr_nfs_fh3(xdrs, &objp->dir))
1882                 return (FALSE);
1883         if (!xdr_u_longlong_t(xdrs, &objp->cookie))
1884                 return (FALSE);
1885         /*
1886          * cookieverf is really an opaque 8 byte
1887          * quantity, but we will treat it as a
1888          * hyper for efficiency, the cost of
1889          * a byteswap here saves bcopys elsewhere
1890          */
1891         if (!xdr_u_longlong_t(xdrs, &objp->cookieverf))
1892                 return (FALSE);
1893         return (xdr_u_int(xdrs, &objp->count));
1894 }
1895 
1896 #ifdef  nextdp
1897 #undef  nextdp
1898 #endif
1899 #define nextdp(dp)      ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
1900 #ifdef  roundup
1901 #undef  roundup
1902 #endif
1903 #define roundup(x, y)   ((((x) + ((y) - 1)) / (y)) * (y))
1904 
1905 /*
1906  * ENCODE ONLY
1907  */
1908 static bool_t
1909 xdr_putdirlist(XDR *xdrs, READDIR3resok *objp)
1910 {
1911         struct dirent64 *dp;
1912         char *name;
1913         int size;
1914         int bufsize;
1915         uint_t namlen;
1916         bool_t true = TRUE;
1917         bool_t false = FALSE;
1918         int entrysz;
1919         int tofit;
1920         fileid3 fileid;
1921         cookie3 cookie;
1922 
1923         if (xdrs->x_op != XDR_ENCODE)
1924                 return (FALSE);
1925 
1926         /*
1927          * bufsize is used to keep track of the size of the response.
1928          * It is primed with:
1929          *      1 for the status +
1930          *      1 for the dir_attributes.attributes boolean +
1931          *      2 for the cookie verifier
1932          * all times BYTES_PER_XDR_UNIT to convert from XDR units
1933          * to bytes.  If there are directory attributes to be
1934          * returned, then:
1935          *      NFS3_SIZEOF_FATTR3 for the dir_attributes.attr fattr3
1936          * time BYTES_PER_XDR_UNIT is added to account for them.
1937          */
1938         bufsize = (1 + 1 + 2) * BYTES_PER_XDR_UNIT;
1939         if (objp->dir_attributes.attributes)
1940                 bufsize += NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT;
1941         for (size = objp->size, dp = (struct dirent64 *)objp->reply.entries;
1942             size > 0;
1943             size -= dp->d_reclen, dp = nextdp(dp)) {
1944                 if (dp->d_reclen == 0)
1945                         return (FALSE);
1946                 if (dp->d_ino == 0)
1947                         continue;
1948                 name = dp->d_name;
1949                 namlen = (uint_t)strlen(dp->d_name);
1950                 /*
1951                  * An entry is composed of:
1952                  *      1 for the true/false list indicator +
1953                  *      2 for the fileid +
1954                  *      1 for the length of the name +
1955                  *      2 for the cookie +
1956                  * all times BYTES_PER_XDR_UNIT to convert from
1957                  * XDR units to bytes, plus the length of the name
1958                  * rounded up to the nearest BYTES_PER_XDR_UNIT.
1959                  */
1960                 entrysz = (1 + 2 + 1 + 2) * BYTES_PER_XDR_UNIT +
1961                     roundup(namlen, BYTES_PER_XDR_UNIT);
1962                 /*
1963                  * We need to check to see if the number of bytes left
1964                  * to go into the buffer will actually fit into the
1965                  * buffer.  This is calculated as the size of this
1966                  * entry plus:
1967                  *      1 for the true/false list indicator +
1968                  *      1 for the eof indicator
1969                  * times BYTES_PER_XDR_UNIT to convert from from
1970                  * XDR units to bytes.
1971                  */
1972                 tofit = entrysz + (1 + 1) * BYTES_PER_XDR_UNIT;
1973                 if (bufsize + tofit > objp->count) {
1974                         objp->reply.eof = FALSE;
1975                         break;
1976                 }
1977                 fileid = (fileid3)(dp->d_ino);
1978                 cookie = (cookie3)(dp->d_off);
1979                 if (!xdr_bool(xdrs, &true) ||
1980                     !xdr_u_longlong_t(xdrs, &fileid) ||
1981                     !xdr_bytes(xdrs, &name, &namlen, ~0) ||
1982                     !xdr_u_longlong_t(xdrs, &cookie)) {
1983                         return (FALSE);
1984                 }
1985                 bufsize += entrysz;
1986         }
1987         if (!xdr_bool(xdrs, &false))
1988                 return (FALSE);
1989         if (!xdr_bool(xdrs, &objp->reply.eof))
1990                 return (FALSE);
1991         return (TRUE);
1992 }
1993 
1994 bool_t
1995 xdr_READDIR3res(XDR *xdrs, READDIR3res *objp)
1996 {
1997         READDIR3resok *resokp;
1998 
1999         /*
2000          * ENCODE or FREE only
2001          */
2002         if (xdrs->x_op == XDR_DECODE)
2003                 return (FALSE);
2004 
2005         if (!xdr_enum(xdrs, (enum_t *)&objp->status))
2006                 return (FALSE);
2007         if (objp->status != NFS3_OK)
2008                 return (xdr_post_op_attr(xdrs, &objp->resfail.dir_attributes));
2009 
2010         /* xdr_READDIR3resok */
2011         resokp = &objp->resok;
2012         if (!xdr_post_op_attr(xdrs, &resokp->dir_attributes))
2013                 return (FALSE);
2014         if (xdrs->x_op != XDR_ENCODE)
2015                 return (TRUE);
2016         /*
2017          * cookieverf is really an opaque 8 byte
2018          * quantity, but we will treat it as a
2019          * hyper for efficiency, the cost of
2020          * a byteswap here saves bcopys elsewhere
2021          */
2022         if (!xdr_u_longlong_t(xdrs, &resokp->cookieverf))
2023                 return (FALSE);
2024         return (xdr_putdirlist(xdrs, resokp));
2025 }
2026 
2027 bool_t
2028 xdr_READDIR3vres(XDR *xdrs, READDIR3vres *objp)
2029 {
2030         dirent64_t *dp;
2031         uint_t entries_size;
2032         int outcount = 0;
2033 
2034         /*
2035          * DECODE or FREE only
2036          */
2037         if (xdrs->x_op == XDR_FREE)
2038                 return (TRUE);
2039 
2040         if (xdrs->x_op != XDR_DECODE)
2041                 return (FALSE);
2042 
2043         if (!xdr_enum(xdrs, (enum_t *)&objp->status))
2044                 return (FALSE);
2045 
2046         if (!xdr_post_op_vattr(xdrs, &objp->dir_attributes))
2047                 return (FALSE);
2048 
2049         if (objp->status != NFS3_OK)
2050                 return (TRUE);
2051 
2052         /*
2053          * cookieverf is really an opaque 8 byte
2054          * quantity, but we will treat it as a
2055          * hyper for efficiency, the cost of
2056          * a byteswap here saves bcopys elsewhere
2057          */
2058         if (!xdr_u_longlong_t(xdrs, &objp->cookieverf))
2059                 return (FALSE);
2060 
2061         entries_size = objp->entries_size;
2062         dp = objp->entries;
2063 
2064         for (;;) {
2065                 uint_t this_reclen;
2066                 bool_t valid;
2067                 uint_t namlen;
2068                 ino64_t fileid;
2069 
2070                 if (!XDR_GETINT32(xdrs, (int32_t *)&valid))
2071                         return (FALSE);
2072                 if (!valid) {
2073                         /*
2074                          * We have run out of entries, decode eof.
2075                          */
2076                         if (!XDR_GETINT32(xdrs, (int32_t *)&objp->eof))
2077                                 return (FALSE);
2078 
2079                         break;
2080                 }
2081 
2082                 /*
2083                  * fileid3 fileid
2084                  */
2085                 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&fileid))
2086                         return (FALSE);
2087 
2088                 /*
2089                  * filename3 name
2090                  */
2091                 if (!XDR_GETINT32(xdrs, (int32_t *)&namlen))
2092                         return (FALSE);
2093                 this_reclen = DIRENT64_RECLEN(namlen);
2094 
2095                 /*
2096                  * If this will overflow buffer, stop decoding
2097                  */
2098                 if ((outcount + this_reclen) > entries_size) {
2099                         objp->eof = FALSE;
2100                         break;
2101                 }
2102                 dp->d_reclen = this_reclen;
2103                 dp->d_ino = fileid;
2104 
2105                 if (!xdr_opaque(xdrs, dp->d_name, namlen))
2106                         return (FALSE);
2107                 bzero(&dp->d_name[namlen],
2108                     DIRENT64_NAMELEN(this_reclen) - namlen);
2109 
2110                 /*
2111                  * cookie3 cookie
2112                  */
2113                 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&dp->d_off))
2114                         return (FALSE);
2115                 objp->loff = dp->d_off;
2116 
2117                 outcount += this_reclen;
2118                 dp = (dirent64_t *)((intptr_t)dp + this_reclen);
2119         }
2120 
2121         objp->size = outcount;
2122         return (TRUE);
2123 }
2124 
2125 bool_t
2126 xdr_READDIRPLUS3args(XDR *xdrs, READDIRPLUS3args *objp)
2127 {
2128         int32_t *ptr;
2129         int32_t *fhp;
2130         uint_t in_size;
2131         int len;
2132 
2133         if (xdrs->x_op == XDR_FREE)
2134                 return (TRUE);
2135 
2136         in_size = RNDUP(sizeof (fhandle_t)) + NFS3_COOKIEVERFSIZE +
2137                 5 * BYTES_PER_XDR_UNIT;
2138 
2139         ptr = XDR_INLINE(xdrs, in_size);
2140         if (ptr != NULL) {
2141                 len = (xdrs->x_op == XDR_DECODE) ? *ptr : objp->dir.fh3_length;
2142 
2143                 if (XDR_CHECKFHSIZE(xdrs, len, in_size)) {
2144 
2145                         fhp = (int32_t *)&(objp->dir.fh3_u.data);
2146 
2147                         if (xdrs->x_op == XDR_DECODE) {
2148                                 objp->dir.fh3_length = IXDR_GET_U_INT32(ptr);
2149                                 *fhp++ = *ptr++;
2150                                 *fhp++ = *ptr++;
2151                                 *fhp++ = *ptr++;
2152                                 *fhp++ = *ptr++;
2153                                 *fhp++ = *ptr++;
2154                                 *fhp++ = *ptr++;
2155                                 *fhp++ = *ptr++;
2156                                 *fhp = *ptr++;
2157                                 IXDR_GET_U_HYPER(ptr, objp->cookie);
2158                                 /*
2159                                  * cookieverf is really an opaque 8 byte
2160                                  * quantity, but we will treat it as a
2161                                  * hyper for efficiency, the cost of
2162                                  * a byteswap here saves bcopys elsewhere
2163                                  */
2164                                 IXDR_GET_U_HYPER(ptr, objp->cookieverf);
2165                                 objp->dircount = IXDR_GET_U_INT32(ptr);
2166                                 objp->maxcount = IXDR_GET_U_INT32(ptr);
2167                         } else {
2168                                 IXDR_PUT_U_INT32(ptr, objp->dir.fh3_length);
2169                                 *ptr++ = *fhp++;
2170                                 *ptr++ = *fhp++;
2171                                 *ptr++ = *fhp++;
2172                                 *ptr++ = *fhp++;
2173                                 *ptr++ = *fhp++;
2174                                 *ptr++ = *fhp++;
2175                                 *ptr++ = *fhp++;
2176                                 *ptr++ = *fhp;
2177                                 IXDR_PUT_U_HYPER(ptr, objp->cookie);
2178                                 /*
2179                                  * cookieverf is really an opaque 8 byte
2180                                  * quantity, but we will treat it as a
2181                                  * hyper for efficiency, the cost of
2182                                  * a byteswap here saves bcopys elsewhere
2183                                  */
2184                                 IXDR_PUT_U_HYPER(ptr, objp->cookieverf);
2185                                 IXDR_PUT_U_INT32(ptr, objp->dircount);
2186                                 IXDR_PUT_U_INT32(ptr, objp->maxcount);
2187                         }
2188                         return (TRUE);
2189                 }
2190         }
2191 
2192         if (!xdr_nfs_fh3(xdrs, &objp->dir))
2193                 return (FALSE);
2194         if (!xdr_u_longlong_t(xdrs, &objp->cookie))
2195                 return (FALSE);
2196         /*
2197          * cookieverf is really an opaque 8 byte
2198          * quantity, but we will treat it as a
2199          * hyper for efficiency, the cost of
2200          * a byteswap here saves bcopys elsewhere
2201          */
2202         if (!xdr_u_longlong_t(xdrs, &objp->cookieverf))
2203                 return (FALSE);
2204         if (!xdr_u_int(xdrs, &objp->dircount))
2205                 return (FALSE);
2206         return (xdr_u_int(xdrs, &objp->maxcount));
2207 
2208 }
2209 
2210 /*
2211  * ENCODE ONLY
2212  */
2213 static bool_t
2214 xdr_putdirpluslist(XDR *xdrs, READDIRPLUS3resok *objp)
2215 {
2216         struct dirent64 *dp;
2217         char *name;
2218         int nents;
2219         bool_t true = TRUE;
2220         bool_t false = FALSE;
2221         fileid3 fileid;
2222         cookie3 cookie;
2223         entryplus3_info *infop;
2224 
2225         if (xdrs->x_op != XDR_ENCODE)
2226                 return (FALSE);
2227 
2228         dp = (struct dirent64 *)objp->reply.entries;
2229         nents = objp->size;
2230         infop = objp->infop;
2231 
2232         while (nents > 0) {
2233                 if (dp->d_reclen == 0)
2234                         return (FALSE);
2235                 if (dp->d_ino != 0) {
2236                         name = dp->d_name;
2237                         fileid = (fileid3)(dp->d_ino);
2238                         cookie = (cookie3)(dp->d_off);
2239                         if (!xdr_bool(xdrs, &true) ||
2240                             !xdr_u_longlong_t(xdrs, &fileid) ||
2241                             !xdr_bytes(xdrs, &name, &infop->namelen, ~0) ||
2242                             !xdr_u_longlong_t(xdrs, &cookie) ||
2243                             !xdr_post_op_attr(xdrs, &infop->attr) ||
2244                             !xdr_post_op_fh3(xdrs, &infop->fh)) {
2245                                 return (FALSE);
2246                         }
2247                 }
2248                 dp = nextdp(dp);
2249                 infop++;
2250                 nents--;
2251         }
2252 
2253         if (!xdr_bool(xdrs, &false))
2254                 return (FALSE);
2255         if (!xdr_bool(xdrs, &objp->reply.eof))
2256                 return (FALSE);
2257         return (TRUE);
2258 }
2259 
2260 bool_t
2261 xdr_READDIRPLUS3res(XDR *xdrs, READDIRPLUS3res *objp)
2262 {
2263         READDIRPLUS3resok *resokp;
2264 
2265         /*
2266          * ENCODE or FREE only
2267          */
2268         if (xdrs->x_op == XDR_DECODE)
2269                 return (FALSE);
2270 
2271         if (!xdr_enum(xdrs, (enum_t *)&objp->status))
2272                 return (FALSE);
2273         switch (objp->status) {
2274         case NFS3_OK:
2275                 /* xdr_READDIRPLUS3resok */
2276                 resokp = &objp->resok;
2277                 if (!xdr_post_op_attr(xdrs, &resokp->dir_attributes))
2278                         return (FALSE);
2279                 /*
2280                  * cookieverf is really an opaque 8 byte
2281                  * quantity, but we will treat it as a
2282                  * hyper for efficiency, the cost of
2283                  * a byteswap here saves bcopys elsewhere
2284                  */
2285                 if (!xdr_u_longlong_t(xdrs, &resokp->cookieverf))
2286                         return (FALSE);
2287                 if (xdrs->x_op == XDR_ENCODE) {
2288                         if (!xdr_putdirpluslist(xdrs, resokp))
2289                                 return (FALSE);
2290                 }
2291                 break;
2292         default:
2293                 return (xdr_post_op_attr(xdrs, &objp->resfail.dir_attributes));
2294         }
2295         return (TRUE);
2296 }
2297 
2298 /*
2299  * Decode readdirplus directly into a dirent64_t and do the DNLC caching.
2300  */
2301 bool_t
2302 xdr_READDIRPLUS3vres(XDR *xdrs, READDIRPLUS3vres *objp)
2303 {
2304         dirent64_t *dp;
2305         vnode_t *dvp;
2306         uint_t entries_size;
2307         int outcount = 0;
2308         vnode_t *nvp;
2309         rnode_t *rp;
2310         post_op_vattr pov;
2311         vattr_t va;
2312 
2313         /*
2314          * DECODE or FREE only
2315          */
2316         if (xdrs->x_op == XDR_FREE)
2317                 return (TRUE);
2318 
2319         if (xdrs->x_op != XDR_DECODE)
2320                 return (FALSE);
2321 
2322         if (!XDR_GETINT32(xdrs, (int32_t *)&objp->status))
2323                 return (FALSE);
2324 
2325         if (!xdr_post_op_vattr(xdrs, &objp->dir_attributes))
2326                 return (FALSE);
2327 
2328         if (objp->status != NFS3_OK)
2329                 return (TRUE);
2330 
2331         /*
2332          * cookieverf is really an opaque 8 byte
2333          * quantity, but we will treat it as a
2334          * hyper for efficiency, the cost of
2335          * a byteswap here saves bcopys elsewhere
2336          */
2337         if (!xdr_u_longlong_t(xdrs, &objp->cookieverf))
2338                 return (FALSE);
2339 
2340         dvp = objp->dir_attributes.fres.vp;
2341         rp = VTOR(dvp);
2342 
2343         pov.fres.vap = &va;
2344         pov.fres.vp = dvp;
2345 
2346         entries_size = objp->entries_size;
2347         dp = objp->entries;
2348 
2349         for (;;) {
2350                 uint_t this_reclen;
2351                 bool_t valid;
2352                 uint_t namlen;
2353                 nfs_fh3 fh;
2354                 int va_valid;
2355                 int fh_valid;
2356                 ino64_t fileid;
2357 
2358                 if (!XDR_GETINT32(xdrs, (int32_t *)&valid))
2359                         return (FALSE);
2360                 if (!valid) {
2361                         /*
2362                          * We have run out of entries, decode eof.
2363                          */
2364                         if (!XDR_GETINT32(xdrs, (int32_t *)&objp->eof))
2365                                 return (FALSE);
2366 
2367                         break;
2368                 }
2369 
2370                 /*
2371                  * fileid3 fileid
2372                  */
2373                 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&fileid))
2374                         return (FALSE);
2375 
2376                 /*
2377                  * filename3 name
2378                  */
2379                 if (!XDR_GETINT32(xdrs, (int32_t *)&namlen))
2380                         return (FALSE);
2381                 this_reclen = DIRENT64_RECLEN(namlen);
2382 
2383                 /*
2384                  * If this will overflow buffer, stop decoding
2385                  */
2386                 if ((outcount + this_reclen) > entries_size) {
2387                         objp->eof = FALSE;
2388                         break;
2389                 }
2390                 dp->d_reclen = this_reclen;
2391                 dp->d_ino = fileid;
2392 
2393                 if (!xdr_opaque(xdrs, dp->d_name, namlen))
2394                         return (FALSE);
2395                 bzero(&dp->d_name[namlen],
2396                     DIRENT64_NAMELEN(this_reclen) - namlen);
2397 
2398                 /*
2399                  * cookie3 cookie
2400                  */
2401                 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&dp->d_off))
2402                         return (FALSE);
2403                 objp->loff = dp->d_off;
2404 
2405                 /*
2406                  * post_op_attr name_attributes
2407                  */
2408                 if (!xdr_post_op_vattr(xdrs, &pov))
2409                         return (FALSE);
2410 
2411                 if (pov.attributes == TRUE &&
2412                                 pov.fres.status == NFS3_OK)
2413                         va_valid = TRUE;
2414                 else
2415                         va_valid = FALSE;
2416 
2417                 /*
2418                  * post_op_fh3 name_handle
2419                  */
2420                 if (!XDR_GETINT32(xdrs, (int32_t *)&fh_valid))
2421                         return (FALSE);
2422 
2423                 /*
2424                  * By definition of the standard fh_valid can be 0 (FALSE) or
2425                  * 1 (TRUE), but we have to account for it being anything else
2426                  * in case some other system didn't follow the standard.  Note
2427                  * that this is why the else checks if the fh_valid variable
2428                  * is != FALSE.
2429                  */
2430                 if (fh_valid == TRUE) {
2431                         if (!xdr_nfs_fh3(xdrs, &fh))
2432                                 return (FALSE);
2433                 } else {
2434                         if (fh_valid != FALSE)
2435                                 return (FALSE);
2436                 }
2437 
2438                 /*
2439                  * If the name is "." or there are no attributes,
2440                  * don't polute the DNLC with "." entries or files
2441                  * we cannot determine the type for.
2442                  */
2443                 if (!(namlen == 1 && dp->d_name[0] == '.') &&
2444                         va_valid && fh_valid) {
2445 
2446                         /*
2447                          * Do the DNLC caching
2448                          */
2449                         nvp = makenfs3node_va(&fh, &va, dvp->v_vfsp,
2450                                 objp->time, objp->credentials,
2451                                 rp->r_path, dp->d_name);
2452                         dnlc_update(dvp, dp->d_name, nvp);
2453                         VN_RELE(nvp);
2454                 }
2455 
2456                 outcount += this_reclen;
2457                 dp = (dirent64_t *)((intptr_t)dp + this_reclen);
2458         }
2459 
2460         objp->size = outcount;
2461         return (TRUE);
2462 }
2463 
2464 bool_t
2465 xdr_FSSTAT3res(XDR *xdrs, FSSTAT3res *objp)
2466 {
2467         FSSTAT3resok *resokp;
2468 
2469         if (!xdr_enum(xdrs, (enum_t *)&objp->status))
2470                 return (FALSE);
2471         if (objp->status != NFS3_OK)
2472                 return (xdr_post_op_attr(xdrs, &objp->resfail.obj_attributes));
2473 
2474         /* xdr_FSSTAT3resok */
2475         resokp = &objp->resok;
2476         if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
2477                 return (FALSE);
2478         if (!xdr_u_longlong_t(xdrs, &resokp->tbytes))
2479                 return (FALSE);
2480         if (!xdr_u_longlong_t(xdrs, &resokp->fbytes))
2481                 return (FALSE);
2482         if (!xdr_u_longlong_t(xdrs, &resokp->abytes))
2483                 return (FALSE);
2484         if (!xdr_u_longlong_t(xdrs, &resokp->tfiles))
2485                 return (FALSE);
2486         if (!xdr_u_longlong_t(xdrs, &resokp->ffiles))
2487                 return (FALSE);
2488         if (!xdr_u_longlong_t(xdrs, &resokp->afiles))
2489                 return (FALSE);
2490         return (xdr_u_int(xdrs, &resokp->invarsec));
2491 }
2492 
2493 bool_t
2494 xdr_FSINFO3res(XDR *xdrs, FSINFO3res *objp)
2495 {
2496         FSINFO3resok *resokp;
2497 
2498         if (!xdr_enum(xdrs, (enum_t *)&objp->status))
2499                 return (FALSE);
2500         if (objp->status != NFS3_OK) /* xdr_FSSTAT3resfail */
2501                 return (xdr_post_op_attr(xdrs, &objp->resfail.obj_attributes));
2502 
2503         /* xdr_FSINFO3resok */
2504         resokp = &objp->resok;
2505         if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
2506                 return (FALSE);
2507         if (!xdr_u_int(xdrs, &resokp->rtmax))
2508                 return (FALSE);
2509         if (!xdr_u_int(xdrs, &resokp->rtpref))
2510                 return (FALSE);
2511         if (!xdr_u_int(xdrs, &resokp->rtmult))
2512                 return (FALSE);
2513         if (!xdr_u_int(xdrs, &resokp->wtmax))
2514                 return (FALSE);
2515         if (!xdr_u_int(xdrs, &resokp->wtpref))
2516                 return (FALSE);
2517         if (!xdr_u_int(xdrs, &resokp->wtmult))
2518                 return (FALSE);
2519         if (!xdr_u_int(xdrs, &resokp->dtpref))
2520                 return (FALSE);
2521         if (!xdr_u_longlong_t(xdrs, &resokp->maxfilesize))
2522                 return (FALSE);
2523         if (!xdr_u_int(xdrs, &resokp->time_delta.seconds))
2524                 return (FALSE);
2525         if (!xdr_u_int(xdrs, &resokp->time_delta.nseconds))
2526                 return (FALSE);
2527         return (xdr_u_int(xdrs, &resokp->properties));
2528 }
2529 
2530 bool_t
2531 xdr_PATHCONF3res(XDR *xdrs, PATHCONF3res *objp)
2532 {
2533         PATHCONF3resok *resokp;
2534 
2535         if (!xdr_enum(xdrs, (enum_t *)&objp->status))
2536                 return (FALSE);
2537         if (objp->status != NFS3_OK)
2538                 return (xdr_post_op_attr(xdrs, &objp->resfail.obj_attributes));
2539 
2540         /* xdr_PATHCONF3resok */
2541         resokp = &objp->resok;
2542         if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
2543                 return (FALSE);
2544         if (!xdr_u_int(xdrs, &resokp->info.link_max))
2545                 return (FALSE);
2546         if (!xdr_u_int(xdrs, &resokp->info.name_max))
2547                 return (FALSE);
2548         if (!xdr_bool(xdrs, &resokp->info.no_trunc))
2549                 return (FALSE);
2550         if (!xdr_bool(xdrs, &resokp->info.chown_restricted))
2551                 return (FALSE);
2552         if (!xdr_bool(xdrs, &resokp->info.case_insensitive))
2553                 return (FALSE);
2554         return (xdr_bool(xdrs, &resokp->info.case_preserving));
2555 }
2556 
2557 bool_t
2558 xdr_COMMIT3args(XDR *xdrs, COMMIT3args *objp)
2559 {
2560         int32_t *ptr;
2561         int32_t *fhp;
2562         int len;
2563         uint_t in_size;
2564 
2565         if (xdrs->x_op == XDR_FREE)
2566                 return (TRUE);
2567 
2568         in_size = RNDUP(sizeof (fhandle_t)) +   4 * BYTES_PER_XDR_UNIT;
2569         ptr = XDR_INLINE(xdrs, in_size);
2570 
2571         if (ptr != NULL) {
2572                 len = (xdrs->x_op == XDR_DECODE) ? *ptr : objp->file.fh3_length;
2573 
2574                 if (XDR_CHECKFHSIZE(xdrs, len, in_size)) {
2575                         fhp = (int32_t *)&(objp->file.fh3_u.data);
2576                         if (xdrs->x_op == XDR_DECODE) {
2577                                 objp->file.fh3_length = IXDR_GET_U_INT32(ptr);
2578                                 *fhp++ = *ptr++;
2579                                 *fhp++ = *ptr++;
2580                                 *fhp++ = *ptr++;
2581                                 *fhp++ = *ptr++;
2582                                 *fhp++ = *ptr++;
2583                                 *fhp++ = *ptr++;
2584                                 *fhp++ = *ptr++;
2585                                 *fhp = *ptr++;
2586                                 IXDR_GET_U_HYPER(ptr, objp->offset);
2587                                 objp->count = IXDR_GET_U_INT32(ptr);
2588                         } else {
2589                                 IXDR_PUT_U_INT32(ptr, objp->file.fh3_length);
2590                                 *ptr++ = *fhp++;
2591                                 *ptr++ = *fhp++;
2592                                 *ptr++ = *fhp++;
2593                                 *ptr++ = *fhp++;
2594                                 *ptr++ = *fhp++;
2595                                 *ptr++ = *fhp++;
2596                                 *ptr++ = *fhp++;
2597                                 *ptr++ = *fhp;
2598                                 IXDR_PUT_U_HYPER(ptr, objp->offset);
2599                                 IXDR_PUT_U_INT32(ptr, objp->count);
2600                         }
2601                         return (TRUE);
2602                 }
2603         }
2604 
2605         if (!xdr_nfs_fh3(xdrs, &objp->file))
2606                 return (FALSE);
2607         if (!xdr_u_longlong_t(xdrs, &objp->offset))
2608                 return (FALSE);
2609         return (xdr_u_int(xdrs, &objp->count));
2610 }
2611 
2612 bool_t
2613 xdr_COMMIT3res(XDR *xdrs, COMMIT3res *objp)
2614 {
2615         COMMIT3resok *resokp;
2616 
2617         if (!xdr_enum(xdrs, (enum_t *)&objp->status))
2618                 return (FALSE);
2619         if (objp->status != NFS3_OK)
2620                 return (xdr_wcc_data(xdrs, &objp->resfail.file_wcc));
2621 
2622         /* xdr_COMMIT3resok */
2623         resokp = &objp->resok;
2624         if (!xdr_wcc_data(xdrs, &resokp->file_wcc))
2625                 return (FALSE);
2626         /*
2627          * writeverf3 is really an opaque 8 byte
2628          * quantity, but we will treat it as a
2629          * hyper for efficiency, the cost of
2630          * a byteswap here saves bcopys elsewhere
2631          */
2632         return (xdr_u_longlong_t(xdrs, &resokp->verf));
2633 }
--- EOF ---