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