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