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 } 1455