1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 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 int i, rndup; 3354 mblk_t *mp; 3355 3356 if (xdrs->x_op == XDR_DECODE) 3357 return (FALSE); 3358 3359 if (xdrs->x_op == XDR_FREE) { 3360 /* 3361 * Optimized free case 3362 */ 3363 if (objp->status != NFS4_OK) 3364 return (TRUE); 3365 if (objp->data_val != NULL) 3366 kmem_free(objp->data_val, objp->data_len); 3367 return (TRUE); 3368 } 3369 3370 /* on with ENCODE paths */ 3371 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->status)) 3372 return (FALSE); 3373 if (objp->status != NFS4_OK) 3374 return (TRUE); 3375 3376 if (!XDR_PUTINT32(xdrs, &objp->eof)) 3377 return (FALSE); 3378 3379 mp = objp->mblk; 3380 if (mp != NULL && xdrs->x_ops == &xdrmblk_ops) { 3381 mp->b_wptr += objp->data_len; 3382 rndup = BYTES_PER_XDR_UNIT - 3383 (objp->data_len % BYTES_PER_XDR_UNIT); 3384 if (rndup != BYTES_PER_XDR_UNIT) 3385 for (i = 0; i < rndup; i++) 3386 *mp->b_wptr++ = '\0'; 3387 if (xdrmblk_putmblk(xdrs, mp, objp->data_len) == TRUE) { 3388 objp->mblk = NULL; 3389 return (TRUE); 3390 } 3391 } else if (mp == NULL) { 3392 if (xdr_u_int(xdrs, &objp->data_len) == FALSE) { 3393 return (FALSE); 3394 } 3395 /* 3396 * If read data sent by wlist (RDMA_WRITE), don't do 3397 * xdr_bytes() below. RDMA_WRITE transfers the data. 3398 * Note: this is encode-only because the client code 3399 * uses xdr_READ4res_clnt to decode results. 3400 */ 3401 if (objp->wlist) { 3402 if (objp->data_len != 0) { 3403 return (xdrrdma_send_read_data( 3404 xdrs, objp->data_len, objp->wlist)); 3405 } 3406 return (TRUE); 3407 } 3408 } 3409 3410 return (xdr_bytes(xdrs, (char **)&objp->data_val, 3411 (uint_t *)&objp->data_len, 3412 objp->data_len)); 3413 } 3414 3415 static bool_t 3416 xdr_READ4res_clnt(XDR *xdrs, READ4res *objp, READ4args *aobjp) 3417 { 3418 mblk_t *mp; 3419 size_t n; 3420 int error; 3421 uint_t size = aobjp->res_maxsize; 3422 count4 ocount; 3423 3424 if (xdrs->x_op == XDR_ENCODE) 3425 return (FALSE); 3426 3427 if (xdrs->x_op == XDR_FREE) { 3428 /* 3429 * Optimized free case 3430 */ 3431 if (objp->status != NFS4_OK) 3432 return (TRUE); 3433 if (objp->data_val != NULL) 3434 kmem_free(objp->data_val, objp->data_len); 3435 return (TRUE); 3436 } 3437 3438 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->status)) 3439 return (FALSE); 3440 if (objp->status != NFS4_OK) 3441 return (TRUE); 3442 3443 if (!XDR_GETINT32(xdrs, &objp->eof)) 3444 return (FALSE); 3445 3446 3447 /* 3448 * This is a special case such that the caller is providing a 3449 * uio as a guide to eventual data location; this is used for 3450 * handling DIRECTIO reads. 3451 */ 3452 if (aobjp->res_uiop != NULL) { 3453 struct uio *uiop = aobjp->res_uiop; 3454 int32_t *ptr; 3455 3456 if (xdrs->x_ops == &xdrmblk_ops) { 3457 if (!xdrmblk_getmblk(xdrs, &mp, &objp->data_len)) 3458 return (FALSE); 3459 3460 if (objp->data_len == 0) 3461 return (TRUE); 3462 3463 if (objp->data_len > size) 3464 return (FALSE); 3465 3466 size = objp->data_len; 3467 do { 3468 n = MIN(size, mp->b_wptr - mp->b_rptr); 3469 if ((n = MIN(uiop->uio_resid, n)) != 0) { 3470 3471 error = uiomove((char *)mp->b_rptr, n, 3472 UIO_READ, uiop); 3473 if (error) 3474 return (FALSE); 3475 mp->b_rptr += n; 3476 size -= n; 3477 } 3478 3479 while (mp && (mp->b_rptr >= mp->b_wptr)) 3480 mp = mp->b_cont; 3481 } while (mp && size > 0 && uiop->uio_resid > 0); 3482 3483 return (TRUE); 3484 } 3485 3486 if (xdrs->x_ops == &xdrrdma_ops) { 3487 struct clist *cl; 3488 3489 XDR_CONTROL(xdrs, XDR_RDMA_GET_WLIST, &cl); 3490 3491 objp->wlist = cl; 3492 3493 if (objp->wlist) { 3494 /* opaque count */ 3495 if (!xdr_u_int(xdrs, &ocount)) { 3496 objp->wlist = NULL; 3497 return (FALSE); 3498 } 3499 3500 objp->wlist_len = clist_len(cl); 3501 objp->data_len = ocount; 3502 3503 if (objp->wlist_len != 3504 roundup( 3505 objp->data_len, BYTES_PER_XDR_UNIT)) { 3506 DTRACE_PROBE2( 3507 xdr__e__read4resuio_clnt_fail, 3508 int, ocount, 3509 int, objp->data_len); 3510 objp->wlist = NULL; 3511 return (FALSE); 3512 } 3513 3514 uiop->uio_resid -= objp->data_len; 3515 uiop->uio_iov->iov_len -= objp->data_len; 3516 uiop->uio_iov->iov_base += objp->data_len; 3517 uiop->uio_loffset += objp->data_len; 3518 3519 objp->wlist = NULL; 3520 return (TRUE); 3521 } 3522 } 3523 3524 /* 3525 * This isn't an xdrmblk stream nor RDMA. 3526 * Handle the likely case that it can be 3527 * inlined (ex. xdrmem). 3528 */ 3529 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->data_len)) 3530 return (FALSE); 3531 3532 if (objp->data_len == 0) 3533 return (TRUE); 3534 3535 if (objp->data_len > size) 3536 return (FALSE); 3537 3538 size = (int)objp->data_len; 3539 if ((ptr = XDR_INLINE(xdrs, size)) != NULL) 3540 return (uiomove(ptr, size, UIO_READ, uiop) ? 3541 FALSE : TRUE); 3542 3543 /* 3544 * Handle some other (unlikely) stream type that will 3545 * need a copy. 3546 */ 3547 if ((ptr = kmem_alloc(size, KM_NOSLEEP)) == NULL) 3548 return (FALSE); 3549 3550 if (!XDR_GETBYTES(xdrs, (caddr_t)ptr, size)) { 3551 kmem_free(ptr, size); 3552 return (FALSE); 3553 } 3554 error = uiomove(ptr, size, UIO_READ, uiop); 3555 kmem_free(ptr, size); 3556 3557 return (error ? FALSE : TRUE); 3558 } 3559 3560 /* 3561 * Check for the other special case of the caller providing 3562 * the target area for the data. 3563 */ 3564 if (aobjp->res_data_val_alt == NULL) 3565 return (FALSE); 3566 3567 /* 3568 * If read data received via RDMA_WRITE, don't do xdr_bytes(). 3569 * RDMA_WRITE already moved the data so decode length of 3570 * RDMA_WRITE. 3571 */ 3572 if (xdrs->x_ops == &xdrrdma_ops) { 3573 struct clist *cl; 3574 3575 XDR_CONTROL(xdrs, XDR_RDMA_GET_WLIST, &cl); 3576 3577 objp->wlist = cl; 3578 3579 /* 3580 * Data transferred through inline if 3581 * objp->wlist == NULL 3582 */ 3583 if (objp->wlist) { 3584 /* opaque count */ 3585 if (!xdr_u_int(xdrs, &ocount)) { 3586 objp->wlist = NULL; 3587 return (FALSE); 3588 } 3589 3590 objp->wlist_len = clist_len(cl); 3591 objp->data_len = ocount; 3592 3593 if (objp->wlist_len != 3594 roundup( 3595 objp->data_len, BYTES_PER_XDR_UNIT)) { 3596 DTRACE_PROBE2( 3597 xdr__e__read4res_clnt_fail, 3598 int, ocount, 3599 int, objp->data_len); 3600 objp->wlist = NULL; 3601 return (FALSE); 3602 } 3603 3604 objp->wlist = NULL; 3605 return (TRUE); 3606 } 3607 } 3608 3609 return (xdr_bytes(xdrs, (char **)&aobjp->res_data_val_alt, 3610 (uint_t *)&objp->data_len, 3611 aobjp->res_maxsize)); 3612 } 3613 3614 static bool_t 3615 xdr_READDIR4args(XDR *xdrs, READDIR4args *objp) 3616 { 3617 rdma_chunkinfo_t rci; 3618 struct xdr_ops *xops = xdrrdma_xops(); 3619 3620 if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) && 3621 xdrs->x_op == XDR_ENCODE) { 3622 rci.rci_type = RCI_REPLY_CHUNK; 3623 rci.rci_len = objp->maxcount; 3624 XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci); 3625 } 3626 3627 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cookie)) 3628 return (FALSE); 3629 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cookieverf)) 3630 return (FALSE); 3631 if (!xdr_u_int(xdrs, &objp->dircount)) 3632 return (FALSE); 3633 if (!xdr_u_int(xdrs, &objp->maxcount)) 3634 return (FALSE); 3635 return (xdr_bitmap4(xdrs, &objp->attr_request)); 3636 } 3637 3638 /* ARGSUSED */ 3639 static bool_t 3640 xdrmblk_putmblk_rd(XDR *xdrs, mblk_t *m) 3641 { 3642 if (((m->b_wptr - m->b_rptr) % BYTES_PER_XDR_UNIT) != 0) 3643 return (FALSE); 3644 3645 /* LINTED pointer alignment */ 3646 ((mblk_t *)xdrs->x_base)->b_cont = m; 3647 xdrs->x_base = (caddr_t)m; 3648 xdrs->x_handy = 0; 3649 return (TRUE); 3650 } 3651 3652 bool_t 3653 xdr_READDIR4res(XDR *xdrs, READDIR4res *objp) 3654 { 3655 mblk_t *mp = objp->mblk; 3656 bool_t ret_val; 3657 uint_t flags = 0; 3658 3659 ASSERT(xdrs->x_op == XDR_ENCODE); 3660 3661 if (!xdr_int(xdrs, (int32_t *)&objp->status)) 3662 return (FALSE); 3663 if (objp->status != NFS4_OK) 3664 return (TRUE); 3665 if (mp == NULL) 3666 return (FALSE); 3667 3668 if (xdrs->x_ops == &xdrmblk_ops) { 3669 if (xdrmblk_putmblk_rd(xdrs, mp) 3670 == TRUE) { 3671 /* mblk successfully inserted into outgoing chain */ 3672 objp->mblk = NULL; 3673 return (TRUE); 3674 } 3675 } 3676 3677 ASSERT(mp->b_cont == NULL); 3678 3679 /* 3680 * If transport is RDMA, the pre-encoded m_blk needs to be moved 3681 * without being chunked. 3682 * Check if chunking is enabled for the xdr stream. 3683 * If it is enabled, disable it temporarily for this op, 3684 * then re-enable. 3685 */ 3686 XDR_CONTROL(xdrs, XDR_RDMA_GET_FLAGS, &flags); 3687 3688 if (!(flags & XDR_RDMA_CHUNK)) 3689 return (xdr_opaque(xdrs, (char *)mp->b_rptr, objp->data_len)); 3690 3691 flags &= ~XDR_RDMA_CHUNK; 3692 3693 (void) XDR_CONTROL(xdrs, XDR_RDMA_SET_FLAGS, &flags); 3694 3695 ret_val = xdr_opaque(xdrs, (char *)mp->b_rptr, objp->data_len); 3696 3697 flags |= XDR_RDMA_CHUNK; 3698 3699 (void) XDR_CONTROL(xdrs, XDR_RDMA_SET_FLAGS, &flags); 3700 3701 return (ret_val); 3702 } 3703 3704 static bool_t 3705 xdr_READLINK4res(XDR *xdrs, READLINK4res *objp) 3706 { 3707 if (xdrs->x_op != XDR_FREE) { 3708 if (!xdr_int(xdrs, (int32_t *)&objp->status)) 3709 return (FALSE); 3710 if (objp->status != NFS4_OK) 3711 return (TRUE); 3712 return (xdr_bytes(xdrs, (char **)&objp->link.utf8string_val, 3713 (uint_t *)&objp->link.utf8string_len, 3714 NFS4_MAX_UTF8STRING)); 3715 } 3716 3717 /* 3718 * Optimized free case 3719 */ 3720 if (objp->status != NFS4_OK) 3721 return (TRUE); 3722 if (objp->link.utf8string_val != NULL) 3723 kmem_free(objp->link.utf8string_val, objp->link.utf8string_len); 3724 return (TRUE); 3725 } 3726 3727 static bool_t 3728 xdr_REMOVE4res(XDR *xdrs, REMOVE4res *objp) 3729 { 3730 if (!xdr_int(xdrs, (int32_t *)&objp->status)) 3731 return (FALSE); 3732 if (objp->status != NFS4_OK) 3733 return (TRUE); 3734 if (!xdr_bool(xdrs, &objp->cinfo.atomic)) 3735 return (FALSE); 3736 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.before)) 3737 return (FALSE); 3738 return (xdr_u_longlong_t(xdrs, 3739 (u_longlong_t *)&objp->cinfo.after)); 3740 } 3741 3742 static bool_t 3743 xdr_RENAME4res(XDR *xdrs, RENAME4res *objp) 3744 { 3745 if (!xdr_int(xdrs, (int32_t *)&objp->status)) 3746 return (FALSE); 3747 if (objp->status != NFS4_OK) 3748 return (TRUE); 3749 if (!xdr_bool(xdrs, &objp->source_cinfo.atomic)) 3750 return (FALSE); 3751 if (!xdr_u_longlong_t(xdrs, 3752 (u_longlong_t *)&objp->source_cinfo.before)) 3753 return (FALSE); 3754 if (!xdr_u_longlong_t(xdrs, 3755 (u_longlong_t *)&objp->source_cinfo.after)) 3756 return (FALSE); 3757 if (!xdr_bool(xdrs, &objp->target_cinfo.atomic)) 3758 return (FALSE); 3759 if (!xdr_u_longlong_t(xdrs, 3760 (u_longlong_t *)&objp->target_cinfo.before)) 3761 return (FALSE); 3762 return (xdr_u_longlong_t(xdrs, 3763 (u_longlong_t *)&objp->target_cinfo.after)); 3764 } 3765 3766 static bool_t 3767 xdr_secinfo4(XDR *xdrs, secinfo4 *objp) 3768 { 3769 if (xdrs->x_op != XDR_FREE) { 3770 if (!xdr_u_int(xdrs, &objp->flavor)) 3771 return (FALSE); 3772 if (objp->flavor != RPCSEC_GSS) 3773 return (TRUE); 3774 if (!xdr_bytes(xdrs, 3775 (char **)&objp->flavor_info.oid.sec_oid4_val, 3776 (uint_t *)&objp->flavor_info.oid.sec_oid4_len, 3777 NFS4_MAX_SECOID4)) 3778 return (FALSE); 3779 if (!xdr_u_int(xdrs, &objp->flavor_info.qop)) 3780 return (FALSE); 3781 return (xdr_int(xdrs, (int *)&objp->flavor_info.service)); 3782 } 3783 3784 /* 3785 * Optimized free path 3786 */ 3787 if (objp->flavor != RPCSEC_GSS) 3788 return (TRUE); 3789 3790 if (objp->flavor_info.oid.sec_oid4_val != NULL) 3791 kmem_free(objp->flavor_info.oid.sec_oid4_val, 3792 objp->flavor_info.oid.sec_oid4_len); 3793 return (TRUE); 3794 } 3795 3796 static bool_t 3797 xdr_SETCLIENTID4args(XDR *xdrs, SETCLIENTID4args *objp) 3798 { 3799 if (xdrs->x_op != XDR_FREE) { 3800 if (!xdr_u_longlong_t(xdrs, 3801 (u_longlong_t *)&objp->client.verifier)) 3802 return (FALSE); 3803 if (!xdr_bytes(xdrs, (char **)&objp->client.id_val, 3804 (uint_t *)&objp->client.id_len, NFS4_OPAQUE_LIMIT)) 3805 return (FALSE); 3806 if (!xdr_u_int(xdrs, &objp->callback.cb_program)) 3807 return (FALSE); 3808 if (!xdr_string(xdrs, &objp->callback.cb_location.r_netid, 3809 NFS4_OPAQUE_LIMIT)) 3810 return (FALSE); 3811 if (!xdr_string(xdrs, &objp->callback.cb_location.r_addr, 3812 NFS4_OPAQUE_LIMIT)) 3813 return (FALSE); 3814 return (xdr_u_int(xdrs, &objp->callback_ident)); 3815 } 3816 3817 /* 3818 * Optimized free case 3819 */ 3820 if (objp->client.id_val != NULL) 3821 kmem_free(objp->client.id_val, objp->client.id_len); 3822 (void) xdr_string(xdrs, &objp->callback.cb_location.r_netid, 3823 NFS4_OPAQUE_LIMIT); 3824 return (xdr_string(xdrs, &objp->callback.cb_location.r_addr, 3825 NFS4_OPAQUE_LIMIT)); 3826 } 3827 3828 static bool_t 3829 xdr_SETCLIENTID4res(XDR *xdrs, SETCLIENTID4res *objp) 3830 { 3831 if (xdrs->x_op != XDR_FREE) { 3832 if (!xdr_int(xdrs, (int32_t *)&objp->status)) 3833 return (FALSE); 3834 switch (objp->status) { 3835 case NFS4_OK: 3836 if (!xdr_u_longlong_t(xdrs, 3837 (u_longlong_t *)&objp->SETCLIENTID4res_u.resok4. 3838 clientid)) 3839 return (FALSE); 3840 return (xdr_u_longlong_t(xdrs, 3841 (u_longlong_t *)&objp->SETCLIENTID4res_u. 3842 resok4.setclientid_confirm)); 3843 case NFS4ERR_CLID_INUSE: 3844 if (!xdr_string(xdrs, 3845 &objp->SETCLIENTID4res_u.client_using. 3846 r_netid, NFS4_OPAQUE_LIMIT)) 3847 return (FALSE); 3848 return (xdr_string(xdrs, 3849 &objp->SETCLIENTID4res_u.client_using. 3850 r_addr, NFS4_OPAQUE_LIMIT)); 3851 } 3852 return (TRUE); 3853 } 3854 3855 /* 3856 * Optimized free case 3857 */ 3858 if (objp->status != NFS4ERR_CLID_INUSE) 3859 return (TRUE); 3860 3861 if (!xdr_string(xdrs, &objp->SETCLIENTID4res_u.client_using.r_netid, 3862 NFS4_OPAQUE_LIMIT)) 3863 return (FALSE); 3864 return (xdr_string(xdrs, &objp->SETCLIENTID4res_u.client_using.r_addr, 3865 NFS4_OPAQUE_LIMIT)); 3866 } 3867 3868 static bool_t 3869 xdr_WRITE4args(XDR *xdrs, WRITE4args *objp) 3870 { 3871 if (xdrs->x_op != XDR_FREE) { 3872 if (!xdr_u_int(xdrs, &objp->stateid.seqid)) 3873 return (FALSE); 3874 if (!xdr_opaque(xdrs, objp->stateid.other, 12)) 3875 return (FALSE); 3876 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset)) 3877 return (FALSE); 3878 if (!xdr_int(xdrs, (int *)&objp->stable)) 3879 return (FALSE); 3880 if (xdrs->x_op == XDR_DECODE) { 3881 if (xdrs->x_ops == &xdrmblk_ops) { 3882 objp->data_val = NULL; 3883 return (xdrmblk_getmblk(xdrs, &objp->mblk, 3884 &objp->data_len)); 3885 } 3886 objp->mblk = NULL; 3887 if (xdrs->x_ops == &xdrrdmablk_ops) { 3888 int retval; 3889 retval = xdrrdma_getrdmablk(xdrs, 3890 &objp->rlist, 3891 &objp->data_len, 3892 &objp->conn, NFS4_DATA_LIMIT); 3893 if (retval == FALSE) 3894 return (FALSE); 3895 return (xdrrdma_read_from_client(objp->rlist, 3896 &objp->conn, objp->data_len)); 3897 } 3898 } 3899 /* Else fall thru for the xdr_bytes(). */ 3900 return (xdr_bytes(xdrs, (char **)&objp->data_val, 3901 (uint_t *)&objp->data_len, NFS4_DATA_LIMIT)); 3902 } 3903 if (objp->rlist != NULL) { 3904 (void) xdrrdma_free_clist(objp->conn, objp->rlist); 3905 objp->rlist = NULL; 3906 objp->data_val = NULL; 3907 3908 return (TRUE); 3909 } 3910 3911 /* 3912 * Optimized free case 3913 */ 3914 if (objp->data_val != NULL) 3915 kmem_free(objp->data_val, objp->data_len); 3916 return (TRUE); 3917 } 3918 3919 static bool_t 3920 xdr_WRITE4res(XDR *xdrs, WRITE4res *objp) 3921 { 3922 if (!xdr_int(xdrs, (int32_t *)&objp->status)) 3923 return (FALSE); 3924 if (objp->status != NFS4_OK) 3925 return (TRUE); 3926 if (!xdr_u_int(xdrs, &objp->count)) 3927 return (FALSE); 3928 if (!xdr_int(xdrs, (int *)&objp->committed)) 3929 return (FALSE); 3930 return (xdr_u_longlong_t(xdrs, 3931 (u_longlong_t *)&objp->writeverf)); 3932 } 3933 3934 static bool_t 3935 xdr_snfs_argop4_free(XDR *xdrs, nfs_argop4 **arrayp, int len) 3936 { 3937 int i; 3938 nfs_argop4 *array = *arrayp; 3939 3940 /* 3941 * Optimized XDR_FREE only args array 3942 */ 3943 ASSERT(xdrs->x_op == XDR_FREE); 3944 3945 /* 3946 * Nothing to do? 3947 */ 3948 if (array == NULL) 3949 return (TRUE); 3950 3951 for (i = 0; i < len; i++) { 3952 /* 3953 * These should be ordered by frequency of use 3954 */ 3955 switch (array[i].argop) { 3956 case OP_PUTFH: 3957 if (array[i].nfs_argop4_u.opputfh.object.nfs_fh4_val != 3958 NULL) { 3959 kmem_free(array[i].nfs_argop4_u.opputfh.object. 3960 nfs_fh4_val, 3961 array[i].nfs_argop4_u.opputfh.object. 3962 nfs_fh4_len); 3963 } 3964 continue; 3965 case OP_GETATTR: 3966 case OP_GETFH: 3967 continue; 3968 case OP_LOOKUP: 3969 if (array[i].nfs_argop4_u.oplookup.objname. 3970 utf8string_val != NULL) { 3971 kmem_free(array[i].nfs_argop4_u.oplookup. 3972 objname.utf8string_val, 3973 array[i].nfs_argop4_u.oplookup. 3974 objname.utf8string_len); 3975 } 3976 continue; 3977 case OP_OPEN: 3978 (void) xdr_OPEN4args(xdrs, 3979 &array[i].nfs_argop4_u.opopen); 3980 continue; 3981 case OP_CLOSE: 3982 case OP_ACCESS: 3983 case OP_READ: 3984 continue; 3985 case OP_WRITE: 3986 (void) xdr_WRITE4args(xdrs, 3987 &array[i].nfs_argop4_u.opwrite); 3988 continue; 3989 case OP_DELEGRETURN: 3990 case OP_LOOKUPP: 3991 case OP_READDIR: 3992 continue; 3993 case OP_REMOVE: 3994 if (array[i].nfs_argop4_u.opremove.target. 3995 utf8string_val != NULL) { 3996 kmem_free(array[i].nfs_argop4_u.opremove.target. 3997 utf8string_val, 3998 array[i].nfs_argop4_u.opremove.target. 3999 utf8string_len); 4000 } 4001 continue; 4002 case OP_COMMIT: 4003 continue; 4004 case OP_CREATE: 4005 (void) xdr_CREATE4args(xdrs, 4006 &array[i].nfs_argop4_u.opcreate); 4007 continue; 4008 case OP_DELEGPURGE: 4009 continue; 4010 case OP_LINK: 4011 if (array[i].nfs_argop4_u.oplink.newname. 4012 utf8string_val != NULL) { 4013 kmem_free(array[i].nfs_argop4_u.oplink.newname. 4014 utf8string_val, 4015 array[i].nfs_argop4_u.oplink.newname. 4016 utf8string_len); 4017 } 4018 continue; 4019 case OP_LOCK: 4020 (void) xdr_LOCK4args(xdrs, 4021 &array[i].nfs_argop4_u.oplock); 4022 continue; 4023 case OP_LOCKT: 4024 (void) xdr_LOCKT4args(xdrs, 4025 &array[i].nfs_argop4_u.oplockt); 4026 continue; 4027 case OP_LOCKU: 4028 continue; 4029 case OP_NVERIFY: 4030 (void) xdr_fattr4(xdrs, 4031 &array[i].nfs_argop4_u.opnverify.obj_attributes); 4032 continue; 4033 case OP_OPENATTR: 4034 case OP_OPEN_CONFIRM: 4035 case OP_OPEN_DOWNGRADE: 4036 case OP_PUTPUBFH: 4037 case OP_PUTROOTFH: 4038 case OP_READLINK: 4039 continue; 4040 case OP_RENAME: 4041 if (array[i].nfs_argop4_u.oprename.oldname. 4042 utf8string_val != NULL) { 4043 kmem_free(array[i].nfs_argop4_u.oprename. 4044 oldname.utf8string_val, 4045 array[i].nfs_argop4_u.oprename. 4046 oldname.utf8string_len); 4047 } 4048 if (array[i].nfs_argop4_u.oprename.newname. 4049 utf8string_val != NULL) { 4050 kmem_free(array[i].nfs_argop4_u.oprename. 4051 newname.utf8string_val, 4052 array[i].nfs_argop4_u.oprename. 4053 newname.utf8string_len); 4054 } 4055 continue; 4056 case OP_RENEW: 4057 case OP_RESTOREFH: 4058 case OP_SAVEFH: 4059 continue; 4060 case OP_SECINFO: 4061 if (array[i].nfs_argop4_u.opsecinfo.name. 4062 utf8string_val != NULL) { 4063 kmem_free(array[i].nfs_argop4_u.opsecinfo.name. 4064 utf8string_val, 4065 array[i].nfs_argop4_u.opsecinfo.name. 4066 utf8string_len); 4067 } 4068 continue; 4069 case OP_SETATTR: 4070 (void) xdr_fattr4(xdrs, 4071 &array[i].nfs_argop4_u.opsetattr.obj_attributes); 4072 continue; 4073 case OP_SETCLIENTID: 4074 (void) xdr_SETCLIENTID4args(xdrs, 4075 &array[i].nfs_argop4_u.opsetclientid); 4076 continue; 4077 case OP_SETCLIENTID_CONFIRM: 4078 continue; 4079 case OP_VERIFY: 4080 (void) xdr_fattr4(xdrs, 4081 &array[i].nfs_argop4_u.opverify.obj_attributes); 4082 continue; 4083 case OP_RELEASE_LOCKOWNER: 4084 if (array[i].nfs_argop4_u.oprelease_lockowner. 4085 lock_owner.owner_val != NULL) { 4086 kmem_free(array[i].nfs_argop4_u. 4087 oprelease_lockowner.lock_owner.owner_val, 4088 array[i].nfs_argop4_u. 4089 oprelease_lockowner.lock_owner.owner_len); 4090 } 4091 continue; 4092 case OP_ILLEGAL: 4093 continue; 4094 default: 4095 /* 4096 * An invalid op is a coding error, it should never 4097 * have been decoded. 4098 * Don't error because the caller cannot finish 4099 * freeing the residual memory of the array. 4100 */ 4101 continue; 4102 } 4103 } 4104 4105 kmem_free(*arrayp, len * sizeof (nfs_argop4)); 4106 *arrayp = NULL; 4107 return (TRUE); 4108 } 4109 4110 static bool_t 4111 xdr_nfs_argop4(XDR *xdrs, nfs_argop4 *objp) 4112 { 4113 rdma_chunkinfo_t rci; 4114 struct xdr_ops *xops = xdrrdma_xops(); 4115 4116 /* 4117 * These should be ordered by frequency of use 4118 */ 4119 switch (objp->argop) { 4120 case OP_PUTFH: 4121 return (xdr_bytes(xdrs, 4122 (char **)&objp->nfs_argop4_u.opputfh.object.nfs_fh4_val, 4123 (uint_t *)&objp->nfs_argop4_u.opputfh.object.nfs_fh4_len, 4124 NFS4_FHSIZE)); 4125 case OP_GETATTR: 4126 return (xdr_bitmap4(xdrs, 4127 &objp->nfs_argop4_u.opgetattr.attr_request)); 4128 case OP_GETFH: 4129 return (TRUE); 4130 case OP_LOOKUP: 4131 return (xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.oplookup. 4132 objname.utf8string_val, 4133 (uint_t *)&objp->nfs_argop4_u.oplookup. 4134 objname.utf8string_len, 4135 NFS4_MAX_UTF8STRING)); 4136 case OP_OPEN: 4137 return (xdr_OPEN4args(xdrs, &objp->nfs_argop4_u.opopen)); 4138 case OP_CLOSE: 4139 return (xdr_CLOSE4args(xdrs, &objp->nfs_argop4_u.opclose)); 4140 case OP_ACCESS: 4141 return (xdr_u_int(xdrs, 4142 &objp->nfs_argop4_u.opaccess.access)); 4143 case OP_READ: 4144 return (xdr_READ4args(xdrs, &objp->nfs_argop4_u.opread)); 4145 case OP_WRITE: 4146 return (xdr_WRITE4args(xdrs, &objp->nfs_argop4_u.opwrite)); 4147 case OP_DELEGRETURN: 4148 if (!xdr_u_int(xdrs, 4149 &objp->nfs_argop4_u.opdelegreturn.deleg_stateid.seqid)) 4150 return (FALSE); 4151 return (xdr_opaque(xdrs, 4152 objp->nfs_argop4_u.opdelegreturn.deleg_stateid.other, 12)); 4153 case OP_LOOKUPP: 4154 return (TRUE); 4155 case OP_READDIR: 4156 return (xdr_READDIR4args(xdrs, &objp->nfs_argop4_u.opreaddir)); 4157 case OP_REMOVE: 4158 return (xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.opremove. 4159 target.utf8string_val, 4160 (uint_t *)&objp->nfs_argop4_u.opremove. 4161 target.utf8string_len, 4162 NFS4_MAX_UTF8STRING)); 4163 case OP_COMMIT: 4164 if (!xdr_u_longlong_t(xdrs, 4165 (u_longlong_t *)&objp->nfs_argop4_u.opcommit.offset)) 4166 return (FALSE); 4167 return (xdr_u_int(xdrs, &objp->nfs_argop4_u.opcommit.count)); 4168 case OP_CREATE: 4169 return (xdr_CREATE4args(xdrs, &objp->nfs_argop4_u.opcreate)); 4170 case OP_DELEGPURGE: 4171 return (xdr_u_longlong_t(xdrs, 4172 (u_longlong_t *)&objp->nfs_argop4_u.opdelegpurge.clientid)); 4173 case OP_LINK: 4174 return (xdr_bytes(xdrs, 4175 (char **)&objp->nfs_argop4_u.oplink.newname.utf8string_val, 4176 (uint_t *)&objp->nfs_argop4_u.oplink.newname.utf8string_len, 4177 NFS4_MAX_UTF8STRING)); 4178 case OP_LOCK: 4179 return (xdr_LOCK4args(xdrs, &objp->nfs_argop4_u.oplock)); 4180 case OP_LOCKT: 4181 return (xdr_LOCKT4args(xdrs, &objp->nfs_argop4_u.oplockt)); 4182 case OP_LOCKU: 4183 return (xdr_LOCKU4args(xdrs, &objp->nfs_argop4_u.oplocku)); 4184 case OP_NVERIFY: 4185 return (xdr_fattr4(xdrs, 4186 &objp->nfs_argop4_u.opnverify.obj_attributes)); 4187 case OP_OPENATTR: 4188 return (xdr_bool(xdrs, 4189 &objp->nfs_argop4_u.opopenattr.createdir)); 4190 case OP_OPEN_CONFIRM: 4191 if (!xdr_u_int(xdrs, &objp->nfs_argop4_u.opopen_confirm. 4192 open_stateid.seqid)) 4193 return (FALSE); 4194 if (!xdr_opaque(xdrs, objp->nfs_argop4_u.opopen_confirm. 4195 open_stateid.other, 12)) 4196 return (FALSE); 4197 return (xdr_u_int(xdrs, &objp->nfs_argop4_u.opopen_confirm. 4198 seqid)); 4199 case OP_OPEN_DOWNGRADE: 4200 return (xdr_OPEN_DOWNGRADE4args(xdrs, 4201 &objp->nfs_argop4_u.opopen_downgrade)); 4202 case OP_PUTPUBFH: 4203 return (TRUE); 4204 case OP_PUTROOTFH: 4205 return (TRUE); 4206 case OP_READLINK: 4207 if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) && 4208 xdrs->x_op == XDR_ENCODE) { 4209 rci.rci_type = RCI_REPLY_CHUNK; 4210 rci.rci_len = MAXPATHLEN; 4211 XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci); 4212 } 4213 return (TRUE); 4214 case OP_RENAME: 4215 if (!xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.oprename. 4216 oldname.utf8string_val, 4217 (uint_t *)&objp->nfs_argop4_u.oprename. 4218 oldname.utf8string_len, 4219 NFS4_MAX_UTF8STRING)) 4220 return (FALSE); 4221 return (xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.oprename. 4222 newname.utf8string_val, 4223 (uint_t *)&objp->nfs_argop4_u.oprename. 4224 newname.utf8string_len, 4225 NFS4_MAX_UTF8STRING)); 4226 case OP_RENEW: 4227 return (xdr_u_longlong_t(xdrs, 4228 (u_longlong_t *)&objp->nfs_argop4_u.oprenew.clientid)); 4229 case OP_RESTOREFH: 4230 return (TRUE); 4231 case OP_SAVEFH: 4232 return (TRUE); 4233 case OP_SECINFO: 4234 return (xdr_bytes(xdrs, 4235 (char **)&objp->nfs_argop4_u.opsecinfo.name.utf8string_val, 4236 (uint_t *)&objp->nfs_argop4_u.opsecinfo.name.utf8string_len, 4237 NFS4_MAX_UTF8STRING)); 4238 case OP_SETATTR: 4239 if (!xdr_u_int(xdrs, &objp->nfs_argop4_u.opsetattr. 4240 stateid.seqid)) 4241 return (FALSE); 4242 if (!xdr_opaque(xdrs, objp->nfs_argop4_u.opsetattr. 4243 stateid.other, 12)) 4244 return (FALSE); 4245 return (xdr_fattr4(xdrs, &objp->nfs_argop4_u.opsetattr. 4246 obj_attributes)); 4247 case OP_SETCLIENTID: 4248 return (xdr_SETCLIENTID4args(xdrs, 4249 &objp->nfs_argop4_u.opsetclientid)); 4250 case OP_SETCLIENTID_CONFIRM: 4251 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->nfs_argop4_u. 4252 opsetclientid_confirm.clientid)) 4253 return (FALSE); 4254 return (xdr_u_longlong_t(xdrs, 4255 (u_longlong_t *)&objp->nfs_argop4_u. 4256 opsetclientid_confirm.setclientid_confirm)); 4257 case OP_VERIFY: 4258 return (xdr_fattr4(xdrs, 4259 &objp->nfs_argop4_u.opverify.obj_attributes)); 4260 case OP_RELEASE_LOCKOWNER: 4261 if (!xdr_u_longlong_t(xdrs, 4262 (u_longlong_t *)&objp->nfs_argop4_u. 4263 oprelease_lockowner.lock_owner.clientid)) 4264 return (FALSE); 4265 return (xdr_bytes(xdrs, 4266 (char **)&objp->nfs_argop4_u.oprelease_lockowner. 4267 lock_owner.owner_val, 4268 (uint_t *)&objp->nfs_argop4_u.oprelease_lockowner. 4269 lock_owner.owner_len, NFS4_OPAQUE_LIMIT)); 4270 case OP_ILLEGAL: 4271 return (TRUE); 4272 } 4273 return (FALSE); 4274 } 4275 4276 static bool_t 4277 xdr_cnfs_argop4_wrap(XDR *xdrs, nfs_argop4 *objp) 4278 { 4279 if (!xdr_int(xdrs, (int *)&objp->argop)) 4280 return (FALSE); 4281 4282 return (xdr_nfs_argop4(xdrs, objp)); 4283 } 4284 4285 static bool_t 4286 xdr_snfs_argop4(XDR *xdrs, nfs_argop4 *objp) 4287 { 4288 if (!xdr_int(xdrs, (int *)&objp->argop)) 4289 return (FALSE); 4290 4291 switch (objp->argop) { 4292 case OP_PUTFH: 4293 return (xdr_decode_nfs_fh4(xdrs, 4294 &objp->nfs_argop4_u.opputfh.object)); 4295 default: 4296 return (xdr_nfs_argop4(xdrs, objp)); 4297 } 4298 } 4299 4300 /* 4301 * Client side encode only arg op processing 4302 */ 4303 static bool_t 4304 xdr_cnfs_argop4(XDR *xdrs, nfs_argop4 *objp) 4305 { 4306 int len; 4307 int op; 4308 nfs4_sharedfh_t *sfh; 4309 mntinfo4_t *mi; 4310 rpc_inline_t *ptr; 4311 4312 ASSERT(xdrs->x_op == XDR_ENCODE); 4313 4314 /* 4315 * Special case the private pseudo ops 4316 */ 4317 if (!(objp->argop & SUNW_PRIVATE_OP)) 4318 return (xdr_cnfs_argop4_wrap(xdrs, objp)); 4319 4320 /* 4321 * These should be ordered by frequency of use 4322 */ 4323 switch (objp->argop) { 4324 case OP_CPUTFH: 4325 /* 4326 * We are passed in the file handle as a nfs4_sharedfh_t * 4327 * We need to acquire the correct locks so we can copy it out. 4328 */ 4329 sfh = (nfs4_sharedfh_t *)objp->nfs_argop4_u.opcputfh.sfh; 4330 mi = sfh->sfh_mi; 4331 (void) nfs_rw_enter_sig(&mi->mi_fh_lock, RW_READER, 0); 4332 4333 len = sfh->sfh_fh.nfs_fh4_len; 4334 ASSERT(len <= NFS4_FHSIZE); 4335 4336 /* 4337 * First try and inline the copy 4338 * Must first be a multiple of BYTES_PER_XDR_UNIT 4339 */ 4340 if (!(len % BYTES_PER_XDR_UNIT) && 4341 (ptr = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT + len)) != 4342 NULL) { 4343 IXDR_PUT_U_INT32(ptr, OP_PUTFH); 4344 IXDR_PUT_U_INT32(ptr, len); 4345 bcopy(sfh->sfh_fh.nfs_fh4_val, ptr, len); 4346 nfs_rw_exit(&mi->mi_fh_lock); 4347 return (TRUE); 4348 } 4349 4350 op = OP_PUTFH; 4351 if (!XDR_PUTINT32(xdrs, &op)) { 4352 nfs_rw_exit(&mi->mi_fh_lock); 4353 return (FALSE); 4354 } 4355 if (!XDR_PUTINT32(xdrs, &len)) { 4356 nfs_rw_exit(&mi->mi_fh_lock); 4357 return (FALSE); 4358 } 4359 if (!(len % BYTES_PER_XDR_UNIT)) { 4360 if (XDR_PUTBYTES(xdrs, sfh->sfh_fh.nfs_fh4_val, len)) { 4361 nfs_rw_exit(&mi->mi_fh_lock); 4362 return (TRUE); 4363 } 4364 } else if (xdr_opaque(xdrs, sfh->sfh_fh.nfs_fh4_val, len)) { 4365 nfs_rw_exit(&mi->mi_fh_lock); 4366 return (TRUE); 4367 } 4368 nfs_rw_exit(&mi->mi_fh_lock); 4369 return (FALSE); 4370 case OP_CLOOKUP: 4371 len = strlen(objp->nfs_argop4_u.opclookup.cname); 4372 if (len > NFS4_MAX_UTF8STRING) 4373 return (FALSE); 4374 op = OP_LOOKUP; 4375 if (XDR_PUTINT32(xdrs, &op)) { 4376 if (XDR_PUTINT32(xdrs, &len)) { 4377 return (xdr_opaque(xdrs, 4378 objp->nfs_argop4_u.opclookup.cname, 4379 len)); 4380 } 4381 } 4382 return (FALSE); 4383 case OP_COPEN: 4384 /* op processing inlined in xdr_OPEN4cargs */ 4385 return (xdr_OPEN4cargs(xdrs, &objp->nfs_argop4_u.opcopen)); 4386 case OP_CREMOVE: 4387 len = strlen(objp->nfs_argop4_u.opcremove.ctarget); 4388 if (len > NFS4_MAX_UTF8STRING) 4389 return (FALSE); 4390 op = OP_REMOVE; 4391 if (XDR_PUTINT32(xdrs, &op)) { 4392 if (XDR_PUTINT32(xdrs, &len)) { 4393 return (xdr_opaque(xdrs, 4394 objp->nfs_argop4_u.opcremove.ctarget, 4395 len)); 4396 } 4397 } 4398 return (FALSE); 4399 case OP_CCREATE: 4400 op = OP_CREATE; 4401 if (!XDR_PUTINT32(xdrs, &op)) 4402 return (FALSE); 4403 return (xdr_CREATE4cargs(xdrs, &objp->nfs_argop4_u.opccreate)); 4404 case OP_CLINK: 4405 len = strlen(objp->nfs_argop4_u.opclink.cnewname); 4406 if (len > NFS4_MAX_UTF8STRING) 4407 return (FALSE); 4408 op = OP_LINK; 4409 if (XDR_PUTINT32(xdrs, &op)) { 4410 if (XDR_PUTINT32(xdrs, &len)) { 4411 return (xdr_opaque(xdrs, 4412 objp->nfs_argop4_u.opclink.cnewname, 4413 len)); 4414 } 4415 } 4416 return (FALSE); 4417 case OP_CRENAME: 4418 len = strlen(objp->nfs_argop4_u.opcrename.coldname); 4419 if (len > NFS4_MAX_UTF8STRING) 4420 return (FALSE); 4421 op = OP_RENAME; 4422 if (!XDR_PUTINT32(xdrs, &op)) 4423 return (FALSE); 4424 if (!XDR_PUTINT32(xdrs, &len)) 4425 return (FALSE); 4426 if (!xdr_opaque(xdrs, 4427 objp->nfs_argop4_u.opcrename.coldname, len)) 4428 return (FALSE); 4429 len = strlen(objp->nfs_argop4_u.opcrename.cnewname); 4430 if (len > NFS4_MAX_UTF8STRING) 4431 return (FALSE); 4432 if (XDR_PUTINT32(xdrs, &len)) { 4433 return (xdr_opaque(xdrs, 4434 objp->nfs_argop4_u.opcrename.cnewname, len)); 4435 } 4436 return (FALSE); 4437 case OP_CSECINFO: 4438 len = strlen(objp->nfs_argop4_u.opcsecinfo.cname); 4439 if (len > NFS4_MAX_UTF8STRING) 4440 return (FALSE); 4441 op = OP_SECINFO; 4442 if (XDR_PUTINT32(xdrs, &op)) { 4443 if (XDR_PUTINT32(xdrs, &len)) { 4444 return (xdr_opaque(xdrs, 4445 objp->nfs_argop4_u.opcsecinfo.cname, 4446 len)); 4447 } 4448 } 4449 return (FALSE); 4450 } 4451 return (FALSE); 4452 } 4453 4454 /* 4455 * Note that the len and decode_len will only be different in the case 4456 * of the client's use of this free function. If the server is 4457 * freeing results, then the len/decode_len will always match. 4458 */ 4459 static bool_t 4460 xdr_nfs_resop4_free(XDR *xdrs, nfs_resop4 **arrayp, int len, int decode_len) 4461 { 4462 int i; 4463 nfs_resop4 *array = *arrayp; 4464 nfs4_ga_res_t *gr; 4465 4466 /* 4467 * Optimized XDR_FREE only results array 4468 */ 4469 ASSERT(xdrs->x_op == XDR_FREE); 4470 4471 if (array == NULL) 4472 return (TRUE); 4473 4474 for (i = 0; i < decode_len; i++) { 4475 /* 4476 * These should be ordered by frequency of use 4477 */ 4478 switch (array[i].resop) { 4479 case OP_PUTFH: 4480 continue; 4481 case OP_GETATTR: 4482 if (array[i].nfs_resop4_u.opgetattr.status != NFS4_OK) 4483 continue; 4484 4485 gr = &array[i].nfs_resop4_u.opgetattr.ga_res; 4486 if (gr->n4g_ext_res) { 4487 if (gr->n4g_resbmap & FATTR4_FS_LOCATIONS_MASK) 4488 (void) xdr_fattr4_fs_locations(xdrs, 4489 &gr->n4g_ext_res->n4g_fslocations); 4490 kmem_free(gr->n4g_ext_res, 4491 sizeof (struct nfs4_ga_ext_res)); 4492 } 4493 continue; 4494 case OP_GETFH: 4495 if (array[i].nfs_resop4_u.opgetfh.status != NFS4_OK) 4496 continue; 4497 if (array[i].nfs_resop4_u.opgetfh.object.nfs_fh4_val != 4498 NULL) { 4499 kmem_free(array[i].nfs_resop4_u.opgetfh.object. 4500 nfs_fh4_val, 4501 array[i].nfs_resop4_u.opgetfh.object. 4502 nfs_fh4_len); 4503 } 4504 continue; 4505 case OP_LOOKUP: 4506 continue; 4507 case OP_OPEN: 4508 (void) xdr_OPEN4res(xdrs, &array[i].nfs_resop4_u. 4509 opopen); 4510 continue; 4511 case OP_CLOSE: 4512 case OP_ACCESS: 4513 continue; 4514 case OP_READ: 4515 (void) xdr_READ4res(xdrs, 4516 &array[i].nfs_resop4_u.opread); 4517 continue; 4518 case OP_WRITE: 4519 case OP_DELEGRETURN: 4520 case OP_LOOKUPP: 4521 case OP_READDIR: 4522 case OP_REMOVE: 4523 case OP_COMMIT: 4524 case OP_CREATE: 4525 case OP_DELEGPURGE: 4526 case OP_LINK: 4527 continue; 4528 case OP_LOCK: 4529 (void) xdr_LOCK4res(xdrs, &array[i].nfs_resop4_u. 4530 oplock); 4531 continue; 4532 case OP_LOCKT: 4533 (void) xdr_LOCKT4res(xdrs, &array[i].nfs_resop4_u. 4534 oplockt); 4535 continue; 4536 case OP_LOCKU: 4537 case OP_NVERIFY: 4538 case OP_OPENATTR: 4539 case OP_OPEN_CONFIRM: 4540 case OP_OPEN_DOWNGRADE: 4541 case OP_PUTPUBFH: 4542 case OP_PUTROOTFH: 4543 case OP_RENAME: 4544 case OP_RENEW: 4545 case OP_RESTOREFH: 4546 case OP_SAVEFH: 4547 continue; 4548 case OP_READLINK: 4549 (void) xdr_READLINK4res(xdrs, &array[i].nfs_resop4_u. 4550 opreadlink); 4551 continue; 4552 case OP_SECINFO: 4553 (void) xdr_array(xdrs, 4554 (char **)&array[i].nfs_resop4_u.opsecinfo. 4555 SECINFO4resok_val, 4556 (uint_t *)&array[i].nfs_resop4_u.opsecinfo. 4557 SECINFO4resok_len, 4558 NFS4_SECINFO_LIMIT, sizeof (secinfo4), 4559 (xdrproc_t)xdr_secinfo4); 4560 continue; 4561 case OP_SETCLIENTID: 4562 (void) xdr_SETCLIENTID4res(xdrs, 4563 &array[i].nfs_resop4_u.opsetclientid); 4564 continue; 4565 case OP_SETATTR: 4566 case OP_SETCLIENTID_CONFIRM: 4567 case OP_VERIFY: 4568 case OP_RELEASE_LOCKOWNER: 4569 case OP_ILLEGAL: 4570 continue; 4571 default: 4572 /* 4573 * An invalid op is a coding error, it should never 4574 * have been decoded. 4575 * Don't error because the caller cannot finish 4576 * freeing the residual memory of the array. 4577 */ 4578 continue; 4579 } 4580 } 4581 4582 kmem_free(*arrayp, len * sizeof (nfs_resop4)); 4583 *arrayp = NULL; 4584 return (TRUE); 4585 } 4586 4587 static bool_t 4588 xdr_snfs_resop4_free(XDR *xdrs, nfs_resop4 **arrayp, int len, int decode_len) 4589 { 4590 return (xdr_nfs_resop4_free(xdrs, arrayp, len, decode_len)); 4591 } 4592 4593 static bool_t 4594 xdr_nfs_resop4(XDR *xdrs, nfs_resop4 *objp) 4595 { 4596 /* 4597 * These should be ordered by frequency of use 4598 */ 4599 switch (objp->resop) { 4600 case OP_PUTFH: 4601 return (xdr_int(xdrs, 4602 (int32_t *)&objp->nfs_resop4_u.opputfh.status)); 4603 case OP_GETATTR: 4604 if (!xdr_int(xdrs, 4605 (int32_t *)&objp->nfs_resop4_u.opgetattr.status)) 4606 return (FALSE); 4607 if (objp->nfs_resop4_u.opgetattr.status != NFS4_OK) 4608 return (TRUE); 4609 return (xdr_fattr4(xdrs, 4610 &objp->nfs_resop4_u.opgetattr.obj_attributes)); 4611 case OP_GETFH: 4612 if (!xdr_int(xdrs, 4613 (int32_t *)&objp->nfs_resop4_u.opgetfh.status)) 4614 return (FALSE); 4615 if (objp->nfs_resop4_u.opgetfh.status != NFS4_OK) 4616 return (TRUE); 4617 return (xdr_bytes(xdrs, 4618 (char **)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_val, 4619 (uint_t *)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_len, 4620 NFS4_FHSIZE)); 4621 case OP_LOOKUP: 4622 return (xdr_int(xdrs, 4623 (int32_t *)&objp->nfs_resop4_u.oplookup.status)); 4624 case OP_OPEN: 4625 return (xdr_OPEN4res(xdrs, &objp->nfs_resop4_u.opopen)); 4626 case OP_CLOSE: 4627 return (xdr_CLOSE4res(xdrs, &objp->nfs_resop4_u.opclose)); 4628 case OP_ACCESS: 4629 return (xdr_ACCESS4res(xdrs, &objp->nfs_resop4_u.opaccess)); 4630 case OP_READ: 4631 return (xdr_READ4res(xdrs, &objp->nfs_resop4_u.opread)); 4632 case OP_WRITE: 4633 return (xdr_WRITE4res(xdrs, &objp->nfs_resop4_u.opwrite)); 4634 case OP_DELEGRETURN: 4635 return (xdr_int(xdrs, 4636 (int32_t *)&objp->nfs_resop4_u.opdelegreturn.status)); 4637 case OP_LOOKUPP: 4638 return (xdr_int(xdrs, 4639 (int32_t *)&objp->nfs_resop4_u.oplookupp.status)); 4640 case OP_READDIR: 4641 return (xdr_READDIR4res(xdrs, &objp->nfs_resop4_u.opreaddir)); 4642 case OP_REMOVE: 4643 return (xdr_REMOVE4res(xdrs, &objp->nfs_resop4_u.opremove)); 4644 4645 case OP_COMMIT: 4646 if (!xdr_int(xdrs, 4647 (int32_t *)&objp->nfs_resop4_u.opcommit.status)) 4648 return (FALSE); 4649 if (objp->nfs_resop4_u.opcommit.status != NFS4_OK) 4650 return (TRUE); 4651 return (xdr_u_longlong_t(xdrs, 4652 (u_longlong_t *)&objp->nfs_resop4_u.opcommit. 4653 writeverf)); 4654 case OP_CREATE: 4655 return (xdr_CREATE4res(xdrs, &objp->nfs_resop4_u.opcreate)); 4656 case OP_DELEGPURGE: 4657 return (xdr_int(xdrs, 4658 (int32_t *)&objp->nfs_resop4_u.opdelegpurge.status)); 4659 case OP_LINK: 4660 return (xdr_LINK4res(xdrs, &objp->nfs_resop4_u.oplink)); 4661 case OP_LOCK: 4662 return (xdr_LOCK4res(xdrs, &objp->nfs_resop4_u.oplock)); 4663 case OP_LOCKT: 4664 return (xdr_LOCKT4res(xdrs, &objp->nfs_resop4_u.oplockt)); 4665 case OP_LOCKU: 4666 if (!xdr_int(xdrs, 4667 (int32_t *)&objp->nfs_resop4_u.oplocku.status)) 4668 return (FALSE); 4669 if (objp->nfs_resop4_u.oplocku.status != NFS4_OK) 4670 return (TRUE); 4671 if (!xdr_u_int(xdrs, 4672 &objp->nfs_resop4_u.oplocku.lock_stateid.seqid)) 4673 return (FALSE); 4674 return (xdr_opaque(xdrs, 4675 objp->nfs_resop4_u.oplocku.lock_stateid.other, 4676 12)); 4677 case OP_NVERIFY: 4678 return (xdr_int(xdrs, 4679 (int32_t *)&objp->nfs_resop4_u.opnverify.status)); 4680 case OP_OPENATTR: 4681 return (xdr_int(xdrs, 4682 (int32_t *)&objp->nfs_resop4_u.opopenattr.status)); 4683 case OP_OPEN_CONFIRM: 4684 return (xdr_OPEN_CONFIRM4res(xdrs, 4685 &objp->nfs_resop4_u.opopen_confirm)); 4686 case OP_OPEN_DOWNGRADE: 4687 return (xdr_OPEN_DOWNGRADE4res(xdrs, 4688 &objp->nfs_resop4_u.opopen_downgrade)); 4689 case OP_PUTPUBFH: 4690 return (xdr_int(xdrs, 4691 (int32_t *)&objp->nfs_resop4_u.opputpubfh.status)); 4692 case OP_PUTROOTFH: 4693 return (xdr_int(xdrs, 4694 (int32_t *)&objp->nfs_resop4_u.opputrootfh.status)); 4695 case OP_READLINK: 4696 return (xdr_READLINK4res(xdrs, &objp->nfs_resop4_u.opreadlink)); 4697 case OP_RENAME: 4698 return (xdr_RENAME4res(xdrs, &objp->nfs_resop4_u.oprename)); 4699 case OP_RENEW: 4700 return (xdr_int(xdrs, 4701 (int32_t *)&objp->nfs_resop4_u.oprenew.status)); 4702 case OP_RESTOREFH: 4703 return (xdr_int(xdrs, 4704 (int32_t *)&objp->nfs_resop4_u.oprestorefh.status)); 4705 case OP_SAVEFH: 4706 return (xdr_int(xdrs, 4707 (int32_t *)&objp->nfs_resop4_u.opsavefh.status)); 4708 case OP_SECINFO: 4709 if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsecinfo. 4710 status)) 4711 return (FALSE); 4712 if (objp->nfs_resop4_u.opsecinfo.status != NFS4_OK) 4713 return (TRUE); 4714 return (xdr_array(xdrs, (char **)&objp->nfs_resop4_u.opsecinfo. 4715 SECINFO4resok_val, 4716 (uint_t *)&objp->nfs_resop4_u.opsecinfo. 4717 SECINFO4resok_len, 4718 NFS4_SECINFO_LIMIT, sizeof (secinfo4), 4719 (xdrproc_t)xdr_secinfo4)); 4720 case OP_SETATTR: 4721 if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsetattr. 4722 status)) 4723 return (FALSE); 4724 return (xdr_bitmap4(xdrs, 4725 &objp->nfs_resop4_u.opsetattr.attrsset)); 4726 case OP_SETCLIENTID: 4727 return (xdr_SETCLIENTID4res(xdrs, 4728 &objp->nfs_resop4_u.opsetclientid)); 4729 case OP_SETCLIENTID_CONFIRM: 4730 return (xdr_int(xdrs, 4731 (int32_t *)&objp->nfs_resop4_u.opsetclientid_confirm. 4732 status)); 4733 case OP_VERIFY: 4734 return (xdr_int(xdrs, 4735 (int32_t *)&objp->nfs_resop4_u.opverify.status)); 4736 case OP_RELEASE_LOCKOWNER: 4737 return (xdr_int(xdrs, 4738 (int32_t *)&objp->nfs_resop4_u.oprelease_lockowner.status)); 4739 case OP_ILLEGAL: 4740 return (xdr_int(xdrs, 4741 (int32_t *)&objp->nfs_resop4_u.opillegal.status)); 4742 } 4743 return (FALSE); 4744 } 4745 4746 static bool_t 4747 xdr_snfs_resop4(XDR *xdrs, nfs_resop4 *objp) 4748 { 4749 if (!xdr_int(xdrs, (int *)&objp->resop)) 4750 return (FALSE); 4751 4752 switch (objp->resop) { 4753 case OP_GETFH: 4754 if (!XDR_PUTINT32(xdrs, 4755 (int32_t *)&objp->nfs_resop4_u.opgetfh.status)) 4756 return (FALSE); 4757 if (objp->nfs_resop4_u.opgetfh.status != NFS4_OK) 4758 return (TRUE); 4759 return (xdr_encode_nfs_fh4(xdrs, 4760 &objp->nfs_resop4_u.opgetfh.object)); 4761 default: 4762 return (xdr_nfs_resop4(xdrs, objp)); 4763 } 4764 } 4765 4766 static bool_t 4767 xdr_nfs_resop4_clnt(XDR *xdrs, nfs_resop4 *objp, nfs_argop4 *aobjp) 4768 { 4769 if (!xdr_int(xdrs, (int *)&objp->resop)) 4770 return (FALSE); 4771 /* 4772 * These should be ordered by frequency of use 4773 */ 4774 switch (objp->resop) { 4775 case OP_PUTFH: 4776 return (xdr_int(xdrs, 4777 (int32_t *)&objp->nfs_resop4_u.opputfh.status)); 4778 case OP_GETATTR: 4779 if (!xdr_int(xdrs, 4780 (int32_t *)&objp->nfs_resop4_u.opgetattr.status)) 4781 return (FALSE); 4782 if (objp->nfs_resop4_u.opgetattr.status != NFS4_OK) 4783 return (TRUE); 4784 return (xdr_ga_res(xdrs, 4785 (GETATTR4res *)&objp->nfs_resop4_u.opgetattr, 4786 &aobjp->nfs_argop4_u.opgetattr)); 4787 case OP_GETFH: 4788 if (!xdr_int(xdrs, 4789 (int32_t *)&objp->nfs_resop4_u.opgetfh.status)) 4790 return (FALSE); 4791 if (objp->nfs_resop4_u.opgetfh.status != NFS4_OK) 4792 return (TRUE); 4793 return (xdr_bytes(xdrs, 4794 (char **)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_val, 4795 (uint_t *)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_len, 4796 NFS4_FHSIZE)); 4797 case OP_LOOKUP: 4798 return (xdr_int(xdrs, 4799 (int32_t *)&objp->nfs_resop4_u.oplookup.status)); 4800 case OP_NVERIFY: 4801 return (xdr_int(xdrs, 4802 (int32_t *)&objp->nfs_resop4_u.opnverify.status)); 4803 case OP_OPEN: 4804 return (xdr_OPEN4res(xdrs, &objp->nfs_resop4_u.opopen)); 4805 case OP_CLOSE: 4806 return (xdr_CLOSE4res(xdrs, &objp->nfs_resop4_u.opclose)); 4807 case OP_ACCESS: 4808 return (xdr_ACCESS4res(xdrs, &objp->nfs_resop4_u.opaccess)); 4809 case OP_READ: 4810 return (xdr_READ4res_clnt(xdrs, &objp->nfs_resop4_u.opread, 4811 &aobjp->nfs_argop4_u.opread)); 4812 case OP_WRITE: 4813 return (xdr_WRITE4res(xdrs, &objp->nfs_resop4_u.opwrite)); 4814 case OP_DELEGRETURN: 4815 return (xdr_int(xdrs, 4816 (int32_t *)&objp->nfs_resop4_u.opdelegreturn.status)); 4817 case OP_LOOKUPP: 4818 return (xdr_int(xdrs, 4819 (int32_t *)&objp->nfs_resop4_u.oplookupp.status)); 4820 case OP_READDIR: 4821 return (xdr_READDIR4res_clnt(xdrs, 4822 &objp->nfs_resop4_u.opreaddirclnt, 4823 &aobjp->nfs_argop4_u.opreaddir)); 4824 case OP_REMOVE: 4825 return (xdr_REMOVE4res(xdrs, &objp->nfs_resop4_u.opremove)); 4826 4827 case OP_COMMIT: 4828 if (!xdr_int(xdrs, 4829 (int32_t *)&objp->nfs_resop4_u.opcommit.status)) 4830 return (FALSE); 4831 if (objp->nfs_resop4_u.opcommit.status != NFS4_OK) 4832 return (TRUE); 4833 return (xdr_u_longlong_t(xdrs, 4834 (u_longlong_t *)&objp->nfs_resop4_u.opcommit. 4835 writeverf)); 4836 case OP_CREATE: 4837 return (xdr_CREATE4res(xdrs, &objp->nfs_resop4_u.opcreate)); 4838 case OP_DELEGPURGE: 4839 return (xdr_int(xdrs, 4840 (int32_t *)&objp->nfs_resop4_u.opdelegpurge.status)); 4841 case OP_LINK: 4842 return (xdr_LINK4res(xdrs, &objp->nfs_resop4_u.oplink)); 4843 case OP_LOCK: 4844 return (xdr_LOCK4res(xdrs, &objp->nfs_resop4_u.oplock)); 4845 case OP_LOCKT: 4846 return (xdr_LOCKT4res(xdrs, &objp->nfs_resop4_u.oplockt)); 4847 case OP_LOCKU: 4848 if (!xdr_int(xdrs, 4849 (int32_t *)&objp->nfs_resop4_u.oplocku.status)) 4850 return (FALSE); 4851 if (objp->nfs_resop4_u.oplocku.status != NFS4_OK) 4852 return (TRUE); 4853 if (!xdr_u_int(xdrs, 4854 &objp->nfs_resop4_u.oplocku.lock_stateid.seqid)) 4855 return (FALSE); 4856 return (xdr_opaque(xdrs, 4857 objp->nfs_resop4_u.oplocku.lock_stateid.other, 4858 12)); 4859 case OP_OPENATTR: 4860 return (xdr_int(xdrs, 4861 (int32_t *)&objp->nfs_resop4_u.opopenattr.status)); 4862 case OP_OPEN_CONFIRM: 4863 return (xdr_OPEN_CONFIRM4res(xdrs, 4864 &objp->nfs_resop4_u.opopen_confirm)); 4865 case OP_OPEN_DOWNGRADE: 4866 return (xdr_OPEN_DOWNGRADE4res(xdrs, 4867 &objp->nfs_resop4_u.opopen_downgrade)); 4868 case OP_PUTPUBFH: 4869 return (xdr_int(xdrs, 4870 (int32_t *)&objp->nfs_resop4_u.opputpubfh.status)); 4871 case OP_PUTROOTFH: 4872 return (xdr_int(xdrs, 4873 (int32_t *)&objp->nfs_resop4_u.opputrootfh.status)); 4874 case OP_READLINK: 4875 return (xdr_READLINK4res(xdrs, &objp->nfs_resop4_u.opreadlink)); 4876 case OP_RENAME: 4877 return (xdr_RENAME4res(xdrs, &objp->nfs_resop4_u.oprename)); 4878 case OP_RENEW: 4879 return (xdr_int(xdrs, 4880 (int32_t *)&objp->nfs_resop4_u.oprenew.status)); 4881 case OP_RESTOREFH: 4882 return (xdr_int(xdrs, 4883 (int32_t *)&objp->nfs_resop4_u.oprestorefh.status)); 4884 case OP_SAVEFH: 4885 return (xdr_int(xdrs, 4886 (int32_t *)&objp->nfs_resop4_u.opsavefh.status)); 4887 case OP_SECINFO: 4888 if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsecinfo. 4889 status)) 4890 return (FALSE); 4891 if (objp->nfs_resop4_u.opsecinfo.status != NFS4_OK) 4892 return (TRUE); 4893 return (xdr_array(xdrs, (char **)&objp->nfs_resop4_u.opsecinfo. 4894 SECINFO4resok_val, 4895 (uint_t *)&objp->nfs_resop4_u.opsecinfo. 4896 SECINFO4resok_len, 4897 ~0, sizeof (secinfo4), (xdrproc_t)xdr_secinfo4)); 4898 case OP_SETATTR: 4899 if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsetattr. 4900 status)) 4901 return (FALSE); 4902 return (xdr_bitmap4(xdrs, 4903 &objp->nfs_resop4_u.opsetattr.attrsset)); 4904 case OP_SETCLIENTID: 4905 return (xdr_SETCLIENTID4res(xdrs, 4906 &objp->nfs_resop4_u.opsetclientid)); 4907 case OP_SETCLIENTID_CONFIRM: 4908 return (xdr_int(xdrs, 4909 (int32_t *)&objp->nfs_resop4_u.opsetclientid_confirm. 4910 status)); 4911 case OP_VERIFY: 4912 return (xdr_int(xdrs, 4913 (int32_t *)&objp->nfs_resop4_u.opverify.status)); 4914 case OP_RELEASE_LOCKOWNER: 4915 return (xdr_int(xdrs, 4916 (int32_t *)&objp->nfs_resop4_u.oprelease_lockowner.status)); 4917 case OP_ILLEGAL: 4918 return (xdr_int(xdrs, 4919 (int32_t *)&objp->nfs_resop4_u.opillegal.status)); 4920 } 4921 return (FALSE); 4922 } 4923 4924 bool_t 4925 xdr_COMPOUND4args_clnt(XDR *xdrs, COMPOUND4args_clnt *objp) 4926 { 4927 static int32_t twelve = 12; 4928 static int32_t minorversion = NFS4_MINORVERSION; 4929 uint32_t *ctagp; 4930 rpc_inline_t *ptr; 4931 rdma_chunkinfo_t rci; 4932 struct xdr_ops *xops = xdrrdma_xops(); 4933 4934 /* 4935 * XDR_ENCODE only 4936 */ 4937 if (xdrs->x_op == XDR_FREE) 4938 return (TRUE); 4939 if (xdrs->x_op == XDR_DECODE) 4940 return (FALSE); 4941 4942 ctagp = (uint32_t *)&nfs4_ctags[objp->ctag].ct_tag; 4943 4944 if ((ptr = XDR_INLINE(xdrs, 5 * BYTES_PER_XDR_UNIT)) != NULL) { 4945 /* 4946 * Efficiently encode fixed length tags, could be longlongs 4947 * but 8 byte XDR alignment not assured 4948 */ 4949 IXDR_PUT_U_INT32(ptr, 12); 4950 IXDR_PUT_U_INT32(ptr, ctagp[0]); 4951 IXDR_PUT_U_INT32(ptr, ctagp[1]); 4952 IXDR_PUT_U_INT32(ptr, ctagp[2]); 4953 4954 /* 4955 * Fixed minor version for now 4956 */ 4957 IXDR_PUT_U_INT32(ptr, NFS4_MINORVERSION); 4958 } else { 4959 if (!XDR_PUTINT32(xdrs, &twelve)) 4960 return (FALSE); 4961 if (!XDR_PUTINT32(xdrs, (int32_t *)&ctagp[0])) 4962 return (FALSE); 4963 if (!XDR_PUTINT32(xdrs, (int32_t *)&ctagp[1])) 4964 return (FALSE); 4965 if (!XDR_PUTINT32(xdrs, (int32_t *)&ctagp[2])) 4966 return (FALSE); 4967 if (!XDR_PUTINT32(xdrs, (int32_t *)&minorversion)) 4968 return (FALSE); 4969 } 4970 if (xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) { 4971 rci.rci_type = RCI_REPLY_CHUNK; 4972 rci.rci_len = MAXPATHLEN * 2; 4973 XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci); 4974 } 4975 4976 return (xdr_array(xdrs, (char **)&objp->array, 4977 (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT, 4978 sizeof (nfs_argop4), (xdrproc_t)xdr_cnfs_argop4)); 4979 } 4980 4981 bool_t 4982 xdr_COMPOUND4args_srv(XDR *xdrs, COMPOUND4args *objp) 4983 { 4984 if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val, 4985 (uint_t *)&objp->tag.utf8string_len, 4986 NFS4_MAX_UTF8STRING)) 4987 return (FALSE); 4988 if (!xdr_u_int(xdrs, &objp->minorversion)) 4989 return (FALSE); 4990 if (xdrs->x_op != XDR_FREE) 4991 return (xdr_array(xdrs, (char **)&objp->array, 4992 (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT, 4993 sizeof (nfs_argop4), (xdrproc_t)xdr_snfs_argop4)); 4994 4995 return (xdr_snfs_argop4_free(xdrs, &objp->array, objp->array_len)); 4996 } 4997 4998 bool_t 4999 xdr_COMPOUND4res_clnt(XDR *xdrs, COMPOUND4res_clnt *objp) 5000 { 5001 uint32_t len; 5002 int32_t *ptr; 5003 nfs_argop4 *argop; 5004 nfs_resop4 *resop; 5005 5006 /* 5007 * No XDR_ENCODE 5008 */ 5009 if (xdrs->x_op == XDR_ENCODE) 5010 return (FALSE); 5011 5012 if (xdrs->x_op != XDR_FREE) { 5013 if ((ptr = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT)) != NULL) { 5014 objp->status = IXDR_GET_U_INT32(ptr); 5015 len = IXDR_GET_U_INT32(ptr); 5016 } else { 5017 if (!xdr_int(xdrs, (int32_t *)&objp->status)) 5018 return (FALSE); 5019 if (!xdr_u_int(xdrs, (uint32_t *)&len)) 5020 return (FALSE); 5021 } 5022 if (len > NFS4_MAX_UTF8STRING) 5023 return (FALSE); 5024 /* 5025 * Ignore the tag 5026 */ 5027 if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &len)) 5028 return (FALSE); 5029 5030 if (!xdr_int(xdrs, (int32_t *)&objp->array_len)) 5031 return (FALSE); 5032 5033 if (objp->array_len > objp->argsp->array_len) 5034 return (FALSE); 5035 5036 if (objp->status == NFS_OK && 5037 objp->array_len != objp->argsp->array_len) 5038 return (FALSE); 5039 5040 /* Alloc the results array */ 5041 argop = objp->argsp->array; 5042 len = objp->array_len * sizeof (nfs_resop4); 5043 objp->decode_len = 0; 5044 objp->array = resop = kmem_zalloc(len, KM_SLEEP); 5045 5046 for (len = 0; len < objp->array_len; 5047 len++, resop++, argop++, objp->decode_len++) { 5048 if (!xdr_nfs_resop4_clnt(xdrs, resop, argop)) { 5049 /* 5050 * Make sure to free anything that may 5051 * have been allocated along the way. 5052 */ 5053 xdrs->x_op = XDR_FREE; 5054 (void) xdr_nfs_resop4_free(xdrs, &objp->array, 5055 objp->array_len, 5056 objp->decode_len); 5057 return (FALSE); 5058 } 5059 } 5060 return (TRUE); 5061 } 5062 return (xdr_nfs_resop4_free(xdrs, &objp->array, 5063 objp->array_len, objp->decode_len)); 5064 } 5065 5066 bool_t 5067 xdr_COMPOUND4res_srv(XDR *xdrs, COMPOUND4res *objp) 5068 { 5069 if (!xdr_int(xdrs, (int32_t *)&objp->status)) 5070 return (FALSE); 5071 if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val, 5072 (uint_t *)&objp->tag.utf8string_len, 5073 NFS4_MAX_UTF8STRING)) 5074 return (FALSE); 5075 5076 if (xdrs->x_op != XDR_FREE) 5077 return (xdr_array(xdrs, (char **)&objp->array, 5078 (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT, 5079 sizeof (nfs_resop4), (xdrproc_t)xdr_snfs_resop4)); 5080 5081 return (xdr_snfs_resop4_free(xdrs, &objp->array, 5082 objp->array_len, objp->array_len)); 5083 } 5084 5085 /* 5086 * NFS server side callback, initiating the callback request so it 5087 * is the RPC client. Must convert from server's internal filehandle 5088 * format to wire format. 5089 */ 5090 static bool_t 5091 xdr_snfs_cb_argop4(XDR *xdrs, nfs_cb_argop4 *objp) 5092 { 5093 CB_GETATTR4args *gargs; 5094 CB_RECALL4args *rargs; 5095 5096 ASSERT(xdrs->x_op == XDR_ENCODE); 5097 5098 if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->argop)) 5099 return (FALSE); 5100 5101 switch (objp->argop) { 5102 case OP_CB_GETATTR: 5103 gargs = &objp->nfs_cb_argop4_u.opcbgetattr; 5104 5105 if (!xdr_encode_nfs_fh4(xdrs, &gargs->fh)) 5106 return (FALSE); 5107 return (xdr_bitmap4(xdrs, &gargs->attr_request)); 5108 case OP_CB_RECALL: 5109 rargs = &objp->nfs_cb_argop4_u.opcbrecall; 5110 5111 if (!XDR_PUTINT32(xdrs, (int32_t *)&rargs->stateid.seqid)) 5112 return (FALSE); 5113 if (!xdr_opaque(xdrs, rargs->stateid.other, 12)) 5114 return (FALSE); 5115 if (!XDR_PUTINT32(xdrs, (int32_t *)&rargs->truncate)) 5116 return (FALSE); 5117 return (xdr_encode_nfs_fh4(xdrs, &rargs->fh)); 5118 case OP_CB_ILLEGAL: 5119 return (TRUE); 5120 } 5121 return (FALSE); 5122 } 5123 5124 /* 5125 * NFS client side callback, receiving the callback request so it 5126 * is the RPC server. Must treat the file handles as opaque. 5127 */ 5128 static bool_t 5129 xdr_cnfs_cb_argop4(XDR *xdrs, nfs_cb_argop4 *objp) 5130 { 5131 CB_GETATTR4args *gargs; 5132 CB_RECALL4args *rargs; 5133 5134 ASSERT(xdrs->x_op != XDR_ENCODE); 5135 5136 if (!xdr_u_int(xdrs, &objp->argop)) 5137 return (FALSE); 5138 switch (objp->argop) { 5139 case OP_CB_GETATTR: 5140 gargs = &objp->nfs_cb_argop4_u.opcbgetattr; 5141 5142 if (!xdr_bytes(xdrs, (char **)&gargs->fh.nfs_fh4_val, 5143 (uint_t *)&gargs->fh.nfs_fh4_len, NFS4_FHSIZE)) 5144 return (FALSE); 5145 return (xdr_bitmap4(xdrs, &gargs->attr_request)); 5146 case OP_CB_RECALL: 5147 rargs = &objp->nfs_cb_argop4_u.opcbrecall; 5148 5149 if (!xdr_u_int(xdrs, &rargs->stateid.seqid)) 5150 return (FALSE); 5151 if (!xdr_opaque(xdrs, rargs->stateid.other, 12)) 5152 return (FALSE); 5153 if (!xdr_bool(xdrs, &rargs->truncate)) 5154 return (FALSE); 5155 return (xdr_bytes(xdrs, (char **)&rargs->fh.nfs_fh4_val, 5156 (uint_t *)&rargs->fh.nfs_fh4_len, NFS4_FHSIZE)); 5157 case OP_CB_ILLEGAL: 5158 return (TRUE); 5159 } 5160 return (FALSE); 5161 } 5162 5163 static bool_t 5164 xdr_nfs_cb_resop4(XDR *xdrs, nfs_cb_resop4 *objp) 5165 { 5166 if (!xdr_u_int(xdrs, &objp->resop)) 5167 return (FALSE); 5168 switch (objp->resop) { 5169 case OP_CB_GETATTR: 5170 if (!xdr_int(xdrs, 5171 (int32_t *)&objp->nfs_cb_resop4_u.opcbgetattr. 5172 status)) 5173 return (FALSE); 5174 if (objp->nfs_cb_resop4_u.opcbgetattr.status != NFS4_OK) 5175 return (TRUE); 5176 return (xdr_fattr4(xdrs, 5177 &objp->nfs_cb_resop4_u.opcbgetattr. 5178 obj_attributes)); 5179 case OP_CB_RECALL: 5180 return (xdr_int(xdrs, 5181 (int32_t *)&objp->nfs_cb_resop4_u.opcbrecall.status)); 5182 case OP_CB_ILLEGAL: 5183 return (xdr_int(xdrs, 5184 (int32_t *)&objp->nfs_cb_resop4_u.opcbillegal.status)); 5185 } 5186 return (FALSE); 5187 } 5188 5189 /* 5190 * The NFS client side callback, RPC server 5191 */ 5192 bool_t 5193 xdr_CB_COMPOUND4args_clnt(XDR *xdrs, CB_COMPOUND4args *objp) 5194 { 5195 if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val, 5196 (uint_t *)&objp->tag.utf8string_len, 5197 NFS4_MAX_UTF8STRING)) 5198 return (FALSE); 5199 if (!xdr_u_int(xdrs, &objp->minorversion)) 5200 return (FALSE); 5201 if (!xdr_u_int(xdrs, &objp->callback_ident)) 5202 return (FALSE); 5203 return (xdr_array(xdrs, (char **)&objp->array, 5204 (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT, 5205 sizeof (nfs_cb_argop4), (xdrproc_t)xdr_cnfs_cb_argop4)); 5206 } 5207 5208 /* 5209 * The NFS server side callback, RPC client 5210 */ 5211 bool_t 5212 xdr_CB_COMPOUND4args_srv(XDR *xdrs, CB_COMPOUND4args *objp) 5213 { 5214 if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val, 5215 (uint_t *)&objp->tag.utf8string_len, 5216 NFS4_MAX_UTF8STRING)) 5217 return (FALSE); 5218 if (!xdr_u_int(xdrs, &objp->minorversion)) 5219 return (FALSE); 5220 if (!xdr_u_int(xdrs, &objp->callback_ident)) 5221 return (FALSE); 5222 return (xdr_array(xdrs, (char **)&objp->array, 5223 (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT, 5224 sizeof (nfs_cb_argop4), (xdrproc_t)xdr_snfs_cb_argop4)); 5225 } 5226 5227 bool_t 5228 xdr_CB_COMPOUND4res(XDR *xdrs, CB_COMPOUND4res *objp) 5229 { 5230 if (!xdr_int(xdrs, (int32_t *)&objp->status)) 5231 return (FALSE); 5232 if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val, 5233 (uint_t *)&objp->tag.utf8string_len, 5234 NFS4_MAX_UTF8STRING)) 5235 return (FALSE); 5236 return (xdr_array(xdrs, (char **)&objp->array, 5237 (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT, 5238 sizeof (nfs_cb_resop4), (xdrproc_t)xdr_nfs_cb_resop4)); 5239 } 5240