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