1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
  27 /* All Rights Reserved */
  28 
  29 #include <sys/param.h>
  30 #include <sys/types.h>
  31 #include <sys/systm.h>
  32 #include <sys/user.h>
  33 #include <sys/vnode.h>
  34 #include <sys/file.h>
  35 #include <sys/dirent.h>
  36 #include <sys/vfs.h>
  37 #include <sys/stream.h>
  38 #include <sys/strsubr.h>
  39 #include <sys/debug.h>
  40 #include <sys/t_lock.h>
  41 #include <sys/sdt.h>
  42 
  43 #include <rpc/types.h>
  44 #include <rpc/xdr.h>
  45 
  46 #include <nfs/nfs.h>
  47 
  48 #include <vm/hat.h>
  49 #include <vm/as.h>
  50 #include <vm/seg.h>
  51 #include <vm/seg_map.h>
  52 #include <vm/seg_kmem.h>
  53 
  54 static bool_t xdr_fastshorten(XDR *, uint_t);
  55 
  56 /*
  57  * These are the XDR routines used to serialize and deserialize
  58  * the various structures passed as parameters accross the network
  59  * between NFS clients and servers.
  60  */
  61 
  62 /*
  63  * File access handle
  64  * The fhandle struct is treated a opaque data on the wire
  65  */
  66 bool_t
  67 xdr_fhandle(XDR *xdrs, fhandle_t *fh)
  68 {
  69         int32_t *ptr;
  70         int32_t *fhp;
  71 
  72         if (xdrs->x_op == XDR_FREE)
  73                 return (TRUE);
  74 
  75         ptr = XDR_INLINE(xdrs, RNDUP(sizeof (fhandle_t)));
  76         if (ptr != NULL) {
  77                 fhp = (int32_t *)fh;
  78                 if (xdrs->x_op == XDR_DECODE) {
  79                         *fhp++ = *ptr++;
  80                         *fhp++ = *ptr++;
  81                         *fhp++ = *ptr++;
  82                         *fhp++ = *ptr++;
  83                         *fhp++ = *ptr++;
  84                         *fhp++ = *ptr++;
  85                         *fhp++ = *ptr++;
  86                         *fhp = *ptr;
  87                 } else {
  88                         *ptr++ = *fhp++;
  89                         *ptr++ = *fhp++;
  90                         *ptr++ = *fhp++;
  91                         *ptr++ = *fhp++;
  92                         *ptr++ = *fhp++;
  93                         *ptr++ = *fhp++;
  94                         *ptr++ = *fhp++;
  95                         *ptr = *fhp;
  96                 }
  97                 return (TRUE);
  98         }
  99 
 100         return (xdr_opaque(xdrs, (caddr_t)fh, NFS_FHSIZE));
 101 }
 102 
 103 bool_t
 104 xdr_fastfhandle(XDR *xdrs, fhandle_t **fh)
 105 {
 106         int32_t *ptr;
 107 
 108         if (xdrs->x_op != XDR_DECODE)
 109                 return (FALSE);
 110 
 111         ptr = XDR_INLINE(xdrs, RNDUP(sizeof (fhandle_t)));
 112         if (ptr != NULL) {
 113                 *fh = (fhandle_t *)ptr;
 114                 return (TRUE);
 115         }
 116 
 117         return (FALSE);
 118 }
 119 
 120 /*
 121  * Arguments to remote write and writecache
 122  */
 123 bool_t
 124 xdr_writeargs(XDR *xdrs, struct nfswriteargs *wa)
 125 {
 126         int32_t *ptr;
 127         int32_t *fhp;
 128 
 129         switch (xdrs->x_op) {
 130         case XDR_DECODE:
 131                 wa->wa_args = &wa->wa_args_buf;
 132                 ptr = XDR_INLINE(xdrs, RNDUP(sizeof (fhandle_t)) +
 133                     3 * BYTES_PER_XDR_UNIT);
 134                 if (ptr != NULL) {
 135                         fhp = (int32_t *)&wa->wa_fhandle;
 136                         *fhp++ = *ptr++;
 137                         *fhp++ = *ptr++;
 138                         *fhp++ = *ptr++;
 139                         *fhp++ = *ptr++;
 140                         *fhp++ = *ptr++;
 141                         *fhp++ = *ptr++;
 142                         *fhp++ = *ptr++;
 143                         *fhp = *ptr++;
 144                         wa->wa_begoff = IXDR_GET_U_INT32(ptr);
 145                         wa->wa_offset = IXDR_GET_U_INT32(ptr);
 146                         wa->wa_totcount = IXDR_GET_U_INT32(ptr);
 147                         wa->wa_mblk = NULL;
 148                         wa->wa_data = NULL;
 149                         wa->wa_rlist = NULL;
 150                         wa->wa_conn = NULL;
 151                         if (xdrs->x_ops == &xdrmblk_ops) {
 152                                 return (xdrmblk_getmblk(xdrs, &wa->wa_mblk,
 153                                     &wa->wa_count));
 154                         } else {
 155                                 if (xdrs->x_ops == &xdrrdmablk_ops) {
 156                                         if (xdrrdma_getrdmablk(xdrs,
 157                                             &wa->wa_rlist,
 158                                             &wa->wa_count,
 159                                             &wa->wa_conn,
 160                                             NFS_MAXDATA) == TRUE)
 161                                         return (xdrrdma_read_from_client(
 162                                             wa->wa_rlist,
 163                                             &wa->wa_conn,
 164                                             wa->wa_count));
 165 
 166                                         wa->wa_rlist = NULL;
 167                                         wa->wa_conn = NULL;
 168                                 }
 169                         }
 170 
 171                         /*
 172                          * It is just as efficient to xdr_bytes
 173                          * an array of unknown length as to inline copy it.
 174                          */
 175                         return (xdr_bytes(xdrs, &wa->wa_data,
 176                             &wa->wa_count, NFS_MAXDATA));
 177                 }
 178                 if (xdr_fhandle(xdrs, &wa->wa_fhandle) &&
 179                     xdr_u_int(xdrs, &wa->wa_begoff) &&
 180                     xdr_u_int(xdrs, &wa->wa_offset) &&
 181                     xdr_u_int(xdrs, &wa->wa_totcount)) {
 182                         /* deal with the variety of data transfer types */
 183 
 184                         wa->wa_mblk = NULL;
 185                         wa->wa_data = NULL;
 186                         wa->wa_rlist = NULL;
 187                         wa->wa_conn = NULL;
 188 
 189                         if (xdrs->x_ops == &xdrmblk_ops) {
 190                                 if (xdrmblk_getmblk(xdrs, &wa->wa_mblk,
 191                                     &wa->wa_count) == TRUE)
 192                                         return (TRUE);
 193                         } else {
 194                                 if (xdrs->x_ops == &xdrrdmablk_ops) {
 195                                         if (xdrrdma_getrdmablk(xdrs,
 196                                             &wa->wa_rlist,
 197                                             &wa->wa_count,
 198                                             &wa->wa_conn,
 199                                             NFS_MAXDATA) == TRUE)
 200                                         return (xdrrdma_read_from_client(
 201                                             wa->wa_rlist,
 202                                             &wa->wa_conn,
 203                                             wa->wa_count));
 204 
 205                                         wa->wa_rlist = NULL;
 206                                         wa->wa_conn = NULL;
 207                                 }
 208                         }
 209                         return (xdr_bytes(xdrs, &wa->wa_data,
 210                             &wa->wa_count, NFS_MAXDATA));
 211                 }
 212                 return (FALSE);
 213         case XDR_ENCODE:
 214                 ptr = XDR_INLINE(xdrs, RNDUP(sizeof (fhandle_t)) +
 215                     3 * BYTES_PER_XDR_UNIT);
 216                 if (ptr != NULL) {
 217                         fhp = (int32_t *)&wa->wa_fhandle;
 218                         *ptr++ = *fhp++;
 219                         *ptr++ = *fhp++;
 220                         *ptr++ = *fhp++;
 221                         *ptr++ = *fhp++;
 222                         *ptr++ = *fhp++;
 223                         *ptr++ = *fhp++;
 224                         *ptr++ = *fhp++;
 225                         *ptr++ = *fhp;
 226                         IXDR_PUT_U_INT32(ptr, wa->wa_begoff);
 227                         IXDR_PUT_U_INT32(ptr, wa->wa_offset);
 228                         IXDR_PUT_U_INT32(ptr, wa->wa_totcount);
 229                 } else {
 230                         if (!(xdr_fhandle(xdrs, &wa->wa_fhandle) &&
 231                             xdr_u_int(xdrs, &wa->wa_begoff) &&
 232                             xdr_u_int(xdrs, &wa->wa_offset) &&
 233                             xdr_u_int(xdrs, &wa->wa_totcount)))
 234                                 return (FALSE);
 235                 }
 236 
 237                 return (xdr_bytes(xdrs, &wa->wa_data, &wa->wa_count,
 238                     NFS_MAXDATA));
 239         case XDR_FREE:
 240                 if (wa->wa_rlist) {
 241                         (void) xdrrdma_free_clist(wa->wa_conn, wa->wa_rlist);
 242                         wa->wa_rlist = NULL;
 243                 }
 244 
 245                 if (wa->wa_data != NULL) {
 246                         kmem_free(wa->wa_data, wa->wa_count);
 247                         wa->wa_data = NULL;
 248                 }
 249                 return (TRUE);
 250         }
 251         return (FALSE);
 252 }
 253 
 254 
 255 /*
 256  * File attributes
 257  */
 258 bool_t
 259 xdr_fattr(XDR *xdrs, struct nfsfattr *na)
 260 {
 261         int32_t *ptr;
 262 
 263         if (xdrs->x_op == XDR_FREE)
 264                 return (TRUE);
 265 
 266         ptr = XDR_INLINE(xdrs, 17 * BYTES_PER_XDR_UNIT);
 267         if (ptr != NULL) {
 268                 if (xdrs->x_op == XDR_DECODE) {
 269                         na->na_type = IXDR_GET_ENUM(ptr, enum nfsftype);
 270                         na->na_mode = IXDR_GET_U_INT32(ptr);
 271                         na->na_nlink = IXDR_GET_U_INT32(ptr);
 272                         na->na_uid = IXDR_GET_U_INT32(ptr);
 273                         na->na_gid = IXDR_GET_U_INT32(ptr);
 274                         na->na_size = IXDR_GET_U_INT32(ptr);
 275                         na->na_blocksize = IXDR_GET_U_INT32(ptr);
 276                         na->na_rdev = IXDR_GET_U_INT32(ptr);
 277                         na->na_blocks = IXDR_GET_U_INT32(ptr);
 278                         na->na_fsid = IXDR_GET_U_INT32(ptr);
 279                         na->na_nodeid = IXDR_GET_U_INT32(ptr);
 280                         na->na_atime.tv_sec = IXDR_GET_U_INT32(ptr);
 281                         na->na_atime.tv_usec = IXDR_GET_U_INT32(ptr);
 282                         na->na_mtime.tv_sec = IXDR_GET_U_INT32(ptr);
 283                         na->na_mtime.tv_usec = IXDR_GET_U_INT32(ptr);
 284                         na->na_ctime.tv_sec = IXDR_GET_U_INT32(ptr);
 285                         na->na_ctime.tv_usec = IXDR_GET_U_INT32(ptr);
 286                 } else {
 287                         IXDR_PUT_ENUM(ptr, na->na_type);
 288                         IXDR_PUT_U_INT32(ptr, na->na_mode);
 289                         IXDR_PUT_U_INT32(ptr, na->na_nlink);
 290                         IXDR_PUT_U_INT32(ptr, na->na_uid);
 291                         IXDR_PUT_U_INT32(ptr, na->na_gid);
 292                         IXDR_PUT_U_INT32(ptr, na->na_size);
 293                         IXDR_PUT_U_INT32(ptr, na->na_blocksize);
 294                         IXDR_PUT_U_INT32(ptr, na->na_rdev);
 295                         IXDR_PUT_U_INT32(ptr, na->na_blocks);
 296                         IXDR_PUT_U_INT32(ptr, na->na_fsid);
 297                         IXDR_PUT_U_INT32(ptr, na->na_nodeid);
 298                         IXDR_PUT_U_INT32(ptr, na->na_atime.tv_sec);
 299                         IXDR_PUT_U_INT32(ptr, na->na_atime.tv_usec);
 300                         IXDR_PUT_U_INT32(ptr, na->na_mtime.tv_sec);
 301                         IXDR_PUT_U_INT32(ptr, na->na_mtime.tv_usec);
 302                         IXDR_PUT_U_INT32(ptr, na->na_ctime.tv_sec);
 303                         IXDR_PUT_U_INT32(ptr, na->na_ctime.tv_usec);
 304                 }
 305                 return (TRUE);
 306         }
 307 
 308         if (xdr_enum(xdrs, (enum_t *)&na->na_type) &&
 309             xdr_u_int(xdrs, &na->na_mode) &&
 310             xdr_u_int(xdrs, &na->na_nlink) &&
 311             xdr_u_int(xdrs, &na->na_uid) &&
 312             xdr_u_int(xdrs, &na->na_gid) &&
 313             xdr_u_int(xdrs, &na->na_size) &&
 314             xdr_u_int(xdrs, &na->na_blocksize) &&
 315             xdr_u_int(xdrs, &na->na_rdev) &&
 316             xdr_u_int(xdrs, &na->na_blocks) &&
 317             xdr_u_int(xdrs, &na->na_fsid) &&
 318             xdr_u_int(xdrs, &na->na_nodeid) &&
 319             xdr_nfs2_timeval(xdrs, &na->na_atime) &&
 320             xdr_nfs2_timeval(xdrs, &na->na_mtime) &&
 321             xdr_nfs2_timeval(xdrs, &na->na_ctime)) {
 322                 return (TRUE);
 323         }
 324         return (FALSE);
 325 }
 326 
 327 #ifdef _LITTLE_ENDIAN
 328 bool_t
 329 xdr_fastfattr(XDR *xdrs, struct nfsfattr *na)
 330 {
 331         if (xdrs->x_op == XDR_FREE)
 332                 return (TRUE);
 333         if (xdrs->x_op == XDR_DECODE)
 334                 return (FALSE);
 335 
 336         na->na_type = htonl(na->na_type);
 337         na->na_mode = htonl(na->na_mode);
 338         na->na_nlink = htonl(na->na_nlink);
 339         na->na_uid = htonl(na->na_uid);
 340         na->na_gid = htonl(na->na_gid);
 341         na->na_size = htonl(na->na_size);
 342         na->na_blocksize = htonl(na->na_blocksize);
 343         na->na_rdev = htonl(na->na_rdev);
 344         na->na_blocks = htonl(na->na_blocks);
 345         na->na_fsid = htonl(na->na_fsid);
 346         na->na_nodeid = htonl(na->na_nodeid);
 347         na->na_atime.tv_sec = htonl(na->na_atime.tv_sec);
 348         na->na_atime.tv_usec = htonl(na->na_atime.tv_usec);
 349         na->na_mtime.tv_sec = htonl(na->na_mtime.tv_sec);
 350         na->na_mtime.tv_usec = htonl(na->na_mtime.tv_usec);
 351         na->na_ctime.tv_sec = htonl(na->na_ctime.tv_sec);
 352         na->na_ctime.tv_usec = htonl(na->na_ctime.tv_usec);
 353         return (TRUE);
 354 }
 355 #endif
 356 
 357 bool_t
 358 xdr_readlink(XDR *xdrs, fhandle_t *fh)
 359 {
 360         rdma_chunkinfo_t rci;
 361         struct xdr_ops *xops = xdrrdma_xops();
 362 
 363         if (xdr_fhandle(xdrs, fh)) {
 364                 if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
 365                     xdrs->x_op == XDR_ENCODE) {
 366                         rci.rci_type = RCI_REPLY_CHUNK;
 367                         rci.rci_len = MAXPATHLEN;
 368                         XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
 369                 }
 370 
 371                 return (TRUE);
 372         }
 373         return (FALSE);
 374 }
 375 
 376 /*
 377  * Arguments to remote read
 378  */
 379 bool_t
 380 xdr_readargs(XDR *xdrs, struct nfsreadargs *ra)
 381 {
 382         int32_t *ptr;
 383         int32_t *fhp;
 384         rdma_chunkinfo_t rci;
 385         rdma_wlist_conn_info_t rwci;
 386         struct xdr_ops *xops = xdrrdma_xops();
 387 
 388         if (xdrs->x_op == XDR_FREE)
 389                 return (TRUE);
 390 
 391         ptr = XDR_INLINE(xdrs,
 392             RNDUP(sizeof (fhandle_t)) + 3 * BYTES_PER_XDR_UNIT);
 393         if (ptr != NULL) {
 394                 if (xdrs->x_op == XDR_DECODE) {
 395                         fhp = (int32_t *)&ra->ra_fhandle;
 396                         *fhp++ = *ptr++;
 397                         *fhp++ = *ptr++;
 398                         *fhp++ = *ptr++;
 399                         *fhp++ = *ptr++;
 400                         *fhp++ = *ptr++;
 401                         *fhp++ = *ptr++;
 402                         *fhp++ = *ptr++;
 403                         *fhp = *ptr++;
 404                         ra->ra_offset = IXDR_GET_INT32(ptr);
 405                         ra->ra_count = IXDR_GET_INT32(ptr);
 406                         ra->ra_totcount = IXDR_GET_INT32(ptr);
 407                 } else {
 408                         fhp = (int32_t *)&ra->ra_fhandle;
 409                         *ptr++ = *fhp++;
 410                         *ptr++ = *fhp++;
 411                         *ptr++ = *fhp++;
 412                         *ptr++ = *fhp++;
 413                         *ptr++ = *fhp++;
 414                         *ptr++ = *fhp++;
 415                         *ptr++ = *fhp++;
 416                         *ptr++ = *fhp;
 417                         IXDR_PUT_INT32(ptr, ra->ra_offset);
 418                         IXDR_PUT_INT32(ptr, ra->ra_count);
 419                         IXDR_PUT_INT32(ptr, ra->ra_totcount);
 420                 }
 421         } else {
 422                 if (!xdr_fhandle(xdrs, &ra->ra_fhandle) ||
 423                     !xdr_u_int(xdrs, &ra->ra_offset) ||
 424                     !xdr_u_int(xdrs, &ra->ra_count) ||
 425                     !xdr_u_int(xdrs, &ra->ra_totcount)) {
 426                         return (FALSE);
 427                 }
 428         }
 429 
 430         if (ra->ra_count > NFS_MAXDATA)
 431                 return (FALSE);
 432 
 433         ra->ra_wlist = NULL;
 434         ra->ra_conn = NULL;
 435 
 436         /* If this is xdrrdma_sizeof, record the expect response size */
 437         if (xdrs->x_ops == xops && xdrs->x_op == XDR_ENCODE) {
 438                 rci.rci_type = RCI_WRITE_ADDR_CHUNK;
 439                 rci.rci_len = ra->ra_count;
 440                 (void) XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
 441         }
 442         /* Nothing special to do, return */
 443         if (xdrs->x_ops != &xdrrdma_ops || xdrs->x_op == XDR_FREE)
 444                 return (TRUE);
 445 
 446         if (xdrs->x_op == XDR_ENCODE) {
 447                 /* Place the target data location into the RDMA header */
 448                 rci.rci_type = RCI_WRITE_ADDR_CHUNK;
 449                 rci.rci_a.rci_addr = ra->ra_data;
 450                 rci.rci_len = ra->ra_count;
 451                 rci.rci_clpp = &ra->ra_wlist;
 452 
 453                 return (XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci));
 454         }
 455 
 456         /* XDR_DECODE case */
 457         (void) XDR_CONTROL(xdrs, XDR_RDMA_GET_WCINFO, &rwci);
 458         ra->ra_wlist = rwci.rwci_wlist;
 459         ra->ra_conn = rwci.rwci_conn;
 460 
 461         return (TRUE);
 462 }
 463 
 464 
 465 /*
 466  * Status OK portion of remote read reply
 467  */
 468 bool_t
 469 xdr_rrok(XDR *xdrs, struct nfsrrok *rrok)
 470 {
 471         bool_t ret;
 472         mblk_t *mp;
 473         struct xdr_ops *xops = xdrrdma_xops();
 474 
 475         if (xdr_fattr(xdrs, &rrok->rrok_attr) == FALSE)
 476                 return (FALSE);
 477 
 478         /* deal with RDMA separately */
 479         if (xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) {
 480                 if (xdrs->x_op == XDR_ENCODE &&
 481                     rrok->rrok_mp != NULL) {
 482                         ret = xdr_bytes(xdrs, (char **)&rrok->rrok_data,
 483                             &rrok->rrok_count, NFS_MAXDATA);
 484                         return (ret);
 485                 }
 486 
 487                 if (xdrs->x_op == XDR_ENCODE) {
 488                         if (xdr_u_int(xdrs, &rrok->rrok_count) == FALSE) {
 489                                 return (FALSE);
 490                         }
 491                         /*
 492                          * If read data sent by wlist (RDMA_WRITE), don't do
 493                          * xdr_bytes() below.   RDMA_WRITE transfers the data.
 494                          */
 495                         if (rrok->rrok_wlist) {
 496                                 if (rrok->rrok_count != 0) {
 497                                         return (xdrrdma_send_read_data(
 498                                             xdrs, rrok->rrok_count,
 499                                             rrok->rrok_wlist));
 500                                 }
 501                                 return (TRUE);
 502                         }
 503                         if (rrok->rrok_count == 0) {
 504                                 return (TRUE);
 505                         }
 506                 } else {
 507                         struct clist *cl;
 508                         uint32_t count;
 509 
 510                         XDR_CONTROL(xdrs, XDR_RDMA_GET_WLIST, &cl);
 511 
 512                         if (cl) {
 513                                 if (!xdr_u_int(xdrs, &count))
 514                                         return (FALSE);
 515                                 if (count == 0) {
 516                                         rrok->rrok_wlist_len = 0;
 517                                         rrok->rrok_count = 0;
 518                                 } else {
 519                                         rrok->rrok_wlist_len = clist_len(cl);
 520                                         if (rrok->rrok_wlist_len !=
 521                                             roundup(count,
 522                                             BYTES_PER_XDR_UNIT)) {
 523                                                 rrok->rrok_wlist_len = 0;
 524                                                 rrok->rrok_count = 0;
 525                                                 return (FALSE);
 526                                         }
 527                                         rrok->rrok_count = count;
 528                                 }
 529                                 return (TRUE);
 530                         }
 531                 }
 532                 ret = xdr_bytes(xdrs, (char **)&rrok->rrok_data,
 533                     &rrok->rrok_count, NFS_MAXDATA);
 534 
 535                 return (ret);
 536         }
 537 
 538         if (xdrs->x_op == XDR_ENCODE) {
 539                 int i, rndup;
 540 
 541                 mp = rrok->rrok_mp;
 542                 if (mp != NULL && xdrs->x_ops == &xdrmblk_ops) {
 543                         mp->b_wptr += rrok->rrok_count;
 544                         rndup = BYTES_PER_XDR_UNIT -
 545                             (rrok->rrok_count % BYTES_PER_XDR_UNIT);
 546                         if (rndup != BYTES_PER_XDR_UNIT)
 547                                 for (i = 0; i < rndup; i++)
 548                                         *mp->b_wptr++ = '\0';
 549                         if (xdrmblk_putmblk(xdrs, mp,
 550                             rrok->rrok_count) == TRUE) {
 551                                 rrok->rrok_mp = NULL;
 552                                 return (TRUE);
 553                         }
 554                 }
 555 
 556                 /*
 557                  * Fall thru for the xdr_bytes()
 558                  *
 559                  * Note: the mblk mp will be freed in rfs_rdfree
 560                  */
 561         }
 562 
 563         ret = xdr_bytes(xdrs, (char **)&rrok->rrok_data,
 564             &rrok->rrok_count, NFS_MAXDATA);
 565 
 566         return (ret);
 567 }
 568 
 569 static struct xdr_discrim rdres_discrim[2] = {
 570         { NFS_OK, xdr_rrok },
 571         { __dontcare__, NULL_xdrproc_t }
 572 };
 573 
 574 /*
 575  * Reply from remote read
 576  */
 577 bool_t
 578 xdr_rdresult(XDR *xdrs, struct nfsrdresult *rr)
 579 {
 580         return (xdr_union(xdrs, (enum_t *)&(rr->rr_status),
 581             (caddr_t)&(rr->rr_ok), rdres_discrim, xdr_void));
 582 }
 583 
 584 /*
 585  * File attributes which can be set
 586  */
 587 bool_t
 588 xdr_sattr(XDR *xdrs, struct nfssattr *sa)
 589 {
 590         if (xdr_u_int(xdrs, &sa->sa_mode) &&
 591             xdr_u_int(xdrs, &sa->sa_uid) &&
 592             xdr_u_int(xdrs, &sa->sa_gid) &&
 593             xdr_u_int(xdrs, &sa->sa_size) &&
 594             xdr_nfs2_timeval(xdrs, &sa->sa_atime) &&
 595             xdr_nfs2_timeval(xdrs, &sa->sa_mtime)) {
 596                 return (TRUE);
 597         }
 598         return (FALSE);
 599 }
 600 
 601 static struct xdr_discrim attrstat_discrim[2] = {
 602         { (int)NFS_OK, xdr_fattr },
 603         { __dontcare__, NULL_xdrproc_t }
 604 };
 605 
 606 /*
 607  * Reply status with file attributes
 608  */
 609 bool_t
 610 xdr_attrstat(XDR *xdrs, struct nfsattrstat *ns)
 611 {
 612         return (xdr_union(xdrs, (enum_t *)&(ns->ns_status),
 613             (caddr_t)&(ns->ns_attr), attrstat_discrim, xdr_void));
 614 }
 615 
 616 /*
 617  * Fast reply status with file attributes
 618  */
 619 bool_t
 620 xdr_fastattrstat(XDR *xdrs, struct nfsattrstat *ns)
 621 {
 622 #if defined(_LITTLE_ENDIAN)
 623         /*
 624          * we deal with the discriminator;  it's an enum
 625          */
 626         if (!xdr_fastenum(xdrs, (enum_t *)&ns->ns_status))
 627                 return (FALSE);
 628 
 629         if (ns->ns_status == NFS_OK)
 630                 return (xdr_fastfattr(xdrs, &ns->ns_attr));
 631 #elif defined(_BIG_ENDIAN)
 632         if (ns->ns_status == NFS_OK)
 633                 return (TRUE);
 634 #endif
 635         return (xdr_fastshorten(xdrs, sizeof (*ns)));
 636 }
 637 
 638 /*
 639  * NFS_OK part of read sym link reply union
 640  */
 641 bool_t
 642 xdr_srok(XDR *xdrs, struct nfssrok *srok)
 643 {
 644         /*
 645          * It is just as efficient to xdr_bytes
 646          * an array of unknown length as to inline copy it.
 647          */
 648         return (xdr_bytes(xdrs, &srok->srok_data, &srok->srok_count,
 649             NFS_MAXPATHLEN));
 650 }
 651 
 652 static struct xdr_discrim rdlnres_discrim[2] = {
 653         { (int)NFS_OK, xdr_srok },
 654         { __dontcare__, NULL_xdrproc_t }
 655 };
 656 
 657 /*
 658  * Result of reading symbolic link
 659  */
 660 bool_t
 661 xdr_rdlnres(XDR *xdrs, struct nfsrdlnres *rl)
 662 {
 663         return (xdr_union(xdrs, (enum_t *)&(rl->rl_status),
 664             (caddr_t)&(rl->rl_srok), rdlnres_discrim, xdr_void));
 665 }
 666 
 667 /*
 668  * Arguments to readdir
 669  */
 670 bool_t
 671 xdr_rddirargs(XDR *xdrs, struct nfsrddirargs *rda)
 672 {
 673         int32_t *ptr;
 674         int32_t *fhp;
 675         rdma_chunkinfo_t rci;
 676         struct xdr_ops *xops = xdrrdma_xops();
 677 
 678         if (xdrs->x_op == XDR_FREE)
 679                 return (TRUE);
 680 
 681         ptr = XDR_INLINE(xdrs,
 682             RNDUP(sizeof (fhandle_t)) + 2 * BYTES_PER_XDR_UNIT);
 683 
 684         if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
 685             xdrs->x_op == XDR_ENCODE) {
 686                 rci.rci_type = RCI_REPLY_CHUNK;
 687                 rci.rci_len = rda->rda_count;
 688                 XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
 689         }
 690 
 691         if (ptr != NULL) {
 692                 if (xdrs->x_op == XDR_DECODE) {
 693                         fhp = (int32_t *)&rda->rda_fh;
 694                         *fhp++ = *ptr++;
 695                         *fhp++ = *ptr++;
 696                         *fhp++ = *ptr++;
 697                         *fhp++ = *ptr++;
 698                         *fhp++ = *ptr++;
 699                         *fhp++ = *ptr++;
 700                         *fhp++ = *ptr++;
 701                         *fhp = *ptr++;
 702                         rda->rda_offset = IXDR_GET_U_INT32(ptr);
 703                         rda->rda_count = IXDR_GET_U_INT32(ptr);
 704                 } else {
 705                         fhp = (int32_t *)&rda->rda_fh;
 706                         *ptr++ = *fhp++;
 707                         *ptr++ = *fhp++;
 708                         *ptr++ = *fhp++;
 709                         *ptr++ = *fhp++;
 710                         *ptr++ = *fhp++;
 711                         *ptr++ = *fhp++;
 712                         *ptr++ = *fhp++;
 713                         *ptr++ = *fhp;
 714                         IXDR_PUT_U_INT32(ptr, rda->rda_offset);
 715                         IXDR_PUT_U_INT32(ptr, rda->rda_count);
 716                 }
 717                 return (TRUE);
 718         }
 719 
 720         if (xdr_fhandle(xdrs, &rda->rda_fh) &&
 721             xdr_u_int(xdrs, &rda->rda_offset) &&
 722             xdr_u_int(xdrs, &rda->rda_count)) {
 723                 return (TRUE);
 724         }
 725         return (FALSE);
 726 }
 727 
 728 
 729 /*
 730  * Directory read reply:
 731  * union (enum status) {
 732  *      NFS_OK: entlist;
 733  *              boolean eof;
 734  *      default:
 735  * }
 736  *
 737  * Directory entries
 738  *      struct  direct {
 739  *              off_t   d_off;                  * offset of next entry *
 740  *              u_int   d_fileno;               * inode number of entry *
 741  *              u_short d_reclen;               * length of this record *
 742  *              u_short d_namlen;               * length of string in d_name *
 743  *              char    d_name[MAXNAMLEN + 1];  * name no longer than this *
 744  *      };
 745  * are on the wire as:
 746  * union entlist (boolean valid) {
 747  *      TRUE:   struct otw_dirent;
 748  *              u_int nxtoffset;
 749  *              union entlist;
 750  *      FALSE:
 751  * }
 752  * where otw_dirent is:
 753  *      struct dirent {
 754  *              u_int   de_fid;
 755  *              string  de_name<NFS_MAXNAMELEN>;
 756  *      }
 757  */
 758 
 759 #ifdef nextdp
 760 #undef  nextdp
 761 #endif
 762 #define nextdp(dp)      ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
 763 #ifdef roundup
 764 #undef  roundup
 765 #endif
 766 #define roundup(x, y)   ((((x) + ((y) - 1)) / (y)) * (y))
 767 
 768 /*
 769  * ENCODE ONLY
 770  */
 771 bool_t
 772 xdr_putrddirres(XDR *xdrs, struct nfsrddirres *rd)
 773 {
 774         struct dirent64 *dp;
 775         char *name;
 776         int size;
 777         uint_t namlen;
 778         bool_t true = TRUE;
 779         bool_t false = FALSE;
 780         int entrysz;
 781         int tofit;
 782         int bufsize;
 783         uint32_t ino, off;
 784 
 785         if (xdrs->x_op != XDR_ENCODE)
 786                 return (FALSE);
 787         if (!xdr_enum(xdrs, (enum_t *)&rd->rd_status))
 788                 return (FALSE);
 789         if (rd->rd_status != NFS_OK)
 790                 return (TRUE);
 791 
 792         bufsize = 1 * BYTES_PER_XDR_UNIT;
 793         for (size = rd->rd_size, dp = rd->rd_entries;
 794             size > 0;
 795             size -= dp->d_reclen, dp = nextdp(dp)) {
 796                 if (dp->d_reclen == 0 /* || DIRSIZ(dp) > dp->d_reclen */)
 797                         return (FALSE);
 798                 if (dp->d_ino == 0)
 799                         continue;
 800                 ino = (uint32_t)dp->d_ino; /* for LP64 we clip the bits */
 801                 if (dp->d_ino != (ino64_t)ino)       /* and they better be zeros */
 802                         return (FALSE);
 803                 off = (uint32_t)dp->d_off;
 804                 name = dp->d_name;
 805                 namlen = (uint_t)strlen(name);
 806                 entrysz = (1 + 1 + 1 + 1) * BYTES_PER_XDR_UNIT +
 807                     roundup(namlen, BYTES_PER_XDR_UNIT);
 808                 tofit = entrysz + 2 * BYTES_PER_XDR_UNIT;
 809                 if (bufsize + tofit > rd->rd_bufsize) {
 810                         rd->rd_eof = FALSE;
 811                         break;
 812                 }
 813                 if (!xdr_bool(xdrs, &true) ||
 814                     !xdr_u_int(xdrs, &ino) ||
 815                     !xdr_bytes(xdrs, &name, &namlen, NFS_MAXNAMLEN) ||
 816                     !xdr_u_int(xdrs, &off)) {
 817                         return (FALSE);
 818                 }
 819                 bufsize += entrysz;
 820         }
 821         if (!xdr_bool(xdrs, &false))
 822                 return (FALSE);
 823         if (!xdr_bool(xdrs, &rd->rd_eof))
 824                 return (FALSE);
 825         return (TRUE);
 826 }
 827 
 828 /*
 829  * DECODE ONLY
 830  */
 831 bool_t
 832 xdr_getrddirres(XDR *xdrs, struct nfsrddirres *rd)
 833 {
 834         struct dirent64 *dp;
 835         uint_t namlen;
 836         int size;
 837         bool_t valid;
 838         uint32_t offset;
 839         uint_t fileid, this_reclen;
 840 
 841         if (xdrs->x_op != XDR_DECODE)
 842                 return (FALSE);
 843 
 844         if (!xdr_enum(xdrs, (enum_t *)&rd->rd_status))
 845                 return (FALSE);
 846         if (rd->rd_status != NFS_OK)
 847                 return (TRUE);
 848 
 849         size = rd->rd_size;
 850         dp = rd->rd_entries;
 851         offset = rd->rd_offset;
 852         for (;;) {
 853                 if (!xdr_bool(xdrs, &valid))
 854                         return (FALSE);
 855                 if (!valid)
 856                         break;
 857                 if (!xdr_u_int(xdrs, &fileid) ||
 858                     !xdr_u_int(xdrs, &namlen))
 859                         return (FALSE);
 860                 this_reclen = DIRENT64_RECLEN(namlen);
 861                 if (this_reclen > size) {
 862                         rd->rd_eof = FALSE;
 863                         goto bufovflw;
 864                 }
 865                 if (!xdr_opaque(xdrs, dp->d_name, namlen)||
 866                     !xdr_u_int(xdrs, &offset)) {
 867                         return (FALSE);
 868                 }
 869                 bzero(&dp->d_name[namlen],
 870                     DIRENT64_NAMELEN(this_reclen) - namlen);
 871                 dp->d_ino = (ino64_t)fileid;
 872                 dp->d_reclen = this_reclen;
 873                 dp->d_off = (off64_t)offset;
 874                 size -= dp->d_reclen;
 875                 dp = nextdp(dp);
 876         }
 877         if (!xdr_bool(xdrs, &rd->rd_eof))
 878                 return (FALSE);
 879 bufovflw:
 880         rd->rd_size = (uint32_t)((char *)dp - (char *)(rd->rd_entries));
 881         rd->rd_offset = offset;
 882         return (TRUE);
 883 }
 884 
 885 /*
 886  * Arguments for directory operations
 887  */
 888 bool_t
 889 xdr_diropargs(XDR *xdrs, struct nfsdiropargs *da)
 890 {
 891         int32_t *ptr;
 892         int32_t *fhp;
 893         uint32_t size;
 894         uint32_t nodesize;
 895         int i;
 896         int rndup;
 897         char *cptr;
 898 
 899         if (xdrs->x_op == XDR_DECODE) {
 900                 da->da_fhandle = &da->da_fhandle_buf;
 901                 ptr = XDR_INLINE(xdrs, RNDUP(sizeof (fhandle_t)) +
 902                     1 * BYTES_PER_XDR_UNIT);
 903                 if (ptr != NULL) {
 904                         fhp = (int32_t *)da->da_fhandle;
 905                         *fhp++ = *ptr++;
 906                         *fhp++ = *ptr++;
 907                         *fhp++ = *ptr++;
 908                         *fhp++ = *ptr++;
 909                         *fhp++ = *ptr++;
 910                         *fhp++ = *ptr++;
 911                         *fhp++ = *ptr++;
 912                         *fhp = *ptr++;
 913                         size = IXDR_GET_U_INT32(ptr);
 914                         if (size > NFS_MAXNAMLEN)
 915                                 return (FALSE);
 916                         nodesize = size + 1;
 917                         if (nodesize == 0)
 918                                 return (TRUE);
 919                         if (da->da_name == NULL) {
 920                                 da->da_name = kmem_alloc(nodesize, KM_NOSLEEP);
 921                                 if (da->da_name == NULL)
 922                                         return (FALSE);
 923                                 da->da_flags |= DA_FREENAME;
 924                         }
 925                         ptr = XDR_INLINE(xdrs, RNDUP(size));
 926                         if (ptr == NULL) {
 927                                 if (!xdr_opaque(xdrs, da->da_name, size)) {
 928                                         if (da->da_flags & DA_FREENAME) {
 929                                                 kmem_free(da->da_name,
 930                                                     nodesize);
 931                                                 da->da_name = NULL;
 932                                         }
 933                                         return (FALSE);
 934                                 }
 935                                 da->da_name[size] = '\0';
 936                                 if (strlen(da->da_name) != size) {
 937                                         if (da->da_flags & DA_FREENAME) {
 938                                                 kmem_free(da->da_name,
 939                                                     nodesize);
 940                                                 da->da_name = NULL;
 941                                         }
 942                                         return (FALSE);
 943                                 }
 944                                 return (TRUE);
 945                         }
 946                         bcopy(ptr, da->da_name, size);
 947                         da->da_name[size] = '\0';
 948                         if (strlen(da->da_name) != size) {
 949                                 if (da->da_flags & DA_FREENAME) {
 950                                         kmem_free(da->da_name, nodesize);
 951                                         da->da_name = NULL;
 952                                 }
 953                                 return (FALSE);
 954                         }
 955                         return (TRUE);
 956                 }
 957                 if (da->da_name == NULL)
 958                         da->da_flags |= DA_FREENAME;
 959         }
 960 
 961         if (xdrs->x_op == XDR_ENCODE) {
 962                 size = (uint32_t)strlen(da->da_name);
 963                 if (size > NFS_MAXNAMLEN)
 964                         return (FALSE);
 965                 ptr = XDR_INLINE(xdrs, (int)(RNDUP(sizeof (fhandle_t)) +
 966                     1 * BYTES_PER_XDR_UNIT + RNDUP(size)));
 967                 if (ptr != NULL) {
 968                         fhp = (int32_t *)da->da_fhandle;
 969                         *ptr++ = *fhp++;
 970                         *ptr++ = *fhp++;
 971                         *ptr++ = *fhp++;
 972                         *ptr++ = *fhp++;
 973                         *ptr++ = *fhp++;
 974                         *ptr++ = *fhp++;
 975                         *ptr++ = *fhp++;
 976                         *ptr++ = *fhp;
 977                         IXDR_PUT_U_INT32(ptr, (uint32_t)size);
 978                         bcopy(da->da_name, ptr, size);
 979                         rndup = BYTES_PER_XDR_UNIT -
 980                             (size % BYTES_PER_XDR_UNIT);
 981                         if (rndup != BYTES_PER_XDR_UNIT) {
 982                                 cptr = (char *)ptr + size;
 983                                 for (i = 0; i < rndup; i++)
 984                                         *cptr++ = '\0';
 985                         }
 986                         return (TRUE);
 987                 }
 988         }
 989 
 990         if (xdrs->x_op == XDR_FREE) {
 991                 if (da->da_name == NULL)
 992                         return (TRUE);
 993                 size = (uint32_t)strlen(da->da_name);
 994                 if (size > NFS_MAXNAMLEN)
 995                         return (FALSE);
 996                 if (da->da_flags & DA_FREENAME)
 997                         kmem_free(da->da_name, size + 1);
 998                 da->da_name = NULL;
 999                 return (TRUE);
1000         }
1001 
1002         if (xdr_fhandle(xdrs, da->da_fhandle) &&
1003             xdr_string(xdrs, &da->da_name, NFS_MAXNAMLEN)) {
1004                 return (TRUE);
1005         }
1006         return (FALSE);
1007 }
1008 
1009 /*
1010  * NFS_OK part of directory operation result
1011  */
1012 bool_t
1013 xdr_drok(XDR *xdrs, struct nfsdrok *drok)
1014 {
1015         int32_t *ptr;
1016         int32_t *fhp;
1017         struct nfsfattr *na;
1018 
1019         if (xdrs->x_op == XDR_FREE)
1020                 return (TRUE);
1021 
1022         ptr = XDR_INLINE(xdrs,
1023             RNDUP(sizeof (fhandle_t)) + 17 * BYTES_PER_XDR_UNIT);
1024         if (ptr != NULL) {
1025                 if (xdrs->x_op == XDR_DECODE) {
1026                         fhp = (int32_t *)&drok->drok_fhandle;
1027                         *fhp++ = *ptr++;
1028                         *fhp++ = *ptr++;
1029                         *fhp++ = *ptr++;
1030                         *fhp++ = *ptr++;
1031                         *fhp++ = *ptr++;
1032                         *fhp++ = *ptr++;
1033                         *fhp++ = *ptr++;
1034                         *fhp = *ptr++;
1035                         na = &drok->drok_attr;
1036                         na->na_type = IXDR_GET_ENUM(ptr, enum nfsftype);
1037                         na->na_mode = IXDR_GET_U_INT32(ptr);
1038                         na->na_nlink = IXDR_GET_U_INT32(ptr);
1039                         na->na_uid = IXDR_GET_U_INT32(ptr);
1040                         na->na_gid = IXDR_GET_U_INT32(ptr);
1041                         na->na_size = IXDR_GET_U_INT32(ptr);
1042                         na->na_blocksize = IXDR_GET_U_INT32(ptr);
1043                         na->na_rdev = IXDR_GET_U_INT32(ptr);
1044                         na->na_blocks = IXDR_GET_U_INT32(ptr);
1045                         na->na_fsid = IXDR_GET_U_INT32(ptr);
1046                         na->na_nodeid = IXDR_GET_U_INT32(ptr);
1047                         na->na_atime.tv_sec = IXDR_GET_U_INT32(ptr);
1048                         na->na_atime.tv_usec = IXDR_GET_U_INT32(ptr);
1049                         na->na_mtime.tv_sec = IXDR_GET_U_INT32(ptr);
1050                         na->na_mtime.tv_usec = IXDR_GET_U_INT32(ptr);
1051                         na->na_ctime.tv_sec = IXDR_GET_U_INT32(ptr);
1052                         na->na_ctime.tv_usec = IXDR_GET_U_INT32(ptr);
1053                 } else {
1054                         fhp = (int32_t *)&drok->drok_fhandle;
1055                         *ptr++ = *fhp++;
1056                         *ptr++ = *fhp++;
1057                         *ptr++ = *fhp++;
1058                         *ptr++ = *fhp++;
1059                         *ptr++ = *fhp++;
1060                         *ptr++ = *fhp++;
1061                         *ptr++ = *fhp++;
1062                         *ptr++ = *fhp;
1063                         na = &drok->drok_attr;
1064                         IXDR_PUT_ENUM(ptr, na->na_type);
1065                         IXDR_PUT_U_INT32(ptr, na->na_mode);
1066                         IXDR_PUT_U_INT32(ptr, na->na_nlink);
1067                         IXDR_PUT_U_INT32(ptr, na->na_uid);
1068                         IXDR_PUT_U_INT32(ptr, na->na_gid);
1069                         IXDR_PUT_U_INT32(ptr, na->na_size);
1070                         IXDR_PUT_U_INT32(ptr, na->na_blocksize);
1071                         IXDR_PUT_U_INT32(ptr, na->na_rdev);
1072                         IXDR_PUT_U_INT32(ptr, na->na_blocks);
1073                         IXDR_PUT_U_INT32(ptr, na->na_fsid);
1074                         IXDR_PUT_U_INT32(ptr, na->na_nodeid);
1075                         IXDR_PUT_U_INT32(ptr, na->na_atime.tv_sec);
1076                         IXDR_PUT_U_INT32(ptr, na->na_atime.tv_usec);
1077                         IXDR_PUT_U_INT32(ptr, na->na_mtime.tv_sec);
1078                         IXDR_PUT_U_INT32(ptr, na->na_mtime.tv_usec);
1079                         IXDR_PUT_U_INT32(ptr, na->na_ctime.tv_sec);
1080                         IXDR_PUT_U_INT32(ptr, na->na_ctime.tv_usec);
1081                 }
1082                 return (TRUE);
1083         }
1084 
1085         if (xdr_fhandle(xdrs, &drok->drok_fhandle) &&
1086             xdr_fattr(xdrs, &drok->drok_attr)) {
1087                 return (TRUE);
1088         }
1089         return (FALSE);
1090 }
1091 
1092 #ifdef _LITTLE_ENDIAN
1093 bool_t
1094 xdr_fastdrok(XDR *xdrs, struct nfsdrok *drok)
1095 {
1096         struct nfsfattr *na;
1097 
1098         if (xdrs->x_op == XDR_FREE)
1099                 return (TRUE);
1100         if (xdrs->x_op == XDR_DECODE)
1101                 return (FALSE);
1102 
1103         na = &drok->drok_attr;
1104         na->na_type = (enum nfsftype)htonl(na->na_type);
1105         na->na_mode = (uint32_t)htonl(na->na_mode);
1106         na->na_nlink = (uint32_t)htonl(na->na_nlink);
1107         na->na_uid = (uint32_t)htonl(na->na_uid);
1108         na->na_gid = (uint32_t)htonl(na->na_gid);
1109         na->na_size = (uint32_t)htonl(na->na_size);
1110         na->na_blocksize = (uint32_t)htonl(na->na_blocksize);
1111         na->na_rdev = (uint32_t)htonl(na->na_rdev);
1112         na->na_blocks = (uint32_t)htonl(na->na_blocks);
1113         na->na_fsid = (uint32_t)htonl(na->na_fsid);
1114         na->na_nodeid = (uint32_t)htonl(na->na_nodeid);
1115         na->na_atime.tv_sec = htonl(na->na_atime.tv_sec);
1116         na->na_atime.tv_usec = htonl(na->na_atime.tv_usec);
1117         na->na_mtime.tv_sec = htonl(na->na_mtime.tv_sec);
1118         na->na_mtime.tv_usec = htonl(na->na_mtime.tv_usec);
1119         na->na_ctime.tv_sec = htonl(na->na_ctime.tv_sec);
1120         na->na_ctime.tv_usec = htonl(na->na_ctime.tv_usec);
1121         return (TRUE);
1122 }
1123 #endif
1124 
1125 static struct xdr_discrim diropres_discrim[2] = {
1126         { NFS_OK, xdr_drok },
1127         { __dontcare__, NULL_xdrproc_t }
1128 };
1129 
1130 /*
1131  * Results from directory operation
1132  */
1133 bool_t
1134 xdr_diropres(XDR *xdrs, struct nfsdiropres *dr)
1135 {
1136         return (xdr_union(xdrs, (enum_t *)&(dr->dr_status),
1137             (caddr_t)&(dr->dr_drok), diropres_discrim, xdr_void));
1138 }
1139 
1140 /*
1141  * Results from directory operation
1142  */
1143 bool_t
1144 xdr_fastdiropres(XDR *xdrs, struct nfsdiropres *dr)
1145 {
1146 #if defined(_LITTLE_ENDIAN)
1147         /*
1148          * we deal with the discriminator;  it's an enum
1149          */
1150         if (!xdr_fastenum(xdrs, (enum_t *)&dr->dr_status))
1151                 return (FALSE);
1152 
1153         if (dr->dr_status == NFS_OK)
1154                 return (xdr_fastdrok(xdrs, &dr->dr_drok));
1155 #elif defined(_BIG_ENDIAN)
1156         if (dr->dr_status == NFS_OK)
1157                 return (TRUE);
1158 #endif
1159         return (xdr_fastshorten(xdrs, sizeof (*dr)));
1160 }
1161 
1162 /*
1163  * Time Structure, unsigned
1164  */
1165 bool_t
1166 xdr_nfs2_timeval(XDR *xdrs, struct nfs2_timeval *tv)
1167 {
1168         if (xdr_u_int(xdrs, &tv->tv_sec) &&
1169             xdr_u_int(xdrs, &tv->tv_usec))
1170                 return (TRUE);
1171         return (FALSE);
1172 }
1173 
1174 /*
1175  * arguments to setattr
1176  */
1177 bool_t
1178 xdr_saargs(XDR *xdrs, struct nfssaargs *argp)
1179 {
1180         int32_t *ptr;
1181         int32_t *arg;
1182         struct nfssattr *sa;
1183 
1184         if (xdrs->x_op == XDR_FREE)
1185                 return (TRUE);
1186 
1187         ptr = XDR_INLINE(xdrs,
1188             RNDUP(sizeof (fhandle_t)) + 8 * BYTES_PER_XDR_UNIT);
1189         if (ptr != NULL) {
1190                 if (xdrs->x_op == XDR_DECODE) {
1191                         arg = (int32_t *)&argp->saa_fh;
1192                         *arg++ = *ptr++;
1193                         *arg++ = *ptr++;
1194                         *arg++ = *ptr++;
1195                         *arg++ = *ptr++;
1196                         *arg++ = *ptr++;
1197                         *arg++ = *ptr++;
1198                         *arg++ = *ptr++;
1199                         *arg = *ptr++;
1200                         sa = &argp->saa_sa;
1201                         sa->sa_mode = IXDR_GET_U_INT32(ptr);
1202                         sa->sa_uid = IXDR_GET_U_INT32(ptr);
1203                         sa->sa_gid = IXDR_GET_U_INT32(ptr);
1204                         sa->sa_size = IXDR_GET_U_INT32(ptr);
1205                         sa->sa_atime.tv_sec = IXDR_GET_U_INT32(ptr);
1206                         sa->sa_atime.tv_usec = IXDR_GET_U_INT32(ptr);
1207                         sa->sa_mtime.tv_sec = IXDR_GET_U_INT32(ptr);
1208                         sa->sa_mtime.tv_usec = IXDR_GET_U_INT32(ptr);
1209                 } else {
1210                         arg = (int32_t *)&argp->saa_fh;
1211                         *ptr++ = *arg++;
1212                         *ptr++ = *arg++;
1213                         *ptr++ = *arg++;
1214                         *ptr++ = *arg++;
1215                         *ptr++ = *arg++;
1216                         *ptr++ = *arg++;
1217                         *ptr++ = *arg++;
1218                         *ptr++ = *arg;
1219                         sa = &argp->saa_sa;
1220                         IXDR_PUT_U_INT32(ptr, sa->sa_mode);
1221                         IXDR_PUT_U_INT32(ptr, sa->sa_uid);
1222                         IXDR_PUT_U_INT32(ptr, sa->sa_gid);
1223                         IXDR_PUT_U_INT32(ptr, sa->sa_size);
1224                         IXDR_PUT_U_INT32(ptr, sa->sa_atime.tv_sec);
1225                         IXDR_PUT_U_INT32(ptr, sa->sa_atime.tv_usec);
1226                         IXDR_PUT_U_INT32(ptr, sa->sa_mtime.tv_sec);
1227                         IXDR_PUT_U_INT32(ptr, sa->sa_mtime.tv_usec);
1228                 }
1229                 return (TRUE);
1230         }
1231 
1232         if (xdr_fhandle(xdrs, &argp->saa_fh) &&
1233             xdr_sattr(xdrs, &argp->saa_sa)) {
1234                 return (TRUE);
1235         }
1236         return (FALSE);
1237 }
1238 
1239 
1240 /*
1241  * arguments to create and mkdir
1242  */
1243 bool_t
1244 xdr_creatargs(XDR *xdrs, struct nfscreatargs *argp)
1245 {
1246         argp->ca_sa = &argp->ca_sa_buf;
1247 
1248         if (xdrs->x_op == XDR_DECODE)
1249                 argp->ca_sa = &argp->ca_sa_buf;
1250         if (xdr_diropargs(xdrs, &argp->ca_da) &&
1251             xdr_sattr(xdrs, argp->ca_sa)) {
1252                 return (TRUE);
1253         }
1254         return (FALSE);
1255 }
1256 
1257 /*
1258  * arguments to link
1259  */
1260 bool_t
1261 xdr_linkargs(XDR *xdrs, struct nfslinkargs *argp)
1262 {
1263         if (xdrs->x_op == XDR_DECODE)
1264                 argp->la_from = &argp->la_from_buf;
1265         if (xdr_fhandle(xdrs, argp->la_from) &&
1266             xdr_diropargs(xdrs, &argp->la_to)) {
1267                 return (TRUE);
1268         }
1269         return (FALSE);
1270 }
1271 
1272 /*
1273  * arguments to rename
1274  */
1275 bool_t
1276 xdr_rnmargs(XDR *xdrs, struct nfsrnmargs *argp)
1277 {
1278         if (xdr_diropargs(xdrs, &argp->rna_from) &&
1279             xdr_diropargs(xdrs, &argp->rna_to))
1280                 return (TRUE);
1281         return (FALSE);
1282 }
1283 
1284 
1285 /*
1286  * arguments to symlink
1287  */
1288 bool_t
1289 xdr_slargs(XDR *xdrs, struct nfsslargs *argp)
1290 {
1291         if (xdrs->x_op == XDR_FREE) {
1292                 if (!xdr_diropargs(xdrs, &argp->sla_from))
1293                         return (FALSE);
1294                 if ((argp->sla_tnm_flags & SLA_FREETNM) &&
1295                     !xdr_string(xdrs, &argp->sla_tnm, (uint_t)NFS_MAXPATHLEN))
1296                         return (FALSE);
1297                 return (TRUE);
1298         }
1299 
1300         if (xdrs->x_op == XDR_DECODE) {
1301                 argp->sla_sa = &argp->sla_sa_buf;
1302                 if (argp->sla_tnm == NULL)
1303                         argp->sla_tnm_flags |= SLA_FREETNM;
1304         }
1305 
1306         if (xdr_diropargs(xdrs, &argp->sla_from) &&
1307             xdr_string(xdrs, &argp->sla_tnm, (uint_t)NFS_MAXPATHLEN) &&
1308             xdr_sattr(xdrs, argp->sla_sa)) {
1309                 return (TRUE);
1310         }
1311         return (FALSE);
1312 }
1313 
1314 
1315 /*
1316  * NFS_OK part of statfs operation
1317  */
1318 bool_t
1319 xdr_fsok(XDR *xdrs, struct nfsstatfsok *fsok)
1320 {
1321         int32_t *ptr;
1322 
1323         if (xdrs->x_op == XDR_FREE)
1324                 return (TRUE);
1325 
1326         ptr = XDR_INLINE(xdrs, 5 * BYTES_PER_XDR_UNIT);
1327         if (ptr != NULL) {
1328                 if (xdrs->x_op == XDR_DECODE) {
1329                         fsok->fsok_tsize = IXDR_GET_INT32(ptr);
1330                         fsok->fsok_bsize = IXDR_GET_INT32(ptr);
1331                         fsok->fsok_blocks = IXDR_GET_INT32(ptr);
1332                         fsok->fsok_bfree = IXDR_GET_INT32(ptr);
1333                         fsok->fsok_bavail = IXDR_GET_INT32(ptr);
1334                 } else {
1335                         IXDR_PUT_INT32(ptr, fsok->fsok_tsize);
1336                         IXDR_PUT_INT32(ptr, fsok->fsok_bsize);
1337                         IXDR_PUT_INT32(ptr, fsok->fsok_blocks);
1338                         IXDR_PUT_INT32(ptr, fsok->fsok_bfree);
1339                         IXDR_PUT_INT32(ptr, fsok->fsok_bavail);
1340                 }
1341                 return (TRUE);
1342         }
1343 
1344         if (xdr_u_int(xdrs, &fsok->fsok_tsize) &&
1345             xdr_u_int(xdrs, &fsok->fsok_bsize) &&
1346             xdr_u_int(xdrs, &fsok->fsok_blocks) &&
1347             xdr_u_int(xdrs, &fsok->fsok_bfree) &&
1348             xdr_u_int(xdrs, &fsok->fsok_bavail)) {
1349                 return (TRUE);
1350         }
1351         return (FALSE);
1352 }
1353 
1354 #ifdef _LITTLE_ENDIAN
1355 bool_t
1356 xdr_fastfsok(XDR *xdrs, struct nfsstatfsok *fsok)
1357 {
1358 
1359         if (xdrs->x_op == XDR_FREE)
1360                 return (TRUE);
1361         if (xdrs->x_op == XDR_DECODE)
1362                 return (FALSE);
1363 
1364         fsok->fsok_tsize = htonl(fsok->fsok_tsize);
1365         fsok->fsok_bsize = htonl(fsok->fsok_bsize);
1366         fsok->fsok_blocks = htonl(fsok->fsok_blocks);
1367         fsok->fsok_bfree = htonl(fsok->fsok_bfree);
1368         fsok->fsok_bavail = htonl(fsok->fsok_bavail);
1369         return (TRUE);
1370 }
1371 #endif
1372 
1373 static struct xdr_discrim statfs_discrim[2] = {
1374         { NFS_OK, xdr_fsok },
1375         { __dontcare__, NULL_xdrproc_t }
1376 };
1377 
1378 /*
1379  * Results of statfs operation
1380  */
1381 bool_t
1382 xdr_statfs(XDR *xdrs, struct nfsstatfs *fs)
1383 {
1384         return (xdr_union(xdrs, (enum_t *)&(fs->fs_status),
1385             (caddr_t)&(fs->fs_fsok), statfs_discrim, xdr_void));
1386 }
1387 
1388 /*
1389  * Results of statfs operation
1390  */
1391 bool_t
1392 xdr_faststatfs(XDR *xdrs, struct nfsstatfs *fs)
1393 {
1394 #if defined(_LITTLE_ENDIAN)
1395         /*
1396          * we deal with the discriminator;  it's an enum
1397          */
1398         if (!xdr_fastenum(xdrs, (enum_t *)&fs->fs_status))
1399                 return (FALSE);
1400 
1401         if (fs->fs_status == NFS_OK)
1402                 return (xdr_fastfsok(xdrs, &fs->fs_fsok));
1403 #elif defined(_BIG_ENDIAN)
1404         if (fs->fs_status == NFS_OK)
1405                 return (TRUE);
1406 #endif
1407         return (xdr_fastshorten(xdrs, sizeof (*fs)));
1408 }
1409 
1410 #ifdef _LITTLE_ENDIAN
1411 /*
1412  * XDR enumerations
1413  */
1414 #ifndef lint
1415 static enum sizecheck { SIZEVAL } sizecheckvar; /* used to find the size of */
1416                                                 /* an enum */
1417 #endif
1418 bool_t
1419 xdr_fastenum(XDR *xdrs, enum_t *ep)
1420 {
1421         if (xdrs->x_op == XDR_FREE)
1422                 return (TRUE);
1423         if (xdrs->x_op == XDR_DECODE)
1424                 return (FALSE);
1425 
1426 #ifndef lint
1427         /*
1428          * enums are treated as ints
1429          */
1430         if (sizeof (sizecheckvar) == sizeof (int32_t)) {
1431                 *ep = (enum_t)htonl((int32_t)(*ep));
1432         } else if (sizeof (sizecheckvar) == sizeof (short)) {
1433                 *ep = (enum_t)htons((short)(*ep));
1434         } else {
1435                 return (FALSE);
1436         }
1437         return (TRUE);
1438 #else
1439         (void) (xdr_short(xdrs, (short *)ep));
1440         return (xdr_int(xdrs, (int *)ep));
1441 #endif
1442 }
1443 #endif
1444 
1445 static bool_t
1446 xdr_fastshorten(XDR *xdrs, uint_t ressize)
1447 {
1448         uint_t curpos;
1449 
1450         curpos = XDR_GETPOS(xdrs);
1451         ressize -= BYTES_PER_XDR_UNIT;
1452         curpos -= ressize;
1453         return (XDR_SETPOS(xdrs, curpos));
1454 }