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 2008 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 /* adjust length to match in the rdma header */ 476 if (rrok->rrok_wlist->c_len != 477 rrok->rrok_count) { 478 rrok->rrok_wlist->c_len = 479 rrok->rrok_count; 480 } 481 if (rrok->rrok_count != 0) { 482 return (xdrrdma_send_read_data( 483 xdrs, rrok->rrok_wlist)); 484 } 485 return (TRUE); 486 } 487 if (rrok->rrok_count == 0) { 488 return (TRUE); 489 } 490 } else { 491 struct clist *cl; 492 uint32_t count; 493 494 XDR_CONTROL(xdrs, XDR_RDMA_GET_WLIST, &cl); 495 496 if (cl) { 497 if (!xdr_u_int(xdrs, &count)) 498 return (FALSE); 499 if (count == 0) { 500 rrok->rrok_wlist_len = 0; 501 rrok->rrok_count = 0; 502 } else { 503 rrok->rrok_wlist_len = cl->c_len; 504 rrok->rrok_count = cl->c_len; 505 } 506 return (TRUE); 507 } 508 } 509 ret = xdr_bytes(xdrs, (char **)&rrok->rrok_data, 510 &rrok->rrok_count, NFS_MAXDATA); 511 512 return (ret); 513 } 514 515 if (xdrs->x_op == XDR_ENCODE) { 516 int i, rndup; 517 518 mp = rrok->rrok_mp; 519 if (mp != NULL && xdrs->x_ops == &xdrmblk_ops) { 520 mp->b_wptr += rrok->rrok_count; 521 rndup = BYTES_PER_XDR_UNIT - 522 (rrok->rrok_count % BYTES_PER_XDR_UNIT); 523 if (rndup != BYTES_PER_XDR_UNIT) 524 for (i = 0; i < rndup; i++) 525 *mp->b_wptr++ = '\0'; 526 if (xdrmblk_putmblk(xdrs, mp, 527 rrok->rrok_count) == TRUE) { 528 rrok->rrok_mp = NULL; 529 return (TRUE); 530 } 531 } 532 533 /* 534 * Fall thru for the xdr_bytes() 535 * 536 * Note: the mblk mp will be freed in rfs_rdfree 537 */ 538 } 539 540 ret = xdr_bytes(xdrs, (char **)&rrok->rrok_data, 541 &rrok->rrok_count, NFS_MAXDATA); 542 543 return (ret); 544 } 545 546 static struct xdr_discrim rdres_discrim[2] = { 547 { NFS_OK, xdr_rrok }, 548 { __dontcare__, NULL_xdrproc_t } 549 }; 550 551 /* 552 * Reply from remote read 553 */ 554 bool_t 555 xdr_rdresult(XDR *xdrs, struct nfsrdresult *rr) 556 { 557 return (xdr_union(xdrs, (enum_t *)&(rr->rr_status), 558 (caddr_t)&(rr->rr_ok), rdres_discrim, xdr_void)); 559 } 560 561 /* 562 * File attributes which can be set 563 */ 564 bool_t 565 xdr_sattr(XDR *xdrs, struct nfssattr *sa) 566 { 567 if (xdr_u_int(xdrs, &sa->sa_mode) && 568 xdr_u_int(xdrs, &sa->sa_uid) && 569 xdr_u_int(xdrs, &sa->sa_gid) && 570 xdr_u_int(xdrs, &sa->sa_size) && 571 xdr_nfs2_timeval(xdrs, &sa->sa_atime) && 572 xdr_nfs2_timeval(xdrs, &sa->sa_mtime)) { 573 return (TRUE); 574 } 575 return (FALSE); 576 } 577 578 static struct xdr_discrim attrstat_discrim[2] = { 579 { (int)NFS_OK, xdr_fattr }, 580 { __dontcare__, NULL_xdrproc_t } 581 }; 582 583 /* 584 * Reply status with file attributes 585 */ 586 bool_t 587 xdr_attrstat(XDR *xdrs, struct nfsattrstat *ns) 588 { 589 return (xdr_union(xdrs, (enum_t *)&(ns->ns_status), 590 (caddr_t)&(ns->ns_attr), attrstat_discrim, xdr_void)); 591 } 592 593 /* 594 * Fast reply status with file attributes 595 */ 596 bool_t 597 xdr_fastattrstat(XDR *xdrs, struct nfsattrstat *ns) 598 { 599 #if defined(_LITTLE_ENDIAN) 600 /* 601 * we deal with the discriminator; it's an enum 602 */ 603 if (!xdr_fastenum(xdrs, (enum_t *)&ns->ns_status)) 604 return (FALSE); 605 606 if (ns->ns_status == NFS_OK) 607 return (xdr_fastfattr(xdrs, &ns->ns_attr)); 608 #elif defined(_BIG_ENDIAN) 609 if (ns->ns_status == NFS_OK) 610 return (TRUE); 611 #endif 612 return (xdr_fastshorten(xdrs, sizeof (*ns))); 613 } 614 615 /* 616 * NFS_OK part of read sym link reply union 617 */ 618 bool_t 619 xdr_srok(XDR *xdrs, struct nfssrok *srok) 620 { 621 /* 622 * It is just as efficient to xdr_bytes 623 * an array of unknown length as to inline copy it. 624 */ 625 return (xdr_bytes(xdrs, &srok->srok_data, &srok->srok_count, 626 NFS_MAXPATHLEN)); 627 } 628 629 static struct xdr_discrim rdlnres_discrim[2] = { 630 { (int)NFS_OK, xdr_srok }, 631 { __dontcare__, NULL_xdrproc_t } 632 }; 633 634 /* 635 * Result of reading symbolic link 636 */ 637 bool_t 638 xdr_rdlnres(XDR *xdrs, struct nfsrdlnres *rl) 639 { 640 return (xdr_union(xdrs, (enum_t *)&(rl->rl_status), 641 (caddr_t)&(rl->rl_srok), rdlnres_discrim, xdr_void)); 642 } 643 644 /* 645 * Arguments to readdir 646 */ 647 bool_t 648 xdr_rddirargs(XDR *xdrs, struct nfsrddirargs *rda) 649 { 650 int32_t *ptr; 651 int32_t *fhp; 652 rdma_chunkinfo_t rci; 653 struct xdr_ops *xops = xdrrdma_xops(); 654 655 if (xdrs->x_op == XDR_FREE) 656 return (TRUE); 657 658 ptr = XDR_INLINE(xdrs, 659 RNDUP(sizeof (fhandle_t)) + 2 * BYTES_PER_XDR_UNIT); 660 661 if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) && 662 xdrs->x_op == XDR_ENCODE) { 663 rci.rci_type = RCI_REPLY_CHUNK; 664 rci.rci_len = rda->rda_count; 665 XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci); 666 } 667 668 if (ptr != NULL) { 669 if (xdrs->x_op == XDR_DECODE) { 670 fhp = (int32_t *)&rda->rda_fh; 671 *fhp++ = *ptr++; 672 *fhp++ = *ptr++; 673 *fhp++ = *ptr++; 674 *fhp++ = *ptr++; 675 *fhp++ = *ptr++; 676 *fhp++ = *ptr++; 677 *fhp++ = *ptr++; 678 *fhp = *ptr++; 679 rda->rda_offset = IXDR_GET_U_INT32(ptr); 680 rda->rda_count = IXDR_GET_U_INT32(ptr); 681 } else { 682 fhp = (int32_t *)&rda->rda_fh; 683 *ptr++ = *fhp++; 684 *ptr++ = *fhp++; 685 *ptr++ = *fhp++; 686 *ptr++ = *fhp++; 687 *ptr++ = *fhp++; 688 *ptr++ = *fhp++; 689 *ptr++ = *fhp++; 690 *ptr++ = *fhp; 691 IXDR_PUT_U_INT32(ptr, rda->rda_offset); 692 IXDR_PUT_U_INT32(ptr, rda->rda_count); 693 } 694 return (TRUE); 695 } 696 697 if (xdr_fhandle(xdrs, &rda->rda_fh) && 698 xdr_u_int(xdrs, &rda->rda_offset) && 699 xdr_u_int(xdrs, &rda->rda_count)) { 700 return (TRUE); 701 } 702 return (FALSE); 703 } 704 705 706 /* 707 * Directory read reply: 708 * union (enum status) { 709 * NFS_OK: entlist; 710 * boolean eof; 711 * default: 712 * } 713 * 714 * Directory entries 715 * struct direct { 716 * off_t d_off; * offset of next entry * 717 * u_int d_fileno; * inode number of entry * 718 * u_short d_reclen; * length of this record * 719 * u_short d_namlen; * length of string in d_name * 720 * char d_name[MAXNAMLEN + 1]; * name no longer than this * 721 * }; 722 * are on the wire as: 723 * union entlist (boolean valid) { 724 * TRUE: struct otw_dirent; 725 * u_int nxtoffset; 726 * union entlist; 727 * FALSE: 728 * } 729 * where otw_dirent is: 730 * struct dirent { 731 * u_int de_fid; 732 * string de_name<NFS_MAXNAMELEN>; 733 * } 734 */ 735 736 #ifdef nextdp 737 #undef nextdp 738 #endif 739 #define nextdp(dp) ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen)) 740 #ifdef roundup 741 #undef roundup 742 #endif 743 #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) 744 745 /* 746 * ENCODE ONLY 747 */ 748 bool_t 749 xdr_putrddirres(XDR *xdrs, struct nfsrddirres *rd) 750 { 751 struct dirent64 *dp; 752 char *name; 753 int size; 754 uint_t namlen; 755 bool_t true = TRUE; 756 bool_t false = FALSE; 757 int entrysz; 758 int tofit; 759 int bufsize; 760 uint32_t ino, off; 761 762 if (xdrs->x_op != XDR_ENCODE) 763 return (FALSE); 764 if (!xdr_enum(xdrs, (enum_t *)&rd->rd_status)) 765 return (FALSE); 766 if (rd->rd_status != NFS_OK) 767 return (TRUE); 768 769 bufsize = 1 * BYTES_PER_XDR_UNIT; 770 for (size = rd->rd_size, dp = rd->rd_entries; 771 size > 0; 772 size -= dp->d_reclen, dp = nextdp(dp)) { 773 if (dp->d_reclen == 0 /* || DIRSIZ(dp) > dp->d_reclen */) 774 return (FALSE); 775 if (dp->d_ino == 0) 776 continue; 777 ino = (uint32_t)dp->d_ino; /* for LP64 we clip the bits */ 778 if (dp->d_ino != (ino64_t)ino) /* and they better be zeros */ 779 return (FALSE); 780 off = (uint32_t)dp->d_off; 781 name = dp->d_name; 782 namlen = (uint_t)strlen(name); 783 entrysz = (1 + 1 + 1 + 1) * BYTES_PER_XDR_UNIT + 784 roundup(namlen, BYTES_PER_XDR_UNIT); 785 tofit = entrysz + 2 * BYTES_PER_XDR_UNIT; 786 if (bufsize + tofit > rd->rd_bufsize) { 787 rd->rd_eof = FALSE; 788 break; 789 } 790 if (!xdr_bool(xdrs, &true) || 791 !xdr_u_int(xdrs, &ino) || 792 !xdr_bytes(xdrs, &name, &namlen, NFS_MAXNAMLEN) || 793 !xdr_u_int(xdrs, &off)) { 794 return (FALSE); 795 } 796 bufsize += entrysz; 797 } 798 if (!xdr_bool(xdrs, &false)) 799 return (FALSE); 800 if (!xdr_bool(xdrs, &rd->rd_eof)) 801 return (FALSE); 802 return (TRUE); 803 } 804 805 /* 806 * DECODE ONLY 807 */ 808 bool_t 809 xdr_getrddirres(XDR *xdrs, struct nfsrddirres *rd) 810 { 811 struct dirent64 *dp; 812 uint_t namlen; 813 int size; 814 bool_t valid; 815 uint32_t offset; 816 uint_t fileid, this_reclen; 817 818 if (xdrs->x_op != XDR_DECODE) 819 return (FALSE); 820 821 if (!xdr_enum(xdrs, (enum_t *)&rd->rd_status)) 822 return (FALSE); 823 if (rd->rd_status != NFS_OK) 824 return (TRUE); 825 826 size = rd->rd_size; 827 dp = rd->rd_entries; 828 offset = rd->rd_offset; 829 for (;;) { 830 if (!xdr_bool(xdrs, &valid)) 831 return (FALSE); 832 if (!valid) 833 break; 834 if (!xdr_u_int(xdrs, &fileid) || 835 !xdr_u_int(xdrs, &namlen)) 836 return (FALSE); 837 this_reclen = DIRENT64_RECLEN(namlen); 838 if (this_reclen > size) { 839 rd->rd_eof = FALSE; 840 goto bufovflw; 841 } 842 if (!xdr_opaque(xdrs, dp->d_name, namlen)|| 843 !xdr_u_int(xdrs, &offset)) { 844 return (FALSE); 845 } 846 bzero(&dp->d_name[namlen], 847 DIRENT64_NAMELEN(this_reclen) - namlen); 848 dp->d_ino = (ino64_t)fileid; 849 dp->d_reclen = this_reclen; 850 dp->d_off = (off64_t)offset; 851 size -= dp->d_reclen; 852 dp = nextdp(dp); 853 } 854 if (!xdr_bool(xdrs, &rd->rd_eof)) 855 return (FALSE); 856 bufovflw: 857 rd->rd_size = (uint32_t)((char *)dp - (char *)(rd->rd_entries)); 858 rd->rd_offset = offset; 859 return (TRUE); 860 } 861 862 /* 863 * Arguments for directory operations 864 */ 865 bool_t 866 xdr_diropargs(XDR *xdrs, struct nfsdiropargs *da) 867 { 868 int32_t *ptr; 869 int32_t *fhp; 870 uint32_t size; 871 uint32_t nodesize; 872 int i; 873 int rndup; 874 char *cptr; 875 876 if (xdrs->x_op == XDR_DECODE) { 877 da->da_fhandle = &da->da_fhandle_buf; 878 ptr = XDR_INLINE(xdrs, RNDUP(sizeof (fhandle_t)) + 879 1 * BYTES_PER_XDR_UNIT); 880 if (ptr != NULL) { 881 fhp = (int32_t *)da->da_fhandle; 882 *fhp++ = *ptr++; 883 *fhp++ = *ptr++; 884 *fhp++ = *ptr++; 885 *fhp++ = *ptr++; 886 *fhp++ = *ptr++; 887 *fhp++ = *ptr++; 888 *fhp++ = *ptr++; 889 *fhp = *ptr++; 890 size = IXDR_GET_U_INT32(ptr); 891 if (size > NFS_MAXNAMLEN) 892 return (FALSE); 893 nodesize = size + 1; 894 if (nodesize == 0) 895 return (TRUE); 896 if (da->da_name == NULL) { 897 da->da_name = kmem_alloc(nodesize, KM_NOSLEEP); 898 if (da->da_name == NULL) 899 return (FALSE); 900 da->da_flags |= DA_FREENAME; 901 } 902 ptr = XDR_INLINE(xdrs, RNDUP(size)); 903 if (ptr == NULL) { 904 if (!xdr_opaque(xdrs, da->da_name, size)) { 905 if (da->da_flags & DA_FREENAME) { 906 kmem_free(da->da_name, 907 nodesize); 908 da->da_name = NULL; 909 } 910 return (FALSE); 911 } 912 da->da_name[size] = '\0'; 913 if (strlen(da->da_name) != size) { 914 if (da->da_flags & DA_FREENAME) { 915 kmem_free(da->da_name, 916 nodesize); 917 da->da_name = NULL; 918 } 919 return (FALSE); 920 } 921 return (TRUE); 922 } 923 bcopy(ptr, da->da_name, size); 924 da->da_name[size] = '\0'; 925 if (strlen(da->da_name) != size) { 926 if (da->da_flags & DA_FREENAME) { 927 kmem_free(da->da_name, nodesize); 928 da->da_name = NULL; 929 } 930 return (FALSE); 931 } 932 return (TRUE); 933 } 934 if (da->da_name == NULL) 935 da->da_flags |= DA_FREENAME; 936 } 937 938 if (xdrs->x_op == XDR_ENCODE) { 939 size = (uint32_t)strlen(da->da_name); 940 if (size > NFS_MAXNAMLEN) 941 return (FALSE); 942 ptr = XDR_INLINE(xdrs, (int)(RNDUP(sizeof (fhandle_t)) + 943 1 * BYTES_PER_XDR_UNIT + RNDUP(size))); 944 if (ptr != NULL) { 945 fhp = (int32_t *)da->da_fhandle; 946 *ptr++ = *fhp++; 947 *ptr++ = *fhp++; 948 *ptr++ = *fhp++; 949 *ptr++ = *fhp++; 950 *ptr++ = *fhp++; 951 *ptr++ = *fhp++; 952 *ptr++ = *fhp++; 953 *ptr++ = *fhp; 954 IXDR_PUT_U_INT32(ptr, (uint32_t)size); 955 bcopy(da->da_name, ptr, size); 956 rndup = BYTES_PER_XDR_UNIT - 957 (size % BYTES_PER_XDR_UNIT); 958 if (rndup != BYTES_PER_XDR_UNIT) { 959 cptr = (char *)ptr + size; 960 for (i = 0; i < rndup; i++) 961 *cptr++ = '\0'; 962 } 963 return (TRUE); 964 } 965 } 966 967 if (xdrs->x_op == XDR_FREE) { 968 if (da->da_name == NULL) 969 return (TRUE); 970 size = (uint32_t)strlen(da->da_name); 971 if (size > NFS_MAXNAMLEN) 972 return (FALSE); 973 if (da->da_flags & DA_FREENAME) 974 kmem_free(da->da_name, size + 1); 975 da->da_name = NULL; 976 return (TRUE); 977 } 978 979 if (xdr_fhandle(xdrs, da->da_fhandle) && 980 xdr_string(xdrs, &da->da_name, NFS_MAXNAMLEN)) { 981 return (TRUE); 982 } 983 return (FALSE); 984 } 985 986 /* 987 * NFS_OK part of directory operation result 988 */ 989 bool_t 990 xdr_drok(XDR *xdrs, struct nfsdrok *drok) 991 { 992 int32_t *ptr; 993 int32_t *fhp; 994 struct nfsfattr *na; 995 996 if (xdrs->x_op == XDR_FREE) 997 return (TRUE); 998 999 ptr = XDR_INLINE(xdrs, 1000 RNDUP(sizeof (fhandle_t)) + 17 * BYTES_PER_XDR_UNIT); 1001 if (ptr != NULL) { 1002 if (xdrs->x_op == XDR_DECODE) { 1003 fhp = (int32_t *)&drok->drok_fhandle; 1004 *fhp++ = *ptr++; 1005 *fhp++ = *ptr++; 1006 *fhp++ = *ptr++; 1007 *fhp++ = *ptr++; 1008 *fhp++ = *ptr++; 1009 *fhp++ = *ptr++; 1010 *fhp++ = *ptr++; 1011 *fhp = *ptr++; 1012 na = &drok->drok_attr; 1013 na->na_type = IXDR_GET_ENUM(ptr, enum nfsftype); 1014 na->na_mode = IXDR_GET_U_INT32(ptr); 1015 na->na_nlink = IXDR_GET_U_INT32(ptr); 1016 na->na_uid = IXDR_GET_U_INT32(ptr); 1017 na->na_gid = IXDR_GET_U_INT32(ptr); 1018 na->na_size = IXDR_GET_U_INT32(ptr); 1019 na->na_blocksize = IXDR_GET_U_INT32(ptr); 1020 na->na_rdev = IXDR_GET_U_INT32(ptr); 1021 na->na_blocks = IXDR_GET_U_INT32(ptr); 1022 na->na_fsid = IXDR_GET_U_INT32(ptr); 1023 na->na_nodeid = IXDR_GET_U_INT32(ptr); 1024 na->na_atime.tv_sec = IXDR_GET_U_INT32(ptr); 1025 na->na_atime.tv_usec = IXDR_GET_U_INT32(ptr); 1026 na->na_mtime.tv_sec = IXDR_GET_U_INT32(ptr); 1027 na->na_mtime.tv_usec = IXDR_GET_U_INT32(ptr); 1028 na->na_ctime.tv_sec = IXDR_GET_U_INT32(ptr); 1029 na->na_ctime.tv_usec = IXDR_GET_U_INT32(ptr); 1030 } else { 1031 fhp = (int32_t *)&drok->drok_fhandle; 1032 *ptr++ = *fhp++; 1033 *ptr++ = *fhp++; 1034 *ptr++ = *fhp++; 1035 *ptr++ = *fhp++; 1036 *ptr++ = *fhp++; 1037 *ptr++ = *fhp++; 1038 *ptr++ = *fhp++; 1039 *ptr++ = *fhp; 1040 na = &drok->drok_attr; 1041 IXDR_PUT_ENUM(ptr, na->na_type); 1042 IXDR_PUT_U_INT32(ptr, na->na_mode); 1043 IXDR_PUT_U_INT32(ptr, na->na_nlink); 1044 IXDR_PUT_U_INT32(ptr, na->na_uid); 1045 IXDR_PUT_U_INT32(ptr, na->na_gid); 1046 IXDR_PUT_U_INT32(ptr, na->na_size); 1047 IXDR_PUT_U_INT32(ptr, na->na_blocksize); 1048 IXDR_PUT_U_INT32(ptr, na->na_rdev); 1049 IXDR_PUT_U_INT32(ptr, na->na_blocks); 1050 IXDR_PUT_U_INT32(ptr, na->na_fsid); 1051 IXDR_PUT_U_INT32(ptr, na->na_nodeid); 1052 IXDR_PUT_U_INT32(ptr, na->na_atime.tv_sec); 1053 IXDR_PUT_U_INT32(ptr, na->na_atime.tv_usec); 1054 IXDR_PUT_U_INT32(ptr, na->na_mtime.tv_sec); 1055 IXDR_PUT_U_INT32(ptr, na->na_mtime.tv_usec); 1056 IXDR_PUT_U_INT32(ptr, na->na_ctime.tv_sec); 1057 IXDR_PUT_U_INT32(ptr, na->na_ctime.tv_usec); 1058 } 1059 return (TRUE); 1060 } 1061 1062 if (xdr_fhandle(xdrs, &drok->drok_fhandle) && 1063 xdr_fattr(xdrs, &drok->drok_attr)) { 1064 return (TRUE); 1065 } 1066 return (FALSE); 1067 } 1068 1069 #ifdef _LITTLE_ENDIAN 1070 bool_t 1071 xdr_fastdrok(XDR *xdrs, struct nfsdrok *drok) 1072 { 1073 struct nfsfattr *na; 1074 1075 if (xdrs->x_op == XDR_FREE) 1076 return (TRUE); 1077 if (xdrs->x_op == XDR_DECODE) 1078 return (FALSE); 1079 1080 na = &drok->drok_attr; 1081 na->na_type = (enum nfsftype)htonl(na->na_type); 1082 na->na_mode = (uint32_t)htonl(na->na_mode); 1083 na->na_nlink = (uint32_t)htonl(na->na_nlink); 1084 na->na_uid = (uint32_t)htonl(na->na_uid); 1085 na->na_gid = (uint32_t)htonl(na->na_gid); 1086 na->na_size = (uint32_t)htonl(na->na_size); 1087 na->na_blocksize = (uint32_t)htonl(na->na_blocksize); 1088 na->na_rdev = (uint32_t)htonl(na->na_rdev); 1089 na->na_blocks = (uint32_t)htonl(na->na_blocks); 1090 na->na_fsid = (uint32_t)htonl(na->na_fsid); 1091 na->na_nodeid = (uint32_t)htonl(na->na_nodeid); 1092 na->na_atime.tv_sec = htonl(na->na_atime.tv_sec); 1093 na->na_atime.tv_usec = htonl(na->na_atime.tv_usec); 1094 na->na_mtime.tv_sec = htonl(na->na_mtime.tv_sec); 1095 na->na_mtime.tv_usec = htonl(na->na_mtime.tv_usec); 1096 na->na_ctime.tv_sec = htonl(na->na_ctime.tv_sec); 1097 na->na_ctime.tv_usec = htonl(na->na_ctime.tv_usec); 1098 return (TRUE); 1099 } 1100 #endif 1101 1102 static struct xdr_discrim diropres_discrim[2] = { 1103 { NFS_OK, xdr_drok }, 1104 { __dontcare__, NULL_xdrproc_t } 1105 }; 1106 1107 /* 1108 * Results from directory operation 1109 */ 1110 bool_t 1111 xdr_diropres(XDR *xdrs, struct nfsdiropres *dr) 1112 { 1113 return (xdr_union(xdrs, (enum_t *)&(dr->dr_status), 1114 (caddr_t)&(dr->dr_drok), diropres_discrim, xdr_void)); 1115 } 1116 1117 /* 1118 * Results from directory operation 1119 */ 1120 bool_t 1121 xdr_fastdiropres(XDR *xdrs, struct nfsdiropres *dr) 1122 { 1123 #if defined(_LITTLE_ENDIAN) 1124 /* 1125 * we deal with the discriminator; it's an enum 1126 */ 1127 if (!xdr_fastenum(xdrs, (enum_t *)&dr->dr_status)) 1128 return (FALSE); 1129 1130 if (dr->dr_status == NFS_OK) 1131 return (xdr_fastdrok(xdrs, &dr->dr_drok)); 1132 #elif defined(_BIG_ENDIAN) 1133 if (dr->dr_status == NFS_OK) 1134 return (TRUE); 1135 #endif 1136 return (xdr_fastshorten(xdrs, sizeof (*dr))); 1137 } 1138 1139 /* 1140 * Time Structure, unsigned 1141 */ 1142 bool_t 1143 xdr_nfs2_timeval(XDR *xdrs, struct nfs2_timeval *tv) 1144 { 1145 if (xdr_u_int(xdrs, &tv->tv_sec) && 1146 xdr_u_int(xdrs, &tv->tv_usec)) 1147 return (TRUE); 1148 return (FALSE); 1149 } 1150 1151 /* 1152 * arguments to setattr 1153 */ 1154 bool_t 1155 xdr_saargs(XDR *xdrs, struct nfssaargs *argp) 1156 { 1157 int32_t *ptr; 1158 int32_t *arg; 1159 struct nfssattr *sa; 1160 1161 if (xdrs->x_op == XDR_FREE) 1162 return (TRUE); 1163 1164 ptr = XDR_INLINE(xdrs, 1165 RNDUP(sizeof (fhandle_t)) + 8 * BYTES_PER_XDR_UNIT); 1166 if (ptr != NULL) { 1167 if (xdrs->x_op == XDR_DECODE) { 1168 arg = (int32_t *)&argp->saa_fh; 1169 *arg++ = *ptr++; 1170 *arg++ = *ptr++; 1171 *arg++ = *ptr++; 1172 *arg++ = *ptr++; 1173 *arg++ = *ptr++; 1174 *arg++ = *ptr++; 1175 *arg++ = *ptr++; 1176 *arg = *ptr++; 1177 sa = &argp->saa_sa; 1178 sa->sa_mode = IXDR_GET_U_INT32(ptr); 1179 sa->sa_uid = IXDR_GET_U_INT32(ptr); 1180 sa->sa_gid = IXDR_GET_U_INT32(ptr); 1181 sa->sa_size = IXDR_GET_U_INT32(ptr); 1182 sa->sa_atime.tv_sec = IXDR_GET_U_INT32(ptr); 1183 sa->sa_atime.tv_usec = IXDR_GET_U_INT32(ptr); 1184 sa->sa_mtime.tv_sec = IXDR_GET_U_INT32(ptr); 1185 sa->sa_mtime.tv_usec = IXDR_GET_U_INT32(ptr); 1186 } else { 1187 arg = (int32_t *)&argp->saa_fh; 1188 *ptr++ = *arg++; 1189 *ptr++ = *arg++; 1190 *ptr++ = *arg++; 1191 *ptr++ = *arg++; 1192 *ptr++ = *arg++; 1193 *ptr++ = *arg++; 1194 *ptr++ = *arg++; 1195 *ptr++ = *arg; 1196 sa = &argp->saa_sa; 1197 IXDR_PUT_U_INT32(ptr, sa->sa_mode); 1198 IXDR_PUT_U_INT32(ptr, sa->sa_uid); 1199 IXDR_PUT_U_INT32(ptr, sa->sa_gid); 1200 IXDR_PUT_U_INT32(ptr, sa->sa_size); 1201 IXDR_PUT_U_INT32(ptr, sa->sa_atime.tv_sec); 1202 IXDR_PUT_U_INT32(ptr, sa->sa_atime.tv_usec); 1203 IXDR_PUT_U_INT32(ptr, sa->sa_mtime.tv_sec); 1204 IXDR_PUT_U_INT32(ptr, sa->sa_mtime.tv_usec); 1205 } 1206 return (TRUE); 1207 } 1208 1209 if (xdr_fhandle(xdrs, &argp->saa_fh) && 1210 xdr_sattr(xdrs, &argp->saa_sa)) { 1211 return (TRUE); 1212 } 1213 return (FALSE); 1214 } 1215 1216 1217 /* 1218 * arguments to create and mkdir 1219 */ 1220 bool_t 1221 xdr_creatargs(XDR *xdrs, struct nfscreatargs *argp) 1222 { 1223 argp->ca_sa = &argp->ca_sa_buf; 1224 1225 if (xdrs->x_op == XDR_DECODE) 1226 argp->ca_sa = &argp->ca_sa_buf; 1227 if (xdr_diropargs(xdrs, &argp->ca_da) && 1228 xdr_sattr(xdrs, argp->ca_sa)) { 1229 return (TRUE); 1230 } 1231 return (FALSE); 1232 } 1233 1234 /* 1235 * arguments to link 1236 */ 1237 bool_t 1238 xdr_linkargs(XDR *xdrs, struct nfslinkargs *argp) 1239 { 1240 if (xdrs->x_op == XDR_DECODE) 1241 argp->la_from = &argp->la_from_buf; 1242 if (xdr_fhandle(xdrs, argp->la_from) && 1243 xdr_diropargs(xdrs, &argp->la_to)) { 1244 return (TRUE); 1245 } 1246 return (FALSE); 1247 } 1248 1249 /* 1250 * arguments to rename 1251 */ 1252 bool_t 1253 xdr_rnmargs(XDR *xdrs, struct nfsrnmargs *argp) 1254 { 1255 if (xdr_diropargs(xdrs, &argp->rna_from) && 1256 xdr_diropargs(xdrs, &argp->rna_to)) 1257 return (TRUE); 1258 return (FALSE); 1259 } 1260 1261 1262 /* 1263 * arguments to symlink 1264 */ 1265 bool_t 1266 xdr_slargs(XDR *xdrs, struct nfsslargs *argp) 1267 { 1268 if (xdrs->x_op == XDR_FREE) { 1269 if (!xdr_diropargs(xdrs, &argp->sla_from)) 1270 return (FALSE); 1271 if ((argp->sla_tnm_flags & SLA_FREETNM) && 1272 !xdr_string(xdrs, &argp->sla_tnm, (uint_t)NFS_MAXPATHLEN)) 1273 return (FALSE); 1274 return (TRUE); 1275 } 1276 1277 if (xdrs->x_op == XDR_DECODE) { 1278 argp->sla_sa = &argp->sla_sa_buf; 1279 if (argp->sla_tnm == NULL) 1280 argp->sla_tnm_flags |= SLA_FREETNM; 1281 } 1282 1283 if (xdr_diropargs(xdrs, &argp->sla_from) && 1284 xdr_string(xdrs, &argp->sla_tnm, (uint_t)NFS_MAXPATHLEN) && 1285 xdr_sattr(xdrs, argp->sla_sa)) { 1286 return (TRUE); 1287 } 1288 return (FALSE); 1289 } 1290 1291 1292 /* 1293 * NFS_OK part of statfs operation 1294 */ 1295 bool_t 1296 xdr_fsok(XDR *xdrs, struct nfsstatfsok *fsok) 1297 { 1298 int32_t *ptr; 1299 1300 if (xdrs->x_op == XDR_FREE) 1301 return (TRUE); 1302 1303 ptr = XDR_INLINE(xdrs, 5 * BYTES_PER_XDR_UNIT); 1304 if (ptr != NULL) { 1305 if (xdrs->x_op == XDR_DECODE) { 1306 fsok->fsok_tsize = IXDR_GET_INT32(ptr); 1307 fsok->fsok_bsize = IXDR_GET_INT32(ptr); 1308 fsok->fsok_blocks = IXDR_GET_INT32(ptr); 1309 fsok->fsok_bfree = IXDR_GET_INT32(ptr); 1310 fsok->fsok_bavail = IXDR_GET_INT32(ptr); 1311 } else { 1312 IXDR_PUT_INT32(ptr, fsok->fsok_tsize); 1313 IXDR_PUT_INT32(ptr, fsok->fsok_bsize); 1314 IXDR_PUT_INT32(ptr, fsok->fsok_blocks); 1315 IXDR_PUT_INT32(ptr, fsok->fsok_bfree); 1316 IXDR_PUT_INT32(ptr, fsok->fsok_bavail); 1317 } 1318 return (TRUE); 1319 } 1320 1321 if (xdr_u_int(xdrs, &fsok->fsok_tsize) && 1322 xdr_u_int(xdrs, &fsok->fsok_bsize) && 1323 xdr_u_int(xdrs, &fsok->fsok_blocks) && 1324 xdr_u_int(xdrs, &fsok->fsok_bfree) && 1325 xdr_u_int(xdrs, &fsok->fsok_bavail)) { 1326 return (TRUE); 1327 } 1328 return (FALSE); 1329 } 1330 1331 #ifdef _LITTLE_ENDIAN 1332 bool_t 1333 xdr_fastfsok(XDR *xdrs, struct nfsstatfsok *fsok) 1334 { 1335 1336 if (xdrs->x_op == XDR_FREE) 1337 return (TRUE); 1338 if (xdrs->x_op == XDR_DECODE) 1339 return (FALSE); 1340 1341 fsok->fsok_tsize = htonl(fsok->fsok_tsize); 1342 fsok->fsok_bsize = htonl(fsok->fsok_bsize); 1343 fsok->fsok_blocks = htonl(fsok->fsok_blocks); 1344 fsok->fsok_bfree = htonl(fsok->fsok_bfree); 1345 fsok->fsok_bavail = htonl(fsok->fsok_bavail); 1346 return (TRUE); 1347 } 1348 #endif 1349 1350 static struct xdr_discrim statfs_discrim[2] = { 1351 { NFS_OK, xdr_fsok }, 1352 { __dontcare__, NULL_xdrproc_t } 1353 }; 1354 1355 /* 1356 * Results of statfs operation 1357 */ 1358 bool_t 1359 xdr_statfs(XDR *xdrs, struct nfsstatfs *fs) 1360 { 1361 return (xdr_union(xdrs, (enum_t *)&(fs->fs_status), 1362 (caddr_t)&(fs->fs_fsok), statfs_discrim, xdr_void)); 1363 } 1364 1365 /* 1366 * Results of statfs operation 1367 */ 1368 bool_t 1369 xdr_faststatfs(XDR *xdrs, struct nfsstatfs *fs) 1370 { 1371 #if defined(_LITTLE_ENDIAN) 1372 /* 1373 * we deal with the discriminator; it's an enum 1374 */ 1375 if (!xdr_fastenum(xdrs, (enum_t *)&fs->fs_status)) 1376 return (FALSE); 1377 1378 if (fs->fs_status == NFS_OK) 1379 return (xdr_fastfsok(xdrs, &fs->fs_fsok)); 1380 #elif defined(_BIG_ENDIAN) 1381 if (fs->fs_status == NFS_OK) 1382 return (TRUE); 1383 #endif 1384 return (xdr_fastshorten(xdrs, sizeof (*fs))); 1385 } 1386 1387 #ifdef _LITTLE_ENDIAN 1388 /* 1389 * XDR enumerations 1390 */ 1391 #ifndef lint 1392 static enum sizecheck { SIZEVAL } sizecheckvar; /* used to find the size of */ 1393 /* an enum */ 1394 #endif 1395 bool_t 1396 xdr_fastenum(XDR *xdrs, enum_t *ep) 1397 { 1398 if (xdrs->x_op == XDR_FREE) 1399 return (TRUE); 1400 if (xdrs->x_op == XDR_DECODE) 1401 return (FALSE); 1402 1403 #ifndef lint 1404 /* 1405 * enums are treated as ints 1406 */ 1407 if (sizeof (sizecheckvar) == sizeof (int32_t)) { 1408 *ep = (enum_t)htonl((int32_t)(*ep)); 1409 } else if (sizeof (sizecheckvar) == sizeof (short)) { 1410 *ep = (enum_t)htons((short)(*ep)); 1411 } else { 1412 return (FALSE); 1413 } 1414 return (TRUE); 1415 #else 1416 (void) (xdr_short(xdrs, (short *)ep)); 1417 return (xdr_int(xdrs, (int *)ep)); 1418 #endif 1419 } 1420 #endif 1421 1422 static bool_t 1423 xdr_fastshorten(XDR *xdrs, uint_t ressize) 1424 { 1425 uint_t curpos; 1426 1427 curpos = XDR_GETPOS(xdrs); 1428 ressize -= BYTES_PER_XDR_UNIT; 1429 curpos -= ressize; 1430 return (XDR_SETPOS(xdrs, curpos)); 1431 } 1432