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