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