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 /* 23 * Copyright 2016 Nexenta Systems, Inc. All rights reserved. 24 * Copyright 2020 RackTop Systems, Inc. 25 */ 26 27 /* 28 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 29 * Use is subject to license terms. 30 */ 31 /* 32 * Copyright (c) 2013 by Delphix. All rights reserved. 33 */ 34 35 /* 36 * A handcoded version based on the original rpcgen code. 37 * 38 * Note: All future NFS4 protocol changes should be added by hand 39 * to this file. 40 * 41 * CAUTION: All protocol changes must also be propagated to: 42 * usr/src/cmd/cmd-inet/usr.sbin/snoop/nfs4_xdr.c 43 */ 44 45 #include <sys/types.h> 46 #include <sys/sunddi.h> 47 #include <sys/dnlc.h> 48 #include <nfs/nfs.h> 49 #include <nfs/nfs4_kprot.h> 50 #include <nfs/rnode4.h> 51 #include <nfs/nfs4.h> 52 #include <nfs/nfs4_clnt.h> 53 #include <sys/sdt.h> 54 #include <sys/mkdev.h> 55 #include <rpc/rpc_rdma.h> 56 #include <rpc/xdr.h> 57 58 #define xdr_dev_t xdr_u_int 59 60 extern bool_t xdr_netbuf(XDR *, struct netbuf *); 61 extern bool_t xdr_vector(XDR *, char *, const uint_t, const uint_t, 62 const xdrproc_t); 63 bool_t xdr_knetconfig(XDR *, struct knetconfig *); 64 65 bool_t 66 xdr_bitmap4(XDR *xdrs, bitmap4 *objp) 67 { 68 int32_t len, size; 69 uint32_t bmval2 = 0; 70 71 if (xdrs->x_op == XDR_FREE) 72 return (TRUE); 73 74 /* 75 * Simplified bitmap4 processing, always encode from uint64_t 76 * to 2 uint32_t's, always decode first 2 uint32_t's into a 77 * uint64_t and ignore all of the rest. 78 * 79 * uint64_t was enough for NFSv4.0, but NFSv4.1 uses extra bits and 80 * uses more than 64-bit. NFSv4.1 attribute FATTR4_SUPPATTR_EXCLCREAT 81 * is 75-th bit. 82 * 83 * In order to not change all code that uses bitmap4, I decided to 84 * use fold/unfold approach - to use rest of free (currently unused) 85 * bits in bitmap4. Until this change bitmap4 was used to keep 0-55 86 * bits : 87 * FATTR4_SUPPORTED_ATTRS_MASK (1ULL << (FATTR4_WORD0 + 0)) 88 * ... 89 * FATTR4_MOUNTED_ON_FILEID_MASK (1ULL << (FATTR4_WORD1 + 23)) 90 * And And 56-th bit is used to fold/unfold. 91 * FATTR4_SUPPATTR_EXCLCREAT_MASK_LOCAL 92 * (1ULL << (FATTR4_WORD1 + 24)) 93 * 94 * FATTR4_SUPPATTR_EXCLCREAT_MASK_LOCAL doesn't affect anything 95 * outside nfssrv. So this usage is purely optimisation. 96 */ 97 if (xdrs->x_op == XDR_ENCODE) { 98 bitmap4 obj = *objp; 99 100 objp = &obj; 101 if (*objp & FATTR4_SUPPATTR_EXCLCREAT_MASK_LOCAL) { 102 bmval2 |= 1ULL << (FATTR4_SUPPATTR_EXCLCREAT - 64); 103 *objp &= ~FATTR4_SUPPATTR_EXCLCREAT_MASK_LOCAL; 104 } 105 106 len = bmval2 ? 3 : 2; 107 108 if (!XDR_PUTINT32(xdrs, &len)) 109 return (FALSE); 110 111 #if defined(_LITTLE_ENDIAN) 112 if (XDR_PUTINT32(xdrs, (int32_t *)((char *)objp + 113 BYTES_PER_XDR_UNIT)) == TRUE) { 114 if (!XDR_PUTINT32(xdrs, (int32_t *)objp)) 115 return (FALSE); 116 } 117 #elif defined(_BIG_ENDIAN) 118 if (XDR_PUTINT32(xdrs, (int32_t *)objp) == TRUE) { 119 if (!XDR_PUTINT32(xdrs, (int32_t *)((char *)objp + 120 BYTES_PER_XDR_UNIT))) 121 return (FALSE); 122 } 123 #endif 124 if (len == 3 && !XDR_PUTINT32(xdrs, (int32_t *)&bmval2)) 125 return (FALSE); 126 return (TRUE); 127 } 128 129 if (!XDR_GETINT32(xdrs, &len)) 130 return (FALSE); 131 132 /* 133 * Common fast DECODE cases 134 */ 135 if (len == 2 || len == 3) { 136 #if defined(_LITTLE_ENDIAN) 137 if (XDR_GETINT32(xdrs, (int32_t *)((char *)objp + 138 BYTES_PER_XDR_UNIT)) == TRUE) { 139 if (!XDR_GETINT32(xdrs, (int32_t *)objp)) 140 return (FALSE); 141 } 142 #elif defined(_BIG_ENDIAN) 143 if (XDR_GETINT32(xdrs, (int32_t *)objp) == TRUE) { 144 if (!XDR_GETINT32(xdrs, (int32_t *)((char *)objp + 145 BYTES_PER_XDR_UNIT))) 146 return (FALSE); 147 } 148 #endif 149 if (len == 3) { 150 if (!XDR_GETINT32(xdrs, (int32_t *)&bmval2)) 151 return (FALSE); 152 if (bmval2 & (1ULL << (FATTR4_SUPPATTR_EXCLCREAT - 64))) 153 *objp |= FATTR4_SUPPATTR_EXCLCREAT_MASK_LOCAL; 154 } 155 156 return (TRUE); 157 } 158 159 *objp = 0; 160 if (len == 0) 161 return (TRUE); 162 163 /* 164 * The not so common DECODE cases, len == 1 || len > 2 165 */ 166 #if defined(_LITTLE_ENDIAN) 167 if (!XDR_GETINT32(xdrs, (int32_t *)((char *)objp + BYTES_PER_XDR_UNIT))) 168 return (FALSE); 169 if (--len == 0) 170 return (TRUE); 171 if (!XDR_GETINT32(xdrs, (int32_t *)objp)) 172 return (FALSE); 173 #elif defined(_BIG_ENDIAN) 174 if (!XDR_GETINT32(xdrs, (int32_t *)objp)) 175 return (FALSE); 176 if (--len == 0) 177 return (TRUE); 178 179 if (!XDR_GETINT32(xdrs, (int32_t *)&bmval2)) 180 return (FALSE); 181 if (bmval2 & (1ULL << (FATTR4_SUPPATTR_EXCLCREAT - 64))) 182 *objp |= FATTR4_SUPPATTR_EXCLCREAT_MASK_LOCAL; 183 184 if (!XDR_GETINT32(xdrs, (int32_t *)((char *)objp + BYTES_PER_XDR_UNIT))) 185 return (FALSE); 186 #else 187 return (FALSE); 188 #endif 189 190 if (--len == 0) 191 return (TRUE); 192 193 size = len * BYTES_PER_XDR_UNIT; 194 return (XDR_CONTROL(xdrs, XDR_SKIPBYTES, &size)); 195 } 196 197 /* Called by xdr_array, nfsid_map_xdr */ 198 bool_t 199 xdr_utf8string(XDR *xdrs, utf8string *objp) 200 { 201 if (xdrs->x_op != XDR_FREE) 202 return (xdr_bytes(xdrs, (char **)&objp->utf8string_val, 203 (uint_t *)&objp->utf8string_len, NFS4_MAX_UTF8STRING)); 204 205 if (objp->utf8string_val != NULL) { 206 kmem_free(objp->utf8string_val, objp->utf8string_len); 207 objp->utf8string_val = NULL; 208 } 209 return (TRUE); 210 } 211 212 /* 213 * used by NFSv4 referrals to get info needed for NFSv4 referral mount. 214 */ 215 bool_t 216 xdr_nfs_fsl_info(XDR *xdrs, struct nfs_fsl_info *objp) 217 { 218 219 if (!xdr_u_int(xdrs, &objp->netbuf_len)) 220 return (FALSE); 221 if (!xdr_u_int(xdrs, &objp->netnm_len)) 222 return (FALSE); 223 if (!xdr_u_int(xdrs, &objp->knconf_len)) 224 return (FALSE); 225 226 #if defined(_LP64) 227 /* 228 * The object can come from a 32-bit binary; nfsmapid. 229 * To be safe we double the size of the knetconfig to 230 * allow some buffering for decoding. 231 */ 232 if (xdrs->x_op == XDR_DECODE) 233 objp->knconf_len += sizeof (struct knetconfig); 234 #endif 235 236 if (!xdr_string(xdrs, &objp->netname, ~0)) 237 return (FALSE); 238 if (!xdr_pointer(xdrs, (char **)&objp->addr, objp->netbuf_len, 239 (xdrproc_t)xdr_netbuf)) 240 return (FALSE); 241 if (!xdr_pointer(xdrs, (char **)&objp->knconf, 242 objp->knconf_len, (xdrproc_t)xdr_knetconfig)) 243 return (FALSE); 244 return (TRUE); 245 } 246 247 bool_t 248 xdr_knetconfig(XDR *xdrs, struct knetconfig *objp) 249 { 250 rpc_inline_t *buf; 251 u_longlong_t dev64; 252 #if !defined(_LP64) 253 uint32_t major, minor; 254 #endif 255 int i; 256 257 if (!xdr_u_int(xdrs, &objp->knc_semantics)) 258 return (FALSE); 259 if (xdrs->x_op == XDR_DECODE) { 260 objp->knc_protofmly = (((char *)objp) + 261 sizeof (struct knetconfig)); 262 objp->knc_proto = objp->knc_protofmly + KNC_STRSIZE; 263 } 264 if (!xdr_opaque(xdrs, objp->knc_protofmly, KNC_STRSIZE)) 265 return (FALSE); 266 if (!xdr_opaque(xdrs, objp->knc_proto, KNC_STRSIZE)) 267 return (FALSE); 268 269 /* 270 * For interoperability between 32-bit daemon and 64-bit kernel, 271 * we always treat dev_t as 64-bit number and do the expanding 272 * or compression of dev_t as needed. 273 * We have to hand craft the conversion since there is no available 274 * function in ddi.c. Besides ddi.c is available only in the kernel 275 * and we want to keep both user and kernel of xdr_knetconfig() the 276 * same for consistency. 277 */ 278 if (xdrs->x_op == XDR_ENCODE) { 279 #if defined(_LP64) 280 dev64 = objp->knc_rdev; 281 #else 282 major = (objp->knc_rdev >> NBITSMINOR32) & MAXMAJ32; 283 minor = objp->knc_rdev & MAXMIN32; 284 dev64 = (((unsigned long long)major) << NBITSMINOR64) | minor; 285 #endif 286 if (!xdr_u_longlong_t(xdrs, &dev64)) 287 return (FALSE); 288 } 289 if (xdrs->x_op == XDR_DECODE) { 290 #if defined(_LP64) 291 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->knc_rdev)) 292 return (FALSE); 293 #else 294 if (!xdr_u_longlong_t(xdrs, &dev64)) 295 return (FALSE); 296 297 major = (dev64 >> NBITSMINOR64) & L_MAXMAJ32; 298 minor = dev64 & L_MAXMIN32; 299 objp->knc_rdev = (major << L_BITSMINOR32) | minor; 300 #endif 301 } 302 303 if (xdrs->x_op == XDR_ENCODE) { 304 buf = XDR_INLINE(xdrs, (8) * BYTES_PER_XDR_UNIT); 305 if (buf == NULL) { 306 if (!xdr_vector(xdrs, (char *)objp->knc_unused, 8, 307 sizeof (uint_t), (xdrproc_t)xdr_u_int)) 308 return (FALSE); 309 } else { 310 uint_t *genp; 311 312 for (i = 0, genp = objp->knc_unused; 313 i < 8; i++) { 314 #if defined(_LP64) || defined(_KERNEL) 315 IXDR_PUT_U_INT32(buf, *genp++); 316 #else 317 IXDR_PUT_U_LONG(buf, *genp++); 318 #endif 319 } 320 } 321 return (TRUE); 322 } else if (xdrs->x_op == XDR_DECODE) { 323 buf = XDR_INLINE(xdrs, (8) * BYTES_PER_XDR_UNIT); 324 if (buf == NULL) { 325 if (!xdr_vector(xdrs, (char *)objp->knc_unused, 8, 326 sizeof (uint_t), (xdrproc_t)xdr_u_int)) 327 return (FALSE); 328 } else { 329 uint_t *genp; 330 331 for (i = 0, genp = objp->knc_unused; 332 i < 8; i++) { 333 #if defined(_LP64) || defined(_KERNEL) 334 *genp++ = IXDR_GET_U_INT32(buf); 335 #else 336 *genp++ = IXDR_GET_U_LONG(buf); 337 #endif 338 } 339 } 340 return (TRUE); 341 } 342 343 if (!xdr_vector(xdrs, (char *)objp->knc_unused, 8, 344 sizeof (uint_t), (xdrproc_t)xdr_u_int)) 345 return (FALSE); 346 return (TRUE); 347 } 348 349 /* 350 * XDR_INLINE decode a filehandle. 351 */ 352 bool_t 353 xdr_inline_decode_nfs_fh4(uint32_t *ptr, nfs_fh4_fmt_t *fhp, uint32_t fhsize) 354 { 355 uchar_t *bp = (uchar_t *)ptr; 356 uchar_t *cp; 357 uint32_t dsize; 358 uintptr_t resid; 359 360 /* 361 * Check to see if what the client sent us is bigger or smaller 362 * than what we can ever possibly send out. NFS_FHMAXDATA is 363 * unfortunately badly named as it is no longer the max and is 364 * really the min of what is sent over the wire. 365 */ 366 if (fhsize > sizeof (nfs_fh4_fmt_t) || fhsize < (sizeof (fsid_t) + 367 sizeof (ushort_t) + NFS_FHMAXDATA + 368 sizeof (ushort_t) + NFS_FHMAXDATA)) { 369 return (FALSE); 370 } 371 372 /* 373 * All internal parts of a filehandle are in native byte order. 374 * 375 * Decode what should be fh4_fsid, it is aligned. 376 */ 377 fhp->fh4_fsid.val[0] = *(uint32_t *)bp; 378 bp += BYTES_PER_XDR_UNIT; 379 fhp->fh4_fsid.val[1] = *(uint32_t *)bp; 380 bp += BYTES_PER_XDR_UNIT; 381 382 /* 383 * Decode what should be fh4_len. fh4_len is two bytes, so we're 384 * unaligned now. 385 */ 386 cp = (uchar_t *)&fhp->fh4_len; 387 *cp++ = *bp++; 388 *cp++ = *bp++; 389 fhsize -= 2 * BYTES_PER_XDR_UNIT + sizeof (ushort_t); 390 391 /* 392 * For backwards compatibility, the fid length may be less than 393 * NFS_FHMAXDATA, but it was always encoded as NFS_FHMAXDATA bytes. 394 */ 395 dsize = fhp->fh4_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_len; 396 397 /* 398 * Make sure the client isn't sending us a bogus length for fh4_data. 399 */ 400 if (fhsize < dsize) 401 return (FALSE); 402 bcopy(bp, fhp->fh4_data, dsize); 403 bp += dsize; 404 fhsize -= dsize; 405 406 if (fhsize < sizeof (ushort_t)) 407 return (FALSE); 408 cp = (uchar_t *)&fhp->fh4_xlen; 409 *cp++ = *bp++; 410 *cp++ = *bp++; 411 fhsize -= sizeof (ushort_t); 412 413 dsize = fhp->fh4_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_xlen; 414 415 /* 416 * Make sure the client isn't sending us a bogus length for fh4_xdata. 417 */ 418 if (fhsize < dsize) 419 return (FALSE); 420 bcopy(bp, fhp->fh4_xdata, dsize); 421 fhsize -= dsize; 422 bp += dsize; 423 424 /* 425 * We realign things on purpose, so skip any padding 426 */ 427 resid = (uintptr_t)bp % BYTES_PER_XDR_UNIT; 428 if (resid != 0) { 429 if (fhsize < (BYTES_PER_XDR_UNIT - resid)) 430 return (FALSE); 431 bp += BYTES_PER_XDR_UNIT - resid; 432 fhsize -= BYTES_PER_XDR_UNIT - resid; 433 } 434 435 if (fhsize < BYTES_PER_XDR_UNIT) 436 return (FALSE); 437 fhp->fh4_flag = *(uint32_t *)bp; 438 bp += BYTES_PER_XDR_UNIT; 439 fhsize -= BYTES_PER_XDR_UNIT; 440 441 #ifdef VOLATILE_FH_TEST 442 if (fhsize < BYTES_PER_XDR_UNIT) 443 return (FALSE); 444 fhp->fh4_volatile_id = *(uint32_t *)bp; 445 bp += BYTES_PER_XDR_UNIT; 446 fhsize -= BYTES_PER_XDR_UNIT; 447 #endif 448 /* 449 * Make sure client didn't send extra bytes 450 */ 451 if (fhsize != 0) 452 return (FALSE); 453 return (TRUE); 454 } 455 456 static bool_t 457 xdr_decode_nfs_fh4(XDR *xdrs, nfs_fh4 *objp) 458 { 459 uint32_t fhsize; /* filehandle size */ 460 uint32_t bufsize; 461 rpc_inline_t *ptr; 462 uchar_t *bp; 463 464 ASSERT(xdrs->x_op == XDR_DECODE); 465 466 /* 467 * Retrieve the filehandle length. 468 */ 469 if (!XDR_GETINT32(xdrs, (int32_t *)&fhsize)) 470 return (FALSE); 471 472 objp->nfs_fh4_val = NULL; 473 objp->nfs_fh4_len = 0; 474 475 /* 476 * Check to see if what the client sent us is bigger or smaller 477 * than what we can ever possibly send out. NFS_FHMAXDATA is 478 * unfortunately badly named as it is no longer the max and is 479 * really the min of what is sent over the wire. 480 */ 481 if (fhsize > sizeof (nfs_fh4_fmt_t) || fhsize < (sizeof (fsid_t) + 482 sizeof (ushort_t) + NFS_FHMAXDATA + 483 sizeof (ushort_t) + NFS_FHMAXDATA)) { 484 if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &fhsize)) 485 return (FALSE); 486 return (TRUE); 487 } 488 489 /* 490 * bring in fhsize plus any padding 491 */ 492 bufsize = RNDUP(fhsize); 493 ptr = XDR_INLINE(xdrs, bufsize); 494 bp = (uchar_t *)ptr; 495 if (ptr == NULL) { 496 bp = kmem_alloc(bufsize, KM_SLEEP); 497 if (!xdr_opaque(xdrs, (char *)bp, bufsize)) { 498 kmem_free(bp, bufsize); 499 return (FALSE); 500 } 501 } 502 503 objp->nfs_fh4_val = kmem_zalloc(sizeof (nfs_fh4_fmt_t), KM_SLEEP); 504 objp->nfs_fh4_len = sizeof (nfs_fh4_fmt_t); 505 506 if (xdr_inline_decode_nfs_fh4((uint32_t *)bp, 507 (nfs_fh4_fmt_t *)objp->nfs_fh4_val, fhsize) == FALSE) { 508 /* 509 * If in the process of decoding we find the file handle 510 * is not correctly formed, we need to continue decoding 511 * and trigger an NFS layer error. Set the nfs_fh4_len to 512 * zero so it gets caught as a bad length. 513 */ 514 kmem_free(objp->nfs_fh4_val, objp->nfs_fh4_len); 515 objp->nfs_fh4_val = NULL; 516 objp->nfs_fh4_len = 0; 517 } 518 519 if (ptr == NULL) 520 kmem_free(bp, bufsize); 521 return (TRUE); 522 } 523 524 /* 525 * XDR_INLINE encode a filehandle. 526 */ 527 bool_t 528 xdr_inline_encode_nfs_fh4(uint32_t **ptrp, uint32_t *ptr_redzone, 529 nfs_fh4_fmt_t *fhp) 530 { 531 uint32_t *ptr = *ptrp; 532 uchar_t *cp; 533 uint_t otw_len, fsize, xsize; /* otw, file, and export sizes */ 534 uint32_t padword; 535 536 fsize = fhp->fh4_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_len; 537 xsize = fhp->fh4_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_xlen; 538 539 /* 540 * First get the initial and variable sized part of the filehandle. 541 */ 542 otw_len = sizeof (fhp->fh4_fsid) + 543 sizeof (fhp->fh4_len) + fsize + 544 sizeof (fhp->fh4_xlen) + xsize; 545 546 /* 547 * Round out to a full word. 548 */ 549 otw_len = RNDUP(otw_len); 550 padword = (otw_len / BYTES_PER_XDR_UNIT); /* includes fhlen */ 551 552 /* 553 * Add in the fixed sized pieces. 554 */ 555 otw_len += sizeof (fhp->fh4_flag); 556 #ifdef VOLATILE_FH_TEST 557 otw_len += sizeof (fhp->fh4_volatile_id); 558 #endif 559 560 /* 561 * Make sure we don't exceed our buffer. 562 */ 563 if ((ptr + (otw_len / BYTES_PER_XDR_UNIT) + 1) > ptr_redzone) 564 return (FALSE); 565 566 /* 567 * Zero out the padding. 568 */ 569 ptr[padword] = 0; 570 571 IXDR_PUT_U_INT32(ptr, otw_len); 572 573 /* 574 * The rest of the filehandle is in native byteorder 575 */ 576 /* fh4_fsid */ 577 *ptr++ = (uint32_t)fhp->fh4_fsid.val[0]; 578 *ptr++ = (uint32_t)fhp->fh4_fsid.val[1]; 579 580 /* 581 * Since the next pieces are unaligned, we need to 582 * do bytewise copies. 583 */ 584 cp = (uchar_t *)ptr; 585 586 /* fh4_len + fh4_data */ 587 bcopy(&fhp->fh4_len, cp, sizeof (fhp->fh4_len) + fsize); 588 cp += sizeof (fhp->fh4_len) + fsize; 589 590 /* fh4_xlen + fh4_xdata */ 591 bcopy(&fhp->fh4_xlen, cp, sizeof (fhp->fh4_xlen) + xsize); 592 cp += sizeof (fhp->fh4_xlen) + xsize; 593 594 /* do necessary rounding/padding */ 595 cp = (uchar_t *)RNDUP((uintptr_t)cp); 596 ptr = (uint32_t *)cp; 597 598 /* 599 * With the above padding, we're word aligned again. 600 */ 601 ASSERT(((uintptr_t)ptr % BYTES_PER_XDR_UNIT) == 0); 602 603 /* fh4_flag */ 604 *ptr++ = (uint32_t)fhp->fh4_flag; 605 606 #ifdef VOLATILE_FH_TEST 607 /* fh4_volatile_id */ 608 *ptr++ = (uint32_t)fhp->fh4_volatile_id; 609 #endif 610 *ptrp = ptr; 611 612 return (TRUE); 613 } 614 615 static bool_t 616 xdr_encode_nfs_fh4(XDR *xdrs, nfs_fh4 *objp) 617 { 618 uint_t otw_len, fsize, xsize; /* otw, file, and export sizes */ 619 bool_t ret; 620 rpc_inline_t *ptr; 621 rpc_inline_t *buf = NULL; 622 uint32_t *ptr_redzone; 623 nfs_fh4_fmt_t *fhp; 624 625 ASSERT(xdrs->x_op == XDR_ENCODE); 626 627 fhp = (nfs_fh4_fmt_t *)objp->nfs_fh4_val; 628 fsize = fhp->fh4_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_len; 629 xsize = fhp->fh4_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_xlen; 630 631 /* 632 * First get the over the wire size, it is the 4 bytes 633 * for the length, plus the combined size of the 634 * file handle components. 635 */ 636 otw_len = BYTES_PER_XDR_UNIT + sizeof (fhp->fh4_fsid) + 637 sizeof (fhp->fh4_len) + fsize + 638 sizeof (fhp->fh4_xlen) + xsize + 639 sizeof (fhp->fh4_flag); 640 #ifdef VOLATILE_FH_TEST 641 otw_len += sizeof (fhp->fh4_volatile_id); 642 #endif 643 /* 644 * Round out to a full word. 645 */ 646 otw_len = RNDUP(otw_len); 647 648 /* 649 * Next try to inline the XDR stream, if that fails (rare) 650 * allocate a buffer to encode the file handle and then 651 * copy it using xdr_opaque and free the buffer. 652 */ 653 ptr = XDR_INLINE(xdrs, otw_len); 654 if (ptr == NULL) 655 ptr = buf = kmem_alloc(otw_len, KM_SLEEP); 656 657 ptr_redzone = (uint32_t *)(ptr + (otw_len / BYTES_PER_XDR_UNIT)); 658 ret = xdr_inline_encode_nfs_fh4((uint32_t **)&ptr, ptr_redzone, fhp); 659 660 if (buf != NULL) { 661 if (ret == TRUE) 662 ret = xdr_opaque(xdrs, (char *)buf, otw_len); 663 kmem_free(buf, otw_len); 664 } 665 return (ret); 666 } 667 668 /* 669 * XDR a NFSv4 filehandle. 670 * Encoding interprets the contents (server). 671 * Decoding the contents are opaque (client). 672 */ 673 bool_t 674 xdr_nfs_fh4(XDR *xdrs, nfs_fh4 *objp) 675 { 676 switch (xdrs->x_op) { 677 case XDR_ENCODE: 678 return (xdr_encode_nfs_fh4(xdrs, objp)); 679 case XDR_DECODE: 680 return (xdr_bytes(xdrs, (char **)&objp->nfs_fh4_val, 681 (uint_t *)&objp->nfs_fh4_len, NFS4_FHSIZE)); 682 case XDR_FREE: 683 if (objp->nfs_fh4_val != NULL) { 684 kmem_free(objp->nfs_fh4_val, objp->nfs_fh4_len); 685 objp->nfs_fh4_val = NULL; 686 } 687 return (TRUE); 688 } 689 return (FALSE); 690 } 691 692 /* Called by xdr_array */ 693 static bool_t 694 xdr_fs_location4(XDR *xdrs, fs_location4 *objp) 695 { 696 if (xdrs->x_op == XDR_DECODE) { 697 objp->server_val = NULL; 698 objp->rootpath.pathname4_val = NULL; 699 } 700 if (!xdr_array(xdrs, (char **)&objp->server_val, 701 (uint_t *)&objp->server_len, NFS4_MAX_UTF8STRING, 702 sizeof (utf8string), (xdrproc_t)xdr_utf8string)) 703 return (FALSE); 704 return (xdr_array(xdrs, (char **)&objp->rootpath.pathname4_val, 705 (uint_t *)&objp->rootpath.pathname4_len, 706 NFS4_MAX_PATHNAME4, 707 sizeof (utf8string), (xdrproc_t)xdr_utf8string)); 708 } 709 710 /* Called by xdr_array */ 711 bool_t 712 xdr_nfsace4(XDR *xdrs, nfsace4 *objp) 713 { 714 if (xdrs->x_op != XDR_FREE) { 715 if (!xdr_u_int(xdrs, &objp->type)) 716 return (FALSE); 717 if (!xdr_u_int(xdrs, &objp->flag)) 718 return (FALSE); 719 if (!xdr_u_int(xdrs, &objp->access_mask)) 720 return (FALSE); 721 722 if (xdrs->x_op == XDR_DECODE) { 723 objp->who.utf8string_val = NULL; 724 objp->who.utf8string_len = 0; 725 } 726 727 return (xdr_bytes(xdrs, (char **)&objp->who.utf8string_val, 728 (uint_t *)&objp->who.utf8string_len, 729 NFS4_MAX_UTF8STRING)); 730 } 731 732 /* 733 * Optimized free case 734 */ 735 if (objp->who.utf8string_val != NULL) { 736 kmem_free(objp->who.utf8string_val, objp->who.utf8string_len); 737 objp->who.utf8string_val = NULL; 738 } 739 return (TRUE); 740 } 741 742 /* 743 * These functions are called out of nfs4_attr.c 744 */ 745 bool_t 746 xdr_fattr4_fsid(XDR *xdrs, fattr4_fsid *objp) 747 { 748 if (xdrs->x_op == XDR_FREE) 749 return (TRUE); 750 751 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->major)) 752 return (FALSE); 753 return (xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->minor)); 754 } 755 756 757 bool_t 758 xdr_fattr4_acl(XDR *xdrs, fattr4_acl *objp) 759 { 760 return (xdr_array(xdrs, (char **)&objp->fattr4_acl_val, 761 (uint_t *)&objp->fattr4_acl_len, NFS4_ACL_LIMIT, 762 sizeof (nfsace4), (xdrproc_t)xdr_nfsace4)); 763 } 764 765 bool_t 766 xdr_fattr4_fs_locations(XDR *xdrs, fattr4_fs_locations *objp) 767 { 768 if (xdrs->x_op == XDR_DECODE) { 769 objp->fs_root.pathname4_len = 0; 770 objp->fs_root.pathname4_val = NULL; 771 objp->locations_val = NULL; 772 } 773 if (!xdr_array(xdrs, (char **)&objp->fs_root.pathname4_val, 774 (uint_t *)&objp->fs_root.pathname4_len, 775 NFS4_MAX_PATHNAME4, 776 sizeof (utf8string), (xdrproc_t)xdr_utf8string)) 777 return (FALSE); 778 return (xdr_array(xdrs, (char **)&objp->locations_val, 779 (uint_t *)&objp->locations_len, NFS4_FS_LOCATIONS_LIMIT, 780 sizeof (fs_location4), (xdrproc_t)xdr_fs_location4)); 781 } 782 783 bool_t 784 xdr_fattr4_rawdev(XDR *xdrs, fattr4_rawdev *objp) 785 { 786 if (xdrs->x_op == XDR_FREE) 787 return (TRUE); 788 789 if (!xdr_u_int(xdrs, &objp->specdata1)) 790 return (FALSE); 791 return (xdr_u_int(xdrs, &objp->specdata2)); 792 } 793 794 bool_t 795 xdr_nfstime4(XDR *xdrs, nfstime4 *objp) 796 { 797 if (xdrs->x_op == XDR_FREE) 798 return (TRUE); 799 800 if (!xdr_longlong_t(xdrs, (longlong_t *)&objp->seconds)) 801 return (FALSE); 802 return (xdr_u_int(xdrs, &objp->nseconds)); 803 } 804 805 bool_t 806 xdr_fattr4_sec_label(XDR *xdrs, fattr4_sec_label *objp) 807 { 808 uint_t dummy = 0; 809 810 if (xdrs->x_op == XDR_FREE) { 811 /* 812 * Optimized free case 813 */ 814 if (objp->slai_val != NULL) 815 kmem_free(objp->slai_val, objp->slai_len); 816 return (TRUE); 817 } 818 819 /* 820 * For now use a 0 here to indicate the null translation; in 821 * the future we place a call to translation code here. 822 */ 823 if (!xdr_u_int(xdrs, &dummy)) /* lfs */ 824 return (FALSE); 825 826 if (!xdr_u_int(xdrs, &dummy)) /* pi */ 827 return (FALSE); 828 829 return (xdr_bytes(xdrs, (char **)&objp->slai_val, 830 (uint_t *)&objp->slai_len, NFS4_OPAQUE_LIMIT)); 831 } 832 833 /* 834 * structured used for calls into xdr_ga_fattr_res() as a means 835 * to do an immediate/short-term cache of owner/group strings 836 * for callers like the readdir processing. In the case of readdir, 837 * it is likely that the directory objects will be owned by the same 838 * owner/group and if so there is no need to call into the uid/gid 839 * mapping code. While the uid/gid interfaces have their own cache 840 * having one here will reduct pathlength further. 841 */ 842 #define MAX_OG_NAME 100 843 typedef struct ug_cache 844 { 845 uid_t uid; 846 gid_t gid; 847 utf8string u_curr, u_last; 848 utf8string g_curr, g_last; 849 char u_buf1[MAX_OG_NAME]; 850 char u_buf2[MAX_OG_NAME]; 851 char g_buf1[MAX_OG_NAME]; 852 char g_buf2[MAX_OG_NAME]; 853 } ug_cache_t; 854 855 #define U_SWAP_CURR_LAST(ug) \ 856 (ug)->u_last.utf8string_len = (ug)->u_curr.utf8string_len; \ 857 if ((ug)->u_last.utf8string_val == (ug)->u_buf1) { \ 858 (ug)->u_last.utf8string_val = (ug)->u_buf2; \ 859 (ug)->u_curr.utf8string_val = (ug)->u_buf1; \ 860 } else { \ 861 (ug)->u_last.utf8string_val = (ug)->u_buf1; \ 862 (ug)->u_curr.utf8string_val = (ug)->u_buf2; \ 863 } 864 865 #define G_SWAP_CURR_LAST(ug) \ 866 (ug)->g_last.utf8string_len = (ug)->g_curr.utf8string_len; \ 867 if ((ug)->g_last.utf8string_val == (ug)->g_buf1) { \ 868 (ug)->g_last.utf8string_val = (ug)->g_buf2; \ 869 (ug)->g_curr.utf8string_val = (ug)->g_buf1; \ 870 } else { \ 871 (ug)->g_last.utf8string_val = (ug)->g_buf1; \ 872 (ug)->g_curr.utf8string_val = (ug)->g_buf2; \ 873 } 874 875 static ug_cache_t * 876 alloc_ugcache() 877 { 878 ug_cache_t *pug = kmem_alloc(sizeof (ug_cache_t), KM_SLEEP); 879 880 pug->uid = pug->gid = 0; 881 pug->u_curr.utf8string_len = 0; 882 pug->u_last.utf8string_len = 0; 883 pug->g_curr.utf8string_len = 0; 884 pug->g_last.utf8string_len = 0; 885 pug->u_curr.utf8string_val = pug->u_buf1; 886 pug->u_last.utf8string_val = pug->u_buf2; 887 pug->g_curr.utf8string_val = pug->g_buf1; 888 pug->g_last.utf8string_val = pug->g_buf2; 889 890 return (pug); 891 } 892 893 static void 894 xdr_ga_prefill_vattr(struct nfs4_ga_res *garp, struct mntinfo4 *mi) 895 { 896 static vattr_t s_vattr = { 897 AT_ALL, /* va_mask */ 898 VNON, /* va_type */ 899 0777, /* va_mode */ 900 UID_NOBODY, /* va_uid */ 901 GID_NOBODY, /* va_gid */ 902 0, /* va_fsid */ 903 0, /* va_nodeid */ 904 1, /* va_nlink */ 905 0, /* va_size */ 906 {0, 0}, /* va_atime */ 907 {0, 0}, /* va_mtime */ 908 {0, 0}, /* va_ctime */ 909 0, /* va_rdev */ 910 MAXBSIZE, /* va_blksize */ 911 0, /* va_nblocks */ 912 0 /* va_seq */ 913 }; 914 915 916 garp->n4g_va = s_vattr; 917 garp->n4g_va.va_fsid = mi->mi_vfsp->vfs_dev; 918 hrt2ts(gethrtime(), &garp->n4g_va.va_atime); 919 garp->n4g_va.va_mtime = garp->n4g_va.va_ctime = garp->n4g_va.va_atime; 920 } 921 922 static void 923 xdr_ga_prefill_statvfs(struct nfs4_ga_ext_res *gesp, struct mntinfo4 *mi) 924 { 925 static statvfs64_t s_sb = { 926 MAXBSIZE, /* f_bsize */ 927 DEV_BSIZE, /* f_frsize */ 928 (fsfilcnt64_t)-1, /* f_blocks */ 929 (fsfilcnt64_t)-1, /* f_bfree */ 930 (fsfilcnt64_t)-1, /* f_bavail */ 931 (fsfilcnt64_t)-1, /* f_files */ 932 (fsfilcnt64_t)-1, /* f_ffree */ 933 (fsfilcnt64_t)-1, /* f_favail */ 934 0, /* f_fsid */ 935 "\0", /* f_basetype */ 936 0, /* f_flag */ 937 MAXNAMELEN, /* f_namemax */ 938 "\0", /* f_fstr */ 939 }; 940 941 gesp->n4g_sb = s_sb; 942 gesp->n4g_sb.f_fsid = mi->mi_vfsp->vfs_fsid.val[0]; 943 } 944 945 static bool_t 946 xdr_ga_fattr_res(XDR *xdrs, struct nfs4_ga_res *garp, bitmap4 resbmap, 947 bitmap4 argbmap, struct mntinfo4 *mi, ug_cache_t *pug) 948 { 949 int truefalse; 950 struct nfs4_ga_ext_res ges, *gesp; 951 vattr_t *vap = &garp->n4g_va; 952 vsecattr_t *vsap = &garp->n4g_vsa; 953 954 ASSERT(xdrs->x_op == XDR_DECODE); 955 956 if (garp->n4g_ext_res) 957 gesp = garp->n4g_ext_res; 958 else 959 gesp = ⩾ 960 961 vap->va_mask = 0; 962 963 /* Check to see if the vattr should be pre-filled */ 964 if (argbmap & NFS4_VATTR_MASK) 965 xdr_ga_prefill_vattr(garp, mi); 966 967 if (argbmap & NFS4_STATFS_ATTR_MASK) 968 xdr_ga_prefill_statvfs(gesp, mi); 969 970 if (resbmap & 971 (FATTR4_SUPPORTED_ATTRS_MASK | 972 FATTR4_TYPE_MASK | 973 FATTR4_FH_EXPIRE_TYPE_MASK | 974 FATTR4_CHANGE_MASK | 975 FATTR4_SIZE_MASK | 976 FATTR4_LINK_SUPPORT_MASK | 977 FATTR4_SYMLINK_SUPPORT_MASK | 978 FATTR4_NAMED_ATTR_MASK)) { 979 980 if (resbmap & FATTR4_SUPPORTED_ATTRS_MASK) { 981 if (!xdr_bitmap4(xdrs, &gesp->n4g_suppattrs)) 982 return (FALSE); 983 } 984 if (resbmap & FATTR4_TYPE_MASK) { 985 if (!XDR_GETINT32(xdrs, (int *)&vap->va_type)) 986 return (FALSE); 987 988 if ((nfs_ftype4)vap->va_type < NF4REG || 989 (nfs_ftype4)vap->va_type > NF4NAMEDATTR) 990 vap->va_type = VBAD; 991 else 992 vap->va_type = nf4_to_vt[vap->va_type]; 993 if (vap->va_type == VBLK) 994 vap->va_blksize = DEV_BSIZE; 995 996 vap->va_mask |= AT_TYPE; 997 } 998 if (resbmap & FATTR4_FH_EXPIRE_TYPE_MASK) { 999 if (!XDR_GETINT32(xdrs, (int *)&gesp->n4g_fet)) 1000 return (FALSE); 1001 } 1002 if (resbmap & FATTR4_CHANGE_MASK) { 1003 if (!xdr_u_longlong_t(xdrs, 1004 (u_longlong_t *)&garp->n4g_change)) 1005 return (FALSE); 1006 garp->n4g_change_valid = 1; 1007 } 1008 if (resbmap & FATTR4_SIZE_MASK) { 1009 if (!xdr_u_longlong_t(xdrs, 1010 (u_longlong_t *)&vap->va_size)) 1011 return (FALSE); 1012 if (!NFS4_SIZE_OK(vap->va_size)) { 1013 garp->n4g_attrerr = EFBIG; 1014 garp->n4g_attrwhy = NFS4_GETATTR_ATSIZE_ERR; 1015 } else { 1016 vap->va_mask |= AT_SIZE; 1017 } 1018 } 1019 if (resbmap & FATTR4_LINK_SUPPORT_MASK) { 1020 if (!XDR_GETINT32(xdrs, (int *)&truefalse)) 1021 return (FALSE); 1022 gesp->n4g_pc4.pc4_link_support = 1023 (truefalse ? TRUE : FALSE); 1024 } 1025 if (resbmap & FATTR4_SYMLINK_SUPPORT_MASK) { 1026 if (!XDR_GETINT32(xdrs, (int *)&truefalse)) 1027 return (FALSE); 1028 gesp->n4g_pc4.pc4_symlink_support = 1029 (truefalse ? TRUE : FALSE); 1030 } 1031 if (resbmap & FATTR4_NAMED_ATTR_MASK) { 1032 if (!XDR_GETINT32(xdrs, (int *)&truefalse)) 1033 return (FALSE); 1034 gesp->n4g_pc4.pc4_xattr_exists = TRUE; 1035 gesp->n4g_pc4.pc4_xattr_exists = 1036 (truefalse ? TRUE : FALSE); 1037 } 1038 } 1039 if (resbmap & 1040 (FATTR4_FSID_MASK | 1041 FATTR4_UNIQUE_HANDLES_MASK | 1042 FATTR4_LEASE_TIME_MASK | 1043 FATTR4_RDATTR_ERROR_MASK)) { 1044 1045 if (resbmap & FATTR4_FSID_MASK) { 1046 if ((!xdr_u_longlong_t(xdrs, 1047 (u_longlong_t *)&garp->n4g_fsid.major)) || 1048 (!xdr_u_longlong_t(xdrs, 1049 (u_longlong_t *)&garp->n4g_fsid.minor))) 1050 return (FALSE); 1051 garp->n4g_fsid_valid = 1; 1052 } 1053 if (resbmap & FATTR4_UNIQUE_HANDLES_MASK) { 1054 if (!XDR_GETINT32(xdrs, (int *)&truefalse)) 1055 return (FALSE); 1056 gesp->n4g_pc4.pc4_unique_handles = 1057 (truefalse ? TRUE : FALSE); 1058 } 1059 if (resbmap & FATTR4_LEASE_TIME_MASK) { 1060 if (!XDR_GETINT32(xdrs, (int *)&gesp->n4g_leasetime)) 1061 return (FALSE); 1062 } 1063 if (resbmap & FATTR4_RDATTR_ERROR_MASK) { 1064 if (!XDR_GETINT32(xdrs, 1065 (int *)&gesp->n4g_rdattr_error)) 1066 return (FALSE); 1067 } 1068 } 1069 if (resbmap & 1070 (FATTR4_ACL_MASK | 1071 FATTR4_ACLSUPPORT_MASK | 1072 FATTR4_ARCHIVE_MASK | 1073 FATTR4_CANSETTIME_MASK)) { 1074 1075 if (resbmap & FATTR4_ACL_MASK) { 1076 fattr4_acl acl; 1077 1078 acl.fattr4_acl_val = NULL; 1079 acl.fattr4_acl_len = 0; 1080 1081 if (!xdr_fattr4_acl(xdrs, &acl)) 1082 return (FALSE); 1083 1084 vsap->vsa_aclcnt = acl.fattr4_acl_len; 1085 vsap->vsa_aclentp = acl.fattr4_acl_val; 1086 vsap->vsa_mask = VSA_ACE | VSA_ACECNT; 1087 vsap->vsa_aclentsz = vsap->vsa_aclcnt * sizeof (ace_t); 1088 1089 } 1090 if (resbmap & FATTR4_ACLSUPPORT_MASK) { 1091 if (!XDR_GETINT32(xdrs, (int *)&gesp->n4g_aclsupport)) 1092 return (FALSE); 1093 } 1094 if (resbmap & FATTR4_ARCHIVE_MASK) { 1095 ASSERT(0); 1096 } 1097 if (resbmap & FATTR4_CANSETTIME_MASK) { 1098 if (!XDR_GETINT32(xdrs, (int *)&truefalse)) 1099 return (FALSE); 1100 gesp->n4g_pc4.pc4_cansettime = 1101 (truefalse ? TRUE : FALSE); 1102 } 1103 } 1104 if (resbmap & 1105 (FATTR4_CASE_INSENSITIVE_MASK | 1106 FATTR4_CASE_PRESERVING_MASK | 1107 FATTR4_CHOWN_RESTRICTED_MASK | 1108 FATTR4_FILEHANDLE_MASK | 1109 FATTR4_FILEID_MASK | 1110 FATTR4_FILES_AVAIL_MASK | 1111 FATTR4_FILES_FREE_MASK | 1112 FATTR4_FILES_TOTAL_MASK)) { 1113 1114 if (resbmap & FATTR4_CASE_INSENSITIVE_MASK) { 1115 if (!XDR_GETINT32(xdrs, (int *)&truefalse)) 1116 return (FALSE); 1117 gesp->n4g_pc4.pc4_case_insensitive = 1118 (truefalse ? TRUE : FALSE); 1119 } 1120 if (resbmap & FATTR4_CASE_PRESERVING_MASK) { 1121 if (!XDR_GETINT32(xdrs, (int *)&truefalse)) 1122 return (FALSE); 1123 gesp->n4g_pc4.pc4_case_preserving = 1124 (truefalse ? TRUE : FALSE); 1125 } 1126 if (resbmap & FATTR4_CHOWN_RESTRICTED_MASK) { 1127 if (!XDR_GETINT32(xdrs, (int *)&truefalse)) 1128 return (FALSE); 1129 gesp->n4g_pc4.pc4_chown_restricted = 1130 (truefalse ? TRUE : FALSE); 1131 } 1132 if (resbmap & FATTR4_FILEHANDLE_MASK) { 1133 gesp->n4g_fh_u.nfs_fh4_alt.len = 0; 1134 gesp->n4g_fh_u.nfs_fh4_alt.val = 1135 gesp->n4g_fh_u.nfs_fh4_alt.data; 1136 if (!xdr_bytes(xdrs, 1137 (char **)&gesp->n4g_fh_u.n4g_fh.nfs_fh4_val, 1138 (uint_t *)&gesp->n4g_fh_u.n4g_fh.nfs_fh4_len, 1139 NFS4_FHSIZE)) 1140 return (FALSE); 1141 } 1142 if (resbmap & FATTR4_FILEID_MASK) { 1143 if (!xdr_u_longlong_t(xdrs, 1144 (u_longlong_t *)&vap->va_nodeid)) 1145 return (FALSE); 1146 vap->va_mask |= AT_NODEID; 1147 } 1148 if (resbmap & FATTR4_FILES_AVAIL_MASK) { 1149 if (!xdr_u_longlong_t(xdrs, 1150 (u_longlong_t *)&gesp->n4g_sb.f_favail)) 1151 return (FALSE); 1152 } 1153 if (resbmap & FATTR4_FILES_FREE_MASK) { 1154 if (!xdr_u_longlong_t(xdrs, 1155 (u_longlong_t *)&gesp->n4g_sb.f_ffree)) 1156 return (FALSE); 1157 } 1158 if (resbmap & FATTR4_FILES_TOTAL_MASK) { 1159 if (!xdr_u_longlong_t(xdrs, 1160 (u_longlong_t *)&gesp->n4g_sb.f_files)) 1161 return (FALSE); 1162 } 1163 } 1164 if (resbmap & 1165 (FATTR4_FS_LOCATIONS_MASK | 1166 FATTR4_HIDDEN_MASK | 1167 FATTR4_HOMOGENEOUS_MASK)) { 1168 1169 if (resbmap & FATTR4_FS_LOCATIONS_MASK) { 1170 if (!xdr_fattr4_fs_locations(xdrs, 1171 &gesp->n4g_fslocations)) 1172 return (FALSE); 1173 } 1174 if (resbmap & FATTR4_HIDDEN_MASK) { 1175 ASSERT(0); 1176 } 1177 if (resbmap & FATTR4_HOMOGENEOUS_MASK) { 1178 if (!XDR_GETINT32(xdrs, (int *)&truefalse)) 1179 return (FALSE); 1180 gesp->n4g_pc4.pc4_homogeneous = 1181 (truefalse ? TRUE : FALSE); 1182 } 1183 } 1184 if (resbmap & 1185 (FATTR4_MAXFILESIZE_MASK | 1186 FATTR4_MAXLINK_MASK | 1187 FATTR4_MAXNAME_MASK | 1188 FATTR4_MAXREAD_MASK | 1189 FATTR4_MAXWRITE_MASK)) { 1190 1191 if (resbmap & FATTR4_MAXFILESIZE_MASK) { 1192 if (!xdr_u_longlong_t(xdrs, 1193 (u_longlong_t *)&gesp->n4g_maxfilesize)) 1194 return (FALSE); 1195 } 1196 if (resbmap & FATTR4_MAXLINK_MASK) { 1197 if (!XDR_GETINT32(xdrs, 1198 (int *)&gesp->n4g_pc4.pc4_link_max)) 1199 return (FALSE); 1200 } 1201 if (resbmap & FATTR4_MAXNAME_MASK) { 1202 if (!XDR_GETINT32(xdrs, 1203 (int *)&gesp->n4g_pc4.pc4_name_max)) 1204 return (FALSE); 1205 gesp->n4g_sb.f_namemax = gesp->n4g_pc4.pc4_name_max; 1206 } 1207 if (resbmap & FATTR4_MAXREAD_MASK) { 1208 if (!xdr_u_longlong_t(xdrs, 1209 (u_longlong_t *)&gesp->n4g_maxread)) 1210 return (FALSE); 1211 } 1212 if (resbmap & FATTR4_MAXWRITE_MASK) { 1213 if (!xdr_u_longlong_t(xdrs, 1214 (u_longlong_t *)&gesp->n4g_maxwrite)) 1215 return (FALSE); 1216 } 1217 } 1218 if (resbmap & 1219 (FATTR4_MIMETYPE_MASK | 1220 FATTR4_MODE_MASK | 1221 FATTR4_NO_TRUNC_MASK | 1222 FATTR4_NUMLINKS_MASK)) { 1223 1224 if (resbmap & FATTR4_MIMETYPE_MASK) { 1225 ASSERT(0); 1226 } 1227 if (resbmap & FATTR4_MODE_MASK) { 1228 if (!XDR_GETINT32(xdrs, (int *)&vap->va_mode)) 1229 return (FALSE); 1230 vap->va_mask |= AT_MODE; 1231 } 1232 if (resbmap & FATTR4_NO_TRUNC_MASK) { 1233 if (!XDR_GETINT32(xdrs, (int *)&truefalse)) 1234 return (FALSE); 1235 gesp->n4g_pc4.pc4_no_trunc = 1236 (truefalse ? TRUE : FALSE); 1237 } 1238 if (resbmap & FATTR4_NUMLINKS_MASK) { 1239 if (!XDR_GETINT32(xdrs, (int *)&vap->va_nlink)) 1240 return (FALSE); 1241 vap->va_mask |= AT_NLINK; 1242 } 1243 } 1244 if (resbmap & 1245 (FATTR4_OWNER_MASK | 1246 FATTR4_OWNER_GROUP_MASK | 1247 FATTR4_QUOTA_AVAIL_HARD_MASK | 1248 FATTR4_QUOTA_AVAIL_SOFT_MASK)) { 1249 1250 if (resbmap & FATTR4_OWNER_MASK) { 1251 uint_t *owner_length, ol; 1252 char *owner_val = NULL; 1253 char *owner_alloc = NULL; 1254 utf8string ov; 1255 int error; 1256 1257 /* get the OWNER_LENGTH */ 1258 if (!xdr_u_int(xdrs, &ol)) 1259 return (FALSE); 1260 1261 /* Manage the owner length location */ 1262 if (pug && ol <= MAX_OG_NAME) { 1263 owner_length = &pug->u_curr.utf8string_len; 1264 *owner_length = ol; 1265 } else { 1266 owner_length = &ol; 1267 } 1268 1269 /* find memory to store the decode */ 1270 if (*owner_length > MAX_OG_NAME || pug == NULL) 1271 owner_val = owner_alloc = 1272 kmem_alloc(*owner_length, KM_SLEEP); 1273 else 1274 owner_val = pug->u_curr.utf8string_val; 1275 1276 /* get the OWNER string */ 1277 if (!xdr_opaque(xdrs, owner_val, *owner_length)) { 1278 if (owner_alloc) 1279 kmem_free(owner_alloc, *owner_length); 1280 return (FALSE); 1281 } 1282 1283 /* Optimize for matching if called for */ 1284 if (pug && 1285 *owner_length == pug->u_last.utf8string_len && 1286 bcmp(owner_val, pug->u_last.utf8string_val, 1287 *owner_length) == 0) { 1288 vap->va_uid = pug->uid; 1289 vap->va_mask |= AT_UID; 1290 } else { 1291 uid_t uid; 1292 1293 ov.utf8string_len = *owner_length; 1294 ov.utf8string_val = owner_val; 1295 error = nfs_idmap_str_uid(&ov, &uid, FALSE); 1296 /* 1297 * String was mapped, but to nobody because 1298 * we are nfsmapid, indicate it should not 1299 * be cached. 1300 */ 1301 if (error == ENOTSUP) { 1302 error = 0; 1303 garp->n4g_attrwhy = 1304 NFS4_GETATTR_NOCACHE_OK; 1305 } 1306 1307 if (error) { 1308 garp->n4g_attrerr = error; 1309 garp->n4g_attrwhy = 1310 NFS4_GETATTR_ATUID_ERR; 1311 } else { 1312 vap->va_uid = uid; 1313 vap->va_mask |= AT_UID; 1314 if (pug && ol <= MAX_OG_NAME) { 1315 pug->uid = uid; 1316 U_SWAP_CURR_LAST(pug); 1317 } 1318 } 1319 if (owner_alloc) 1320 kmem_free(owner_alloc, *owner_length); 1321 } 1322 } 1323 if (resbmap & FATTR4_OWNER_GROUP_MASK) { 1324 uint_t *group_length, gl; 1325 char *group_val = NULL; 1326 char *group_alloc = NULL; 1327 utf8string gv; 1328 int error; 1329 1330 /* get the OWNER_GROUP_LENGTH */ 1331 if (!xdr_u_int(xdrs, &gl)) 1332 return (FALSE); 1333 1334 /* Manage the group length location */ 1335 if (pug && gl <= MAX_OG_NAME) { 1336 group_length = &pug->g_curr.utf8string_len; 1337 *group_length = gl; 1338 } else { 1339 group_length = ≷ 1340 } 1341 1342 /* find memory to store the decode */ 1343 if (*group_length > MAX_OG_NAME || pug == NULL) 1344 group_val = group_alloc = 1345 kmem_alloc(*group_length, KM_SLEEP); 1346 else 1347 group_val = pug->g_curr.utf8string_val; 1348 1349 /* get the OWNER_GROUP string */ 1350 if (!xdr_opaque(xdrs, group_val, *group_length)) { 1351 if (group_alloc) 1352 kmem_free(group_alloc, *group_length); 1353 return (FALSE); 1354 } 1355 1356 /* Optimize for matching if called for */ 1357 if (pug && 1358 *group_length == pug->g_last.utf8string_len && 1359 bcmp(group_val, pug->g_last.utf8string_val, 1360 *group_length) == 0) { 1361 vap->va_gid = pug->gid; 1362 vap->va_mask |= AT_GID; 1363 } else { 1364 uid_t gid; 1365 1366 gv.utf8string_len = *group_length; 1367 gv.utf8string_val = group_val; 1368 error = nfs_idmap_str_gid(&gv, &gid, FALSE); 1369 /* 1370 * String was mapped, but to nobody because 1371 * we are nfsmapid, indicate it should not 1372 * be cached. 1373 */ 1374 if (error == ENOTSUP) { 1375 error = 0; 1376 garp->n4g_attrwhy = 1377 NFS4_GETATTR_NOCACHE_OK; 1378 } 1379 1380 if (error) { 1381 garp->n4g_attrerr = error; 1382 garp->n4g_attrwhy = 1383 NFS4_GETATTR_ATGID_ERR; 1384 } else { 1385 vap->va_gid = gid; 1386 vap->va_mask |= AT_GID; 1387 if (pug && gl <= MAX_OG_NAME) { 1388 pug->gid = gid; 1389 G_SWAP_CURR_LAST(pug); 1390 } 1391 } 1392 if (group_alloc) { 1393 kmem_free(group_alloc, *group_length); 1394 } 1395 } 1396 } 1397 if (resbmap & FATTR4_QUOTA_AVAIL_HARD_MASK) { 1398 ASSERT(0); 1399 } 1400 if (resbmap & FATTR4_QUOTA_AVAIL_SOFT_MASK) { 1401 ASSERT(0); 1402 } 1403 } 1404 if (resbmap & 1405 (FATTR4_QUOTA_USED_MASK | 1406 FATTR4_SPACE_AVAIL_MASK | 1407 FATTR4_SPACE_FREE_MASK | 1408 FATTR4_SPACE_TOTAL_MASK | 1409 FATTR4_SPACE_USED_MASK | 1410 FATTR4_SYSTEM_MASK)) { 1411 1412 if (resbmap & FATTR4_QUOTA_USED_MASK) { 1413 ASSERT(0); 1414 } 1415 if (resbmap & FATTR4_RAWDEV_MASK) { 1416 fattr4_rawdev rawdev; 1417 if (!xdr_fattr4_rawdev(xdrs, &rawdev)) 1418 return (FALSE); 1419 1420 if (vap->va_type == VCHR || vap->va_type == VBLK) { 1421 vap->va_rdev = makedevice(rawdev.specdata1, 1422 rawdev.specdata2); 1423 } else { 1424 vap->va_rdev = 0; 1425 } 1426 vap->va_mask |= AT_RDEV; 1427 } 1428 if (resbmap & FATTR4_SPACE_AVAIL_MASK) { 1429 if (!xdr_u_longlong_t(xdrs, 1430 (u_longlong_t *)&gesp->n4g_sb.f_bavail)) 1431 return (FALSE); 1432 gesp->n4g_sb.f_bavail /= DEV_BSIZE; 1433 } 1434 if (resbmap & FATTR4_SPACE_FREE_MASK) { 1435 if (!xdr_u_longlong_t(xdrs, 1436 (u_longlong_t *)&gesp->n4g_sb.f_bfree)) 1437 return (FALSE); 1438 gesp->n4g_sb.f_bfree /= DEV_BSIZE; 1439 } 1440 if (resbmap & FATTR4_SPACE_TOTAL_MASK) { 1441 if (!xdr_u_longlong_t(xdrs, 1442 (u_longlong_t *)&gesp->n4g_sb.f_blocks)) 1443 return (FALSE); 1444 gesp->n4g_sb.f_blocks /= DEV_BSIZE; 1445 } 1446 if (resbmap & FATTR4_SPACE_USED_MASK) { 1447 uint64_t space_used; 1448 if (!xdr_u_longlong_t(xdrs, 1449 (u_longlong_t *)&space_used)) 1450 return (FALSE); 1451 1452 /* Compute space depending on device type */ 1453 ASSERT((vap->va_mask & AT_TYPE)); 1454 if (vap->va_type == VREG || vap->va_type == VDIR || 1455 vap->va_type == VLNK) { 1456 vap->va_nblocks = (u_longlong_t) 1457 ((space_used + (offset4)DEV_BSIZE - 1458 (offset4)1) / (offset4)DEV_BSIZE); 1459 } else { 1460 vap->va_nblocks = 0; 1461 } 1462 vap->va_mask |= AT_NBLOCKS; 1463 } 1464 if (resbmap & FATTR4_SYSTEM_MASK) { 1465 ASSERT(0); 1466 } 1467 } 1468 if (resbmap & 1469 (FATTR4_TIME_ACCESS_MASK | 1470 FATTR4_TIME_ACCESS_SET_MASK | 1471 FATTR4_TIME_BACKUP_MASK | 1472 FATTR4_TIME_CREATE_MASK | 1473 FATTR4_TIME_DELTA_MASK | 1474 FATTR4_TIME_METADATA_MASK | 1475 FATTR4_TIME_MODIFY_MASK | 1476 FATTR4_TIME_MODIFY_SET_MASK | 1477 FATTR4_MOUNTED_ON_FILEID_MASK)) { 1478 1479 if (resbmap & FATTR4_TIME_ACCESS_MASK) { 1480 nfstime4 atime; 1481 int error; 1482 1483 if (!xdr_longlong_t(xdrs, 1484 (longlong_t *)&atime.seconds)) 1485 return (FALSE); 1486 if (!XDR_GETINT32(xdrs, (int *)&atime.nseconds)) 1487 return (FALSE); 1488 error = nfs4_time_ntov(&atime, &vap->va_atime); 1489 if (error) { 1490 garp->n4g_attrerr = error; 1491 garp->n4g_attrwhy = NFS4_GETATTR_ATATIME_ERR; 1492 } 1493 vap->va_mask |= AT_ATIME; 1494 } 1495 if (resbmap & FATTR4_TIME_ACCESS_SET_MASK) { 1496 ASSERT(0); 1497 } 1498 if (resbmap & FATTR4_TIME_BACKUP_MASK) { 1499 ASSERT(0); 1500 } 1501 if (resbmap & FATTR4_TIME_CREATE_MASK) { 1502 ASSERT(0); 1503 } 1504 if (resbmap & FATTR4_TIME_DELTA_MASK) { 1505 if ((!xdr_u_longlong_t(xdrs, 1506 (u_longlong_t *)&gesp->n4g_delta.seconds)) || 1507 (!xdr_u_int(xdrs, &gesp->n4g_delta.nseconds))) 1508 return (FALSE); 1509 } 1510 if (resbmap & FATTR4_TIME_METADATA_MASK) { 1511 nfstime4 mdt; 1512 int error; 1513 1514 if (!xdr_longlong_t(xdrs, (longlong_t *)&mdt.seconds)) 1515 return (FALSE); 1516 if (!XDR_GETINT32(xdrs, (int32_t *)&mdt.nseconds)) 1517 return (FALSE); 1518 error = nfs4_time_ntov(&mdt, &vap->va_ctime); 1519 if (error) { 1520 garp->n4g_attrerr = error; 1521 garp->n4g_attrwhy = NFS4_GETATTR_ATCTIME_ERR; 1522 } 1523 vap->va_mask |= AT_CTIME; 1524 } 1525 if (resbmap & FATTR4_TIME_MODIFY_MASK) { 1526 nfstime4 mtime; 1527 int error; 1528 1529 if (!xdr_longlong_t(xdrs, 1530 (longlong_t *)&mtime.seconds)) 1531 return (FALSE); 1532 if (!XDR_GETINT32(xdrs, (int32_t *)&mtime.nseconds)) 1533 return (FALSE); 1534 error = nfs4_time_ntov(&mtime, &vap->va_mtime); 1535 if (error) { 1536 garp->n4g_attrerr = error; 1537 garp->n4g_attrwhy = NFS4_GETATTR_ATMTIME_ERR; 1538 } 1539 vap->va_mask |= AT_MTIME; 1540 } 1541 if (resbmap & FATTR4_TIME_MODIFY_SET_MASK) { 1542 ASSERT(0); 1543 } 1544 if (resbmap & FATTR4_MOUNTED_ON_FILEID_MASK) { 1545 if (!xdr_u_longlong_t(xdrs, 1546 (u_longlong_t *)&garp->n4g_mon_fid)) 1547 return (FALSE); 1548 garp->n4g_mon_fid_valid = 1; 1549 } 1550 } 1551 1552 if (resbmap & ~(NFS4_VATTR_MASK | FATTR4_ACL_MASK)) { 1553 /* copy only if not provided */ 1554 if (garp->n4g_ext_res == NULL) { 1555 garp->n4g_ext_res = kmem_alloc(sizeof (ges), KM_SLEEP); 1556 bcopy(&ges, garp->n4g_ext_res, sizeof (ges)); 1557 } 1558 } 1559 1560 return (TRUE); 1561 } 1562 1563 /* 1564 * Inlined version of get_bitmap4 processing 1565 */ 1566 bitmap4 1567 xdr_get_bitmap4_inline(uint32_t **iptr) 1568 { 1569 uint32_t resbmaplen; 1570 bitmap4 bm; 1571 uint32_t *ptr = *iptr; 1572 1573 /* bitmap LENGTH */ 1574 resbmaplen = IXDR_GET_U_INT32(ptr); 1575 1576 /* Inline the bitmap and attrlen for common case of two word map */ 1577 if (resbmaplen == 2) { 1578 IXDR_GET_HYPER(ptr, bm); 1579 *iptr = ptr; 1580 return (bm); 1581 } 1582 1583 #if defined(_LITTLE_ENDIAN) 1584 bm = IXDR_GET_U_INT32(ptr); 1585 if (--resbmaplen == 0) { 1586 *iptr = ptr; 1587 return (bm); 1588 } 1589 *((uint32_t *)&bm) |= IXDR_GET_U_INT32(ptr); 1590 if (--resbmaplen == 0) { 1591 *iptr = ptr; 1592 return (bm); 1593 } 1594 ptr += resbmaplen; 1595 *iptr = ptr; 1596 return (bm); 1597 #elif defined(_BIG_ENDIAN) 1598 *((uint32_t *)&bm) = IXDR_GET_U_INT32(ptr); 1599 if (--resbmaplen == 0) { 1600 *iptr = ptr; 1601 return (bm); 1602 } 1603 bm |= IXDR_GET_U_INT32(ptr); 1604 if (--resbmaplen == 0) { 1605 *iptr = ptr; 1606 return (bm); 1607 } 1608 ptr += resbmaplen; 1609 *iptr = ptr; 1610 return (bm); 1611 #else 1612 ASSERT(0); 1613 ptr += resbmaplen; 1614 *iptr = ptr; 1615 return (0); 1616 #endif 1617 } 1618 1619 static bool_t 1620 xdr_ga_fattr_res_inline(uint32_t *ptr, struct nfs4_ga_res *garp, 1621 bitmap4 resbmap, bitmap4 argbmap, struct mntinfo4 *mi, ug_cache_t *pug) 1622 { 1623 int truefalse; 1624 struct nfs4_ga_ext_res ges, *gesp; 1625 vattr_t *vap = &garp->n4g_va; 1626 1627 if (garp->n4g_ext_res) 1628 gesp = garp->n4g_ext_res; 1629 else 1630 gesp = ⩾ 1631 1632 vap->va_mask = 0; 1633 1634 /* Check to see if the vattr should be pre-filled */ 1635 if (argbmap & NFS4_VATTR_MASK) 1636 xdr_ga_prefill_vattr(garp, mi); 1637 1638 if (argbmap & NFS4_STATFS_ATTR_MASK) 1639 xdr_ga_prefill_statvfs(gesp, mi); 1640 1641 if (resbmap & 1642 (FATTR4_SUPPORTED_ATTRS_MASK | 1643 FATTR4_TYPE_MASK | 1644 FATTR4_FH_EXPIRE_TYPE_MASK | 1645 FATTR4_CHANGE_MASK | 1646 FATTR4_SIZE_MASK | 1647 FATTR4_LINK_SUPPORT_MASK | 1648 FATTR4_SYMLINK_SUPPORT_MASK | 1649 FATTR4_NAMED_ATTR_MASK)) { 1650 1651 if (resbmap & FATTR4_SUPPORTED_ATTRS_MASK) { 1652 gesp->n4g_suppattrs = xdr_get_bitmap4_inline(&ptr); 1653 } 1654 if (resbmap & FATTR4_TYPE_MASK) { 1655 vap->va_type = IXDR_GET_U_INT32(ptr); 1656 1657 if ((nfs_ftype4)vap->va_type < NF4REG || 1658 (nfs_ftype4)vap->va_type > NF4NAMEDATTR) 1659 vap->va_type = VBAD; 1660 else 1661 vap->va_type = nf4_to_vt[vap->va_type]; 1662 if (vap->va_type == VBLK) 1663 vap->va_blksize = DEV_BSIZE; 1664 1665 vap->va_mask |= AT_TYPE; 1666 } 1667 if (resbmap & FATTR4_FH_EXPIRE_TYPE_MASK) { 1668 gesp->n4g_fet = IXDR_GET_U_INT32(ptr); 1669 } 1670 if (resbmap & FATTR4_CHANGE_MASK) { 1671 IXDR_GET_U_HYPER(ptr, garp->n4g_change); 1672 garp->n4g_change_valid = 1; 1673 } 1674 if (resbmap & FATTR4_SIZE_MASK) { 1675 IXDR_GET_U_HYPER(ptr, vap->va_size); 1676 1677 if (!NFS4_SIZE_OK(vap->va_size)) { 1678 garp->n4g_attrerr = EFBIG; 1679 garp->n4g_attrwhy = NFS4_GETATTR_ATSIZE_ERR; 1680 } else { 1681 vap->va_mask |= AT_SIZE; 1682 } 1683 } 1684 if (resbmap & FATTR4_LINK_SUPPORT_MASK) { 1685 truefalse = IXDR_GET_U_INT32(ptr); 1686 gesp->n4g_pc4.pc4_link_support = 1687 (truefalse ? TRUE : FALSE); 1688 } 1689 if (resbmap & FATTR4_SYMLINK_SUPPORT_MASK) { 1690 truefalse = IXDR_GET_U_INT32(ptr); 1691 gesp->n4g_pc4.pc4_symlink_support = 1692 (truefalse ? TRUE : FALSE); 1693 } 1694 if (resbmap & FATTR4_NAMED_ATTR_MASK) { 1695 truefalse = IXDR_GET_U_INT32(ptr); 1696 gesp->n4g_pc4.pc4_xattr_exists = TRUE; 1697 gesp->n4g_pc4.pc4_xattr_exists = 1698 (truefalse ? TRUE : FALSE); 1699 } 1700 } 1701 if (resbmap & 1702 (FATTR4_FSID_MASK | 1703 FATTR4_UNIQUE_HANDLES_MASK | 1704 FATTR4_LEASE_TIME_MASK | 1705 FATTR4_RDATTR_ERROR_MASK)) { 1706 1707 if (resbmap & FATTR4_FSID_MASK) { 1708 IXDR_GET_U_HYPER(ptr, garp->n4g_fsid.major); 1709 IXDR_GET_U_HYPER(ptr, garp->n4g_fsid.minor); 1710 garp->n4g_fsid_valid = 1; 1711 } 1712 if (resbmap & FATTR4_UNIQUE_HANDLES_MASK) { 1713 truefalse = IXDR_GET_U_INT32(ptr); 1714 gesp->n4g_pc4.pc4_unique_handles = 1715 (truefalse ? TRUE : FALSE); 1716 } 1717 if (resbmap & FATTR4_LEASE_TIME_MASK) { 1718 gesp->n4g_leasetime = IXDR_GET_U_INT32(ptr); 1719 } 1720 if (resbmap & FATTR4_RDATTR_ERROR_MASK) { 1721 gesp->n4g_rdattr_error = IXDR_GET_U_INT32(ptr); 1722 } 1723 } 1724 if (resbmap & 1725 (FATTR4_ACL_MASK | 1726 FATTR4_ACLSUPPORT_MASK | 1727 FATTR4_ARCHIVE_MASK | 1728 FATTR4_CANSETTIME_MASK)) { 1729 1730 if (resbmap & FATTR4_ACL_MASK) { 1731 ASSERT(0); 1732 } 1733 if (resbmap & FATTR4_ACLSUPPORT_MASK) { 1734 gesp->n4g_aclsupport = IXDR_GET_U_INT32(ptr); 1735 } 1736 if (resbmap & FATTR4_ARCHIVE_MASK) { 1737 ASSERT(0); 1738 } 1739 if (resbmap & FATTR4_CANSETTIME_MASK) { 1740 truefalse = IXDR_GET_U_INT32(ptr); 1741 gesp->n4g_pc4.pc4_cansettime = 1742 (truefalse ? TRUE : FALSE); 1743 } 1744 } 1745 if (resbmap & 1746 (FATTR4_CASE_INSENSITIVE_MASK | 1747 FATTR4_CASE_PRESERVING_MASK | 1748 FATTR4_CHOWN_RESTRICTED_MASK | 1749 FATTR4_FILEHANDLE_MASK | 1750 FATTR4_FILEID_MASK | 1751 FATTR4_FILES_AVAIL_MASK | 1752 FATTR4_FILES_FREE_MASK | 1753 FATTR4_FILES_TOTAL_MASK)) { 1754 1755 if (resbmap & FATTR4_CASE_INSENSITIVE_MASK) { 1756 truefalse = IXDR_GET_U_INT32(ptr); 1757 gesp->n4g_pc4.pc4_case_insensitive = 1758 (truefalse ? TRUE : FALSE); 1759 } 1760 if (resbmap & FATTR4_CASE_PRESERVING_MASK) { 1761 truefalse = IXDR_GET_U_INT32(ptr); 1762 gesp->n4g_pc4.pc4_case_preserving = 1763 (truefalse ? TRUE : FALSE); 1764 } 1765 if (resbmap & FATTR4_CHOWN_RESTRICTED_MASK) { 1766 truefalse = IXDR_GET_U_INT32(ptr); 1767 gesp->n4g_pc4.pc4_chown_restricted = 1768 (truefalse ? TRUE : FALSE); 1769 } 1770 if (resbmap & FATTR4_FILEHANDLE_MASK) { 1771 int len = IXDR_GET_U_INT32(ptr); 1772 1773 gesp->n4g_fh_u.nfs_fh4_alt.len = 0; 1774 gesp->n4g_fh_u.nfs_fh4_alt.val = 1775 gesp->n4g_fh_u.nfs_fh4_alt.data; 1776 gesp->n4g_fh_u.n4g_fh.nfs_fh4_len = len; 1777 1778 bcopy(ptr, gesp->n4g_fh_u.n4g_fh.nfs_fh4_val, len); 1779 1780 ptr += RNDUP(len) / BYTES_PER_XDR_UNIT; 1781 } 1782 if (resbmap & FATTR4_FILEID_MASK) { 1783 IXDR_GET_U_HYPER(ptr, vap->va_nodeid); 1784 vap->va_mask |= AT_NODEID; 1785 } 1786 if (resbmap & FATTR4_FILES_AVAIL_MASK) { 1787 IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_favail); 1788 } 1789 if (resbmap & FATTR4_FILES_FREE_MASK) { 1790 IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_ffree); 1791 } 1792 if (resbmap & FATTR4_FILES_TOTAL_MASK) { 1793 IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_files); 1794 } 1795 } 1796 if (resbmap & 1797 (FATTR4_FS_LOCATIONS_MASK | 1798 FATTR4_HIDDEN_MASK | 1799 FATTR4_HOMOGENEOUS_MASK)) { 1800 1801 if (resbmap & FATTR4_FS_LOCATIONS_MASK) { 1802 ASSERT(0); 1803 } 1804 if (resbmap & FATTR4_HIDDEN_MASK) { 1805 ASSERT(0); 1806 } 1807 if (resbmap & FATTR4_HOMOGENEOUS_MASK) { 1808 truefalse = IXDR_GET_U_INT32(ptr); 1809 gesp->n4g_pc4.pc4_homogeneous = 1810 (truefalse ? TRUE : FALSE); 1811 } 1812 } 1813 if (resbmap & 1814 (FATTR4_MAXFILESIZE_MASK | 1815 FATTR4_MAXLINK_MASK | 1816 FATTR4_MAXNAME_MASK | 1817 FATTR4_MAXREAD_MASK | 1818 FATTR4_MAXWRITE_MASK)) { 1819 1820 if (resbmap & FATTR4_MAXFILESIZE_MASK) { 1821 IXDR_GET_U_HYPER(ptr, gesp->n4g_maxfilesize); 1822 } 1823 if (resbmap & FATTR4_MAXLINK_MASK) { 1824 gesp->n4g_pc4.pc4_link_max = IXDR_GET_U_INT32(ptr); 1825 } 1826 if (resbmap & FATTR4_MAXNAME_MASK) { 1827 gesp->n4g_pc4.pc4_name_max = IXDR_GET_U_INT32(ptr); 1828 gesp->n4g_sb.f_namemax = gesp->n4g_pc4.pc4_name_max; 1829 } 1830 if (resbmap & FATTR4_MAXREAD_MASK) { 1831 IXDR_GET_U_HYPER(ptr, gesp->n4g_maxread); 1832 } 1833 if (resbmap & FATTR4_MAXWRITE_MASK) { 1834 IXDR_GET_U_HYPER(ptr, gesp->n4g_maxwrite); 1835 } 1836 } 1837 if (resbmap & 1838 (FATTR4_MIMETYPE_MASK | 1839 FATTR4_MODE_MASK | 1840 FATTR4_NO_TRUNC_MASK | 1841 FATTR4_NUMLINKS_MASK)) { 1842 1843 if (resbmap & FATTR4_MIMETYPE_MASK) { 1844 ASSERT(0); 1845 } 1846 if (resbmap & FATTR4_MODE_MASK) { 1847 vap->va_mode = IXDR_GET_U_INT32(ptr); 1848 vap->va_mask |= AT_MODE; 1849 } 1850 if (resbmap & FATTR4_NO_TRUNC_MASK) { 1851 truefalse = IXDR_GET_U_INT32(ptr); 1852 gesp->n4g_pc4.pc4_no_trunc = 1853 (truefalse ? TRUE : FALSE); 1854 } 1855 if (resbmap & FATTR4_NUMLINKS_MASK) { 1856 vap->va_nlink = IXDR_GET_U_INT32(ptr); 1857 vap->va_mask |= AT_NLINK; 1858 } 1859 } 1860 if (resbmap & 1861 (FATTR4_OWNER_MASK | 1862 FATTR4_OWNER_GROUP_MASK | 1863 FATTR4_QUOTA_AVAIL_HARD_MASK | 1864 FATTR4_QUOTA_AVAIL_SOFT_MASK)) { 1865 1866 if (resbmap & FATTR4_OWNER_MASK) { 1867 uint_t *owner_length, ol; 1868 char *owner_val = NULL; 1869 utf8string ov; 1870 int error; 1871 1872 /* get the OWNER_LENGTH */ 1873 ol = IXDR_GET_U_INT32(ptr); 1874 1875 /* Manage the owner length location */ 1876 if (pug && ol <= MAX_OG_NAME) { 1877 owner_length = &pug->u_curr.utf8string_len; 1878 *owner_length = ol; 1879 } else { 1880 owner_length = &ol; 1881 } 1882 1883 /* find memory to store the decode */ 1884 if (*owner_length > MAX_OG_NAME || pug == NULL) 1885 owner_val = (char *)ptr; 1886 else 1887 owner_val = (char *)ptr; 1888 1889 /* Optimize for matching if called for */ 1890 if (pug && 1891 *owner_length == pug->u_last.utf8string_len && 1892 bcmp(owner_val, pug->u_last.utf8string_val, 1893 *owner_length) == 0) { 1894 vap->va_uid = pug->uid; 1895 vap->va_mask |= AT_UID; 1896 } else { 1897 uid_t uid; 1898 1899 ov.utf8string_len = *owner_length; 1900 ov.utf8string_val = owner_val; 1901 error = nfs_idmap_str_uid(&ov, &uid, FALSE); 1902 /* 1903 * String was mapped, but to nobody because 1904 * we are nfsmapid, indicate it should not 1905 * be cached. 1906 */ 1907 if (error == ENOTSUP) { 1908 error = 0; 1909 garp->n4g_attrwhy = 1910 NFS4_GETATTR_NOCACHE_OK; 1911 } 1912 1913 if (error) { 1914 garp->n4g_attrerr = error; 1915 garp->n4g_attrwhy = 1916 NFS4_GETATTR_ATUID_ERR; 1917 } else { 1918 vap->va_uid = uid; 1919 vap->va_mask |= AT_UID; 1920 /* save the results for next time */ 1921 if (pug && ol <= MAX_OG_NAME) { 1922 pug->uid = uid; 1923 pug->u_curr.utf8string_len = 1924 ov.utf8string_len; 1925 bcopy(owner_val, 1926 pug->u_curr.utf8string_val, 1927 ol); 1928 U_SWAP_CURR_LAST(pug); 1929 } 1930 } 1931 } 1932 ptr += RNDUP(ol) / BYTES_PER_XDR_UNIT; 1933 } 1934 if (resbmap & FATTR4_OWNER_GROUP_MASK) { 1935 uint_t *group_length, gl; 1936 char *group_val = NULL; 1937 utf8string gv; 1938 int error; 1939 1940 /* get the OWNER_GROUP_LENGTH */ 1941 gl = IXDR_GET_U_INT32(ptr); 1942 1943 /* Manage the group length location */ 1944 if (pug && gl <= MAX_OG_NAME) { 1945 group_length = &pug->g_curr.utf8string_len; 1946 *group_length = gl; 1947 } else { 1948 group_length = ≷ 1949 } 1950 1951 /* find memory to store the decode */ 1952 if (*group_length > MAX_OG_NAME || pug == NULL) 1953 group_val = (char *)ptr; 1954 else 1955 group_val = (char *)ptr; 1956 1957 /* Optimize for matching if called for */ 1958 if (pug && 1959 *group_length == pug->g_last.utf8string_len && 1960 bcmp(group_val, pug->g_last.utf8string_val, 1961 *group_length) == 0) { 1962 vap->va_gid = pug->gid; 1963 vap->va_mask |= AT_GID; 1964 } else { 1965 uid_t gid; 1966 1967 gv.utf8string_len = *group_length; 1968 gv.utf8string_val = group_val; 1969 error = nfs_idmap_str_gid(&gv, &gid, FALSE); 1970 /* 1971 * String was mapped, but to nobody because 1972 * we are nfsmapid, indicate it should not 1973 * be cached. 1974 */ 1975 if (error == ENOTSUP) { 1976 error = 0; 1977 garp->n4g_attrwhy = 1978 NFS4_GETATTR_NOCACHE_OK; 1979 } 1980 1981 if (error) { 1982 garp->n4g_attrerr = error; 1983 garp->n4g_attrwhy = 1984 NFS4_GETATTR_ATGID_ERR; 1985 } else { 1986 vap->va_gid = gid; 1987 vap->va_mask |= AT_GID; 1988 if (pug && gl <= MAX_OG_NAME) { 1989 pug->gid = gid; 1990 pug->g_curr.utf8string_len = 1991 gv.utf8string_len; 1992 bcopy(group_val, 1993 pug->g_curr.utf8string_val, 1994 gl); 1995 G_SWAP_CURR_LAST(pug); 1996 } 1997 } 1998 } 1999 ptr += RNDUP(gl) / BYTES_PER_XDR_UNIT; 2000 } 2001 if (resbmap & FATTR4_QUOTA_AVAIL_HARD_MASK) { 2002 ASSERT(0); 2003 } 2004 if (resbmap & FATTR4_QUOTA_AVAIL_SOFT_MASK) { 2005 ASSERT(0); 2006 } 2007 } 2008 if (resbmap & 2009 (FATTR4_QUOTA_USED_MASK | 2010 FATTR4_SPACE_AVAIL_MASK | 2011 FATTR4_SPACE_FREE_MASK | 2012 FATTR4_SPACE_TOTAL_MASK | 2013 FATTR4_SPACE_USED_MASK | 2014 FATTR4_SYSTEM_MASK)) { 2015 2016 if (resbmap & FATTR4_QUOTA_USED_MASK) { 2017 ASSERT(0); 2018 } 2019 if (resbmap & FATTR4_RAWDEV_MASK) { 2020 fattr4_rawdev rawdev; 2021 2022 rawdev.specdata1 = IXDR_GET_U_INT32(ptr); 2023 rawdev.specdata2 = IXDR_GET_U_INT32(ptr); 2024 2025 if (vap->va_type == VCHR || vap->va_type == VBLK) { 2026 vap->va_rdev = makedevice(rawdev.specdata1, 2027 rawdev.specdata2); 2028 } else { 2029 vap->va_rdev = 0; 2030 } 2031 vap->va_mask |= AT_RDEV; 2032 } 2033 if (resbmap & FATTR4_SPACE_AVAIL_MASK) { 2034 IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_bavail); 2035 gesp->n4g_sb.f_bavail /= DEV_BSIZE; 2036 } 2037 if (resbmap & FATTR4_SPACE_FREE_MASK) { 2038 IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_bfree); 2039 gesp->n4g_sb.f_bfree /= DEV_BSIZE; 2040 } 2041 if (resbmap & FATTR4_SPACE_TOTAL_MASK) { 2042 IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_blocks); 2043 gesp->n4g_sb.f_blocks /= DEV_BSIZE; 2044 } 2045 if (resbmap & FATTR4_SPACE_USED_MASK) { 2046 uint64_t space_used; 2047 IXDR_GET_U_HYPER(ptr, space_used); 2048 2049 /* Compute space depending on device type */ 2050 ASSERT((vap->va_mask & AT_TYPE)); 2051 if (vap->va_type == VREG || vap->va_type == VDIR || 2052 vap->va_type == VLNK) { 2053 vap->va_nblocks = (u_longlong_t) 2054 ((space_used + (offset4)DEV_BSIZE - 2055 (offset4)1) / (offset4)DEV_BSIZE); 2056 } else { 2057 vap->va_nblocks = 0; 2058 } 2059 vap->va_mask |= AT_NBLOCKS; 2060 } 2061 if (resbmap & FATTR4_SYSTEM_MASK) { 2062 ASSERT(0); 2063 } 2064 } 2065 if (resbmap & 2066 (FATTR4_TIME_ACCESS_MASK | 2067 FATTR4_TIME_ACCESS_SET_MASK | 2068 FATTR4_TIME_BACKUP_MASK | 2069 FATTR4_TIME_CREATE_MASK | 2070 FATTR4_TIME_DELTA_MASK | 2071 FATTR4_TIME_METADATA_MASK | 2072 FATTR4_TIME_MODIFY_MASK | 2073 FATTR4_TIME_MODIFY_SET_MASK | 2074 FATTR4_MOUNTED_ON_FILEID_MASK)) { 2075 2076 if (resbmap & FATTR4_TIME_ACCESS_MASK) { 2077 nfstime4 atime; 2078 int error; 2079 2080 IXDR_GET_U_HYPER(ptr, atime.seconds); 2081 atime.nseconds = IXDR_GET_U_INT32(ptr); 2082 2083 error = nfs4_time_ntov(&atime, &vap->va_atime); 2084 if (error) { 2085 garp->n4g_attrerr = error; 2086 garp->n4g_attrwhy = NFS4_GETATTR_ATATIME_ERR; 2087 } 2088 vap->va_mask |= AT_ATIME; 2089 } 2090 if (resbmap & FATTR4_TIME_ACCESS_SET_MASK) { 2091 ASSERT(0); 2092 } 2093 if (resbmap & FATTR4_TIME_BACKUP_MASK) { 2094 ASSERT(0); 2095 } 2096 if (resbmap & FATTR4_TIME_CREATE_MASK) { 2097 ASSERT(0); 2098 } 2099 if (resbmap & FATTR4_TIME_DELTA_MASK) { 2100 IXDR_GET_U_HYPER(ptr, gesp->n4g_delta.seconds); 2101 gesp->n4g_delta.nseconds = IXDR_GET_U_INT32(ptr); 2102 } 2103 if (resbmap & FATTR4_TIME_METADATA_MASK) { 2104 nfstime4 mdt; 2105 int error; 2106 2107 IXDR_GET_U_HYPER(ptr, mdt.seconds); 2108 mdt.nseconds = IXDR_GET_U_INT32(ptr); 2109 2110 error = nfs4_time_ntov(&mdt, &vap->va_ctime); 2111 if (error) { 2112 garp->n4g_attrerr = error; 2113 garp->n4g_attrwhy = NFS4_GETATTR_ATCTIME_ERR; 2114 } 2115 vap->va_mask |= AT_CTIME; 2116 } 2117 if (resbmap & FATTR4_TIME_MODIFY_MASK) { 2118 nfstime4 mtime; 2119 int error; 2120 2121 IXDR_GET_U_HYPER(ptr, mtime.seconds); 2122 mtime.nseconds = IXDR_GET_U_INT32(ptr); 2123 2124 error = nfs4_time_ntov(&mtime, &vap->va_mtime); 2125 if (error) { 2126 garp->n4g_attrerr = error; 2127 garp->n4g_attrwhy = NFS4_GETATTR_ATMTIME_ERR; 2128 } 2129 vap->va_mask |= AT_MTIME; 2130 } 2131 if (resbmap & FATTR4_TIME_MODIFY_SET_MASK) { 2132 ASSERT(0); 2133 } 2134 if (resbmap & FATTR4_MOUNTED_ON_FILEID_MASK) { 2135 IXDR_GET_U_HYPER(ptr, garp->n4g_mon_fid); 2136 garp->n4g_mon_fid_valid = 1; 2137 } 2138 } 2139 2140 /* 2141 * FATTR4_ACL_MASK is not yet supported by this function, but 2142 * we check against it anyway, in case it ever is. 2143 */ 2144 if (resbmap & ~(NFS4_VATTR_MASK | FATTR4_ACL_MASK)) { 2145 /* copy only if not provided */ 2146 if (garp->n4g_ext_res == NULL) { 2147 garp->n4g_ext_res = kmem_alloc(sizeof (ges), KM_SLEEP); 2148 bcopy(&ges, garp->n4g_ext_res, sizeof (ges)); 2149 } 2150 } 2151 2152 return (TRUE); 2153 } 2154 2155 2156 /* 2157 * "." and ".." buffers for filling in on read and readdir 2158 * calls. Intialize the first time and fill in on every 2159 * call to to readdir. 2160 */ 2161 char *nfs4_dot_entries; 2162 char *nfs4_dot_dot_entry; 2163 2164 /* 2165 * Create the "." or ".." and pad the buffer once so they are 2166 * copied out as required into the user supplied buffer everytime. 2167 * DIRENT64_RECLEN(sizeof (".") - 1) = DIRENT64_RECLEN(1) 2168 * DIRENT64_RECLEN(sizeof ("..") - 1) = DIRENT64_RECLEN(2) 2169 */ 2170 void 2171 nfs4_init_dot_entries() 2172 { 2173 struct dirent64 *odp; 2174 2175 /* 2176 * zalloc it so it zeros the buffer out. Need 2177 * to just do it once. 2178 */ 2179 nfs4_dot_entries = kmem_zalloc(DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2), 2180 KM_SLEEP); 2181 2182 odp = (struct dirent64 *)nfs4_dot_entries; 2183 odp->d_off = 1; /* magic cookie for "." entry */ 2184 odp->d_reclen = DIRENT64_RECLEN(1); 2185 odp->d_name[0] = '.'; 2186 odp->d_name[1] = '\0'; 2187 2188 nfs4_dot_dot_entry = nfs4_dot_entries + DIRENT64_RECLEN(1); 2189 odp = (struct dirent64 *)nfs4_dot_dot_entry; 2190 2191 odp->d_off = 2; 2192 odp->d_reclen = DIRENT64_RECLEN(2); 2193 odp->d_name[0] = '.'; 2194 odp->d_name[1] = '.'; 2195 odp->d_name[2] = '\0'; 2196 } 2197 2198 void 2199 nfs4_destroy_dot_entries() 2200 { 2201 if (nfs4_dot_entries) 2202 kmem_free(nfs4_dot_entries, DIRENT64_RECLEN(1) + 2203 DIRENT64_RECLEN(2)); 2204 2205 nfs4_dot_entries = nfs4_dot_dot_entry = NULL; 2206 } 2207 2208 bool_t 2209 xdr_READDIR4res_clnt(XDR *xdrs, READDIR4res_clnt *objp, READDIR4args *aobjp) 2210 { 2211 bool_t more_data; 2212 rddir4_cache *rdc = aobjp->rdc; 2213 dirent64_t *dp = NULL; 2214 int entry_length = 0; 2215 int space_left = 0; 2216 bitmap4 resbmap; 2217 uint32_t attrlen; 2218 nfs4_ga_res_t gar; 2219 struct nfs4_ga_ext_res ges; 2220 uint64_t last_cookie = 0; 2221 int skip_to_end; 2222 ug_cache_t *pug = NULL; 2223 2224 ASSERT(xdrs->x_op == XDR_DECODE); 2225 ASSERT(rdc->entries == NULL); 2226 ASSERT(aobjp->dircount > 0); 2227 2228 if (!xdr_int(xdrs, (int32_t *)&objp->status)) 2229 return (FALSE); 2230 if (objp->status != NFS4_OK) 2231 return (TRUE); 2232 2233 gar.n4g_va.va_mask = 0; 2234 gar.n4g_change_valid = 0; 2235 gar.n4g_mon_fid_valid = 0; 2236 gar.n4g_fsid_valid = 0; 2237 gar.n4g_vsa.vsa_mask = 0; 2238 gar.n4g_attrwhy = NFS4_GETATTR_OP_OK; 2239 ges.n4g_pc4.pc4_cache_valid = 0; 2240 ges.n4g_pc4.pc4_xattr_valid = 0; 2241 gar.n4g_ext_res = ⩾ 2242 2243 /* READDIR4res_clnt_free needs to kmem_free this buffer */ 2244 rdc->entries = kmem_alloc(aobjp->dircount, KM_SLEEP); 2245 2246 dp = (dirent64_t *)rdc->entries; 2247 rdc->entlen = rdc->buflen = space_left = aobjp->dircount; 2248 2249 /* Fill in dot and dot-dot if needed */ 2250 if (rdc->nfs4_cookie == (nfs_cookie4) 0 || 2251 rdc->nfs4_cookie == (nfs_cookie4) 1) { 2252 2253 if (rdc->nfs4_cookie == (nfs_cookie4)0) { 2254 bcopy(nfs4_dot_entries, rdc->entries, 2255 DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2)); 2256 objp->dotp = dp; 2257 dp = (struct dirent64 *)(((char *)dp) + 2258 DIRENT64_RECLEN(1)); 2259 objp->dotdotp = dp; 2260 dp = (struct dirent64 *)(((char *)dp) + 2261 DIRENT64_RECLEN(2)); 2262 space_left -= DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2); 2263 2264 } else { /* for ".." entry */ 2265 bcopy(nfs4_dot_dot_entry, rdc->entries, 2266 DIRENT64_RECLEN(2)); 2267 objp->dotp = NULL; 2268 objp->dotdotp = dp; 2269 dp = (struct dirent64 *)(((char *)dp) + 2270 DIRENT64_RECLEN(2)); 2271 space_left -= DIRENT64_RECLEN(2); 2272 } 2273 /* Magic NFSv4 number for entry after start */ 2274 last_cookie = 2; 2275 } 2276 2277 /* Get the cookie VERIFIER */ 2278 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cookieverf)) 2279 goto noentries; 2280 2281 /* Get the do-we-have-a-next-entry BOOL */ 2282 if (!xdr_bool(xdrs, &more_data)) 2283 goto noentries; 2284 2285 if (aobjp->attr_request & (FATTR4_OWNER_MASK | FATTR4_OWNER_GROUP_MASK)) 2286 pug = alloc_ugcache(); 2287 2288 skip_to_end = 0; 2289 while (more_data) { 2290 uint_t namelen; 2291 uint64_t cookie; 2292 2293 /* Get the COOKIE */ 2294 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&cookie)) 2295 goto noentries; 2296 2297 /* Get the LENGTH of the entry name */ 2298 if (!xdr_u_int(xdrs, &namelen)) 2299 goto noentries; 2300 2301 if (!skip_to_end) { 2302 /* 2303 * With the length of the directory entry name 2304 * in hand, figure out if there is room left 2305 * to encode it for the requestor. If not, 2306 * that is okay, but the rest of the readdir 2307 * operation result must be decoded in the 2308 * case there are following operations 2309 * in the compound request. Therefore, mark 2310 * the rest of the response as "skip" and 2311 * decode or skip the remaining data 2312 */ 2313 entry_length = DIRENT64_RECLEN(namelen); 2314 if (space_left < entry_length) 2315 skip_to_end = 1; 2316 } 2317 2318 /* Get the NAME of the entry */ 2319 if (!skip_to_end) { 2320 if (!xdr_opaque(xdrs, dp->d_name, namelen)) 2321 goto noentries; 2322 bzero(&dp->d_name[namelen], 2323 DIRENT64_NAMELEN(entry_length) - namelen); 2324 dp->d_off = last_cookie = cookie; 2325 dp->d_reclen = entry_length; 2326 } else { 2327 if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &namelen)) 2328 goto noentries; 2329 } 2330 2331 /* Get the attribute BITMAP */ 2332 if (!xdr_bitmap4(xdrs, &resbmap)) 2333 goto noentries; 2334 /* Get the LENGTH of the attributes */ 2335 if (!xdr_u_int(xdrs, (uint_t *)&attrlen)) 2336 goto noentries; 2337 2338 /* Get the ATTRIBUTES */ 2339 if (!skip_to_end) { 2340 uint32_t *ptr; 2341 2342 if (!(resbmap & FATTR4_ACL_MASK) && 2343 (ptr = (uint32_t *)XDR_INLINE(xdrs, attrlen)) 2344 != NULL) { 2345 if (!xdr_ga_fattr_res_inline(ptr, &gar, resbmap, 2346 aobjp->attr_request, aobjp->mi, pug)) 2347 goto noentries; 2348 } else { 2349 if (!xdr_ga_fattr_res(xdrs, &gar, resbmap, 2350 aobjp->attr_request, aobjp->mi, pug)) 2351 goto noentries; 2352 } 2353 2354 /* Fill in the d_ino per the server's fid values */ 2355 /* 2356 * Important to note that the mounted on fileid 2357 * is returned in d_ino if supported. This is 2358 * expected, readdir returns the mounted on fileid 2359 * while stat() returns the fileid of the object 2360 * on "top" of the mount. 2361 */ 2362 if (gar.n4g_mon_fid_valid) 2363 dp->d_ino = gar.n4g_mon_fid; 2364 else if (gar.n4g_va.va_mask & AT_NODEID) 2365 dp->d_ino = gar.n4g_va.va_nodeid; 2366 else 2367 dp->d_ino = 0; 2368 2369 /* See about creating an rnode for this entry */ 2370 if ((resbmap & 2371 (NFS4_VATTR_MASK | FATTR4_FILEHANDLE_MASK)) == 2372 (NFS4_VATTR_MASK | FATTR4_FILEHANDLE_MASK)) { 2373 nfs4_sharedfh_t *sfhp; 2374 vnode_t *vp; 2375 2376 sfhp = sfh4_put(&ges.n4g_fh_u.n4g_fh, 2377 aobjp->mi, NULL); 2378 vp = makenfs4node(sfhp, &gar, 2379 aobjp->dvp->v_vfsp, 2380 aobjp->t, 2381 aobjp->cr, 2382 aobjp->dvp, 2383 fn_get(VTOSV(aobjp->dvp)->sv_name, 2384 dp->d_name, sfhp)); 2385 sfh4_rele(&sfhp); 2386 dnlc_update(aobjp->dvp, dp->d_name, vp); 2387 VN_RELE(vp); 2388 } 2389 2390 dp = (struct dirent64 *)(((caddr_t)dp) + dp->d_reclen); 2391 2392 space_left -= entry_length; 2393 2394 } else { 2395 if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &attrlen)) 2396 goto noentries; 2397 } 2398 2399 /* Get the do-we-have-a-next-entry BOOL */ 2400 if (!xdr_bool(xdrs, &more_data)) 2401 goto noentries; 2402 } 2403 2404 if (pug) { 2405 kmem_free(pug, sizeof (ug_cache_t)); 2406 pug = NULL; 2407 } 2408 2409 /* 2410 * Finish up the rddir cache 2411 * If no entries were returned, free up buffer & 2412 * set ncookie to the starting cookie for this 2413 * readdir request so that the direof caching 2414 * will work properly. 2415 */ 2416 ASSERT(rdc->entries); 2417 if (last_cookie == 0) { 2418 kmem_free(rdc->entries, rdc->entlen); 2419 rdc->entries = NULL; 2420 last_cookie = rdc->nfs4_cookie; 2421 } 2422 2423 rdc->actlen = rdc->entlen - space_left; 2424 rdc->nfs4_ncookie = last_cookie; 2425 2426 /* Get the EOF marker */ 2427 if (!xdr_bool(xdrs, &objp->eof)) 2428 goto noentries; 2429 2430 /* 2431 * If the server returns eof and there were no 2432 * skipped entries, set eof 2433 */ 2434 rdc->eof = (objp->eof && !skip_to_end) ? TRUE : FALSE; 2435 2436 /* 2437 * If we encoded entries we are done 2438 */ 2439 if (rdc->entries) { 2440 rdc->error = 0; 2441 return (TRUE); 2442 } 2443 2444 /* 2445 * If there were no entries and we skipped because 2446 * there was not enough space, return EINVAL 2447 */ 2448 if (skip_to_end) { 2449 rdc->error = EINVAL; 2450 return (TRUE); 2451 } 2452 2453 /* 2454 * No entries, nothing skipped, and EOF, return OK. 2455 */ 2456 if (objp->eof == TRUE) { 2457 rdc->error = 0; 2458 return (TRUE); 2459 } 2460 2461 /* 2462 * No entries, nothing skipped, and not EOF 2463 * probably a bad cookie, return ENOENT. 2464 */ 2465 rdc->error = ENOENT; 2466 return (TRUE); 2467 2468 noentries: 2469 if (rdc->entries) { 2470 kmem_free(rdc->entries, rdc->entlen); 2471 rdc->entries = NULL; 2472 } 2473 if (pug) 2474 kmem_free(pug, sizeof (ug_cache_t)); 2475 rdc->error = EIO; 2476 return (FALSE); 2477 } 2478 2479 /* 2480 * xdr_ga_res 2481 * 2482 * Returns: FALSE on raw data processing errors, TRUE otherwise. 2483 * 2484 * This function pre-processes the OP_GETATTR response, and then 2485 * calls common routines to process the GETATTR fattr4 results into 2486 * vnode attributes and other components that the client is interested 2487 * in. If an error other than an RPC error is encountered, the details 2488 * of the error are filled into objp, although the result of the 2489 * processing is set to TRUE. 2490 */ 2491 static bool_t 2492 xdr_ga_res(XDR *xdrs, GETATTR4res *objp, GETATTR4args *aobjp) 2493 { 2494 #ifdef INLINE 2495 uint32_t *ptr; 2496 #endif 2497 bitmap4 resbmap; 2498 uint32_t attrlen; 2499 2500 ASSERT(xdrs->x_op == XDR_DECODE); 2501 2502 /* Initialize objp attribute error values */ 2503 objp->ga_res.n4g_attrerr = 2504 objp->ga_res.n4g_attrwhy = NFS4_GETATTR_OP_OK; 2505 2506 if (!xdr_bitmap4(xdrs, &resbmap)) 2507 return (FALSE); 2508 2509 /* save the response bitmap for the caller */ 2510 objp->ga_res.n4g_resbmap = resbmap; 2511 2512 /* attrlen */ 2513 if (!XDR_GETINT32(xdrs, (int32_t *)&attrlen)) 2514 return (FALSE); 2515 2516 /* 2517 * Handle case where request and response bitmaps don't match. 2518 */ 2519 if (aobjp->attr_request && aobjp->attr_request != resbmap) { 2520 bitmap4 deltabmap; 2521 2522 /* 2523 * Return error for case where server sent extra attributes 2524 * because the "unknown" attributes may be anywhere in the 2525 * xdr stream and can't be properly processed. 2526 */ 2527 deltabmap = ((aobjp->attr_request ^ resbmap) & resbmap); 2528 if (deltabmap) { 2529 objp->ga_res.n4g_attrerr = EINVAL; 2530 objp->ga_res.n4g_attrwhy = NFS4_GETATTR_BITMAP_ERR; 2531 return (TRUE); 2532 } 2533 2534 /* 2535 * Return error for case where there is a mandatory 2536 * attribute missing in the server response. Note that 2537 * missing recommended attributes are evaluated in the 2538 * specific routines that decode the server response. 2539 */ 2540 deltabmap = ((aobjp->attr_request ^ resbmap) 2541 & aobjp->attr_request); 2542 if ((deltabmap & FATTR4_MANDATTR_MASK)) { 2543 objp->ga_res.n4g_attrerr = EINVAL; 2544 objp->ga_res.n4g_attrwhy = NFS4_GETATTR_MANDATTR_ERR; 2545 return (TRUE); 2546 } 2547 } 2548 2549 /* Check to see if the attrs can be inlined and go for it if so */ 2550 #ifdef INLINE 2551 if (!(resbmap & FATTR4_ACL_MASK) && 2552 (ptr = (uint32_t *)XDR_INLINE(xdrs, attrlen)) != NULL) 2553 return (xdr_ga_fattr_res_inline(ptr, &objp->ga_res, 2554 resbmap, aobjp->attr_request, aobjp->mi, NULL)); 2555 else 2556 #endif 2557 return (xdr_ga_fattr_res(xdrs, &objp->ga_res, 2558 resbmap, aobjp->attr_request, aobjp->mi, NULL)); 2559 } 2560 2561 #if defined(DEBUG) && !defined(lint) 2562 /* 2563 * We assume that an enum is a 32-bit value, check it once 2564 */ 2565 static enum szchk { SZVAL } szchkvar; 2566 #endif 2567 2568 bool_t 2569 xdr_settime4(XDR *xdrs, settime4 *objp) 2570 { 2571 #if defined(DEBUG) && !defined(lint) 2572 ASSERT(sizeof (szchkvar) == sizeof (int32_t)); 2573 #endif 2574 if (xdrs->x_op == XDR_FREE) 2575 return (TRUE); 2576 2577 if (!xdr_int(xdrs, (int *)&objp->set_it)) 2578 return (FALSE); 2579 if (objp->set_it != SET_TO_CLIENT_TIME4) 2580 return (TRUE); 2581 /* xdr_nfstime4 */ 2582 if (!xdr_longlong_t(xdrs, (longlong_t *)&objp->time.seconds)) 2583 return (FALSE); 2584 return (xdr_u_int(xdrs, &objp->time.nseconds)); 2585 } 2586 2587 bool_t 2588 xdr_fattr4(XDR *xdrs, fattr4 *objp) 2589 { 2590 if (xdrs->x_op != XDR_FREE) { 2591 if (!xdr_bitmap4(xdrs, &objp->attrmask)) 2592 return (FALSE); 2593 return (xdr_bytes(xdrs, (char **)&objp->attrlist4, 2594 (uint_t *)&objp->attrlist4_len, NFS4_FATTR4_LIMIT)); 2595 } 2596 2597 /* 2598 * Optimized free case 2599 */ 2600 if (objp->attrlist4 != NULL) 2601 kmem_free(objp->attrlist4, objp->attrlist4_len); 2602 return (TRUE); 2603 } 2604 2605 static bool_t 2606 xdr_ACCESS4res(XDR *xdrs, ACCESS4res *objp) 2607 { 2608 if (!xdr_int(xdrs, (int32_t *)&objp->status)) 2609 return (FALSE); 2610 if (objp->status != NFS4_OK) 2611 return (TRUE); 2612 if (!xdr_u_int(xdrs, &objp->supported)) 2613 return (FALSE); 2614 return (xdr_u_int(xdrs, &objp->access)); 2615 } 2616 2617 static bool_t 2618 xdr_CLOSE4args(XDR *xdrs, CLOSE4args *objp) 2619 { 2620 if (!xdr_u_int(xdrs, &objp->seqid)) 2621 return (FALSE); 2622 if (!xdr_u_int(xdrs, &objp->open_stateid.seqid)) 2623 return (FALSE); 2624 return (xdr_opaque(xdrs, objp->open_stateid.other, NFS4_OTHER_SIZE)); 2625 } 2626 2627 static bool_t 2628 xdr_CLOSE4res(XDR *xdrs, CLOSE4res *objp) 2629 { 2630 if (!xdr_int(xdrs, (int32_t *)&objp->status)) 2631 return (FALSE); 2632 if (objp->status != NFS4_OK) 2633 return (TRUE); 2634 if (!xdr_u_int(xdrs, &objp->open_stateid.seqid)) 2635 return (FALSE); 2636 return (xdr_opaque(xdrs, objp->open_stateid.other, NFS4_OTHER_SIZE)); 2637 } 2638 2639 static bool_t 2640 xdr_CREATE4args(XDR *xdrs, CREATE4args *objp) 2641 { 2642 if (xdrs->x_op != XDR_FREE) { 2643 if (!xdr_int(xdrs, (int32_t *)&objp->type)) 2644 return (FALSE); 2645 switch (objp->type) { 2646 case NF4LNK: 2647 if (!xdr_bytes(xdrs, 2648 (char **)&objp->ftype4_u.linkdata.linktext4_val, 2649 (uint_t *)&objp->ftype4_u.linkdata.linktext4_len, 2650 NFS4_MAX_UTF8STRING)) 2651 return (FALSE); 2652 break; 2653 case NF4BLK: 2654 case NF4CHR: 2655 if (!xdr_u_int(xdrs, &objp->ftype4_u.devdata.specdata1)) 2656 return (FALSE); 2657 if (!xdr_u_int(xdrs, &objp->ftype4_u.devdata.specdata2)) 2658 return (FALSE); 2659 break; 2660 case NF4SOCK: 2661 case NF4FIFO: 2662 case NF4DIR: 2663 default: 2664 break; /* server should return NFS4ERR_BADTYPE */ 2665 } 2666 if (!xdr_bytes(xdrs, (char **)&objp->objname.utf8string_val, 2667 (uint_t *)&objp->objname.utf8string_len, 2668 NFS4_MAX_UTF8STRING)) 2669 return (FALSE); 2670 return (xdr_fattr4(xdrs, &objp->createattrs)); 2671 } 2672 2673 /* 2674 * Optimized free case 2675 */ 2676 if (objp->type == NF4LNK) { 2677 if (objp->ftype4_u.linkdata.linktext4_val != NULL) 2678 kmem_free(objp->ftype4_u.linkdata.linktext4_val, 2679 objp->ftype4_u.linkdata.linktext4_len); 2680 } 2681 if (objp->objname.utf8string_val != NULL) 2682 kmem_free(objp->objname.utf8string_val, 2683 objp->objname.utf8string_len); 2684 return (xdr_fattr4(xdrs, &objp->createattrs)); 2685 } 2686 2687 static bool_t 2688 xdr_CREATE4cargs(XDR *xdrs, CREATE4cargs *objp) 2689 { 2690 int len; 2691 2692 ASSERT(xdrs->x_op == XDR_ENCODE); 2693 2694 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->type)) 2695 return (FALSE); 2696 switch (objp->type) { 2697 case NF4LNK: 2698 len = strlen(objp->ftype4_u.clinkdata); 2699 if (len > NFS4_MAX_UTF8STRING) 2700 return (FALSE); 2701 if (!XDR_PUTINT32(xdrs, &len)) 2702 return (FALSE); 2703 if (!xdr_opaque(xdrs, objp->ftype4_u.clinkdata, len)) 2704 return (FALSE); 2705 break; 2706 case NF4BLK: 2707 case NF4CHR: 2708 if (!XDR_PUTINT32(xdrs, 2709 (int32_t *)&objp->ftype4_u.devdata.specdata1)) 2710 return (FALSE); 2711 if (!XDR_PUTINT32(xdrs, 2712 (int32_t *)&objp->ftype4_u.devdata.specdata2)) 2713 return (FALSE); 2714 break; 2715 case NF4SOCK: 2716 case NF4FIFO: 2717 case NF4DIR: 2718 default: 2719 break; /* server should return NFS4ERR_BADTYPE */ 2720 } 2721 2722 len = strlen(objp->cname); 2723 if (len > NFS4_MAX_UTF8STRING) 2724 return (FALSE); 2725 if (!XDR_PUTINT32(xdrs, &len)) 2726 return (FALSE); 2727 if (!xdr_opaque(xdrs, objp->cname, len)) 2728 return (FALSE); 2729 2730 return (xdr_fattr4(xdrs, &objp->createattrs)); 2731 } 2732 2733 static bool_t 2734 xdr_CREATE4res(XDR *xdrs, CREATE4res *objp) 2735 { 2736 if (!xdr_int(xdrs, (int32_t *)&objp->status)) 2737 return (FALSE); 2738 if (objp->status != NFS4_OK) 2739 return (TRUE); 2740 if (!xdr_bool(xdrs, &objp->cinfo.atomic)) 2741 return (FALSE); 2742 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.before)) 2743 return (FALSE); 2744 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.after)) 2745 return (FALSE); 2746 return (xdr_bitmap4(xdrs, &objp->attrset)); 2747 } 2748 2749 static bool_t 2750 xdr_LINK4res(XDR *xdrs, LINK4res *objp) 2751 { 2752 if (!xdr_int(xdrs, (int32_t *)&objp->status)) 2753 return (FALSE); 2754 if (objp->status != NFS4_OK) 2755 return (TRUE); 2756 if (!xdr_bool(xdrs, &objp->cinfo.atomic)) 2757 return (FALSE); 2758 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.before)) 2759 return (FALSE); 2760 return (xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.after)); 2761 } 2762 2763 static bool_t 2764 xdr_LOCK4args(XDR *xdrs, LOCK4args *objp) 2765 { 2766 if (xdrs->x_op != XDR_FREE) { 2767 if (!xdr_int(xdrs, (int *)&objp->locktype)) 2768 return (FALSE); 2769 if (!xdr_bool(xdrs, &objp->reclaim)) 2770 return (FALSE); 2771 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset)) 2772 return (FALSE); 2773 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->length)) 2774 return (FALSE); 2775 if (!xdr_bool(xdrs, &objp->locker.new_lock_owner)) 2776 return (FALSE); 2777 if (objp->locker.new_lock_owner == TRUE) { 2778 if (!xdr_u_int(xdrs, &objp->locker.locker4_u.open_owner. 2779 open_seqid)) 2780 return (FALSE); 2781 if (!xdr_u_int(xdrs, &objp->locker.locker4_u.open_owner. 2782 open_stateid.seqid)) 2783 return (FALSE); 2784 if (!xdr_opaque(xdrs, objp->locker.locker4_u.open_owner. 2785 open_stateid.other, NFS4_OTHER_SIZE)) 2786 return (FALSE); 2787 if (!xdr_u_int(xdrs, &objp->locker.locker4_u.open_owner. 2788 lock_seqid)) 2789 return (FALSE); 2790 if (!xdr_u_longlong_t(xdrs, 2791 (u_longlong_t *)&objp->locker.locker4_u. 2792 open_owner.lock_owner.clientid)) 2793 return (FALSE); 2794 return (xdr_bytes(xdrs, 2795 (char **)&objp->locker.locker4_u.open_owner. 2796 lock_owner.owner_val, 2797 (uint_t *)&objp->locker.locker4_u.open_owner. 2798 lock_owner.owner_len, 2799 NFS4_OPAQUE_LIMIT)); 2800 } 2801 2802 if (objp->locker.new_lock_owner != FALSE) 2803 return (FALSE); 2804 2805 if (!xdr_u_int(xdrs, &objp->locker.locker4_u.lock_owner. 2806 lock_stateid.seqid)) 2807 return (FALSE); 2808 if (!xdr_opaque(xdrs, objp->locker.locker4_u.lock_owner. 2809 lock_stateid.other, NFS4_OTHER_SIZE)) 2810 return (FALSE); 2811 return (xdr_u_int(xdrs, &objp->locker.locker4_u.lock_owner. 2812 lock_seqid)); 2813 } 2814 2815 /* 2816 * Optimized free case 2817 */ 2818 if (objp->locker.new_lock_owner == TRUE) { 2819 if (objp->locker.locker4_u.open_owner.lock_owner.owner_val != 2820 NULL) { 2821 kmem_free(objp->locker.locker4_u.open_owner.lock_owner. 2822 owner_val, 2823 objp->locker.locker4_u.open_owner.lock_owner. 2824 owner_len); 2825 } 2826 } 2827 2828 return (TRUE); 2829 } 2830 2831 static bool_t 2832 xdr_LOCK4res(XDR *xdrs, LOCK4res *objp) 2833 { 2834 if (xdrs->x_op != XDR_FREE) { 2835 if (!xdr_int(xdrs, (int32_t *)&objp->status)) 2836 return (FALSE); 2837 if (objp->status == NFS4_OK) { 2838 if (!xdr_u_int(xdrs, 2839 &objp->LOCK4res_u.lock_stateid.seqid)) 2840 return (FALSE); 2841 return (xdr_opaque(xdrs, 2842 objp->LOCK4res_u.lock_stateid.other, 2843 NFS4_OTHER_SIZE)); 2844 } 2845 if (objp->status != NFS4ERR_DENIED) 2846 return (TRUE); 2847 2848 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->LOCK4res_u. 2849 denied.offset)) 2850 return (FALSE); 2851 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->LOCK4res_u. 2852 denied.length)) 2853 return (FALSE); 2854 if (!xdr_int(xdrs, (int *)&objp->LOCK4res_u.denied.locktype)) 2855 return (FALSE); 2856 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->LOCK4res_u. 2857 denied.owner.clientid)) 2858 return (FALSE); 2859 return (xdr_bytes(xdrs, 2860 (char **)&objp->LOCK4res_u.denied.owner.owner_val, 2861 (uint_t *)&objp->LOCK4res_u.denied.owner.owner_len, 2862 NFS4_OPAQUE_LIMIT)); 2863 } 2864 2865 /* 2866 * Optimized free case 2867 */ 2868 if (objp->status == NFS4_OK || objp->status != NFS4ERR_DENIED) 2869 return (TRUE); 2870 2871 if (objp->LOCK4res_u.denied.owner.owner_val != NULL) 2872 kmem_free(objp->LOCK4res_u.denied.owner.owner_val, 2873 objp->LOCK4res_u.denied.owner.owner_len); 2874 return (TRUE); 2875 } 2876 2877 static bool_t 2878 xdr_LOCKT4args(XDR *xdrs, LOCKT4args *objp) 2879 { 2880 if (xdrs->x_op != XDR_FREE) { 2881 if (!xdr_int(xdrs, (int *)&objp->locktype)) 2882 return (FALSE); 2883 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset)) 2884 return (FALSE); 2885 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->length)) 2886 return (FALSE); 2887 if (!xdr_u_longlong_t(xdrs, 2888 (u_longlong_t *)&objp->owner.clientid)) 2889 return (FALSE); 2890 return (xdr_bytes(xdrs, (char **)&objp->owner.owner_val, 2891 (uint_t *)&objp->owner.owner_len, 2892 NFS4_OPAQUE_LIMIT)); 2893 } 2894 2895 /* 2896 * Optimized free case 2897 */ 2898 if (objp->owner.owner_val != NULL) 2899 kmem_free(objp->owner.owner_val, objp->owner.owner_len); 2900 return (TRUE); 2901 } 2902 2903 static bool_t 2904 xdr_LOCKT4res(XDR *xdrs, LOCKT4res *objp) 2905 { 2906 if (xdrs->x_op != XDR_FREE) { 2907 if (!xdr_int(xdrs, (int32_t *)&objp->status)) 2908 return (FALSE); 2909 if (objp->status == NFS4_OK) 2910 return (TRUE); 2911 if (objp->status != NFS4ERR_DENIED) 2912 return (TRUE); 2913 /* xdr_LOCK4denied */ 2914 if (!xdr_u_longlong_t(xdrs, 2915 (u_longlong_t *)&objp->denied.offset)) 2916 return (FALSE); 2917 if (!xdr_u_longlong_t(xdrs, 2918 (u_longlong_t *)&objp->denied.length)) 2919 return (FALSE); 2920 if (!xdr_int(xdrs, (int *)&objp->denied.locktype)) 2921 return (FALSE); 2922 if (!xdr_u_longlong_t(xdrs, 2923 (u_longlong_t *)&objp->denied.owner.clientid)) 2924 return (FALSE); 2925 return (xdr_bytes(xdrs, 2926 (char **)&objp->denied.owner.owner_val, 2927 (uint_t *)&objp->denied.owner.owner_len, 2928 NFS4_OPAQUE_LIMIT)); 2929 } 2930 2931 /* 2932 * Optimized free case 2933 */ 2934 if (objp->status == NFS4_OK || objp->status != NFS4ERR_DENIED) 2935 return (TRUE); 2936 if (objp->denied.owner.owner_val != NULL) 2937 kmem_free(objp->denied.owner.owner_val, 2938 objp->denied.owner.owner_len); 2939 return (TRUE); 2940 } 2941 2942 static bool_t 2943 xdr_LOCKU4args(XDR *xdrs, LOCKU4args *objp) 2944 { 2945 if (!xdr_int(xdrs, (int *)&objp->locktype)) 2946 return (FALSE); 2947 if (!xdr_u_int(xdrs, &objp->seqid)) 2948 return (FALSE); 2949 if (!xdr_u_int(xdrs, &objp->lock_stateid.seqid)) 2950 return (FALSE); 2951 if (!xdr_opaque(xdrs, objp->lock_stateid.other, NFS4_OTHER_SIZE)) 2952 return (FALSE); 2953 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset)) 2954 return (FALSE); 2955 return (xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->length)); 2956 } 2957 2958 static bool_t 2959 xdr_share_access(XDR *xdrs, uint32_t *share_access, uint32_t *deleg_want) 2960 { 2961 uint32_t w; 2962 2963 switch (xdrs->x_op) { 2964 case XDR_DECODE: 2965 if (!xdr_u_int(xdrs, &w)) 2966 break; 2967 2968 *share_access = w & OPEN4_SHARE_ACCESS_MASK; 2969 *deleg_want = w & OPEN4_SHARE_WANT_MASK; 2970 return (TRUE); 2971 2972 case XDR_ENCODE: 2973 return (xdr_u_int(xdrs, share_access)); 2974 2975 case XDR_FREE: 2976 return (TRUE); 2977 } 2978 2979 return (FALSE); 2980 } 2981 2982 static bool_t 2983 xdr_OPEN4args(XDR *xdrs, OPEN4args *objp) 2984 { 2985 if (xdrs->x_op != XDR_FREE) { 2986 if (!xdr_u_int(xdrs, &objp->seqid)) 2987 return (FALSE); 2988 if (!xdr_share_access(xdrs, &objp->share_access, 2989 &objp->deleg_want)) 2990 return (FALSE); 2991 if (!xdr_u_int(xdrs, &objp->share_deny)) 2992 return (FALSE); 2993 2994 /* xdr_open_owner4 */ 2995 if (!xdr_u_longlong_t(xdrs, 2996 (u_longlong_t *)&objp->owner.clientid)) 2997 return (FALSE); 2998 if (!xdr_bytes(xdrs, (char **)&objp->owner.owner_val, 2999 (uint_t *)&objp->owner.owner_len, 3000 NFS4_OPAQUE_LIMIT)) 3001 return (FALSE); 3002 3003 /* xdr_openflag4 */ 3004 if (!xdr_int(xdrs, (int *)&objp->opentype)) 3005 return (FALSE); 3006 if (objp->opentype == OPEN4_CREATE) { 3007 3008 /* xdr_createhow4 */ 3009 if (!xdr_int(xdrs, (int *)&objp->mode)) 3010 return (FALSE); 3011 switch (objp->mode) { 3012 case UNCHECKED4: 3013 case GUARDED4: 3014 if (!xdr_fattr4(xdrs, 3015 &objp->createhow4_u.createattrs)) 3016 return (FALSE); 3017 break; 3018 case EXCLUSIVE4: 3019 if (!xdr_u_longlong_t(xdrs, 3020 (u_longlong_t *)&objp->createhow4_u. 3021 createverf)) 3022 return (FALSE); 3023 break; 3024 case EXCLUSIVE4_1: 3025 if (!xdr_creatverfattr(xdrs, 3026 &objp->createhow4_u.ch_createboth)) 3027 return (FALSE); 3028 break; 3029 default: 3030 return (FALSE); 3031 } 3032 } 3033 3034 /* xdr_open_claim4 */ 3035 if (!xdr_open_claim4(xdrs, &objp->claim)) 3036 return (FALSE); 3037 3038 return (TRUE); 3039 } 3040 3041 /* 3042 * Optimized free case 3043 */ 3044 if (objp->owner.owner_val != NULL) 3045 kmem_free(objp->owner.owner_val, objp->owner.owner_len); 3046 3047 if (objp->opentype == OPEN4_CREATE) { 3048 switch (objp->mode) { 3049 case UNCHECKED4: 3050 case GUARDED4: 3051 (void) xdr_fattr4(xdrs, 3052 &objp->createhow4_u.createattrs); 3053 break; 3054 case EXCLUSIVE4: 3055 default: 3056 break; 3057 } 3058 } 3059 3060 (void) xdr_open_claim4(xdrs, &objp->claim); 3061 return (TRUE); 3062 } 3063 3064 static bool_t 3065 xdr_OPEN4cargs(XDR *xdrs, OPEN4cargs *objp) 3066 { 3067 int op; 3068 int len; 3069 rpc_inline_t *ptr; 3070 3071 ASSERT(xdrs->x_op == XDR_ENCODE); 3072 3073 /* 3074 * We must always define the client's open_owner to be 3075 * 4 byte aligned and sized. 3076 */ 3077 ASSERT(objp->owner.owner_len <= NFS4_OPAQUE_LIMIT); 3078 ASSERT(!(objp->owner.owner_len % BYTES_PER_XDR_UNIT)); 3079 3080 len = objp->owner.owner_len; 3081 if ((ptr = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT + len)) != NULL) { 3082 int i; 3083 int32_t *ip; 3084 3085 IXDR_PUT_U_INT32(ptr, OP_OPEN); 3086 IXDR_PUT_U_INT32(ptr, objp->seqid); 3087 IXDR_PUT_U_INT32(ptr, objp->share_access); 3088 IXDR_PUT_U_INT32(ptr, objp->share_deny); 3089 3090 /* xdr_open_owner4 */ 3091 IXDR_PUT_HYPER(ptr, objp->owner.clientid); 3092 IXDR_PUT_U_INT32(ptr, objp->owner.owner_len); 3093 /* We know this is very short so don't bcopy */ 3094 ip = (int32_t *)objp->owner.owner_val; 3095 len /= BYTES_PER_XDR_UNIT; 3096 for (i = 0; i < len; i++) 3097 *ptr++ = *ip++; 3098 3099 /* xdr_openflag4 */ 3100 IXDR_PUT_U_INT32(ptr, objp->opentype); 3101 } else { 3102 op = OP_OPEN; 3103 if (!XDR_PUTINT32(xdrs, (int32_t *)&op)) 3104 return (FALSE); 3105 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->seqid)) 3106 return (FALSE); 3107 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->share_access)) 3108 return (FALSE); 3109 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->share_deny)) 3110 return (FALSE); 3111 3112 /* xdr_open_owner4 */ 3113 if (!xdr_u_longlong_t(xdrs, 3114 (u_longlong_t *)&objp->owner.clientid)) 3115 return (FALSE); 3116 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->owner.owner_len)) 3117 return (FALSE); 3118 if (!xdr_opaque(xdrs, objp->owner.owner_val, 3119 objp->owner.owner_len)) 3120 return (FALSE); 3121 3122 /* xdr_openflag4 */ 3123 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->opentype)) 3124 return (FALSE); 3125 } 3126 3127 if (objp->opentype == OPEN4_CREATE) { 3128 /* xdr_createhow4 */ 3129 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->mode)) 3130 return (FALSE); 3131 switch (objp->mode) { 3132 case UNCHECKED4: 3133 case GUARDED4: 3134 if (!xdr_fattr4(xdrs, 3135 &objp->createhow4_u.createattrs)) 3136 return (FALSE); 3137 break; 3138 case EXCLUSIVE4: 3139 if (!xdr_u_longlong_t(xdrs, 3140 (u_longlong_t *)&objp->createhow4_u. 3141 createverf)) 3142 return (FALSE); 3143 break; 3144 default: 3145 return (FALSE); 3146 } 3147 } 3148 3149 /* xdr_open_claim4 */ 3150 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->claim)) 3151 return (FALSE); 3152 3153 switch (objp->claim) { 3154 case CLAIM_NULL: 3155 len = strlen(objp->open_claim4_u.cfile); 3156 if (len > NFS4_MAX_UTF8STRING) 3157 return (FALSE); 3158 if (XDR_PUTINT32(xdrs, &len)) { 3159 return (xdr_opaque(xdrs, 3160 objp->open_claim4_u.cfile, len)); 3161 } 3162 return (FALSE); 3163 case CLAIM_PREVIOUS: 3164 return (XDR_PUTINT32(xdrs, 3165 (int32_t *)&objp->open_claim4_u.delegate_type)); 3166 case CLAIM_DELEGATE_CUR: 3167 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->open_claim4_u. 3168 delegate_cur_info.delegate_stateid.seqid)) 3169 return (FALSE); 3170 if (!xdr_opaque(xdrs, objp->open_claim4_u. 3171 delegate_cur_info.delegate_stateid.other, 3172 NFS4_OTHER_SIZE)) 3173 return (FALSE); 3174 len = strlen(objp->open_claim4_u.delegate_cur_info.cfile); 3175 if (len > NFS4_MAX_UTF8STRING) 3176 return (FALSE); 3177 if (XDR_PUTINT32(xdrs, &len)) { 3178 return (xdr_opaque(xdrs, 3179 objp->open_claim4_u.delegate_cur_info.cfile, 3180 len)); 3181 } 3182 return (FALSE); 3183 case CLAIM_DELEGATE_PREV: 3184 len = strlen(objp->open_claim4_u.cfile_delegate_prev); 3185 if (len > NFS4_MAX_UTF8STRING) 3186 return (FALSE); 3187 if (XDR_PUTINT32(xdrs, &len)) { 3188 return (xdr_opaque(xdrs, 3189 objp->open_claim4_u.cfile_delegate_prev, len)); 3190 } 3191 return (FALSE); 3192 default: 3193 return (FALSE); 3194 } 3195 } 3196 3197 static bool_t 3198 xdr_OPEN4res(XDR *xdrs, OPEN4res *objp) 3199 { 3200 if (xdrs->x_op != XDR_FREE) { 3201 if (!xdr_int(xdrs, (int32_t *)&objp->status)) 3202 return (FALSE); 3203 if (objp->status != NFS4_OK) 3204 return (TRUE); 3205 if (!xdr_u_int(xdrs, &objp->stateid.seqid)) 3206 return (FALSE); 3207 if (!xdr_opaque(xdrs, objp->stateid.other, NFS4_OTHER_SIZE)) 3208 return (FALSE); 3209 if (!xdr_bool(xdrs, &objp->cinfo.atomic)) 3210 return (FALSE); 3211 if (!xdr_u_longlong_t(xdrs, 3212 (u_longlong_t *)&objp->cinfo.before)) 3213 return (FALSE); 3214 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.after)) 3215 return (FALSE); 3216 if (!xdr_u_int(xdrs, &objp->rflags)) 3217 return (FALSE); 3218 if (!xdr_bitmap4(xdrs, &objp->attrset)) 3219 return (FALSE); 3220 if (!xdr_int(xdrs, 3221 (int *)&objp->delegation.delegation_type)) 3222 return (FALSE); 3223 switch (objp->delegation.delegation_type) { 3224 case OPEN_DELEGATE_NONE: 3225 return (TRUE); 3226 case OPEN_DELEGATE_READ: 3227 if (!xdr_u_int(xdrs, &objp->delegation. 3228 open_delegation4_u.read.stateid.seqid)) 3229 return (FALSE); 3230 if (!xdr_opaque(xdrs, objp->delegation. 3231 open_delegation4_u.read.stateid.other, 3232 NFS4_OTHER_SIZE)) 3233 return (FALSE); 3234 if (!xdr_bool(xdrs, &objp->delegation. 3235 open_delegation4_u.read.recall)) 3236 return (FALSE); 3237 return (xdr_nfsace4(xdrs, &objp->delegation. 3238 open_delegation4_u.read.permissions)); 3239 case OPEN_DELEGATE_WRITE: 3240 if (!xdr_u_int(xdrs, &objp->delegation. 3241 open_delegation4_u.write.stateid.seqid)) 3242 return (FALSE); 3243 if (!xdr_opaque(xdrs, objp->delegation. 3244 open_delegation4_u.write.stateid.other, 3245 NFS4_OTHER_SIZE)) 3246 return (FALSE); 3247 if (!xdr_bool(xdrs, &objp->delegation. 3248 open_delegation4_u.write.recall)) 3249 return (FALSE); 3250 if (!xdr_int(xdrs, (int *)&objp->delegation. 3251 open_delegation4_u.write.space_limit. 3252 limitby)) 3253 return (FALSE); 3254 switch (objp->delegation. 3255 open_delegation4_u.write.space_limit. 3256 limitby) { 3257 case NFS_LIMIT_SIZE: 3258 if (!xdr_u_longlong_t(xdrs, 3259 (u_longlong_t *)&objp->delegation. 3260 open_delegation4_u.write.space_limit. 3261 nfs_space_limit4_u.filesize)) 3262 return (FALSE); 3263 break; 3264 case NFS_LIMIT_BLOCKS: 3265 if (!xdr_u_int(xdrs, 3266 &objp->delegation.open_delegation4_u.write. 3267 space_limit.nfs_space_limit4_u. 3268 mod_blocks.num_blocks)) 3269 return (FALSE); 3270 if (!xdr_u_int(xdrs, &objp->delegation. 3271 open_delegation4_u.write.space_limit. 3272 nfs_space_limit4_u.mod_blocks. 3273 bytes_per_block)) 3274 return (FALSE); 3275 break; 3276 default: 3277 return (FALSE); 3278 } 3279 return (xdr_nfsace4(xdrs, &objp->delegation. 3280 open_delegation4_u.write.permissions)); 3281 } 3282 return (FALSE); 3283 } 3284 3285 /* 3286 * Optimized free case 3287 */ 3288 if (objp->status != NFS4_OK) 3289 return (TRUE); 3290 3291 switch (objp->delegation.delegation_type) { 3292 case OPEN_DELEGATE_NONE: 3293 return (TRUE); 3294 case OPEN_DELEGATE_READ: 3295 return (xdr_nfsace4(xdrs, &objp->delegation. 3296 open_delegation4_u.read.permissions)); 3297 case OPEN_DELEGATE_WRITE: 3298 switch (objp->delegation. 3299 open_delegation4_u.write.space_limit.limitby) { 3300 case NFS_LIMIT_SIZE: 3301 case NFS_LIMIT_BLOCKS: 3302 break; 3303 default: 3304 return (FALSE); 3305 } 3306 return (xdr_nfsace4(xdrs, &objp->delegation. 3307 open_delegation4_u.write.permissions)); 3308 } 3309 return (FALSE); 3310 } 3311 3312 static bool_t 3313 xdr_OPEN_CONFIRM4res(XDR *xdrs, OPEN_CONFIRM4res *objp) 3314 { 3315 if (!xdr_int(xdrs, (int32_t *)&objp->status)) 3316 return (FALSE); 3317 if (objp->status != NFS4_OK) 3318 return (TRUE); 3319 if (!xdr_u_int(xdrs, &objp->open_stateid.seqid)) 3320 return (FALSE); 3321 return (xdr_opaque(xdrs, objp->open_stateid.other, NFS4_OTHER_SIZE)); 3322 } 3323 3324 static bool_t 3325 xdr_OPEN_DOWNGRADE4args(XDR *xdrs, OPEN_DOWNGRADE4args *objp) 3326 { 3327 if (!xdr_u_int(xdrs, &objp->open_stateid.seqid)) 3328 return (FALSE); 3329 if (!xdr_opaque(xdrs, objp->open_stateid.other, NFS4_OTHER_SIZE)) 3330 return (FALSE); 3331 if (!xdr_u_int(xdrs, &objp->seqid)) 3332 return (FALSE); 3333 if (!xdr_share_access(xdrs, &objp->share_access, &objp->deleg_want)) 3334 return (FALSE); 3335 return (xdr_u_int(xdrs, &objp->share_deny)); 3336 } 3337 3338 static bool_t 3339 xdr_OPEN_DOWNGRADE4res(XDR *xdrs, OPEN_DOWNGRADE4res *objp) 3340 { 3341 if (!xdr_int(xdrs, (int32_t *)&objp->status)) 3342 return (FALSE); 3343 if (objp->status != NFS4_OK) 3344 return (TRUE); 3345 if (!xdr_u_int(xdrs, &objp->open_stateid.seqid)) 3346 return (FALSE); 3347 return (xdr_opaque(xdrs, objp->open_stateid.other, NFS4_OTHER_SIZE)); 3348 } 3349 3350 static bool_t 3351 xdr_READ4args(XDR *xdrs, READ4args *objp) 3352 { 3353 rdma_chunkinfo_t rci; 3354 rdma_wlist_conn_info_t rwci; 3355 struct xdr_ops *xops = xdrrdma_xops(); 3356 3357 if (!xdr_u_int(xdrs, &objp->stateid.seqid)) 3358 return (FALSE); 3359 if (!xdr_opaque(xdrs, objp->stateid.other, NFS4_OTHER_SIZE)) 3360 return (FALSE); 3361 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset)) 3362 return (FALSE); 3363 if (!xdr_u_int(xdrs, &objp->count)) 3364 return (FALSE); 3365 3366 DTRACE_PROBE1(xdr__i__read4args_buf_len, 3367 int, objp->count); 3368 3369 objp->wlist = NULL; 3370 3371 if (xdrs->x_ops == xops && xdrs->x_op == XDR_ENCODE) { 3372 rci.rci_type = RCI_WRITE_ADDR_CHUNK; 3373 rci.rci_len = objp->count; 3374 (void) XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci); 3375 } 3376 3377 if (xdrs->x_ops != &xdrrdma_ops || xdrs->x_op == XDR_FREE) 3378 return (TRUE); 3379 3380 if (xdrs->x_op == XDR_ENCODE) { 3381 if (objp->res_uiop != NULL) { 3382 rci.rci_type = RCI_WRITE_UIO_CHUNK; 3383 rci.rci_a.rci_uiop = objp->res_uiop; 3384 rci.rci_len = objp->count; 3385 rci.rci_clpp = &objp->wlist; 3386 } else { 3387 rci.rci_type = RCI_WRITE_ADDR_CHUNK; 3388 rci.rci_a.rci_addr = objp->res_data_val_alt; 3389 rci.rci_len = objp->count; 3390 rci.rci_clpp = &objp->wlist; 3391 } 3392 3393 return (XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci)); 3394 } 3395 3396 /* XDR_DECODE case */ 3397 (void) XDR_CONTROL(xdrs, XDR_RDMA_GET_WCINFO, &rwci); 3398 objp->wlist = rwci.rwci_wlist; 3399 objp->conn = rwci.rwci_conn; 3400 3401 return (TRUE); 3402 } 3403 3404 static bool_t 3405 xdr_READ4res(XDR *xdrs, READ4res *objp) 3406 { 3407 mblk_t *mp; 3408 3409 if (xdrs->x_op == XDR_DECODE) 3410 return (FALSE); 3411 3412 if (xdrs->x_op == XDR_FREE) { 3413 /* 3414 * Optimized free case 3415 */ 3416 if (objp->status != NFS4_OK) 3417 return (TRUE); 3418 if (objp->data_val != NULL) 3419 kmem_free(objp->data_val, objp->data_len); 3420 return (TRUE); 3421 } 3422 3423 /* on with ENCODE paths */ 3424 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->status)) 3425 return (FALSE); 3426 if (objp->status != NFS4_OK) 3427 return (TRUE); 3428 3429 if (!XDR_PUTINT32(xdrs, &objp->eof)) 3430 return (FALSE); 3431 3432 mp = objp->mblk; 3433 if (mp != NULL) { 3434 if (xdrs->x_ops == &xdrmblk_ops) { 3435 if (xdrmblk_putmblk(xdrs, mp, objp->data_len)) { 3436 objp->mblk = NULL; 3437 return (TRUE); 3438 } else { 3439 return (FALSE); 3440 } 3441 } else if (mp->b_cont != NULL) { 3442 /* 3443 * See xdr_READ3res() for an explanation of why we need 3444 * to do a pullup here. 3445 */ 3446 if (pullupmsg(mp, -1) == 0) 3447 return (FALSE); 3448 objp->data_val = (caddr_t)mp->b_rptr; 3449 } 3450 } else { 3451 if (xdr_u_int(xdrs, &objp->data_len) == FALSE) { 3452 return (FALSE); 3453 } 3454 /* 3455 * If read data sent by wlist (RDMA_WRITE), don't do 3456 * xdr_bytes() below. RDMA_WRITE transfers the data. 3457 * Note: this is encode-only because the client code 3458 * uses xdr_READ4res_clnt to decode results. 3459 */ 3460 if (objp->wlist) { 3461 if (objp->data_len != 0) { 3462 return (xdrrdma_send_read_data( 3463 xdrs, objp->data_len, objp->wlist)); 3464 } 3465 return (TRUE); 3466 } 3467 } 3468 3469 return (xdr_bytes(xdrs, (char **)&objp->data_val, 3470 (uint_t *)&objp->data_len, 3471 objp->data_len)); 3472 } 3473 3474 static bool_t 3475 xdr_READ4res_clnt(XDR *xdrs, READ4res *objp, READ4args *aobjp) 3476 { 3477 mblk_t *mp; 3478 size_t n; 3479 int error; 3480 uint_t size = aobjp->res_maxsize; 3481 count4 ocount; 3482 3483 if (xdrs->x_op == XDR_ENCODE) 3484 return (FALSE); 3485 3486 if (xdrs->x_op == XDR_FREE) { 3487 /* 3488 * Optimized free case 3489 */ 3490 if (objp->status != NFS4_OK) 3491 return (TRUE); 3492 if (objp->data_val != NULL) 3493 kmem_free(objp->data_val, objp->data_len); 3494 return (TRUE); 3495 } 3496 3497 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->status)) 3498 return (FALSE); 3499 if (objp->status != NFS4_OK) 3500 return (TRUE); 3501 3502 if (!XDR_GETINT32(xdrs, &objp->eof)) 3503 return (FALSE); 3504 3505 3506 /* 3507 * This is a special case such that the caller is providing a 3508 * uio as a guide to eventual data location; this is used for 3509 * handling DIRECTIO reads. 3510 */ 3511 if (aobjp->res_uiop != NULL) { 3512 struct uio *uiop = aobjp->res_uiop; 3513 int32_t *ptr; 3514 3515 if (xdrs->x_ops == &xdrmblk_ops) { 3516 if (!xdrmblk_getmblk(xdrs, &mp, &objp->data_len)) 3517 return (FALSE); 3518 3519 if (objp->data_len == 0) 3520 return (TRUE); 3521 3522 if (objp->data_len > size) 3523 return (FALSE); 3524 3525 size = objp->data_len; 3526 do { 3527 n = MIN(size, mp->b_wptr - mp->b_rptr); 3528 if ((n = MIN(uiop->uio_resid, n)) != 0) { 3529 3530 error = uiomove((char *)mp->b_rptr, n, 3531 UIO_READ, uiop); 3532 if (error) 3533 return (FALSE); 3534 mp->b_rptr += n; 3535 size -= n; 3536 } 3537 3538 while (mp && (mp->b_rptr >= mp->b_wptr)) 3539 mp = mp->b_cont; 3540 } while (mp && size > 0 && uiop->uio_resid > 0); 3541 3542 return (TRUE); 3543 } 3544 3545 if (xdrs->x_ops == &xdrrdma_ops) { 3546 struct clist *cl; 3547 3548 XDR_CONTROL(xdrs, XDR_RDMA_GET_WLIST, &cl); 3549 3550 objp->wlist = cl; 3551 3552 if (objp->wlist) { 3553 /* opaque count */ 3554 if (!xdr_u_int(xdrs, &ocount)) { 3555 objp->wlist = NULL; 3556 return (FALSE); 3557 } 3558 3559 objp->wlist_len = clist_len(cl); 3560 objp->data_len = ocount; 3561 3562 if (objp->wlist_len != 3563 roundup( 3564 objp->data_len, BYTES_PER_XDR_UNIT)) { 3565 DTRACE_PROBE2( 3566 xdr__e__read4resuio_clnt_fail, 3567 int, ocount, 3568 int, objp->data_len); 3569 objp->wlist = NULL; 3570 return (FALSE); 3571 } 3572 3573 uiop->uio_resid -= objp->data_len; 3574 uiop->uio_iov->iov_len -= objp->data_len; 3575 uiop->uio_iov->iov_base += objp->data_len; 3576 uiop->uio_loffset += objp->data_len; 3577 3578 objp->wlist = NULL; 3579 return (TRUE); 3580 } 3581 } 3582 3583 /* 3584 * This isn't an xdrmblk stream nor RDMA. 3585 * Handle the likely case that it can be 3586 * inlined (ex. xdrmem). 3587 */ 3588 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->data_len)) 3589 return (FALSE); 3590 3591 if (objp->data_len == 0) 3592 return (TRUE); 3593 3594 if (objp->data_len > size) 3595 return (FALSE); 3596 3597 size = (int)objp->data_len; 3598 if ((ptr = XDR_INLINE(xdrs, size)) != NULL) 3599 return (uiomove(ptr, size, UIO_READ, uiop) ? 3600 FALSE : TRUE); 3601 3602 /* 3603 * Handle some other (unlikely) stream type that will 3604 * need a copy. 3605 */ 3606 if ((ptr = kmem_alloc(size, KM_NOSLEEP)) == NULL) 3607 return (FALSE); 3608 3609 if (!XDR_GETBYTES(xdrs, (caddr_t)ptr, size)) { 3610 kmem_free(ptr, size); 3611 return (FALSE); 3612 } 3613 error = uiomove(ptr, size, UIO_READ, uiop); 3614 kmem_free(ptr, size); 3615 3616 return (error ? FALSE : TRUE); 3617 } 3618 3619 /* 3620 * Check for the other special case of the caller providing 3621 * the target area for the data. 3622 */ 3623 if (aobjp->res_data_val_alt == NULL) 3624 return (FALSE); 3625 3626 /* 3627 * If read data received via RDMA_WRITE, don't do xdr_bytes(). 3628 * RDMA_WRITE already moved the data so decode length of 3629 * RDMA_WRITE. 3630 */ 3631 if (xdrs->x_ops == &xdrrdma_ops) { 3632 struct clist *cl; 3633 3634 XDR_CONTROL(xdrs, XDR_RDMA_GET_WLIST, &cl); 3635 3636 objp->wlist = cl; 3637 3638 /* 3639 * Data transferred through inline if 3640 * objp->wlist == NULL 3641 */ 3642 if (objp->wlist) { 3643 /* opaque count */ 3644 if (!xdr_u_int(xdrs, &ocount)) { 3645 objp->wlist = NULL; 3646 return (FALSE); 3647 } 3648 3649 objp->wlist_len = clist_len(cl); 3650 objp->data_len = ocount; 3651 3652 if (objp->wlist_len != 3653 roundup( 3654 objp->data_len, BYTES_PER_XDR_UNIT)) { 3655 DTRACE_PROBE2( 3656 xdr__e__read4res_clnt_fail, 3657 int, ocount, 3658 int, objp->data_len); 3659 objp->wlist = NULL; 3660 return (FALSE); 3661 } 3662 3663 objp->wlist = NULL; 3664 return (TRUE); 3665 } 3666 } 3667 3668 return (xdr_bytes(xdrs, (char **)&aobjp->res_data_val_alt, 3669 (uint_t *)&objp->data_len, 3670 aobjp->res_maxsize)); 3671 } 3672 3673 static bool_t 3674 xdr_READDIR4args(XDR *xdrs, READDIR4args *objp) 3675 { 3676 rdma_chunkinfo_t rci; 3677 struct xdr_ops *xops = xdrrdma_xops(); 3678 3679 if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) && 3680 xdrs->x_op == XDR_ENCODE) { 3681 rci.rci_type = RCI_REPLY_CHUNK; 3682 rci.rci_len = objp->maxcount; 3683 XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci); 3684 } 3685 3686 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cookie)) 3687 return (FALSE); 3688 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cookieverf)) 3689 return (FALSE); 3690 if (!xdr_u_int(xdrs, &objp->dircount)) 3691 return (FALSE); 3692 if (!xdr_u_int(xdrs, &objp->maxcount)) 3693 return (FALSE); 3694 return (xdr_bitmap4(xdrs, &objp->attr_request)); 3695 } 3696 3697 bool_t 3698 xdr_READDIR4res(XDR *xdrs, READDIR4res *objp) 3699 { 3700 mblk_t *mp = objp->mblk; 3701 bool_t ret_val; 3702 uint_t flags = 0; 3703 3704 ASSERT(xdrs->x_op == XDR_ENCODE); 3705 3706 if (!xdr_int(xdrs, (int32_t *)&objp->status)) 3707 return (FALSE); 3708 if (objp->status != NFS4_OK) 3709 return (TRUE); 3710 if (mp == NULL) 3711 return (FALSE); 3712 3713 if (xdrs->x_ops == &xdrmblk_ops) { 3714 if (xdrmblk_putmblk_raw(xdrs, mp) 3715 == TRUE) { 3716 /* mblk successfully inserted into outgoing chain */ 3717 objp->mblk = NULL; 3718 return (TRUE); 3719 } 3720 } 3721 3722 ASSERT(mp->b_cont == NULL); 3723 3724 /* 3725 * If transport is RDMA, the pre-encoded m_blk needs to be moved 3726 * without being chunked. 3727 * Check if chunking is enabled for the xdr stream. 3728 * If it is enabled, disable it temporarily for this op, 3729 * then re-enable. 3730 */ 3731 XDR_CONTROL(xdrs, XDR_RDMA_GET_FLAGS, &flags); 3732 3733 if (!(flags & XDR_RDMA_CHUNK)) 3734 return (xdr_opaque(xdrs, (char *)mp->b_rptr, objp->data_len)); 3735 3736 flags &= ~XDR_RDMA_CHUNK; 3737 3738 (void) XDR_CONTROL(xdrs, XDR_RDMA_SET_FLAGS, &flags); 3739 3740 ret_val = xdr_opaque(xdrs, (char *)mp->b_rptr, objp->data_len); 3741 3742 flags |= XDR_RDMA_CHUNK; 3743 3744 (void) XDR_CONTROL(xdrs, XDR_RDMA_SET_FLAGS, &flags); 3745 3746 return (ret_val); 3747 } 3748 3749 static bool_t 3750 xdr_READLINK4res(XDR *xdrs, READLINK4res *objp) 3751 { 3752 if (xdrs->x_op != XDR_FREE) { 3753 if (!xdr_int(xdrs, (int32_t *)&objp->status)) 3754 return (FALSE); 3755 if (objp->status != NFS4_OK) 3756 return (TRUE); 3757 return (xdr_bytes(xdrs, (char **)&objp->link.linktext4_val, 3758 (uint_t *)&objp->link.linktext4_len, 3759 NFS4_MAX_UTF8STRING)); 3760 } 3761 3762 /* 3763 * Optimized free case 3764 */ 3765 if (objp->status != NFS4_OK) 3766 return (TRUE); 3767 if (objp->link.linktext4_val != NULL) 3768 kmem_free(objp->link.linktext4_val, objp->link.linktext4_len); 3769 return (TRUE); 3770 } 3771 3772 static bool_t 3773 xdr_REMOVE4res(XDR *xdrs, REMOVE4res *objp) 3774 { 3775 if (!xdr_int(xdrs, (int32_t *)&objp->status)) 3776 return (FALSE); 3777 if (objp->status != NFS4_OK) 3778 return (TRUE); 3779 if (!xdr_bool(xdrs, &objp->cinfo.atomic)) 3780 return (FALSE); 3781 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.before)) 3782 return (FALSE); 3783 return (xdr_u_longlong_t(xdrs, 3784 (u_longlong_t *)&objp->cinfo.after)); 3785 } 3786 3787 static bool_t 3788 xdr_RENAME4res(XDR *xdrs, RENAME4res *objp) 3789 { 3790 if (!xdr_int(xdrs, (int32_t *)&objp->status)) 3791 return (FALSE); 3792 if (objp->status != NFS4_OK) 3793 return (TRUE); 3794 if (!xdr_bool(xdrs, &objp->source_cinfo.atomic)) 3795 return (FALSE); 3796 if (!xdr_u_longlong_t(xdrs, 3797 (u_longlong_t *)&objp->source_cinfo.before)) 3798 return (FALSE); 3799 if (!xdr_u_longlong_t(xdrs, 3800 (u_longlong_t *)&objp->source_cinfo.after)) 3801 return (FALSE); 3802 if (!xdr_bool(xdrs, &objp->target_cinfo.atomic)) 3803 return (FALSE); 3804 if (!xdr_u_longlong_t(xdrs, 3805 (u_longlong_t *)&objp->target_cinfo.before)) 3806 return (FALSE); 3807 return (xdr_u_longlong_t(xdrs, 3808 (u_longlong_t *)&objp->target_cinfo.after)); 3809 } 3810 3811 static bool_t 3812 xdr_secinfo4(XDR *xdrs, secinfo4 *objp) 3813 { 3814 if (xdrs->x_op != XDR_FREE) { 3815 if (!xdr_u_int(xdrs, &objp->flavor)) 3816 return (FALSE); 3817 if (objp->flavor != RPCSEC_GSS) 3818 return (TRUE); 3819 if (!xdr_bytes(xdrs, 3820 (char **)&objp->flavor_info.oid.sec_oid4_val, 3821 (uint_t *)&objp->flavor_info.oid.sec_oid4_len, 3822 NFS4_MAX_SECOID4)) 3823 return (FALSE); 3824 if (!xdr_u_int(xdrs, &objp->flavor_info.qop)) 3825 return (FALSE); 3826 return (xdr_int(xdrs, (int *)&objp->flavor_info.service)); 3827 } 3828 3829 /* 3830 * Optimized free path 3831 */ 3832 if (objp->flavor != RPCSEC_GSS) 3833 return (TRUE); 3834 3835 if (objp->flavor_info.oid.sec_oid4_val != NULL) 3836 kmem_free(objp->flavor_info.oid.sec_oid4_val, 3837 objp->flavor_info.oid.sec_oid4_len); 3838 return (TRUE); 3839 } 3840 3841 bool_t 3842 xdr_SECINFO4res(XDR *xdrs, SECINFO4res *objp) 3843 { 3844 if (!xdr_int(xdrs, (int32_t *)&objp->status)) 3845 return (FALSE); 3846 if (objp->status != NFS4_OK) 3847 return (TRUE); 3848 return (xdr_array(xdrs, (char **)&objp->SECINFO4resok_val, 3849 (uint_t *)&objp->SECINFO4resok_len, ~0, sizeof (secinfo4), 3850 (xdrproc_t)xdr_secinfo4)); 3851 } 3852 3853 static bool_t 3854 xdr_SETCLIENTID4args(XDR *xdrs, SETCLIENTID4args *objp) 3855 { 3856 if (xdrs->x_op != XDR_FREE) { 3857 if (!xdr_u_longlong_t(xdrs, 3858 (u_longlong_t *)&objp->client.verifier)) 3859 return (FALSE); 3860 if (!xdr_bytes(xdrs, (char **)&objp->client.id_val, 3861 (uint_t *)&objp->client.id_len, NFS4_OPAQUE_LIMIT)) 3862 return (FALSE); 3863 if (!xdr_u_int(xdrs, &objp->callback.cb_program)) 3864 return (FALSE); 3865 if (!xdr_string(xdrs, &objp->callback.cb_location.r_netid, 3866 NFS4_OPAQUE_LIMIT)) 3867 return (FALSE); 3868 if (!xdr_string(xdrs, &objp->callback.cb_location.r_addr, 3869 NFS4_OPAQUE_LIMIT)) 3870 return (FALSE); 3871 return (xdr_u_int(xdrs, &objp->callback_ident)); 3872 } 3873 3874 /* 3875 * Optimized free case 3876 */ 3877 if (objp->client.id_val != NULL) 3878 kmem_free(objp->client.id_val, objp->client.id_len); 3879 (void) xdr_string(xdrs, &objp->callback.cb_location.r_netid, 3880 NFS4_OPAQUE_LIMIT); 3881 return (xdr_string(xdrs, &objp->callback.cb_location.r_addr, 3882 NFS4_OPAQUE_LIMIT)); 3883 } 3884 3885 static bool_t 3886 xdr_SETCLIENTID4res(XDR *xdrs, SETCLIENTID4res *objp) 3887 { 3888 if (xdrs->x_op != XDR_FREE) { 3889 if (!xdr_int(xdrs, (int32_t *)&objp->status)) 3890 return (FALSE); 3891 switch (objp->status) { 3892 case NFS4_OK: 3893 if (!xdr_u_longlong_t(xdrs, 3894 (u_longlong_t *)&objp->SETCLIENTID4res_u.resok4. 3895 clientid)) 3896 return (FALSE); 3897 return (xdr_u_longlong_t(xdrs, 3898 (u_longlong_t *)&objp->SETCLIENTID4res_u. 3899 resok4.setclientid_confirm)); 3900 case NFS4ERR_CLID_INUSE: 3901 if (!xdr_string(xdrs, 3902 &objp->SETCLIENTID4res_u.client_using. 3903 r_netid, NFS4_OPAQUE_LIMIT)) 3904 return (FALSE); 3905 return (xdr_string(xdrs, 3906 &objp->SETCLIENTID4res_u.client_using. 3907 r_addr, NFS4_OPAQUE_LIMIT)); 3908 } 3909 return (TRUE); 3910 } 3911 3912 /* 3913 * Optimized free case 3914 */ 3915 if (objp->status != NFS4ERR_CLID_INUSE) 3916 return (TRUE); 3917 3918 if (!xdr_string(xdrs, &objp->SETCLIENTID4res_u.client_using.r_netid, 3919 NFS4_OPAQUE_LIMIT)) 3920 return (FALSE); 3921 return (xdr_string(xdrs, &objp->SETCLIENTID4res_u.client_using.r_addr, 3922 NFS4_OPAQUE_LIMIT)); 3923 } 3924 3925 static bool_t 3926 xdr_WRITE4args(XDR *xdrs, WRITE4args *objp) 3927 { 3928 if (xdrs->x_op != XDR_FREE) { 3929 if (!xdr_u_int(xdrs, &objp->stateid.seqid)) 3930 return (FALSE); 3931 if (!xdr_opaque(xdrs, objp->stateid.other, NFS4_OTHER_SIZE)) 3932 return (FALSE); 3933 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset)) 3934 return (FALSE); 3935 if (!xdr_int(xdrs, (int *)&objp->stable)) 3936 return (FALSE); 3937 if (xdrs->x_op == XDR_DECODE) { 3938 if (xdrs->x_ops == &xdrmblk_ops) { 3939 objp->data_val = NULL; 3940 return (xdrmblk_getmblk(xdrs, &objp->mblk, 3941 &objp->data_len)); 3942 } 3943 objp->mblk = NULL; 3944 if (xdrs->x_ops == &xdrrdmablk_ops) { 3945 int retval; 3946 retval = xdrrdma_getrdmablk(xdrs, 3947 &objp->rlist, 3948 &objp->data_len, 3949 &objp->conn, NFS4_DATA_LIMIT); 3950 if (retval == FALSE) 3951 return (FALSE); 3952 return (xdrrdma_read_from_client(objp->rlist, 3953 &objp->conn, objp->data_len)); 3954 } 3955 } 3956 /* Else fall thru for the xdr_bytes(). */ 3957 return (xdr_bytes(xdrs, (char **)&objp->data_val, 3958 (uint_t *)&objp->data_len, NFS4_DATA_LIMIT)); 3959 } 3960 if (objp->rlist != NULL) { 3961 (void) xdrrdma_free_clist(objp->conn, objp->rlist); 3962 objp->rlist = NULL; 3963 objp->data_val = NULL; 3964 3965 return (TRUE); 3966 } 3967 3968 /* 3969 * Optimized free case 3970 */ 3971 if (objp->data_val != NULL) 3972 kmem_free(objp->data_val, objp->data_len); 3973 return (TRUE); 3974 } 3975 3976 static bool_t 3977 xdr_WRITE4res(XDR *xdrs, WRITE4res *objp) 3978 { 3979 if (!xdr_int(xdrs, (int32_t *)&objp->status)) 3980 return (FALSE); 3981 if (objp->status != NFS4_OK) 3982 return (TRUE); 3983 if (!xdr_u_int(xdrs, &objp->count)) 3984 return (FALSE); 3985 if (!xdr_int(xdrs, (int *)&objp->committed)) 3986 return (FALSE); 3987 return (xdr_u_longlong_t(xdrs, 3988 (u_longlong_t *)&objp->writeverf)); 3989 } 3990 3991 static bool_t 3992 xdr_snfs_argop4_free(XDR *xdrs, nfs_argop4 **arrayp, int len) 3993 { 3994 int i; 3995 nfs_argop4 *array = *arrayp; 3996 3997 /* 3998 * Optimized XDR_FREE only args array 3999 */ 4000 ASSERT(xdrs->x_op == XDR_FREE); 4001 4002 /* 4003 * Nothing to do? 4004 */ 4005 if (array == NULL) 4006 return (TRUE); 4007 4008 for (i = 0; i < len; i++) { 4009 /* Freeing for nfs4.x */ 4010 if (array[i].argop >= OP_BACKCHANNEL_CTL && 4011 array[i].argop != OP_ILLEGAL) { 4012 xdr_nfs4x_argop4(xdrs, &array[i]); 4013 continue; 4014 } 4015 4016 /* 4017 * These should be ordered by frequency of use 4018 */ 4019 switch (array[i].argop) { 4020 case OP_PUTFH: { 4021 nfs_fh4 *objp = &array[i].nfs_argop4_u.opputfh.object; 4022 4023 if (objp->nfs_fh4_val != NULL) { 4024 kmem_free(objp->nfs_fh4_val, objp->nfs_fh4_len); 4025 } 4026 continue; 4027 } 4028 case OP_GETATTR: 4029 case OP_GETFH: 4030 continue; 4031 case OP_LOOKUP: 4032 if (array[i].nfs_argop4_u.oplookup.objname. 4033 utf8string_val != NULL) { 4034 kmem_free(array[i].nfs_argop4_u.oplookup. 4035 objname.utf8string_val, 4036 array[i].nfs_argop4_u.oplookup. 4037 objname.utf8string_len); 4038 } 4039 continue; 4040 case OP_OPEN: 4041 (void) xdr_OPEN4args(xdrs, 4042 &array[i].nfs_argop4_u.opopen); 4043 continue; 4044 case OP_CLOSE: 4045 case OP_ACCESS: 4046 case OP_READ: 4047 continue; 4048 case OP_WRITE: 4049 (void) xdr_WRITE4args(xdrs, 4050 &array[i].nfs_argop4_u.opwrite); 4051 continue; 4052 case OP_DELEGRETURN: 4053 case OP_LOOKUPP: 4054 case OP_READDIR: 4055 continue; 4056 case OP_REMOVE: 4057 if (array[i].nfs_argop4_u.opremove.target. 4058 utf8string_val != NULL) { 4059 kmem_free(array[i].nfs_argop4_u.opremove.target. 4060 utf8string_val, 4061 array[i].nfs_argop4_u.opremove.target. 4062 utf8string_len); 4063 } 4064 continue; 4065 case OP_COMMIT: 4066 continue; 4067 case OP_CREATE: 4068 (void) xdr_CREATE4args(xdrs, 4069 &array[i].nfs_argop4_u.opcreate); 4070 continue; 4071 case OP_DELEGPURGE: 4072 continue; 4073 case OP_LINK: 4074 if (array[i].nfs_argop4_u.oplink.newname. 4075 utf8string_val != NULL) { 4076 kmem_free(array[i].nfs_argop4_u.oplink.newname. 4077 utf8string_val, 4078 array[i].nfs_argop4_u.oplink.newname. 4079 utf8string_len); 4080 } 4081 continue; 4082 case OP_LOCK: 4083 (void) xdr_LOCK4args(xdrs, 4084 &array[i].nfs_argop4_u.oplock); 4085 continue; 4086 case OP_LOCKT: 4087 (void) xdr_LOCKT4args(xdrs, 4088 &array[i].nfs_argop4_u.oplockt); 4089 continue; 4090 case OP_LOCKU: 4091 continue; 4092 case OP_NVERIFY: 4093 (void) xdr_fattr4(xdrs, 4094 &array[i].nfs_argop4_u.opnverify.obj_attributes); 4095 continue; 4096 case OP_OPENATTR: 4097 case OP_OPEN_CONFIRM: 4098 case OP_OPEN_DOWNGRADE: 4099 case OP_PUTPUBFH: 4100 case OP_PUTROOTFH: 4101 case OP_READLINK: 4102 continue; 4103 case OP_RENAME: 4104 if (array[i].nfs_argop4_u.oprename.oldname. 4105 utf8string_val != NULL) { 4106 kmem_free(array[i].nfs_argop4_u.oprename. 4107 oldname.utf8string_val, 4108 array[i].nfs_argop4_u.oprename. 4109 oldname.utf8string_len); 4110 } 4111 if (array[i].nfs_argop4_u.oprename.newname. 4112 utf8string_val != NULL) { 4113 kmem_free(array[i].nfs_argop4_u.oprename. 4114 newname.utf8string_val, 4115 array[i].nfs_argop4_u.oprename. 4116 newname.utf8string_len); 4117 } 4118 continue; 4119 case OP_RENEW: 4120 case OP_RESTOREFH: 4121 case OP_SAVEFH: 4122 continue; 4123 case OP_SECINFO: 4124 if (array[i].nfs_argop4_u.opsecinfo.name. 4125 utf8string_val != NULL) { 4126 kmem_free(array[i].nfs_argop4_u.opsecinfo.name. 4127 utf8string_val, 4128 array[i].nfs_argop4_u.opsecinfo.name. 4129 utf8string_len); 4130 } 4131 continue; 4132 case OP_SETATTR: 4133 (void) xdr_fattr4(xdrs, 4134 &array[i].nfs_argop4_u.opsetattr.obj_attributes); 4135 continue; 4136 case OP_SETCLIENTID: 4137 (void) xdr_SETCLIENTID4args(xdrs, 4138 &array[i].nfs_argop4_u.opsetclientid); 4139 continue; 4140 case OP_SETCLIENTID_CONFIRM: 4141 continue; 4142 case OP_VERIFY: 4143 (void) xdr_fattr4(xdrs, 4144 &array[i].nfs_argop4_u.opverify.obj_attributes); 4145 continue; 4146 case OP_RELEASE_LOCKOWNER: 4147 if (array[i].nfs_argop4_u.oprelease_lockowner. 4148 lock_owner.owner_val != NULL) { 4149 kmem_free(array[i].nfs_argop4_u. 4150 oprelease_lockowner.lock_owner.owner_val, 4151 array[i].nfs_argop4_u. 4152 oprelease_lockowner.lock_owner.owner_len); 4153 } 4154 continue; 4155 case OP_ILLEGAL: 4156 continue; 4157 default: 4158 /* 4159 * An invalid op is a coding error, it should never 4160 * have been decoded. 4161 * Don't error because the caller cannot finish 4162 * freeing the residual memory of the array. 4163 */ 4164 continue; 4165 } 4166 } 4167 4168 kmem_free(*arrayp, len * sizeof (nfs_argop4)); 4169 *arrayp = NULL; 4170 return (TRUE); 4171 } 4172 4173 static bool_t 4174 xdr_nfs_argop4(XDR *xdrs, nfs_argop4 *objp) 4175 { 4176 rdma_chunkinfo_t rci; 4177 struct xdr_ops *xops = xdrrdma_xops(); 4178 4179 /* 4180 * These should be ordered by frequency of use 4181 */ 4182 switch (objp->argop) { 4183 case OP_PUTFH: 4184 return (xdr_bytes(xdrs, 4185 (char **)&objp->nfs_argop4_u.opputfh.object.nfs_fh4_val, 4186 (uint_t *)&objp->nfs_argop4_u.opputfh.object.nfs_fh4_len, 4187 NFS4_FHSIZE)); 4188 case OP_GETATTR: 4189 /* 4190 * ACLs can become relatively large ( > 8K) and the default 4191 * 8K reply chunk of RDMA may not suffice. Check for 4192 * get ACL bit and if it's RDMA, add a chunk equal the size 4193 * of the transfer size to the reply chunk list. 4194 */ 4195 if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) && 4196 (xdrs->x_op == XDR_ENCODE) && 4197 (objp->nfs_argop4_u.opgetattr.attr_request & 4198 FATTR4_ACL_MASK)) { 4199 rci.rci_type = RCI_REPLY_CHUNK; 4200 rci.rci_len = objp->nfs_argop4_u.opgetattr.mi->mi_tsize; 4201 XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci); 4202 4203 DTRACE_PROBE1(xdr__i__argop4__getattr, int, 4204 rci.rci_len); 4205 } 4206 return (xdr_bitmap4(xdrs, 4207 &objp->nfs_argop4_u.opgetattr.attr_request)); 4208 case OP_GETFH: 4209 return (TRUE); 4210 case OP_LOOKUP: 4211 return (xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.oplookup. 4212 objname.utf8string_val, 4213 (uint_t *)&objp->nfs_argop4_u.oplookup. 4214 objname.utf8string_len, 4215 NFS4_MAX_UTF8STRING)); 4216 case OP_OPEN: 4217 return (xdr_OPEN4args(xdrs, &objp->nfs_argop4_u.opopen)); 4218 case OP_CLOSE: 4219 return (xdr_CLOSE4args(xdrs, &objp->nfs_argop4_u.opclose)); 4220 case OP_ACCESS: 4221 return (xdr_u_int(xdrs, 4222 &objp->nfs_argop4_u.opaccess.access)); 4223 case OP_READ: 4224 return (xdr_READ4args(xdrs, &objp->nfs_argop4_u.opread)); 4225 case OP_WRITE: 4226 return (xdr_WRITE4args(xdrs, &objp->nfs_argop4_u.opwrite)); 4227 case OP_DELEGRETURN: 4228 if (!xdr_u_int(xdrs, 4229 &objp->nfs_argop4_u.opdelegreturn.deleg_stateid.seqid)) 4230 return (FALSE); 4231 return (xdr_opaque(xdrs, 4232 objp->nfs_argop4_u.opdelegreturn.deleg_stateid.other, 4233 NFS4_OTHER_SIZE)); 4234 case OP_LOOKUPP: 4235 return (TRUE); 4236 case OP_READDIR: 4237 return (xdr_READDIR4args(xdrs, &objp->nfs_argop4_u.opreaddir)); 4238 case OP_REMOVE: 4239 return (xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.opremove. 4240 target.utf8string_val, 4241 (uint_t *)&objp->nfs_argop4_u.opremove. 4242 target.utf8string_len, 4243 NFS4_MAX_UTF8STRING)); 4244 case OP_COMMIT: 4245 if (!xdr_u_longlong_t(xdrs, 4246 (u_longlong_t *)&objp->nfs_argop4_u.opcommit.offset)) 4247 return (FALSE); 4248 return (xdr_u_int(xdrs, &objp->nfs_argop4_u.opcommit.count)); 4249 case OP_CREATE: 4250 return (xdr_CREATE4args(xdrs, &objp->nfs_argop4_u.opcreate)); 4251 case OP_DELEGPURGE: 4252 return (xdr_u_longlong_t(xdrs, 4253 (u_longlong_t *)&objp->nfs_argop4_u.opdelegpurge.clientid)); 4254 case OP_LINK: 4255 return (xdr_bytes(xdrs, 4256 (char **)&objp->nfs_argop4_u.oplink.newname.utf8string_val, 4257 (uint_t *)&objp->nfs_argop4_u.oplink.newname.utf8string_len, 4258 NFS4_MAX_UTF8STRING)); 4259 case OP_LOCK: 4260 return (xdr_LOCK4args(xdrs, &objp->nfs_argop4_u.oplock)); 4261 case OP_LOCKT: 4262 return (xdr_LOCKT4args(xdrs, &objp->nfs_argop4_u.oplockt)); 4263 case OP_LOCKU: 4264 return (xdr_LOCKU4args(xdrs, &objp->nfs_argop4_u.oplocku)); 4265 case OP_NVERIFY: 4266 return (xdr_fattr4(xdrs, 4267 &objp->nfs_argop4_u.opnverify.obj_attributes)); 4268 case OP_OPENATTR: 4269 return (xdr_bool(xdrs, 4270 &objp->nfs_argop4_u.opopenattr.createdir)); 4271 case OP_OPEN_CONFIRM: 4272 if (!xdr_u_int(xdrs, &objp->nfs_argop4_u.opopen_confirm. 4273 open_stateid.seqid)) 4274 return (FALSE); 4275 if (!xdr_opaque(xdrs, objp->nfs_argop4_u.opopen_confirm. 4276 open_stateid.other, NFS4_OTHER_SIZE)) 4277 return (FALSE); 4278 return (xdr_u_int(xdrs, &objp->nfs_argop4_u.opopen_confirm. 4279 seqid)); 4280 case OP_OPEN_DOWNGRADE: 4281 return (xdr_OPEN_DOWNGRADE4args(xdrs, 4282 &objp->nfs_argop4_u.opopen_downgrade)); 4283 case OP_PUTPUBFH: 4284 return (TRUE); 4285 case OP_PUTROOTFH: 4286 return (TRUE); 4287 case OP_READLINK: 4288 if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) && 4289 xdrs->x_op == XDR_ENCODE) { 4290 rci.rci_type = RCI_REPLY_CHUNK; 4291 rci.rci_len = MAXPATHLEN; 4292 XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci); 4293 } 4294 return (TRUE); 4295 case OP_RENAME: 4296 if (!xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.oprename. 4297 oldname.utf8string_val, 4298 (uint_t *)&objp->nfs_argop4_u.oprename. 4299 oldname.utf8string_len, 4300 NFS4_MAX_UTF8STRING)) 4301 return (FALSE); 4302 return (xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.oprename. 4303 newname.utf8string_val, 4304 (uint_t *)&objp->nfs_argop4_u.oprename. 4305 newname.utf8string_len, 4306 NFS4_MAX_UTF8STRING)); 4307 case OP_RENEW: 4308 return (xdr_u_longlong_t(xdrs, 4309 (u_longlong_t *)&objp->nfs_argop4_u.oprenew.clientid)); 4310 case OP_RESTOREFH: 4311 return (TRUE); 4312 case OP_SAVEFH: 4313 return (TRUE); 4314 case OP_SECINFO: 4315 return (xdr_bytes(xdrs, 4316 (char **)&objp->nfs_argop4_u.opsecinfo.name.utf8string_val, 4317 (uint_t *)&objp->nfs_argop4_u.opsecinfo.name.utf8string_len, 4318 NFS4_MAX_UTF8STRING)); 4319 case OP_SETATTR: 4320 if (!xdr_u_int(xdrs, &objp->nfs_argop4_u.opsetattr. 4321 stateid.seqid)) 4322 return (FALSE); 4323 if (!xdr_opaque(xdrs, objp->nfs_argop4_u.opsetattr. 4324 stateid.other, NFS4_OTHER_SIZE)) 4325 return (FALSE); 4326 return (xdr_fattr4(xdrs, &objp->nfs_argop4_u.opsetattr. 4327 obj_attributes)); 4328 case OP_SETCLIENTID: 4329 return (xdr_SETCLIENTID4args(xdrs, 4330 &objp->nfs_argop4_u.opsetclientid)); 4331 case OP_SETCLIENTID_CONFIRM: 4332 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->nfs_argop4_u. 4333 opsetclientid_confirm.clientid)) 4334 return (FALSE); 4335 return (xdr_u_longlong_t(xdrs, 4336 (u_longlong_t *)&objp->nfs_argop4_u. 4337 opsetclientid_confirm.setclientid_confirm)); 4338 case OP_VERIFY: 4339 return (xdr_fattr4(xdrs, 4340 &objp->nfs_argop4_u.opverify.obj_attributes)); 4341 case OP_RELEASE_LOCKOWNER: 4342 if (!xdr_u_longlong_t(xdrs, 4343 (u_longlong_t *)&objp->nfs_argop4_u. 4344 oprelease_lockowner.lock_owner.clientid)) 4345 return (FALSE); 4346 return (xdr_bytes(xdrs, 4347 (char **)&objp->nfs_argop4_u.oprelease_lockowner. 4348 lock_owner.owner_val, 4349 (uint_t *)&objp->nfs_argop4_u.oprelease_lockowner. 4350 lock_owner.owner_len, NFS4_OPAQUE_LIMIT)); 4351 case OP_ILLEGAL: 4352 return (TRUE); 4353 } 4354 return (FALSE); 4355 } 4356 4357 static bool_t 4358 xdr_cnfs_argop4_wrap(XDR *xdrs, nfs_argop4 *objp) 4359 { 4360 if (!xdr_int(xdrs, (int *)&objp->argop)) 4361 return (FALSE); 4362 4363 return (xdr_nfs_argop4(xdrs, objp)); 4364 } 4365 4366 static bool_t 4367 xdr_snfs_argop4(XDR *xdrs, nfs_argop4 *objp) 4368 { 4369 if (!xdr_int(xdrs, (int *)&objp->argop)) 4370 return (FALSE); 4371 4372 switch (objp->argop) { 4373 case OP_PUTFH: 4374 return (xdr_decode_nfs_fh4(xdrs, 4375 &objp->nfs_argop4_u.opputfh.object)); 4376 default: 4377 if (objp->argop >= OP_BACKCHANNEL_CTL && 4378 objp->argop != OP_ILLEGAL) 4379 return (xdr_nfs4x_argop4(xdrs, objp)); 4380 4381 return (xdr_nfs_argop4(xdrs, objp)); 4382 } 4383 } 4384 4385 /* 4386 * Client side encode only arg op processing 4387 */ 4388 static bool_t 4389 xdr_cnfs_argop4(XDR *xdrs, nfs_argop4 *objp) 4390 { 4391 int len; 4392 int op; 4393 nfs4_sharedfh_t *sfh; 4394 mntinfo4_t *mi; 4395 rpc_inline_t *ptr; 4396 4397 ASSERT(xdrs->x_op == XDR_ENCODE); 4398 4399 /* 4400 * Special case the private pseudo ops 4401 */ 4402 if (!(objp->argop & SUNW_PRIVATE_OP)) 4403 return (xdr_cnfs_argop4_wrap(xdrs, objp)); 4404 4405 /* 4406 * These should be ordered by frequency of use 4407 */ 4408 switch (objp->argop) { 4409 case OP_CPUTFH: 4410 /* 4411 * We are passed in the file handle as a nfs4_sharedfh_t * 4412 * We need to acquire the correct locks so we can copy it out. 4413 */ 4414 sfh = (nfs4_sharedfh_t *)objp->nfs_argop4_u.opcputfh.sfh; 4415 mi = sfh->sfh_mi; 4416 (void) nfs_rw_enter_sig(&mi->mi_fh_lock, RW_READER, 0); 4417 4418 len = sfh->sfh_fh.nfs_fh4_len; 4419 ASSERT(len <= NFS4_FHSIZE); 4420 4421 /* 4422 * First try and inline the copy 4423 * Must first be a multiple of BYTES_PER_XDR_UNIT 4424 */ 4425 if (!(len % BYTES_PER_XDR_UNIT) && 4426 (ptr = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT + len)) != 4427 NULL) { 4428 IXDR_PUT_U_INT32(ptr, OP_PUTFH); 4429 IXDR_PUT_U_INT32(ptr, len); 4430 bcopy(sfh->sfh_fh.nfs_fh4_val, ptr, len); 4431 nfs_rw_exit(&mi->mi_fh_lock); 4432 return (TRUE); 4433 } 4434 4435 op = OP_PUTFH; 4436 if (!XDR_PUTINT32(xdrs, &op)) { 4437 nfs_rw_exit(&mi->mi_fh_lock); 4438 return (FALSE); 4439 } 4440 if (!XDR_PUTINT32(xdrs, &len)) { 4441 nfs_rw_exit(&mi->mi_fh_lock); 4442 return (FALSE); 4443 } 4444 if (!(len % BYTES_PER_XDR_UNIT)) { 4445 if (XDR_PUTBYTES(xdrs, sfh->sfh_fh.nfs_fh4_val, len)) { 4446 nfs_rw_exit(&mi->mi_fh_lock); 4447 return (TRUE); 4448 } 4449 } else if (xdr_opaque(xdrs, sfh->sfh_fh.nfs_fh4_val, len)) { 4450 nfs_rw_exit(&mi->mi_fh_lock); 4451 return (TRUE); 4452 } 4453 nfs_rw_exit(&mi->mi_fh_lock); 4454 return (FALSE); 4455 case OP_CLOOKUP: 4456 len = strlen(objp->nfs_argop4_u.opclookup.cname); 4457 if (len > NFS4_MAX_UTF8STRING) 4458 return (FALSE); 4459 op = OP_LOOKUP; 4460 if (XDR_PUTINT32(xdrs, &op)) { 4461 if (XDR_PUTINT32(xdrs, &len)) { 4462 return (xdr_opaque(xdrs, 4463 objp->nfs_argop4_u.opclookup.cname, 4464 len)); 4465 } 4466 } 4467 return (FALSE); 4468 case OP_COPEN: 4469 /* op processing inlined in xdr_OPEN4cargs */ 4470 return (xdr_OPEN4cargs(xdrs, &objp->nfs_argop4_u.opcopen)); 4471 case OP_CREMOVE: 4472 len = strlen(objp->nfs_argop4_u.opcremove.ctarget); 4473 if (len > NFS4_MAX_UTF8STRING) 4474 return (FALSE); 4475 op = OP_REMOVE; 4476 if (XDR_PUTINT32(xdrs, &op)) { 4477 if (XDR_PUTINT32(xdrs, &len)) { 4478 return (xdr_opaque(xdrs, 4479 objp->nfs_argop4_u.opcremove.ctarget, 4480 len)); 4481 } 4482 } 4483 return (FALSE); 4484 case OP_CCREATE: 4485 op = OP_CREATE; 4486 if (!XDR_PUTINT32(xdrs, &op)) 4487 return (FALSE); 4488 return (xdr_CREATE4cargs(xdrs, &objp->nfs_argop4_u.opccreate)); 4489 case OP_CLINK: 4490 len = strlen(objp->nfs_argop4_u.opclink.cnewname); 4491 if (len > NFS4_MAX_UTF8STRING) 4492 return (FALSE); 4493 op = OP_LINK; 4494 if (XDR_PUTINT32(xdrs, &op)) { 4495 if (XDR_PUTINT32(xdrs, &len)) { 4496 return (xdr_opaque(xdrs, 4497 objp->nfs_argop4_u.opclink.cnewname, 4498 len)); 4499 } 4500 } 4501 return (FALSE); 4502 case OP_CRENAME: 4503 len = strlen(objp->nfs_argop4_u.opcrename.coldname); 4504 if (len > NFS4_MAX_UTF8STRING) 4505 return (FALSE); 4506 op = OP_RENAME; 4507 if (!XDR_PUTINT32(xdrs, &op)) 4508 return (FALSE); 4509 if (!XDR_PUTINT32(xdrs, &len)) 4510 return (FALSE); 4511 if (!xdr_opaque(xdrs, 4512 objp->nfs_argop4_u.opcrename.coldname, len)) 4513 return (FALSE); 4514 len = strlen(objp->nfs_argop4_u.opcrename.cnewname); 4515 if (len > NFS4_MAX_UTF8STRING) 4516 return (FALSE); 4517 if (XDR_PUTINT32(xdrs, &len)) { 4518 return (xdr_opaque(xdrs, 4519 objp->nfs_argop4_u.opcrename.cnewname, len)); 4520 } 4521 return (FALSE); 4522 case OP_CSECINFO: 4523 len = strlen(objp->nfs_argop4_u.opcsecinfo.cname); 4524 if (len > NFS4_MAX_UTF8STRING) 4525 return (FALSE); 4526 op = OP_SECINFO; 4527 if (XDR_PUTINT32(xdrs, &op)) { 4528 if (XDR_PUTINT32(xdrs, &len)) { 4529 return (xdr_opaque(xdrs, 4530 objp->nfs_argop4_u.opcsecinfo.cname, 4531 len)); 4532 } 4533 } 4534 return (FALSE); 4535 } 4536 return (FALSE); 4537 } 4538 4539 /* 4540 * Note that the len and decode_len will only be different in the case 4541 * of the client's use of this free function. If the server is 4542 * freeing results, then the len/decode_len will always match. 4543 */ 4544 static bool_t 4545 xdr_nfs_resop4_free(XDR *xdrs, nfs_resop4 **arrayp, int len, int decode_len) 4546 { 4547 int i; 4548 nfs_resop4 *array = *arrayp; 4549 nfs4_ga_res_t *gr; 4550 4551 /* 4552 * Optimized XDR_FREE only results array 4553 */ 4554 ASSERT(xdrs->x_op == XDR_FREE); 4555 4556 if (array == NULL) 4557 return (TRUE); 4558 4559 for (i = 0; i < decode_len; i++) { 4560 /* 4561 * These should be ordered by frequency of use 4562 */ 4563 switch (array[i].resop) { 4564 case OP_PUTFH: 4565 continue; 4566 case OP_GETATTR: 4567 if (array[i].nfs_resop4_u.opgetattr.status != NFS4_OK) 4568 continue; 4569 4570 gr = &array[i].nfs_resop4_u.opgetattr.ga_res; 4571 if (gr->n4g_ext_res) { 4572 if (gr->n4g_resbmap & FATTR4_FS_LOCATIONS_MASK) 4573 (void) xdr_fattr4_fs_locations(xdrs, 4574 &gr->n4g_ext_res->n4g_fslocations); 4575 kmem_free(gr->n4g_ext_res, 4576 sizeof (struct nfs4_ga_ext_res)); 4577 } 4578 continue; 4579 case OP_GETFH: 4580 if (array[i].nfs_resop4_u.opgetfh.status != NFS4_OK) 4581 continue; 4582 if (array[i].nfs_resop4_u.opgetfh.object.nfs_fh4_val != 4583 NULL) { 4584 kmem_free(array[i].nfs_resop4_u.opgetfh.object. 4585 nfs_fh4_val, 4586 array[i].nfs_resop4_u.opgetfh.object. 4587 nfs_fh4_len); 4588 } 4589 continue; 4590 case OP_LOOKUP: 4591 continue; 4592 case OP_OPEN: 4593 (void) xdr_OPEN4res(xdrs, &array[i].nfs_resop4_u. 4594 opopen); 4595 continue; 4596 case OP_CLOSE: 4597 case OP_ACCESS: 4598 continue; 4599 case OP_READ: 4600 (void) xdr_READ4res(xdrs, 4601 &array[i].nfs_resop4_u.opread); 4602 continue; 4603 case OP_WRITE: 4604 case OP_DELEGRETURN: 4605 case OP_LOOKUPP: 4606 case OP_READDIR: 4607 case OP_REMOVE: 4608 case OP_COMMIT: 4609 case OP_CREATE: 4610 case OP_DELEGPURGE: 4611 case OP_LINK: 4612 continue; 4613 case OP_LOCK: 4614 (void) xdr_LOCK4res(xdrs, &array[i].nfs_resop4_u. 4615 oplock); 4616 continue; 4617 case OP_LOCKT: 4618 (void) xdr_LOCKT4res(xdrs, &array[i].nfs_resop4_u. 4619 oplockt); 4620 continue; 4621 case OP_LOCKU: 4622 case OP_NVERIFY: 4623 case OP_OPENATTR: 4624 case OP_OPEN_CONFIRM: 4625 case OP_OPEN_DOWNGRADE: 4626 case OP_PUTPUBFH: 4627 case OP_PUTROOTFH: 4628 case OP_RENAME: 4629 case OP_RENEW: 4630 case OP_RESTOREFH: 4631 case OP_SAVEFH: 4632 continue; 4633 case OP_READLINK: 4634 (void) xdr_READLINK4res(xdrs, &array[i].nfs_resop4_u. 4635 opreadlink); 4636 continue; 4637 case OP_SECINFO: 4638 (void) xdr_array(xdrs, 4639 (char **)&array[i].nfs_resop4_u.opsecinfo. 4640 SECINFO4resok_val, 4641 (uint_t *)&array[i].nfs_resop4_u.opsecinfo. 4642 SECINFO4resok_len, 4643 NFS4_SECINFO_LIMIT, sizeof (secinfo4), 4644 (xdrproc_t)xdr_secinfo4); 4645 continue; 4646 case OP_SETCLIENTID: 4647 (void) xdr_SETCLIENTID4res(xdrs, 4648 &array[i].nfs_resop4_u.opsetclientid); 4649 continue; 4650 case OP_SETATTR: 4651 case OP_SETCLIENTID_CONFIRM: 4652 case OP_VERIFY: 4653 case OP_RELEASE_LOCKOWNER: 4654 case OP_ILLEGAL: 4655 continue; 4656 default: 4657 /* 4658 * An invalid op is a coding error, it should never 4659 * have been decoded. 4660 * Don't error because the caller cannot finish 4661 * freeing the residual memory of the array. 4662 */ 4663 continue; 4664 } 4665 } 4666 4667 kmem_free(*arrayp, len * sizeof (nfs_resop4)); 4668 *arrayp = NULL; 4669 return (TRUE); 4670 } 4671 4672 static bool_t 4673 xdr_snfs_resop4_free(XDR *xdrs, nfs_resop4 **arrayp, int len, int decode_len) 4674 { 4675 return (xdr_nfs_resop4_free(xdrs, arrayp, len, decode_len)); 4676 } 4677 4678 static bool_t 4679 xdr_nfs_resop4(XDR *xdrs, nfs_resop4 *objp) 4680 { 4681 /* 4682 * These should be ordered by frequency of use 4683 */ 4684 switch (objp->resop) { 4685 case OP_PUTFH: 4686 return (xdr_int(xdrs, 4687 (int32_t *)&objp->nfs_resop4_u.opputfh.status)); 4688 case OP_GETATTR: 4689 if (!xdr_int(xdrs, 4690 (int32_t *)&objp->nfs_resop4_u.opgetattr.status)) 4691 return (FALSE); 4692 if (objp->nfs_resop4_u.opgetattr.status != NFS4_OK) 4693 return (TRUE); 4694 return (xdr_fattr4(xdrs, 4695 &objp->nfs_resop4_u.opgetattr.obj_attributes)); 4696 case OP_GETFH: 4697 if (!xdr_int(xdrs, 4698 (int32_t *)&objp->nfs_resop4_u.opgetfh.status)) 4699 return (FALSE); 4700 if (objp->nfs_resop4_u.opgetfh.status != NFS4_OK) 4701 return (TRUE); 4702 return (xdr_bytes(xdrs, 4703 (char **)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_val, 4704 (uint_t *)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_len, 4705 NFS4_FHSIZE)); 4706 case OP_LOOKUP: 4707 return (xdr_int(xdrs, 4708 (int32_t *)&objp->nfs_resop4_u.oplookup.status)); 4709 case OP_OPEN: 4710 return (xdr_OPEN4res(xdrs, &objp->nfs_resop4_u.opopen)); 4711 case OP_CLOSE: 4712 return (xdr_CLOSE4res(xdrs, &objp->nfs_resop4_u.opclose)); 4713 case OP_ACCESS: 4714 return (xdr_ACCESS4res(xdrs, &objp->nfs_resop4_u.opaccess)); 4715 case OP_READ: 4716 return (xdr_READ4res(xdrs, &objp->nfs_resop4_u.opread)); 4717 case OP_WRITE: 4718 return (xdr_WRITE4res(xdrs, &objp->nfs_resop4_u.opwrite)); 4719 case OP_DELEGRETURN: 4720 return (xdr_int(xdrs, 4721 (int32_t *)&objp->nfs_resop4_u.opdelegreturn.status)); 4722 case OP_LOOKUPP: 4723 return (xdr_int(xdrs, 4724 (int32_t *)&objp->nfs_resop4_u.oplookupp.status)); 4725 case OP_READDIR: 4726 return (xdr_READDIR4res(xdrs, &objp->nfs_resop4_u.opreaddir)); 4727 case OP_REMOVE: 4728 return (xdr_REMOVE4res(xdrs, &objp->nfs_resop4_u.opremove)); 4729 4730 case OP_COMMIT: 4731 if (!xdr_int(xdrs, 4732 (int32_t *)&objp->nfs_resop4_u.opcommit.status)) 4733 return (FALSE); 4734 if (objp->nfs_resop4_u.opcommit.status != NFS4_OK) 4735 return (TRUE); 4736 return (xdr_u_longlong_t(xdrs, 4737 (u_longlong_t *)&objp->nfs_resop4_u.opcommit. 4738 writeverf)); 4739 case OP_CREATE: 4740 return (xdr_CREATE4res(xdrs, &objp->nfs_resop4_u.opcreate)); 4741 case OP_DELEGPURGE: 4742 return (xdr_int(xdrs, 4743 (int32_t *)&objp->nfs_resop4_u.opdelegpurge.status)); 4744 case OP_LINK: 4745 return (xdr_LINK4res(xdrs, &objp->nfs_resop4_u.oplink)); 4746 case OP_LOCK: 4747 return (xdr_LOCK4res(xdrs, &objp->nfs_resop4_u.oplock)); 4748 case OP_LOCKT: 4749 return (xdr_LOCKT4res(xdrs, &objp->nfs_resop4_u.oplockt)); 4750 case OP_LOCKU: 4751 if (!xdr_int(xdrs, 4752 (int32_t *)&objp->nfs_resop4_u.oplocku.status)) 4753 return (FALSE); 4754 if (objp->nfs_resop4_u.oplocku.status != NFS4_OK) 4755 return (TRUE); 4756 if (!xdr_u_int(xdrs, 4757 &objp->nfs_resop4_u.oplocku.lock_stateid.seqid)) 4758 return (FALSE); 4759 return (xdr_opaque(xdrs, 4760 objp->nfs_resop4_u.oplocku.lock_stateid.other, 4761 NFS4_OTHER_SIZE)); 4762 case OP_NVERIFY: 4763 return (xdr_int(xdrs, 4764 (int32_t *)&objp->nfs_resop4_u.opnverify.status)); 4765 case OP_OPENATTR: 4766 return (xdr_int(xdrs, 4767 (int32_t *)&objp->nfs_resop4_u.opopenattr.status)); 4768 case OP_OPEN_CONFIRM: 4769 return (xdr_OPEN_CONFIRM4res(xdrs, 4770 &objp->nfs_resop4_u.opopen_confirm)); 4771 case OP_OPEN_DOWNGRADE: 4772 return (xdr_OPEN_DOWNGRADE4res(xdrs, 4773 &objp->nfs_resop4_u.opopen_downgrade)); 4774 case OP_PUTPUBFH: 4775 return (xdr_int(xdrs, 4776 (int32_t *)&objp->nfs_resop4_u.opputpubfh.status)); 4777 case OP_PUTROOTFH: 4778 return (xdr_int(xdrs, 4779 (int32_t *)&objp->nfs_resop4_u.opputrootfh.status)); 4780 case OP_READLINK: 4781 return (xdr_READLINK4res(xdrs, &objp->nfs_resop4_u.opreadlink)); 4782 case OP_RENAME: 4783 return (xdr_RENAME4res(xdrs, &objp->nfs_resop4_u.oprename)); 4784 case OP_RENEW: 4785 return (xdr_int(xdrs, 4786 (int32_t *)&objp->nfs_resop4_u.oprenew.status)); 4787 case OP_RESTOREFH: 4788 return (xdr_int(xdrs, 4789 (int32_t *)&objp->nfs_resop4_u.oprestorefh.status)); 4790 case OP_SAVEFH: 4791 return (xdr_int(xdrs, 4792 (int32_t *)&objp->nfs_resop4_u.opsavefh.status)); 4793 case OP_SECINFO: 4794 if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsecinfo. 4795 status)) 4796 return (FALSE); 4797 if (objp->nfs_resop4_u.opsecinfo.status != NFS4_OK) 4798 return (TRUE); 4799 return (xdr_array(xdrs, (char **)&objp->nfs_resop4_u.opsecinfo. 4800 SECINFO4resok_val, 4801 (uint_t *)&objp->nfs_resop4_u.opsecinfo. 4802 SECINFO4resok_len, 4803 NFS4_SECINFO_LIMIT, sizeof (secinfo4), 4804 (xdrproc_t)xdr_secinfo4)); 4805 case OP_SETATTR: 4806 if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsetattr. 4807 status)) 4808 return (FALSE); 4809 return (xdr_bitmap4(xdrs, 4810 &objp->nfs_resop4_u.opsetattr.attrsset)); 4811 case OP_SETCLIENTID: 4812 return (xdr_SETCLIENTID4res(xdrs, 4813 &objp->nfs_resop4_u.opsetclientid)); 4814 case OP_SETCLIENTID_CONFIRM: 4815 return (xdr_int(xdrs, 4816 (int32_t *)&objp->nfs_resop4_u.opsetclientid_confirm. 4817 status)); 4818 case OP_VERIFY: 4819 return (xdr_int(xdrs, 4820 (int32_t *)&objp->nfs_resop4_u.opverify.status)); 4821 case OP_RELEASE_LOCKOWNER: 4822 return (xdr_int(xdrs, 4823 (int32_t *)&objp->nfs_resop4_u.oprelease_lockowner.status)); 4824 case OP_ILLEGAL: 4825 return (xdr_int(xdrs, 4826 (int32_t *)&objp->nfs_resop4_u.opillegal.status)); 4827 } 4828 return (FALSE); 4829 } 4830 4831 static bool_t 4832 xdr_snfs_resop4(XDR *xdrs, nfs_resop4 *objp) 4833 { 4834 if (!xdr_int(xdrs, (int *)&objp->resop)) 4835 return (FALSE); 4836 4837 switch (objp->resop) { 4838 case OP_GETFH: 4839 if (!XDR_PUTINT32(xdrs, 4840 (int32_t *)&objp->nfs_resop4_u.opgetfh.status)) 4841 return (FALSE); 4842 if (objp->nfs_resop4_u.opgetfh.status != NFS4_OK) 4843 return (TRUE); 4844 return (xdr_encode_nfs_fh4(xdrs, 4845 &objp->nfs_resop4_u.opgetfh.object)); 4846 default: 4847 if (objp->resop >= OP_BACKCHANNEL_CTL && 4848 objp->resop != OP_ILLEGAL) 4849 return (xdr_nfs4x_resop4(xdrs, objp)); 4850 4851 return (xdr_nfs_resop4(xdrs, objp)); 4852 } 4853 } 4854 4855 static bool_t 4856 xdr_nfs_resop4_clnt(XDR *xdrs, nfs_resop4 *objp, nfs_argop4 *aobjp) 4857 { 4858 if (!xdr_int(xdrs, (int *)&objp->resop)) 4859 return (FALSE); 4860 /* 4861 * These should be ordered by frequency of use 4862 */ 4863 switch (objp->resop) { 4864 case OP_PUTFH: 4865 return (xdr_int(xdrs, 4866 (int32_t *)&objp->nfs_resop4_u.opputfh.status)); 4867 case OP_GETATTR: 4868 if (!xdr_int(xdrs, 4869 (int32_t *)&objp->nfs_resop4_u.opgetattr.status)) 4870 return (FALSE); 4871 if (objp->nfs_resop4_u.opgetattr.status != NFS4_OK) 4872 return (TRUE); 4873 return (xdr_ga_res(xdrs, 4874 (GETATTR4res *)&objp->nfs_resop4_u.opgetattr, 4875 &aobjp->nfs_argop4_u.opgetattr)); 4876 case OP_GETFH: 4877 if (!xdr_int(xdrs, 4878 (int32_t *)&objp->nfs_resop4_u.opgetfh.status)) 4879 return (FALSE); 4880 if (objp->nfs_resop4_u.opgetfh.status != NFS4_OK) 4881 return (TRUE); 4882 return (xdr_bytes(xdrs, 4883 (char **)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_val, 4884 (uint_t *)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_len, 4885 NFS4_FHSIZE)); 4886 case OP_LOOKUP: 4887 return (xdr_int(xdrs, 4888 (int32_t *)&objp->nfs_resop4_u.oplookup.status)); 4889 case OP_NVERIFY: 4890 return (xdr_int(xdrs, 4891 (int32_t *)&objp->nfs_resop4_u.opnverify.status)); 4892 case OP_OPEN: 4893 return (xdr_OPEN4res(xdrs, &objp->nfs_resop4_u.opopen)); 4894 case OP_CLOSE: 4895 return (xdr_CLOSE4res(xdrs, &objp->nfs_resop4_u.opclose)); 4896 case OP_ACCESS: 4897 return (xdr_ACCESS4res(xdrs, &objp->nfs_resop4_u.opaccess)); 4898 case OP_READ: 4899 return (xdr_READ4res_clnt(xdrs, &objp->nfs_resop4_u.opread, 4900 &aobjp->nfs_argop4_u.opread)); 4901 case OP_WRITE: 4902 return (xdr_WRITE4res(xdrs, &objp->nfs_resop4_u.opwrite)); 4903 case OP_DELEGRETURN: 4904 return (xdr_int(xdrs, 4905 (int32_t *)&objp->nfs_resop4_u.opdelegreturn.status)); 4906 case OP_LOOKUPP: 4907 return (xdr_int(xdrs, 4908 (int32_t *)&objp->nfs_resop4_u.oplookupp.status)); 4909 case OP_READDIR: 4910 return (xdr_READDIR4res_clnt(xdrs, 4911 &objp->nfs_resop4_u.opreaddirclnt, 4912 &aobjp->nfs_argop4_u.opreaddir)); 4913 case OP_REMOVE: 4914 return (xdr_REMOVE4res(xdrs, &objp->nfs_resop4_u.opremove)); 4915 4916 case OP_COMMIT: 4917 if (!xdr_int(xdrs, 4918 (int32_t *)&objp->nfs_resop4_u.opcommit.status)) 4919 return (FALSE); 4920 if (objp->nfs_resop4_u.opcommit.status != NFS4_OK) 4921 return (TRUE); 4922 return (xdr_u_longlong_t(xdrs, 4923 (u_longlong_t *)&objp->nfs_resop4_u.opcommit. 4924 writeverf)); 4925 case OP_CREATE: 4926 return (xdr_CREATE4res(xdrs, &objp->nfs_resop4_u.opcreate)); 4927 case OP_DELEGPURGE: 4928 return (xdr_int(xdrs, 4929 (int32_t *)&objp->nfs_resop4_u.opdelegpurge.status)); 4930 case OP_LINK: 4931 return (xdr_LINK4res(xdrs, &objp->nfs_resop4_u.oplink)); 4932 case OP_LOCK: 4933 return (xdr_LOCK4res(xdrs, &objp->nfs_resop4_u.oplock)); 4934 case OP_LOCKT: 4935 return (xdr_LOCKT4res(xdrs, &objp->nfs_resop4_u.oplockt)); 4936 case OP_LOCKU: 4937 if (!xdr_int(xdrs, 4938 (int32_t *)&objp->nfs_resop4_u.oplocku.status)) 4939 return (FALSE); 4940 if (objp->nfs_resop4_u.oplocku.status != NFS4_OK) 4941 return (TRUE); 4942 if (!xdr_u_int(xdrs, 4943 &objp->nfs_resop4_u.oplocku.lock_stateid.seqid)) 4944 return (FALSE); 4945 return (xdr_opaque(xdrs, 4946 objp->nfs_resop4_u.oplocku.lock_stateid.other, 4947 NFS4_OTHER_SIZE)); 4948 case OP_OPENATTR: 4949 return (xdr_int(xdrs, 4950 (int32_t *)&objp->nfs_resop4_u.opopenattr.status)); 4951 case OP_OPEN_CONFIRM: 4952 return (xdr_OPEN_CONFIRM4res(xdrs, 4953 &objp->nfs_resop4_u.opopen_confirm)); 4954 case OP_OPEN_DOWNGRADE: 4955 return (xdr_OPEN_DOWNGRADE4res(xdrs, 4956 &objp->nfs_resop4_u.opopen_downgrade)); 4957 case OP_PUTPUBFH: 4958 return (xdr_int(xdrs, 4959 (int32_t *)&objp->nfs_resop4_u.opputpubfh.status)); 4960 case OP_PUTROOTFH: 4961 return (xdr_int(xdrs, 4962 (int32_t *)&objp->nfs_resop4_u.opputrootfh.status)); 4963 case OP_READLINK: 4964 return (xdr_READLINK4res(xdrs, &objp->nfs_resop4_u.opreadlink)); 4965 case OP_RENAME: 4966 return (xdr_RENAME4res(xdrs, &objp->nfs_resop4_u.oprename)); 4967 case OP_RENEW: 4968 return (xdr_int(xdrs, 4969 (int32_t *)&objp->nfs_resop4_u.oprenew.status)); 4970 case OP_RESTOREFH: 4971 return (xdr_int(xdrs, 4972 (int32_t *)&objp->nfs_resop4_u.oprestorefh.status)); 4973 case OP_SAVEFH: 4974 return (xdr_int(xdrs, 4975 (int32_t *)&objp->nfs_resop4_u.opsavefh.status)); 4976 case OP_SECINFO: 4977 if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsecinfo. 4978 status)) 4979 return (FALSE); 4980 if (objp->nfs_resop4_u.opsecinfo.status != NFS4_OK) 4981 return (TRUE); 4982 return (xdr_array(xdrs, (char **)&objp->nfs_resop4_u.opsecinfo. 4983 SECINFO4resok_val, 4984 (uint_t *)&objp->nfs_resop4_u.opsecinfo. 4985 SECINFO4resok_len, 4986 ~0, sizeof (secinfo4), (xdrproc_t)xdr_secinfo4)); 4987 case OP_SETATTR: 4988 if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsetattr. 4989 status)) 4990 return (FALSE); 4991 return (xdr_bitmap4(xdrs, 4992 &objp->nfs_resop4_u.opsetattr.attrsset)); 4993 case OP_SETCLIENTID: 4994 return (xdr_SETCLIENTID4res(xdrs, 4995 &objp->nfs_resop4_u.opsetclientid)); 4996 case OP_SETCLIENTID_CONFIRM: 4997 return (xdr_int(xdrs, 4998 (int32_t *)&objp->nfs_resop4_u.opsetclientid_confirm. 4999 status)); 5000 case OP_VERIFY: 5001 return (xdr_int(xdrs, 5002 (int32_t *)&objp->nfs_resop4_u.opverify.status)); 5003 case OP_RELEASE_LOCKOWNER: 5004 return (xdr_int(xdrs, 5005 (int32_t *)&objp->nfs_resop4_u.oprelease_lockowner.status)); 5006 case OP_ILLEGAL: 5007 return (xdr_int(xdrs, 5008 (int32_t *)&objp->nfs_resop4_u.opillegal.status)); 5009 } 5010 return (FALSE); 5011 } 5012 5013 bool_t 5014 xdr_COMPOUND4args_clnt(XDR *xdrs, COMPOUND4args_clnt *objp) 5015 { 5016 static int32_t twelve = 12; 5017 static int32_t minorversion = NFS4_MINORVERSION; 5018 uint32_t *ctagp; 5019 rpc_inline_t *ptr; 5020 rdma_chunkinfo_t rci; 5021 struct xdr_ops *xops = xdrrdma_xops(); 5022 5023 /* 5024 * XDR_ENCODE only 5025 */ 5026 if (xdrs->x_op == XDR_FREE) 5027 return (TRUE); 5028 if (xdrs->x_op == XDR_DECODE) 5029 return (FALSE); 5030 5031 ctagp = (uint32_t *)&nfs4_ctags[objp->ctag].ct_tag; 5032 5033 if ((ptr = XDR_INLINE(xdrs, 5 * BYTES_PER_XDR_UNIT)) != NULL) { 5034 /* 5035 * Efficiently encode fixed length tags, could be longlongs 5036 * but 8 byte XDR alignment not assured 5037 */ 5038 IXDR_PUT_U_INT32(ptr, 12); 5039 IXDR_PUT_U_INT32(ptr, ctagp[0]); 5040 IXDR_PUT_U_INT32(ptr, ctagp[1]); 5041 IXDR_PUT_U_INT32(ptr, ctagp[2]); 5042 5043 /* 5044 * Fixed minor version for now 5045 */ 5046 IXDR_PUT_U_INT32(ptr, NFS4_MINORVERSION); 5047 } else { 5048 if (!XDR_PUTINT32(xdrs, &twelve)) 5049 return (FALSE); 5050 if (!XDR_PUTINT32(xdrs, (int32_t *)&ctagp[0])) 5051 return (FALSE); 5052 if (!XDR_PUTINT32(xdrs, (int32_t *)&ctagp[1])) 5053 return (FALSE); 5054 if (!XDR_PUTINT32(xdrs, (int32_t *)&ctagp[2])) 5055 return (FALSE); 5056 if (!XDR_PUTINT32(xdrs, (int32_t *)&minorversion)) 5057 return (FALSE); 5058 } 5059 if (xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) { 5060 rci.rci_type = RCI_REPLY_CHUNK; 5061 rci.rci_len = MAXPATHLEN * 2; 5062 XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci); 5063 } 5064 5065 return (xdr_array(xdrs, (char **)&objp->array, 5066 (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT, 5067 sizeof (nfs_argop4), (xdrproc_t)xdr_cnfs_argop4)); 5068 } 5069 5070 bool_t 5071 xdr_COMPOUND4args_srv(XDR *xdrs, COMPOUND4args *objp) 5072 { 5073 if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val, 5074 (uint_t *)&objp->tag.utf8string_len, 5075 NFS4_MAX_UTF8STRING)) 5076 return (FALSE); 5077 if (!xdr_u_int(xdrs, &objp->minorversion)) 5078 return (FALSE); 5079 if (xdrs->x_op != XDR_FREE) 5080 return (xdr_array(xdrs, (char **)&objp->array, 5081 (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT, 5082 sizeof (nfs_argop4), (xdrproc_t)xdr_snfs_argop4)); 5083 5084 return (xdr_snfs_argop4_free(xdrs, &objp->array, objp->array_len)); 5085 } 5086 5087 bool_t 5088 xdr_COMPOUND4res_clnt(XDR *xdrs, COMPOUND4res_clnt *objp) 5089 { 5090 uint32_t len; 5091 int32_t *ptr; 5092 nfs_argop4 *argop; 5093 nfs_resop4 *resop; 5094 5095 /* 5096 * No XDR_ENCODE 5097 */ 5098 if (xdrs->x_op == XDR_ENCODE) 5099 return (FALSE); 5100 5101 if (xdrs->x_op != XDR_FREE) { 5102 if ((ptr = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT)) != NULL) { 5103 objp->status = IXDR_GET_U_INT32(ptr); 5104 len = IXDR_GET_U_INT32(ptr); 5105 } else { 5106 if (!xdr_int(xdrs, (int32_t *)&objp->status)) 5107 return (FALSE); 5108 if (!xdr_u_int(xdrs, (uint32_t *)&len)) 5109 return (FALSE); 5110 } 5111 if (len > NFS4_MAX_UTF8STRING) 5112 return (FALSE); 5113 /* 5114 * Ignore the tag 5115 */ 5116 if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &len)) 5117 return (FALSE); 5118 5119 if (!xdr_int(xdrs, (int32_t *)&objp->array_len)) 5120 return (FALSE); 5121 5122 if (objp->array_len > objp->argsp->array_len) 5123 return (FALSE); 5124 5125 if (objp->status == NFS4_OK && 5126 objp->array_len != objp->argsp->array_len) 5127 return (FALSE); 5128 5129 /* Alloc the results array */ 5130 argop = objp->argsp->array; 5131 len = objp->array_len * sizeof (nfs_resop4); 5132 objp->decode_len = 0; 5133 objp->array = resop = kmem_zalloc(len, KM_SLEEP); 5134 5135 for (len = 0; len < objp->array_len; 5136 len++, resop++, argop++, objp->decode_len++) { 5137 if (!xdr_nfs_resop4_clnt(xdrs, resop, argop)) { 5138 /* 5139 * Make sure to free anything that may 5140 * have been allocated along the way. 5141 */ 5142 xdrs->x_op = XDR_FREE; 5143 (void) xdr_nfs_resop4_free(xdrs, &objp->array, 5144 objp->array_len, 5145 objp->decode_len); 5146 return (FALSE); 5147 } 5148 } 5149 return (TRUE); 5150 } 5151 return (xdr_nfs_resop4_free(xdrs, &objp->array, 5152 objp->array_len, objp->decode_len)); 5153 } 5154 5155 bool_t 5156 xdr_COMPOUND4res_srv(XDR *xdrs, COMPOUND4res *objp) 5157 { 5158 if (!xdr_int(xdrs, (int32_t *)&objp->status)) 5159 return (FALSE); 5160 if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val, 5161 (uint_t *)&objp->tag.utf8string_len, 5162 NFS4_MAX_UTF8STRING)) 5163 return (FALSE); 5164 5165 if (xdrs->x_op != XDR_FREE) 5166 return (xdr_array(xdrs, (char **)&objp->array, 5167 (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT, 5168 sizeof (nfs_resop4), (xdrproc_t)xdr_snfs_resop4)); 5169 5170 return (xdr_snfs_resop4_free(xdrs, &objp->array, 5171 objp->array_len, objp->array_len)); 5172 } 5173 5174 /* 5175 * NFS server side callback, initiating the callback request so it 5176 * is the RPC client. Must convert from server's internal filehandle 5177 * format to wire format. 5178 */ 5179 static bool_t 5180 xdr_snfs_cb_argop4(XDR *xdrs, nfs_cb_argop4 *objp) 5181 { 5182 CB_GETATTR4args *gargs; 5183 CB_RECALL4args *rargs; 5184 5185 ASSERT(xdrs->x_op == XDR_ENCODE); 5186 5187 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->argop)) 5188 return (FALSE); 5189 5190 switch (objp->argop) { 5191 case OP_CB_GETATTR: 5192 gargs = &objp->nfs_cb_argop4_u.opcbgetattr; 5193 5194 if (!xdr_encode_nfs_fh4(xdrs, &gargs->fh)) 5195 return (FALSE); 5196 return (xdr_bitmap4(xdrs, &gargs->attr_request)); 5197 case OP_CB_RECALL: 5198 rargs = &objp->nfs_cb_argop4_u.opcbrecall; 5199 5200 if (!XDR_PUTINT32(xdrs, (int32_t *)&rargs->stateid.seqid)) 5201 return (FALSE); 5202 if (!xdr_opaque(xdrs, rargs->stateid.other, NFS4_OTHER_SIZE)) 5203 return (FALSE); 5204 if (!XDR_PUTINT32(xdrs, (int32_t *)&rargs->truncate)) 5205 return (FALSE); 5206 return (xdr_encode_nfs_fh4(xdrs, &rargs->fh)); 5207 case OP_CB_ILLEGAL: 5208 return (TRUE); 5209 } 5210 return (FALSE); 5211 } 5212 5213 /* 5214 * NFS client side callback, receiving the callback request so it 5215 * is the RPC server. Must treat the file handles as opaque. 5216 */ 5217 static bool_t 5218 xdr_cnfs_cb_argop4(XDR *xdrs, nfs_cb_argop4 *objp) 5219 { 5220 CB_GETATTR4args *gargs; 5221 CB_RECALL4args *rargs; 5222 5223 ASSERT(xdrs->x_op != XDR_ENCODE); 5224 5225 if (!xdr_u_int(xdrs, &objp->argop)) 5226 return (FALSE); 5227 switch (objp->argop) { 5228 case OP_CB_GETATTR: 5229 gargs = &objp->nfs_cb_argop4_u.opcbgetattr; 5230 5231 if (!xdr_bytes(xdrs, (char **)&gargs->fh.nfs_fh4_val, 5232 (uint_t *)&gargs->fh.nfs_fh4_len, NFS4_FHSIZE)) 5233 return (FALSE); 5234 return (xdr_bitmap4(xdrs, &gargs->attr_request)); 5235 case OP_CB_RECALL: 5236 rargs = &objp->nfs_cb_argop4_u.opcbrecall; 5237 5238 if (!xdr_u_int(xdrs, &rargs->stateid.seqid)) 5239 return (FALSE); 5240 if (!xdr_opaque(xdrs, rargs->stateid.other, NFS4_OTHER_SIZE)) 5241 return (FALSE); 5242 if (!xdr_bool(xdrs, &rargs->truncate)) 5243 return (FALSE); 5244 return (xdr_bytes(xdrs, (char **)&rargs->fh.nfs_fh4_val, 5245 (uint_t *)&rargs->fh.nfs_fh4_len, NFS4_FHSIZE)); 5246 case OP_CB_ILLEGAL: 5247 return (TRUE); 5248 } 5249 return (FALSE); 5250 } 5251 5252 /* 5253 * The NFS client side callback, RPC server 5254 */ 5255 bool_t 5256 xdr_CB_COMPOUND4args_clnt(XDR *xdrs, CB_COMPOUND4args *objp) 5257 { 5258 if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val, 5259 (uint_t *)&objp->tag.utf8string_len, 5260 NFS4_MAX_UTF8STRING)) 5261 return (FALSE); 5262 if (!xdr_u_int(xdrs, &objp->minorversion)) 5263 return (FALSE); 5264 if (!xdr_u_int(xdrs, &objp->callback_ident)) 5265 return (FALSE); 5266 return (xdr_array(xdrs, (char **)&objp->array, 5267 (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT, 5268 sizeof (nfs_cb_argop4), (xdrproc_t)xdr_cnfs_cb_argop4)); 5269 } 5270 5271 /* 5272 * The NFS server side callback, RPC client 5273 */ 5274 bool_t 5275 xdr_CB_COMPOUND4args_srv(XDR *xdrs, CB_COMPOUND4args *objp) 5276 { 5277 if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val, 5278 (uint_t *)&objp->tag.utf8string_len, 5279 NFS4_MAX_UTF8STRING)) 5280 return (FALSE); 5281 if (!xdr_u_int(xdrs, &objp->minorversion)) 5282 return (FALSE); 5283 if (!xdr_u_int(xdrs, &objp->callback_ident)) 5284 return (FALSE); 5285 return (xdr_array(xdrs, (char **)&objp->array, 5286 (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT, 5287 sizeof (nfs_cb_argop4), (xdrproc_t)xdr_snfs_cb_argop4)); 5288 } 5289 5290 bool_t 5291 xdr_CB_COMPOUND4res(XDR *xdrs, CB_COMPOUND4res *objp) 5292 { 5293 if (!xdr_int(xdrs, (int32_t *)&objp->status)) 5294 return (FALSE); 5295 if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val, 5296 (uint_t *)&objp->tag.utf8string_len, 5297 NFS4_MAX_UTF8STRING)) 5298 return (FALSE); 5299 return (xdr_array(xdrs, (char **)&objp->array, 5300 (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT, 5301 sizeof (nfs_cb_resop4), (xdrproc_t)xdr_nfs_cb_resop4)); 5302 } 5303