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