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