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/cmn_err.h> 42 #include <sys/dnlc.h> 43 #include <sys/cred.h> 44 #include <sys/time.h> 45 #include <sys/sdt.h> 46 47 #include <rpc/types.h> 48 #include <rpc/xdr.h> 49 50 #include <nfs/nfs.h> 51 #include <nfs/rnode.h> 52 #include <rpc/rpc_rdma.h> 53 54 /* 55 * These are the XDR routines used to serialize and deserialize 56 * the various structures passed as parameters across the network 57 * between NFS clients and servers. 58 */ 59 60 /* 61 * XDR null terminated ASCII strings 62 * xdr_string3 deals with "C strings" - arrays of bytes that are 63 * terminated by a NULL character. The parameter cpp references a 64 * pointer to storage; If the pointer is null, then the necessary 65 * storage is allocated. The last parameter is the max allowed length 66 * of the string as allowed by the system. The NFS Version 3 protocol 67 * does not place limits on strings, but the implementation needs to 68 * place a reasonable limit to avoid problems. 69 */ 70 bool_t 71 xdr_string3(XDR *xdrs, char **cpp, uint_t maxsize) 72 { 73 char *sp; 74 uint_t size; 75 uint_t nodesize; 76 bool_t mem_alloced = FALSE; 77 78 /* 79 * first deal with the length since xdr strings are counted-strings 80 */ 81 sp = *cpp; 82 switch (xdrs->x_op) { 83 case XDR_FREE: 84 if (sp == NULL || sp == nfs3nametoolong) 85 return (TRUE); /* already free */ 86 /* FALLTHROUGH */ 87 88 case XDR_ENCODE: 89 size = (uint_t)strlen(sp); 90 break; 91 92 case XDR_DECODE: 93 break; 94 } 95 96 if (!xdr_u_int(xdrs, &size)) 97 return (FALSE); 98 99 /* 100 * now deal with the actual bytes 101 */ 102 switch (xdrs->x_op) { 103 case XDR_DECODE: 104 if (size >= maxsize) { 105 *cpp = nfs3nametoolong; 106 if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &size)) 107 return (FALSE); 108 return (TRUE); 109 } 110 nodesize = size + 1; 111 if (nodesize == 0) 112 return (TRUE); 113 if (sp == NULL) { 114 sp = kmem_alloc(nodesize, KM_NOSLEEP); 115 *cpp = sp; 116 if (sp == NULL) 117 return (FALSE); 118 mem_alloced = TRUE; 119 } 120 sp[size] = 0; 121 122 if (xdr_opaque(xdrs, sp, size)) { 123 if (strlen(sp) != size) { 124 if (mem_alloced) 125 kmem_free(sp, nodesize); 126 *cpp = NULL; 127 return (FALSE); 128 } 129 } else { 130 if (mem_alloced) 131 kmem_free(sp, nodesize); 132 *cpp = NULL; 133 return (FALSE); 134 } 135 return (TRUE); 136 137 case XDR_ENCODE: 138 return (xdr_opaque(xdrs, sp, size)); 139 140 case XDR_FREE: 141 nodesize = size + 1; 142 kmem_free(sp, nodesize); 143 *cpp = NULL; 144 return (TRUE); 145 } 146 147 return (FALSE); 148 } 149 150 /* 151 * XDR_INLINE decode a filehandle. 152 */ 153 bool_t 154 xdr_inline_decode_nfs_fh3(uint32_t *ptr, nfs_fh3 *fhp, uint32_t fhsize) 155 { 156 uchar_t *bp = (uchar_t *)ptr; 157 uchar_t *cp; 158 uint32_t dsize; 159 uintptr_t resid; 160 161 /* 162 * Check to see if what the client sent us is bigger or smaller 163 * than what we can ever possibly send out. NFS_FHMAXDATA is 164 * unfortunately badly named as it is no longer the max and is 165 * really the min of what is sent over the wire. 166 */ 167 if (fhsize > sizeof (fhandle3_t) || fhsize < (sizeof (fsid_t) + 168 sizeof (ushort_t) + NFS_FHMAXDATA + 169 sizeof (ushort_t) + NFS_FHMAXDATA)) { 170 return (FALSE); 171 } 172 173 /* 174 * All internal parts of a filehandle are in native byte order. 175 * 176 * Decode what should be fh3_fsid, it is aligned. 177 */ 178 fhp->fh3_fsid.val[0] = *(uint32_t *)bp; 179 bp += BYTES_PER_XDR_UNIT; 180 fhp->fh3_fsid.val[1] = *(uint32_t *)bp; 181 bp += BYTES_PER_XDR_UNIT; 182 183 /* 184 * Decode what should be fh3_len. fh3_len is two bytes, so we're 185 * unaligned now. 186 */ 187 cp = (uchar_t *)&fhp->fh3_len; 188 *cp++ = *bp++; 189 *cp++ = *bp++; 190 fhsize -= 2 * BYTES_PER_XDR_UNIT + sizeof (ushort_t); 191 192 /* 193 * For backwards compatability, the fid length may be less than 194 * NFS_FHMAXDATA, but it was always encoded as NFS_FHMAXDATA bytes. 195 */ 196 dsize = fhp->fh3_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh3_len; 197 198 /* 199 * Make sure the client isn't sending us a bogus length for fh3x_data. 200 */ 201 if (fhsize < dsize) 202 return (FALSE); 203 bcopy(bp, fhp->fh3_data, dsize); 204 bp += dsize; 205 fhsize -= dsize; 206 207 if (fhsize < sizeof (ushort_t)) 208 return (FALSE); 209 cp = (uchar_t *)&fhp->fh3_xlen; 210 *cp++ = *bp++; 211 *cp++ = *bp++; 212 fhsize -= sizeof (ushort_t); 213 214 dsize = fhp->fh3_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh3_xlen; 215 216 /* 217 * Make sure the client isn't sending us a bogus length for fh3x_xdata. 218 */ 219 if (fhsize < dsize) 220 return (FALSE); 221 bcopy(bp, fhp->fh3_xdata, dsize); 222 fhsize -= dsize; 223 bp += dsize; 224 225 /* 226 * We realign things on purpose, so skip any padding 227 */ 228 resid = (uintptr_t)bp % BYTES_PER_XDR_UNIT; 229 if (resid != 0) { 230 if (fhsize < (BYTES_PER_XDR_UNIT - resid)) 231 return (FALSE); 232 bp += BYTES_PER_XDR_UNIT - resid; 233 fhsize -= BYTES_PER_XDR_UNIT - resid; 234 } 235 236 /* 237 * Make sure client didn't send extra bytes 238 */ 239 if (fhsize != 0) 240 return (FALSE); 241 return (TRUE); 242 } 243 244 static bool_t 245 xdr_decode_nfs_fh3(XDR *xdrs, nfs_fh3 *objp) 246 { 247 uint32_t fhsize; /* filehandle size */ 248 uint32_t bufsize; 249 rpc_inline_t *ptr; 250 uchar_t *bp; 251 252 ASSERT(xdrs->x_op == XDR_DECODE); 253 254 /* 255 * Retrieve the filehandle length. 256 */ 257 if (!XDR_GETINT32(xdrs, (int32_t *)&fhsize)) 258 return (FALSE); 259 260 bzero(objp->fh3_u.data, sizeof (objp->fh3_u.data)); 261 objp->fh3_length = 0; 262 263 /* 264 * Check to see if what the client sent us is bigger or smaller 265 * than what we can ever possibly send out. NFS_FHMAXDATA is 266 * unfortunately badly named as it is no longer the max and is 267 * really the min of what is sent over the wire. 268 */ 269 if (fhsize > sizeof (fhandle3_t) || fhsize < (sizeof (fsid_t) + 270 sizeof (ushort_t) + NFS_FHMAXDATA + 271 sizeof (ushort_t) + NFS_FHMAXDATA)) { 272 if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &fhsize)) 273 return (FALSE); 274 return (TRUE); 275 } 276 277 /* 278 * bring in fhsize plus any padding 279 */ 280 bufsize = RNDUP(fhsize); 281 ptr = XDR_INLINE(xdrs, bufsize); 282 bp = (uchar_t *)ptr; 283 if (ptr == NULL) { 284 bp = kmem_alloc(bufsize, KM_SLEEP); 285 if (!xdr_opaque(xdrs, (char *)bp, bufsize)) { 286 kmem_free(bp, bufsize); 287 return (FALSE); 288 } 289 } 290 291 objp->fh3_length = sizeof (fhandle3_t); 292 293 if (xdr_inline_decode_nfs_fh3((uint32_t *)bp, objp, fhsize) == FALSE) { 294 /* 295 * If in the process of decoding we find the file handle 296 * is not correctly formed, we need to continue decoding 297 * and trigger an NFS layer error. Set the nfs_fh3_len to 298 * zero so it gets caught as a bad length. 299 */ 300 bzero(objp->fh3_u.data, sizeof (objp->fh3_u.data)); 301 objp->fh3_length = 0; 302 } 303 304 if (ptr == NULL) 305 kmem_free(bp, bufsize); 306 return (TRUE); 307 } 308 309 /* 310 * XDR_INLINE encode a filehandle. 311 */ 312 bool_t 313 xdr_inline_encode_nfs_fh3(uint32_t **ptrp, uint32_t *ptr_redzone, 314 nfs_fh3 *fhp) 315 { 316 uint32_t *ptr = *ptrp; 317 uchar_t *cp; 318 uint_t otw_len, fsize, xsize; /* otw, file, and export sizes */ 319 uint32_t padword; 320 321 fsize = fhp->fh3_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh3_len; 322 xsize = fhp->fh3_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh3_xlen; 323 324 /* 325 * First get the initial and variable sized part of the filehandle. 326 */ 327 otw_len = sizeof (fhp->fh3_fsid) + 328 sizeof (fhp->fh3_len) + fsize + 329 sizeof (fhp->fh3_xlen) + xsize; 330 331 /* 332 * Round out to a full word. 333 */ 334 otw_len = RNDUP(otw_len); 335 padword = (otw_len / BYTES_PER_XDR_UNIT); /* includes fhlen */ 336 337 /* 338 * Make sure we don't exceed our buffer. 339 */ 340 if ((ptr + (otw_len / BYTES_PER_XDR_UNIT) + 1) > ptr_redzone) 341 return (FALSE); 342 343 /* 344 * Zero out the pading. 345 */ 346 ptr[padword] = 0; 347 348 IXDR_PUT_U_INT32(ptr, otw_len); 349 350 /* 351 * The rest of the filehandle is in native byteorder 352 */ 353 /* fh3_fsid */ 354 *ptr++ = (uint32_t)fhp->fh3_fsid.val[0]; 355 *ptr++ = (uint32_t)fhp->fh3_fsid.val[1]; 356 357 /* 358 * Since the next pieces are unaligned, we need to 359 * do bytewise copies. 360 */ 361 cp = (uchar_t *)ptr; 362 363 /* fh3_len + fh3_data */ 364 bcopy(&fhp->fh3_len, cp, sizeof (fhp->fh3_len) + fsize); 365 cp += sizeof (fhp->fh3_len) + fsize; 366 367 /* fh3_xlen + fh3_xdata */ 368 bcopy(&fhp->fh3_xlen, cp, sizeof (fhp->fh3_xlen) + xsize); 369 cp += sizeof (fhp->fh3_xlen) + xsize; 370 371 /* do necessary rounding/padding */ 372 cp = (uchar_t *)RNDUP((uintptr_t)cp); 373 ptr = (uint32_t *)cp; 374 375 /* 376 * With the above padding, we're word aligned again. 377 */ 378 ASSERT(((uintptr_t)ptr % BYTES_PER_XDR_UNIT) == 0); 379 380 *ptrp = ptr; 381 382 return (TRUE); 383 } 384 385 static bool_t 386 xdr_encode_nfs_fh3(XDR *xdrs, nfs_fh3 *objp) 387 { 388 uint_t otw_len, fsize, xsize; /* otw, file, and export sizes */ 389 bool_t ret; 390 rpc_inline_t *ptr; 391 rpc_inline_t *buf = NULL; 392 uint32_t *ptr_redzone; 393 394 ASSERT(xdrs->x_op == XDR_ENCODE); 395 396 fsize = objp->fh3_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : objp->fh3_len; 397 xsize = objp->fh3_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : objp->fh3_xlen; 398 399 /* 400 * First get the over the wire size, it is the 4 bytes 401 * for the length, plus the combined size of the 402 * file handle components. 403 */ 404 otw_len = BYTES_PER_XDR_UNIT + sizeof (objp->fh3_fsid) + 405 sizeof (objp->fh3_len) + fsize + 406 sizeof (objp->fh3_xlen) + xsize; 407 /* 408 * Round out to a full word. 409 */ 410 otw_len = RNDUP(otw_len); 411 412 /* 413 * Next try to inline the XDR stream, if that fails (rare) 414 * allocate a buffer to encode the file handle and then 415 * copy it using xdr_opaque and free the buffer. 416 */ 417 ptr = XDR_INLINE(xdrs, otw_len); 418 if (ptr == NULL) 419 ptr = buf = kmem_alloc(otw_len, KM_SLEEP); 420 421 ptr_redzone = (uint32_t *)(ptr + (otw_len / BYTES_PER_XDR_UNIT)); 422 ret = xdr_inline_encode_nfs_fh3((uint32_t **)&ptr, ptr_redzone, objp); 423 424 if (buf != NULL) { 425 if (ret == TRUE) 426 ret = xdr_opaque(xdrs, (char *)buf, otw_len); 427 kmem_free(buf, otw_len); 428 } 429 return (ret); 430 } 431 432 /* 433 * XDR a NFSv3 filehandle the naive way. 434 */ 435 bool_t 436 xdr_nfs_fh3(XDR *xdrs, nfs_fh3 *objp) 437 { 438 if (xdrs->x_op == XDR_FREE) 439 return (TRUE); 440 441 if (!xdr_u_int(xdrs, &objp->fh3_length)) 442 return (FALSE); 443 444 if (objp->fh3_length > NFS3_FHSIZE) 445 return (FALSE); 446 447 return (xdr_opaque(xdrs, objp->fh3_u.data, objp->fh3_length)); 448 } 449 450 /* 451 * XDR a NFSv3 filehandle with intelligence on the server. 452 * Encoding goes from our in-memory structure to wire format. 453 * Decoding goes from wire format to our in-memory structure. 454 */ 455 bool_t 456 xdr_nfs_fh3_server(XDR *xdrs, nfs_fh3 *objp) 457 { 458 switch (xdrs->x_op) { 459 case XDR_ENCODE: 460 if (objp->fh3_flags & FH_WEBNFS) 461 return (xdr_nfs_fh3(xdrs, objp)); 462 else 463 return (xdr_encode_nfs_fh3(xdrs, objp)); 464 case XDR_DECODE: 465 return (xdr_decode_nfs_fh3(xdrs, objp)); 466 case XDR_FREE: 467 if (objp->fh3_u.data != NULL) 468 bzero(objp->fh3_u.data, sizeof (objp->fh3_u.data)); 469 return (TRUE); 470 } 471 return (FALSE); 472 } 473 474 bool_t 475 xdr_diropargs3(XDR *xdrs, diropargs3 *objp) 476 { 477 switch (xdrs->x_op) { 478 case XDR_FREE: 479 case XDR_ENCODE: 480 if (!xdr_nfs_fh3(xdrs, objp->dirp)) 481 return (FALSE); 482 break; 483 case XDR_DECODE: 484 if (!xdr_nfs_fh3_server(xdrs, &objp->dir)) 485 return (FALSE); 486 break; 487 } 488 return (xdr_string3(xdrs, &objp->name, MAXNAMELEN)); 489 } 490 491 static bool_t 492 xdr_fattr3(XDR *xdrs, fattr3 *na) 493 { 494 int32_t *ptr; 495 496 if (xdrs->x_op == XDR_FREE) 497 return (TRUE); 498 499 ptr = XDR_INLINE(xdrs, NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT); 500 if (ptr != NULL) { 501 if (xdrs->x_op == XDR_DECODE) { 502 na->type = IXDR_GET_ENUM(ptr, enum ftype3); 503 na->mode = IXDR_GET_U_INT32(ptr); 504 na->nlink = IXDR_GET_U_INT32(ptr); 505 na->uid = IXDR_GET_U_INT32(ptr); 506 na->gid = IXDR_GET_U_INT32(ptr); 507 IXDR_GET_U_HYPER(ptr, na->size); 508 IXDR_GET_U_HYPER(ptr, na->used); 509 na->rdev.specdata1 = IXDR_GET_U_INT32(ptr); 510 na->rdev.specdata2 = IXDR_GET_U_INT32(ptr); 511 IXDR_GET_U_HYPER(ptr, na->fsid); 512 IXDR_GET_U_HYPER(ptr, na->fileid); 513 na->atime.seconds = IXDR_GET_U_INT32(ptr); 514 na->atime.nseconds = IXDR_GET_U_INT32(ptr); 515 na->mtime.seconds = IXDR_GET_U_INT32(ptr); 516 na->mtime.nseconds = IXDR_GET_U_INT32(ptr); 517 na->ctime.seconds = IXDR_GET_U_INT32(ptr); 518 na->ctime.nseconds = IXDR_GET_U_INT32(ptr); 519 } else { 520 IXDR_PUT_ENUM(ptr, na->type); 521 IXDR_PUT_U_INT32(ptr, na->mode); 522 IXDR_PUT_U_INT32(ptr, na->nlink); 523 IXDR_PUT_U_INT32(ptr, na->uid); 524 IXDR_PUT_U_INT32(ptr, na->gid); 525 IXDR_PUT_U_HYPER(ptr, na->size); 526 IXDR_PUT_U_HYPER(ptr, na->used); 527 IXDR_PUT_U_INT32(ptr, na->rdev.specdata1); 528 IXDR_PUT_U_INT32(ptr, na->rdev.specdata2); 529 IXDR_PUT_U_HYPER(ptr, na->fsid); 530 IXDR_PUT_U_HYPER(ptr, na->fileid); 531 IXDR_PUT_U_INT32(ptr, na->atime.seconds); 532 IXDR_PUT_U_INT32(ptr, na->atime.nseconds); 533 IXDR_PUT_U_INT32(ptr, na->mtime.seconds); 534 IXDR_PUT_U_INT32(ptr, na->mtime.nseconds); 535 IXDR_PUT_U_INT32(ptr, na->ctime.seconds); 536 IXDR_PUT_U_INT32(ptr, na->ctime.nseconds); 537 } 538 return (TRUE); 539 } 540 if (!(xdr_enum(xdrs, (enum_t *)&na->type) && 541 xdr_u_int(xdrs, &na->mode) && 542 xdr_u_int(xdrs, &na->nlink) && 543 xdr_u_int(xdrs, &na->uid) && 544 xdr_u_int(xdrs, &na->gid) && 545 xdr_u_longlong_t(xdrs, &na->size) && 546 xdr_u_longlong_t(xdrs, &na->used) && 547 xdr_u_int(xdrs, &na->rdev.specdata1) && 548 xdr_u_int(xdrs, &na->rdev.specdata2) && 549 xdr_u_longlong_t(xdrs, &na->fsid) && 550 xdr_u_longlong_t(xdrs, &na->fileid) && 551 xdr_u_int(xdrs, &na->atime.seconds) && 552 xdr_u_int(xdrs, &na->atime.nseconds) && 553 xdr_u_int(xdrs, &na->mtime.seconds) && 554 xdr_u_int(xdrs, &na->mtime.nseconds) && 555 xdr_u_int(xdrs, &na->ctime.seconds) && 556 xdr_u_int(xdrs, &na->ctime.nseconds))) 557 return (FALSE); 558 return (TRUE); 559 } 560 561 /* 562 * Fast decode of an fattr3 to a vattr 563 * Only return FALSE on decode error, all other fattr to vattr translation 564 * failures set status. 565 * 566 * Callers must catch the following errors: 567 * EFBIG - file size will not fit in va_size 568 * EOVERFLOW - time will not fit in va_*time 569 */ 570 static bool_t 571 xdr_fattr3_to_vattr(XDR *xdrs, fattr3_res *objp) 572 { 573 int32_t *ptr; 574 size3 used; 575 specdata3 rdev; 576 uint32_t ntime; 577 vattr_t *vap = objp->vap; 578 579 /* 580 * DECODE only 581 */ 582 ASSERT(xdrs->x_op == XDR_DECODE); 583 584 objp->status = 0; 585 ptr = XDR_INLINE(xdrs, NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT); 586 if (ptr != NULL) { 587 /* 588 * Common case 589 */ 590 vap->va_type = IXDR_GET_ENUM(ptr, enum vtype); 591 if (vap->va_type < NF3REG || vap->va_type > NF3FIFO) 592 vap->va_type = VBAD; 593 else 594 vap->va_type = nf3_to_vt[vap->va_type]; 595 vap->va_mode = IXDR_GET_U_INT32(ptr); 596 vap->va_nlink = IXDR_GET_U_INT32(ptr); 597 vap->va_uid = (uid_t)IXDR_GET_U_INT32(ptr); 598 if (vap->va_uid == NFS_UID_NOBODY) 599 vap->va_uid = UID_NOBODY; 600 vap->va_gid = (gid_t)IXDR_GET_U_INT32(ptr); 601 if (vap->va_gid == NFS_GID_NOBODY) 602 vap->va_gid = GID_NOBODY; 603 IXDR_GET_U_HYPER(ptr, vap->va_size); 604 /* 605 * If invalid size, stop decode, set status, and 606 * return TRUE, x_handy will be correct, caller must ignore vap. 607 */ 608 if (!NFS3_SIZE_OK(vap->va_size)) { 609 objp->status = EFBIG; 610 return (TRUE); 611 } 612 IXDR_GET_U_HYPER(ptr, used); 613 rdev.specdata1 = IXDR_GET_U_INT32(ptr); 614 rdev.specdata2 = IXDR_GET_U_INT32(ptr); 615 /* fsid is ignored */ 616 ptr += 2; 617 IXDR_GET_U_HYPER(ptr, vap->va_nodeid); 618 619 /* 620 * nfs protocol defines times as unsigned so don't 621 * extend sign, unless sysadmin set nfs_allow_preepoch_time. 622 * The inline macros do the equivilant of NFS_TIME_T_CONVERT 623 */ 624 if (nfs_allow_preepoch_time) { 625 vap->va_atime.tv_sec = IXDR_GET_INT32(ptr); 626 vap->va_atime.tv_nsec = IXDR_GET_U_INT32(ptr); 627 vap->va_mtime.tv_sec = IXDR_GET_INT32(ptr); 628 vap->va_mtime.tv_nsec = IXDR_GET_U_INT32(ptr); 629 vap->va_ctime.tv_sec = IXDR_GET_INT32(ptr); 630 vap->va_ctime.tv_nsec = IXDR_GET_U_INT32(ptr); 631 } else { 632 /* 633 * Check if the time would overflow on 32-bit 634 */ 635 ntime = IXDR_GET_U_INT32(ptr); 636 /*CONSTCOND*/ 637 if (NFS3_TIME_OVERFLOW(ntime)) { 638 objp->status = EOVERFLOW; 639 return (TRUE); 640 } 641 vap->va_atime.tv_sec = ntime; 642 vap->va_atime.tv_nsec = IXDR_GET_U_INT32(ptr); 643 644 ntime = IXDR_GET_U_INT32(ptr); 645 /*CONSTCOND*/ 646 if (NFS3_TIME_OVERFLOW(ntime)) { 647 objp->status = EOVERFLOW; 648 return (TRUE); 649 } 650 vap->va_mtime.tv_sec = ntime; 651 vap->va_mtime.tv_nsec = IXDR_GET_U_INT32(ptr); 652 653 ntime = IXDR_GET_U_INT32(ptr); 654 /*CONSTCOND*/ 655 if (NFS3_TIME_OVERFLOW(ntime)) { 656 objp->status = EOVERFLOW; 657 return (TRUE); 658 } 659 vap->va_ctime.tv_sec = ntime; 660 vap->va_ctime.tv_nsec = IXDR_GET_U_INT32(ptr); 661 } 662 663 } else { 664 uint64 fsid; 665 666 /* 667 * Slow path 668 */ 669 if (!(xdr_enum(xdrs, (enum_t *)&vap->va_type) && 670 xdr_u_int(xdrs, &vap->va_mode) && 671 xdr_u_int(xdrs, &vap->va_nlink) && 672 xdr_u_int(xdrs, (uint_t *)&vap->va_uid) && 673 xdr_u_int(xdrs, (uint_t *)&vap->va_gid) && 674 xdr_u_longlong_t(xdrs, &vap->va_size) && 675 xdr_u_longlong_t(xdrs, &used) && 676 xdr_u_int(xdrs, &rdev.specdata1) && 677 xdr_u_int(xdrs, &rdev.specdata2) && 678 xdr_u_longlong_t(xdrs, &fsid) && /* ignored */ 679 xdr_u_longlong_t(xdrs, &vap->va_nodeid))) 680 return (FALSE); 681 682 if (nfs_allow_preepoch_time) { 683 if (!xdr_u_int(xdrs, &ntime)) 684 return (FALSE); 685 vap->va_atime.tv_sec = (int32_t)ntime; 686 if (!xdr_u_int(xdrs, &ntime)) 687 return (FALSE); 688 vap->va_atime.tv_nsec = ntime; 689 690 if (!xdr_u_int(xdrs, &ntime)) 691 return (FALSE); 692 vap->va_mtime.tv_sec = (int32_t)ntime; 693 if (!xdr_u_int(xdrs, &ntime)) 694 return (FALSE); 695 vap->va_mtime.tv_nsec = ntime; 696 697 if (!xdr_u_int(xdrs, &ntime)) 698 return (FALSE); 699 vap->va_ctime.tv_sec = (int32_t)ntime; 700 if (!xdr_u_int(xdrs, &ntime)) 701 return (FALSE); 702 vap->va_ctime.tv_nsec = ntime; 703 } else { 704 /* 705 * Check if the time would overflow on 32-bit 706 * Set status and keep decoding stream. 707 */ 708 if (!xdr_u_int(xdrs, &ntime)) 709 return (FALSE); 710 /*CONSTCOND*/ 711 if (NFS3_TIME_OVERFLOW(ntime)) { 712 objp->status = EOVERFLOW; 713 } 714 vap->va_atime.tv_sec = ntime; 715 if (!xdr_u_int(xdrs, &ntime)) 716 return (FALSE); 717 vap->va_atime.tv_nsec = ntime; 718 719 if (!xdr_u_int(xdrs, &ntime)) 720 return (FALSE); 721 /*CONSTCOND*/ 722 if (NFS3_TIME_OVERFLOW(ntime)) { 723 objp->status = EOVERFLOW; 724 } 725 vap->va_mtime.tv_sec = ntime; 726 if (!xdr_u_int(xdrs, &ntime)) 727 return (FALSE); 728 vap->va_mtime.tv_nsec = ntime; 729 730 if (!xdr_u_int(xdrs, &ntime)) 731 return (FALSE); 732 /*CONSTCOND*/ 733 if (NFS3_TIME_OVERFLOW(ntime)) { 734 objp->status = EOVERFLOW; 735 } 736 vap->va_ctime.tv_sec = ntime; 737 if (!xdr_u_int(xdrs, &ntime)) 738 return (FALSE); 739 vap->va_ctime.tv_nsec = ntime; 740 } 741 742 /* 743 * Fixup as needed 744 */ 745 if (vap->va_type < NF3REG || vap->va_type > NF3FIFO) 746 vap->va_type = VBAD; 747 else 748 vap->va_type = nf3_to_vt[vap->va_type]; 749 if (vap->va_uid == NFS_UID_NOBODY) 750 vap->va_uid = UID_NOBODY; 751 if (vap->va_gid == NFS_GID_NOBODY) 752 vap->va_gid = GID_NOBODY; 753 /* 754 * If invalid size, set status, and 755 * return TRUE, caller must ignore vap. 756 */ 757 if (!NFS3_SIZE_OK(vap->va_size)) { 758 objp->status = EFBIG; 759 return (TRUE); 760 } 761 } 762 763 /* 764 * Fill in derived fields 765 */ 766 vap->va_fsid = objp->vp->v_vfsp->vfs_dev; 767 vap->va_seq = 0; 768 769 /* 770 * Common case values 771 */ 772 vap->va_rdev = 0; 773 vap->va_blksize = MAXBSIZE; 774 vap->va_nblocks = 0; 775 776 switch (vap->va_type) { 777 case VREG: 778 case VDIR: 779 case VLNK: 780 vap->va_nblocks = (u_longlong_t) 781 ((used + (size3)DEV_BSIZE - (size3)1) / 782 (size3)DEV_BSIZE); 783 break; 784 case VBLK: 785 vap->va_blksize = DEV_BSIZE; 786 /* FALLTHRU */ 787 case VCHR: 788 vap->va_rdev = makedevice(rdev.specdata1, rdev.specdata2); 789 break; 790 case VSOCK: 791 case VFIFO: 792 default: 793 break; 794 } 795 796 return (TRUE); 797 } 798 799 static bool_t 800 xdr_post_op_vattr(XDR *xdrs, post_op_vattr *objp) 801 { 802 /* 803 * DECODE only 804 */ 805 ASSERT(xdrs->x_op == XDR_DECODE); 806 807 if (!xdr_bool(xdrs, &objp->attributes)) 808 return (FALSE); 809 810 if (objp->attributes == FALSE) 811 return (TRUE); 812 813 if (objp->attributes != TRUE) 814 return (FALSE); 815 816 if (!xdr_fattr3_to_vattr(xdrs, &objp->fres)) 817 return (FALSE); 818 819 /* 820 * The file size may cause an EFBIG or the time values 821 * may cause EOVERFLOW, if so simply drop the attributes. 822 */ 823 if (objp->fres.status != NFS3_OK) 824 objp->attributes = FALSE; 825 826 return (TRUE); 827 } 828 829 bool_t 830 xdr_post_op_attr(XDR *xdrs, post_op_attr *objp) 831 { 832 if (!xdr_bool(xdrs, &objp->attributes)) 833 return (FALSE); 834 835 if (objp->attributes == FALSE) 836 return (TRUE); 837 838 if (objp->attributes != TRUE) 839 return (FALSE); 840 841 if (!xdr_fattr3(xdrs, &objp->attr)) 842 return (FALSE); 843 844 /* 845 * Check that we don't get a file we can't handle through 846 * existing interfaces (especially stat64()). 847 * Decode only check since on encode the data has 848 * been dealt with in the above call to xdr_fattr3(). 849 */ 850 if (xdrs->x_op == XDR_DECODE) { 851 /* Set attrs to false if invalid size or time */ 852 if (!NFS3_SIZE_OK(objp->attr.size)) { 853 objp->attributes = FALSE; 854 return (TRUE); 855 } 856 #ifndef _LP64 857 if (!NFS3_FATTR_TIME_OK(&objp->attr)) 858 objp->attributes = FALSE; 859 #endif 860 } 861 return (TRUE); 862 } 863 864 static bool_t 865 xdr_wcc_data(XDR *xdrs, wcc_data *objp) 866 { 867 int32_t *ptr; 868 wcc_attr *attrp; 869 870 if (xdrs->x_op == XDR_FREE) 871 return (TRUE); 872 873 if (xdrs->x_op == XDR_DECODE) { 874 /* pre_op_attr */ 875 if (!xdr_bool(xdrs, &objp->before.attributes)) 876 return (FALSE); 877 878 switch (objp->before.attributes) { 879 case TRUE: 880 attrp = &objp->before.attr; 881 ptr = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT); 882 if (ptr != NULL) { 883 IXDR_GET_U_HYPER(ptr, attrp->size); 884 attrp->mtime.seconds = IXDR_GET_U_INT32(ptr); 885 attrp->mtime.nseconds = IXDR_GET_U_INT32(ptr); 886 attrp->ctime.seconds = IXDR_GET_U_INT32(ptr); 887 attrp->ctime.nseconds = IXDR_GET_U_INT32(ptr); 888 } else { 889 if (!xdr_u_longlong_t(xdrs, &attrp->size)) 890 return (FALSE); 891 if (!xdr_u_int(xdrs, &attrp->mtime.seconds)) 892 return (FALSE); 893 if (!xdr_u_int(xdrs, &attrp->mtime.nseconds)) 894 return (FALSE); 895 if (!xdr_u_int(xdrs, &attrp->ctime.seconds)) 896 return (FALSE); 897 if (!xdr_u_int(xdrs, &attrp->ctime.nseconds)) 898 return (FALSE); 899 } 900 901 #ifndef _LP64 902 /* 903 * check time overflow. 904 */ 905 if (!NFS3_TIME_OK(attrp->mtime.seconds) || 906 !NFS3_TIME_OK(attrp->ctime.seconds)) 907 objp->before.attributes = FALSE; 908 #endif 909 break; 910 case FALSE: 911 break; 912 default: 913 return (FALSE); 914 } 915 } 916 917 if (xdrs->x_op == XDR_ENCODE) { 918 /* pre_op_attr */ 919 if (!xdr_bool(xdrs, &objp->before.attributes)) 920 return (FALSE); 921 922 switch (objp->before.attributes) { 923 case TRUE: 924 attrp = &objp->before.attr; 925 926 ptr = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT); 927 if (ptr != NULL) { 928 IXDR_PUT_U_HYPER(ptr, attrp->size); 929 IXDR_PUT_U_INT32(ptr, attrp->mtime.seconds); 930 IXDR_PUT_U_INT32(ptr, attrp->mtime.nseconds); 931 IXDR_PUT_U_INT32(ptr, attrp->ctime.seconds); 932 IXDR_PUT_U_INT32(ptr, attrp->ctime.nseconds); 933 } else { 934 if (!xdr_u_longlong_t(xdrs, &attrp->size)) 935 return (FALSE); 936 if (!xdr_u_int(xdrs, &attrp->mtime.seconds)) 937 return (FALSE); 938 if (!xdr_u_int(xdrs, &attrp->mtime.nseconds)) 939 return (FALSE); 940 if (!xdr_u_int(xdrs, &attrp->ctime.seconds)) 941 return (FALSE); 942 if (!xdr_u_int(xdrs, &attrp->ctime.nseconds)) 943 return (FALSE); 944 } 945 break; 946 case FALSE: 947 break; 948 default: 949 return (FALSE); 950 } 951 } 952 return (xdr_post_op_attr(xdrs, &objp->after)); 953 } 954 955 bool_t 956 xdr_post_op_fh3(XDR *xdrs, post_op_fh3 *objp) 957 { 958 if (!xdr_bool(xdrs, &objp->handle_follows)) 959 return (FALSE); 960 switch (objp->handle_follows) { 961 case TRUE: 962 switch (xdrs->x_op) { 963 case XDR_ENCODE: 964 if (!xdr_nfs_fh3_server(xdrs, &objp->handle)) 965 return (FALSE); 966 break; 967 case XDR_FREE: 968 case XDR_DECODE: 969 if (!xdr_nfs_fh3(xdrs, &objp->handle)) 970 return (FALSE); 971 break; 972 } 973 return (TRUE); 974 case FALSE: 975 return (TRUE); 976 default: 977 return (FALSE); 978 } 979 } 980 981 static bool_t 982 xdr_sattr3(XDR *xdrs, sattr3 *objp) 983 { 984 /* set_mode3 */ 985 if (!xdr_bool(xdrs, &objp->mode.set_it)) 986 return (FALSE); 987 if (objp->mode.set_it) 988 if (!xdr_u_int(xdrs, &objp->mode.mode)) 989 return (FALSE); 990 /* set_uid3 */ 991 if (!xdr_bool(xdrs, &objp->uid.set_it)) 992 return (FALSE); 993 if (objp->uid.set_it) 994 if (!xdr_u_int(xdrs, &objp->uid.uid)) 995 return (FALSE); 996 /* set_gid3 */ 997 if (!xdr_bool(xdrs, &objp->gid.set_it)) 998 return (FALSE); 999 if (objp->gid.set_it) 1000 if (!xdr_u_int(xdrs, &objp->gid.gid)) 1001 return (FALSE); 1002 1003 /* set_size3 */ 1004 if (!xdr_bool(xdrs, &objp->size.set_it)) 1005 return (FALSE); 1006 if (objp->size.set_it) 1007 if (!xdr_u_longlong_t(xdrs, &objp->size.size)) 1008 return (FALSE); 1009 1010 /* set_atime */ 1011 if (!xdr_enum(xdrs, (enum_t *)&objp->atime.set_it)) 1012 return (FALSE); 1013 if (objp->atime.set_it == SET_TO_CLIENT_TIME) { 1014 if (!xdr_u_int(xdrs, &objp->atime.atime.seconds)) 1015 return (FALSE); 1016 if (!xdr_u_int(xdrs, &objp->atime.atime.nseconds)) 1017 return (FALSE); 1018 } 1019 1020 /* set_mtime */ 1021 if (!xdr_enum(xdrs, (enum_t *)&objp->mtime.set_it)) 1022 return (FALSE); 1023 if (objp->mtime.set_it == SET_TO_CLIENT_TIME) { 1024 if (!xdr_u_int(xdrs, &objp->mtime.mtime.seconds)) 1025 return (FALSE); 1026 if (!xdr_u_int(xdrs, &objp->mtime.mtime.nseconds)) 1027 return (FALSE); 1028 } 1029 1030 return (TRUE); 1031 } 1032 1033 bool_t 1034 xdr_GETATTR3res(XDR *xdrs, GETATTR3res *objp) 1035 { 1036 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 1037 return (FALSE); 1038 if (objp->status != NFS3_OK) 1039 return (TRUE); 1040 /* xdr_GETATTR3resok */ 1041 return (xdr_fattr3(xdrs, &objp->resok.obj_attributes)); 1042 } 1043 1044 bool_t 1045 xdr_GETATTR3vres(XDR *xdrs, GETATTR3vres *objp) 1046 { 1047 /* 1048 * DECODE or FREE only 1049 */ 1050 if (xdrs->x_op == XDR_FREE) 1051 return (TRUE); 1052 1053 if (xdrs->x_op != XDR_DECODE) 1054 return (FALSE); 1055 1056 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 1057 return (FALSE); 1058 1059 if (objp->status != NFS3_OK) 1060 return (TRUE); 1061 1062 return (xdr_fattr3_to_vattr(xdrs, &objp->fres)); 1063 } 1064 1065 1066 bool_t 1067 xdr_SETATTR3args(XDR *xdrs, SETATTR3args *objp) 1068 { 1069 switch (xdrs->x_op) { 1070 case XDR_FREE: 1071 case XDR_ENCODE: 1072 if (!xdr_nfs_fh3(xdrs, &objp->object)) 1073 return (FALSE); 1074 break; 1075 case XDR_DECODE: 1076 if (!xdr_nfs_fh3_server(xdrs, &objp->object)) 1077 return (FALSE); 1078 break; 1079 } 1080 if (!xdr_sattr3(xdrs, &objp->new_attributes)) 1081 return (FALSE); 1082 1083 /* sattrguard3 */ 1084 if (!xdr_bool(xdrs, &objp->guard.check)) 1085 return (FALSE); 1086 switch (objp->guard.check) { 1087 case TRUE: 1088 if (!xdr_u_int(xdrs, &objp->guard.obj_ctime.seconds)) 1089 return (FALSE); 1090 return (xdr_u_int(xdrs, &objp->guard.obj_ctime.nseconds)); 1091 case FALSE: 1092 return (TRUE); 1093 default: 1094 return (FALSE); 1095 } 1096 } 1097 1098 bool_t 1099 xdr_SETATTR3res(XDR *xdrs, SETATTR3res *objp) 1100 { 1101 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 1102 return (FALSE); 1103 switch (objp->status) { 1104 case NFS3_OK: 1105 return (xdr_wcc_data(xdrs, &objp->resok.obj_wcc)); 1106 default: 1107 return (xdr_wcc_data(xdrs, &objp->resfail.obj_wcc)); 1108 } 1109 } 1110 1111 bool_t 1112 xdr_LOOKUP3res(XDR *xdrs, LOOKUP3res *objp) 1113 { 1114 LOOKUP3resok *resokp; 1115 1116 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 1117 return (FALSE); 1118 1119 if (objp->status != NFS3_OK) 1120 return (xdr_post_op_attr(xdrs, &objp->resfail.dir_attributes)); 1121 1122 /* xdr_LOOKUP3resok */ 1123 resokp = &objp->resok; 1124 switch (xdrs->x_op) { 1125 case XDR_ENCODE: 1126 if (!xdr_nfs_fh3_server(xdrs, &resokp->object)) 1127 return (FALSE); 1128 break; 1129 case XDR_FREE: 1130 case XDR_DECODE: 1131 if (!xdr_nfs_fh3(xdrs, &resokp->object)) 1132 return (FALSE); 1133 break; 1134 } 1135 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes)) 1136 return (FALSE); 1137 return (xdr_post_op_attr(xdrs, &resokp->dir_attributes)); 1138 } 1139 1140 bool_t 1141 xdr_LOOKUP3vres(XDR *xdrs, LOOKUP3vres *objp) 1142 { 1143 /* 1144 * DECODE or FREE only 1145 */ 1146 if (xdrs->x_op == XDR_FREE) 1147 return (TRUE); 1148 1149 if (xdrs->x_op != XDR_DECODE) 1150 return (FALSE); 1151 1152 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 1153 return (FALSE); 1154 1155 if (objp->status != NFS3_OK) 1156 return (xdr_post_op_vattr(xdrs, &objp->dir_attributes)); 1157 1158 if (!xdr_nfs_fh3(xdrs, &objp->object)) 1159 return (FALSE); 1160 if (!xdr_post_op_vattr(xdrs, &objp->obj_attributes)) 1161 return (FALSE); 1162 return (xdr_post_op_vattr(xdrs, &objp->dir_attributes)); 1163 } 1164 1165 bool_t 1166 xdr_ACCESS3args(XDR *xdrs, ACCESS3args *objp) 1167 { 1168 switch (xdrs->x_op) { 1169 case XDR_FREE: 1170 case XDR_ENCODE: 1171 if (!xdr_nfs_fh3(xdrs, &objp->object)) 1172 return (FALSE); 1173 break; 1174 case XDR_DECODE: 1175 if (!xdr_nfs_fh3_server(xdrs, &objp->object)) 1176 return (FALSE); 1177 break; 1178 } 1179 return (xdr_u_int(xdrs, &objp->access)); 1180 } 1181 1182 1183 bool_t 1184 xdr_ACCESS3res(XDR *xdrs, ACCESS3res *objp) 1185 { 1186 ACCESS3resok *resokp; 1187 1188 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 1189 return (FALSE); 1190 if (objp->status != NFS3_OK) 1191 return (xdr_post_op_attr(xdrs, &objp->resfail.obj_attributes)); 1192 1193 /* xdr_ACCESS3resok */ 1194 resokp = &objp->resok; 1195 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes)) 1196 return (FALSE); 1197 return (xdr_u_int(xdrs, &resokp->access)); 1198 } 1199 1200 bool_t 1201 xdr_READLINK3args(XDR *xdrs, READLINK3args *objp) 1202 { 1203 rdma_chunkinfo_t rci; 1204 struct xdr_ops *xops = xdrrdma_xops(); 1205 1206 if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) && 1207 xdrs->x_op == XDR_ENCODE) { 1208 rci.rci_type = RCI_REPLY_CHUNK; 1209 rci.rci_len = MAXPATHLEN; 1210 XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci); 1211 } 1212 if (!xdr_nfs_fh3(xdrs, (nfs_fh3 *)objp)) 1213 return (FALSE); 1214 return (TRUE); 1215 } 1216 1217 bool_t 1218 xdr_READLINK3res(XDR *xdrs, READLINK3res *objp) 1219 { 1220 1221 READLINK3resok *resokp; 1222 1223 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 1224 return (FALSE); 1225 if (objp->status != NFS3_OK) 1226 return (xdr_post_op_attr(xdrs, 1227 &objp->resfail.symlink_attributes)); 1228 1229 /* xdr_READLINK3resok */ 1230 resokp = &objp->resok; 1231 if (!xdr_post_op_attr(xdrs, &resokp->symlink_attributes)) 1232 return (FALSE); 1233 return (xdr_string3(xdrs, &resokp->data, MAXPATHLEN)); 1234 } 1235 1236 bool_t 1237 xdr_READ3args(XDR *xdrs, READ3args *objp) 1238 { 1239 rdma_chunkinfo_t rci; 1240 rdma_wlist_conn_info_t rwci; 1241 struct xdr_ops *xops = xdrrdma_xops(); 1242 1243 switch (xdrs->x_op) { 1244 case XDR_FREE: 1245 case XDR_ENCODE: 1246 if (!xdr_nfs_fh3(xdrs, &objp->file)) 1247 return (FALSE); 1248 break; 1249 case XDR_DECODE: 1250 if (!xdr_nfs_fh3_server(xdrs, &objp->file)) 1251 return (FALSE); 1252 break; 1253 } 1254 if (!xdr_u_longlong_t(xdrs, &objp->offset)) 1255 return (FALSE); 1256 if (!xdr_u_int(xdrs, &objp->count)) 1257 return (FALSE); 1258 1259 DTRACE_PROBE1(xdr__i__read3_buf_len, int, objp->count); 1260 1261 objp->wlist = NULL; 1262 1263 /* if xdrrdma_sizeof in progress, then store the size */ 1264 if (xdrs->x_ops == xops && xdrs->x_op == XDR_ENCODE) { 1265 rci.rci_type = RCI_WRITE_ADDR_CHUNK; 1266 rci.rci_len = objp->count; 1267 (void) XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci); 1268 } 1269 1270 if (xdrs->x_ops != &xdrrdma_ops || xdrs->x_op == XDR_FREE) 1271 return (TRUE); 1272 1273 if (xdrs->x_op == XDR_ENCODE) { 1274 1275 if (objp->res_uiop != NULL) { 1276 rci.rci_type = RCI_WRITE_UIO_CHUNK; 1277 rci.rci_a.rci_uiop = objp->res_uiop; 1278 rci.rci_len = objp->count; 1279 rci.rci_clpp = &objp->wlist; 1280 } else { 1281 rci.rci_type = RCI_WRITE_ADDR_CHUNK; 1282 rci.rci_a.rci_addr = objp->res_data_val_alt; 1283 rci.rci_len = objp->count; 1284 rci.rci_clpp = &objp->wlist; 1285 } 1286 1287 return (XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci)); 1288 } 1289 1290 /* XDR_DECODE case */ 1291 (void) XDR_CONTROL(xdrs, XDR_RDMA_GET_WCINFO, &rwci); 1292 objp->wlist = rwci.rwci_wlist; 1293 objp->conn = rwci.rwci_conn; 1294 1295 return (TRUE); 1296 } 1297 1298 bool_t 1299 xdr_READ3res(XDR *xdrs, READ3res *objp) 1300 { 1301 READ3resok *resokp; 1302 bool_t ret; 1303 mblk_t *mp; 1304 1305 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 1306 return (FALSE); 1307 1308 if (objp->status != NFS3_OK) 1309 return (xdr_post_op_attr(xdrs, &objp->resfail.file_attributes)); 1310 1311 resokp = &objp->resok; 1312 1313 if (xdr_post_op_attr(xdrs, &resokp->file_attributes) == FALSE || 1314 xdr_u_int(xdrs, &resokp->count) == FALSE || 1315 xdr_bool(xdrs, &resokp->eof) == FALSE) { 1316 return (FALSE); 1317 } 1318 1319 if (xdrs->x_op == XDR_ENCODE) { 1320 int i, rndup; 1321 1322 mp = resokp->data.mp; 1323 if (mp != NULL && xdrs->x_ops == &xdrmblk_ops) { 1324 mp->b_wptr += resokp->count; 1325 rndup = BYTES_PER_XDR_UNIT - 1326 (resokp->data.data_len % BYTES_PER_XDR_UNIT); 1327 if (rndup != BYTES_PER_XDR_UNIT) 1328 for (i = 0; i < rndup; i++) 1329 *mp->b_wptr++ = '\0'; 1330 if (xdrmblk_putmblk(xdrs, mp, resokp->count) == TRUE) { 1331 resokp->data.mp = NULL; 1332 return (TRUE); 1333 } 1334 } else if (mp == NULL) { 1335 if (xdr_u_int(xdrs, &resokp->count) == FALSE) { 1336 return (FALSE); 1337 } 1338 /* 1339 * If read data sent by wlist (RDMA_WRITE), don't do 1340 * xdr_bytes() below. RDMA_WRITE transfers the data. 1341 * Note: this is encode-only because the client code 1342 * uses xdr_READ3vres/xdr_READ3uiores to decode results. 1343 */ 1344 if (resokp->wlist) { 1345 if (resokp->wlist->c_len != resokp->count) { 1346 resokp->wlist->c_len = resokp->count; 1347 } 1348 if (resokp->count != 0) { 1349 return (xdrrdma_send_read_data( 1350 xdrs, resokp->wlist)); 1351 } 1352 return (TRUE); 1353 } 1354 } 1355 /* 1356 * Fall thru for the xdr_bytes() 1357 * 1358 * note: the mblk will be freed in 1359 * rfs3_read_free. 1360 */ 1361 } 1362 1363 /* no RDMA_WRITE transfer -- send data inline */ 1364 1365 ret = xdr_bytes(xdrs, (char **)&resokp->data.data_val, 1366 &resokp->data.data_len, nfs3tsize()); 1367 1368 return (ret); 1369 } 1370 1371 bool_t 1372 xdr_READ3vres(XDR *xdrs, READ3vres *objp) 1373 { 1374 count3 ocount; 1375 /* 1376 * DECODE or FREE only 1377 */ 1378 if (xdrs->x_op == XDR_FREE) 1379 return (TRUE); 1380 1381 if (xdrs->x_op != XDR_DECODE) 1382 return (FALSE); 1383 1384 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 1385 return (FALSE); 1386 1387 if (!xdr_post_op_vattr(xdrs, &objp->pov)) 1388 return (FALSE); 1389 1390 if (objp->status != NFS3_OK) 1391 return (TRUE); 1392 1393 if (!xdr_u_int(xdrs, &objp->count)) 1394 return (FALSE); 1395 1396 if (!xdr_bool(xdrs, &objp->eof)) 1397 return (FALSE); 1398 1399 /* 1400 * If read data received via RDMA_WRITE, don't do xdr_bytes(). 1401 * RDMA_WRITE already moved the data so decode length of RDMA_WRITE. 1402 */ 1403 if (xdrs->x_ops == &xdrrdma_ops) { 1404 struct clist *cl; 1405 1406 XDR_CONTROL(xdrs, XDR_RDMA_GET_WLIST, &cl); 1407 1408 if (cl) { 1409 if (!xdr_u_int(xdrs, &ocount)) { 1410 return (FALSE); 1411 } 1412 if (ocount != objp->count) { 1413 DTRACE_PROBE2(xdr__e__read3vres_fail, 1414 int, ocount, int, objp->count); 1415 return (FALSE); 1416 } 1417 1418 objp->wlist_len = cl->c_len; 1419 objp->data.data_len = objp->wlist_len; 1420 return (TRUE); 1421 } 1422 } 1423 1424 return (xdr_bytes(xdrs, (char **)&objp->data.data_val, 1425 &objp->data.data_len, nfs3tsize())); 1426 } 1427 1428 bool_t 1429 xdr_READ3uiores(XDR *xdrs, READ3uiores *objp) 1430 { 1431 count3 ocount; 1432 bool_t attributes; 1433 mblk_t *mp; 1434 size_t n; 1435 int error; 1436 int size = (int)objp->size; 1437 struct uio *uiop = objp->uiop; 1438 int32_t fattr3_len = NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT; 1439 int32_t *ptr; 1440 1441 /* 1442 * DECODE or FREE only 1443 */ 1444 if (xdrs->x_op == XDR_FREE) 1445 return (TRUE); 1446 1447 if (xdrs->x_op != XDR_DECODE) 1448 return (FALSE); 1449 1450 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->status)) 1451 return (FALSE); 1452 1453 if (!XDR_GETINT32(xdrs, (int32_t *)&attributes)) 1454 return (FALSE); 1455 1456 /* 1457 * For directio we just skip over attributes if present 1458 */ 1459 switch (attributes) { 1460 case TRUE: 1461 if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &fattr3_len)) 1462 return (FALSE); 1463 break; 1464 case FALSE: 1465 break; 1466 default: 1467 return (FALSE); 1468 } 1469 1470 if (objp->status != NFS3_OK) 1471 return (TRUE); 1472 1473 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->count)) 1474 return (FALSE); 1475 1476 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->eof)) 1477 return (FALSE); 1478 1479 if (xdrs->x_ops == &xdrmblk_ops) { 1480 if (!xdrmblk_getmblk(xdrs, &mp, &objp->size)) 1481 return (FALSE); 1482 1483 if (objp->size == 0) 1484 return (TRUE); 1485 1486 if (objp->size > size) 1487 return (FALSE); 1488 1489 size = (int)objp->size; 1490 do { 1491 n = MIN(size, mp->b_wptr - mp->b_rptr); 1492 if ((n = MIN(uiop->uio_resid, n)) != 0) { 1493 1494 error = uiomove((char *)mp->b_rptr, n, UIO_READ, 1495 uiop); 1496 if (error) 1497 return (FALSE); 1498 mp->b_rptr += n; 1499 size -= n; 1500 } 1501 1502 while (mp && (mp->b_rptr >= mp->b_wptr)) 1503 mp = mp->b_cont; 1504 } while (mp && size > 0 && uiop->uio_resid > 0); 1505 1506 return (TRUE); 1507 } 1508 1509 if (xdrs->x_ops == &xdrrdma_ops) { 1510 struct clist *cl; 1511 1512 XDR_CONTROL(xdrs, XDR_RDMA_GET_WLIST, &cl); 1513 1514 objp->wlist = cl; 1515 1516 if (objp->wlist) { 1517 if (!xdr_u_int(xdrs, &ocount)) { 1518 objp->wlist = NULL; 1519 return (FALSE); 1520 } 1521 1522 if (ocount != objp->count) { 1523 DTRACE_PROBE2(xdr__e__read3uiores_fail, 1524 int, ocount, int, objp->count); 1525 objp->wlist = NULL; 1526 return (FALSE); 1527 } 1528 1529 objp->wlist_len = cl->c_len; 1530 1531 uiop->uio_resid -= objp->count; 1532 uiop->uio_iov->iov_len -= objp->count; 1533 uiop->uio_iov->iov_base += objp->count; 1534 uiop->uio_loffset += objp->count; 1535 1536 /* 1537 * XXX: Assume 1 iov, needs to be changed. 1538 */ 1539 objp->size = objp->wlist_len; 1540 1541 return (TRUE); 1542 } 1543 } 1544 1545 /* 1546 * This isn't an xdrmblk stream nor RDMA. 1547 * Handle the likely case that it can be 1548 * inlined (ex. xdrmem). 1549 */ 1550 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->size)) 1551 return (FALSE); 1552 1553 if (objp->size == 0) 1554 return (TRUE); 1555 1556 if (objp->size > size) 1557 return (FALSE); 1558 1559 size = (int)objp->size; 1560 if ((ptr = XDR_INLINE(xdrs, size)) != NULL) 1561 return (uiomove(ptr, size, UIO_READ, uiop) ? FALSE : TRUE); 1562 1563 /* 1564 * Handle some other (unlikely) stream type that will need a copy. 1565 */ 1566 if ((ptr = kmem_alloc(size, KM_NOSLEEP)) == NULL) 1567 return (FALSE); 1568 1569 if (!XDR_GETBYTES(xdrs, (caddr_t)ptr, size)) { 1570 kmem_free(ptr, size); 1571 return (FALSE); 1572 } 1573 error = uiomove(ptr, size, UIO_READ, uiop); 1574 kmem_free(ptr, size); 1575 1576 return (error ? FALSE : TRUE); 1577 } 1578 1579 bool_t 1580 xdr_WRITE3args(XDR *xdrs, WRITE3args *objp) 1581 { 1582 switch (xdrs->x_op) { 1583 case XDR_FREE: 1584 case XDR_ENCODE: 1585 if (!xdr_nfs_fh3(xdrs, &objp->file)) 1586 return (FALSE); 1587 break; 1588 case XDR_DECODE: 1589 if (!xdr_nfs_fh3_server(xdrs, &objp->file)) 1590 return (FALSE); 1591 break; 1592 } 1593 if (!xdr_u_longlong_t(xdrs, &objp->offset)) 1594 return (FALSE); 1595 if (!xdr_u_int(xdrs, &objp->count)) 1596 return (FALSE); 1597 if (!xdr_enum(xdrs, (enum_t *)&objp->stable)) 1598 return (FALSE); 1599 1600 if (xdrs->x_op == XDR_DECODE) { 1601 if (xdrs->x_ops == &xdrmblk_ops) { 1602 if (xdrmblk_getmblk(xdrs, &objp->mblk, 1603 &objp->data.data_len) == TRUE) { 1604 objp->data.data_val = NULL; 1605 return (TRUE); 1606 } 1607 } 1608 objp->mblk = NULL; 1609 1610 if (xdrs->x_ops == &xdrrdmablk_ops) { 1611 if (xdrrdma_getrdmablk(xdrs, &objp->rlist, 1612 &objp->data.data_len, 1613 &objp->conn, nfs3tsize()) == TRUE) { 1614 objp->data.data_val = NULL; 1615 if (xdrrdma_read_from_client( 1616 &objp->rlist, 1617 &objp->conn, 1618 objp->count) == FALSE) { 1619 return (FALSE); 1620 } 1621 return (TRUE); 1622 } 1623 } 1624 objp->rlist = NULL; 1625 1626 /* Else fall thru for the xdr_bytes(). */ 1627 } 1628 1629 if (xdrs->x_op == XDR_FREE) { 1630 if (objp->rlist != NULL) { 1631 (void) xdrrdma_free_clist(objp->conn, objp->rlist); 1632 objp->rlist = NULL; 1633 objp->data.data_val = NULL; 1634 return (TRUE); 1635 } 1636 } 1637 1638 DTRACE_PROBE1(xdr__i__write3_buf_len, 1639 int, objp->data.data_len); 1640 1641 return (xdr_bytes(xdrs, (char **)&objp->data.data_val, 1642 &objp->data.data_len, nfs3tsize())); 1643 } 1644 1645 bool_t 1646 xdr_WRITE3res(XDR *xdrs, WRITE3res *objp) 1647 { 1648 WRITE3resok *resokp; 1649 1650 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 1651 return (FALSE); 1652 if (objp->status != NFS3_OK) /* xdr_WRITE3resfail */ 1653 return (xdr_wcc_data(xdrs, &objp->resfail.file_wcc)); 1654 1655 /* xdr_WRITE3resok */ 1656 resokp = &objp->resok; 1657 if (!xdr_wcc_data(xdrs, &resokp->file_wcc)) 1658 return (FALSE); 1659 if (!xdr_u_int(xdrs, &resokp->count)) 1660 return (FALSE); 1661 if (!xdr_enum(xdrs, (enum_t *)&resokp->committed)) 1662 return (FALSE); 1663 /* 1664 * writeverf3 is really an opaque 8 byte 1665 * quantity, but we will treat it as a 1666 * hyper for efficiency, the cost of 1667 * a byteswap here saves bcopys elsewhere 1668 */ 1669 return (xdr_u_longlong_t(xdrs, &resokp->verf)); 1670 } 1671 1672 bool_t 1673 xdr_CREATE3args(XDR *xdrs, CREATE3args *objp) 1674 { 1675 createhow3 *howp; 1676 1677 if (!xdr_diropargs3(xdrs, &objp->where)) 1678 return (FALSE); 1679 1680 /* xdr_createhow3 */ 1681 howp = &objp->how; 1682 1683 if (!xdr_enum(xdrs, (enum_t *)&howp->mode)) 1684 return (FALSE); 1685 switch (howp->mode) { 1686 case UNCHECKED: 1687 case GUARDED: 1688 return (xdr_sattr3(xdrs, &howp->createhow3_u.obj_attributes)); 1689 case EXCLUSIVE: 1690 /* 1691 * createverf3 is really an opaque 8 byte 1692 * quantity, but we will treat it as a 1693 * hyper for efficiency, the cost of 1694 * a byteswap here saves bcopys elsewhere 1695 */ 1696 return (xdr_u_longlong_t(xdrs, &howp->createhow3_u.verf)); 1697 default: 1698 return (FALSE); 1699 } 1700 } 1701 1702 bool_t 1703 xdr_CREATE3res(XDR *xdrs, CREATE3res *objp) 1704 { 1705 CREATE3resok *resokp; 1706 1707 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 1708 return (FALSE); 1709 switch (objp->status) { 1710 case NFS3_OK: 1711 /* xdr_CREATE3resok */ 1712 resokp = &objp->resok; 1713 1714 if (!xdr_post_op_fh3(xdrs, &resokp->obj)) 1715 return (FALSE); 1716 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes)) 1717 return (FALSE); 1718 return (xdr_wcc_data(xdrs, &resokp->dir_wcc)); 1719 default: 1720 /* xdr_CREATE3resfail */ 1721 return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc)); 1722 } 1723 } 1724 1725 bool_t 1726 xdr_MKDIR3args(XDR *xdrs, MKDIR3args *objp) 1727 { 1728 if (!xdr_diropargs3(xdrs, &objp->where)) 1729 return (FALSE); 1730 return (xdr_sattr3(xdrs, &objp->attributes)); 1731 } 1732 1733 bool_t 1734 xdr_MKDIR3res(XDR *xdrs, MKDIR3res *objp) 1735 { 1736 MKDIR3resok *resokp; 1737 1738 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 1739 return (FALSE); 1740 switch (objp->status) { 1741 case NFS3_OK: 1742 /* xdr_MKDIR3resok */ 1743 resokp = &objp->resok; 1744 1745 if (!xdr_post_op_fh3(xdrs, &resokp->obj)) 1746 return (FALSE); 1747 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes)) 1748 return (FALSE); 1749 return (xdr_wcc_data(xdrs, &resokp->dir_wcc)); 1750 default: 1751 return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc)); 1752 } 1753 } 1754 1755 bool_t 1756 xdr_SYMLINK3args(XDR *xdrs, SYMLINK3args *objp) 1757 { 1758 if (!xdr_diropargs3(xdrs, &objp->where)) 1759 return (FALSE); 1760 if (!xdr_sattr3(xdrs, &objp->symlink.symlink_attributes)) 1761 return (FALSE); 1762 return (xdr_string3(xdrs, &objp->symlink.symlink_data, MAXPATHLEN)); 1763 } 1764 1765 bool_t 1766 xdr_SYMLINK3res(XDR *xdrs, SYMLINK3res *objp) 1767 { 1768 SYMLINK3resok *resokp; 1769 1770 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 1771 return (FALSE); 1772 switch (objp->status) { 1773 case NFS3_OK: 1774 resokp = &objp->resok; 1775 /* xdr_SYMLINK3resok */ 1776 if (!xdr_post_op_fh3(xdrs, &resokp->obj)) 1777 return (FALSE); 1778 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes)) 1779 return (FALSE); 1780 return (xdr_wcc_data(xdrs, &resokp->dir_wcc)); 1781 default: 1782 return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc)); 1783 } 1784 } 1785 1786 bool_t 1787 xdr_MKNOD3args(XDR *xdrs, MKNOD3args *objp) 1788 { 1789 mknoddata3 *whatp; 1790 devicedata3 *nod_objp; 1791 1792 if (!xdr_diropargs3(xdrs, &objp->where)) 1793 return (FALSE); 1794 1795 whatp = &objp->what; 1796 if (!xdr_enum(xdrs, (enum_t *)&whatp->type)) 1797 return (FALSE); 1798 switch (whatp->type) { 1799 case NF3CHR: 1800 case NF3BLK: 1801 /* xdr_devicedata3 */ 1802 nod_objp = &whatp->mknoddata3_u.device; 1803 if (!xdr_sattr3(xdrs, &nod_objp->dev_attributes)) 1804 return (FALSE); 1805 if (!xdr_u_int(xdrs, &nod_objp->spec.specdata1)) 1806 return (FALSE); 1807 return (xdr_u_int(xdrs, &nod_objp->spec.specdata2)); 1808 case NF3SOCK: 1809 case NF3FIFO: 1810 return (xdr_sattr3(xdrs, &whatp->mknoddata3_u.pipe_attributes)); 1811 default: 1812 break; 1813 } 1814 return (TRUE); 1815 } 1816 1817 bool_t 1818 xdr_MKNOD3res(XDR *xdrs, MKNOD3res *objp) 1819 { 1820 MKNOD3resok *resokp; 1821 1822 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 1823 return (FALSE); 1824 switch (objp->status) { 1825 case NFS3_OK: 1826 /* xdr_MKNOD3resok */ 1827 resokp = &objp->resok; 1828 if (!xdr_post_op_fh3(xdrs, &resokp->obj)) 1829 return (FALSE); 1830 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes)) 1831 return (FALSE); 1832 return (xdr_wcc_data(xdrs, &resokp->dir_wcc)); 1833 default: 1834 return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc)); 1835 } 1836 } 1837 1838 bool_t 1839 xdr_REMOVE3res(XDR *xdrs, REMOVE3res *objp) 1840 { 1841 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 1842 return (FALSE); 1843 switch (objp->status) { 1844 case NFS3_OK: 1845 return (xdr_wcc_data(xdrs, &objp->resok.dir_wcc)); 1846 default: 1847 return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc)); 1848 } 1849 } 1850 1851 bool_t 1852 xdr_RMDIR3res(XDR *xdrs, RMDIR3res *objp) 1853 { 1854 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 1855 return (FALSE); 1856 switch (objp->status) { 1857 case NFS3_OK: 1858 return (xdr_wcc_data(xdrs, &objp->resok.dir_wcc)); 1859 default: 1860 return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc)); 1861 } 1862 } 1863 1864 bool_t 1865 xdr_RENAME3args(XDR *xdrs, RENAME3args *objp) 1866 { 1867 if (!xdr_diropargs3(xdrs, &objp->from)) 1868 return (FALSE); 1869 return (xdr_diropargs3(xdrs, &objp->to)); 1870 } 1871 1872 bool_t 1873 xdr_RENAME3res(XDR *xdrs, RENAME3res *objp) 1874 { 1875 RENAME3resok *resokp; 1876 RENAME3resfail *resfailp; 1877 1878 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 1879 return (FALSE); 1880 switch (objp->status) { 1881 case NFS3_OK: 1882 /* xdr_RENAME3resok */ 1883 resokp = &objp->resok; 1884 1885 if (!xdr_wcc_data(xdrs, &resokp->fromdir_wcc)) 1886 return (FALSE); 1887 return (xdr_wcc_data(xdrs, &resokp->todir_wcc)); 1888 default: 1889 /* xdr_RENAME3resfail */ 1890 resfailp = &objp->resfail; 1891 if (!xdr_wcc_data(xdrs, &resfailp->fromdir_wcc)) 1892 return (FALSE); 1893 return (xdr_wcc_data(xdrs, &resfailp->todir_wcc)); 1894 } 1895 } 1896 1897 bool_t 1898 xdr_LINK3args(XDR *xdrs, LINK3args *objp) 1899 { 1900 switch (xdrs->x_op) { 1901 case XDR_FREE: 1902 case XDR_ENCODE: 1903 if (!xdr_nfs_fh3(xdrs, &objp->file)) 1904 return (FALSE); 1905 break; 1906 case XDR_DECODE: 1907 if (!xdr_nfs_fh3_server(xdrs, &objp->file)) 1908 return (FALSE); 1909 break; 1910 } 1911 return (xdr_diropargs3(xdrs, &objp->link)); 1912 } 1913 1914 bool_t 1915 xdr_LINK3res(XDR *xdrs, LINK3res *objp) 1916 { 1917 LINK3resok *resokp; 1918 LINK3resfail *resfailp; 1919 1920 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 1921 return (FALSE); 1922 switch (objp->status) { 1923 case NFS3_OK: 1924 /* xdr_LINK3resok */ 1925 resokp = &objp->resok; 1926 if (!xdr_post_op_attr(xdrs, &resokp->file_attributes)) 1927 return (FALSE); 1928 return (xdr_wcc_data(xdrs, &resokp->linkdir_wcc)); 1929 default: 1930 /* xdr_LINK3resfail */ 1931 resfailp = &objp->resfail; 1932 if (!xdr_post_op_attr(xdrs, &resfailp->file_attributes)) 1933 return (FALSE); 1934 return (xdr_wcc_data(xdrs, &resfailp->linkdir_wcc)); 1935 } 1936 } 1937 1938 bool_t 1939 xdr_READDIR3args(XDR *xdrs, READDIR3args *objp) 1940 { 1941 rdma_chunkinfo_t rci; 1942 struct xdr_ops *xops = xdrrdma_xops(); 1943 1944 if (xdrs->x_op == XDR_FREE) 1945 return (TRUE); 1946 1947 switch (xdrs->x_op) { 1948 case XDR_FREE: 1949 case XDR_ENCODE: 1950 if (!xdr_nfs_fh3(xdrs, &objp->dir)) 1951 return (FALSE); 1952 break; 1953 case XDR_DECODE: 1954 if (!xdr_nfs_fh3_server(xdrs, &objp->dir)) 1955 return (FALSE); 1956 break; 1957 } 1958 if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) && 1959 xdrs->x_op == XDR_ENCODE) { 1960 rci.rci_type = RCI_REPLY_CHUNK; 1961 rci.rci_len = objp->count; 1962 XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci); 1963 } 1964 1965 if (!xdr_u_longlong_t(xdrs, &objp->cookie)) 1966 return (FALSE); 1967 /* 1968 * cookieverf is really an opaque 8 byte 1969 * quantity, but we will treat it as a 1970 * hyper for efficiency, the cost of 1971 * a byteswap here saves bcopys elsewhere 1972 */ 1973 if (!xdr_u_longlong_t(xdrs, &objp->cookieverf)) 1974 return (FALSE); 1975 return (xdr_u_int(xdrs, &objp->count)); 1976 } 1977 1978 #ifdef nextdp 1979 #undef nextdp 1980 #endif 1981 #define nextdp(dp) ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen)) 1982 #ifdef roundup 1983 #undef roundup 1984 #endif 1985 #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) 1986 1987 /* 1988 * ENCODE ONLY 1989 */ 1990 static bool_t 1991 xdr_putdirlist(XDR *xdrs, READDIR3resok *objp) 1992 { 1993 struct dirent64 *dp; 1994 char *name; 1995 int size; 1996 int bufsize; 1997 uint_t namlen; 1998 bool_t true = TRUE; 1999 bool_t false = FALSE; 2000 int entrysz; 2001 int tofit; 2002 fileid3 fileid; 2003 cookie3 cookie; 2004 2005 if (xdrs->x_op != XDR_ENCODE) 2006 return (FALSE); 2007 2008 /* 2009 * bufsize is used to keep track of the size of the response. 2010 * It is primed with: 2011 * 1 for the status + 2012 * 1 for the dir_attributes.attributes boolean + 2013 * 2 for the cookie verifier 2014 * all times BYTES_PER_XDR_UNIT to convert from XDR units 2015 * to bytes. If there are directory attributes to be 2016 * returned, then: 2017 * NFS3_SIZEOF_FATTR3 for the dir_attributes.attr fattr3 2018 * time BYTES_PER_XDR_UNIT is added to account for them. 2019 */ 2020 bufsize = (1 + 1 + 2) * BYTES_PER_XDR_UNIT; 2021 if (objp->dir_attributes.attributes) 2022 bufsize += NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT; 2023 for (size = objp->size, dp = (struct dirent64 *)objp->reply.entries; 2024 size > 0; 2025 size -= dp->d_reclen, dp = nextdp(dp)) { 2026 if (dp->d_reclen == 0) 2027 return (FALSE); 2028 if (dp->d_ino == 0) 2029 continue; 2030 name = dp->d_name; 2031 namlen = (uint_t)strlen(dp->d_name); 2032 /* 2033 * An entry is composed of: 2034 * 1 for the true/false list indicator + 2035 * 2 for the fileid + 2036 * 1 for the length of the name + 2037 * 2 for the cookie + 2038 * all times BYTES_PER_XDR_UNIT to convert from 2039 * XDR units to bytes, plus the length of the name 2040 * rounded up to the nearest BYTES_PER_XDR_UNIT. 2041 */ 2042 entrysz = (1 + 2 + 1 + 2) * BYTES_PER_XDR_UNIT + 2043 roundup(namlen, BYTES_PER_XDR_UNIT); 2044 /* 2045 * We need to check to see if the number of bytes left 2046 * to go into the buffer will actually fit into the 2047 * buffer. This is calculated as the size of this 2048 * entry plus: 2049 * 1 for the true/false list indicator + 2050 * 1 for the eof indicator 2051 * times BYTES_PER_XDR_UNIT to convert from from 2052 * XDR units to bytes. 2053 */ 2054 tofit = entrysz + (1 + 1) * BYTES_PER_XDR_UNIT; 2055 if (bufsize + tofit > objp->count) { 2056 objp->reply.eof = FALSE; 2057 break; 2058 } 2059 fileid = (fileid3)(dp->d_ino); 2060 cookie = (cookie3)(dp->d_off); 2061 if (!xdr_bool(xdrs, &true) || 2062 !xdr_u_longlong_t(xdrs, &fileid) || 2063 !xdr_bytes(xdrs, &name, &namlen, ~0) || 2064 !xdr_u_longlong_t(xdrs, &cookie)) { 2065 return (FALSE); 2066 } 2067 bufsize += entrysz; 2068 } 2069 if (!xdr_bool(xdrs, &false)) 2070 return (FALSE); 2071 if (!xdr_bool(xdrs, &objp->reply.eof)) 2072 return (FALSE); 2073 return (TRUE); 2074 } 2075 2076 bool_t 2077 xdr_READDIR3res(XDR *xdrs, READDIR3res *objp) 2078 { 2079 READDIR3resok *resokp; 2080 2081 /* 2082 * ENCODE or FREE only 2083 */ 2084 if (xdrs->x_op == XDR_DECODE) 2085 return (FALSE); 2086 2087 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 2088 return (FALSE); 2089 if (objp->status != NFS3_OK) 2090 return (xdr_post_op_attr(xdrs, &objp->resfail.dir_attributes)); 2091 2092 /* xdr_READDIR3resok */ 2093 resokp = &objp->resok; 2094 if (!xdr_post_op_attr(xdrs, &resokp->dir_attributes)) 2095 return (FALSE); 2096 if (xdrs->x_op != XDR_ENCODE) 2097 return (TRUE); 2098 /* 2099 * cookieverf is really an opaque 8 byte 2100 * quantity, but we will treat it as a 2101 * hyper for efficiency, the cost of 2102 * a byteswap here saves bcopys elsewhere 2103 */ 2104 if (!xdr_u_longlong_t(xdrs, &resokp->cookieverf)) 2105 return (FALSE); 2106 return (xdr_putdirlist(xdrs, resokp)); 2107 } 2108 2109 bool_t 2110 xdr_READDIR3vres(XDR *xdrs, READDIR3vres *objp) 2111 { 2112 dirent64_t *dp; 2113 uint_t entries_size; 2114 int outcount = 0; 2115 2116 /* 2117 * DECODE or FREE only 2118 */ 2119 if (xdrs->x_op == XDR_FREE) 2120 return (TRUE); 2121 2122 if (xdrs->x_op != XDR_DECODE) 2123 return (FALSE); 2124 2125 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 2126 return (FALSE); 2127 2128 if (!xdr_post_op_vattr(xdrs, &objp->dir_attributes)) 2129 return (FALSE); 2130 2131 if (objp->status != NFS3_OK) 2132 return (TRUE); 2133 2134 /* 2135 * cookieverf is really an opaque 8 byte 2136 * quantity, but we will treat it as a 2137 * hyper for efficiency, the cost of 2138 * a byteswap here saves bcopys elsewhere 2139 */ 2140 if (!xdr_u_longlong_t(xdrs, &objp->cookieverf)) 2141 return (FALSE); 2142 2143 entries_size = objp->entries_size; 2144 dp = objp->entries; 2145 2146 for (;;) { 2147 uint_t this_reclen; 2148 bool_t valid; 2149 uint_t namlen; 2150 ino64_t fileid; 2151 2152 if (!XDR_GETINT32(xdrs, (int32_t *)&valid)) 2153 return (FALSE); 2154 if (!valid) { 2155 /* 2156 * We have run out of entries, decode eof. 2157 */ 2158 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->eof)) 2159 return (FALSE); 2160 2161 break; 2162 } 2163 2164 /* 2165 * fileid3 fileid 2166 */ 2167 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&fileid)) 2168 return (FALSE); 2169 2170 /* 2171 * filename3 name 2172 */ 2173 if (!XDR_GETINT32(xdrs, (int32_t *)&namlen)) 2174 return (FALSE); 2175 this_reclen = DIRENT64_RECLEN(namlen); 2176 2177 /* 2178 * If this will overflow buffer, stop decoding 2179 */ 2180 if ((outcount + this_reclen) > entries_size) { 2181 objp->eof = FALSE; 2182 break; 2183 } 2184 dp->d_reclen = this_reclen; 2185 dp->d_ino = fileid; 2186 2187 if (!xdr_opaque(xdrs, dp->d_name, namlen)) 2188 return (FALSE); 2189 bzero(&dp->d_name[namlen], 2190 DIRENT64_NAMELEN(this_reclen) - namlen); 2191 2192 /* 2193 * cookie3 cookie 2194 */ 2195 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&dp->d_off)) 2196 return (FALSE); 2197 objp->loff = dp->d_off; 2198 2199 outcount += this_reclen; 2200 dp = (dirent64_t *)((intptr_t)dp + this_reclen); 2201 } 2202 2203 objp->size = outcount; 2204 return (TRUE); 2205 } 2206 2207 bool_t 2208 xdr_READDIRPLUS3args(XDR *xdrs, READDIRPLUS3args *objp) 2209 { 2210 rdma_chunkinfo_t rci; 2211 struct xdr_ops *xops = xdrrdma_xops(); 2212 2213 if (xdrs->x_op == XDR_FREE) 2214 return (TRUE); 2215 2216 switch (xdrs->x_op) { 2217 case XDR_FREE: 2218 case XDR_ENCODE: 2219 if (!xdr_nfs_fh3(xdrs, &objp->dir)) 2220 return (FALSE); 2221 break; 2222 case XDR_DECODE: 2223 if (!xdr_nfs_fh3_server(xdrs, &objp->dir)) 2224 return (FALSE); 2225 break; 2226 } 2227 if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) && 2228 xdrs->x_op == XDR_ENCODE) { 2229 rci.rci_type = RCI_REPLY_CHUNK; 2230 rci.rci_len = objp->maxcount; 2231 XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci); 2232 } 2233 2234 if (!xdr_u_longlong_t(xdrs, &objp->cookie)) 2235 return (FALSE); 2236 /* 2237 * cookieverf is really an opaque 8 byte 2238 * quantity, but we will treat it as a 2239 * hyper for efficiency, the cost of 2240 * a byteswap here saves bcopys elsewhere 2241 */ 2242 if (!xdr_u_longlong_t(xdrs, &objp->cookieverf)) 2243 return (FALSE); 2244 if (!xdr_u_int(xdrs, &objp->dircount)) 2245 return (FALSE); 2246 return (xdr_u_int(xdrs, &objp->maxcount)); 2247 } 2248 2249 /* 2250 * ENCODE ONLY 2251 */ 2252 static bool_t 2253 xdr_putdirpluslist(XDR *xdrs, READDIRPLUS3resok *objp) 2254 { 2255 struct dirent64 *dp; 2256 char *name; 2257 int nents; 2258 bool_t true = TRUE; 2259 bool_t false = FALSE; 2260 fileid3 fileid; 2261 cookie3 cookie; 2262 entryplus3_info *infop; 2263 2264 if (xdrs->x_op != XDR_ENCODE) 2265 return (FALSE); 2266 2267 dp = (struct dirent64 *)objp->reply.entries; 2268 nents = objp->size; 2269 infop = objp->infop; 2270 2271 while (nents > 0) { 2272 if (dp->d_reclen == 0) 2273 return (FALSE); 2274 if (dp->d_ino != 0) { 2275 name = dp->d_name; 2276 fileid = (fileid3)(dp->d_ino); 2277 cookie = (cookie3)(dp->d_off); 2278 if (!xdr_bool(xdrs, &true) || 2279 !xdr_u_longlong_t(xdrs, &fileid) || 2280 !xdr_bytes(xdrs, &name, &infop->namelen, ~0) || 2281 !xdr_u_longlong_t(xdrs, &cookie) || 2282 !xdr_post_op_attr(xdrs, &infop->attr) || 2283 !xdr_post_op_fh3(xdrs, &infop->fh)) { 2284 return (FALSE); 2285 } 2286 } 2287 dp = nextdp(dp); 2288 infop++; 2289 nents--; 2290 } 2291 2292 if (!xdr_bool(xdrs, &false)) 2293 return (FALSE); 2294 if (!xdr_bool(xdrs, &objp->reply.eof)) 2295 return (FALSE); 2296 return (TRUE); 2297 } 2298 2299 bool_t 2300 xdr_READDIRPLUS3res(XDR *xdrs, READDIRPLUS3res *objp) 2301 { 2302 READDIRPLUS3resok *resokp; 2303 2304 /* 2305 * ENCODE or FREE only 2306 */ 2307 if (xdrs->x_op == XDR_DECODE) 2308 return (FALSE); 2309 2310 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 2311 return (FALSE); 2312 switch (objp->status) { 2313 case NFS3_OK: 2314 /* xdr_READDIRPLUS3resok */ 2315 resokp = &objp->resok; 2316 if (!xdr_post_op_attr(xdrs, &resokp->dir_attributes)) 2317 return (FALSE); 2318 /* 2319 * cookieverf is really an opaque 8 byte 2320 * quantity, but we will treat it as a 2321 * hyper for efficiency, the cost of 2322 * a byteswap here saves bcopys elsewhere 2323 */ 2324 if (!xdr_u_longlong_t(xdrs, &resokp->cookieverf)) 2325 return (FALSE); 2326 if (xdrs->x_op == XDR_ENCODE) { 2327 if (!xdr_putdirpluslist(xdrs, resokp)) 2328 return (FALSE); 2329 } 2330 break; 2331 default: 2332 return (xdr_post_op_attr(xdrs, &objp->resfail.dir_attributes)); 2333 } 2334 return (TRUE); 2335 } 2336 2337 /* 2338 * Decode readdirplus directly into a dirent64_t and do the DNLC caching. 2339 */ 2340 bool_t 2341 xdr_READDIRPLUS3vres(XDR *xdrs, READDIRPLUS3vres *objp) 2342 { 2343 dirent64_t *dp; 2344 vnode_t *dvp; 2345 uint_t entries_size; 2346 int outcount = 0; 2347 vnode_t *nvp; 2348 rnode_t *rp; 2349 post_op_vattr pov; 2350 vattr_t va; 2351 2352 /* 2353 * DECODE or FREE only 2354 */ 2355 if (xdrs->x_op == XDR_FREE) 2356 return (TRUE); 2357 2358 if (xdrs->x_op != XDR_DECODE) 2359 return (FALSE); 2360 2361 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->status)) 2362 return (FALSE); 2363 2364 if (!xdr_post_op_vattr(xdrs, &objp->dir_attributes)) 2365 return (FALSE); 2366 2367 if (objp->status != NFS3_OK) 2368 return (TRUE); 2369 2370 /* 2371 * cookieverf is really an opaque 8 byte 2372 * quantity, but we will treat it as a 2373 * hyper for efficiency, the cost of 2374 * a byteswap here saves bcopys elsewhere 2375 */ 2376 if (!xdr_u_longlong_t(xdrs, &objp->cookieverf)) 2377 return (FALSE); 2378 2379 dvp = objp->dir_attributes.fres.vp; 2380 rp = VTOR(dvp); 2381 2382 pov.fres.vap = &va; 2383 pov.fres.vp = dvp; 2384 2385 entries_size = objp->entries_size; 2386 dp = objp->entries; 2387 2388 for (;;) { 2389 uint_t this_reclen; 2390 bool_t valid; 2391 uint_t namlen; 2392 nfs_fh3 fh; 2393 int va_valid; 2394 int fh_valid; 2395 ino64_t fileid; 2396 2397 if (!XDR_GETINT32(xdrs, (int32_t *)&valid)) 2398 return (FALSE); 2399 if (!valid) { 2400 /* 2401 * We have run out of entries, decode eof. 2402 */ 2403 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->eof)) 2404 return (FALSE); 2405 2406 break; 2407 } 2408 2409 /* 2410 * fileid3 fileid 2411 */ 2412 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&fileid)) 2413 return (FALSE); 2414 2415 /* 2416 * filename3 name 2417 */ 2418 if (!XDR_GETINT32(xdrs, (int32_t *)&namlen)) 2419 return (FALSE); 2420 this_reclen = DIRENT64_RECLEN(namlen); 2421 2422 /* 2423 * If this will overflow buffer, stop decoding 2424 */ 2425 if ((outcount + this_reclen) > entries_size) { 2426 objp->eof = FALSE; 2427 break; 2428 } 2429 dp->d_reclen = this_reclen; 2430 dp->d_ino = fileid; 2431 2432 if (!xdr_opaque(xdrs, dp->d_name, namlen)) 2433 return (FALSE); 2434 bzero(&dp->d_name[namlen], 2435 DIRENT64_NAMELEN(this_reclen) - namlen); 2436 2437 /* 2438 * cookie3 cookie 2439 */ 2440 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&dp->d_off)) 2441 return (FALSE); 2442 objp->loff = dp->d_off; 2443 2444 /* 2445 * post_op_attr name_attributes 2446 */ 2447 if (!xdr_post_op_vattr(xdrs, &pov)) 2448 return (FALSE); 2449 2450 if (pov.attributes == TRUE && 2451 pov.fres.status == NFS3_OK) 2452 va_valid = TRUE; 2453 else 2454 va_valid = FALSE; 2455 2456 /* 2457 * post_op_fh3 name_handle 2458 */ 2459 if (!XDR_GETINT32(xdrs, (int32_t *)&fh_valid)) 2460 return (FALSE); 2461 2462 /* 2463 * By definition of the standard fh_valid can be 0 (FALSE) or 2464 * 1 (TRUE), but we have to account for it being anything else 2465 * in case some other system didn't follow the standard. Note 2466 * that this is why the else checks if the fh_valid variable 2467 * is != FALSE. 2468 */ 2469 if (fh_valid == TRUE) { 2470 if (!xdr_nfs_fh3(xdrs, &fh)) 2471 return (FALSE); 2472 } else { 2473 if (fh_valid != FALSE) 2474 return (FALSE); 2475 } 2476 2477 /* 2478 * If the name is "." or there are no attributes, 2479 * don't polute the DNLC with "." entries or files 2480 * we cannot determine the type for. 2481 */ 2482 if (!(namlen == 1 && dp->d_name[0] == '.') && 2483 va_valid && fh_valid) { 2484 2485 /* 2486 * Do the DNLC caching 2487 */ 2488 nvp = makenfs3node_va(&fh, &va, dvp->v_vfsp, 2489 objp->time, objp->credentials, 2490 rp->r_path, dp->d_name); 2491 dnlc_update(dvp, dp->d_name, nvp); 2492 VN_RELE(nvp); 2493 } 2494 2495 outcount += this_reclen; 2496 dp = (dirent64_t *)((intptr_t)dp + this_reclen); 2497 } 2498 2499 objp->size = outcount; 2500 return (TRUE); 2501 } 2502 2503 bool_t 2504 xdr_FSSTAT3res(XDR *xdrs, FSSTAT3res *objp) 2505 { 2506 FSSTAT3resok *resokp; 2507 2508 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 2509 return (FALSE); 2510 if (objp->status != NFS3_OK) 2511 return (xdr_post_op_attr(xdrs, &objp->resfail.obj_attributes)); 2512 2513 /* xdr_FSSTAT3resok */ 2514 resokp = &objp->resok; 2515 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes)) 2516 return (FALSE); 2517 if (!xdr_u_longlong_t(xdrs, &resokp->tbytes)) 2518 return (FALSE); 2519 if (!xdr_u_longlong_t(xdrs, &resokp->fbytes)) 2520 return (FALSE); 2521 if (!xdr_u_longlong_t(xdrs, &resokp->abytes)) 2522 return (FALSE); 2523 if (!xdr_u_longlong_t(xdrs, &resokp->tfiles)) 2524 return (FALSE); 2525 if (!xdr_u_longlong_t(xdrs, &resokp->ffiles)) 2526 return (FALSE); 2527 if (!xdr_u_longlong_t(xdrs, &resokp->afiles)) 2528 return (FALSE); 2529 return (xdr_u_int(xdrs, &resokp->invarsec)); 2530 } 2531 2532 bool_t 2533 xdr_FSINFO3res(XDR *xdrs, FSINFO3res *objp) 2534 { 2535 FSINFO3resok *resokp; 2536 2537 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 2538 return (FALSE); 2539 if (objp->status != NFS3_OK) /* xdr_FSSTAT3resfail */ 2540 return (xdr_post_op_attr(xdrs, &objp->resfail.obj_attributes)); 2541 2542 /* xdr_FSINFO3resok */ 2543 resokp = &objp->resok; 2544 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes)) 2545 return (FALSE); 2546 if (!xdr_u_int(xdrs, &resokp->rtmax)) 2547 return (FALSE); 2548 if (!xdr_u_int(xdrs, &resokp->rtpref)) 2549 return (FALSE); 2550 if (!xdr_u_int(xdrs, &resokp->rtmult)) 2551 return (FALSE); 2552 if (!xdr_u_int(xdrs, &resokp->wtmax)) 2553 return (FALSE); 2554 if (!xdr_u_int(xdrs, &resokp->wtpref)) 2555 return (FALSE); 2556 if (!xdr_u_int(xdrs, &resokp->wtmult)) 2557 return (FALSE); 2558 if (!xdr_u_int(xdrs, &resokp->dtpref)) 2559 return (FALSE); 2560 if (!xdr_u_longlong_t(xdrs, &resokp->maxfilesize)) 2561 return (FALSE); 2562 if (!xdr_u_int(xdrs, &resokp->time_delta.seconds)) 2563 return (FALSE); 2564 if (!xdr_u_int(xdrs, &resokp->time_delta.nseconds)) 2565 return (FALSE); 2566 return (xdr_u_int(xdrs, &resokp->properties)); 2567 } 2568 2569 bool_t 2570 xdr_PATHCONF3res(XDR *xdrs, PATHCONF3res *objp) 2571 { 2572 PATHCONF3resok *resokp; 2573 2574 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 2575 return (FALSE); 2576 if (objp->status != NFS3_OK) 2577 return (xdr_post_op_attr(xdrs, &objp->resfail.obj_attributes)); 2578 2579 /* xdr_PATHCONF3resok */ 2580 resokp = &objp->resok; 2581 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes)) 2582 return (FALSE); 2583 if (!xdr_u_int(xdrs, &resokp->info.link_max)) 2584 return (FALSE); 2585 if (!xdr_u_int(xdrs, &resokp->info.name_max)) 2586 return (FALSE); 2587 if (!xdr_bool(xdrs, &resokp->info.no_trunc)) 2588 return (FALSE); 2589 if (!xdr_bool(xdrs, &resokp->info.chown_restricted)) 2590 return (FALSE); 2591 if (!xdr_bool(xdrs, &resokp->info.case_insensitive)) 2592 return (FALSE); 2593 return (xdr_bool(xdrs, &resokp->info.case_preserving)); 2594 } 2595 2596 bool_t 2597 xdr_COMMIT3args(XDR *xdrs, COMMIT3args *objp) 2598 { 2599 if (xdrs->x_op == XDR_FREE) 2600 return (TRUE); 2601 2602 switch (xdrs->x_op) { 2603 case XDR_FREE: 2604 case XDR_ENCODE: 2605 if (!xdr_nfs_fh3(xdrs, &objp->file)) 2606 return (FALSE); 2607 break; 2608 case XDR_DECODE: 2609 if (!xdr_nfs_fh3_server(xdrs, &objp->file)) 2610 return (FALSE); 2611 break; 2612 } 2613 if (!xdr_u_longlong_t(xdrs, &objp->offset)) 2614 return (FALSE); 2615 return (xdr_u_int(xdrs, &objp->count)); 2616 } 2617 2618 bool_t 2619 xdr_COMMIT3res(XDR *xdrs, COMMIT3res *objp) 2620 { 2621 COMMIT3resok *resokp; 2622 2623 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 2624 return (FALSE); 2625 if (objp->status != NFS3_OK) 2626 return (xdr_wcc_data(xdrs, &objp->resfail.file_wcc)); 2627 2628 /* xdr_COMMIT3resok */ 2629 resokp = &objp->resok; 2630 if (!xdr_wcc_data(xdrs, &resokp->file_wcc)) 2631 return (FALSE); 2632 /* 2633 * writeverf3 is really an opaque 8 byte 2634 * quantity, but we will treat it as a 2635 * hyper for efficiency, the cost of 2636 * a byteswap here saves bcopys elsewhere 2637 */ 2638 return (xdr_u_longlong_t(xdrs, &resokp->verf)); 2639 } 2640