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