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