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