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