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