1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 27 /* All Rights Reserved */ 28 29 #include <sys/param.h> 30 #include <sys/types.h> 31 #include <sys/systm.h> 32 #include <sys/user.h> 33 #include <sys/vnode.h> 34 #include <sys/file.h> 35 #include <sys/dirent.h> 36 #include <sys/vfs.h> 37 #include <sys/stream.h> 38 #include <sys/strsubr.h> 39 #include <sys/debug.h> 40 #include <sys/t_lock.h> 41 #include <sys/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->count != 0) { 1346 return (xdrrdma_send_read_data( 1347 xdrs, resokp->count, 1348 resokp->wlist)); 1349 } 1350 return (TRUE); 1351 } 1352 } 1353 /* 1354 * Fall thru for the xdr_bytes() 1355 * 1356 * note: the mblk will be freed in 1357 * rfs3_read_free. 1358 */ 1359 } 1360 1361 /* no RDMA_WRITE transfer -- send data inline */ 1362 1363 ret = xdr_bytes(xdrs, (char **)&resokp->data.data_val, 1364 &resokp->data.data_len, nfs3tsize()); 1365 1366 return (ret); 1367 } 1368 1369 bool_t 1370 xdr_READ3vres(XDR *xdrs, READ3vres *objp) 1371 { 1372 count3 ocount; 1373 /* 1374 * DECODE or FREE only 1375 */ 1376 if (xdrs->x_op == XDR_FREE) 1377 return (TRUE); 1378 1379 if (xdrs->x_op != XDR_DECODE) 1380 return (FALSE); 1381 1382 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 1383 return (FALSE); 1384 1385 if (!xdr_post_op_vattr(xdrs, &objp->pov)) 1386 return (FALSE); 1387 1388 if (objp->status != NFS3_OK) 1389 return (TRUE); 1390 1391 if (!xdr_u_int(xdrs, &objp->count)) 1392 return (FALSE); 1393 1394 if (!xdr_bool(xdrs, &objp->eof)) 1395 return (FALSE); 1396 1397 /* 1398 * If read data received via RDMA_WRITE, don't do xdr_bytes(). 1399 * RDMA_WRITE already moved the data so decode length of RDMA_WRITE. 1400 */ 1401 if (xdrs->x_ops == &xdrrdma_ops) { 1402 struct clist *cl; 1403 1404 XDR_CONTROL(xdrs, XDR_RDMA_GET_WLIST, &cl); 1405 1406 if (cl) { 1407 if (!xdr_u_int(xdrs, &ocount)) { 1408 return (FALSE); 1409 } 1410 if (ocount != objp->count) { 1411 DTRACE_PROBE2(xdr__e__read3vres_fail, 1412 int, ocount, int, objp->count); 1413 objp->wlist = NULL; 1414 return (FALSE); 1415 } 1416 1417 objp->wlist_len = clist_len(cl); 1418 objp->data.data_len = ocount; 1419 1420 if (objp->wlist_len != 1421 roundup(objp->data.data_len, BYTES_PER_XDR_UNIT)) { 1422 DTRACE_PROBE2( 1423 xdr__e__read3vres_fail, 1424 int, ocount, 1425 int, objp->data.data_len); 1426 objp->wlist = NULL; 1427 return (FALSE); 1428 } 1429 return (TRUE); 1430 } 1431 } 1432 1433 return (xdr_bytes(xdrs, (char **)&objp->data.data_val, 1434 &objp->data.data_len, nfs3tsize())); 1435 } 1436 1437 bool_t 1438 xdr_READ3uiores(XDR *xdrs, READ3uiores *objp) 1439 { 1440 count3 ocount; 1441 bool_t attributes; 1442 mblk_t *mp; 1443 size_t n; 1444 int error; 1445 int size = (int)objp->size; 1446 struct uio *uiop = objp->uiop; 1447 int32_t fattr3_len = NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT; 1448 int32_t *ptr; 1449 1450 /* 1451 * DECODE or FREE only 1452 */ 1453 if (xdrs->x_op == XDR_FREE) 1454 return (TRUE); 1455 1456 if (xdrs->x_op != XDR_DECODE) 1457 return (FALSE); 1458 1459 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->status)) 1460 return (FALSE); 1461 1462 if (!XDR_GETINT32(xdrs, (int32_t *)&attributes)) 1463 return (FALSE); 1464 1465 /* 1466 * For directio we just skip over attributes if present 1467 */ 1468 switch (attributes) { 1469 case TRUE: 1470 if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &fattr3_len)) 1471 return (FALSE); 1472 break; 1473 case FALSE: 1474 break; 1475 default: 1476 return (FALSE); 1477 } 1478 1479 if (objp->status != NFS3_OK) 1480 return (TRUE); 1481 1482 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->count)) 1483 return (FALSE); 1484 1485 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->eof)) 1486 return (FALSE); 1487 1488 if (xdrs->x_ops == &xdrmblk_ops) { 1489 if (!xdrmblk_getmblk(xdrs, &mp, &objp->size)) 1490 return (FALSE); 1491 1492 if (objp->size == 0) 1493 return (TRUE); 1494 1495 if (objp->size > size) 1496 return (FALSE); 1497 1498 size = (int)objp->size; 1499 do { 1500 n = MIN(size, mp->b_wptr - mp->b_rptr); 1501 if ((n = MIN(uiop->uio_resid, n)) != 0) { 1502 1503 error = uiomove((char *)mp->b_rptr, n, UIO_READ, 1504 uiop); 1505 if (error) 1506 return (FALSE); 1507 mp->b_rptr += n; 1508 size -= n; 1509 } 1510 1511 while (mp && (mp->b_rptr >= mp->b_wptr)) 1512 mp = mp->b_cont; 1513 } while (mp && size > 0 && uiop->uio_resid > 0); 1514 1515 return (TRUE); 1516 } 1517 1518 if (xdrs->x_ops == &xdrrdma_ops) { 1519 struct clist *cl; 1520 1521 XDR_CONTROL(xdrs, XDR_RDMA_GET_WLIST, &cl); 1522 1523 objp->wlist = cl; 1524 1525 if (objp->wlist) { 1526 if (!xdr_u_int(xdrs, &ocount)) { 1527 objp->wlist = NULL; 1528 return (FALSE); 1529 } 1530 1531 if (ocount != objp->count) { 1532 DTRACE_PROBE2(xdr__e__read3uiores_fail, 1533 int, ocount, int, objp->count); 1534 objp->wlist = NULL; 1535 return (FALSE); 1536 } 1537 1538 objp->wlist_len = clist_len(cl); 1539 1540 uiop->uio_resid -= objp->count; 1541 uiop->uio_iov->iov_len -= objp->count; 1542 uiop->uio_iov->iov_base += objp->count; 1543 uiop->uio_loffset += objp->count; 1544 1545 /* 1546 * XXX: Assume 1 iov, needs to be changed. 1547 */ 1548 objp->size = objp->count; 1549 1550 return (TRUE); 1551 } 1552 } 1553 1554 /* 1555 * This isn't an xdrmblk stream nor RDMA. 1556 * Handle the likely case that it can be 1557 * inlined (ex. xdrmem). 1558 */ 1559 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->size)) 1560 return (FALSE); 1561 1562 if (objp->size == 0) 1563 return (TRUE); 1564 1565 if (objp->size > size) 1566 return (FALSE); 1567 1568 size = (int)objp->size; 1569 if ((ptr = XDR_INLINE(xdrs, size)) != NULL) 1570 return (uiomove(ptr, size, UIO_READ, uiop) ? FALSE : TRUE); 1571 1572 /* 1573 * Handle some other (unlikely) stream type that will need a copy. 1574 */ 1575 if ((ptr = kmem_alloc(size, KM_NOSLEEP)) == NULL) 1576 return (FALSE); 1577 1578 if (!XDR_GETBYTES(xdrs, (caddr_t)ptr, size)) { 1579 kmem_free(ptr, size); 1580 return (FALSE); 1581 } 1582 error = uiomove(ptr, size, UIO_READ, uiop); 1583 kmem_free(ptr, size); 1584 1585 return (error ? FALSE : TRUE); 1586 } 1587 1588 bool_t 1589 xdr_WRITE3args(XDR *xdrs, WRITE3args *objp) 1590 { 1591 switch (xdrs->x_op) { 1592 case XDR_FREE: 1593 case XDR_ENCODE: 1594 if (!xdr_nfs_fh3(xdrs, &objp->file)) 1595 return (FALSE); 1596 break; 1597 case XDR_DECODE: 1598 if (!xdr_nfs_fh3_server(xdrs, &objp->file)) 1599 return (FALSE); 1600 break; 1601 } 1602 if (!xdr_u_longlong_t(xdrs, &objp->offset)) 1603 return (FALSE); 1604 if (!xdr_u_int(xdrs, &objp->count)) 1605 return (FALSE); 1606 if (!xdr_enum(xdrs, (enum_t *)&objp->stable)) 1607 return (FALSE); 1608 1609 if (xdrs->x_op == XDR_DECODE) { 1610 if (xdrs->x_ops == &xdrmblk_ops) { 1611 if (xdrmblk_getmblk(xdrs, &objp->mblk, 1612 &objp->data.data_len) == TRUE) { 1613 objp->data.data_val = NULL; 1614 return (TRUE); 1615 } 1616 } 1617 objp->mblk = NULL; 1618 1619 if (xdrs->x_ops == &xdrrdmablk_ops) { 1620 if (xdrrdma_getrdmablk(xdrs, &objp->rlist, 1621 &objp->data.data_len, 1622 &objp->conn, nfs3tsize()) == TRUE) { 1623 objp->data.data_val = NULL; 1624 if (xdrrdma_read_from_client( 1625 objp->rlist, 1626 &objp->conn, 1627 objp->count) == FALSE) { 1628 return (FALSE); 1629 } 1630 return (TRUE); 1631 } 1632 } 1633 objp->rlist = NULL; 1634 1635 /* Else fall thru for the xdr_bytes(). */ 1636 } 1637 1638 if (xdrs->x_op == XDR_FREE) { 1639 if (objp->rlist != NULL) { 1640 (void) xdrrdma_free_clist(objp->conn, objp->rlist); 1641 objp->rlist = NULL; 1642 objp->data.data_val = NULL; 1643 return (TRUE); 1644 } 1645 } 1646 1647 DTRACE_PROBE1(xdr__i__write3_buf_len, 1648 int, objp->data.data_len); 1649 1650 return (xdr_bytes(xdrs, (char **)&objp->data.data_val, 1651 &objp->data.data_len, nfs3tsize())); 1652 } 1653 1654 bool_t 1655 xdr_WRITE3res(XDR *xdrs, WRITE3res *objp) 1656 { 1657 WRITE3resok *resokp; 1658 1659 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 1660 return (FALSE); 1661 if (objp->status != NFS3_OK) /* xdr_WRITE3resfail */ 1662 return (xdr_wcc_data(xdrs, &objp->resfail.file_wcc)); 1663 1664 /* xdr_WRITE3resok */ 1665 resokp = &objp->resok; 1666 if (!xdr_wcc_data(xdrs, &resokp->file_wcc)) 1667 return (FALSE); 1668 if (!xdr_u_int(xdrs, &resokp->count)) 1669 return (FALSE); 1670 if (!xdr_enum(xdrs, (enum_t *)&resokp->committed)) 1671 return (FALSE); 1672 /* 1673 * writeverf3 is really an opaque 8 byte 1674 * quantity, but we will treat it as a 1675 * hyper for efficiency, the cost of 1676 * a byteswap here saves bcopys elsewhere 1677 */ 1678 return (xdr_u_longlong_t(xdrs, &resokp->verf)); 1679 } 1680 1681 bool_t 1682 xdr_CREATE3args(XDR *xdrs, CREATE3args *objp) 1683 { 1684 createhow3 *howp; 1685 1686 if (!xdr_diropargs3(xdrs, &objp->where)) 1687 return (FALSE); 1688 1689 /* xdr_createhow3 */ 1690 howp = &objp->how; 1691 1692 if (!xdr_enum(xdrs, (enum_t *)&howp->mode)) 1693 return (FALSE); 1694 switch (howp->mode) { 1695 case UNCHECKED: 1696 case GUARDED: 1697 return (xdr_sattr3(xdrs, &howp->createhow3_u.obj_attributes)); 1698 case EXCLUSIVE: 1699 /* 1700 * createverf3 is really an opaque 8 byte 1701 * quantity, but we will treat it as a 1702 * hyper for efficiency, the cost of 1703 * a byteswap here saves bcopys elsewhere 1704 */ 1705 return (xdr_u_longlong_t(xdrs, &howp->createhow3_u.verf)); 1706 default: 1707 return (FALSE); 1708 } 1709 } 1710 1711 bool_t 1712 xdr_CREATE3res(XDR *xdrs, CREATE3res *objp) 1713 { 1714 CREATE3resok *resokp; 1715 1716 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 1717 return (FALSE); 1718 switch (objp->status) { 1719 case NFS3_OK: 1720 /* xdr_CREATE3resok */ 1721 resokp = &objp->resok; 1722 1723 if (!xdr_post_op_fh3(xdrs, &resokp->obj)) 1724 return (FALSE); 1725 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes)) 1726 return (FALSE); 1727 return (xdr_wcc_data(xdrs, &resokp->dir_wcc)); 1728 default: 1729 /* xdr_CREATE3resfail */ 1730 return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc)); 1731 } 1732 } 1733 1734 bool_t 1735 xdr_MKDIR3args(XDR *xdrs, MKDIR3args *objp) 1736 { 1737 if (!xdr_diropargs3(xdrs, &objp->where)) 1738 return (FALSE); 1739 return (xdr_sattr3(xdrs, &objp->attributes)); 1740 } 1741 1742 bool_t 1743 xdr_MKDIR3res(XDR *xdrs, MKDIR3res *objp) 1744 { 1745 MKDIR3resok *resokp; 1746 1747 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 1748 return (FALSE); 1749 switch (objp->status) { 1750 case NFS3_OK: 1751 /* xdr_MKDIR3resok */ 1752 resokp = &objp->resok; 1753 1754 if (!xdr_post_op_fh3(xdrs, &resokp->obj)) 1755 return (FALSE); 1756 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes)) 1757 return (FALSE); 1758 return (xdr_wcc_data(xdrs, &resokp->dir_wcc)); 1759 default: 1760 return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc)); 1761 } 1762 } 1763 1764 bool_t 1765 xdr_SYMLINK3args(XDR *xdrs, SYMLINK3args *objp) 1766 { 1767 if (!xdr_diropargs3(xdrs, &objp->where)) 1768 return (FALSE); 1769 if (!xdr_sattr3(xdrs, &objp->symlink.symlink_attributes)) 1770 return (FALSE); 1771 return (xdr_string3(xdrs, &objp->symlink.symlink_data, MAXPATHLEN)); 1772 } 1773 1774 bool_t 1775 xdr_SYMLINK3res(XDR *xdrs, SYMLINK3res *objp) 1776 { 1777 SYMLINK3resok *resokp; 1778 1779 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 1780 return (FALSE); 1781 switch (objp->status) { 1782 case NFS3_OK: 1783 resokp = &objp->resok; 1784 /* xdr_SYMLINK3resok */ 1785 if (!xdr_post_op_fh3(xdrs, &resokp->obj)) 1786 return (FALSE); 1787 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes)) 1788 return (FALSE); 1789 return (xdr_wcc_data(xdrs, &resokp->dir_wcc)); 1790 default: 1791 return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc)); 1792 } 1793 } 1794 1795 bool_t 1796 xdr_MKNOD3args(XDR *xdrs, MKNOD3args *objp) 1797 { 1798 mknoddata3 *whatp; 1799 devicedata3 *nod_objp; 1800 1801 if (!xdr_diropargs3(xdrs, &objp->where)) 1802 return (FALSE); 1803 1804 whatp = &objp->what; 1805 if (!xdr_enum(xdrs, (enum_t *)&whatp->type)) 1806 return (FALSE); 1807 switch (whatp->type) { 1808 case NF3CHR: 1809 case NF3BLK: 1810 /* xdr_devicedata3 */ 1811 nod_objp = &whatp->mknoddata3_u.device; 1812 if (!xdr_sattr3(xdrs, &nod_objp->dev_attributes)) 1813 return (FALSE); 1814 if (!xdr_u_int(xdrs, &nod_objp->spec.specdata1)) 1815 return (FALSE); 1816 return (xdr_u_int(xdrs, &nod_objp->spec.specdata2)); 1817 case NF3SOCK: 1818 case NF3FIFO: 1819 return (xdr_sattr3(xdrs, &whatp->mknoddata3_u.pipe_attributes)); 1820 default: 1821 break; 1822 } 1823 return (TRUE); 1824 } 1825 1826 bool_t 1827 xdr_MKNOD3res(XDR *xdrs, MKNOD3res *objp) 1828 { 1829 MKNOD3resok *resokp; 1830 1831 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 1832 return (FALSE); 1833 switch (objp->status) { 1834 case NFS3_OK: 1835 /* xdr_MKNOD3resok */ 1836 resokp = &objp->resok; 1837 if (!xdr_post_op_fh3(xdrs, &resokp->obj)) 1838 return (FALSE); 1839 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes)) 1840 return (FALSE); 1841 return (xdr_wcc_data(xdrs, &resokp->dir_wcc)); 1842 default: 1843 return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc)); 1844 } 1845 } 1846 1847 bool_t 1848 xdr_REMOVE3res(XDR *xdrs, REMOVE3res *objp) 1849 { 1850 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 1851 return (FALSE); 1852 switch (objp->status) { 1853 case NFS3_OK: 1854 return (xdr_wcc_data(xdrs, &objp->resok.dir_wcc)); 1855 default: 1856 return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc)); 1857 } 1858 } 1859 1860 bool_t 1861 xdr_RMDIR3res(XDR *xdrs, RMDIR3res *objp) 1862 { 1863 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 1864 return (FALSE); 1865 switch (objp->status) { 1866 case NFS3_OK: 1867 return (xdr_wcc_data(xdrs, &objp->resok.dir_wcc)); 1868 default: 1869 return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc)); 1870 } 1871 } 1872 1873 bool_t 1874 xdr_RENAME3args(XDR *xdrs, RENAME3args *objp) 1875 { 1876 if (!xdr_diropargs3(xdrs, &objp->from)) 1877 return (FALSE); 1878 return (xdr_diropargs3(xdrs, &objp->to)); 1879 } 1880 1881 bool_t 1882 xdr_RENAME3res(XDR *xdrs, RENAME3res *objp) 1883 { 1884 RENAME3resok *resokp; 1885 RENAME3resfail *resfailp; 1886 1887 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 1888 return (FALSE); 1889 switch (objp->status) { 1890 case NFS3_OK: 1891 /* xdr_RENAME3resok */ 1892 resokp = &objp->resok; 1893 1894 if (!xdr_wcc_data(xdrs, &resokp->fromdir_wcc)) 1895 return (FALSE); 1896 return (xdr_wcc_data(xdrs, &resokp->todir_wcc)); 1897 default: 1898 /* xdr_RENAME3resfail */ 1899 resfailp = &objp->resfail; 1900 if (!xdr_wcc_data(xdrs, &resfailp->fromdir_wcc)) 1901 return (FALSE); 1902 return (xdr_wcc_data(xdrs, &resfailp->todir_wcc)); 1903 } 1904 } 1905 1906 bool_t 1907 xdr_LINK3args(XDR *xdrs, LINK3args *objp) 1908 { 1909 switch (xdrs->x_op) { 1910 case XDR_FREE: 1911 case XDR_ENCODE: 1912 if (!xdr_nfs_fh3(xdrs, &objp->file)) 1913 return (FALSE); 1914 break; 1915 case XDR_DECODE: 1916 if (!xdr_nfs_fh3_server(xdrs, &objp->file)) 1917 return (FALSE); 1918 break; 1919 } 1920 return (xdr_diropargs3(xdrs, &objp->link)); 1921 } 1922 1923 bool_t 1924 xdr_LINK3res(XDR *xdrs, LINK3res *objp) 1925 { 1926 LINK3resok *resokp; 1927 LINK3resfail *resfailp; 1928 1929 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 1930 return (FALSE); 1931 switch (objp->status) { 1932 case NFS3_OK: 1933 /* xdr_LINK3resok */ 1934 resokp = &objp->resok; 1935 if (!xdr_post_op_attr(xdrs, &resokp->file_attributes)) 1936 return (FALSE); 1937 return (xdr_wcc_data(xdrs, &resokp->linkdir_wcc)); 1938 default: 1939 /* xdr_LINK3resfail */ 1940 resfailp = &objp->resfail; 1941 if (!xdr_post_op_attr(xdrs, &resfailp->file_attributes)) 1942 return (FALSE); 1943 return (xdr_wcc_data(xdrs, &resfailp->linkdir_wcc)); 1944 } 1945 } 1946 1947 bool_t 1948 xdr_READDIR3args(XDR *xdrs, READDIR3args *objp) 1949 { 1950 rdma_chunkinfo_t rci; 1951 struct xdr_ops *xops = xdrrdma_xops(); 1952 1953 if (xdrs->x_op == XDR_FREE) 1954 return (TRUE); 1955 1956 switch (xdrs->x_op) { 1957 case XDR_FREE: 1958 case XDR_ENCODE: 1959 if (!xdr_nfs_fh3(xdrs, &objp->dir)) 1960 return (FALSE); 1961 break; 1962 case XDR_DECODE: 1963 if (!xdr_nfs_fh3_server(xdrs, &objp->dir)) 1964 return (FALSE); 1965 break; 1966 } 1967 if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) && 1968 xdrs->x_op == XDR_ENCODE) { 1969 rci.rci_type = RCI_REPLY_CHUNK; 1970 rci.rci_len = objp->count; 1971 XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci); 1972 } 1973 1974 if (!xdr_u_longlong_t(xdrs, &objp->cookie)) 1975 return (FALSE); 1976 /* 1977 * cookieverf is really an opaque 8 byte 1978 * quantity, but we will treat it as a 1979 * hyper for efficiency, the cost of 1980 * a byteswap here saves bcopys elsewhere 1981 */ 1982 if (!xdr_u_longlong_t(xdrs, &objp->cookieverf)) 1983 return (FALSE); 1984 return (xdr_u_int(xdrs, &objp->count)); 1985 } 1986 1987 #ifdef nextdp 1988 #undef nextdp 1989 #endif 1990 #define nextdp(dp) ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen)) 1991 #ifdef roundup 1992 #undef roundup 1993 #endif 1994 #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) 1995 1996 /* 1997 * ENCODE ONLY 1998 */ 1999 static bool_t 2000 xdr_putdirlist(XDR *xdrs, READDIR3resok *objp) 2001 { 2002 struct dirent64 *dp; 2003 char *name; 2004 int size; 2005 int bufsize; 2006 uint_t namlen; 2007 bool_t true = TRUE; 2008 bool_t false = FALSE; 2009 int entrysz; 2010 int tofit; 2011 fileid3 fileid; 2012 cookie3 cookie; 2013 2014 if (xdrs->x_op != XDR_ENCODE) 2015 return (FALSE); 2016 2017 /* 2018 * bufsize is used to keep track of the size of the response. 2019 * It is primed with: 2020 * 1 for the status + 2021 * 1 for the dir_attributes.attributes boolean + 2022 * 2 for the cookie verifier 2023 * all times BYTES_PER_XDR_UNIT to convert from XDR units 2024 * to bytes. If there are directory attributes to be 2025 * returned, then: 2026 * NFS3_SIZEOF_FATTR3 for the dir_attributes.attr fattr3 2027 * time BYTES_PER_XDR_UNIT is added to account for them. 2028 */ 2029 bufsize = (1 + 1 + 2) * BYTES_PER_XDR_UNIT; 2030 if (objp->dir_attributes.attributes) 2031 bufsize += NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT; 2032 for (size = objp->size, dp = (struct dirent64 *)objp->reply.entries; 2033 size > 0; 2034 size -= dp->d_reclen, dp = nextdp(dp)) { 2035 if (dp->d_reclen == 0) 2036 return (FALSE); 2037 if (dp->d_ino == 0) 2038 continue; 2039 name = dp->d_name; 2040 namlen = (uint_t)strlen(dp->d_name); 2041 /* 2042 * An entry is composed of: 2043 * 1 for the true/false list indicator + 2044 * 2 for the fileid + 2045 * 1 for the length of the name + 2046 * 2 for the cookie + 2047 * all times BYTES_PER_XDR_UNIT to convert from 2048 * XDR units to bytes, plus the length of the name 2049 * rounded up to the nearest BYTES_PER_XDR_UNIT. 2050 */ 2051 entrysz = (1 + 2 + 1 + 2) * BYTES_PER_XDR_UNIT + 2052 roundup(namlen, BYTES_PER_XDR_UNIT); 2053 /* 2054 * We need to check to see if the number of bytes left 2055 * to go into the buffer will actually fit into the 2056 * buffer. This is calculated as the size of this 2057 * entry plus: 2058 * 1 for the true/false list indicator + 2059 * 1 for the eof indicator 2060 * times BYTES_PER_XDR_UNIT to convert from from 2061 * XDR units to bytes. 2062 */ 2063 tofit = entrysz + (1 + 1) * BYTES_PER_XDR_UNIT; 2064 if (bufsize + tofit > objp->count) { 2065 objp->reply.eof = FALSE; 2066 break; 2067 } 2068 fileid = (fileid3)(dp->d_ino); 2069 cookie = (cookie3)(dp->d_off); 2070 if (!xdr_bool(xdrs, &true) || 2071 !xdr_u_longlong_t(xdrs, &fileid) || 2072 !xdr_bytes(xdrs, &name, &namlen, ~0) || 2073 !xdr_u_longlong_t(xdrs, &cookie)) { 2074 return (FALSE); 2075 } 2076 bufsize += entrysz; 2077 } 2078 if (!xdr_bool(xdrs, &false)) 2079 return (FALSE); 2080 if (!xdr_bool(xdrs, &objp->reply.eof)) 2081 return (FALSE); 2082 return (TRUE); 2083 } 2084 2085 bool_t 2086 xdr_READDIR3res(XDR *xdrs, READDIR3res *objp) 2087 { 2088 READDIR3resok *resokp; 2089 2090 /* 2091 * ENCODE or FREE only 2092 */ 2093 if (xdrs->x_op == XDR_DECODE) 2094 return (FALSE); 2095 2096 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 2097 return (FALSE); 2098 if (objp->status != NFS3_OK) 2099 return (xdr_post_op_attr(xdrs, &objp->resfail.dir_attributes)); 2100 2101 /* xdr_READDIR3resok */ 2102 resokp = &objp->resok; 2103 if (!xdr_post_op_attr(xdrs, &resokp->dir_attributes)) 2104 return (FALSE); 2105 if (xdrs->x_op != XDR_ENCODE) 2106 return (TRUE); 2107 /* 2108 * cookieverf is really an opaque 8 byte 2109 * quantity, but we will treat it as a 2110 * hyper for efficiency, the cost of 2111 * a byteswap here saves bcopys elsewhere 2112 */ 2113 if (!xdr_u_longlong_t(xdrs, &resokp->cookieverf)) 2114 return (FALSE); 2115 return (xdr_putdirlist(xdrs, resokp)); 2116 } 2117 2118 bool_t 2119 xdr_READDIR3vres(XDR *xdrs, READDIR3vres *objp) 2120 { 2121 dirent64_t *dp; 2122 uint_t entries_size; 2123 int outcount = 0; 2124 2125 /* 2126 * DECODE or FREE only 2127 */ 2128 if (xdrs->x_op == XDR_FREE) 2129 return (TRUE); 2130 2131 if (xdrs->x_op != XDR_DECODE) 2132 return (FALSE); 2133 2134 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 2135 return (FALSE); 2136 2137 if (!xdr_post_op_vattr(xdrs, &objp->dir_attributes)) 2138 return (FALSE); 2139 2140 if (objp->status != NFS3_OK) 2141 return (TRUE); 2142 2143 /* 2144 * cookieverf is really an opaque 8 byte 2145 * quantity, but we will treat it as a 2146 * hyper for efficiency, the cost of 2147 * a byteswap here saves bcopys elsewhere 2148 */ 2149 if (!xdr_u_longlong_t(xdrs, &objp->cookieverf)) 2150 return (FALSE); 2151 2152 entries_size = objp->entries_size; 2153 dp = objp->entries; 2154 2155 for (;;) { 2156 uint_t this_reclen; 2157 bool_t valid; 2158 uint_t namlen; 2159 ino64_t fileid; 2160 2161 if (!XDR_GETINT32(xdrs, (int32_t *)&valid)) 2162 return (FALSE); 2163 if (!valid) { 2164 /* 2165 * We have run out of entries, decode eof. 2166 */ 2167 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->eof)) 2168 return (FALSE); 2169 2170 break; 2171 } 2172 2173 /* 2174 * fileid3 fileid 2175 */ 2176 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&fileid)) 2177 return (FALSE); 2178 2179 /* 2180 * filename3 name 2181 */ 2182 if (!XDR_GETINT32(xdrs, (int32_t *)&namlen)) 2183 return (FALSE); 2184 this_reclen = DIRENT64_RECLEN(namlen); 2185 2186 /* 2187 * If this will overflow buffer, stop decoding 2188 */ 2189 if ((outcount + this_reclen) > entries_size) { 2190 objp->eof = FALSE; 2191 break; 2192 } 2193 dp->d_reclen = this_reclen; 2194 dp->d_ino = fileid; 2195 2196 if (!xdr_opaque(xdrs, dp->d_name, namlen)) 2197 return (FALSE); 2198 bzero(&dp->d_name[namlen], 2199 DIRENT64_NAMELEN(this_reclen) - namlen); 2200 2201 /* 2202 * cookie3 cookie 2203 */ 2204 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&dp->d_off)) 2205 return (FALSE); 2206 objp->loff = dp->d_off; 2207 2208 outcount += this_reclen; 2209 dp = (dirent64_t *)((intptr_t)dp + this_reclen); 2210 } 2211 2212 objp->size = outcount; 2213 return (TRUE); 2214 } 2215 2216 bool_t 2217 xdr_READDIRPLUS3args(XDR *xdrs, READDIRPLUS3args *objp) 2218 { 2219 rdma_chunkinfo_t rci; 2220 struct xdr_ops *xops = xdrrdma_xops(); 2221 2222 if (xdrs->x_op == XDR_FREE) 2223 return (TRUE); 2224 2225 switch (xdrs->x_op) { 2226 case XDR_FREE: 2227 case XDR_ENCODE: 2228 if (!xdr_nfs_fh3(xdrs, &objp->dir)) 2229 return (FALSE); 2230 break; 2231 case XDR_DECODE: 2232 if (!xdr_nfs_fh3_server(xdrs, &objp->dir)) 2233 return (FALSE); 2234 break; 2235 } 2236 if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) && 2237 xdrs->x_op == XDR_ENCODE) { 2238 rci.rci_type = RCI_REPLY_CHUNK; 2239 rci.rci_len = objp->maxcount; 2240 XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci); 2241 } 2242 2243 if (!xdr_u_longlong_t(xdrs, &objp->cookie)) 2244 return (FALSE); 2245 /* 2246 * cookieverf is really an opaque 8 byte 2247 * quantity, but we will treat it as a 2248 * hyper for efficiency, the cost of 2249 * a byteswap here saves bcopys elsewhere 2250 */ 2251 if (!xdr_u_longlong_t(xdrs, &objp->cookieverf)) 2252 return (FALSE); 2253 if (!xdr_u_int(xdrs, &objp->dircount)) 2254 return (FALSE); 2255 return (xdr_u_int(xdrs, &objp->maxcount)); 2256 } 2257 2258 /* 2259 * ENCODE ONLY 2260 */ 2261 static bool_t 2262 xdr_putdirpluslist(XDR *xdrs, READDIRPLUS3resok *objp) 2263 { 2264 struct dirent64 *dp; 2265 char *name; 2266 int nents; 2267 bool_t true = TRUE; 2268 bool_t false = FALSE; 2269 fileid3 fileid; 2270 cookie3 cookie; 2271 entryplus3_info *infop; 2272 2273 if (xdrs->x_op != XDR_ENCODE) 2274 return (FALSE); 2275 2276 dp = (struct dirent64 *)objp->reply.entries; 2277 nents = objp->size; 2278 infop = objp->infop; 2279 2280 while (nents > 0) { 2281 if (dp->d_reclen == 0) 2282 return (FALSE); 2283 if (dp->d_ino != 0) { 2284 name = dp->d_name; 2285 fileid = (fileid3)(dp->d_ino); 2286 cookie = (cookie3)(dp->d_off); 2287 if (!xdr_bool(xdrs, &true) || 2288 !xdr_u_longlong_t(xdrs, &fileid) || 2289 !xdr_bytes(xdrs, &name, &infop->namelen, ~0) || 2290 !xdr_u_longlong_t(xdrs, &cookie) || 2291 !xdr_post_op_attr(xdrs, &infop->attr) || 2292 !xdr_post_op_fh3(xdrs, &infop->fh)) { 2293 return (FALSE); 2294 } 2295 } 2296 dp = nextdp(dp); 2297 infop++; 2298 nents--; 2299 } 2300 2301 if (!xdr_bool(xdrs, &false)) 2302 return (FALSE); 2303 if (!xdr_bool(xdrs, &objp->reply.eof)) 2304 return (FALSE); 2305 return (TRUE); 2306 } 2307 2308 bool_t 2309 xdr_READDIRPLUS3res(XDR *xdrs, READDIRPLUS3res *objp) 2310 { 2311 READDIRPLUS3resok *resokp; 2312 2313 /* 2314 * ENCODE or FREE only 2315 */ 2316 if (xdrs->x_op == XDR_DECODE) 2317 return (FALSE); 2318 2319 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 2320 return (FALSE); 2321 switch (objp->status) { 2322 case NFS3_OK: 2323 /* xdr_READDIRPLUS3resok */ 2324 resokp = &objp->resok; 2325 if (!xdr_post_op_attr(xdrs, &resokp->dir_attributes)) 2326 return (FALSE); 2327 /* 2328 * cookieverf is really an opaque 8 byte 2329 * quantity, but we will treat it as a 2330 * hyper for efficiency, the cost of 2331 * a byteswap here saves bcopys elsewhere 2332 */ 2333 if (!xdr_u_longlong_t(xdrs, &resokp->cookieverf)) 2334 return (FALSE); 2335 if (xdrs->x_op == XDR_ENCODE) { 2336 if (!xdr_putdirpluslist(xdrs, resokp)) 2337 return (FALSE); 2338 } 2339 break; 2340 default: 2341 return (xdr_post_op_attr(xdrs, &objp->resfail.dir_attributes)); 2342 } 2343 return (TRUE); 2344 } 2345 2346 /* 2347 * Decode readdirplus directly into a dirent64_t and do the DNLC caching. 2348 */ 2349 bool_t 2350 xdr_READDIRPLUS3vres(XDR *xdrs, READDIRPLUS3vres *objp) 2351 { 2352 dirent64_t *dp; 2353 vnode_t *dvp; 2354 uint_t entries_size; 2355 int outcount = 0; 2356 vnode_t *nvp; 2357 rnode_t *rp; 2358 post_op_vattr pov; 2359 vattr_t va; 2360 2361 /* 2362 * DECODE or FREE only 2363 */ 2364 if (xdrs->x_op == XDR_FREE) 2365 return (TRUE); 2366 2367 if (xdrs->x_op != XDR_DECODE) 2368 return (FALSE); 2369 2370 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->status)) 2371 return (FALSE); 2372 2373 if (!xdr_post_op_vattr(xdrs, &objp->dir_attributes)) 2374 return (FALSE); 2375 2376 if (objp->status != NFS3_OK) 2377 return (TRUE); 2378 2379 /* 2380 * cookieverf is really an opaque 8 byte 2381 * quantity, but we will treat it as a 2382 * hyper for efficiency, the cost of 2383 * a byteswap here saves bcopys elsewhere 2384 */ 2385 if (!xdr_u_longlong_t(xdrs, &objp->cookieverf)) 2386 return (FALSE); 2387 2388 dvp = objp->dir_attributes.fres.vp; 2389 rp = VTOR(dvp); 2390 2391 pov.fres.vap = &va; 2392 pov.fres.vp = dvp; 2393 2394 entries_size = objp->entries_size; 2395 dp = objp->entries; 2396 2397 for (;;) { 2398 uint_t this_reclen; 2399 bool_t valid; 2400 uint_t namlen; 2401 nfs_fh3 fh; 2402 int va_valid; 2403 int fh_valid; 2404 ino64_t fileid; 2405 2406 if (!XDR_GETINT32(xdrs, (int32_t *)&valid)) 2407 return (FALSE); 2408 if (!valid) { 2409 /* 2410 * We have run out of entries, decode eof. 2411 */ 2412 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->eof)) 2413 return (FALSE); 2414 2415 break; 2416 } 2417 2418 /* 2419 * fileid3 fileid 2420 */ 2421 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&fileid)) 2422 return (FALSE); 2423 2424 /* 2425 * filename3 name 2426 */ 2427 if (!XDR_GETINT32(xdrs, (int32_t *)&namlen)) 2428 return (FALSE); 2429 this_reclen = DIRENT64_RECLEN(namlen); 2430 2431 /* 2432 * If this will overflow buffer, stop decoding 2433 */ 2434 if ((outcount + this_reclen) > entries_size) { 2435 objp->eof = FALSE; 2436 break; 2437 } 2438 dp->d_reclen = this_reclen; 2439 dp->d_ino = fileid; 2440 2441 if (!xdr_opaque(xdrs, dp->d_name, namlen)) 2442 return (FALSE); 2443 bzero(&dp->d_name[namlen], 2444 DIRENT64_NAMELEN(this_reclen) - namlen); 2445 2446 /* 2447 * cookie3 cookie 2448 */ 2449 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&dp->d_off)) 2450 return (FALSE); 2451 objp->loff = dp->d_off; 2452 2453 /* 2454 * post_op_attr name_attributes 2455 */ 2456 if (!xdr_post_op_vattr(xdrs, &pov)) 2457 return (FALSE); 2458 2459 if (pov.attributes == TRUE && 2460 pov.fres.status == NFS3_OK) 2461 va_valid = TRUE; 2462 else 2463 va_valid = FALSE; 2464 2465 /* 2466 * post_op_fh3 name_handle 2467 */ 2468 if (!XDR_GETINT32(xdrs, (int32_t *)&fh_valid)) 2469 return (FALSE); 2470 2471 /* 2472 * By definition of the standard fh_valid can be 0 (FALSE) or 2473 * 1 (TRUE), but we have to account for it being anything else 2474 * in case some other system didn't follow the standard. Note 2475 * that this is why the else checks if the fh_valid variable 2476 * is != FALSE. 2477 */ 2478 if (fh_valid == TRUE) { 2479 if (!xdr_nfs_fh3(xdrs, &fh)) 2480 return (FALSE); 2481 } else { 2482 if (fh_valid != FALSE) 2483 return (FALSE); 2484 } 2485 2486 /* 2487 * If the name is "." or there are no attributes, 2488 * don't polute the DNLC with "." entries or files 2489 * we cannot determine the type for. 2490 */ 2491 if (!(namlen == 1 && dp->d_name[0] == '.') && 2492 va_valid && fh_valid) { 2493 2494 /* 2495 * Do the DNLC caching 2496 */ 2497 nvp = makenfs3node_va(&fh, &va, dvp->v_vfsp, 2498 objp->time, objp->credentials, 2499 rp->r_path, dp->d_name); 2500 dnlc_update(dvp, dp->d_name, nvp); 2501 VN_RELE(nvp); 2502 } 2503 2504 outcount += this_reclen; 2505 dp = (dirent64_t *)((intptr_t)dp + this_reclen); 2506 } 2507 2508 objp->size = outcount; 2509 return (TRUE); 2510 } 2511 2512 bool_t 2513 xdr_FSSTAT3res(XDR *xdrs, FSSTAT3res *objp) 2514 { 2515 FSSTAT3resok *resokp; 2516 2517 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 2518 return (FALSE); 2519 if (objp->status != NFS3_OK) 2520 return (xdr_post_op_attr(xdrs, &objp->resfail.obj_attributes)); 2521 2522 /* xdr_FSSTAT3resok */ 2523 resokp = &objp->resok; 2524 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes)) 2525 return (FALSE); 2526 if (!xdr_u_longlong_t(xdrs, &resokp->tbytes)) 2527 return (FALSE); 2528 if (!xdr_u_longlong_t(xdrs, &resokp->fbytes)) 2529 return (FALSE); 2530 if (!xdr_u_longlong_t(xdrs, &resokp->abytes)) 2531 return (FALSE); 2532 if (!xdr_u_longlong_t(xdrs, &resokp->tfiles)) 2533 return (FALSE); 2534 if (!xdr_u_longlong_t(xdrs, &resokp->ffiles)) 2535 return (FALSE); 2536 if (!xdr_u_longlong_t(xdrs, &resokp->afiles)) 2537 return (FALSE); 2538 return (xdr_u_int(xdrs, &resokp->invarsec)); 2539 } 2540 2541 bool_t 2542 xdr_FSINFO3res(XDR *xdrs, FSINFO3res *objp) 2543 { 2544 FSINFO3resok *resokp; 2545 2546 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 2547 return (FALSE); 2548 if (objp->status != NFS3_OK) /* xdr_FSSTAT3resfail */ 2549 return (xdr_post_op_attr(xdrs, &objp->resfail.obj_attributes)); 2550 2551 /* xdr_FSINFO3resok */ 2552 resokp = &objp->resok; 2553 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes)) 2554 return (FALSE); 2555 if (!xdr_u_int(xdrs, &resokp->rtmax)) 2556 return (FALSE); 2557 if (!xdr_u_int(xdrs, &resokp->rtpref)) 2558 return (FALSE); 2559 if (!xdr_u_int(xdrs, &resokp->rtmult)) 2560 return (FALSE); 2561 if (!xdr_u_int(xdrs, &resokp->wtmax)) 2562 return (FALSE); 2563 if (!xdr_u_int(xdrs, &resokp->wtpref)) 2564 return (FALSE); 2565 if (!xdr_u_int(xdrs, &resokp->wtmult)) 2566 return (FALSE); 2567 if (!xdr_u_int(xdrs, &resokp->dtpref)) 2568 return (FALSE); 2569 if (!xdr_u_longlong_t(xdrs, &resokp->maxfilesize)) 2570 return (FALSE); 2571 if (!xdr_u_int(xdrs, &resokp->time_delta.seconds)) 2572 return (FALSE); 2573 if (!xdr_u_int(xdrs, &resokp->time_delta.nseconds)) 2574 return (FALSE); 2575 return (xdr_u_int(xdrs, &resokp->properties)); 2576 } 2577 2578 bool_t 2579 xdr_PATHCONF3res(XDR *xdrs, PATHCONF3res *objp) 2580 { 2581 PATHCONF3resok *resokp; 2582 2583 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 2584 return (FALSE); 2585 if (objp->status != NFS3_OK) 2586 return (xdr_post_op_attr(xdrs, &objp->resfail.obj_attributes)); 2587 2588 /* xdr_PATHCONF3resok */ 2589 resokp = &objp->resok; 2590 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes)) 2591 return (FALSE); 2592 if (!xdr_u_int(xdrs, &resokp->info.link_max)) 2593 return (FALSE); 2594 if (!xdr_u_int(xdrs, &resokp->info.name_max)) 2595 return (FALSE); 2596 if (!xdr_bool(xdrs, &resokp->info.no_trunc)) 2597 return (FALSE); 2598 if (!xdr_bool(xdrs, &resokp->info.chown_restricted)) 2599 return (FALSE); 2600 if (!xdr_bool(xdrs, &resokp->info.case_insensitive)) 2601 return (FALSE); 2602 return (xdr_bool(xdrs, &resokp->info.case_preserving)); 2603 } 2604 2605 bool_t 2606 xdr_COMMIT3args(XDR *xdrs, COMMIT3args *objp) 2607 { 2608 if (xdrs->x_op == XDR_FREE) 2609 return (TRUE); 2610 2611 switch (xdrs->x_op) { 2612 case XDR_FREE: 2613 case XDR_ENCODE: 2614 if (!xdr_nfs_fh3(xdrs, &objp->file)) 2615 return (FALSE); 2616 break; 2617 case XDR_DECODE: 2618 if (!xdr_nfs_fh3_server(xdrs, &objp->file)) 2619 return (FALSE); 2620 break; 2621 } 2622 if (!xdr_u_longlong_t(xdrs, &objp->offset)) 2623 return (FALSE); 2624 return (xdr_u_int(xdrs, &objp->count)); 2625 } 2626 2627 bool_t 2628 xdr_COMMIT3res(XDR *xdrs, COMMIT3res *objp) 2629 { 2630 COMMIT3resok *resokp; 2631 2632 if (!xdr_enum(xdrs, (enum_t *)&objp->status)) 2633 return (FALSE); 2634 if (objp->status != NFS3_OK) 2635 return (xdr_wcc_data(xdrs, &objp->resfail.file_wcc)); 2636 2637 /* xdr_COMMIT3resok */ 2638 resokp = &objp->resok; 2639 if (!xdr_wcc_data(xdrs, &resokp->file_wcc)) 2640 return (FALSE); 2641 /* 2642 * writeverf3 is really an opaque 8 byte 2643 * quantity, but we will treat it as a 2644 * hyper for efficiency, the cost of 2645 * a byteswap here saves bcopys elsewhere 2646 */ 2647 return (xdr_u_longlong_t(xdrs, &resokp->verf)); 2648 } 2649