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