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