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