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