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