1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 /*
  27  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  28  * Use is subject to license terms.
  29  */
  30 /*
  31  * Copyright (c) 2013 by Delphix. All rights reserved.
  32  */
  33 
  34 /*
  35  * A handcoded version based on the original rpcgen code.
  36  *
  37  * Note: All future NFS4 protocol changes should be added by hand
  38  * to this file.
  39  *
  40  * CAUTION: All protocol changes must also be propagated to:
  41  *     usr/src/cmd/cmd-inet/usr.sbin/snoop/nfs4_xdr.c
  42  */
  43 
  44 #include <sys/types.h>
  45 #include <sys/sunddi.h>
  46 #include <sys/dnlc.h>
  47 #include <nfs/nfs.h>
  48 #include <nfs/nfs4_kprot.h>
  49 #include <nfs/rnode4.h>
  50 #include <nfs/nfs4.h>
  51 #include <nfs/nfs4_clnt.h>
  52 #include <sys/sdt.h>
  53 #include <sys/mkdev.h>
  54 #include <rpc/rpc_rdma.h>
  55 #include <rpc/xdr.h>
  56 
  57 #define xdr_dev_t xdr_u_int
  58 
  59 extern bool_t xdr_netbuf(XDR *, struct netbuf *);
  60 extern bool_t xdr_vector(XDR *, char *, const uint_t, const uint_t,
  61         const xdrproc_t);
  62 bool_t xdr_knetconfig(XDR *, struct knetconfig *);
  63 
  64 bool_t
  65 xdr_bitmap4(XDR *xdrs, bitmap4 *objp)
  66 {
  67         int32_t len, size;
  68 
  69         if (xdrs->x_op == XDR_FREE)
  70                 return (TRUE);
  71 
  72         /*
  73          * Simplified bitmap4 processing, always encode from uint64_t
  74          * to 2 uint32_t's, always decode first 2 uint32_t's into a
  75          * uint64_t and ignore all of the rest.
  76          */
  77         if (xdrs->x_op == XDR_ENCODE) {
  78                 len = 2;
  79 
  80                 if (!XDR_PUTINT32(xdrs, &len))
  81                         return (FALSE);
  82 
  83 #if defined(_LITTLE_ENDIAN)
  84                 if (XDR_PUTINT32(xdrs, (int32_t *)((char *)objp +
  85                     BYTES_PER_XDR_UNIT)) == TRUE) {
  86                         return (XDR_PUTINT32(xdrs, (int32_t *)objp));
  87                 }
  88 #elif defined(_BIG_ENDIAN)
  89                 if (XDR_PUTINT32(xdrs, (int32_t *)objp) == TRUE) {
  90                         return (XDR_PUTINT32(xdrs, (int32_t *)((char *)objp +
  91                             BYTES_PER_XDR_UNIT)));
  92                 }
  93 #endif
  94                 return (FALSE);
  95         }
  96 
  97         if (!XDR_GETINT32(xdrs, &len))
  98                 return (FALSE);
  99 
 100         /*
 101          * Common fast DECODE cases
 102          */
 103         if (len == 2) {
 104 #if defined(_LITTLE_ENDIAN)
 105                 if (XDR_GETINT32(xdrs, (int32_t *)((char *)objp +
 106                     BYTES_PER_XDR_UNIT)) == TRUE) {
 107                         return (XDR_GETINT32(xdrs, (int32_t *)objp));
 108                 }
 109 #elif defined(_BIG_ENDIAN)
 110                 if (XDR_GETINT32(xdrs, (int32_t *)objp) == TRUE) {
 111                         return (XDR_GETINT32(xdrs, (int32_t *)((char *)objp +
 112                             BYTES_PER_XDR_UNIT)));
 113                 }
 114 #endif
 115                 return (FALSE);
 116         }
 117 
 118         *objp = 0;
 119         if (len == 0)
 120                 return (TRUE);
 121 
 122         /*
 123          * The not so common DECODE cases, len == 1 || len > 2
 124          */
 125 #if defined(_LITTLE_ENDIAN)
 126         if (!XDR_GETINT32(xdrs, (int32_t *)((char *)objp + BYTES_PER_XDR_UNIT)))
 127                 return (FALSE);
 128         if (--len == 0)
 129                 return (TRUE);
 130         if (!XDR_GETINT32(xdrs, (int32_t *)objp))
 131                 return (FALSE);
 132 #elif defined(_BIG_ENDIAN)
 133         if (!XDR_GETINT32(xdrs, (int32_t *)objp))
 134                 return (FALSE);
 135         if (--len == 0)
 136                 return (TRUE);
 137         if (!XDR_GETINT32(xdrs, (int32_t *)((char *)objp + BYTES_PER_XDR_UNIT)))
 138                 return (FALSE);
 139 #else
 140         return (FALSE);
 141 #endif
 142 
 143         if (--len == 0)
 144                 return (TRUE);
 145 
 146         size = len * BYTES_PER_XDR_UNIT;
 147         return (XDR_CONTROL(xdrs, XDR_SKIPBYTES, &size));
 148 }
 149 
 150 /* Called by xdr_array, nfsid_map_xdr */
 151 bool_t
 152 xdr_utf8string(XDR *xdrs, utf8string *objp)
 153 {
 154         if (xdrs->x_op != XDR_FREE)
 155                 return (xdr_bytes(xdrs, (char **)&objp->utf8string_val,
 156                     (uint_t *)&objp->utf8string_len, NFS4_MAX_UTF8STRING));
 157 
 158         if (objp->utf8string_val != NULL) {
 159                 kmem_free(objp->utf8string_val, objp->utf8string_len);
 160                 objp->utf8string_val = NULL;
 161         }
 162         return (TRUE);
 163 }
 164 
 165 /*
 166  * used by NFSv4 referrals to get info needed for NFSv4 referral mount.
 167  */
 168 bool_t
 169 xdr_nfs_fsl_info(XDR *xdrs, struct nfs_fsl_info *objp)
 170 {
 171 
 172         if (!xdr_u_int(xdrs, &objp->netbuf_len))
 173                 return (FALSE);
 174         if (!xdr_u_int(xdrs, &objp->netnm_len))
 175                 return (FALSE);
 176         if (!xdr_u_int(xdrs, &objp->knconf_len))
 177                 return (FALSE);
 178 
 179 #if defined(_LP64)
 180         /*
 181          * The object can come from a 32-bit binary; nfsmapid.
 182          * To be safe we double the size of the knetconfig to
 183          * allow some buffering for decoding.
 184          */
 185         if (xdrs->x_op == XDR_DECODE)
 186                 objp->knconf_len += sizeof (struct knetconfig);
 187 #endif
 188 
 189         if (!xdr_string(xdrs, &objp->netname, ~0))
 190                 return (FALSE);
 191         if (!xdr_pointer(xdrs, (char **)&objp->addr, objp->netbuf_len,
 192             (xdrproc_t)xdr_netbuf))
 193                 return (FALSE);
 194         if (!xdr_pointer(xdrs, (char **)&objp->knconf,
 195             objp->knconf_len, (xdrproc_t)xdr_knetconfig))
 196                 return (FALSE);
 197         return (TRUE);
 198 }
 199 
 200 bool_t
 201 xdr_knetconfig(XDR *xdrs, struct knetconfig *objp)
 202 {
 203         rpc_inline_t *buf;
 204         u_longlong_t dev64;
 205 #if !defined(_LP64)
 206         uint32_t major, minor;
 207 #endif
 208         int i;
 209 
 210         if (!xdr_u_int(xdrs, &objp->knc_semantics))
 211                 return (FALSE);
 212         if (xdrs->x_op == XDR_DECODE) {
 213                 objp->knc_protofmly = (((char *)objp) +
 214                     sizeof (struct knetconfig));
 215                 objp->knc_proto = objp->knc_protofmly + KNC_STRSIZE;
 216         }
 217         if (!xdr_opaque(xdrs, objp->knc_protofmly, KNC_STRSIZE))
 218                 return (FALSE);
 219         if (!xdr_opaque(xdrs, objp->knc_proto, KNC_STRSIZE))
 220                 return (FALSE);
 221 
 222         /*
 223          * For interoperability between 32-bit daemon and 64-bit kernel,
 224          * we always treat dev_t as 64-bit number and do the expanding
 225          * or compression of dev_t as needed.
 226          * We have to hand craft the conversion since there is no available
 227          * function in ddi.c. Besides ddi.c is available only in the kernel
 228          * and we want to keep both user and kernel of xdr_knetconfig() the
 229          * same for consistency.
 230          */
 231         if (xdrs->x_op == XDR_ENCODE) {
 232 #if defined(_LP64)
 233                 dev64 = objp->knc_rdev;
 234 #else
 235                 major = (objp->knc_rdev >> NBITSMINOR32) & MAXMAJ32;
 236                 minor = objp->knc_rdev & MAXMIN32;
 237                 dev64 = (((unsigned long long)major) << NBITSMINOR64) | minor;
 238 #endif
 239                 if (!xdr_u_longlong_t(xdrs, &dev64))
 240                         return (FALSE);
 241         }
 242         if (xdrs->x_op == XDR_DECODE) {
 243 #if defined(_LP64)
 244                 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->knc_rdev))
 245                         return (FALSE);
 246 #else
 247                 if (!xdr_u_longlong_t(xdrs, &dev64))
 248                         return (FALSE);
 249 
 250                 major = (dev64 >> NBITSMINOR64) & L_MAXMAJ32;
 251                 minor = dev64 & L_MAXMIN32;
 252                 objp->knc_rdev = (major << L_BITSMINOR32) | minor;
 253 #endif
 254         }
 255 
 256         if (xdrs->x_op == XDR_ENCODE) {
 257                 buf = XDR_INLINE(xdrs, (8) * BYTES_PER_XDR_UNIT);
 258                 if (buf == NULL) {
 259                         if (!xdr_vector(xdrs, (char *)objp->knc_unused, 8,
 260                             sizeof (uint_t), (xdrproc_t)xdr_u_int))
 261                                 return (FALSE);
 262                 } else {
 263                         uint_t *genp;
 264 
 265                         for (i = 0, genp = objp->knc_unused;
 266                             i < 8; i++) {
 267 #if defined(_LP64) || defined(_KERNEL)
 268                                 IXDR_PUT_U_INT32(buf, *genp++);
 269 #else
 270                                 IXDR_PUT_U_LONG(buf, *genp++);
 271 #endif
 272                         }
 273                 }
 274                 return (TRUE);
 275         } else if (xdrs->x_op == XDR_DECODE) {
 276                 buf = XDR_INLINE(xdrs, (8) * BYTES_PER_XDR_UNIT);
 277                 if (buf == NULL) {
 278                         if (!xdr_vector(xdrs, (char *)objp->knc_unused, 8,
 279                             sizeof (uint_t), (xdrproc_t)xdr_u_int))
 280                                 return (FALSE);
 281                 } else {
 282                         uint_t *genp;
 283 
 284                         for (i = 0, genp = objp->knc_unused;
 285                             i < 8; i++) {
 286 #if defined(_LP64) || defined(_KERNEL)
 287                                         *genp++ = IXDR_GET_U_INT32(buf);
 288 #else
 289                                         *genp++ = IXDR_GET_U_LONG(buf);
 290 #endif
 291                         }
 292                 }
 293                 return (TRUE);
 294         }
 295 
 296         if (!xdr_vector(xdrs, (char *)objp->knc_unused, 8,
 297             sizeof (uint_t), (xdrproc_t)xdr_u_int))
 298                 return (FALSE);
 299         return (TRUE);
 300 }
 301 
 302 /*
 303  * XDR_INLINE decode a filehandle.
 304  */
 305 bool_t
 306 xdr_inline_decode_nfs_fh4(uint32_t *ptr, nfs_fh4_fmt_t *fhp, uint32_t fhsize)
 307 {
 308         uchar_t *bp = (uchar_t *)ptr;
 309         uchar_t *cp;
 310         uint32_t dsize;
 311         uintptr_t resid;
 312 
 313         /*
 314          * Check to see if what the client sent us is bigger or smaller
 315          * than what we can ever possibly send out. NFS_FHMAXDATA is
 316          * unfortunately badly named as it is no longer the max and is
 317          * really the min of what is sent over the wire.
 318          */
 319         if (fhsize > sizeof (nfs_fh4_fmt_t) || fhsize < (sizeof (fsid_t) +
 320             sizeof (ushort_t) + NFS_FHMAXDATA +
 321             sizeof (ushort_t) + NFS_FHMAXDATA)) {
 322                 return (FALSE);
 323         }
 324 
 325         /*
 326          * All internal parts of a filehandle are in native byte order.
 327          *
 328          * Decode what should be fh4_fsid, it is aligned.
 329          */
 330         fhp->fh4_fsid.val[0] = *(uint32_t *)bp;
 331         bp += BYTES_PER_XDR_UNIT;
 332         fhp->fh4_fsid.val[1] = *(uint32_t *)bp;
 333         bp += BYTES_PER_XDR_UNIT;
 334 
 335         /*
 336          * Decode what should be fh4_len.  fh4_len is two bytes, so we're
 337          * unaligned now.
 338          */
 339         cp = (uchar_t *)&fhp->fh4_len;
 340         *cp++ = *bp++;
 341         *cp++ = *bp++;
 342         fhsize -= 2 * BYTES_PER_XDR_UNIT + sizeof (ushort_t);
 343 
 344         /*
 345          * For backwards compatibility, the fid length may be less than
 346          * NFS_FHMAXDATA, but it was always encoded as NFS_FHMAXDATA bytes.
 347          */
 348         dsize = fhp->fh4_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_len;
 349 
 350         /*
 351          * Make sure the client isn't sending us a bogus length for fh4_data.
 352          */
 353         if (fhsize < dsize)
 354                 return (FALSE);
 355         bcopy(bp, fhp->fh4_data, dsize);
 356         bp += dsize;
 357         fhsize -= dsize;
 358 
 359         if (fhsize < sizeof (ushort_t))
 360                 return (FALSE);
 361         cp = (uchar_t *)&fhp->fh4_xlen;
 362         *cp++ = *bp++;
 363         *cp++ = *bp++;
 364         fhsize -= sizeof (ushort_t);
 365 
 366         dsize = fhp->fh4_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_xlen;
 367 
 368         /*
 369          * Make sure the client isn't sending us a bogus length for fh4_xdata.
 370          */
 371         if (fhsize < dsize)
 372                 return (FALSE);
 373         bcopy(bp, fhp->fh4_xdata, dsize);
 374         fhsize -= dsize;
 375         bp += dsize;
 376 
 377         /*
 378          * We realign things on purpose, so skip any padding
 379          */
 380         resid = (uintptr_t)bp % BYTES_PER_XDR_UNIT;
 381         if (resid != 0) {
 382                 if (fhsize < (BYTES_PER_XDR_UNIT - resid))
 383                         return (FALSE);
 384                 bp += BYTES_PER_XDR_UNIT - resid;
 385                 fhsize -= BYTES_PER_XDR_UNIT - resid;
 386         }
 387 
 388         if (fhsize < BYTES_PER_XDR_UNIT)
 389                 return (FALSE);
 390         fhp->fh4_flag = *(uint32_t *)bp;
 391         bp += BYTES_PER_XDR_UNIT;
 392         fhsize -= BYTES_PER_XDR_UNIT;
 393 
 394 #ifdef VOLATILE_FH_TEST
 395         if (fhsize < BYTES_PER_XDR_UNIT)
 396                 return (FALSE);
 397         fhp->fh4_volatile_id = *(uint32_t *)bp;
 398         bp += BYTES_PER_XDR_UNIT;
 399         fhsize -= BYTES_PER_XDR_UNIT;
 400 #endif
 401         /*
 402          * Make sure client didn't send extra bytes
 403          */
 404         if (fhsize != 0)
 405                 return (FALSE);
 406         return (TRUE);
 407 }
 408 
 409 static bool_t
 410 xdr_decode_nfs_fh4(XDR *xdrs, nfs_fh4 *objp)
 411 {
 412         uint32_t fhsize;                /* filehandle size */
 413         uint32_t bufsize;
 414         rpc_inline_t *ptr;
 415         uchar_t *bp;
 416 
 417         ASSERT(xdrs->x_op == XDR_DECODE);
 418 
 419         /*
 420          * Retrieve the filehandle length.
 421          */
 422         if (!XDR_GETINT32(xdrs, (int32_t *)&fhsize))
 423                 return (FALSE);
 424 
 425         objp->nfs_fh4_val = NULL;
 426         objp->nfs_fh4_len = 0;
 427 
 428         /*
 429          * Check to see if what the client sent us is bigger or smaller
 430          * than what we can ever possibly send out. NFS_FHMAXDATA is
 431          * unfortunately badly named as it is no longer the max and is
 432          * really the min of what is sent over the wire.
 433          */
 434         if (fhsize > sizeof (nfs_fh4_fmt_t) || fhsize < (sizeof (fsid_t) +
 435             sizeof (ushort_t) + NFS_FHMAXDATA +
 436             sizeof (ushort_t) + NFS_FHMAXDATA)) {
 437                 if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &fhsize))
 438                         return (FALSE);
 439                 return (TRUE);
 440         }
 441 
 442         /*
 443          * bring in fhsize plus any padding
 444          */
 445         bufsize = RNDUP(fhsize);
 446         ptr = XDR_INLINE(xdrs, bufsize);
 447         bp = (uchar_t *)ptr;
 448         if (ptr == NULL) {
 449                 bp = kmem_alloc(bufsize, KM_SLEEP);
 450                 if (!xdr_opaque(xdrs, (char *)bp, bufsize)) {
 451                         kmem_free(bp, bufsize);
 452                         return (FALSE);
 453                 }
 454         }
 455 
 456         objp->nfs_fh4_val = kmem_zalloc(sizeof (nfs_fh4_fmt_t), KM_SLEEP);
 457         objp->nfs_fh4_len = sizeof (nfs_fh4_fmt_t);
 458 
 459         if (xdr_inline_decode_nfs_fh4((uint32_t *)bp,
 460             (nfs_fh4_fmt_t *)objp->nfs_fh4_val, fhsize) == FALSE) {
 461                 /*
 462                  * If in the process of decoding we find the file handle
 463                  * is not correctly formed, we need to continue decoding
 464                  * and trigger an NFS layer error. Set the nfs_fh4_len to
 465                  * zero so it gets caught as a bad length.
 466                  */
 467                 kmem_free(objp->nfs_fh4_val, objp->nfs_fh4_len);
 468                 objp->nfs_fh4_val = NULL;
 469                 objp->nfs_fh4_len = 0;
 470         }
 471 
 472         if (ptr == NULL)
 473                 kmem_free(bp, bufsize);
 474         return (TRUE);
 475 }
 476 
 477 /*
 478  * XDR_INLINE encode a filehandle.
 479  */
 480 bool_t
 481 xdr_inline_encode_nfs_fh4(uint32_t **ptrp, uint32_t *ptr_redzone,
 482     nfs_fh4_fmt_t *fhp)
 483 {
 484         uint32_t *ptr = *ptrp;
 485         uchar_t *cp;
 486         uint_t otw_len, fsize, xsize;   /* otw, file, and export sizes */
 487         uint32_t padword;
 488 
 489         fsize = fhp->fh4_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_len;
 490         xsize = fhp->fh4_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_xlen;
 491 
 492         /*
 493          * First get the initial and variable sized part of the filehandle.
 494          */
 495         otw_len = sizeof (fhp->fh4_fsid) +
 496             sizeof (fhp->fh4_len) + fsize +
 497             sizeof (fhp->fh4_xlen) + xsize;
 498 
 499         /*
 500          * Round out to a full word.
 501          */
 502         otw_len = RNDUP(otw_len);
 503         padword = (otw_len / BYTES_PER_XDR_UNIT);       /* includes fhlen */
 504 
 505         /*
 506          * Add in the fixed sized pieces.
 507          */
 508         otw_len += sizeof (fhp->fh4_flag);
 509 #ifdef VOLATILE_FH_TEST
 510         otw_len += sizeof (fhp->fh4_volatile_id);
 511 #endif
 512 
 513         /*
 514          * Make sure we don't exceed our buffer.
 515          */
 516         if ((ptr + (otw_len / BYTES_PER_XDR_UNIT) + 1) > ptr_redzone)
 517                 return (FALSE);
 518 
 519         /*
 520          * Zero out the padding.
 521          */
 522         ptr[padword] = 0;
 523 
 524         IXDR_PUT_U_INT32(ptr, otw_len);
 525 
 526         /*
 527          * The rest of the filehandle is in native byteorder
 528          */
 529         /* fh4_fsid */
 530         *ptr++ = (uint32_t)fhp->fh4_fsid.val[0];
 531         *ptr++ = (uint32_t)fhp->fh4_fsid.val[1];
 532 
 533         /*
 534          * Since the next pieces are unaligned, we need to
 535          * do bytewise copies.
 536          */
 537         cp = (uchar_t *)ptr;
 538 
 539         /* fh4_len + fh4_data */
 540         bcopy(&fhp->fh4_len, cp, sizeof (fhp->fh4_len) + fsize);
 541         cp += sizeof (fhp->fh4_len) + fsize;
 542 
 543         /* fh4_xlen + fh4_xdata */
 544         bcopy(&fhp->fh4_xlen, cp, sizeof (fhp->fh4_xlen) + xsize);
 545         cp += sizeof (fhp->fh4_xlen) + xsize;
 546 
 547         /* do necessary rounding/padding */
 548         cp = (uchar_t *)RNDUP((uintptr_t)cp);
 549         ptr = (uint32_t *)cp;
 550 
 551         /*
 552          * With the above padding, we're word aligned again.
 553          */
 554         ASSERT(((uintptr_t)ptr % BYTES_PER_XDR_UNIT) == 0);
 555 
 556         /* fh4_flag */
 557         *ptr++ = (uint32_t)fhp->fh4_flag;
 558 
 559 #ifdef VOLATILE_FH_TEST
 560         /* fh4_volatile_id */
 561         *ptr++ = (uint32_t)fhp->fh4_volatile_id;
 562 #endif
 563         *ptrp = ptr;
 564 
 565         return (TRUE);
 566 }
 567 
 568 static bool_t
 569 xdr_encode_nfs_fh4(XDR *xdrs, nfs_fh4 *objp)
 570 {
 571         uint_t otw_len, fsize, xsize;   /* otw, file, and export sizes */
 572         bool_t ret;
 573         rpc_inline_t *ptr;
 574         rpc_inline_t *buf = NULL;
 575         uint32_t *ptr_redzone;
 576         nfs_fh4_fmt_t *fhp;
 577 
 578         ASSERT(xdrs->x_op == XDR_ENCODE);
 579 
 580         fhp = (nfs_fh4_fmt_t *)objp->nfs_fh4_val;
 581         fsize = fhp->fh4_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_len;
 582         xsize = fhp->fh4_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_xlen;
 583 
 584         /*
 585          * First get the over the wire size, it is the 4 bytes
 586          * for the length, plus the combined size of the
 587          * file handle components.
 588          */
 589         otw_len = BYTES_PER_XDR_UNIT + sizeof (fhp->fh4_fsid) +
 590             sizeof (fhp->fh4_len) + fsize +
 591             sizeof (fhp->fh4_xlen) + xsize +
 592             sizeof (fhp->fh4_flag);
 593 #ifdef VOLATILE_FH_TEST
 594         otw_len += sizeof (fhp->fh4_volatile_id);
 595 #endif
 596         /*
 597          * Round out to a full word.
 598          */
 599         otw_len = RNDUP(otw_len);
 600 
 601         /*
 602          * Next try to inline the XDR stream, if that fails (rare)
 603          * allocate a buffer to encode the file handle and then
 604          * copy it using xdr_opaque and free the buffer.
 605          */
 606         ptr = XDR_INLINE(xdrs, otw_len);
 607         if (ptr == NULL)
 608                 ptr = buf = kmem_alloc(otw_len, KM_SLEEP);
 609 
 610         ptr_redzone = (uint32_t *)(ptr + (otw_len / BYTES_PER_XDR_UNIT));
 611         ret = xdr_inline_encode_nfs_fh4((uint32_t **)&ptr, ptr_redzone, fhp);
 612 
 613         if (buf != NULL) {
 614                 if (ret == TRUE)
 615                         ret = xdr_opaque(xdrs, (char *)buf, otw_len);
 616                 kmem_free(buf, otw_len);
 617         }
 618         return (ret);
 619 }
 620 
 621 /*
 622  * XDR a NFSv4 filehandle.
 623  * Encoding interprets the contents (server).
 624  * Decoding the contents are opaque (client).
 625  */
 626 bool_t
 627 xdr_nfs_fh4(XDR *xdrs, nfs_fh4 *objp)
 628 {
 629         switch (xdrs->x_op) {
 630         case XDR_ENCODE:
 631                 return (xdr_encode_nfs_fh4(xdrs, objp));
 632         case XDR_DECODE:
 633                 return (xdr_bytes(xdrs, (char **)&objp->nfs_fh4_val,
 634                     (uint_t *)&objp->nfs_fh4_len, NFS4_FHSIZE));
 635         case XDR_FREE:
 636                 if (objp->nfs_fh4_val != NULL) {
 637                         kmem_free(objp->nfs_fh4_val, objp->nfs_fh4_len);
 638                         objp->nfs_fh4_val = NULL;
 639                 }
 640                 return (TRUE);
 641         }
 642         return (FALSE);
 643 }
 644 
 645 /* Called by xdr_array */
 646 static bool_t
 647 xdr_fs_location4(XDR *xdrs, fs_location4 *objp)
 648 {
 649         if (xdrs->x_op == XDR_DECODE) {
 650                 objp->server_val = NULL;
 651                 objp->rootpath.pathname4_val = NULL;
 652         }
 653         if (!xdr_array(xdrs, (char **)&objp->server_val,
 654             (uint_t *)&objp->server_len, NFS4_MAX_UTF8STRING,
 655             sizeof (utf8string), (xdrproc_t)xdr_utf8string))
 656                 return (FALSE);
 657         return (xdr_array(xdrs, (char **)&objp->rootpath.pathname4_val,
 658             (uint_t *)&objp->rootpath.pathname4_len,
 659             NFS4_MAX_PATHNAME4,
 660             sizeof (utf8string), (xdrproc_t)xdr_utf8string));
 661 }
 662 
 663 /* Called by xdr_array */
 664 static bool_t
 665 xdr_nfsace4(XDR *xdrs, nfsace4 *objp)
 666 {
 667         if (xdrs->x_op != XDR_FREE) {
 668                 if (!xdr_u_int(xdrs, &objp->type))
 669                         return (FALSE);
 670                 if (!xdr_u_int(xdrs, &objp->flag))
 671                         return (FALSE);
 672                 if (!xdr_u_int(xdrs, &objp->access_mask))
 673                         return (FALSE);
 674 
 675                 if (xdrs->x_op == XDR_DECODE) {
 676                         objp->who.utf8string_val = NULL;
 677                         objp->who.utf8string_len = 0;
 678                 }
 679 
 680                 return (xdr_bytes(xdrs, (char **)&objp->who.utf8string_val,
 681                     (uint_t *)&objp->who.utf8string_len,
 682                     NFS4_MAX_UTF8STRING));
 683         }
 684 
 685         /*
 686          * Optimized free case
 687          */
 688         if (objp->who.utf8string_val != NULL) {
 689                 kmem_free(objp->who.utf8string_val, objp->who.utf8string_len);
 690                 objp->who.utf8string_val = NULL;
 691         }
 692         return (TRUE);
 693 }
 694 
 695 /*
 696  * These functions are called out of nfs4_attr.c
 697  */
 698 bool_t
 699 xdr_fattr4_fsid(XDR *xdrs, fattr4_fsid *objp)
 700 {
 701         if (xdrs->x_op == XDR_FREE)
 702                 return (TRUE);
 703 
 704         if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->major))
 705                 return (FALSE);
 706         return (xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->minor));
 707 }
 708 
 709 
 710 bool_t
 711 xdr_fattr4_acl(XDR *xdrs, fattr4_acl *objp)
 712 {
 713         return (xdr_array(xdrs, (char **)&objp->fattr4_acl_val,
 714             (uint_t *)&objp->fattr4_acl_len, NFS4_ACL_LIMIT,
 715             sizeof (nfsace4), (xdrproc_t)xdr_nfsace4));
 716 }
 717 
 718 bool_t
 719 xdr_fattr4_fs_locations(XDR *xdrs, fattr4_fs_locations *objp)
 720 {
 721         if (xdrs->x_op == XDR_DECODE) {
 722                 objp->fs_root.pathname4_len = 0;
 723                 objp->fs_root.pathname4_val = NULL;
 724                 objp->locations_val = NULL;
 725         }
 726         if (!xdr_array(xdrs, (char **)&objp->fs_root.pathname4_val,
 727             (uint_t *)&objp->fs_root.pathname4_len,
 728             NFS4_MAX_PATHNAME4,
 729             sizeof (utf8string), (xdrproc_t)xdr_utf8string))
 730                 return (FALSE);
 731         return (xdr_array(xdrs, (char **)&objp->locations_val,
 732             (uint_t *)&objp->locations_len, NFS4_FS_LOCATIONS_LIMIT,
 733             sizeof (fs_location4), (xdrproc_t)xdr_fs_location4));
 734 }
 735 
 736 bool_t
 737 xdr_fattr4_rawdev(XDR *xdrs, fattr4_rawdev *objp)
 738 {
 739         if (xdrs->x_op == XDR_FREE)
 740                 return (TRUE);
 741 
 742         if (!xdr_u_int(xdrs, &objp->specdata1))
 743                 return (FALSE);
 744         return (xdr_u_int(xdrs, &objp->specdata2));
 745 }
 746 
 747 bool_t
 748 xdr_nfstime4(XDR *xdrs, nfstime4 *objp)
 749 {
 750         if (xdrs->x_op == XDR_FREE)
 751                 return (TRUE);
 752 
 753         if (!xdr_longlong_t(xdrs, (longlong_t *)&objp->seconds))
 754                 return (FALSE);
 755         return (xdr_u_int(xdrs, &objp->nseconds));
 756 }
 757 
 758 
 759 /*
 760  * structured used for calls into xdr_ga_fattr_res() as a means
 761  * to do an immediate/short-term cache of owner/group strings
 762  * for callers like the readdir processing.  In the case of readdir,
 763  * it is likely that the directory objects will be owned by the same
 764  * owner/group and if so there is no need to call into the uid/gid
 765  * mapping code.  While the uid/gid interfaces have their own cache
 766  * having one here will reduct pathlength further.
 767  */
 768 #define MAX_OG_NAME 100
 769 typedef struct ug_cache
 770 {
 771         uid_t   uid;
 772         gid_t   gid;
 773         utf8string u_curr, u_last;
 774         utf8string g_curr, g_last;
 775         char    u_buf1[MAX_OG_NAME];
 776         char    u_buf2[MAX_OG_NAME];
 777         char    g_buf1[MAX_OG_NAME];
 778         char    g_buf2[MAX_OG_NAME];
 779 } ug_cache_t;
 780 
 781 #define U_SWAP_CURR_LAST(ug) \
 782         (ug)->u_last.utf8string_len = (ug)->u_curr.utf8string_len;        \
 783         if ((ug)->u_last.utf8string_val == (ug)->u_buf1) {                \
 784                 (ug)->u_last.utf8string_val = (ug)->u_buf2;               \
 785                 (ug)->u_curr.utf8string_val = (ug)->u_buf1;               \
 786         } else {                                                        \
 787                 (ug)->u_last.utf8string_val = (ug)->u_buf1;               \
 788                 (ug)->u_curr.utf8string_val = (ug)->u_buf2;               \
 789         }
 790 
 791 #define G_SWAP_CURR_LAST(ug) \
 792         (ug)->g_last.utf8string_len = (ug)->g_curr.utf8string_len;        \
 793         if ((ug)->g_last.utf8string_val == (ug)->g_buf1) {                \
 794                 (ug)->g_last.utf8string_val = (ug)->g_buf2;               \
 795                 (ug)->g_curr.utf8string_val = (ug)->g_buf1;               \
 796         } else {                                                        \
 797                 (ug)->g_last.utf8string_val = (ug)->g_buf1;               \
 798                 (ug)->g_curr.utf8string_val = (ug)->g_buf2;               \
 799         }
 800 
 801 static ug_cache_t *
 802 alloc_ugcache()
 803 {
 804         ug_cache_t *pug = kmem_alloc(sizeof (ug_cache_t), KM_SLEEP);
 805 
 806         pug->uid = pug->gid = 0;
 807         pug->u_curr.utf8string_len = 0;
 808         pug->u_last.utf8string_len = 0;
 809         pug->g_curr.utf8string_len = 0;
 810         pug->g_last.utf8string_len = 0;
 811         pug->u_curr.utf8string_val = pug->u_buf1;
 812         pug->u_last.utf8string_val = pug->u_buf2;
 813         pug->g_curr.utf8string_val = pug->g_buf1;
 814         pug->g_last.utf8string_val = pug->g_buf2;
 815 
 816         return (pug);
 817 }
 818 
 819 static void
 820 xdr_ga_prefill_vattr(struct nfs4_ga_res *garp, struct mntinfo4 *mi)
 821 {
 822         static vattr_t s_vattr = {
 823                 AT_ALL,         /* va_mask */
 824                 VNON,           /* va_type */
 825                 0777,           /* va_mode */
 826                 UID_NOBODY,     /* va_uid */
 827                 GID_NOBODY,     /* va_gid */
 828                 0,              /* va_fsid */
 829                 0,              /* va_nodeid */
 830                 1,              /* va_nlink */
 831                 0,              /* va_size */
 832                 {0, 0},         /* va_atime */
 833                 {0, 0},         /* va_mtime */
 834                 {0, 0},         /* va_ctime */
 835                 0,              /* va_rdev */
 836                 MAXBSIZE,       /* va_blksize */
 837                 0,              /* va_nblocks */
 838                 0               /* va_seq */
 839         };
 840 
 841 
 842         garp->n4g_va = s_vattr;
 843         garp->n4g_va.va_fsid = mi->mi_vfsp->vfs_dev;
 844         hrt2ts(gethrtime(), &garp->n4g_va.va_atime);
 845         garp->n4g_va.va_mtime = garp->n4g_va.va_ctime = garp->n4g_va.va_atime;
 846 }
 847 
 848 static void
 849 xdr_ga_prefill_statvfs(struct nfs4_ga_ext_res *gesp, struct mntinfo4 *mi)
 850 {
 851         static statvfs64_t s_sb = {
 852                 MAXBSIZE,       /* f_bsize */
 853                 DEV_BSIZE,      /* f_frsize */
 854                 (fsfilcnt64_t)-1, /* f_blocks */
 855                 (fsfilcnt64_t)-1, /* f_bfree */
 856                 (fsfilcnt64_t)-1, /* f_bavail */
 857                 (fsfilcnt64_t)-1, /* f_files */
 858                 (fsfilcnt64_t)-1, /* f_ffree */
 859                 (fsfilcnt64_t)-1, /* f_favail */
 860                 0,              /* f_fsid */
 861                 "\0",           /* f_basetype */
 862                 0,              /* f_flag */
 863                 MAXNAMELEN,     /* f_namemax */
 864                 "\0",           /* f_fstr */
 865         };
 866 
 867         gesp->n4g_sb = s_sb;
 868         gesp->n4g_sb.f_fsid = mi->mi_vfsp->vfs_fsid.val[0];
 869 }
 870 
 871 static bool_t
 872 xdr_ga_fattr_res(XDR *xdrs, struct nfs4_ga_res *garp, bitmap4 resbmap,
 873     bitmap4 argbmap, struct mntinfo4 *mi, ug_cache_t *pug)
 874 {
 875         int truefalse;
 876         struct nfs4_ga_ext_res ges, *gesp;
 877         vattr_t *vap = &garp->n4g_va;
 878         vsecattr_t *vsap = &garp->n4g_vsa;
 879 
 880         ASSERT(xdrs->x_op == XDR_DECODE);
 881 
 882         if (garp->n4g_ext_res)
 883                 gesp = garp->n4g_ext_res;
 884         else
 885                 gesp = ⩾
 886 
 887         vap->va_mask = 0;
 888 
 889         /* Check to see if the vattr should be pre-filled */
 890         if (argbmap & NFS4_VATTR_MASK)
 891                 xdr_ga_prefill_vattr(garp, mi);
 892 
 893         if (argbmap & NFS4_STATFS_ATTR_MASK)
 894                 xdr_ga_prefill_statvfs(gesp, mi);
 895 
 896         if (resbmap &
 897             (FATTR4_SUPPORTED_ATTRS_MASK |
 898             FATTR4_TYPE_MASK |
 899             FATTR4_FH_EXPIRE_TYPE_MASK |
 900             FATTR4_CHANGE_MASK |
 901             FATTR4_SIZE_MASK |
 902             FATTR4_LINK_SUPPORT_MASK |
 903             FATTR4_SYMLINK_SUPPORT_MASK |
 904             FATTR4_NAMED_ATTR_MASK)) {
 905 
 906                 if (resbmap & FATTR4_SUPPORTED_ATTRS_MASK) {
 907                         if (!xdr_bitmap4(xdrs, &gesp->n4g_suppattrs))
 908                                 return (FALSE);
 909                 }
 910                 if (resbmap & FATTR4_TYPE_MASK) {
 911                         if (!XDR_GETINT32(xdrs, (int *)&vap->va_type))
 912                                 return (FALSE);
 913 
 914                         if ((nfs_ftype4)vap->va_type < NF4REG ||
 915                             (nfs_ftype4)vap->va_type > NF4NAMEDATTR)
 916                                 vap->va_type = VBAD;
 917                         else
 918                                 vap->va_type = nf4_to_vt[vap->va_type];
 919                         if (vap->va_type == VBLK)
 920                                 vap->va_blksize = DEV_BSIZE;
 921 
 922                         vap->va_mask |= AT_TYPE;
 923                 }
 924                 if (resbmap & FATTR4_FH_EXPIRE_TYPE_MASK) {
 925                         if (!XDR_GETINT32(xdrs, (int *)&gesp->n4g_fet))
 926                                 return (FALSE);
 927                 }
 928                 if (resbmap & FATTR4_CHANGE_MASK) {
 929                         if (!xdr_u_longlong_t(xdrs,
 930                             (u_longlong_t *)&garp->n4g_change))
 931                                 return (FALSE);
 932                         garp->n4g_change_valid = 1;
 933                 }
 934                 if (resbmap & FATTR4_SIZE_MASK) {
 935                         if (!xdr_u_longlong_t(xdrs,
 936                             (u_longlong_t *)&vap->va_size))
 937                                 return (FALSE);
 938                         if (!NFS4_SIZE_OK(vap->va_size)) {
 939                                 garp->n4g_attrerr = EFBIG;
 940                                 garp->n4g_attrwhy = NFS4_GETATTR_ATSIZE_ERR;
 941                         } else {
 942                                 vap->va_mask |= AT_SIZE;
 943                         }
 944                 }
 945                 if (resbmap & FATTR4_LINK_SUPPORT_MASK) {
 946                         if (!XDR_GETINT32(xdrs, (int *)&truefalse))
 947                                 return (FALSE);
 948                         gesp->n4g_pc4.pc4_link_support =
 949                             (truefalse ? TRUE : FALSE);
 950                 }
 951                 if (resbmap & FATTR4_SYMLINK_SUPPORT_MASK) {
 952                         if (!XDR_GETINT32(xdrs, (int *)&truefalse))
 953                                 return (FALSE);
 954                         gesp->n4g_pc4.pc4_symlink_support =
 955                             (truefalse ? TRUE : FALSE);
 956                 }
 957                 if (resbmap & FATTR4_NAMED_ATTR_MASK) {
 958                         if (!XDR_GETINT32(xdrs, (int *)&truefalse))
 959                                 return (FALSE);
 960                         gesp->n4g_pc4.pc4_xattr_exists = TRUE;
 961                         gesp->n4g_pc4.pc4_xattr_exists =
 962                             (truefalse ? TRUE : FALSE);
 963                 }
 964         }
 965         if (resbmap &
 966             (FATTR4_FSID_MASK |
 967             FATTR4_UNIQUE_HANDLES_MASK |
 968             FATTR4_LEASE_TIME_MASK |
 969             FATTR4_RDATTR_ERROR_MASK)) {
 970 
 971                 if (resbmap & FATTR4_FSID_MASK) {
 972                         if ((!xdr_u_longlong_t(xdrs,
 973                             (u_longlong_t *)&garp->n4g_fsid.major)) ||
 974                             (!xdr_u_longlong_t(xdrs,
 975                             (u_longlong_t *)&garp->n4g_fsid.minor)))
 976                                 return (FALSE);
 977                         garp->n4g_fsid_valid = 1;
 978                 }
 979                 if (resbmap & FATTR4_UNIQUE_HANDLES_MASK) {
 980                         if (!XDR_GETINT32(xdrs, (int *)&truefalse))
 981                                 return (FALSE);
 982                         gesp->n4g_pc4.pc4_unique_handles =
 983                             (truefalse ? TRUE : FALSE);
 984                 }
 985                 if (resbmap & FATTR4_LEASE_TIME_MASK) {
 986                         if (!XDR_GETINT32(xdrs, (int *)&gesp->n4g_leasetime))
 987                                 return (FALSE);
 988                 }
 989                 if (resbmap & FATTR4_RDATTR_ERROR_MASK) {
 990                         if (!XDR_GETINT32(xdrs,
 991                             (int *)&gesp->n4g_rdattr_error))
 992                                 return (FALSE);
 993                 }
 994         }
 995         if (resbmap &
 996             (FATTR4_ACL_MASK |
 997             FATTR4_ACLSUPPORT_MASK |
 998             FATTR4_ARCHIVE_MASK |
 999             FATTR4_CANSETTIME_MASK)) {
1000 
1001                 if (resbmap & FATTR4_ACL_MASK) {
1002                         fattr4_acl      acl;
1003 
1004                         acl.fattr4_acl_val = NULL;
1005                         acl.fattr4_acl_len = 0;
1006 
1007                         if (!xdr_fattr4_acl(xdrs, &acl))
1008                                 return (FALSE);
1009 
1010                         vsap->vsa_aclcnt = acl.fattr4_acl_len;
1011                         vsap->vsa_aclentp = acl.fattr4_acl_val;
1012                         vsap->vsa_mask = VSA_ACE | VSA_ACECNT;
1013                         vsap->vsa_aclentsz = vsap->vsa_aclcnt * sizeof (ace_t);
1014 
1015                 }
1016                 if (resbmap & FATTR4_ACLSUPPORT_MASK) {
1017                         if (!XDR_GETINT32(xdrs, (int *)&gesp->n4g_aclsupport))
1018                                 return (FALSE);
1019                 }
1020                 if (resbmap & FATTR4_ARCHIVE_MASK) {
1021                         ASSERT(0);
1022                 }
1023                 if (resbmap & FATTR4_CANSETTIME_MASK) {
1024                         if (!XDR_GETINT32(xdrs, (int *)&truefalse))
1025                                 return (FALSE);
1026                         gesp->n4g_pc4.pc4_cansettime =
1027                             (truefalse ? TRUE : FALSE);
1028                 }
1029         }
1030         if (resbmap &
1031             (FATTR4_CASE_INSENSITIVE_MASK |
1032             FATTR4_CASE_PRESERVING_MASK |
1033             FATTR4_CHOWN_RESTRICTED_MASK |
1034             FATTR4_FILEHANDLE_MASK |
1035             FATTR4_FILEID_MASK |
1036             FATTR4_FILES_AVAIL_MASK |
1037             FATTR4_FILES_FREE_MASK |
1038             FATTR4_FILES_TOTAL_MASK)) {
1039 
1040                 if (resbmap & FATTR4_CASE_INSENSITIVE_MASK) {
1041                         if (!XDR_GETINT32(xdrs, (int *)&truefalse))
1042                                 return (FALSE);
1043                         gesp->n4g_pc4.pc4_case_insensitive =
1044                             (truefalse ? TRUE : FALSE);
1045                 }
1046                 if (resbmap & FATTR4_CASE_PRESERVING_MASK) {
1047                         if (!XDR_GETINT32(xdrs, (int *)&truefalse))
1048                                 return (FALSE);
1049                         gesp->n4g_pc4.pc4_case_preserving =
1050                             (truefalse ? TRUE : FALSE);
1051                 }
1052                 if (resbmap & FATTR4_CHOWN_RESTRICTED_MASK) {
1053                         if (!XDR_GETINT32(xdrs, (int *)&truefalse))
1054                                 return (FALSE);
1055                         gesp->n4g_pc4.pc4_chown_restricted =
1056                             (truefalse ? TRUE : FALSE);
1057                 }
1058                 if (resbmap & FATTR4_FILEHANDLE_MASK) {
1059                         gesp->n4g_fh_u.nfs_fh4_alt.len = 0;
1060                         gesp->n4g_fh_u.nfs_fh4_alt.val =
1061                             gesp->n4g_fh_u.nfs_fh4_alt.data;
1062                         if (!xdr_bytes(xdrs,
1063                             (char **)&gesp->n4g_fh_u.n4g_fh.nfs_fh4_val,
1064                             (uint_t *)&gesp->n4g_fh_u.n4g_fh.nfs_fh4_len,
1065                             NFS4_FHSIZE))
1066                                 return (FALSE);
1067                 }
1068                 if (resbmap & FATTR4_FILEID_MASK) {
1069                         if (!xdr_u_longlong_t(xdrs,
1070                             (u_longlong_t *)&vap->va_nodeid))
1071                                 return (FALSE);
1072                         vap->va_mask |= AT_NODEID;
1073                 }
1074                 if (resbmap & FATTR4_FILES_AVAIL_MASK) {
1075                         if (!xdr_u_longlong_t(xdrs,
1076                             (u_longlong_t *)&gesp->n4g_sb.f_favail))
1077                                 return (FALSE);
1078                 }
1079                 if (resbmap & FATTR4_FILES_FREE_MASK) {
1080                         if (!xdr_u_longlong_t(xdrs,
1081                             (u_longlong_t *)&gesp->n4g_sb.f_ffree))
1082                                 return (FALSE);
1083                 }
1084                 if (resbmap & FATTR4_FILES_TOTAL_MASK) {
1085                         if (!xdr_u_longlong_t(xdrs,
1086                             (u_longlong_t *)&gesp->n4g_sb.f_files))
1087                                 return (FALSE);
1088                 }
1089         }
1090         if (resbmap &
1091             (FATTR4_FS_LOCATIONS_MASK |
1092             FATTR4_HIDDEN_MASK |
1093             FATTR4_HOMOGENEOUS_MASK)) {
1094 
1095                 if (resbmap & FATTR4_FS_LOCATIONS_MASK) {
1096                         if (!xdr_fattr4_fs_locations(xdrs,
1097                             &gesp->n4g_fslocations))
1098                                 return (FALSE);
1099                 }
1100                 if (resbmap & FATTR4_HIDDEN_MASK) {
1101                         ASSERT(0);
1102                 }
1103                 if (resbmap & FATTR4_HOMOGENEOUS_MASK) {
1104                         if (!XDR_GETINT32(xdrs, (int *)&truefalse))
1105                                 return (FALSE);
1106                         gesp->n4g_pc4.pc4_homogeneous =
1107                             (truefalse ? TRUE : FALSE);
1108                 }
1109         }
1110         if (resbmap &
1111             (FATTR4_MAXFILESIZE_MASK |
1112             FATTR4_MAXLINK_MASK |
1113             FATTR4_MAXNAME_MASK |
1114             FATTR4_MAXREAD_MASK |
1115             FATTR4_MAXWRITE_MASK)) {
1116 
1117                 if (resbmap & FATTR4_MAXFILESIZE_MASK) {
1118                         if (!xdr_u_longlong_t(xdrs,
1119                             (u_longlong_t *)&gesp->n4g_maxfilesize))
1120                                 return (FALSE);
1121                 }
1122                 if (resbmap & FATTR4_MAXLINK_MASK) {
1123                         if (!XDR_GETINT32(xdrs,
1124                             (int *)&gesp->n4g_pc4.pc4_link_max))
1125                                 return (FALSE);
1126                 }
1127                 if (resbmap & FATTR4_MAXNAME_MASK) {
1128                         if (!XDR_GETINT32(xdrs,
1129                             (int *)&gesp->n4g_pc4.pc4_name_max))
1130                                 return (FALSE);
1131                         gesp->n4g_sb.f_namemax = gesp->n4g_pc4.pc4_name_max;
1132                 }
1133                 if (resbmap & FATTR4_MAXREAD_MASK) {
1134                         if (!xdr_u_longlong_t(xdrs,
1135                             (u_longlong_t *)&gesp->n4g_maxread))
1136                                 return (FALSE);
1137                 }
1138                 if (resbmap & FATTR4_MAXWRITE_MASK) {
1139                         if (!xdr_u_longlong_t(xdrs,
1140                             (u_longlong_t *)&gesp->n4g_maxwrite))
1141                                 return (FALSE);
1142                 }
1143         }
1144         if (resbmap &
1145             (FATTR4_MIMETYPE_MASK |
1146             FATTR4_MODE_MASK |
1147             FATTR4_NO_TRUNC_MASK |
1148             FATTR4_NUMLINKS_MASK)) {
1149 
1150                 if (resbmap & FATTR4_MIMETYPE_MASK) {
1151                         ASSERT(0);
1152                 }
1153                 if (resbmap & FATTR4_MODE_MASK) {
1154                         if (!XDR_GETINT32(xdrs, (int *)&vap->va_mode))
1155                                 return (FALSE);
1156                         vap->va_mask |= AT_MODE;
1157                 }
1158                 if (resbmap & FATTR4_NO_TRUNC_MASK) {
1159                         if (!XDR_GETINT32(xdrs, (int *)&truefalse))
1160                                 return (FALSE);
1161                         gesp->n4g_pc4.pc4_no_trunc =
1162                             (truefalse ? TRUE : FALSE);
1163                 }
1164                 if (resbmap & FATTR4_NUMLINKS_MASK) {
1165                         if (!XDR_GETINT32(xdrs, (int *)&vap->va_nlink))
1166                                 return (FALSE);
1167                         vap->va_mask |= AT_NLINK;
1168                 }
1169         }
1170         if (resbmap &
1171             (FATTR4_OWNER_MASK |
1172             FATTR4_OWNER_GROUP_MASK |
1173             FATTR4_QUOTA_AVAIL_HARD_MASK |
1174             FATTR4_QUOTA_AVAIL_SOFT_MASK)) {
1175 
1176                 if (resbmap & FATTR4_OWNER_MASK) {
1177                         uint_t *owner_length, ol;
1178                         char *owner_val = NULL;
1179                         char *owner_alloc = NULL;
1180                         utf8string ov;
1181                         int error;
1182 
1183                         /* get the OWNER_LENGTH */
1184                         if (!xdr_u_int(xdrs, &ol))
1185                                 return (FALSE);
1186 
1187                         /* Manage the owner length location */
1188                         if (pug && ol <= MAX_OG_NAME) {
1189                                 owner_length = &pug->u_curr.utf8string_len;
1190                                 *owner_length = ol;
1191                         } else {
1192                                 owner_length = &ol;
1193                         }
1194 
1195                         /* find memory to store the decode */
1196                         if (*owner_length > MAX_OG_NAME || pug == NULL)
1197                                 owner_val = owner_alloc =
1198                                     kmem_alloc(*owner_length, KM_SLEEP);
1199                         else
1200                                 owner_val = pug->u_curr.utf8string_val;
1201 
1202                         /* get the OWNER string */
1203                         if (!xdr_opaque(xdrs, owner_val, *owner_length)) {
1204                                 if (owner_alloc)
1205                                         kmem_free(owner_alloc, *owner_length);
1206                                 return (FALSE);
1207                         }
1208 
1209                         /* Optimize for matching if called for */
1210                         if (pug &&
1211                             *owner_length == pug->u_last.utf8string_len &&
1212                             bcmp(owner_val, pug->u_last.utf8string_val,
1213                             *owner_length) == 0) {
1214                                 vap->va_uid = pug->uid;
1215                                 vap->va_mask |= AT_UID;
1216                         } else {
1217                                 uid_t uid;
1218 
1219                                 ov.utf8string_len = *owner_length;
1220                                 ov.utf8string_val = owner_val;
1221                                 error = nfs_idmap_str_uid(&ov, &uid, FALSE);
1222                                 /*
1223                                  * String was mapped, but to nobody because
1224                                  * we are nfsmapid, indicate it should not
1225                                  * be cached.
1226                                  */
1227                                 if (error == ENOTSUP) {
1228                                         error = 0;
1229                                         garp->n4g_attrwhy =
1230                                             NFS4_GETATTR_NOCACHE_OK;
1231                                 }
1232 
1233                                 if (error) {
1234                                         garp->n4g_attrerr = error;
1235                                         garp->n4g_attrwhy =
1236                                             NFS4_GETATTR_ATUID_ERR;
1237                                 } else {
1238                                         vap->va_uid = uid;
1239                                         vap->va_mask |= AT_UID;
1240                                         if (pug && ol <= MAX_OG_NAME) {
1241                                                 pug->uid = uid;
1242                                                 U_SWAP_CURR_LAST(pug);
1243                                         }
1244                                 }
1245                                 if (owner_alloc)
1246                                         kmem_free(owner_alloc, *owner_length);
1247                         }
1248                 }
1249                 if (resbmap & FATTR4_OWNER_GROUP_MASK) {
1250                         uint_t *group_length, gl;
1251                         char *group_val = NULL;
1252                         char *group_alloc = NULL;
1253                         utf8string gv;
1254                         int error;
1255 
1256                         /* get the OWNER_GROUP_LENGTH */
1257                         if (!xdr_u_int(xdrs, &gl))
1258                                 return (FALSE);
1259 
1260                         /* Manage the group length location */
1261                         if (pug && gl <= MAX_OG_NAME) {
1262                                 group_length = &pug->g_curr.utf8string_len;
1263                                 *group_length = gl;
1264                         } else {
1265                                 group_length = ≷
1266                         }
1267 
1268                         /* find memory to store the decode */
1269                         if (*group_length > MAX_OG_NAME || pug == NULL)
1270                                 group_val = group_alloc =
1271                                     kmem_alloc(*group_length, KM_SLEEP);
1272                         else
1273                                 group_val = pug->g_curr.utf8string_val;
1274 
1275                         /* get the OWNER_GROUP string */
1276                         if (!xdr_opaque(xdrs, group_val, *group_length)) {
1277                                 if (group_alloc)
1278                                         kmem_free(group_alloc, *group_length);
1279                                 return (FALSE);
1280                         }
1281 
1282                         /* Optimize for matching if called for */
1283                         if (pug &&
1284                             *group_length == pug->g_last.utf8string_len &&
1285                             bcmp(group_val, pug->g_last.utf8string_val,
1286                             *group_length) == 0) {
1287                                 vap->va_gid = pug->gid;
1288                                 vap->va_mask |= AT_GID;
1289                         } else {
1290                                 uid_t gid;
1291 
1292                                 gv.utf8string_len = *group_length;
1293                                 gv.utf8string_val = group_val;
1294                                 error = nfs_idmap_str_gid(&gv, &gid, FALSE);
1295                                 /*
1296                                  * String was mapped, but to nobody because
1297                                  * we are nfsmapid, indicate it should not
1298                                  * be cached.
1299                                  */
1300                                 if (error == ENOTSUP) {
1301                                         error = 0;
1302                                         garp->n4g_attrwhy =
1303                                             NFS4_GETATTR_NOCACHE_OK;
1304                                 }
1305 
1306                                 if (error) {
1307                                         garp->n4g_attrerr = error;
1308                                         garp->n4g_attrwhy =
1309                                             NFS4_GETATTR_ATGID_ERR;
1310                                 } else {
1311                                         vap->va_gid = gid;
1312                                         vap->va_mask |= AT_GID;
1313                                         if (pug && gl <= MAX_OG_NAME) {
1314                                                 pug->gid = gid;
1315                                                 G_SWAP_CURR_LAST(pug);
1316                                         }
1317                                 }
1318                                 if (group_alloc) {
1319                                         kmem_free(group_alloc, *group_length);
1320                                 }
1321                         }
1322                 }
1323                 if (resbmap & FATTR4_QUOTA_AVAIL_HARD_MASK) {
1324                         ASSERT(0);
1325                 }
1326                 if (resbmap & FATTR4_QUOTA_AVAIL_SOFT_MASK) {
1327                         ASSERT(0);
1328                 }
1329         }
1330         if (resbmap &
1331             (FATTR4_QUOTA_USED_MASK |
1332             FATTR4_SPACE_AVAIL_MASK |
1333             FATTR4_SPACE_FREE_MASK |
1334             FATTR4_SPACE_TOTAL_MASK |
1335             FATTR4_SPACE_USED_MASK |
1336             FATTR4_SYSTEM_MASK)) {
1337 
1338                 if (resbmap & FATTR4_QUOTA_USED_MASK) {
1339                         ASSERT(0);
1340                 }
1341                 if (resbmap & FATTR4_RAWDEV_MASK) {
1342                         fattr4_rawdev rawdev;
1343                         if (!xdr_fattr4_rawdev(xdrs, &rawdev))
1344                                 return (FALSE);
1345 
1346                         if (vap->va_type == VCHR || vap->va_type == VBLK) {
1347                                 vap->va_rdev = makedevice(rawdev.specdata1,
1348                                     rawdev.specdata2);
1349                         } else {
1350                                 vap->va_rdev = 0;
1351                         }
1352                         vap->va_mask |= AT_RDEV;
1353                 }
1354                 if (resbmap & FATTR4_SPACE_AVAIL_MASK) {
1355                         if (!xdr_u_longlong_t(xdrs,
1356                             (u_longlong_t *)&gesp->n4g_sb.f_bavail))
1357                                 return (FALSE);
1358                         gesp->n4g_sb.f_bavail /= DEV_BSIZE;
1359                 }
1360                 if (resbmap & FATTR4_SPACE_FREE_MASK) {
1361                         if (!xdr_u_longlong_t(xdrs,
1362                             (u_longlong_t *)&gesp->n4g_sb.f_bfree))
1363                                 return (FALSE);
1364                         gesp->n4g_sb.f_bfree /= DEV_BSIZE;
1365                 }
1366                 if (resbmap & FATTR4_SPACE_TOTAL_MASK) {
1367                         if (!xdr_u_longlong_t(xdrs,
1368                             (u_longlong_t *)&gesp->n4g_sb.f_blocks))
1369                                 return (FALSE);
1370                         gesp->n4g_sb.f_blocks /= DEV_BSIZE;
1371                 }
1372                 if (resbmap & FATTR4_SPACE_USED_MASK) {
1373                         uint64_t space_used;
1374                         if (!xdr_u_longlong_t(xdrs,
1375                             (u_longlong_t *)&space_used))
1376                                 return (FALSE);
1377 
1378                         /* Compute space depending on device type */
1379                         ASSERT((vap->va_mask & AT_TYPE));
1380                         if (vap->va_type == VREG || vap->va_type == VDIR ||
1381                             vap->va_type == VLNK) {
1382                                 vap->va_nblocks = (u_longlong_t)
1383                                     ((space_used + (offset4)DEV_BSIZE -
1384                                     (offset4)1) / (offset4)DEV_BSIZE);
1385                         } else {
1386                                 vap->va_nblocks = 0;
1387                         }
1388                         vap->va_mask |= AT_NBLOCKS;
1389                 }
1390                 if (resbmap & FATTR4_SYSTEM_MASK) {
1391                         ASSERT(0);
1392                 }
1393         }
1394         if (resbmap &
1395             (FATTR4_TIME_ACCESS_MASK |
1396             FATTR4_TIME_ACCESS_SET_MASK |
1397             FATTR4_TIME_BACKUP_MASK |
1398             FATTR4_TIME_CREATE_MASK |
1399             FATTR4_TIME_DELTA_MASK |
1400             FATTR4_TIME_METADATA_MASK |
1401             FATTR4_TIME_MODIFY_MASK |
1402             FATTR4_TIME_MODIFY_SET_MASK |
1403             FATTR4_MOUNTED_ON_FILEID_MASK)) {
1404 
1405                 if (resbmap & FATTR4_TIME_ACCESS_MASK) {
1406                         nfstime4 atime;
1407                         int error;
1408 
1409                         if (!xdr_longlong_t(xdrs,
1410                             (longlong_t *)&atime.seconds))
1411                                 return (FALSE);
1412                         if (!XDR_GETINT32(xdrs, (int *)&atime.nseconds))
1413                                 return (FALSE);
1414                         error = nfs4_time_ntov(&atime, &vap->va_atime);
1415                         if (error) {
1416                                 garp->n4g_attrerr = error;
1417                                 garp->n4g_attrwhy = NFS4_GETATTR_ATATIME_ERR;
1418                         }
1419                         vap->va_mask |= AT_ATIME;
1420                 }
1421                 if (resbmap & FATTR4_TIME_ACCESS_SET_MASK) {
1422                         ASSERT(0);
1423                 }
1424                 if (resbmap & FATTR4_TIME_BACKUP_MASK) {
1425                         ASSERT(0);
1426                 }
1427                 if (resbmap & FATTR4_TIME_CREATE_MASK) {
1428                         ASSERT(0);
1429                 }
1430                 if (resbmap & FATTR4_TIME_DELTA_MASK) {
1431                         if ((!xdr_u_longlong_t(xdrs,
1432                             (u_longlong_t *)&gesp->n4g_delta.seconds)) ||
1433                             (!xdr_u_int(xdrs, &gesp->n4g_delta.nseconds)))
1434                                 return (FALSE);
1435                 }
1436                 if (resbmap & FATTR4_TIME_METADATA_MASK) {
1437                         nfstime4 mdt;
1438                         int error;
1439 
1440                         if (!xdr_longlong_t(xdrs, (longlong_t *)&mdt.seconds))
1441                                 return (FALSE);
1442                         if (!XDR_GETINT32(xdrs, (int32_t *)&mdt.nseconds))
1443                                 return (FALSE);
1444                         error = nfs4_time_ntov(&mdt, &vap->va_ctime);
1445                         if (error) {
1446                                 garp->n4g_attrerr = error;
1447                                 garp->n4g_attrwhy = NFS4_GETATTR_ATCTIME_ERR;
1448                         }
1449                         vap->va_mask |= AT_CTIME;
1450                 }
1451                 if (resbmap & FATTR4_TIME_MODIFY_MASK) {
1452                         nfstime4 mtime;
1453                         int error;
1454 
1455                         if (!xdr_longlong_t(xdrs,
1456                             (longlong_t *)&mtime.seconds))
1457                                 return (FALSE);
1458                         if (!XDR_GETINT32(xdrs, (int32_t *)&mtime.nseconds))
1459                                 return (FALSE);
1460                         error = nfs4_time_ntov(&mtime, &vap->va_mtime);
1461                         if (error) {
1462                                 garp->n4g_attrerr = error;
1463                                 garp->n4g_attrwhy = NFS4_GETATTR_ATMTIME_ERR;
1464                         }
1465                         vap->va_mask |= AT_MTIME;
1466                 }
1467                 if (resbmap & FATTR4_TIME_MODIFY_SET_MASK) {
1468                         ASSERT(0);
1469                 }
1470                 if (resbmap & FATTR4_MOUNTED_ON_FILEID_MASK) {
1471                         if (!xdr_u_longlong_t(xdrs,
1472                             (u_longlong_t *)&garp->n4g_mon_fid))
1473                                 return (FALSE);
1474                         garp->n4g_mon_fid_valid = 1;
1475                 }
1476         }
1477 
1478         if (resbmap & ~(NFS4_VATTR_MASK | FATTR4_ACL_MASK)) {
1479                 /* copy only if not provided */
1480                 if (garp->n4g_ext_res == NULL) {
1481                         garp->n4g_ext_res = kmem_alloc(sizeof (ges), KM_SLEEP);
1482                         bcopy(&ges, garp->n4g_ext_res, sizeof (ges));
1483                 }
1484         }
1485 
1486         return (TRUE);
1487 }
1488 
1489 /*
1490  * Inlined version of get_bitmap4 processing
1491  */
1492 bitmap4
1493 xdr_get_bitmap4_inline(uint32_t **iptr)
1494 {
1495         uint32_t resbmaplen;
1496         bitmap4 bm;
1497         uint32_t *ptr = *iptr;
1498 
1499         /* bitmap LENGTH */
1500         resbmaplen = IXDR_GET_U_INT32(ptr);
1501 
1502         /* Inline the bitmap and attrlen for common case of two word map */
1503         if (resbmaplen == 2) {
1504                 IXDR_GET_HYPER(ptr, bm);
1505                 *iptr = ptr;
1506                 return (bm);
1507         }
1508 
1509 #if defined(_LITTLE_ENDIAN)
1510         bm = IXDR_GET_U_INT32(ptr);
1511         if (--resbmaplen == 0) {
1512                 *iptr = ptr;
1513                 return (bm);
1514         }
1515         *((uint32_t *)&bm) |= IXDR_GET_U_INT32(ptr);
1516         if (--resbmaplen == 0) {
1517                 *iptr = ptr;
1518                 return (bm);
1519         }
1520         ptr += resbmaplen;
1521         *iptr = ptr;
1522         return (bm);
1523 #elif defined(_BIG_ENDIAN)
1524         *((uint32_t *)&bm) = IXDR_GET_U_INT32(ptr);
1525         if (--resbmaplen == 0) {
1526                 *iptr = ptr;
1527                 return (bm);
1528         }
1529         bm |= IXDR_GET_U_INT32(ptr);
1530         if (--resbmaplen == 0) {
1531                 *iptr = ptr;
1532                 return (bm);
1533         }
1534         ptr += resbmaplen;
1535         *iptr = ptr;
1536         return (bm);
1537 #else
1538         ASSERT(0);
1539         ptr += resbmaplen;
1540         *iptr = ptr;
1541         return (0);
1542 #endif
1543 }
1544 
1545 static bool_t
1546 xdr_ga_fattr_res_inline(uint32_t *ptr, struct nfs4_ga_res *garp,
1547     bitmap4 resbmap, bitmap4 argbmap, struct mntinfo4 *mi, ug_cache_t *pug)
1548 {
1549         int truefalse;
1550         struct nfs4_ga_ext_res ges, *gesp;
1551         vattr_t *vap = &garp->n4g_va;
1552 
1553         if (garp->n4g_ext_res)
1554                 gesp = garp->n4g_ext_res;
1555         else
1556                 gesp = ⩾
1557 
1558         vap->va_mask = 0;
1559 
1560         /* Check to see if the vattr should be pre-filled */
1561         if (argbmap & NFS4_VATTR_MASK)
1562                 xdr_ga_prefill_vattr(garp, mi);
1563 
1564         if (argbmap & NFS4_STATFS_ATTR_MASK)
1565                 xdr_ga_prefill_statvfs(gesp, mi);
1566 
1567         if (resbmap &
1568             (FATTR4_SUPPORTED_ATTRS_MASK |
1569             FATTR4_TYPE_MASK |
1570             FATTR4_FH_EXPIRE_TYPE_MASK |
1571             FATTR4_CHANGE_MASK |
1572             FATTR4_SIZE_MASK |
1573             FATTR4_LINK_SUPPORT_MASK |
1574             FATTR4_SYMLINK_SUPPORT_MASK |
1575             FATTR4_NAMED_ATTR_MASK)) {
1576 
1577                 if (resbmap & FATTR4_SUPPORTED_ATTRS_MASK) {
1578                         gesp->n4g_suppattrs = xdr_get_bitmap4_inline(&ptr);
1579                 }
1580                 if (resbmap & FATTR4_TYPE_MASK) {
1581                         vap->va_type = IXDR_GET_U_INT32(ptr);
1582 
1583                         if ((nfs_ftype4)vap->va_type < NF4REG ||
1584                             (nfs_ftype4)vap->va_type > NF4NAMEDATTR)
1585                                 vap->va_type = VBAD;
1586                         else
1587                                 vap->va_type = nf4_to_vt[vap->va_type];
1588                         if (vap->va_type == VBLK)
1589                                 vap->va_blksize = DEV_BSIZE;
1590 
1591                         vap->va_mask |= AT_TYPE;
1592                 }
1593                 if (resbmap & FATTR4_FH_EXPIRE_TYPE_MASK) {
1594                         gesp->n4g_fet = IXDR_GET_U_INT32(ptr);
1595                 }
1596                 if (resbmap & FATTR4_CHANGE_MASK) {
1597                         IXDR_GET_U_HYPER(ptr, garp->n4g_change);
1598                         garp->n4g_change_valid = 1;
1599                 }
1600                 if (resbmap & FATTR4_SIZE_MASK) {
1601                         IXDR_GET_U_HYPER(ptr, vap->va_size);
1602 
1603                         if (!NFS4_SIZE_OK(vap->va_size)) {
1604                                 garp->n4g_attrerr = EFBIG;
1605                                 garp->n4g_attrwhy = NFS4_GETATTR_ATSIZE_ERR;
1606                         } else {
1607                                 vap->va_mask |= AT_SIZE;
1608                         }
1609                 }
1610                 if (resbmap & FATTR4_LINK_SUPPORT_MASK) {
1611                         truefalse = IXDR_GET_U_INT32(ptr);
1612                         gesp->n4g_pc4.pc4_link_support =
1613                             (truefalse ? TRUE : FALSE);
1614                 }
1615                 if (resbmap & FATTR4_SYMLINK_SUPPORT_MASK) {
1616                         truefalse = IXDR_GET_U_INT32(ptr);
1617                         gesp->n4g_pc4.pc4_symlink_support =
1618                             (truefalse ? TRUE : FALSE);
1619                 }
1620                 if (resbmap & FATTR4_NAMED_ATTR_MASK) {
1621                         truefalse = IXDR_GET_U_INT32(ptr);
1622                         gesp->n4g_pc4.pc4_xattr_exists = TRUE;
1623                         gesp->n4g_pc4.pc4_xattr_exists =
1624                             (truefalse ? TRUE : FALSE);
1625                 }
1626         }
1627         if (resbmap &
1628             (FATTR4_FSID_MASK |
1629             FATTR4_UNIQUE_HANDLES_MASK |
1630             FATTR4_LEASE_TIME_MASK |
1631             FATTR4_RDATTR_ERROR_MASK)) {
1632 
1633                 if (resbmap & FATTR4_FSID_MASK) {
1634                         IXDR_GET_U_HYPER(ptr, garp->n4g_fsid.major);
1635                         IXDR_GET_U_HYPER(ptr, garp->n4g_fsid.minor);
1636                         garp->n4g_fsid_valid = 1;
1637                 }
1638                 if (resbmap & FATTR4_UNIQUE_HANDLES_MASK) {
1639                         truefalse = IXDR_GET_U_INT32(ptr);
1640                         gesp->n4g_pc4.pc4_unique_handles =
1641                             (truefalse ? TRUE : FALSE);
1642                 }
1643                 if (resbmap & FATTR4_LEASE_TIME_MASK) {
1644                         gesp->n4g_leasetime = IXDR_GET_U_INT32(ptr);
1645                 }
1646                 if (resbmap & FATTR4_RDATTR_ERROR_MASK) {
1647                         gesp->n4g_rdattr_error = IXDR_GET_U_INT32(ptr);
1648                 }
1649         }
1650         if (resbmap &
1651             (FATTR4_ACL_MASK |
1652             FATTR4_ACLSUPPORT_MASK |
1653             FATTR4_ARCHIVE_MASK |
1654             FATTR4_CANSETTIME_MASK)) {
1655 
1656                 if (resbmap & FATTR4_ACL_MASK) {
1657                         ASSERT(0);
1658                 }
1659                 if (resbmap & FATTR4_ACLSUPPORT_MASK) {
1660                         gesp->n4g_aclsupport = IXDR_GET_U_INT32(ptr);
1661                 }
1662                 if (resbmap & FATTR4_ARCHIVE_MASK) {
1663                         ASSERT(0);
1664                 }
1665                 if (resbmap & FATTR4_CANSETTIME_MASK) {
1666                         truefalse = IXDR_GET_U_INT32(ptr);
1667                         gesp->n4g_pc4.pc4_cansettime =
1668                             (truefalse ? TRUE : FALSE);
1669                 }
1670         }
1671         if (resbmap &
1672             (FATTR4_CASE_INSENSITIVE_MASK |
1673             FATTR4_CASE_PRESERVING_MASK |
1674             FATTR4_CHOWN_RESTRICTED_MASK |
1675             FATTR4_FILEHANDLE_MASK |
1676             FATTR4_FILEID_MASK |
1677             FATTR4_FILES_AVAIL_MASK |
1678             FATTR4_FILES_FREE_MASK |
1679             FATTR4_FILES_TOTAL_MASK)) {
1680 
1681                 if (resbmap & FATTR4_CASE_INSENSITIVE_MASK) {
1682                         truefalse = IXDR_GET_U_INT32(ptr);
1683                         gesp->n4g_pc4.pc4_case_insensitive =
1684                             (truefalse ? TRUE : FALSE);
1685                 }
1686                 if (resbmap & FATTR4_CASE_PRESERVING_MASK) {
1687                         truefalse = IXDR_GET_U_INT32(ptr);
1688                         gesp->n4g_pc4.pc4_case_preserving =
1689                             (truefalse ? TRUE : FALSE);
1690                 }
1691                 if (resbmap & FATTR4_CHOWN_RESTRICTED_MASK) {
1692                         truefalse = IXDR_GET_U_INT32(ptr);
1693                         gesp->n4g_pc4.pc4_chown_restricted =
1694                             (truefalse ? TRUE : FALSE);
1695                 }
1696                 if (resbmap & FATTR4_FILEHANDLE_MASK) {
1697                         int len = IXDR_GET_U_INT32(ptr);
1698 
1699                         gesp->n4g_fh_u.nfs_fh4_alt.len = 0;
1700                         gesp->n4g_fh_u.nfs_fh4_alt.val =
1701                             gesp->n4g_fh_u.nfs_fh4_alt.data;
1702                         gesp->n4g_fh_u.n4g_fh.nfs_fh4_len = len;
1703 
1704                         bcopy(ptr, gesp->n4g_fh_u.n4g_fh.nfs_fh4_val, len);
1705 
1706                         ptr += RNDUP(len) / BYTES_PER_XDR_UNIT;
1707                 }
1708                 if (resbmap & FATTR4_FILEID_MASK) {
1709                         IXDR_GET_U_HYPER(ptr, vap->va_nodeid);
1710                         vap->va_mask |= AT_NODEID;
1711                 }
1712                 if (resbmap & FATTR4_FILES_AVAIL_MASK) {
1713                         IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_favail);
1714                 }
1715                 if (resbmap & FATTR4_FILES_FREE_MASK) {
1716                         IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_ffree);
1717                 }
1718                 if (resbmap & FATTR4_FILES_TOTAL_MASK) {
1719                         IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_files);
1720                 }
1721         }
1722         if (resbmap &
1723             (FATTR4_FS_LOCATIONS_MASK |
1724             FATTR4_HIDDEN_MASK |
1725             FATTR4_HOMOGENEOUS_MASK)) {
1726 
1727                 if (resbmap & FATTR4_FS_LOCATIONS_MASK) {
1728                         ASSERT(0);
1729                 }
1730                 if (resbmap & FATTR4_HIDDEN_MASK) {
1731                         ASSERT(0);
1732                 }
1733                 if (resbmap & FATTR4_HOMOGENEOUS_MASK) {
1734                         truefalse = IXDR_GET_U_INT32(ptr);
1735                         gesp->n4g_pc4.pc4_homogeneous =
1736                             (truefalse ? TRUE : FALSE);
1737                 }
1738         }
1739         if (resbmap &
1740             (FATTR4_MAXFILESIZE_MASK |
1741             FATTR4_MAXLINK_MASK |
1742             FATTR4_MAXNAME_MASK |
1743             FATTR4_MAXREAD_MASK |
1744             FATTR4_MAXWRITE_MASK)) {
1745 
1746                 if (resbmap & FATTR4_MAXFILESIZE_MASK) {
1747                         IXDR_GET_U_HYPER(ptr, gesp->n4g_maxfilesize);
1748                 }
1749                 if (resbmap & FATTR4_MAXLINK_MASK) {
1750                         gesp->n4g_pc4.pc4_link_max = IXDR_GET_U_INT32(ptr);
1751                 }
1752                 if (resbmap & FATTR4_MAXNAME_MASK) {
1753                         gesp->n4g_pc4.pc4_name_max = IXDR_GET_U_INT32(ptr);
1754                         gesp->n4g_sb.f_namemax = gesp->n4g_pc4.pc4_name_max;
1755                 }
1756                 if (resbmap & FATTR4_MAXREAD_MASK) {
1757                         IXDR_GET_U_HYPER(ptr, gesp->n4g_maxread);
1758                 }
1759                 if (resbmap & FATTR4_MAXWRITE_MASK) {
1760                         IXDR_GET_U_HYPER(ptr, gesp->n4g_maxwrite);
1761                 }
1762         }
1763         if (resbmap &
1764             (FATTR4_MIMETYPE_MASK |
1765             FATTR4_MODE_MASK |
1766             FATTR4_NO_TRUNC_MASK |
1767             FATTR4_NUMLINKS_MASK)) {
1768 
1769                 if (resbmap & FATTR4_MIMETYPE_MASK) {
1770                         ASSERT(0);
1771                 }
1772                 if (resbmap & FATTR4_MODE_MASK) {
1773                         vap->va_mode = IXDR_GET_U_INT32(ptr);
1774                         vap->va_mask |= AT_MODE;
1775                 }
1776                 if (resbmap & FATTR4_NO_TRUNC_MASK) {
1777                         truefalse = IXDR_GET_U_INT32(ptr);
1778                         gesp->n4g_pc4.pc4_no_trunc =
1779                             (truefalse ? TRUE : FALSE);
1780                 }
1781                 if (resbmap & FATTR4_NUMLINKS_MASK) {
1782                         vap->va_nlink = IXDR_GET_U_INT32(ptr);
1783                         vap->va_mask |= AT_NLINK;
1784                 }
1785         }
1786         if (resbmap &
1787             (FATTR4_OWNER_MASK |
1788             FATTR4_OWNER_GROUP_MASK |
1789             FATTR4_QUOTA_AVAIL_HARD_MASK |
1790             FATTR4_QUOTA_AVAIL_SOFT_MASK)) {
1791 
1792                 if (resbmap & FATTR4_OWNER_MASK) {
1793                         uint_t *owner_length, ol;
1794                         char *owner_val = NULL;
1795                         utf8string ov;
1796                         int error;
1797 
1798                         /* get the OWNER_LENGTH */
1799                         ol = IXDR_GET_U_INT32(ptr);
1800 
1801                         /* Manage the owner length location */
1802                         if (pug && ol <= MAX_OG_NAME) {
1803                                 owner_length = &pug->u_curr.utf8string_len;
1804                                 *owner_length = ol;
1805                         } else {
1806                                 owner_length = &ol;
1807                         }
1808 
1809                         /* find memory to store the decode */
1810                         if (*owner_length > MAX_OG_NAME || pug == NULL)
1811                                 owner_val = (char *)ptr;
1812                         else
1813                                 owner_val = (char *)ptr;
1814 
1815                         /* Optimize for matching if called for */
1816                         if (pug &&
1817                             *owner_length == pug->u_last.utf8string_len &&
1818                             bcmp(owner_val, pug->u_last.utf8string_val,
1819                             *owner_length) == 0) {
1820                                 vap->va_uid = pug->uid;
1821                                 vap->va_mask |= AT_UID;
1822                         } else {
1823                                 uid_t uid;
1824 
1825                                 ov.utf8string_len = *owner_length;
1826                                 ov.utf8string_val = owner_val;
1827                                 error = nfs_idmap_str_uid(&ov, &uid, FALSE);
1828                                 /*
1829                                  * String was mapped, but to nobody because
1830                                  * we are nfsmapid, indicate it should not
1831                                  * be cached.
1832                                  */
1833                                 if (error == ENOTSUP) {
1834                                         error = 0;
1835                                         garp->n4g_attrwhy =
1836                                             NFS4_GETATTR_NOCACHE_OK;
1837                                 }
1838 
1839                                 if (error) {
1840                                         garp->n4g_attrerr = error;
1841                                         garp->n4g_attrwhy =
1842                                             NFS4_GETATTR_ATUID_ERR;
1843                                 } else {
1844                                         vap->va_uid = uid;
1845                                         vap->va_mask |= AT_UID;
1846                                         /* save the results for next time */
1847                                         if (pug && ol <= MAX_OG_NAME) {
1848                                                 pug->uid = uid;
1849                                                 pug->u_curr.utf8string_len =
1850                                                     ov.utf8string_len;
1851                                                 bcopy(owner_val,
1852                                                     pug->u_curr.utf8string_val,
1853                                                     ol);
1854                                                 U_SWAP_CURR_LAST(pug);
1855                                         }
1856                                 }
1857                         }
1858                         ptr += RNDUP(ol) / BYTES_PER_XDR_UNIT;
1859                 }
1860                 if (resbmap & FATTR4_OWNER_GROUP_MASK) {
1861                         uint_t *group_length, gl;
1862                         char *group_val = NULL;
1863                         utf8string gv;
1864                         int error;
1865 
1866                         /* get the OWNER_GROUP_LENGTH */
1867                         gl = IXDR_GET_U_INT32(ptr);
1868 
1869                         /* Manage the group length location */
1870                         if (pug && gl <= MAX_OG_NAME) {
1871                                 group_length = &pug->g_curr.utf8string_len;
1872                                 *group_length = gl;
1873                         } else {
1874                                 group_length = ≷
1875                         }
1876 
1877                         /* find memory to store the decode */
1878                         if (*group_length > MAX_OG_NAME || pug == NULL)
1879                                 group_val = (char *)ptr;
1880                         else
1881                                 group_val = (char *)ptr;
1882 
1883                         /* Optimize for matching if called for */
1884                         if (pug &&
1885                             *group_length == pug->g_last.utf8string_len &&
1886                             bcmp(group_val, pug->g_last.utf8string_val,
1887                             *group_length) == 0) {
1888                                 vap->va_gid = pug->gid;
1889                                 vap->va_mask |= AT_GID;
1890                         } else {
1891                                 uid_t gid;
1892 
1893                                 gv.utf8string_len = *group_length;
1894                                 gv.utf8string_val = group_val;
1895                                 error = nfs_idmap_str_gid(&gv, &gid, FALSE);
1896                                 /*
1897                                  * String was mapped, but to nobody because
1898                                  * we are nfsmapid, indicate it should not
1899                                  * be cached.
1900                                  */
1901                                 if (error == ENOTSUP) {
1902                                         error = 0;
1903                                         garp->n4g_attrwhy =
1904                                             NFS4_GETATTR_NOCACHE_OK;
1905                                 }
1906 
1907                                 if (error) {
1908                                         garp->n4g_attrerr = error;
1909                                         garp->n4g_attrwhy =
1910                                             NFS4_GETATTR_ATGID_ERR;
1911                                 } else {
1912                                         vap->va_gid = gid;
1913                                         vap->va_mask |= AT_GID;
1914                                         if (pug && gl <= MAX_OG_NAME) {
1915                                                 pug->gid = gid;
1916                                                 pug->g_curr.utf8string_len =
1917                                                     gv.utf8string_len;
1918                                                 bcopy(group_val,
1919                                                     pug->g_curr.utf8string_val,
1920                                                     gl);
1921                                                 G_SWAP_CURR_LAST(pug);
1922                                         }
1923                                 }
1924                         }
1925                         ptr += RNDUP(gl) / BYTES_PER_XDR_UNIT;
1926                 }
1927                 if (resbmap & FATTR4_QUOTA_AVAIL_HARD_MASK) {
1928                         ASSERT(0);
1929                 }
1930                 if (resbmap & FATTR4_QUOTA_AVAIL_SOFT_MASK) {
1931                         ASSERT(0);
1932                 }
1933         }
1934         if (resbmap &
1935             (FATTR4_QUOTA_USED_MASK |
1936             FATTR4_SPACE_AVAIL_MASK |
1937             FATTR4_SPACE_FREE_MASK |
1938             FATTR4_SPACE_TOTAL_MASK |
1939             FATTR4_SPACE_USED_MASK |
1940             FATTR4_SYSTEM_MASK)) {
1941 
1942                 if (resbmap & FATTR4_QUOTA_USED_MASK) {
1943                         ASSERT(0);
1944                 }
1945                 if (resbmap & FATTR4_RAWDEV_MASK) {
1946                         fattr4_rawdev rawdev;
1947 
1948                         rawdev.specdata1 = IXDR_GET_U_INT32(ptr);
1949                         rawdev.specdata2 = IXDR_GET_U_INT32(ptr);
1950 
1951                         if (vap->va_type == VCHR || vap->va_type == VBLK) {
1952                                 vap->va_rdev = makedevice(rawdev.specdata1,
1953                                     rawdev.specdata2);
1954                         } else {
1955                                 vap->va_rdev = 0;
1956                         }
1957                         vap->va_mask |= AT_RDEV;
1958                 }
1959                 if (resbmap & FATTR4_SPACE_AVAIL_MASK) {
1960                         IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_bavail);
1961                         gesp->n4g_sb.f_bavail /= DEV_BSIZE;
1962                 }
1963                 if (resbmap & FATTR4_SPACE_FREE_MASK) {
1964                         IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_bfree);
1965                         gesp->n4g_sb.f_bfree /= DEV_BSIZE;
1966                 }
1967                 if (resbmap & FATTR4_SPACE_TOTAL_MASK) {
1968                         IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_blocks);
1969                         gesp->n4g_sb.f_blocks /= DEV_BSIZE;
1970                 }
1971                 if (resbmap & FATTR4_SPACE_USED_MASK) {
1972                         uint64_t space_used;
1973                         IXDR_GET_U_HYPER(ptr, space_used);
1974 
1975                         /* Compute space depending on device type */
1976                         ASSERT((vap->va_mask & AT_TYPE));
1977                         if (vap->va_type == VREG || vap->va_type == VDIR ||
1978                             vap->va_type == VLNK) {
1979                                 vap->va_nblocks = (u_longlong_t)
1980                                     ((space_used + (offset4)DEV_BSIZE -
1981                                     (offset4)1) / (offset4)DEV_BSIZE);
1982                         } else {
1983                                 vap->va_nblocks = 0;
1984                         }
1985                         vap->va_mask |= AT_NBLOCKS;
1986                 }
1987                 if (resbmap & FATTR4_SYSTEM_MASK) {
1988                         ASSERT(0);
1989                 }
1990         }
1991         if (resbmap &
1992             (FATTR4_TIME_ACCESS_MASK |
1993             FATTR4_TIME_ACCESS_SET_MASK |
1994             FATTR4_TIME_BACKUP_MASK |
1995             FATTR4_TIME_CREATE_MASK |
1996             FATTR4_TIME_DELTA_MASK |
1997             FATTR4_TIME_METADATA_MASK |
1998             FATTR4_TIME_MODIFY_MASK |
1999             FATTR4_TIME_MODIFY_SET_MASK |
2000             FATTR4_MOUNTED_ON_FILEID_MASK)) {
2001 
2002                 if (resbmap & FATTR4_TIME_ACCESS_MASK) {
2003                         nfstime4 atime;
2004                         int error;
2005 
2006                         IXDR_GET_U_HYPER(ptr, atime.seconds);
2007                         atime.nseconds = IXDR_GET_U_INT32(ptr);
2008 
2009                         error = nfs4_time_ntov(&atime, &vap->va_atime);
2010                         if (error) {
2011                                 garp->n4g_attrerr = error;
2012                                 garp->n4g_attrwhy = NFS4_GETATTR_ATATIME_ERR;
2013                         }
2014                         vap->va_mask |= AT_ATIME;
2015                 }
2016                 if (resbmap & FATTR4_TIME_ACCESS_SET_MASK) {
2017                         ASSERT(0);
2018                 }
2019                 if (resbmap & FATTR4_TIME_BACKUP_MASK) {
2020                         ASSERT(0);
2021                 }
2022                 if (resbmap & FATTR4_TIME_CREATE_MASK) {
2023                         ASSERT(0);
2024                 }
2025                 if (resbmap & FATTR4_TIME_DELTA_MASK) {
2026                         IXDR_GET_U_HYPER(ptr, gesp->n4g_delta.seconds);
2027                         gesp->n4g_delta.nseconds = IXDR_GET_U_INT32(ptr);
2028                 }
2029                 if (resbmap & FATTR4_TIME_METADATA_MASK) {
2030                         nfstime4 mdt;
2031                         int error;
2032 
2033                         IXDR_GET_U_HYPER(ptr, mdt.seconds);
2034                         mdt.nseconds = IXDR_GET_U_INT32(ptr);
2035 
2036                         error = nfs4_time_ntov(&mdt, &vap->va_ctime);
2037                         if (error) {
2038                                 garp->n4g_attrerr = error;
2039                                 garp->n4g_attrwhy = NFS4_GETATTR_ATCTIME_ERR;
2040                         }
2041                         vap->va_mask |= AT_CTIME;
2042                 }
2043                 if (resbmap & FATTR4_TIME_MODIFY_MASK) {
2044                         nfstime4 mtime;
2045                         int error;
2046 
2047                         IXDR_GET_U_HYPER(ptr, mtime.seconds);
2048                         mtime.nseconds = IXDR_GET_U_INT32(ptr);
2049 
2050                         error = nfs4_time_ntov(&mtime, &vap->va_mtime);
2051                         if (error) {
2052                                 garp->n4g_attrerr = error;
2053                                 garp->n4g_attrwhy = NFS4_GETATTR_ATMTIME_ERR;
2054                         }
2055                         vap->va_mask |= AT_MTIME;
2056                 }
2057                 if (resbmap & FATTR4_TIME_MODIFY_SET_MASK) {
2058                         ASSERT(0);
2059                 }
2060                 if (resbmap & FATTR4_MOUNTED_ON_FILEID_MASK) {
2061                         IXDR_GET_U_HYPER(ptr, garp->n4g_mon_fid);
2062                         garp->n4g_mon_fid_valid = 1;
2063                 }
2064         }
2065 
2066         /*
2067          * FATTR4_ACL_MASK is not yet supported by this function, but
2068          * we check against it anyway, in case it ever is.
2069          */
2070         if (resbmap & ~(NFS4_VATTR_MASK | FATTR4_ACL_MASK)) {
2071                 /* copy only if not provided */
2072                 if (garp->n4g_ext_res == NULL) {
2073                         garp->n4g_ext_res = kmem_alloc(sizeof (ges), KM_SLEEP);
2074                         bcopy(&ges, garp->n4g_ext_res, sizeof (ges));
2075                 }
2076         }
2077 
2078         return (TRUE);
2079 }
2080 
2081 
2082 /*
2083  * "." and ".." buffers for filling in on read and readdir
2084  * calls. Intialize the first time and fill in on every
2085  * call to to readdir.
2086  */
2087 char    *nfs4_dot_entries;
2088 char    *nfs4_dot_dot_entry;
2089 
2090 /*
2091  * Create the "." or ".." and pad the buffer once so they are
2092  * copied out as required into the user supplied buffer everytime.
2093  * DIRENT64_RECLEN(sizeof (".") - 1) = DIRENT64_RECLEN(1)
2094  * DIRENT64_RECLEN(sizeof ("..") - 1) = DIRENT64_RECLEN(2)
2095  */
2096 void
2097 nfs4_init_dot_entries()
2098 {
2099         struct dirent64 *odp;
2100 
2101         /*
2102          * zalloc it so it zeros the buffer out. Need
2103          * to just do it once.
2104          */
2105         nfs4_dot_entries = kmem_zalloc(DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2),
2106             KM_SLEEP);
2107 
2108         odp = (struct dirent64 *)nfs4_dot_entries;
2109         odp->d_off = 1; /* magic cookie for "." entry */
2110         odp->d_reclen = DIRENT64_RECLEN(1);
2111         odp->d_name[0] = '.';
2112         odp->d_name[1] = '\0';
2113 
2114         nfs4_dot_dot_entry = nfs4_dot_entries + DIRENT64_RECLEN(1);
2115         odp = (struct dirent64 *)nfs4_dot_dot_entry;
2116 
2117         odp->d_off = 2;
2118         odp->d_reclen = DIRENT64_RECLEN(2);
2119         odp->d_name[0] = '.';
2120         odp->d_name[1] = '.';
2121         odp->d_name[2] = '\0';
2122 }
2123 
2124 void
2125 nfs4_destroy_dot_entries()
2126 {
2127         if (nfs4_dot_entries)
2128                 kmem_free(nfs4_dot_entries, DIRENT64_RECLEN(1) +
2129                     DIRENT64_RECLEN(2));
2130 
2131         nfs4_dot_entries = nfs4_dot_dot_entry = NULL;
2132 }
2133 
2134 bool_t
2135 xdr_READDIR4res_clnt(XDR *xdrs, READDIR4res_clnt *objp, READDIR4args *aobjp)
2136 {
2137         bool_t more_data;
2138         rddir4_cache *rdc = aobjp->rdc;
2139         dirent64_t *dp = NULL;
2140         int entry_length = 0;
2141         int space_left = 0;
2142         bitmap4 resbmap;
2143         uint32_t attrlen;
2144         nfs4_ga_res_t gar;
2145         struct nfs4_ga_ext_res ges;
2146         uint64_t last_cookie = 0;
2147         int skip_to_end;
2148         ug_cache_t *pug = NULL;
2149 
2150         ASSERT(xdrs->x_op == XDR_DECODE);
2151         ASSERT(rdc->entries == NULL);
2152         ASSERT(aobjp->dircount > 0);
2153 
2154         if (!xdr_int(xdrs, (int32_t *)&objp->status))
2155                 return (FALSE);
2156         if (objp->status != NFS4_OK)
2157                 return (TRUE);
2158 
2159         gar.n4g_va.va_mask = 0;
2160         gar.n4g_change_valid = 0;
2161         gar.n4g_mon_fid_valid = 0;
2162         gar.n4g_fsid_valid = 0;
2163         gar.n4g_vsa.vsa_mask = 0;
2164         gar.n4g_attrwhy = NFS4_GETATTR_OP_OK;
2165         ges.n4g_pc4.pc4_cache_valid = 0;
2166         ges.n4g_pc4.pc4_xattr_valid = 0;
2167         gar.n4g_ext_res = ⩾
2168 
2169         /* READDIR4res_clnt_free needs to kmem_free this buffer */
2170         rdc->entries = kmem_alloc(aobjp->dircount, KM_SLEEP);
2171 
2172         dp = (dirent64_t *)rdc->entries;
2173         rdc->entlen = rdc->buflen = space_left = aobjp->dircount;
2174 
2175         /* Fill in dot and dot-dot if needed */
2176         if (rdc->nfs4_cookie == (nfs_cookie4) 0 ||
2177             rdc->nfs4_cookie == (nfs_cookie4) 1) {
2178 
2179                 if (rdc->nfs4_cookie == (nfs_cookie4)0) {
2180                         bcopy(nfs4_dot_entries, rdc->entries,
2181                             DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2));
2182                         objp->dotp = dp;
2183                         dp = (struct dirent64 *)(((char *)dp) +
2184                             DIRENT64_RECLEN(1));
2185                         objp->dotdotp = dp;
2186                         dp = (struct dirent64 *)(((char *)dp) +
2187                             DIRENT64_RECLEN(2));
2188                         space_left -= DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2);
2189 
2190                 } else  {       /* for ".." entry */
2191                         bcopy(nfs4_dot_dot_entry, rdc->entries,
2192                             DIRENT64_RECLEN(2));
2193                         objp->dotp = NULL;
2194                         objp->dotdotp = dp;
2195                         dp = (struct dirent64 *)(((char *)dp) +
2196                             DIRENT64_RECLEN(2));
2197                         space_left -= DIRENT64_RECLEN(2);
2198                 }
2199                 /* Magic NFSv4 number for entry after start */
2200                 last_cookie = 2;
2201         }
2202 
2203         /* Get the cookie VERIFIER */
2204         if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cookieverf))
2205                 goto noentries;
2206 
2207         /* Get the do-we-have-a-next-entry BOOL */
2208         if (!xdr_bool(xdrs, &more_data))
2209                 goto noentries;
2210 
2211         if (aobjp->attr_request & (FATTR4_OWNER_MASK | FATTR4_OWNER_GROUP_MASK))
2212                 pug = alloc_ugcache();
2213 
2214         skip_to_end = 0;
2215         while (more_data) {
2216                 uint_t namelen;
2217                 uint64_t cookie;
2218 
2219                 /* Get the COOKIE */
2220                 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&cookie))
2221                         goto noentries;
2222 
2223                 /* Get the LENGTH of the entry name */
2224                 if (!xdr_u_int(xdrs, &namelen))
2225                         goto noentries;
2226 
2227                 if (!skip_to_end) {
2228                         /*
2229                          * With the length of the directory entry name
2230                          * in hand, figure out if there is room left
2231                          * to encode it for the requestor.  If not,
2232                          * that is okay, but the rest of the readdir
2233                          * operation result must be decoded in the
2234                          * case there are following operations
2235                          * in the compound request.  Therefore, mark
2236                          * the rest of the response as "skip" and
2237                          * decode or skip the remaining data
2238                          */
2239                         entry_length = DIRENT64_RECLEN(namelen);
2240                         if (space_left < entry_length)
2241                                 skip_to_end = 1;
2242                 }
2243 
2244                 /* Get the NAME of the entry */
2245                 if (!skip_to_end) {
2246                         if (!xdr_opaque(xdrs, dp->d_name, namelen))
2247                                 goto noentries;
2248                         bzero(&dp->d_name[namelen],
2249                             DIRENT64_NAMELEN(entry_length) - namelen);
2250                         dp->d_off = last_cookie = cookie;
2251                         dp->d_reclen = entry_length;
2252                 } else {
2253                         if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &namelen))
2254                                 goto noentries;
2255                 }
2256 
2257                 /* Get the attribute BITMAP */
2258                 if (!xdr_bitmap4(xdrs, &resbmap))
2259                         goto noentries;
2260                 /* Get the LENGTH of the attributes */
2261                 if (!xdr_u_int(xdrs, (uint_t *)&attrlen))
2262                         goto noentries;
2263 
2264                 /* Get the ATTRIBUTES */
2265                 if (!skip_to_end) {
2266                         uint32_t *ptr;
2267 
2268                         if (!(resbmap & FATTR4_ACL_MASK) &&
2269                             (ptr = (uint32_t *)XDR_INLINE(xdrs, attrlen))
2270                             != NULL) {
2271                                 if (!xdr_ga_fattr_res_inline(ptr, &gar, resbmap,
2272                                     aobjp->attr_request, aobjp->mi, pug))
2273                                         goto noentries;
2274                         } else {
2275                                 if (!xdr_ga_fattr_res(xdrs, &gar, resbmap,
2276                                     aobjp->attr_request, aobjp->mi, pug))
2277                                         goto noentries;
2278                         }
2279 
2280                         /* Fill in the d_ino per the server's fid values */
2281                         /*
2282                          * Important to note that the mounted on fileid
2283                          * is returned in d_ino if supported.  This is
2284                          * expected, readdir returns the mounted on fileid
2285                          * while stat() returns the fileid of the object
2286                          * on "top" of the mount.
2287                          */
2288                         if (gar.n4g_mon_fid_valid)
2289                                 dp->d_ino = gar.n4g_mon_fid;
2290                         else if (gar.n4g_va.va_mask & AT_NODEID)
2291                                 dp->d_ino = gar.n4g_va.va_nodeid;
2292                         else
2293                                 dp->d_ino = 0;
2294 
2295                         /* See about creating an rnode for this entry */
2296                         if ((resbmap &
2297                             (NFS4_VATTR_MASK | FATTR4_FILEHANDLE_MASK)) ==
2298                             (NFS4_VATTR_MASK | FATTR4_FILEHANDLE_MASK)) {
2299                                 nfs4_sharedfh_t *sfhp;
2300                                 vnode_t *vp;
2301 
2302                                 sfhp = sfh4_put(&ges.n4g_fh_u.n4g_fh,
2303                                     aobjp->mi, NULL);
2304                                 vp = makenfs4node(sfhp, &gar,
2305                                     aobjp->dvp->v_vfsp,
2306                                     aobjp->t,
2307                                     aobjp->cr,
2308                                     aobjp->dvp,
2309                                     fn_get(VTOSV(aobjp->dvp)->sv_name,
2310                                     dp->d_name, sfhp));
2311                                 sfh4_rele(&sfhp);
2312                                 dnlc_update(aobjp->dvp, dp->d_name, vp);
2313                                 VN_RELE(vp);
2314                         }
2315 
2316                         dp = (struct dirent64 *)(((caddr_t)dp) + dp->d_reclen);
2317 
2318                         space_left -= entry_length;
2319 
2320                 } else {
2321                         if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &attrlen))
2322                                 goto noentries;
2323                 }
2324 
2325                 /* Get the do-we-have-a-next-entry BOOL */
2326                 if (!xdr_bool(xdrs, &more_data))
2327                         goto noentries;
2328         }
2329 
2330         if (pug) {
2331                 kmem_free(pug, sizeof (ug_cache_t));
2332                 pug = NULL;
2333         }
2334 
2335         /*
2336          * Finish up the rddir cache
2337          * If no entries were returned, free up buffer &
2338          * set ncookie to the starting cookie for this
2339          * readdir request so that the direof caching
2340          * will work properly.
2341          */
2342         ASSERT(rdc->entries);
2343         if (last_cookie == 0) {
2344                 kmem_free(rdc->entries, rdc->entlen);
2345                 rdc->entries = NULL;
2346                 last_cookie = rdc->nfs4_cookie;
2347         }
2348 
2349         rdc->actlen = rdc->entlen - space_left;
2350         rdc->nfs4_ncookie = last_cookie;
2351 
2352         /* Get the EOF marker */
2353         if (!xdr_bool(xdrs, &objp->eof))
2354                 goto noentries;
2355 
2356         /*
2357          * If the server returns eof and there were no
2358          * skipped entries, set eof
2359          */
2360         rdc->eof = (objp->eof && !skip_to_end) ? TRUE : FALSE;
2361 
2362         /*
2363          * If we encoded entries we are done
2364          */
2365         if (rdc->entries) {
2366                 rdc->error = 0;
2367                 return (TRUE);
2368         }
2369 
2370         /*
2371          * If there were no entries and we skipped because
2372          * there was not enough space, return EINVAL
2373          */
2374         if (skip_to_end) {
2375                 rdc->error = EINVAL;
2376                 return (TRUE);
2377         }
2378 
2379         /*
2380          * No entries, nothing skipped, and EOF, return OK.
2381          */
2382         if (objp->eof == TRUE) {
2383                 rdc->error = 0;
2384                 return (TRUE);
2385         }
2386 
2387         /*
2388          * No entries, nothing skipped, and not EOF
2389          * probably a bad cookie, return ENOENT.
2390          */
2391         rdc->error = ENOENT;
2392         return (TRUE);
2393 
2394 noentries:
2395         if (rdc->entries) {
2396                 kmem_free(rdc->entries, rdc->entlen);
2397                 rdc->entries = NULL;
2398         }
2399         if (pug)
2400                 kmem_free(pug, sizeof (ug_cache_t));
2401         rdc->error = EIO;
2402         return (FALSE);
2403 }
2404 
2405 /*
2406  * xdr_ga_res
2407  *
2408  * Returns: FALSE on raw data processing errors, TRUE otherwise.
2409  *
2410  * This function pre-processes the OP_GETATTR response, and then
2411  * calls common routines to process the GETATTR fattr4 results into
2412  * vnode attributes and other components that the client is interested
2413  * in. If an error other than an RPC error is encountered, the details
2414  * of the error are filled into objp, although the result of the
2415  * processing is set to TRUE.
2416  */
2417 static bool_t
2418 xdr_ga_res(XDR *xdrs, GETATTR4res *objp, GETATTR4args *aobjp)
2419 {
2420 #ifdef INLINE
2421         uint32_t *ptr;
2422 #endif
2423         bitmap4 resbmap;
2424         uint32_t attrlen;
2425 
2426         ASSERT(xdrs->x_op == XDR_DECODE);
2427 
2428         /* Initialize objp attribute error values */
2429         objp->ga_res.n4g_attrerr =
2430             objp->ga_res.n4g_attrwhy = NFS4_GETATTR_OP_OK;
2431 
2432         if (!xdr_bitmap4(xdrs, &resbmap))
2433                 return (FALSE);
2434 
2435         /* save the response bitmap for the caller */
2436         objp->ga_res.n4g_resbmap = resbmap;
2437 
2438         /* attrlen */
2439         if (!XDR_GETINT32(xdrs, (int32_t *)&attrlen))
2440                 return (FALSE);
2441 
2442         /*
2443          * Handle case where request and response bitmaps don't match.
2444          */
2445         if (aobjp->attr_request && aobjp->attr_request != resbmap) {
2446                 bitmap4 deltabmap;
2447 
2448                 /*
2449                  * Return error for case where server sent extra attributes
2450                  * because the "unknown" attributes may be anywhere in the
2451                  * xdr stream and can't be properly processed.
2452                  */
2453                 deltabmap = ((aobjp->attr_request ^ resbmap) & resbmap);
2454                 if (deltabmap) {
2455                         objp->ga_res.n4g_attrerr = EINVAL;
2456                         objp->ga_res.n4g_attrwhy = NFS4_GETATTR_BITMAP_ERR;
2457                         return (TRUE);
2458                 }
2459 
2460                 /*
2461                  * Return error for case where there is a mandatory
2462                  * attribute missing in the server response. Note that
2463                  * missing recommended attributes are evaluated in the
2464                  * specific routines that decode the server response.
2465                  */
2466                 deltabmap = ((aobjp->attr_request ^ resbmap)
2467                     & aobjp->attr_request);
2468                 if ((deltabmap & FATTR4_MANDATTR_MASK)) {
2469                         objp->ga_res.n4g_attrerr = EINVAL;
2470                         objp->ga_res.n4g_attrwhy = NFS4_GETATTR_MANDATTR_ERR;
2471                         return (TRUE);
2472                 }
2473         }
2474 
2475         /* Check to see if the attrs can be inlined and go for it if so */
2476 #ifdef INLINE
2477         if (!(resbmap & FATTR4_ACL_MASK) &&
2478             (ptr = (uint32_t *)XDR_INLINE(xdrs, attrlen)) != NULL)
2479                 return (xdr_ga_fattr_res_inline(ptr, &objp->ga_res,
2480                     resbmap, aobjp->attr_request, aobjp->mi, NULL));
2481         else
2482 #endif
2483                 return (xdr_ga_fattr_res(xdrs, &objp->ga_res,
2484                     resbmap, aobjp->attr_request, aobjp->mi, NULL));
2485 }
2486 
2487 #if defined(DEBUG) && !defined(lint)
2488 /*
2489  * We assume that an enum is a 32-bit value, check it once
2490  */
2491 static enum szchk { SZVAL } szchkvar;
2492 #endif
2493 
2494 bool_t
2495 xdr_settime4(XDR *xdrs, settime4 *objp)
2496 {
2497 #if defined(DEBUG) && !defined(lint)
2498         ASSERT(sizeof (szchkvar) == sizeof (int32_t));
2499 #endif
2500         if (xdrs->x_op == XDR_FREE)
2501                 return (TRUE);
2502 
2503         if (!xdr_int(xdrs, (int *)&objp->set_it))
2504                 return (FALSE);
2505         if (objp->set_it != SET_TO_CLIENT_TIME4)
2506                 return (TRUE);
2507         /* xdr_nfstime4 */
2508         if (!xdr_longlong_t(xdrs, (longlong_t *)&objp->time.seconds))
2509                 return (FALSE);
2510         return (xdr_u_int(xdrs, &objp->time.nseconds));
2511 }
2512 
2513 static bool_t
2514 xdr_fattr4(XDR *xdrs, fattr4 *objp)
2515 {
2516         if (xdrs->x_op != XDR_FREE) {
2517                 if (!xdr_bitmap4(xdrs, &objp->attrmask))
2518                         return (FALSE);
2519                 return (xdr_bytes(xdrs, (char **)&objp->attrlist4,
2520                     (uint_t *)&objp->attrlist4_len, NFS4_FATTR4_LIMIT));
2521         }
2522 
2523         /*
2524          * Optimized free case
2525          */
2526         if (objp->attrlist4 != NULL)
2527                 kmem_free(objp->attrlist4, objp->attrlist4_len);
2528         return (TRUE);
2529 }
2530 
2531 static bool_t
2532 xdr_ACCESS4res(XDR *xdrs, ACCESS4res *objp)
2533 {
2534         if (!xdr_int(xdrs, (int32_t *)&objp->status))
2535                 return (FALSE);
2536         if (objp->status != NFS4_OK)
2537                 return (TRUE);
2538         if (!xdr_u_int(xdrs, &objp->supported))
2539                 return (FALSE);
2540         return (xdr_u_int(xdrs, &objp->access));
2541 }
2542 
2543 static bool_t
2544 xdr_CLOSE4args(XDR *xdrs, CLOSE4args *objp)
2545 {
2546         if (!xdr_u_int(xdrs, &objp->seqid))
2547                 return (FALSE);
2548         if (!xdr_u_int(xdrs, &objp->open_stateid.seqid))
2549                 return (FALSE);
2550         return (xdr_opaque(xdrs, objp->open_stateid.other, NFS4_OTHER_SIZE));
2551 }
2552 
2553 static bool_t
2554 xdr_CLOSE4res(XDR *xdrs, CLOSE4res *objp)
2555 {
2556         if (!xdr_int(xdrs, (int32_t *)&objp->status))
2557                 return (FALSE);
2558         if (objp->status != NFS4_OK)
2559                 return (TRUE);
2560         if (!xdr_u_int(xdrs, &objp->open_stateid.seqid))
2561                 return (FALSE);
2562         return (xdr_opaque(xdrs, objp->open_stateid.other, NFS4_OTHER_SIZE));
2563 }
2564 
2565 static bool_t
2566 xdr_CREATE4args(XDR *xdrs, CREATE4args *objp)
2567 {
2568         if (xdrs->x_op != XDR_FREE) {
2569                 if (!xdr_int(xdrs, (int32_t *)&objp->type))
2570                         return (FALSE);
2571                 switch (objp->type) {
2572                 case NF4LNK:
2573                         if (!xdr_bytes(xdrs,
2574                             (char **)&objp->ftype4_u.linkdata.linktext4_val,
2575                             (uint_t *)&objp->ftype4_u.linkdata.linktext4_len,
2576                             NFS4_MAX_UTF8STRING))
2577                                 return (FALSE);
2578                         break;
2579                 case NF4BLK:
2580                 case NF4CHR:
2581                         if (!xdr_u_int(xdrs, &objp->ftype4_u.devdata.specdata1))
2582                                 return (FALSE);
2583                         if (!xdr_u_int(xdrs, &objp->ftype4_u.devdata.specdata2))
2584                                 return (FALSE);
2585                         break;
2586                 case NF4SOCK:
2587                 case NF4FIFO:
2588                 case NF4DIR:
2589                 default:
2590                         break;  /* server should return NFS4ERR_BADTYPE */
2591                 }
2592                 if (!xdr_bytes(xdrs, (char **)&objp->objname.utf8string_val,
2593                     (uint_t *)&objp->objname.utf8string_len,
2594                     NFS4_MAX_UTF8STRING))
2595                         return (FALSE);
2596                 return (xdr_fattr4(xdrs, &objp->createattrs));
2597         }
2598 
2599         /*
2600          * Optimized free case
2601          */
2602         if (objp->type == NF4LNK) {
2603                 if (objp->ftype4_u.linkdata.linktext4_val != NULL)
2604                         kmem_free(objp->ftype4_u.linkdata.linktext4_val,
2605                             objp->ftype4_u.linkdata.linktext4_len);
2606         }
2607         if (objp->objname.utf8string_val != NULL)
2608                 kmem_free(objp->objname.utf8string_val,
2609                     objp->objname.utf8string_len);
2610         return (xdr_fattr4(xdrs, &objp->createattrs));
2611 }
2612 
2613 static bool_t
2614 xdr_CREATE4cargs(XDR *xdrs, CREATE4cargs *objp)
2615 {
2616         int len;
2617 
2618         ASSERT(xdrs->x_op == XDR_ENCODE);
2619 
2620         if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->type))
2621                 return (FALSE);
2622         switch (objp->type) {
2623         case NF4LNK:
2624                 len = strlen(objp->ftype4_u.clinkdata);
2625                 if (len > NFS4_MAX_UTF8STRING)
2626                         return (FALSE);
2627                 if (!XDR_PUTINT32(xdrs, &len))
2628                         return (FALSE);
2629                 if (!xdr_opaque(xdrs, objp->ftype4_u.clinkdata, len))
2630                         return (FALSE);
2631                 break;
2632         case NF4BLK:
2633         case NF4CHR:
2634                 if (!XDR_PUTINT32(xdrs,
2635                     (int32_t *)&objp->ftype4_u.devdata.specdata1))
2636                         return (FALSE);
2637                 if (!XDR_PUTINT32(xdrs,
2638                     (int32_t *)&objp->ftype4_u.devdata.specdata2))
2639                         return (FALSE);
2640                 break;
2641         case NF4SOCK:
2642         case NF4FIFO:
2643         case NF4DIR:
2644         default:
2645                 break;  /* server should return NFS4ERR_BADTYPE */
2646         }
2647 
2648         len = strlen(objp->cname);
2649         if (len > NFS4_MAX_UTF8STRING)
2650                 return (FALSE);
2651         if (!XDR_PUTINT32(xdrs, &len))
2652                 return (FALSE);
2653         if (!xdr_opaque(xdrs, objp->cname, len))
2654                 return (FALSE);
2655 
2656         return (xdr_fattr4(xdrs, &objp->createattrs));
2657 }
2658 
2659 static bool_t
2660 xdr_CREATE4res(XDR *xdrs, CREATE4res *objp)
2661 {
2662         if (!xdr_int(xdrs, (int32_t *)&objp->status))
2663                 return (FALSE);
2664         if (objp->status != NFS4_OK)
2665                 return (TRUE);
2666         if (!xdr_bool(xdrs, &objp->cinfo.atomic))
2667                 return (FALSE);
2668         if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.before))
2669                 return (FALSE);
2670         if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.after))
2671                 return (FALSE);
2672         return (xdr_bitmap4(xdrs, &objp->attrset));
2673 }
2674 
2675 static bool_t
2676 xdr_LINK4res(XDR *xdrs, LINK4res *objp)
2677 {
2678         if (!xdr_int(xdrs, (int32_t *)&objp->status))
2679                 return (FALSE);
2680         if (objp->status != NFS4_OK)
2681                 return (TRUE);
2682         if (!xdr_bool(xdrs, &objp->cinfo.atomic))
2683                 return (FALSE);
2684         if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.before))
2685                 return (FALSE);
2686         return (xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.after));
2687 }
2688 
2689 static bool_t
2690 xdr_LOCK4args(XDR *xdrs, LOCK4args *objp)
2691 {
2692         if (xdrs->x_op != XDR_FREE) {
2693                 if (!xdr_int(xdrs, (int *)&objp->locktype))
2694                         return (FALSE);
2695                 if (!xdr_bool(xdrs, &objp->reclaim))
2696                         return (FALSE);
2697                 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset))
2698                         return (FALSE);
2699                 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->length))
2700                         return (FALSE);
2701                 if (!xdr_bool(xdrs, &objp->locker.new_lock_owner))
2702                         return (FALSE);
2703                 if (objp->locker.new_lock_owner == TRUE) {
2704                         if (!xdr_u_int(xdrs, &objp->locker.locker4_u.open_owner.
2705                             open_seqid))
2706                                 return (FALSE);
2707                         if (!xdr_u_int(xdrs, &objp->locker.locker4_u.open_owner.
2708                             open_stateid.seqid))
2709                                 return (FALSE);
2710                         if (!xdr_opaque(xdrs, objp->locker.locker4_u.open_owner.
2711                             open_stateid.other, NFS4_OTHER_SIZE))
2712                                 return (FALSE);
2713                         if (!xdr_u_int(xdrs, &objp->locker.locker4_u.open_owner.
2714                             lock_seqid))
2715                                 return (FALSE);
2716                         if (!xdr_u_longlong_t(xdrs,
2717                             (u_longlong_t *)&objp->locker.locker4_u.
2718                             open_owner.lock_owner.clientid))
2719                                 return (FALSE);
2720                         return (xdr_bytes(xdrs,
2721                             (char **)&objp->locker.locker4_u.open_owner.
2722                             lock_owner.owner_val,
2723                             (uint_t *)&objp->locker.locker4_u.open_owner.
2724                             lock_owner.owner_len,
2725                             NFS4_OPAQUE_LIMIT));
2726                 }
2727 
2728                 if (objp->locker.new_lock_owner != FALSE)
2729                         return (FALSE);
2730 
2731                 if (!xdr_u_int(xdrs, &objp->locker.locker4_u.lock_owner.
2732                     lock_stateid.seqid))
2733                         return (FALSE);
2734                 if (!xdr_opaque(xdrs, objp->locker.locker4_u.lock_owner.
2735                     lock_stateid.other, NFS4_OTHER_SIZE))
2736                         return (FALSE);
2737                 return (xdr_u_int(xdrs, &objp->locker.locker4_u.lock_owner.
2738                     lock_seqid));
2739         }
2740 
2741         /*
2742          * Optimized free case
2743          */
2744         if (objp->locker.new_lock_owner == TRUE) {
2745                 if (objp->locker.locker4_u.open_owner.lock_owner.owner_val !=
2746                     NULL) {
2747                         kmem_free(objp->locker.locker4_u.open_owner.lock_owner.
2748                             owner_val,
2749                             objp->locker.locker4_u.open_owner.lock_owner.
2750                             owner_len);
2751                 }
2752         }
2753 
2754         return (TRUE);
2755 }
2756 
2757 static bool_t
2758 xdr_LOCK4res(XDR *xdrs, LOCK4res *objp)
2759 {
2760         if (xdrs->x_op != XDR_FREE) {
2761                 if (!xdr_int(xdrs, (int32_t *)&objp->status))
2762                         return (FALSE);
2763                 if (objp->status == NFS4_OK) {
2764                         if (!xdr_u_int(xdrs,
2765                             &objp->LOCK4res_u.lock_stateid.seqid))
2766                                 return (FALSE);
2767                         return (xdr_opaque(xdrs,
2768                             objp->LOCK4res_u.lock_stateid.other,
2769                             NFS4_OTHER_SIZE));
2770                 }
2771                 if (objp->status != NFS4ERR_DENIED)
2772                         return (TRUE);
2773 
2774                 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->LOCK4res_u.
2775                     denied.offset))
2776                         return (FALSE);
2777                 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->LOCK4res_u.
2778                     denied.length))
2779                         return (FALSE);
2780                 if (!xdr_int(xdrs, (int *)&objp->LOCK4res_u.denied.locktype))
2781                         return (FALSE);
2782                 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->LOCK4res_u.
2783                     denied.owner.clientid))
2784                         return (FALSE);
2785                 return (xdr_bytes(xdrs,
2786                     (char **)&objp->LOCK4res_u.denied.owner.owner_val,
2787                     (uint_t *)&objp->LOCK4res_u.denied.owner.owner_len,
2788                     NFS4_OPAQUE_LIMIT));
2789         }
2790 
2791         /*
2792          * Optimized free case
2793          */
2794         if (objp->status == NFS4_OK || objp->status != NFS4ERR_DENIED)
2795                 return (TRUE);
2796 
2797         if (objp->LOCK4res_u.denied.owner.owner_val != NULL)
2798                 kmem_free(objp->LOCK4res_u.denied.owner.owner_val,
2799                     objp->LOCK4res_u.denied.owner.owner_len);
2800         return (TRUE);
2801 }
2802 
2803 static bool_t
2804 xdr_LOCKT4args(XDR *xdrs, LOCKT4args *objp)
2805 {
2806         if (xdrs->x_op != XDR_FREE) {
2807                 if (!xdr_int(xdrs, (int *)&objp->locktype))
2808                         return (FALSE);
2809                 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset))
2810                         return (FALSE);
2811                 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->length))
2812                         return (FALSE);
2813                 if (!xdr_u_longlong_t(xdrs,
2814                     (u_longlong_t *)&objp->owner.clientid))
2815                         return (FALSE);
2816                 return (xdr_bytes(xdrs, (char **)&objp->owner.owner_val,
2817                     (uint_t *)&objp->owner.owner_len,
2818                     NFS4_OPAQUE_LIMIT));
2819         }
2820 
2821         /*
2822          * Optimized free case
2823          */
2824         if (objp->owner.owner_val != NULL)
2825                 kmem_free(objp->owner.owner_val, objp->owner.owner_len);
2826         return (TRUE);
2827 }
2828 
2829 static bool_t
2830 xdr_LOCKT4res(XDR *xdrs, LOCKT4res *objp)
2831 {
2832         if (xdrs->x_op != XDR_FREE) {
2833                 if (!xdr_int(xdrs, (int32_t *)&objp->status))
2834                         return (FALSE);
2835                 if (objp->status == NFS4_OK)
2836                         return (TRUE);
2837                 if (objp->status != NFS4ERR_DENIED)
2838                         return (TRUE);
2839                 /* xdr_LOCK4denied */
2840                 if (!xdr_u_longlong_t(xdrs,
2841                     (u_longlong_t *)&objp->denied.offset))
2842                         return (FALSE);
2843                 if (!xdr_u_longlong_t(xdrs,
2844                     (u_longlong_t *)&objp->denied.length))
2845                         return (FALSE);
2846                 if (!xdr_int(xdrs, (int *)&objp->denied.locktype))
2847                         return (FALSE);
2848                 if (!xdr_u_longlong_t(xdrs,
2849                     (u_longlong_t *)&objp->denied.owner.clientid))
2850                         return (FALSE);
2851                 return (xdr_bytes(xdrs,
2852                     (char **)&objp->denied.owner.owner_val,
2853                     (uint_t *)&objp->denied.owner.owner_len,
2854                     NFS4_OPAQUE_LIMIT));
2855         }
2856 
2857         /*
2858          * Optimized free case
2859          */
2860         if (objp->status == NFS4_OK || objp->status != NFS4ERR_DENIED)
2861                 return (TRUE);
2862         if (objp->denied.owner.owner_val != NULL)
2863                 kmem_free(objp->denied.owner.owner_val,
2864                     objp->denied.owner.owner_len);
2865         return (TRUE);
2866 }
2867 
2868 static bool_t
2869 xdr_LOCKU4args(XDR *xdrs, LOCKU4args *objp)
2870 {
2871         if (!xdr_int(xdrs, (int *)&objp->locktype))
2872                 return (FALSE);
2873         if (!xdr_u_int(xdrs, &objp->seqid))
2874                 return (FALSE);
2875         if (!xdr_u_int(xdrs, &objp->lock_stateid.seqid))
2876                 return (FALSE);
2877         if (!xdr_opaque(xdrs, objp->lock_stateid.other, NFS4_OTHER_SIZE))
2878                 return (FALSE);
2879         if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset))
2880                 return (FALSE);
2881         return (xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->length));
2882 }
2883 
2884 static bool_t
2885 xdr_OPEN4args(XDR *xdrs, OPEN4args *objp)
2886 {
2887         if (xdrs->x_op != XDR_FREE) {
2888                 if (!xdr_u_int(xdrs, &objp->seqid))
2889                         return (FALSE);
2890                 if (!xdr_u_int(xdrs, &objp->share_access))
2891                         return (FALSE);
2892                 if (!xdr_u_int(xdrs, &objp->share_deny))
2893                         return (FALSE);
2894 
2895                 /* xdr_open_owner4 */
2896                 if (!xdr_u_longlong_t(xdrs,
2897                     (u_longlong_t *)&objp->owner.clientid))
2898                         return (FALSE);
2899                 if (!xdr_bytes(xdrs, (char **)&objp->owner.owner_val,
2900                     (uint_t *)&objp->owner.owner_len,
2901                     NFS4_OPAQUE_LIMIT))
2902                         return (FALSE);
2903 
2904                 /* xdr_openflag4 */
2905                 if (!xdr_int(xdrs, (int *)&objp->opentype))
2906                         return (FALSE);
2907                 if (objp->opentype == OPEN4_CREATE) {
2908 
2909                         /* xdr_createhow4 */
2910                         if (!xdr_int(xdrs, (int *)&objp->mode))
2911                                 return (FALSE);
2912                         switch (objp->mode) {
2913                         case UNCHECKED4:
2914                         case GUARDED4:
2915                                 if (!xdr_fattr4(xdrs,
2916                                     &objp->createhow4_u.createattrs))
2917                                         return (FALSE);
2918                                 break;
2919                         case EXCLUSIVE4:
2920                                 if (!xdr_u_longlong_t(xdrs,
2921                                     (u_longlong_t *)&objp->createhow4_u.
2922                                     createverf))
2923                                         return (FALSE);
2924                                 break;
2925                         default:
2926                                 return (FALSE);
2927                         }
2928                 }
2929 
2930                 /* xdr_open_claim4 */
2931                 if (!xdr_int(xdrs, (int *)&objp->claim))
2932                         return (FALSE);
2933 
2934                 switch (objp->claim) {
2935                 case CLAIM_NULL:
2936                         return (xdr_bytes(xdrs, (char **)&objp->open_claim4_u.
2937                             file.utf8string_val,
2938                             (uint_t *)&objp->open_claim4_u.file.
2939                             utf8string_len,
2940                             NFS4_MAX_UTF8STRING));
2941                 case CLAIM_PREVIOUS:
2942                         return (xdr_int(xdrs,
2943                             (int *)&objp->open_claim4_u.delegate_type));
2944                 case CLAIM_DELEGATE_CUR:
2945                         if (!xdr_u_int(xdrs, (uint_t *)&objp->open_claim4_u.
2946                             delegate_cur_info.delegate_stateid.seqid))
2947                                 return (FALSE);
2948                         if (!xdr_opaque(xdrs, objp->open_claim4_u.
2949                             delegate_cur_info.delegate_stateid.other,
2950                             NFS4_OTHER_SIZE))
2951                                 return (FALSE);
2952                         return (xdr_bytes(xdrs, (char **)&objp->open_claim4_u.
2953                             delegate_cur_info.file.utf8string_val,
2954                             (uint_t *)&objp->open_claim4_u.
2955                             delegate_cur_info.file.utf8string_len,
2956                             NFS4_MAX_UTF8STRING));
2957                 case CLAIM_DELEGATE_PREV:
2958                         return (xdr_bytes(xdrs, (char **)&objp->open_claim4_u.
2959                             file_delegate_prev.utf8string_val,
2960                             (uint_t *)&objp->open_claim4_u.
2961                             file_delegate_prev.utf8string_len,
2962                             NFS4_MAX_UTF8STRING));
2963                 default:
2964                         return (FALSE);
2965                 }
2966         }
2967 
2968         /*
2969          * Optimized free case
2970          */
2971         if (objp->owner.owner_val != NULL)
2972                 kmem_free(objp->owner.owner_val, objp->owner.owner_len);
2973 
2974         if (objp->opentype == OPEN4_CREATE) {
2975                 switch (objp->mode) {
2976                 case UNCHECKED4:
2977                 case GUARDED4:
2978                         (void) xdr_fattr4(xdrs,
2979                             &objp->createhow4_u.createattrs);
2980                         break;
2981                 case EXCLUSIVE4:
2982                 default:
2983                         break;
2984                 }
2985         }
2986 
2987         switch (objp->claim) {
2988         case CLAIM_NULL:
2989                 if (objp->open_claim4_u.file.utf8string_val != NULL)
2990                         kmem_free(objp->open_claim4_u.file.utf8string_val,
2991                             objp->open_claim4_u.file.utf8string_len);
2992                 return (TRUE);
2993         case CLAIM_PREVIOUS:
2994                 return (TRUE);
2995         case CLAIM_DELEGATE_CUR:
2996                 if (objp->open_claim4_u.delegate_cur_info.file.utf8string_val !=
2997                     NULL) {
2998                         kmem_free(objp->open_claim4_u.delegate_cur_info.file.
2999                             utf8string_val,
3000                             objp->open_claim4_u.delegate_cur_info.file.
3001                             utf8string_len);
3002                 }
3003                 return (TRUE);
3004         case CLAIM_DELEGATE_PREV:
3005                 if (objp->open_claim4_u.file_delegate_prev.utf8string_val !=
3006                     NULL) {
3007                         kmem_free(objp->open_claim4_u.file_delegate_prev.
3008                             utf8string_val,
3009                             objp->open_claim4_u.file_delegate_prev.
3010                             utf8string_len);
3011                 }
3012                 return (TRUE);
3013         default:
3014                 return (TRUE);
3015         }
3016 }
3017 
3018 static bool_t
3019 xdr_OPEN4cargs(XDR *xdrs, OPEN4cargs *objp)
3020 {
3021         int op;
3022         int len;
3023         rpc_inline_t *ptr;
3024 
3025         ASSERT(xdrs->x_op == XDR_ENCODE);
3026 
3027         /*
3028          * We must always define the client's open_owner to be
3029          * 4 byte aligned and sized.
3030          */
3031         ASSERT(objp->owner.owner_len <= NFS4_OPAQUE_LIMIT);
3032         ASSERT(!(objp->owner.owner_len % BYTES_PER_XDR_UNIT));
3033 
3034         len = objp->owner.owner_len;
3035         if ((ptr = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT + len)) != NULL) {
3036                 int i;
3037                 int32_t *ip;
3038 
3039                 IXDR_PUT_U_INT32(ptr, OP_OPEN);
3040                 IXDR_PUT_U_INT32(ptr, objp->seqid);
3041                 IXDR_PUT_U_INT32(ptr, objp->share_access);
3042                 IXDR_PUT_U_INT32(ptr, objp->share_deny);
3043 
3044                 /* xdr_open_owner4 */
3045                 IXDR_PUT_HYPER(ptr, objp->owner.clientid);
3046                 IXDR_PUT_U_INT32(ptr, objp->owner.owner_len);
3047                 /* We know this is very short so don't bcopy */
3048                 ip = (int32_t *)objp->owner.owner_val;
3049                 len /= BYTES_PER_XDR_UNIT;
3050                 for (i = 0; i < len; i++)
3051                         *ptr++ = *ip++;
3052 
3053                 /* xdr_openflag4 */
3054                 IXDR_PUT_U_INT32(ptr, objp->opentype);
3055         } else {
3056                 op = OP_OPEN;
3057                 if (!XDR_PUTINT32(xdrs, (int32_t *)&op))
3058                         return (FALSE);
3059                 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->seqid))
3060                         return (FALSE);
3061                 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->share_access))
3062                         return (FALSE);
3063                 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->share_deny))
3064                         return (FALSE);
3065 
3066                 /* xdr_open_owner4 */
3067                 if (!xdr_u_longlong_t(xdrs,
3068                     (u_longlong_t *)&objp->owner.clientid))
3069                         return (FALSE);
3070                 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->owner.owner_len))
3071                         return (FALSE);
3072                 if (!xdr_opaque(xdrs, objp->owner.owner_val,
3073                     objp->owner.owner_len))
3074                         return (FALSE);
3075 
3076                 /* xdr_openflag4 */
3077                 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->opentype))
3078                         return (FALSE);
3079         }
3080 
3081         if (objp->opentype == OPEN4_CREATE) {
3082                 /* xdr_createhow4 */
3083                 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->mode))
3084                         return (FALSE);
3085                 switch (objp->mode) {
3086                 case UNCHECKED4:
3087                 case GUARDED4:
3088                         if (!xdr_fattr4(xdrs,
3089                             &objp->createhow4_u.createattrs))
3090                                 return (FALSE);
3091                         break;
3092                 case EXCLUSIVE4:
3093                         if (!xdr_u_longlong_t(xdrs,
3094                             (u_longlong_t *)&objp->createhow4_u.
3095                             createverf))
3096                                 return (FALSE);
3097                         break;
3098                 default:
3099                         return (FALSE);
3100                 }
3101         }
3102 
3103         /* xdr_open_claim4 */
3104         if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->claim))
3105                 return (FALSE);
3106 
3107         switch (objp->claim) {
3108         case CLAIM_NULL:
3109                 len = strlen(objp->open_claim4_u.cfile);
3110                 if (len > NFS4_MAX_UTF8STRING)
3111                         return (FALSE);
3112                 if (XDR_PUTINT32(xdrs, &len)) {
3113                         return (xdr_opaque(xdrs,
3114                             objp->open_claim4_u.cfile, len));
3115                 }
3116                 return (FALSE);
3117         case CLAIM_PREVIOUS:
3118                 return (XDR_PUTINT32(xdrs,
3119                     (int32_t *)&objp->open_claim4_u.delegate_type));
3120         case CLAIM_DELEGATE_CUR:
3121                 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->open_claim4_u.
3122                     delegate_cur_info.delegate_stateid.seqid))
3123                         return (FALSE);
3124                 if (!xdr_opaque(xdrs, objp->open_claim4_u.
3125                     delegate_cur_info.delegate_stateid.other,
3126                     NFS4_OTHER_SIZE))
3127                         return (FALSE);
3128                 len = strlen(objp->open_claim4_u.delegate_cur_info.cfile);
3129                 if (len > NFS4_MAX_UTF8STRING)
3130                         return (FALSE);
3131                 if (XDR_PUTINT32(xdrs, &len)) {
3132                         return (xdr_opaque(xdrs,
3133                             objp->open_claim4_u.delegate_cur_info.cfile,
3134                             len));
3135                 }
3136                 return (FALSE);
3137         case CLAIM_DELEGATE_PREV:
3138                 len = strlen(objp->open_claim4_u.cfile_delegate_prev);
3139                 if (len > NFS4_MAX_UTF8STRING)
3140                         return (FALSE);
3141                 if (XDR_PUTINT32(xdrs, &len)) {
3142                         return (xdr_opaque(xdrs,
3143                             objp->open_claim4_u.cfile_delegate_prev, len));
3144                 }
3145                 return (FALSE);
3146         default:
3147                 return (FALSE);
3148         }
3149 }
3150 
3151 static bool_t
3152 xdr_OPEN4res(XDR *xdrs, OPEN4res *objp)
3153 {
3154         if (xdrs->x_op != XDR_FREE) {
3155                 if (!xdr_int(xdrs, (int32_t *)&objp->status))
3156                         return (FALSE);
3157                 if (objp->status != NFS4_OK)
3158                         return (TRUE);
3159                 if (!xdr_u_int(xdrs, &objp->stateid.seqid))
3160                         return (FALSE);
3161                 if (!xdr_opaque(xdrs, objp->stateid.other, NFS4_OTHER_SIZE))
3162                         return (FALSE);
3163                 if (!xdr_bool(xdrs, &objp->cinfo.atomic))
3164                         return (FALSE);
3165                 if (!xdr_u_longlong_t(xdrs,
3166                     (u_longlong_t *)&objp->cinfo.before))
3167                         return (FALSE);
3168                 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.after))
3169                         return (FALSE);
3170                 if (!xdr_u_int(xdrs, &objp->rflags))
3171                         return (FALSE);
3172                 if (!xdr_bitmap4(xdrs, &objp->attrset))
3173                         return (FALSE);
3174                 if (!xdr_int(xdrs,
3175                     (int *)&objp->delegation.delegation_type))
3176                         return (FALSE);
3177                 switch (objp->delegation.delegation_type) {
3178                 case OPEN_DELEGATE_NONE:
3179                         return (TRUE);
3180                 case OPEN_DELEGATE_READ:
3181                         if (!xdr_u_int(xdrs, &objp->delegation.
3182                             open_delegation4_u.read.stateid.seqid))
3183                                 return (FALSE);
3184                         if (!xdr_opaque(xdrs, objp->delegation.
3185                             open_delegation4_u.read.stateid.other,
3186                             NFS4_OTHER_SIZE))
3187                                 return (FALSE);
3188                         if (!xdr_bool(xdrs, &objp->delegation.
3189                             open_delegation4_u.read.recall))
3190                                 return (FALSE);
3191                         return (xdr_nfsace4(xdrs, &objp->delegation.
3192                             open_delegation4_u.read.permissions));
3193                 case OPEN_DELEGATE_WRITE:
3194                         if (!xdr_u_int(xdrs, &objp->delegation.
3195                             open_delegation4_u.write.stateid.seqid))
3196                                 return (FALSE);
3197                         if (!xdr_opaque(xdrs, objp->delegation.
3198                             open_delegation4_u.write.stateid.other,
3199                             NFS4_OTHER_SIZE))
3200                                 return (FALSE);
3201                         if (!xdr_bool(xdrs, &objp->delegation.
3202                             open_delegation4_u.write.recall))
3203                                 return (FALSE);
3204                         if (!xdr_int(xdrs, (int *)&objp->delegation.
3205                             open_delegation4_u.write.space_limit.
3206                             limitby))
3207                                 return (FALSE);
3208                         switch (objp->delegation.
3209                             open_delegation4_u.write.space_limit.
3210                             limitby) {
3211                         case NFS_LIMIT_SIZE:
3212                                 if (!xdr_u_longlong_t(xdrs,
3213                                     (u_longlong_t *)&objp->delegation.
3214                                     open_delegation4_u.write.space_limit.
3215                                     nfs_space_limit4_u.filesize))
3216                                         return (FALSE);
3217                                 break;
3218                         case NFS_LIMIT_BLOCKS:
3219                                 if (!xdr_u_int(xdrs,
3220                                     &objp->delegation.open_delegation4_u.write.
3221                                     space_limit.nfs_space_limit4_u.
3222                                     mod_blocks.num_blocks))
3223                                         return (FALSE);
3224                                 if (!xdr_u_int(xdrs, &objp->delegation.
3225                                     open_delegation4_u.write.space_limit.
3226                                     nfs_space_limit4_u.mod_blocks.
3227                                     bytes_per_block))
3228                                         return (FALSE);
3229                                 break;
3230                         default:
3231                                 return (FALSE);
3232                         }
3233                         return (xdr_nfsace4(xdrs, &objp->delegation.
3234                             open_delegation4_u.write.permissions));
3235                 }
3236                 return (FALSE);
3237         }
3238 
3239         /*
3240          * Optimized free case
3241          */
3242         if (objp->status != NFS4_OK)
3243                 return (TRUE);
3244 
3245         switch (objp->delegation.delegation_type) {
3246         case OPEN_DELEGATE_NONE:
3247                 return (TRUE);
3248         case OPEN_DELEGATE_READ:
3249                 return (xdr_nfsace4(xdrs, &objp->delegation.
3250                     open_delegation4_u.read.permissions));
3251         case OPEN_DELEGATE_WRITE:
3252                 switch (objp->delegation.
3253                     open_delegation4_u.write.space_limit.limitby) {
3254                 case NFS_LIMIT_SIZE:
3255                 case NFS_LIMIT_BLOCKS:
3256                         break;
3257                 default:
3258                         return (FALSE);
3259                 }
3260                 return (xdr_nfsace4(xdrs, &objp->delegation.
3261                     open_delegation4_u.write.permissions));
3262         }
3263         return (FALSE);
3264 }
3265 
3266 static bool_t
3267 xdr_OPEN_CONFIRM4res(XDR *xdrs, OPEN_CONFIRM4res *objp)
3268 {
3269         if (!xdr_int(xdrs, (int32_t *)&objp->status))
3270                 return (FALSE);
3271         if (objp->status != NFS4_OK)
3272                 return (TRUE);
3273         if (!xdr_u_int(xdrs, &objp->open_stateid.seqid))
3274                 return (FALSE);
3275         return (xdr_opaque(xdrs, objp->open_stateid.other, NFS4_OTHER_SIZE));
3276 }
3277 
3278 static bool_t
3279 xdr_OPEN_DOWNGRADE4args(XDR *xdrs, OPEN_DOWNGRADE4args *objp)
3280 {
3281         if (!xdr_u_int(xdrs, &objp->open_stateid.seqid))
3282                 return (FALSE);
3283         if (!xdr_opaque(xdrs, objp->open_stateid.other, NFS4_OTHER_SIZE))
3284                 return (FALSE);
3285         if (!xdr_u_int(xdrs, &objp->seqid))
3286                 return (FALSE);
3287         if (!xdr_u_int(xdrs, &objp->share_access))
3288                 return (FALSE);
3289         return (xdr_u_int(xdrs, &objp->share_deny));
3290 }
3291 
3292 static bool_t
3293 xdr_OPEN_DOWNGRADE4res(XDR *xdrs, OPEN_DOWNGRADE4res *objp)
3294 {
3295         if (!xdr_int(xdrs, (int32_t *)&objp->status))
3296                 return (FALSE);
3297         if (objp->status != NFS4_OK)
3298                 return (TRUE);
3299         if (!xdr_u_int(xdrs, &objp->open_stateid.seqid))
3300                 return (FALSE);
3301         return (xdr_opaque(xdrs, objp->open_stateid.other, NFS4_OTHER_SIZE));
3302 }
3303 
3304 static bool_t
3305 xdr_READ4args(XDR *xdrs, READ4args *objp)
3306 {
3307         rdma_chunkinfo_t rci;
3308         rdma_wlist_conn_info_t rwci;
3309         struct xdr_ops *xops = xdrrdma_xops();
3310 
3311         if (!xdr_u_int(xdrs, &objp->stateid.seqid))
3312                 return (FALSE);
3313         if (!xdr_opaque(xdrs, objp->stateid.other, NFS4_OTHER_SIZE))
3314                 return (FALSE);
3315         if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset))
3316                 return (FALSE);
3317         if (!xdr_u_int(xdrs, &objp->count))
3318                 return (FALSE);
3319 
3320         DTRACE_PROBE1(xdr__i__read4args_buf_len,
3321             int, objp->count);
3322 
3323         objp->wlist = NULL;
3324 
3325         if (xdrs->x_ops == xops && xdrs->x_op == XDR_ENCODE) {
3326                 rci.rci_type = RCI_WRITE_ADDR_CHUNK;
3327                 rci.rci_len = objp->count;
3328                 (void) XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
3329         }
3330 
3331         if (xdrs->x_ops != &xdrrdma_ops || xdrs->x_op == XDR_FREE)
3332                 return (TRUE);
3333 
3334         if (xdrs->x_op == XDR_ENCODE) {
3335                 if (objp->res_uiop != NULL) {
3336                         rci.rci_type = RCI_WRITE_UIO_CHUNK;
3337                         rci.rci_a.rci_uiop = objp->res_uiop;
3338                         rci.rci_len = objp->count;
3339                         rci.rci_clpp = &objp->wlist;
3340                 } else {
3341                         rci.rci_type = RCI_WRITE_ADDR_CHUNK;
3342                         rci.rci_a.rci_addr = objp->res_data_val_alt;
3343                         rci.rci_len = objp->count;
3344                         rci.rci_clpp = &objp->wlist;
3345                 }
3346 
3347                 return (XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci));
3348         }
3349 
3350         /* XDR_DECODE case */
3351         (void) XDR_CONTROL(xdrs, XDR_RDMA_GET_WCINFO, &rwci);
3352         objp->wlist = rwci.rwci_wlist;
3353         objp->conn = rwci.rwci_conn;
3354 
3355         return (TRUE);
3356 }
3357 
3358 static bool_t
3359 xdr_READ4res(XDR *xdrs, READ4res *objp)
3360 {
3361         mblk_t *mp;
3362 
3363         if (xdrs->x_op == XDR_DECODE)
3364                 return (FALSE);
3365 
3366         if (xdrs->x_op == XDR_FREE) {
3367                 /*
3368                  * Optimized free case
3369                  */
3370                 if (objp->status != NFS4_OK)
3371                         return (TRUE);
3372                 if (objp->data_val != NULL)
3373                         kmem_free(objp->data_val, objp->data_len);
3374                 return (TRUE);
3375         }
3376 
3377         /* on with ENCODE paths */
3378         if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->status))
3379                 return (FALSE);
3380         if (objp->status != NFS4_OK)
3381                 return (TRUE);
3382 
3383         if (!XDR_PUTINT32(xdrs, &objp->eof))
3384                 return (FALSE);
3385 
3386         mp = objp->mblk;
3387         if (mp != NULL) {
3388                 if (xdrs->x_ops == &xdrmblk_ops) {
3389                         if (xdrmblk_putmblk(xdrs, mp, objp->data_len)) {
3390                                 objp->mblk = NULL;
3391                                 return (TRUE);
3392                         } else {
3393                                 return (FALSE);
3394                         }
3395                 } else if (mp->b_cont != NULL) {
3396                         /*
3397                          * See xdr_READ3res() for an explanation of why we need
3398                          * to do a pullup here.
3399                          */
3400                         if (pullupmsg(mp, -1) == 0)
3401                                 return (FALSE);
3402                         objp->data_val = (caddr_t)mp->b_rptr;
3403                 }
3404         } else {
3405                 if (xdr_u_int(xdrs, &objp->data_len) == FALSE) {
3406                         return (FALSE);
3407                 }
3408                 /*
3409                  * If read data sent by wlist (RDMA_WRITE), don't do
3410                  * xdr_bytes() below.   RDMA_WRITE transfers the data.
3411                  * Note: this is encode-only because the client code
3412                  * uses xdr_READ4res_clnt to decode results.
3413                  */
3414                 if (objp->wlist) {
3415                         if (objp->data_len != 0) {
3416                                 return (xdrrdma_send_read_data(
3417                                     xdrs, objp->data_len, objp->wlist));
3418                         }
3419                         return (TRUE);
3420                 }
3421         }
3422 
3423         return (xdr_bytes(xdrs, (char **)&objp->data_val,
3424             (uint_t *)&objp->data_len,
3425             objp->data_len));
3426 }
3427 
3428 static bool_t
3429 xdr_READ4res_clnt(XDR *xdrs, READ4res *objp, READ4args *aobjp)
3430 {
3431         mblk_t *mp;
3432         size_t n;
3433         int error;
3434         uint_t size = aobjp->res_maxsize;
3435         count4 ocount;
3436 
3437         if (xdrs->x_op == XDR_ENCODE)
3438                 return (FALSE);
3439 
3440         if (xdrs->x_op == XDR_FREE) {
3441                 /*
3442                  * Optimized free case
3443                  */
3444                 if (objp->status != NFS4_OK)
3445                         return (TRUE);
3446                 if (objp->data_val != NULL)
3447                         kmem_free(objp->data_val, objp->data_len);
3448                 return (TRUE);
3449         }
3450 
3451         if (!XDR_GETINT32(xdrs, (int32_t *)&objp->status))
3452                 return (FALSE);
3453         if (objp->status != NFS4_OK)
3454                 return (TRUE);
3455 
3456         if (!XDR_GETINT32(xdrs, &objp->eof))
3457                 return (FALSE);
3458 
3459 
3460         /*
3461          * This is a special case such that the caller is providing a
3462          * uio as a guide to eventual data location; this is used for
3463          * handling DIRECTIO reads.
3464          */
3465         if (aobjp->res_uiop != NULL) {
3466                 struct uio *uiop = aobjp->res_uiop;
3467                 int32_t *ptr;
3468 
3469                 if (xdrs->x_ops == &xdrmblk_ops) {
3470                         if (!xdrmblk_getmblk(xdrs, &mp, &objp->data_len))
3471                                 return (FALSE);
3472 
3473                         if (objp->data_len == 0)
3474                                 return (TRUE);
3475 
3476                         if (objp->data_len > size)
3477                                 return (FALSE);
3478 
3479                         size = objp->data_len;
3480                         do {
3481                                 n = MIN(size, mp->b_wptr - mp->b_rptr);
3482                                 if ((n = MIN(uiop->uio_resid, n)) != 0) {
3483 
3484                                         error = uiomove((char *)mp->b_rptr, n,
3485                                             UIO_READ, uiop);
3486                                         if (error)
3487                                                 return (FALSE);
3488                                         mp->b_rptr += n;
3489                                         size -= n;
3490                                 }
3491 
3492                                 while (mp && (mp->b_rptr >= mp->b_wptr))
3493                                         mp = mp->b_cont;
3494                         } while (mp && size > 0 && uiop->uio_resid > 0);
3495 
3496                         return (TRUE);
3497                 }
3498 
3499                 if (xdrs->x_ops == &xdrrdma_ops) {
3500                         struct clist *cl;
3501 
3502                         XDR_CONTROL(xdrs, XDR_RDMA_GET_WLIST, &cl);
3503 
3504                         objp->wlist = cl;
3505 
3506                         if (objp->wlist) {
3507                                 /* opaque count */
3508                                 if (!xdr_u_int(xdrs, &ocount)) {
3509                                         objp->wlist = NULL;
3510                                         return (FALSE);
3511                                 }
3512 
3513                                 objp->wlist_len = clist_len(cl);
3514                                 objp->data_len = ocount;
3515 
3516                                 if (objp->wlist_len !=
3517                                     roundup(
3518                                     objp->data_len, BYTES_PER_XDR_UNIT)) {
3519                                         DTRACE_PROBE2(
3520                                             xdr__e__read4resuio_clnt_fail,
3521                                             int, ocount,
3522                                             int, objp->data_len);
3523                                         objp->wlist = NULL;
3524                                         return (FALSE);
3525                                 }
3526 
3527                                 uiop->uio_resid -= objp->data_len;
3528                                 uiop->uio_iov->iov_len -= objp->data_len;
3529                                 uiop->uio_iov->iov_base += objp->data_len;
3530                                 uiop->uio_loffset += objp->data_len;
3531 
3532                                 objp->wlist = NULL;
3533                                 return (TRUE);
3534                         }
3535                 }
3536 
3537                 /*
3538                  * This isn't an xdrmblk stream nor RDMA.
3539                  * Handle the likely case that it can be
3540                  * inlined (ex. xdrmem).
3541                  */
3542                 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->data_len))
3543                         return (FALSE);
3544 
3545                 if (objp->data_len == 0)
3546                         return (TRUE);
3547 
3548                 if (objp->data_len > size)
3549                         return (FALSE);
3550 
3551                 size = (int)objp->data_len;
3552                 if ((ptr = XDR_INLINE(xdrs, size)) != NULL)
3553                         return (uiomove(ptr, size, UIO_READ, uiop) ?
3554                             FALSE : TRUE);
3555 
3556                 /*
3557                  * Handle some other (unlikely) stream type that will
3558                  * need a copy.
3559                  */
3560                 if ((ptr = kmem_alloc(size, KM_NOSLEEP)) == NULL)
3561                         return (FALSE);
3562 
3563                 if (!XDR_GETBYTES(xdrs, (caddr_t)ptr, size)) {
3564                         kmem_free(ptr, size);
3565                         return (FALSE);
3566                 }
3567                 error = uiomove(ptr, size, UIO_READ, uiop);
3568                 kmem_free(ptr, size);
3569 
3570                 return (error ? FALSE : TRUE);
3571         }
3572 
3573         /*
3574          * Check for the other special case of the caller providing
3575          * the target area for the data.
3576          */
3577         if (aobjp->res_data_val_alt == NULL)
3578                 return (FALSE);
3579 
3580         /*
3581          * If read data received via RDMA_WRITE, don't do xdr_bytes().
3582          * RDMA_WRITE already moved the data so decode length of
3583          * RDMA_WRITE.
3584          */
3585         if (xdrs->x_ops == &xdrrdma_ops) {
3586                 struct clist *cl;
3587 
3588                 XDR_CONTROL(xdrs, XDR_RDMA_GET_WLIST, &cl);
3589 
3590                 objp->wlist = cl;
3591 
3592                 /*
3593                  * Data transferred through inline if
3594                  * objp->wlist == NULL
3595                  */
3596                 if (objp->wlist) {
3597                         /* opaque count */
3598                         if (!xdr_u_int(xdrs, &ocount)) {
3599                                 objp->wlist = NULL;
3600                                 return (FALSE);
3601                         }
3602 
3603                         objp->wlist_len = clist_len(cl);
3604                         objp->data_len = ocount;
3605 
3606                         if (objp->wlist_len !=
3607                             roundup(
3608                             objp->data_len, BYTES_PER_XDR_UNIT)) {
3609                                 DTRACE_PROBE2(
3610                                     xdr__e__read4res_clnt_fail,
3611                                     int, ocount,
3612                                     int, objp->data_len);
3613                                 objp->wlist = NULL;
3614                                 return (FALSE);
3615                         }
3616 
3617                         objp->wlist = NULL;
3618                         return (TRUE);
3619                 }
3620         }
3621 
3622         return (xdr_bytes(xdrs, (char **)&aobjp->res_data_val_alt,
3623             (uint_t *)&objp->data_len,
3624             aobjp->res_maxsize));
3625 }
3626 
3627 static bool_t
3628 xdr_READDIR4args(XDR *xdrs, READDIR4args *objp)
3629 {
3630         rdma_chunkinfo_t rci;
3631         struct xdr_ops *xops = xdrrdma_xops();
3632 
3633         if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
3634             xdrs->x_op == XDR_ENCODE) {
3635                 rci.rci_type = RCI_REPLY_CHUNK;
3636                 rci.rci_len = objp->maxcount;
3637                 XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
3638         }
3639 
3640         if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cookie))
3641                 return (FALSE);
3642         if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cookieverf))
3643                 return (FALSE);
3644         if (!xdr_u_int(xdrs, &objp->dircount))
3645                 return (FALSE);
3646         if (!xdr_u_int(xdrs, &objp->maxcount))
3647                 return (FALSE);
3648         return (xdr_bitmap4(xdrs, &objp->attr_request));
3649 }
3650 
3651 bool_t
3652 xdr_READDIR4res(XDR *xdrs, READDIR4res *objp)
3653 {
3654         mblk_t *mp = objp->mblk;
3655         bool_t ret_val;
3656         uint_t flags = 0;
3657 
3658         ASSERT(xdrs->x_op == XDR_ENCODE);
3659 
3660         if (!xdr_int(xdrs, (int32_t *)&objp->status))
3661                 return (FALSE);
3662         if (objp->status != NFS4_OK)
3663                 return (TRUE);
3664         if (mp == NULL)
3665                 return (FALSE);
3666 
3667         if (xdrs->x_ops == &xdrmblk_ops) {
3668                 if (xdrmblk_putmblk_raw(xdrs, mp)
3669                     == TRUE) {
3670                         /* mblk successfully inserted into outgoing chain */
3671                         objp->mblk = NULL;
3672                         return (TRUE);
3673                 }
3674         }
3675 
3676         ASSERT(mp->b_cont == NULL);
3677 
3678         /*
3679          * If transport is RDMA, the pre-encoded m_blk needs to be moved
3680          * without being chunked.
3681          * Check if chunking is enabled for the xdr stream.
3682          * If it is enabled, disable it temporarily for this op,
3683          * then re-enable.
3684          */
3685         XDR_CONTROL(xdrs, XDR_RDMA_GET_FLAGS, &flags);
3686 
3687         if (!(flags & XDR_RDMA_CHUNK))
3688                 return (xdr_opaque(xdrs, (char *)mp->b_rptr, objp->data_len));
3689 
3690         flags &= ~XDR_RDMA_CHUNK;
3691 
3692         (void) XDR_CONTROL(xdrs, XDR_RDMA_SET_FLAGS, &flags);
3693 
3694         ret_val = xdr_opaque(xdrs, (char *)mp->b_rptr, objp->data_len);
3695 
3696         flags |= XDR_RDMA_CHUNK;
3697 
3698         (void) XDR_CONTROL(xdrs, XDR_RDMA_SET_FLAGS, &flags);
3699 
3700         return (ret_val);
3701 }
3702 
3703 static bool_t
3704 xdr_READLINK4res(XDR *xdrs, READLINK4res *objp)
3705 {
3706         if (xdrs->x_op != XDR_FREE) {
3707                 if (!xdr_int(xdrs, (int32_t *)&objp->status))
3708                         return (FALSE);
3709                 if (objp->status != NFS4_OK)
3710                         return (TRUE);
3711                 return (xdr_bytes(xdrs, (char **)&objp->link.linktext4_val,
3712                     (uint_t *)&objp->link.linktext4_len,
3713                     NFS4_MAX_UTF8STRING));
3714         }
3715 
3716         /*
3717          * Optimized free case
3718          */
3719         if (objp->status != NFS4_OK)
3720                 return (TRUE);
3721         if (objp->link.linktext4_val != NULL)
3722                 kmem_free(objp->link.linktext4_val, objp->link.linktext4_len);
3723         return (TRUE);
3724 }
3725 
3726 static bool_t
3727 xdr_REMOVE4res(XDR *xdrs, REMOVE4res *objp)
3728 {
3729         if (!xdr_int(xdrs, (int32_t *)&objp->status))
3730                 return (FALSE);
3731         if (objp->status != NFS4_OK)
3732                 return (TRUE);
3733         if (!xdr_bool(xdrs, &objp->cinfo.atomic))
3734                 return (FALSE);
3735         if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.before))
3736                 return (FALSE);
3737         return (xdr_u_longlong_t(xdrs,
3738             (u_longlong_t *)&objp->cinfo.after));
3739 }
3740 
3741 static bool_t
3742 xdr_RENAME4res(XDR *xdrs, RENAME4res *objp)
3743 {
3744         if (!xdr_int(xdrs, (int32_t *)&objp->status))
3745                 return (FALSE);
3746         if (objp->status != NFS4_OK)
3747                 return (TRUE);
3748         if (!xdr_bool(xdrs, &objp->source_cinfo.atomic))
3749                 return (FALSE);
3750         if (!xdr_u_longlong_t(xdrs,
3751             (u_longlong_t *)&objp->source_cinfo.before))
3752                 return (FALSE);
3753         if (!xdr_u_longlong_t(xdrs,
3754             (u_longlong_t *)&objp->source_cinfo.after))
3755                 return (FALSE);
3756         if (!xdr_bool(xdrs, &objp->target_cinfo.atomic))
3757                 return (FALSE);
3758         if (!xdr_u_longlong_t(xdrs,
3759             (u_longlong_t *)&objp->target_cinfo.before))
3760                 return (FALSE);
3761         return (xdr_u_longlong_t(xdrs,
3762             (u_longlong_t *)&objp->target_cinfo.after));
3763 }
3764 
3765 static bool_t
3766 xdr_secinfo4(XDR *xdrs, secinfo4 *objp)
3767 {
3768         if (xdrs->x_op != XDR_FREE) {
3769                 if (!xdr_u_int(xdrs, &objp->flavor))
3770                         return (FALSE);
3771                 if (objp->flavor != RPCSEC_GSS)
3772                         return (TRUE);
3773                 if (!xdr_bytes(xdrs,
3774                     (char **)&objp->flavor_info.oid.sec_oid4_val,
3775                     (uint_t *)&objp->flavor_info.oid.sec_oid4_len,
3776                     NFS4_MAX_SECOID4))
3777                         return (FALSE);
3778                 if (!xdr_u_int(xdrs, &objp->flavor_info.qop))
3779                         return (FALSE);
3780                 return (xdr_int(xdrs, (int *)&objp->flavor_info.service));
3781         }
3782 
3783         /*
3784          * Optimized free path
3785          */
3786         if (objp->flavor != RPCSEC_GSS)
3787                 return (TRUE);
3788 
3789         if (objp->flavor_info.oid.sec_oid4_val != NULL)
3790                 kmem_free(objp->flavor_info.oid.sec_oid4_val,
3791                     objp->flavor_info.oid.sec_oid4_len);
3792         return (TRUE);
3793 }
3794 
3795 static bool_t
3796 xdr_SETCLIENTID4args(XDR *xdrs, SETCLIENTID4args *objp)
3797 {
3798         if (xdrs->x_op != XDR_FREE) {
3799                 if (!xdr_u_longlong_t(xdrs,
3800                     (u_longlong_t *)&objp->client.verifier))
3801                         return (FALSE);
3802                 if (!xdr_bytes(xdrs, (char **)&objp->client.id_val,
3803                     (uint_t *)&objp->client.id_len, NFS4_OPAQUE_LIMIT))
3804                         return (FALSE);
3805                 if (!xdr_u_int(xdrs, &objp->callback.cb_program))
3806                         return (FALSE);
3807                 if (!xdr_string(xdrs, &objp->callback.cb_location.r_netid,
3808                     NFS4_OPAQUE_LIMIT))
3809                         return (FALSE);
3810                 if (!xdr_string(xdrs, &objp->callback.cb_location.r_addr,
3811                     NFS4_OPAQUE_LIMIT))
3812                         return (FALSE);
3813                 return (xdr_u_int(xdrs, &objp->callback_ident));
3814         }
3815 
3816         /*
3817          * Optimized free case
3818          */
3819         if (objp->client.id_val != NULL)
3820                 kmem_free(objp->client.id_val, objp->client.id_len);
3821         (void) xdr_string(xdrs, &objp->callback.cb_location.r_netid,
3822             NFS4_OPAQUE_LIMIT);
3823         return (xdr_string(xdrs, &objp->callback.cb_location.r_addr,
3824             NFS4_OPAQUE_LIMIT));
3825 }
3826 
3827 static bool_t
3828 xdr_SETCLIENTID4res(XDR *xdrs, SETCLIENTID4res *objp)
3829 {
3830         if (xdrs->x_op != XDR_FREE) {
3831                 if (!xdr_int(xdrs, (int32_t *)&objp->status))
3832                         return (FALSE);
3833                 switch (objp->status) {
3834                 case NFS4_OK:
3835                         if (!xdr_u_longlong_t(xdrs,
3836                             (u_longlong_t *)&objp->SETCLIENTID4res_u.resok4.
3837                             clientid))
3838                                 return (FALSE);
3839                         return (xdr_u_longlong_t(xdrs,
3840                             (u_longlong_t *)&objp->SETCLIENTID4res_u.
3841                             resok4.setclientid_confirm));
3842                 case NFS4ERR_CLID_INUSE:
3843                         if (!xdr_string(xdrs,
3844                             &objp->SETCLIENTID4res_u.client_using.
3845                             r_netid, NFS4_OPAQUE_LIMIT))
3846                                 return (FALSE);
3847                         return (xdr_string(xdrs,
3848                             &objp->SETCLIENTID4res_u.client_using.
3849                             r_addr, NFS4_OPAQUE_LIMIT));
3850                 }
3851                 return (TRUE);
3852         }
3853 
3854         /*
3855          * Optimized free case
3856          */
3857         if (objp->status != NFS4ERR_CLID_INUSE)
3858                 return (TRUE);
3859 
3860         if (!xdr_string(xdrs, &objp->SETCLIENTID4res_u.client_using.r_netid,
3861             NFS4_OPAQUE_LIMIT))
3862                 return (FALSE);
3863         return (xdr_string(xdrs, &objp->SETCLIENTID4res_u.client_using.r_addr,
3864             NFS4_OPAQUE_LIMIT));
3865 }
3866 
3867 static bool_t
3868 xdr_WRITE4args(XDR *xdrs, WRITE4args *objp)
3869 {
3870         if (xdrs->x_op != XDR_FREE) {
3871                 if (!xdr_u_int(xdrs, &objp->stateid.seqid))
3872                         return (FALSE);
3873                 if (!xdr_opaque(xdrs, objp->stateid.other, NFS4_OTHER_SIZE))
3874                         return (FALSE);
3875                 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset))
3876                         return (FALSE);
3877                 if (!xdr_int(xdrs, (int *)&objp->stable))
3878                         return (FALSE);
3879                 if (xdrs->x_op == XDR_DECODE) {
3880                         if (xdrs->x_ops == &xdrmblk_ops) {
3881                                 objp->data_val = NULL;
3882                                 return (xdrmblk_getmblk(xdrs, &objp->mblk,
3883                                     &objp->data_len));
3884                         }
3885                         objp->mblk = NULL;
3886                         if (xdrs->x_ops == &xdrrdmablk_ops) {
3887                                 int retval;
3888                                 retval = xdrrdma_getrdmablk(xdrs,
3889                                     &objp->rlist,
3890                                     &objp->data_len,
3891                                     &objp->conn, NFS4_DATA_LIMIT);
3892                                 if (retval == FALSE)
3893                                         return (FALSE);
3894                                 return (xdrrdma_read_from_client(objp->rlist,
3895                                     &objp->conn, objp->data_len));
3896                         }
3897                 }
3898                 /* Else fall thru for the xdr_bytes(). */
3899                 return (xdr_bytes(xdrs, (char **)&objp->data_val,
3900                     (uint_t *)&objp->data_len, NFS4_DATA_LIMIT));
3901         }
3902         if (objp->rlist != NULL) {
3903                 (void) xdrrdma_free_clist(objp->conn, objp->rlist);
3904                 objp->rlist = NULL;
3905                 objp->data_val = NULL;
3906 
3907                 return (TRUE);
3908         }
3909 
3910         /*
3911          * Optimized free case
3912          */
3913         if (objp->data_val != NULL)
3914                 kmem_free(objp->data_val, objp->data_len);
3915         return (TRUE);
3916 }
3917 
3918 static bool_t
3919 xdr_WRITE4res(XDR *xdrs, WRITE4res *objp)
3920 {
3921         if (!xdr_int(xdrs, (int32_t *)&objp->status))
3922                 return (FALSE);
3923         if (objp->status != NFS4_OK)
3924                 return (TRUE);
3925         if (!xdr_u_int(xdrs, &objp->count))
3926                 return (FALSE);
3927         if (!xdr_int(xdrs, (int *)&objp->committed))
3928                 return (FALSE);
3929         return (xdr_u_longlong_t(xdrs,
3930             (u_longlong_t *)&objp->writeverf));
3931 }
3932 
3933 static bool_t
3934 xdr_snfs_argop4_free(XDR *xdrs, nfs_argop4 **arrayp, int len)
3935 {
3936         int i;
3937         nfs_argop4 *array = *arrayp;
3938 
3939         /*
3940          * Optimized XDR_FREE only args array
3941          */
3942         ASSERT(xdrs->x_op == XDR_FREE);
3943 
3944         /*
3945          * Nothing to do?
3946          */
3947         if (array == NULL)
3948                 return (TRUE);
3949 
3950         for (i = 0; i < len; i++) {
3951                 /*
3952                  * These should be ordered by frequency of use
3953                  */
3954                 switch (array[i].argop) {
3955                 case OP_PUTFH: {
3956                         nfs_fh4 *objp = &array[i].nfs_argop4_u.opputfh.object;
3957 
3958                         if (objp->nfs_fh4_val != NULL) {
3959                                 kmem_free(objp->nfs_fh4_val, objp->nfs_fh4_len);
3960                         }
3961                         continue;
3962                 }
3963                 case OP_GETATTR:
3964                 case OP_GETFH:
3965                         continue;
3966                 case OP_LOOKUP:
3967                         if (array[i].nfs_argop4_u.oplookup.objname.
3968                             utf8string_val != NULL) {
3969                                 kmem_free(array[i].nfs_argop4_u.oplookup.
3970                                     objname.utf8string_val,
3971                                     array[i].nfs_argop4_u.oplookup.
3972                                     objname.utf8string_len);
3973                         }
3974                         continue;
3975                 case OP_OPEN:
3976                         (void) xdr_OPEN4args(xdrs,
3977                             &array[i].nfs_argop4_u.opopen);
3978                         continue;
3979                 case OP_CLOSE:
3980                 case OP_ACCESS:
3981                 case OP_READ:
3982                         continue;
3983                 case OP_WRITE:
3984                         (void) xdr_WRITE4args(xdrs,
3985                             &array[i].nfs_argop4_u.opwrite);
3986                         continue;
3987                 case OP_DELEGRETURN:
3988                 case OP_LOOKUPP:
3989                 case OP_READDIR:
3990                         continue;
3991                 case OP_REMOVE:
3992                         if (array[i].nfs_argop4_u.opremove.target.
3993                             utf8string_val != NULL) {
3994                                 kmem_free(array[i].nfs_argop4_u.opremove.target.
3995                                     utf8string_val,
3996                                     array[i].nfs_argop4_u.opremove.target.
3997                                     utf8string_len);
3998                         }
3999                         continue;
4000                 case OP_COMMIT:
4001                         continue;
4002                 case OP_CREATE:
4003                         (void) xdr_CREATE4args(xdrs,
4004                             &array[i].nfs_argop4_u.opcreate);
4005                         continue;
4006                 case OP_DELEGPURGE:
4007                         continue;
4008                 case OP_LINK:
4009                         if (array[i].nfs_argop4_u.oplink.newname.
4010                             utf8string_val != NULL) {
4011                                 kmem_free(array[i].nfs_argop4_u.oplink.newname.
4012                                     utf8string_val,
4013                                     array[i].nfs_argop4_u.oplink.newname.
4014                                     utf8string_len);
4015                         }
4016                         continue;
4017                 case OP_LOCK:
4018                         (void) xdr_LOCK4args(xdrs,
4019                             &array[i].nfs_argop4_u.oplock);
4020                         continue;
4021                 case OP_LOCKT:
4022                         (void) xdr_LOCKT4args(xdrs,
4023                             &array[i].nfs_argop4_u.oplockt);
4024                         continue;
4025                 case OP_LOCKU:
4026                         continue;
4027                 case OP_NVERIFY:
4028                         (void) xdr_fattr4(xdrs,
4029                             &array[i].nfs_argop4_u.opnverify.obj_attributes);
4030                         continue;
4031                 case OP_OPENATTR:
4032                 case OP_OPEN_CONFIRM:
4033                 case OP_OPEN_DOWNGRADE:
4034                 case OP_PUTPUBFH:
4035                 case OP_PUTROOTFH:
4036                 case OP_READLINK:
4037                         continue;
4038                 case OP_RENAME:
4039                         if (array[i].nfs_argop4_u.oprename.oldname.
4040                             utf8string_val != NULL) {
4041                                 kmem_free(array[i].nfs_argop4_u.oprename.
4042                                     oldname.utf8string_val,
4043                                     array[i].nfs_argop4_u.oprename.
4044                                     oldname.utf8string_len);
4045                         }
4046                         if (array[i].nfs_argop4_u.oprename.newname.
4047                             utf8string_val != NULL) {
4048                                 kmem_free(array[i].nfs_argop4_u.oprename.
4049                                     newname.utf8string_val,
4050                                     array[i].nfs_argop4_u.oprename.
4051                                     newname.utf8string_len);
4052                         }
4053                         continue;
4054                 case OP_RENEW:
4055                 case OP_RESTOREFH:
4056                 case OP_SAVEFH:
4057                         continue;
4058                 case OP_SECINFO:
4059                         if (array[i].nfs_argop4_u.opsecinfo.name.
4060                             utf8string_val != NULL) {
4061                                 kmem_free(array[i].nfs_argop4_u.opsecinfo.name.
4062                                     utf8string_val,
4063                                     array[i].nfs_argop4_u.opsecinfo.name.
4064                                     utf8string_len);
4065                         }
4066                         continue;
4067                 case OP_SETATTR:
4068                         (void) xdr_fattr4(xdrs,
4069                             &array[i].nfs_argop4_u.opsetattr.obj_attributes);
4070                         continue;
4071                 case OP_SETCLIENTID:
4072                         (void) xdr_SETCLIENTID4args(xdrs,
4073                             &array[i].nfs_argop4_u.opsetclientid);
4074                         continue;
4075                 case OP_SETCLIENTID_CONFIRM:
4076                         continue;
4077                 case OP_VERIFY:
4078                         (void) xdr_fattr4(xdrs,
4079                             &array[i].nfs_argop4_u.opverify.obj_attributes);
4080                         continue;
4081                 case OP_RELEASE_LOCKOWNER:
4082                         if (array[i].nfs_argop4_u.oprelease_lockowner.
4083                             lock_owner.owner_val != NULL) {
4084                                 kmem_free(array[i].nfs_argop4_u.
4085                                     oprelease_lockowner.lock_owner.owner_val,
4086                                     array[i].nfs_argop4_u.
4087                                     oprelease_lockowner.lock_owner.owner_len);
4088                         }
4089                         continue;
4090                 case OP_ILLEGAL:
4091                         continue;
4092                 default:
4093                         /*
4094                          * An invalid op is a coding error, it should never
4095                          * have been decoded.
4096                          * Don't error because the caller cannot finish
4097                          * freeing the residual memory of the array.
4098                          */
4099                         continue;
4100                 }
4101         }
4102 
4103         kmem_free(*arrayp, len * sizeof (nfs_argop4));
4104         *arrayp = NULL;
4105         return (TRUE);
4106 }
4107 
4108 static bool_t
4109 xdr_nfs_argop4(XDR *xdrs, nfs_argop4 *objp)
4110 {
4111         rdma_chunkinfo_t rci;
4112         struct xdr_ops *xops = xdrrdma_xops();
4113 
4114         /*
4115          * These should be ordered by frequency of use
4116          */
4117         switch (objp->argop) {
4118         case OP_PUTFH:
4119                 return (xdr_bytes(xdrs,
4120                     (char **)&objp->nfs_argop4_u.opputfh.object.nfs_fh4_val,
4121                     (uint_t *)&objp->nfs_argop4_u.opputfh.object.nfs_fh4_len,
4122                     NFS4_FHSIZE));
4123         case OP_GETATTR:
4124                 /*
4125                  * ACLs can become relatively large ( > 8K) and the default
4126                  * 8K reply chunk of RDMA may not suffice. Check for
4127                  * get ACL bit and if it's RDMA, add a chunk equal the size
4128                  * of the transfer size to the reply chunk list.
4129                  */
4130                 if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
4131                     (xdrs->x_op == XDR_ENCODE) &&
4132                     (objp->nfs_argop4_u.opgetattr.attr_request &
4133                     FATTR4_ACL_MASK)) {
4134                         rci.rci_type = RCI_REPLY_CHUNK;
4135                         rci.rci_len = objp->nfs_argop4_u.opgetattr.mi->mi_tsize;
4136                         XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
4137 
4138                         DTRACE_PROBE1(xdr__i__argop4__getattr, int,
4139                             rci.rci_len);
4140                 }
4141                 return (xdr_bitmap4(xdrs,
4142                     &objp->nfs_argop4_u.opgetattr.attr_request));
4143         case OP_GETFH:
4144                 return (TRUE);
4145         case OP_LOOKUP:
4146                 return (xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.oplookup.
4147                     objname.utf8string_val,
4148                     (uint_t *)&objp->nfs_argop4_u.oplookup.
4149                     objname.utf8string_len,
4150                     NFS4_MAX_UTF8STRING));
4151         case OP_OPEN:
4152                 return (xdr_OPEN4args(xdrs, &objp->nfs_argop4_u.opopen));
4153         case OP_CLOSE:
4154                 return (xdr_CLOSE4args(xdrs, &objp->nfs_argop4_u.opclose));
4155         case OP_ACCESS:
4156                 return (xdr_u_int(xdrs,
4157                     &objp->nfs_argop4_u.opaccess.access));
4158         case OP_READ:
4159                 return (xdr_READ4args(xdrs, &objp->nfs_argop4_u.opread));
4160         case OP_WRITE:
4161                 return (xdr_WRITE4args(xdrs, &objp->nfs_argop4_u.opwrite));
4162         case OP_DELEGRETURN:
4163                 if (!xdr_u_int(xdrs,
4164                     &objp->nfs_argop4_u.opdelegreturn.deleg_stateid.seqid))
4165                         return (FALSE);
4166                 return (xdr_opaque(xdrs,
4167                     objp->nfs_argop4_u.opdelegreturn.deleg_stateid.other,
4168                     NFS4_OTHER_SIZE));
4169         case OP_LOOKUPP:
4170                 return (TRUE);
4171         case OP_READDIR:
4172                 return (xdr_READDIR4args(xdrs, &objp->nfs_argop4_u.opreaddir));
4173         case OP_REMOVE:
4174                 return (xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.opremove.
4175                     target.utf8string_val,
4176                     (uint_t *)&objp->nfs_argop4_u.opremove.
4177                     target.utf8string_len,
4178                     NFS4_MAX_UTF8STRING));
4179         case OP_COMMIT:
4180                 if (!xdr_u_longlong_t(xdrs,
4181                     (u_longlong_t *)&objp->nfs_argop4_u.opcommit.offset))
4182                         return (FALSE);
4183                 return (xdr_u_int(xdrs, &objp->nfs_argop4_u.opcommit.count));
4184         case OP_CREATE:
4185                 return (xdr_CREATE4args(xdrs, &objp->nfs_argop4_u.opcreate));
4186         case OP_DELEGPURGE:
4187                 return (xdr_u_longlong_t(xdrs,
4188                     (u_longlong_t *)&objp->nfs_argop4_u.opdelegpurge.clientid));
4189         case OP_LINK:
4190                 return (xdr_bytes(xdrs,
4191                     (char **)&objp->nfs_argop4_u.oplink.newname.utf8string_val,
4192                     (uint_t *)&objp->nfs_argop4_u.oplink.newname.utf8string_len,
4193                     NFS4_MAX_UTF8STRING));
4194         case OP_LOCK:
4195                 return (xdr_LOCK4args(xdrs, &objp->nfs_argop4_u.oplock));
4196         case OP_LOCKT:
4197                 return (xdr_LOCKT4args(xdrs, &objp->nfs_argop4_u.oplockt));
4198         case OP_LOCKU:
4199                 return (xdr_LOCKU4args(xdrs, &objp->nfs_argop4_u.oplocku));
4200         case OP_NVERIFY:
4201                 return (xdr_fattr4(xdrs,
4202                     &objp->nfs_argop4_u.opnverify.obj_attributes));
4203         case OP_OPENATTR:
4204                 return (xdr_bool(xdrs,
4205                     &objp->nfs_argop4_u.opopenattr.createdir));
4206         case OP_OPEN_CONFIRM:
4207                 if (!xdr_u_int(xdrs, &objp->nfs_argop4_u.opopen_confirm.
4208                     open_stateid.seqid))
4209                         return (FALSE);
4210                 if (!xdr_opaque(xdrs, objp->nfs_argop4_u.opopen_confirm.
4211                     open_stateid.other, NFS4_OTHER_SIZE))
4212                         return (FALSE);
4213                 return (xdr_u_int(xdrs, &objp->nfs_argop4_u.opopen_confirm.
4214                     seqid));
4215         case OP_OPEN_DOWNGRADE:
4216                 return (xdr_OPEN_DOWNGRADE4args(xdrs,
4217                     &objp->nfs_argop4_u.opopen_downgrade));
4218         case OP_PUTPUBFH:
4219                 return (TRUE);
4220         case OP_PUTROOTFH:
4221                 return (TRUE);
4222         case OP_READLINK:
4223                 if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
4224                     xdrs->x_op == XDR_ENCODE) {
4225                         rci.rci_type = RCI_REPLY_CHUNK;
4226                         rci.rci_len = MAXPATHLEN;
4227                         XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
4228                 }
4229                 return (TRUE);
4230         case OP_RENAME:
4231                 if (!xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.oprename.
4232                     oldname.utf8string_val,
4233                     (uint_t *)&objp->nfs_argop4_u.oprename.
4234                     oldname.utf8string_len,
4235                     NFS4_MAX_UTF8STRING))
4236                         return (FALSE);
4237                 return (xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.oprename.
4238                     newname.utf8string_val,
4239                     (uint_t *)&objp->nfs_argop4_u.oprename.
4240                     newname.utf8string_len,
4241                     NFS4_MAX_UTF8STRING));
4242         case OP_RENEW:
4243                 return (xdr_u_longlong_t(xdrs,
4244                     (u_longlong_t *)&objp->nfs_argop4_u.oprenew.clientid));
4245         case OP_RESTOREFH:
4246                 return (TRUE);
4247         case OP_SAVEFH:
4248                 return (TRUE);
4249         case OP_SECINFO:
4250                 return (xdr_bytes(xdrs,
4251                     (char **)&objp->nfs_argop4_u.opsecinfo.name.utf8string_val,
4252                     (uint_t *)&objp->nfs_argop4_u.opsecinfo.name.utf8string_len,
4253                     NFS4_MAX_UTF8STRING));
4254         case OP_SETATTR:
4255                 if (!xdr_u_int(xdrs, &objp->nfs_argop4_u.opsetattr.
4256                     stateid.seqid))
4257                         return (FALSE);
4258                 if (!xdr_opaque(xdrs, objp->nfs_argop4_u.opsetattr.
4259                     stateid.other, NFS4_OTHER_SIZE))
4260                         return (FALSE);
4261                 return (xdr_fattr4(xdrs, &objp->nfs_argop4_u.opsetattr.
4262                     obj_attributes));
4263         case OP_SETCLIENTID:
4264                 return (xdr_SETCLIENTID4args(xdrs,
4265                     &objp->nfs_argop4_u.opsetclientid));
4266         case OP_SETCLIENTID_CONFIRM:
4267                 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->nfs_argop4_u.
4268                     opsetclientid_confirm.clientid))
4269                         return (FALSE);
4270                 return (xdr_u_longlong_t(xdrs,
4271                     (u_longlong_t *)&objp->nfs_argop4_u.
4272                     opsetclientid_confirm.setclientid_confirm));
4273         case OP_VERIFY:
4274                 return (xdr_fattr4(xdrs,
4275                     &objp->nfs_argop4_u.opverify.obj_attributes));
4276         case OP_RELEASE_LOCKOWNER:
4277                 if (!xdr_u_longlong_t(xdrs,
4278                     (u_longlong_t *)&objp->nfs_argop4_u.
4279                     oprelease_lockowner.lock_owner.clientid))
4280                         return (FALSE);
4281                 return (xdr_bytes(xdrs,
4282                     (char **)&objp->nfs_argop4_u.oprelease_lockowner.
4283                     lock_owner.owner_val,
4284                     (uint_t *)&objp->nfs_argop4_u.oprelease_lockowner.
4285                     lock_owner.owner_len, NFS4_OPAQUE_LIMIT));
4286         case OP_ILLEGAL:
4287                 return (TRUE);
4288         }
4289         return (FALSE);
4290 }
4291 
4292 static bool_t
4293 xdr_cnfs_argop4_wrap(XDR *xdrs, nfs_argop4 *objp)
4294 {
4295         if (!xdr_int(xdrs, (int *)&objp->argop))
4296                 return (FALSE);
4297 
4298         return (xdr_nfs_argop4(xdrs, objp));
4299 }
4300 
4301 static bool_t
4302 xdr_snfs_argop4(XDR *xdrs, nfs_argop4 *objp)
4303 {
4304         uint_t pos;
4305         bool_t ret;
4306 
4307         if (xdrs->x_op == XDR_DECODE)
4308                 pos = XDR_GETPOS(xdrs);
4309 
4310         if (!xdr_int(xdrs, (int *)&objp->argop))
4311                 return (FALSE);
4312 
4313         switch (objp->argop) {
4314         case OP_PUTFH:
4315                 ret = xdr_decode_nfs_fh4(xdrs,
4316                     &objp->nfs_argop4_u.opputfh.object);
4317                 break;
4318         default:
4319                 ret = xdr_nfs_argop4(xdrs, objp);
4320                 break;
4321         }
4322 
4323         if (ret && xdrs->x_op == XDR_DECODE)
4324                 objp->opsize = XDR_GETPOS(xdrs) - pos;
4325 
4326         return (ret);
4327 }
4328 
4329 /*
4330  * Client side encode only arg op processing
4331  */
4332 static bool_t
4333 xdr_cnfs_argop4(XDR *xdrs, nfs_argop4 *objp)
4334 {
4335         int len;
4336         int op;
4337         nfs4_sharedfh_t *sfh;
4338         mntinfo4_t *mi;
4339         rpc_inline_t *ptr;
4340 
4341         ASSERT(xdrs->x_op == XDR_ENCODE);
4342 
4343         /*
4344          * Special case the private pseudo ops
4345          */
4346         if (!(objp->argop & SUNW_PRIVATE_OP))
4347                 return (xdr_cnfs_argop4_wrap(xdrs, objp));
4348 
4349         /*
4350          * These should be ordered by frequency of use
4351          */
4352         switch (objp->argop) {
4353         case OP_CPUTFH:
4354                 /*
4355                  * We are passed in the file handle as a nfs4_sharedfh_t *
4356                  * We need to acquire the correct locks so we can copy it out.
4357                  */
4358                 sfh = (nfs4_sharedfh_t *)objp->nfs_argop4_u.opcputfh.sfh;
4359                 mi = sfh->sfh_mi;
4360                 (void) nfs_rw_enter_sig(&mi->mi_fh_lock, RW_READER, 0);
4361 
4362                 len = sfh->sfh_fh.nfs_fh4_len;
4363                 ASSERT(len <= NFS4_FHSIZE);
4364 
4365                 /*
4366                  * First try and inline the copy
4367                  * Must first be a multiple of BYTES_PER_XDR_UNIT
4368                  */
4369                 if (!(len % BYTES_PER_XDR_UNIT) &&
4370                     (ptr = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT + len)) !=
4371                     NULL) {
4372                         IXDR_PUT_U_INT32(ptr, OP_PUTFH);
4373                         IXDR_PUT_U_INT32(ptr, len);
4374                         bcopy(sfh->sfh_fh.nfs_fh4_val, ptr, len);
4375                         nfs_rw_exit(&mi->mi_fh_lock);
4376                         return (TRUE);
4377                 }
4378 
4379                 op = OP_PUTFH;
4380                 if (!XDR_PUTINT32(xdrs, &op)) {
4381                         nfs_rw_exit(&mi->mi_fh_lock);
4382                         return (FALSE);
4383                 }
4384                 if (!XDR_PUTINT32(xdrs, &len)) {
4385                         nfs_rw_exit(&mi->mi_fh_lock);
4386                         return (FALSE);
4387                 }
4388                 if (!(len % BYTES_PER_XDR_UNIT)) {
4389                         if (XDR_PUTBYTES(xdrs, sfh->sfh_fh.nfs_fh4_val, len)) {
4390                                 nfs_rw_exit(&mi->mi_fh_lock);
4391                                 return (TRUE);
4392                         }
4393                 } else if (xdr_opaque(xdrs, sfh->sfh_fh.nfs_fh4_val, len)) {
4394                         nfs_rw_exit(&mi->mi_fh_lock);
4395                         return (TRUE);
4396                 }
4397                 nfs_rw_exit(&mi->mi_fh_lock);
4398                 return (FALSE);
4399         case OP_CLOOKUP:
4400                 len = strlen(objp->nfs_argop4_u.opclookup.cname);
4401                 if (len > NFS4_MAX_UTF8STRING)
4402                         return (FALSE);
4403                 op = OP_LOOKUP;
4404                 if (XDR_PUTINT32(xdrs, &op)) {
4405                         if (XDR_PUTINT32(xdrs, &len)) {
4406                                 return (xdr_opaque(xdrs,
4407                                     objp->nfs_argop4_u.opclookup.cname,
4408                                     len));
4409                         }
4410                 }
4411                 return (FALSE);
4412         case OP_COPEN:
4413                 /* op processing inlined in xdr_OPEN4cargs */
4414                 return (xdr_OPEN4cargs(xdrs, &objp->nfs_argop4_u.opcopen));
4415         case OP_CREMOVE:
4416                 len = strlen(objp->nfs_argop4_u.opcremove.ctarget);
4417                 if (len > NFS4_MAX_UTF8STRING)
4418                         return (FALSE);
4419                 op = OP_REMOVE;
4420                 if (XDR_PUTINT32(xdrs, &op)) {
4421                         if (XDR_PUTINT32(xdrs, &len)) {
4422                                 return (xdr_opaque(xdrs,
4423                                     objp->nfs_argop4_u.opcremove.ctarget,
4424                                     len));
4425                         }
4426                 }
4427                 return (FALSE);
4428         case OP_CCREATE:
4429                 op = OP_CREATE;
4430                 if (!XDR_PUTINT32(xdrs, &op))
4431                         return (FALSE);
4432                 return (xdr_CREATE4cargs(xdrs, &objp->nfs_argop4_u.opccreate));
4433         case OP_CLINK:
4434                 len = strlen(objp->nfs_argop4_u.opclink.cnewname);
4435                 if (len > NFS4_MAX_UTF8STRING)
4436                         return (FALSE);
4437                 op = OP_LINK;
4438                 if (XDR_PUTINT32(xdrs, &op)) {
4439                         if (XDR_PUTINT32(xdrs, &len)) {
4440                                 return (xdr_opaque(xdrs,
4441                                     objp->nfs_argop4_u.opclink.cnewname,
4442                                     len));
4443                         }
4444                 }
4445                 return (FALSE);
4446         case OP_CRENAME:
4447                 len = strlen(objp->nfs_argop4_u.opcrename.coldname);
4448                 if (len > NFS4_MAX_UTF8STRING)
4449                         return (FALSE);
4450                 op = OP_RENAME;
4451                 if (!XDR_PUTINT32(xdrs, &op))
4452                         return (FALSE);
4453                 if (!XDR_PUTINT32(xdrs, &len))
4454                         return (FALSE);
4455                 if (!xdr_opaque(xdrs,
4456                     objp->nfs_argop4_u.opcrename.coldname, len))
4457                         return (FALSE);
4458                 len = strlen(objp->nfs_argop4_u.opcrename.cnewname);
4459                 if (len > NFS4_MAX_UTF8STRING)
4460                         return (FALSE);
4461                 if (XDR_PUTINT32(xdrs, &len)) {
4462                         return (xdr_opaque(xdrs,
4463                             objp->nfs_argop4_u.opcrename.cnewname, len));
4464                 }
4465                 return (FALSE);
4466         case OP_CSECINFO:
4467                 len = strlen(objp->nfs_argop4_u.opcsecinfo.cname);
4468                 if (len > NFS4_MAX_UTF8STRING)
4469                         return (FALSE);
4470                 op = OP_SECINFO;
4471                 if (XDR_PUTINT32(xdrs, &op)) {
4472                         if (XDR_PUTINT32(xdrs, &len)) {
4473                                 return (xdr_opaque(xdrs,
4474                                     objp->nfs_argop4_u.opcsecinfo.cname,
4475                                     len));
4476                         }
4477                 }
4478                 return (FALSE);
4479         }
4480         return (FALSE);
4481 }
4482 
4483 /*
4484  * Note that the len and decode_len will only be different in the case
4485  * of the client's use of this free function.  If the server is
4486  * freeing results, then the len/decode_len will always match.
4487  */
4488 static bool_t
4489 xdr_nfs_resop4_free(XDR *xdrs, nfs_resop4 **arrayp, int len, int decode_len)
4490 {
4491         int i;
4492         nfs_resop4 *array = *arrayp;
4493         nfs4_ga_res_t *gr;
4494 
4495         /*
4496          * Optimized XDR_FREE only results array
4497          */
4498         ASSERT(xdrs->x_op == XDR_FREE);
4499 
4500         if (array == NULL)
4501                 return (TRUE);
4502 
4503         for (i = 0; i < decode_len; i++) {
4504                 /*
4505                  * These should be ordered by frequency of use
4506                  */
4507                 switch (array[i].resop) {
4508                 case OP_PUTFH:
4509                         continue;
4510                 case OP_GETATTR:
4511                         if (array[i].nfs_resop4_u.opgetattr.status != NFS4_OK)
4512                                 continue;
4513 
4514                         gr = &array[i].nfs_resop4_u.opgetattr.ga_res;
4515                         if (gr->n4g_ext_res) {
4516                                 if (gr->n4g_resbmap & FATTR4_FS_LOCATIONS_MASK)
4517                                         (void) xdr_fattr4_fs_locations(xdrs,
4518                                             &gr->n4g_ext_res->n4g_fslocations);
4519                                 kmem_free(gr->n4g_ext_res,
4520                                     sizeof (struct nfs4_ga_ext_res));
4521                         }
4522                         continue;
4523                 case OP_GETFH:
4524                         if (array[i].nfs_resop4_u.opgetfh.status != NFS4_OK)
4525                                 continue;
4526                         if (array[i].nfs_resop4_u.opgetfh.object.nfs_fh4_val !=
4527                             NULL) {
4528                                 kmem_free(array[i].nfs_resop4_u.opgetfh.object.
4529                                     nfs_fh4_val,
4530                                     array[i].nfs_resop4_u.opgetfh.object.
4531                                     nfs_fh4_len);
4532                         }
4533                         continue;
4534                 case OP_LOOKUP:
4535                         continue;
4536                 case OP_OPEN:
4537                         (void) xdr_OPEN4res(xdrs, &array[i].nfs_resop4_u.
4538                             opopen);
4539                         continue;
4540                 case OP_CLOSE:
4541                 case OP_ACCESS:
4542                         continue;
4543                 case OP_READ:
4544                         (void) xdr_READ4res(xdrs,
4545                             &array[i].nfs_resop4_u.opread);
4546                         continue;
4547                 case OP_WRITE:
4548                 case OP_DELEGRETURN:
4549                 case OP_LOOKUPP:
4550                 case OP_READDIR:
4551                 case OP_REMOVE:
4552                 case OP_COMMIT:
4553                 case OP_CREATE:
4554                 case OP_DELEGPURGE:
4555                 case OP_LINK:
4556                         continue;
4557                 case OP_LOCK:
4558                         (void) xdr_LOCK4res(xdrs, &array[i].nfs_resop4_u.
4559                             oplock);
4560                         continue;
4561                 case OP_LOCKT:
4562                         (void) xdr_LOCKT4res(xdrs, &array[i].nfs_resop4_u.
4563                             oplockt);
4564                         continue;
4565                 case OP_LOCKU:
4566                 case OP_NVERIFY:
4567                 case OP_OPENATTR:
4568                 case OP_OPEN_CONFIRM:
4569                 case OP_OPEN_DOWNGRADE:
4570                 case OP_PUTPUBFH:
4571                 case OP_PUTROOTFH:
4572                 case OP_RENAME:
4573                 case OP_RENEW:
4574                 case OP_RESTOREFH:
4575                 case OP_SAVEFH:
4576                         continue;
4577                 case OP_READLINK:
4578                         (void) xdr_READLINK4res(xdrs, &array[i].nfs_resop4_u.
4579                             opreadlink);
4580                         continue;
4581                 case OP_SECINFO:
4582                         (void) xdr_array(xdrs,
4583                             (char **)&array[i].nfs_resop4_u.opsecinfo.
4584                             SECINFO4resok_val,
4585                             (uint_t *)&array[i].nfs_resop4_u.opsecinfo.
4586                             SECINFO4resok_len,
4587                             NFS4_SECINFO_LIMIT, sizeof (secinfo4),
4588                             (xdrproc_t)xdr_secinfo4);
4589                         continue;
4590                 case OP_SETCLIENTID:
4591                         (void) xdr_SETCLIENTID4res(xdrs,
4592                             &array[i].nfs_resop4_u.opsetclientid);
4593                         continue;
4594                 case OP_SETATTR:
4595                 case OP_SETCLIENTID_CONFIRM:
4596                 case OP_VERIFY:
4597                 case OP_RELEASE_LOCKOWNER:
4598                 case OP_ILLEGAL:
4599                         continue;
4600                 default:
4601                         /*
4602                          * An invalid op is a coding error, it should never
4603                          * have been decoded.
4604                          * Don't error because the caller cannot finish
4605                          * freeing the residual memory of the array.
4606                          */
4607                         continue;
4608                 }
4609         }
4610 
4611         kmem_free(*arrayp, len * sizeof (nfs_resop4));
4612         *arrayp = NULL;
4613         return (TRUE);
4614 }
4615 
4616 static bool_t
4617 xdr_snfs_resop4_free(XDR *xdrs, nfs_resop4 **arrayp, int len, int decode_len)
4618 {
4619         return (xdr_nfs_resop4_free(xdrs, arrayp, len, decode_len));
4620 }
4621 
4622 static bool_t
4623 xdr_nfs_resop4(XDR *xdrs, nfs_resop4 *objp)
4624 {
4625         /*
4626          * These should be ordered by frequency of use
4627          */
4628         switch (objp->resop) {
4629         case OP_PUTFH:
4630                 return (xdr_int(xdrs,
4631                     (int32_t *)&objp->nfs_resop4_u.opputfh.status));
4632         case OP_GETATTR:
4633                 if (!xdr_int(xdrs,
4634                     (int32_t *)&objp->nfs_resop4_u.opgetattr.status))
4635                         return (FALSE);
4636                 if (objp->nfs_resop4_u.opgetattr.status != NFS4_OK)
4637                         return (TRUE);
4638                 return (xdr_fattr4(xdrs,
4639                     &objp->nfs_resop4_u.opgetattr.obj_attributes));
4640         case OP_GETFH:
4641                 if (!xdr_int(xdrs,
4642                     (int32_t *)&objp->nfs_resop4_u.opgetfh.status))
4643                         return (FALSE);
4644                 if (objp->nfs_resop4_u.opgetfh.status != NFS4_OK)
4645                         return (TRUE);
4646                 return (xdr_bytes(xdrs,
4647                     (char **)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_val,
4648                     (uint_t *)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_len,
4649                     NFS4_FHSIZE));
4650         case OP_LOOKUP:
4651                 return (xdr_int(xdrs,
4652                     (int32_t *)&objp->nfs_resop4_u.oplookup.status));
4653         case OP_OPEN:
4654                 return (xdr_OPEN4res(xdrs, &objp->nfs_resop4_u.opopen));
4655         case OP_CLOSE:
4656                 return (xdr_CLOSE4res(xdrs, &objp->nfs_resop4_u.opclose));
4657         case OP_ACCESS:
4658                 return (xdr_ACCESS4res(xdrs, &objp->nfs_resop4_u.opaccess));
4659         case OP_READ:
4660                 return (xdr_READ4res(xdrs, &objp->nfs_resop4_u.opread));
4661         case OP_WRITE:
4662                 return (xdr_WRITE4res(xdrs, &objp->nfs_resop4_u.opwrite));
4663         case OP_DELEGRETURN:
4664                 return (xdr_int(xdrs,
4665                     (int32_t *)&objp->nfs_resop4_u.opdelegreturn.status));
4666         case OP_LOOKUPP:
4667                 return (xdr_int(xdrs,
4668                     (int32_t *)&objp->nfs_resop4_u.oplookupp.status));
4669         case OP_READDIR:
4670                 return (xdr_READDIR4res(xdrs, &objp->nfs_resop4_u.opreaddir));
4671         case OP_REMOVE:
4672                 return (xdr_REMOVE4res(xdrs, &objp->nfs_resop4_u.opremove));
4673 
4674         case OP_COMMIT:
4675                 if (!xdr_int(xdrs,
4676                     (int32_t *)&objp->nfs_resop4_u.opcommit.status))
4677                         return (FALSE);
4678                 if (objp->nfs_resop4_u.opcommit.status != NFS4_OK)
4679                         return (TRUE);
4680                 return (xdr_u_longlong_t(xdrs,
4681                     (u_longlong_t *)&objp->nfs_resop4_u.opcommit.
4682                     writeverf));
4683         case OP_CREATE:
4684                 return (xdr_CREATE4res(xdrs, &objp->nfs_resop4_u.opcreate));
4685         case OP_DELEGPURGE:
4686                 return (xdr_int(xdrs,
4687                     (int32_t *)&objp->nfs_resop4_u.opdelegpurge.status));
4688         case OP_LINK:
4689                 return (xdr_LINK4res(xdrs, &objp->nfs_resop4_u.oplink));
4690         case OP_LOCK:
4691                 return (xdr_LOCK4res(xdrs, &objp->nfs_resop4_u.oplock));
4692         case OP_LOCKT:
4693                 return (xdr_LOCKT4res(xdrs, &objp->nfs_resop4_u.oplockt));
4694         case OP_LOCKU:
4695                 if (!xdr_int(xdrs,
4696                     (int32_t *)&objp->nfs_resop4_u.oplocku.status))
4697                         return (FALSE);
4698                 if (objp->nfs_resop4_u.oplocku.status != NFS4_OK)
4699                         return (TRUE);
4700                 if (!xdr_u_int(xdrs,
4701                     &objp->nfs_resop4_u.oplocku.lock_stateid.seqid))
4702                         return (FALSE);
4703                 return (xdr_opaque(xdrs,
4704                     objp->nfs_resop4_u.oplocku.lock_stateid.other,
4705                     NFS4_OTHER_SIZE));
4706         case OP_NVERIFY:
4707                 return (xdr_int(xdrs,
4708                     (int32_t *)&objp->nfs_resop4_u.opnverify.status));
4709         case OP_OPENATTR:
4710                 return (xdr_int(xdrs,
4711                     (int32_t *)&objp->nfs_resop4_u.opopenattr.status));
4712         case OP_OPEN_CONFIRM:
4713                 return (xdr_OPEN_CONFIRM4res(xdrs,
4714                     &objp->nfs_resop4_u.opopen_confirm));
4715         case OP_OPEN_DOWNGRADE:
4716                 return (xdr_OPEN_DOWNGRADE4res(xdrs,
4717                     &objp->nfs_resop4_u.opopen_downgrade));
4718         case OP_PUTPUBFH:
4719                 return (xdr_int(xdrs,
4720                     (int32_t *)&objp->nfs_resop4_u.opputpubfh.status));
4721         case OP_PUTROOTFH:
4722                 return (xdr_int(xdrs,
4723                     (int32_t *)&objp->nfs_resop4_u.opputrootfh.status));
4724         case OP_READLINK:
4725                 return (xdr_READLINK4res(xdrs, &objp->nfs_resop4_u.opreadlink));
4726         case OP_RENAME:
4727                 return (xdr_RENAME4res(xdrs, &objp->nfs_resop4_u.oprename));
4728         case OP_RENEW:
4729                 return (xdr_int(xdrs,
4730                     (int32_t *)&objp->nfs_resop4_u.oprenew.status));
4731         case OP_RESTOREFH:
4732                 return (xdr_int(xdrs,
4733                     (int32_t *)&objp->nfs_resop4_u.oprestorefh.status));
4734         case OP_SAVEFH:
4735                 return (xdr_int(xdrs,
4736                     (int32_t *)&objp->nfs_resop4_u.opsavefh.status));
4737         case OP_SECINFO:
4738                 if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsecinfo.
4739                     status))
4740                         return (FALSE);
4741                 if (objp->nfs_resop4_u.opsecinfo.status != NFS4_OK)
4742                         return (TRUE);
4743                 return (xdr_array(xdrs, (char **)&objp->nfs_resop4_u.opsecinfo.
4744                     SECINFO4resok_val,
4745                     (uint_t *)&objp->nfs_resop4_u.opsecinfo.
4746                     SECINFO4resok_len,
4747                     NFS4_SECINFO_LIMIT, sizeof (secinfo4),
4748                     (xdrproc_t)xdr_secinfo4));
4749         case OP_SETATTR:
4750                 if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsetattr.
4751                     status))
4752                         return (FALSE);
4753                 return (xdr_bitmap4(xdrs,
4754                     &objp->nfs_resop4_u.opsetattr.attrsset));
4755         case OP_SETCLIENTID:
4756                 return (xdr_SETCLIENTID4res(xdrs,
4757                     &objp->nfs_resop4_u.opsetclientid));
4758         case OP_SETCLIENTID_CONFIRM:
4759                 return (xdr_int(xdrs,
4760                     (int32_t *)&objp->nfs_resop4_u.opsetclientid_confirm.
4761                     status));
4762         case OP_VERIFY:
4763                 return (xdr_int(xdrs,
4764                     (int32_t *)&objp->nfs_resop4_u.opverify.status));
4765         case OP_RELEASE_LOCKOWNER:
4766                 return (xdr_int(xdrs,
4767                     (int32_t *)&objp->nfs_resop4_u.oprelease_lockowner.status));
4768         case OP_ILLEGAL:
4769                 return (xdr_int(xdrs,
4770                     (int32_t *)&objp->nfs_resop4_u.opillegal.status));
4771         }
4772         return (FALSE);
4773 }
4774 
4775 static bool_t
4776 xdr_snfs_resop4(XDR *xdrs, nfs_resop4 *objp)
4777 {
4778         uint_t pos;
4779         bool_t ret;
4780 
4781         if (xdrs->x_op == XDR_ENCODE)
4782                 pos = XDR_GETPOS(xdrs);
4783 
4784         if (!xdr_int(xdrs, (int *)&objp->resop))
4785                 return (FALSE);
4786 
4787         switch (objp->resop) {
4788         case OP_GETFH:
4789                 if (!XDR_PUTINT32(xdrs,
4790                     (int32_t *)&objp->nfs_resop4_u.opgetfh.status))
4791                         return (FALSE);
4792                 if (objp->nfs_resop4_u.opgetfh.status != NFS4_OK)
4793                         ret = TRUE;
4794                 else
4795                         ret = xdr_encode_nfs_fh4(xdrs,
4796                             &objp->nfs_resop4_u.opgetfh.object);
4797                 break;
4798         default:
4799                 ret = xdr_nfs_resop4(xdrs, objp);
4800                 break;
4801         }
4802 
4803         if (ret && xdrs->x_op == XDR_ENCODE)
4804                 objp->opsize = XDR_GETPOS(xdrs) - pos;
4805 
4806         return (ret);
4807 }
4808 
4809 static bool_t
4810 xdr_nfs_resop4_clnt(XDR *xdrs, nfs_resop4 *objp, nfs_argop4 *aobjp)
4811 {
4812         if (!xdr_int(xdrs, (int *)&objp->resop))
4813                 return (FALSE);
4814         /*
4815          * These should be ordered by frequency of use
4816          */
4817         switch (objp->resop) {
4818         case OP_PUTFH:
4819                 return (xdr_int(xdrs,
4820                     (int32_t *)&objp->nfs_resop4_u.opputfh.status));
4821         case OP_GETATTR:
4822                 if (!xdr_int(xdrs,
4823                     (int32_t *)&objp->nfs_resop4_u.opgetattr.status))
4824                         return (FALSE);
4825                 if (objp->nfs_resop4_u.opgetattr.status != NFS4_OK)
4826                         return (TRUE);
4827                 return (xdr_ga_res(xdrs,
4828                     (GETATTR4res *)&objp->nfs_resop4_u.opgetattr,
4829                     &aobjp->nfs_argop4_u.opgetattr));
4830         case OP_GETFH:
4831                 if (!xdr_int(xdrs,
4832                     (int32_t *)&objp->nfs_resop4_u.opgetfh.status))
4833                         return (FALSE);
4834                 if (objp->nfs_resop4_u.opgetfh.status != NFS4_OK)
4835                         return (TRUE);
4836                 return (xdr_bytes(xdrs,
4837                     (char **)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_val,
4838                     (uint_t *)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_len,
4839                     NFS4_FHSIZE));
4840         case OP_LOOKUP:
4841                 return (xdr_int(xdrs,
4842                     (int32_t *)&objp->nfs_resop4_u.oplookup.status));
4843         case OP_NVERIFY:
4844                 return (xdr_int(xdrs,
4845                     (int32_t *)&objp->nfs_resop4_u.opnverify.status));
4846         case OP_OPEN:
4847                 return (xdr_OPEN4res(xdrs, &objp->nfs_resop4_u.opopen));
4848         case OP_CLOSE:
4849                 return (xdr_CLOSE4res(xdrs, &objp->nfs_resop4_u.opclose));
4850         case OP_ACCESS:
4851                 return (xdr_ACCESS4res(xdrs, &objp->nfs_resop4_u.opaccess));
4852         case OP_READ:
4853                 return (xdr_READ4res_clnt(xdrs, &objp->nfs_resop4_u.opread,
4854                     &aobjp->nfs_argop4_u.opread));
4855         case OP_WRITE:
4856                 return (xdr_WRITE4res(xdrs, &objp->nfs_resop4_u.opwrite));
4857         case OP_DELEGRETURN:
4858                 return (xdr_int(xdrs,
4859                     (int32_t *)&objp->nfs_resop4_u.opdelegreturn.status));
4860         case OP_LOOKUPP:
4861                 return (xdr_int(xdrs,
4862                     (int32_t *)&objp->nfs_resop4_u.oplookupp.status));
4863         case OP_READDIR:
4864                 return (xdr_READDIR4res_clnt(xdrs,
4865                     &objp->nfs_resop4_u.opreaddirclnt,
4866                     &aobjp->nfs_argop4_u.opreaddir));
4867         case OP_REMOVE:
4868                 return (xdr_REMOVE4res(xdrs, &objp->nfs_resop4_u.opremove));
4869 
4870         case OP_COMMIT:
4871                 if (!xdr_int(xdrs,
4872                     (int32_t *)&objp->nfs_resop4_u.opcommit.status))
4873                         return (FALSE);
4874                 if (objp->nfs_resop4_u.opcommit.status != NFS4_OK)
4875                         return (TRUE);
4876                 return (xdr_u_longlong_t(xdrs,
4877                     (u_longlong_t *)&objp->nfs_resop4_u.opcommit.
4878                     writeverf));
4879         case OP_CREATE:
4880                 return (xdr_CREATE4res(xdrs, &objp->nfs_resop4_u.opcreate));
4881         case OP_DELEGPURGE:
4882                 return (xdr_int(xdrs,
4883                     (int32_t *)&objp->nfs_resop4_u.opdelegpurge.status));
4884         case OP_LINK:
4885                 return (xdr_LINK4res(xdrs, &objp->nfs_resop4_u.oplink));
4886         case OP_LOCK:
4887                 return (xdr_LOCK4res(xdrs, &objp->nfs_resop4_u.oplock));
4888         case OP_LOCKT:
4889                 return (xdr_LOCKT4res(xdrs, &objp->nfs_resop4_u.oplockt));
4890         case OP_LOCKU:
4891                 if (!xdr_int(xdrs,
4892                     (int32_t *)&objp->nfs_resop4_u.oplocku.status))
4893                         return (FALSE);
4894                 if (objp->nfs_resop4_u.oplocku.status != NFS4_OK)
4895                         return (TRUE);
4896                 if (!xdr_u_int(xdrs,
4897                     &objp->nfs_resop4_u.oplocku.lock_stateid.seqid))
4898                         return (FALSE);
4899                 return (xdr_opaque(xdrs,
4900                     objp->nfs_resop4_u.oplocku.lock_stateid.other,
4901                     NFS4_OTHER_SIZE));
4902         case OP_OPENATTR:
4903                 return (xdr_int(xdrs,
4904                     (int32_t *)&objp->nfs_resop4_u.opopenattr.status));
4905         case OP_OPEN_CONFIRM:
4906                 return (xdr_OPEN_CONFIRM4res(xdrs,
4907                     &objp->nfs_resop4_u.opopen_confirm));
4908         case OP_OPEN_DOWNGRADE:
4909                 return (xdr_OPEN_DOWNGRADE4res(xdrs,
4910                     &objp->nfs_resop4_u.opopen_downgrade));
4911         case OP_PUTPUBFH:
4912                 return (xdr_int(xdrs,
4913                     (int32_t *)&objp->nfs_resop4_u.opputpubfh.status));
4914         case OP_PUTROOTFH:
4915                 return (xdr_int(xdrs,
4916                     (int32_t *)&objp->nfs_resop4_u.opputrootfh.status));
4917         case OP_READLINK:
4918                 return (xdr_READLINK4res(xdrs, &objp->nfs_resop4_u.opreadlink));
4919         case OP_RENAME:
4920                 return (xdr_RENAME4res(xdrs, &objp->nfs_resop4_u.oprename));
4921         case OP_RENEW:
4922                 return (xdr_int(xdrs,
4923                     (int32_t *)&objp->nfs_resop4_u.oprenew.status));
4924         case OP_RESTOREFH:
4925                 return (xdr_int(xdrs,
4926                     (int32_t *)&objp->nfs_resop4_u.oprestorefh.status));
4927         case OP_SAVEFH:
4928                 return (xdr_int(xdrs,
4929                     (int32_t *)&objp->nfs_resop4_u.opsavefh.status));
4930         case OP_SECINFO:
4931                 if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsecinfo.
4932                     status))
4933                         return (FALSE);
4934                 if (objp->nfs_resop4_u.opsecinfo.status != NFS4_OK)
4935                         return (TRUE);
4936                 return (xdr_array(xdrs, (char **)&objp->nfs_resop4_u.opsecinfo.
4937                     SECINFO4resok_val,
4938                     (uint_t *)&objp->nfs_resop4_u.opsecinfo.
4939                     SECINFO4resok_len,
4940                     ~0, sizeof (secinfo4), (xdrproc_t)xdr_secinfo4));
4941         case OP_SETATTR:
4942                 if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsetattr.
4943                     status))
4944                         return (FALSE);
4945                 return (xdr_bitmap4(xdrs,
4946                     &objp->nfs_resop4_u.opsetattr.attrsset));
4947         case OP_SETCLIENTID:
4948                 return (xdr_SETCLIENTID4res(xdrs,
4949                     &objp->nfs_resop4_u.opsetclientid));
4950         case OP_SETCLIENTID_CONFIRM:
4951                 return (xdr_int(xdrs,
4952                     (int32_t *)&objp->nfs_resop4_u.opsetclientid_confirm.
4953                     status));
4954         case OP_VERIFY:
4955                 return (xdr_int(xdrs,
4956                     (int32_t *)&objp->nfs_resop4_u.opverify.status));
4957         case OP_RELEASE_LOCKOWNER:
4958                 return (xdr_int(xdrs,
4959                     (int32_t *)&objp->nfs_resop4_u.oprelease_lockowner.status));
4960         case OP_ILLEGAL:
4961                 return (xdr_int(xdrs,
4962                     (int32_t *)&objp->nfs_resop4_u.opillegal.status));
4963         }
4964         return (FALSE);
4965 }
4966 
4967 bool_t
4968 xdr_COMPOUND4args_clnt(XDR *xdrs, COMPOUND4args_clnt *objp)
4969 {
4970         static int32_t twelve = 12;
4971         static int32_t minorversion = NFS4_MINORVERSION;
4972         uint32_t *ctagp;
4973         rpc_inline_t *ptr;
4974         rdma_chunkinfo_t rci;
4975         struct xdr_ops *xops = xdrrdma_xops();
4976 
4977         /*
4978          * XDR_ENCODE only
4979          */
4980         if (xdrs->x_op == XDR_FREE)
4981                 return (TRUE);
4982         if (xdrs->x_op == XDR_DECODE)
4983                 return (FALSE);
4984 
4985         ctagp = (uint32_t *)&nfs4_ctags[objp->ctag].ct_tag;
4986 
4987         if ((ptr = XDR_INLINE(xdrs, 5 * BYTES_PER_XDR_UNIT)) != NULL) {
4988                 /*
4989                  * Efficiently encode fixed length tags, could be longlongs
4990                  * but 8 byte XDR alignment not assured
4991                  */
4992                 IXDR_PUT_U_INT32(ptr, 12);
4993                 IXDR_PUT_U_INT32(ptr, ctagp[0]);
4994                 IXDR_PUT_U_INT32(ptr, ctagp[1]);
4995                 IXDR_PUT_U_INT32(ptr, ctagp[2]);
4996 
4997                 /*
4998                  * Fixed minor version for now
4999                  */
5000                 IXDR_PUT_U_INT32(ptr, NFS4_MINORVERSION);
5001         } else {
5002                 if (!XDR_PUTINT32(xdrs, &twelve))
5003                         return (FALSE);
5004                 if (!XDR_PUTINT32(xdrs, (int32_t *)&ctagp[0]))
5005                         return (FALSE);
5006                 if (!XDR_PUTINT32(xdrs, (int32_t *)&ctagp[1]))
5007                         return (FALSE);
5008                 if (!XDR_PUTINT32(xdrs, (int32_t *)&ctagp[2]))
5009                         return (FALSE);
5010                 if (!XDR_PUTINT32(xdrs, (int32_t *)&minorversion))
5011                         return (FALSE);
5012         }
5013         if (xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) {
5014                 rci.rci_type = RCI_REPLY_CHUNK;
5015                 rci.rci_len = MAXPATHLEN * 2;
5016                 XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
5017         }
5018 
5019         return (xdr_array(xdrs, (char **)&objp->array,
5020             (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
5021             sizeof (nfs_argop4), (xdrproc_t)xdr_cnfs_argop4));
5022 }
5023 
5024 bool_t
5025 xdr_COMPOUND4args_srv(XDR *xdrs, COMPOUND4args *objp)
5026 {
5027         if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val,
5028             (uint_t *)&objp->tag.utf8string_len,
5029             NFS4_MAX_UTF8STRING))
5030                 return (FALSE);
5031         if (!xdr_u_int(xdrs, &objp->minorversion))
5032                 return (FALSE);
5033         if (xdrs->x_op != XDR_FREE)
5034                 return (xdr_array(xdrs, (char **)&objp->array,
5035                     (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
5036                     sizeof (nfs_argop4), (xdrproc_t)xdr_snfs_argop4));
5037 
5038         return (xdr_snfs_argop4_free(xdrs, &objp->array, objp->array_len));
5039 }
5040 
5041 bool_t
5042 xdr_COMPOUND4res_clnt(XDR *xdrs, COMPOUND4res_clnt *objp)
5043 {
5044         uint32_t len;
5045         int32_t *ptr;
5046         nfs_argop4 *argop;
5047         nfs_resop4 *resop;
5048 
5049         /*
5050          * No XDR_ENCODE
5051          */
5052         if (xdrs->x_op == XDR_ENCODE)
5053                 return (FALSE);
5054 
5055         if (xdrs->x_op != XDR_FREE) {
5056                 if ((ptr = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT)) != NULL) {
5057                         objp->status = IXDR_GET_U_INT32(ptr);
5058                         len = IXDR_GET_U_INT32(ptr);
5059                 } else {
5060                         if (!xdr_int(xdrs, (int32_t *)&objp->status))
5061                                 return (FALSE);
5062                         if (!xdr_u_int(xdrs, (uint32_t *)&len))
5063                                 return (FALSE);
5064                 }
5065                 if (len > NFS4_MAX_UTF8STRING)
5066                         return (FALSE);
5067                 /*
5068                  * Ignore the tag
5069                  */
5070                 if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &len))
5071                         return (FALSE);
5072 
5073                 if (!xdr_int(xdrs, (int32_t *)&objp->array_len))
5074                         return (FALSE);
5075 
5076                 if (objp->array_len > objp->argsp->array_len)
5077                         return (FALSE);
5078 
5079                 if (objp->status == NFS4_OK &&
5080                     objp->array_len != objp->argsp->array_len)
5081                         return (FALSE);
5082 
5083                 /* Alloc the results array */
5084                 argop = objp->argsp->array;
5085                 len = objp->array_len * sizeof (nfs_resop4);
5086                 objp->decode_len = 0;
5087                 objp->array = resop = kmem_zalloc(len, KM_SLEEP);
5088 
5089                 for (len = 0; len < objp->array_len;
5090                     len++, resop++, argop++, objp->decode_len++) {
5091                         if (!xdr_nfs_resop4_clnt(xdrs, resop, argop)) {
5092                                 /*
5093                                  * Make sure to free anything that may
5094                                  * have been allocated along the way.
5095                                  */
5096                                 xdrs->x_op = XDR_FREE;
5097                                 (void) xdr_nfs_resop4_free(xdrs, &objp->array,
5098                                     objp->array_len,
5099                                     objp->decode_len);
5100                                 return (FALSE);
5101                         }
5102                 }
5103                 return (TRUE);
5104         }
5105         return (xdr_nfs_resop4_free(xdrs, &objp->array,
5106             objp->array_len, objp->decode_len));
5107 }
5108 
5109 bool_t
5110 xdr_COMPOUND4res_srv(XDR *xdrs, COMPOUND4res *objp)
5111 {
5112         if (!xdr_int(xdrs, (int32_t *)&objp->status))
5113                 return (FALSE);
5114         if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val,
5115             (uint_t *)&objp->tag.utf8string_len,
5116             NFS4_MAX_UTF8STRING))
5117                 return (FALSE);
5118 
5119         if (xdrs->x_op != XDR_FREE)
5120                 return (xdr_array(xdrs, (char **)&objp->array,
5121                     (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
5122                     sizeof (nfs_resop4), (xdrproc_t)xdr_snfs_resop4));
5123 
5124         return (xdr_snfs_resop4_free(xdrs, &objp->array,
5125             objp->array_len, objp->array_len));
5126 }
5127 
5128 /*
5129  * NFS server side callback, initiating the callback request so it
5130  * is the RPC client. Must convert from server's internal filehandle
5131  * format to wire format.
5132  */
5133 static bool_t
5134 xdr_snfs_cb_argop4(XDR *xdrs, nfs_cb_argop4 *objp)
5135 {
5136         CB_GETATTR4args *gargs;
5137         CB_RECALL4args *rargs;
5138 
5139         ASSERT(xdrs->x_op == XDR_ENCODE);
5140 
5141         if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->argop))
5142                 return (FALSE);
5143 
5144         switch (objp->argop) {
5145         case OP_CB_GETATTR:
5146                 gargs = &objp->nfs_cb_argop4_u.opcbgetattr;
5147 
5148                 if (!xdr_encode_nfs_fh4(xdrs, &gargs->fh))
5149                         return (FALSE);
5150                 return (xdr_bitmap4(xdrs, &gargs->attr_request));
5151         case OP_CB_RECALL:
5152                 rargs = &objp->nfs_cb_argop4_u.opcbrecall;
5153 
5154                 if (!XDR_PUTINT32(xdrs, (int32_t *)&rargs->stateid.seqid))
5155                         return (FALSE);
5156                 if (!xdr_opaque(xdrs, rargs->stateid.other, NFS4_OTHER_SIZE))
5157                         return (FALSE);
5158                 if (!XDR_PUTINT32(xdrs, (int32_t *)&rargs->truncate))
5159                         return (FALSE);
5160                 return (xdr_encode_nfs_fh4(xdrs, &rargs->fh));
5161         case OP_CB_ILLEGAL:
5162                 return (TRUE);
5163         }
5164         return (FALSE);
5165 }
5166 
5167 /*
5168  * NFS client side callback, receiving the callback request so it
5169  * is the RPC server. Must treat the file handles as opaque.
5170  */
5171 static bool_t
5172 xdr_cnfs_cb_argop4(XDR *xdrs, nfs_cb_argop4 *objp)
5173 {
5174         CB_GETATTR4args *gargs;
5175         CB_RECALL4args *rargs;
5176 
5177         ASSERT(xdrs->x_op != XDR_ENCODE);
5178 
5179         if (!xdr_u_int(xdrs, &objp->argop))
5180                 return (FALSE);
5181         switch (objp->argop) {
5182         case OP_CB_GETATTR:
5183                 gargs = &objp->nfs_cb_argop4_u.opcbgetattr;
5184 
5185                 if (!xdr_bytes(xdrs, (char **)&gargs->fh.nfs_fh4_val,
5186                     (uint_t *)&gargs->fh.nfs_fh4_len, NFS4_FHSIZE))
5187                         return (FALSE);
5188                 return (xdr_bitmap4(xdrs, &gargs->attr_request));
5189         case OP_CB_RECALL:
5190                 rargs = &objp->nfs_cb_argop4_u.opcbrecall;
5191 
5192                 if (!xdr_u_int(xdrs, &rargs->stateid.seqid))
5193                         return (FALSE);
5194                 if (!xdr_opaque(xdrs, rargs->stateid.other, NFS4_OTHER_SIZE))
5195                         return (FALSE);
5196                 if (!xdr_bool(xdrs, &rargs->truncate))
5197                         return (FALSE);
5198                 return (xdr_bytes(xdrs, (char **)&rargs->fh.nfs_fh4_val,
5199                     (uint_t *)&rargs->fh.nfs_fh4_len, NFS4_FHSIZE));
5200         case OP_CB_ILLEGAL:
5201                 return (TRUE);
5202         }
5203         return (FALSE);
5204 }
5205 
5206 static bool_t
5207 xdr_nfs_cb_resop4(XDR *xdrs, nfs_cb_resop4 *objp)
5208 {
5209         if (!xdr_u_int(xdrs, &objp->resop))
5210                 return (FALSE);
5211         switch (objp->resop) {
5212         case OP_CB_GETATTR:
5213                 if (!xdr_int(xdrs,
5214                     (int32_t *)&objp->nfs_cb_resop4_u.opcbgetattr.
5215                     status))
5216                         return (FALSE);
5217                 if (objp->nfs_cb_resop4_u.opcbgetattr.status != NFS4_OK)
5218                         return (TRUE);
5219                 return (xdr_fattr4(xdrs,
5220                     &objp->nfs_cb_resop4_u.opcbgetattr.
5221                     obj_attributes));
5222         case OP_CB_RECALL:
5223                 return (xdr_int(xdrs,
5224                     (int32_t *)&objp->nfs_cb_resop4_u.opcbrecall.status));
5225         case OP_CB_ILLEGAL:
5226                 return (xdr_int(xdrs,
5227                     (int32_t *)&objp->nfs_cb_resop4_u.opcbillegal.status));
5228         }
5229         return (FALSE);
5230 }
5231 
5232 /*
5233  * The NFS client side callback, RPC server
5234  */
5235 bool_t
5236 xdr_CB_COMPOUND4args_clnt(XDR *xdrs, CB_COMPOUND4args *objp)
5237 {
5238         if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val,
5239             (uint_t *)&objp->tag.utf8string_len,
5240             NFS4_MAX_UTF8STRING))
5241                 return (FALSE);
5242         if (!xdr_u_int(xdrs, &objp->minorversion))
5243                 return (FALSE);
5244         if (!xdr_u_int(xdrs, &objp->callback_ident))
5245                 return (FALSE);
5246         return (xdr_array(xdrs, (char **)&objp->array,
5247             (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
5248             sizeof (nfs_cb_argop4), (xdrproc_t)xdr_cnfs_cb_argop4));
5249 }
5250 
5251 /*
5252  * The NFS server side callback, RPC client
5253  */
5254 bool_t
5255 xdr_CB_COMPOUND4args_srv(XDR *xdrs, CB_COMPOUND4args *objp)
5256 {
5257         if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val,
5258             (uint_t *)&objp->tag.utf8string_len,
5259             NFS4_MAX_UTF8STRING))
5260                 return (FALSE);
5261         if (!xdr_u_int(xdrs, &objp->minorversion))
5262                 return (FALSE);
5263         if (!xdr_u_int(xdrs, &objp->callback_ident))
5264                 return (FALSE);
5265         return (xdr_array(xdrs, (char **)&objp->array,
5266             (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
5267             sizeof (nfs_cb_argop4), (xdrproc_t)xdr_snfs_cb_argop4));
5268 }
5269 
5270 bool_t
5271 xdr_CB_COMPOUND4res(XDR *xdrs, CB_COMPOUND4res *objp)
5272 {
5273         if (!xdr_int(xdrs, (int32_t *)&objp->status))
5274                 return (FALSE);
5275         if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val,
5276             (uint_t *)&objp->tag.utf8string_len,
5277             NFS4_MAX_UTF8STRING))
5278                 return (FALSE);
5279         return (xdr_array(xdrs, (char **)&objp->array,
5280             (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
5281             sizeof (nfs_cb_resop4), (xdrproc_t)xdr_nfs_cb_resop4));
5282 }