1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/systm.h> 27 #include <sys/cmn_err.h> 28 #include <nfs/nfs.h> 29 #include <nfs/export.h> 30 #include <nfs/nfs4.h> 31 #include <sys/ddi.h> 32 33 void rfs4_init_compound_state(struct compound_state *); 34 35 bitmap4 rfs4_supported_attrs; 36 int MSG_PRT_DEBUG = FALSE; 37 38 /* If building with DEBUG enabled, enable mandattr tunable by default */ 39 #ifdef DEBUG 40 #ifndef RFS4_SUPPORT_MANDATTR_ONLY 41 #define RFS4_SUPPORT_MANDATTR_ONLY 42 #endif 43 #endif 44 45 /* 46 * If building with mandattr only code, disable it by default. 47 * To enable, set rfs4_mandattr_only in /etc/system and reboot. 48 * When building without mandattr ifdef, the compiler should 49 * optimize away the the comparisons because RFS4_MANDATTR_ONLY 50 * is defined to be 0. 51 */ 52 #ifdef RFS4_SUPPORT_MANDATTR_ONLY 53 #define NFS4_LAST_MANDATTR FATTR4_RDATTR_ERROR 54 #define RFS4_MANDATTR_ONLY rfs4_mandattr_only 55 int rfs4_mandattr_only = 0; 56 #else 57 #define RFS4_MANDATTR_ONLY 0 58 #endif 59 60 61 static void rfs4_ntov_init(void); 62 static int rfs4_fattr4_supported_attrs(); 63 static int rfs4_fattr4_type(); 64 static int rfs4_fattr4_fh_expire_type(); 65 static int rfs4_fattr4_change(); 66 static int rfs4_fattr4_size(); 67 static int rfs4_fattr4_link_support(); 68 static int rfs4_fattr4_symlink_support(); 69 static int rfs4_fattr4_named_attr(); 70 static int rfs4_fattr4_fsid(); 71 static int rfs4_fattr4_unique_handles(); 72 static int rfs4_fattr4_lease_time(); 73 static int rfs4_fattr4_rdattr_error(); 74 static int rfs4_fattr4_acl(); 75 static int rfs4_fattr4_aclsupport(); 76 static int rfs4_fattr4_archive(); 77 static int rfs4_fattr4_cansettime(); 78 static int rfs4_fattr4_case_insensitive(); 79 static int rfs4_fattr4_case_preserving(); 80 static int rfs4_fattr4_chown_restricted(); 81 static int rfs4_fattr4_filehandle(); 82 static int rfs4_fattr4_fileid(); 83 static int rfs4_fattr4_files_avail(); 84 static int rfs4_fattr4_files_free(); 85 static int rfs4_fattr4_files_total(); 86 static int rfs4_fattr4_fs_locations(); 87 static int rfs4_fattr4_hidden(); 88 static int rfs4_fattr4_homogeneous(); 89 static int rfs4_fattr4_maxfilesize(); 90 static int rfs4_fattr4_maxlink(); 91 static int rfs4_fattr4_maxname(); 92 static int rfs4_fattr4_maxread(); 93 static int rfs4_fattr4_maxwrite(); 94 static int rfs4_fattr4_mimetype(); 95 static int rfs4_fattr4_mode(); 96 static int rfs4_fattr4_no_trunc(); 97 static int rfs4_fattr4_numlinks(); 98 static int rfs4_fattr4_owner(); 99 static int rfs4_fattr4_owner_group(); 100 static int rfs4_fattr4_quota_avail_hard(); 101 static int rfs4_fattr4_quota_avail_soft(); 102 static int rfs4_fattr4_quota_used(); 103 static int rfs4_fattr4_rawdev(); 104 static int rfs4_fattr4_space_avail(); 105 static int rfs4_fattr4_space_free(); 106 static int rfs4_fattr4_space_total(); 107 static int rfs4_fattr4_space_used(); 108 static int rfs4_fattr4_system(); 109 static int rfs4_fattr4_time_access(); 110 static int rfs4_fattr4_time_access_set(); 111 static int rfs4_fattr4_time_backup(); 112 static int rfs4_fattr4_time_create(); 113 static int rfs4_fattr4_time_delta(); 114 static int rfs4_fattr4_time_metadata(); 115 static int rfs4_fattr4_time_modify(); 116 static int rfs4_fattr4_time_modify_set(); 117 118 /* 119 * Initialize the supported attributes 120 */ 121 void 122 rfs4_attr_init() 123 { 124 int i; 125 struct nfs4_svgetit_arg sarg; 126 struct compound_state cs; 127 struct statvfs64 sb; 128 129 rfs4_init_compound_state(&cs); 130 cs.vp = rootvp; 131 cs.fh.nfs_fh4_val = NULL; 132 cs.cr = kcred; 133 134 /* 135 * Get all the supported attributes 136 */ 137 sarg.op = NFS4ATTR_SUPPORTED; 138 sarg.cs = &cs; 139 sarg.vap->va_mask = AT_ALL; 140 sarg.sbp = &sb; 141 sarg.flag = 0; 142 sarg.rdattr_error = NFS4_OK; 143 sarg.rdattr_error_req = FALSE; 144 145 rfs4_ntov_init(); 146 147 rfs4_supported_attrs = 0; 148 for (i = 0; i < NFS4_MAXNUM_ATTRS; i++) { 149 #ifdef RFS4_SUPPORT_MANDATTR_ONLY 150 if (rfs4_mandattr_only == TRUE && i > NFS4_LAST_MANDATTR) 151 continue; 152 #endif 153 if ((*nfs4_ntov_map[i].sv_getit)(NFS4ATTR_SUPPORTED, 154 &sarg, NULL) == 0) { 155 rfs4_supported_attrs |= nfs4_ntov_map[i].fbit; 156 } 157 } 158 } 159 160 /* 161 * The following rfs4_fattr4_* functions convert between the fattr4 162 * arguments/attributes and the system (e.g. vattr) values. The following 163 * commands are currently in use: 164 * 165 * NFS4ATTR_SUPPORTED: checks if the attribute in question is supported: 166 * sarg.op = SUPPORTED - all supported attrs 167 * sarg.op = GETIT - only supported readable attrs 168 * sarg.op = SETIT - only supported writable attrs 169 * 170 * NFS4ATTR_GETIT: getattr type conversion - convert system values 171 * (e.g. vattr struct) to fattr4 type values to be returned to the 172 * user - usually in response to nfsv4 getattr request. 173 * 174 * NFS4ATTR_SETIT: convert fattr4 type values to system values to use by 175 * setattr. Allows only read/write and write attributes, 176 * even if not supported by the filesystem. Note that ufs only allows setattr 177 * of owner/group, mode, size, atime/mtime. 178 * 179 * NFS4ATTR_VERIT: convert fattr4 type values to system values to use by 180 * verify/nverify. Implemented to allow 181 * almost everything that can be returned by getattr into known structs 182 * (like vfsstat64 or vattr_t), that is, both read only and read/write attrs. 183 * The function will return -1 if it found that the arguments don't match. 184 * This applies to system-wide values that don't require a VOP_GETATTR 185 * or other further checks to verify. It will return no error if they 186 * either match or were retrieved successfully for later checking. 187 * 188 * NFS4ATTR_FREEIT: free up any space allocated by either of the above. 189 * The sargp->op should be either NFS4ATTR_GETIT or NFS4ATTR_SETIT 190 * to indicate which op was used to allocate the space. 191 * 192 * XXX Note: these functions are currently used by the server only. A 193 * XXX different method of conversion is used on the client side. 194 * XXX Eventually combining the two (possibly by adding NFS4ATTR_CLNT_GETIT 195 * XXX and SETIT) may be a cleaner approach. 196 */ 197 198 /* 199 * Mandatory attributes 200 */ 201 202 /* ARGSUSED */ 203 static int 204 rfs4_fattr4_supported_attrs(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 205 union nfs4_attr_u *na) 206 { 207 int error = 0; 208 209 switch (cmd) { 210 case NFS4ATTR_SUPPORTED: 211 if (sarg->op == NFS4ATTR_SETIT) 212 error = EINVAL; 213 break; /* this attr is supported */ 214 case NFS4ATTR_GETIT: 215 na->supported_attrs = rfs4_supported_attrs; 216 break; 217 case NFS4ATTR_SETIT: 218 /* 219 * read-only attr 220 */ 221 error = EINVAL; 222 break; 223 case NFS4ATTR_VERIT: 224 /* 225 * Compare the input bitmap to the server's bitmap 226 */ 227 if (na->supported_attrs != rfs4_supported_attrs) { 228 error = -1; /* no match */ 229 } 230 break; 231 case NFS4ATTR_FREEIT: 232 break; 233 } 234 return (error); 235 } 236 237 /* 238 * Translate vnode vtype to nfsv4_ftype. 239 */ 240 static nfs_ftype4 vt_to_nf4[] = { 241 0, NF4REG, NF4DIR, NF4BLK, NF4CHR, NF4LNK, NF4FIFO, 0, 0, NF4SOCK, 0 242 }; 243 244 /* ARGSUSED */ 245 static int 246 rfs4_fattr4_type(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 247 union nfs4_attr_u *na) 248 { 249 int error = 0; 250 251 switch (cmd) { 252 case NFS4ATTR_SUPPORTED: 253 if (sarg->op == NFS4ATTR_SETIT) 254 error = EINVAL; 255 break; /* this attr is supported */ 256 case NFS4ATTR_GETIT: 257 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_TYPE)) { 258 error = -1; /* may be okay if rdattr_error */ 259 break; 260 } 261 ASSERT(sarg->vap->va_mask & AT_TYPE); 262 263 /* 264 * if xattr flag not set, use v4_to_nf4 mapping; 265 * otherwise verify xattr flag is in sync with va_type 266 * and set xattr types. 267 */ 268 if (! (sarg->xattr & (FH4_NAMEDATTR | FH4_ATTRDIR))) 269 na->type = vt_to_nf4[sarg->vap->va_type]; 270 else { 271 /* 272 * FH4 flag was set. Dir type maps to attrdir, 273 * and all other types map to namedattr. 274 */ 275 if (sarg->vap->va_type == VDIR) 276 na->type = NF4ATTRDIR; 277 else 278 na->type = NF4NAMEDATTR; 279 } 280 break; 281 case NFS4ATTR_SETIT: 282 /* 283 * read-only attr 284 */ 285 error = EINVAL; 286 break; 287 case NFS4ATTR_VERIT: 288 /* 289 * Compare the input type to the object type on server 290 */ 291 ASSERT(sarg->vap->va_mask & AT_TYPE); 292 if (sarg->vap->va_type != nf4_to_vt[na->type]) 293 error = -1; /* no match */ 294 break; 295 case NFS4ATTR_FREEIT: 296 break; 297 } 298 return (error); 299 } 300 301 /* ARGSUSED */ 302 static int 303 fattr4_get_fh_expire_type(struct exportinfo *exi, uint32_t *fh_expire_typep) 304 { 305 #ifdef VOLATILE_FH_TEST 306 int ex_flags; 307 308 if (exi == NULL) 309 return (ESTALE); 310 ex_flags = exi->exi_export.ex_flags; 311 if ((ex_flags & (EX_VOLFH | EX_VOLRNM | EX_VOLMIG | EX_NOEXPOPEN)) 312 == 0) { 313 *fh_expire_typep = FH4_PERSISTENT; 314 return (0); 315 } 316 *fh_expire_typep = 0; 317 318 if (ex_flags & EX_NOEXPOPEN) { 319 /* file handles should not expire with open - not used */ 320 *fh_expire_typep = FH4_NOEXPIRE_WITH_OPEN; 321 } 322 if (ex_flags & EX_VOLFH) { 323 /* 324 * file handles may expire any time - on share here. 325 * If volatile any, no need to check other flags. 326 */ 327 *fh_expire_typep |= FH4_VOLATILE_ANY; 328 return (0); 329 } 330 if (ex_flags & EX_VOLRNM) { 331 /* file handles may expire on rename */ 332 *fh_expire_typep |= FH4_VOL_RENAME; 333 } 334 if (ex_flags & EX_VOLMIG) { 335 /* file handles may expire on migration - not used */ 336 *fh_expire_typep |= FH4_VOL_MIGRATION; 337 } 338 #else /* not VOLATILE_FH_TEST */ 339 *fh_expire_typep = FH4_PERSISTENT; 340 #endif /* VOLATILE_FH_TEST */ 341 342 return (0); 343 } 344 345 /* 346 * At this point the only volatile filehandles we allow (for test purposes 347 * only) are either fh's that expire when the filesystem is shared (reshared), 348 * fh's that expire on a rename and persistent ones. 349 */ 350 /* ARGSUSED */ 351 static int 352 rfs4_fattr4_fh_expire_type(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 353 union nfs4_attr_u *na) 354 { 355 uint32_t fh_expire_type; 356 int error = 0; 357 358 switch (cmd) { 359 case NFS4ATTR_SUPPORTED: 360 if (sarg->op == NFS4ATTR_SETIT) 361 error = EINVAL; 362 break; /* this attr is supported */ 363 case NFS4ATTR_GETIT: 364 error = fattr4_get_fh_expire_type(sarg->cs->exi, 365 &na->fh_expire_type); 366 break; 367 case NFS4ATTR_SETIT: 368 /* 369 * read-only attr 370 */ 371 error = EINVAL; 372 break; 373 case NFS4ATTR_VERIT: 374 error = fattr4_get_fh_expire_type(sarg->cs->exi, 375 &fh_expire_type); 376 if (!error && (na->fh_expire_type != fh_expire_type)) 377 error = -1; /* no match */ 378 break; 379 case NFS4ATTR_FREEIT: 380 break; 381 } 382 return (error); 383 } 384 385 static int 386 fattr4_get_change(struct nfs4_svgetit_arg *sarg, fattr4_change *changep) 387 { 388 vattr_t vap2[1], *vap = sarg->vap; 389 struct compound_state *cs = sarg->cs; 390 vnode_t *vp = cs->vp; 391 nfsstat4 status; 392 393 if ((vap->va_mask & AT_CTIME) == 0) { 394 if (sarg->rdattr_error && (vp == NULL)) { 395 return (-1); /* may be okay if rdattr_error */ 396 } 397 ASSERT(vp != NULL); 398 vap = vap2; 399 vap->va_mask = AT_CTIME; 400 status = rfs4_vop_getattr(vp, vap, 0, cs->cr); 401 if (status != NFS4_OK) 402 return (geterrno4(status)); 403 } 404 NFS4_SET_FATTR4_CHANGE(*changep, vap->va_ctime) 405 return (0); 406 } 407 408 /* ARGSUSED */ 409 static int 410 rfs4_fattr4_change(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 411 union nfs4_attr_u *na) 412 { 413 int error = 0; 414 fattr4_change change; 415 uint_t mask; 416 vattr_t *vap = sarg->vap; 417 418 switch (cmd) { 419 case NFS4ATTR_SUPPORTED: 420 if (sarg->op == NFS4ATTR_SETIT) 421 error = EINVAL; 422 break; /* this attr is supported */ 423 case NFS4ATTR_GETIT: 424 error = fattr4_get_change(sarg, &na->change); 425 break; 426 case NFS4ATTR_SETIT: 427 /* 428 * read-only attr 429 */ 430 error = EINVAL; 431 break; 432 case NFS4ATTR_VERIT: 433 mask = vap->va_mask; 434 vap->va_mask &= ~AT_CTIME; /* force a VOP_GETATTR */ 435 error = fattr4_get_change(sarg, &change); 436 vap->va_mask = mask; 437 if (!error && (na->change != change)) 438 error = -1; 439 break; 440 case NFS4ATTR_FREEIT: 441 break; 442 } 443 return (error); 444 } 445 446 /* ARGSUSED */ 447 static int 448 rfs4_fattr4_size(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 449 union nfs4_attr_u *na) 450 { 451 int error = 0; 452 453 switch (cmd) { 454 case NFS4ATTR_SUPPORTED: 455 break; /* this attr is supported */ 456 case NFS4ATTR_GETIT: 457 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_SIZE)) { 458 error = -1; /* may be okay if rdattr_error */ 459 break; 460 } 461 ASSERT(sarg->vap->va_mask & AT_SIZE); 462 na->size = sarg->vap->va_size; 463 break; 464 case NFS4ATTR_SETIT: 465 ASSERT(sarg->vap->va_mask & AT_SIZE); 466 sarg->vap->va_size = na->size; 467 break; 468 case NFS4ATTR_VERIT: 469 ASSERT(sarg->vap->va_mask & AT_SIZE); 470 if (sarg->vap->va_size != na->size) 471 error = -1; /* no match */ 472 break; 473 case NFS4ATTR_FREEIT: 474 break; 475 } 476 return (error); 477 } 478 479 /* 480 * XXX - need VOP extension to ask file system (e.g. pcfs) if it supports 481 * hard links. 482 */ 483 /* ARGSUSED */ 484 static int 485 rfs4_fattr4_link_support(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 486 union nfs4_attr_u *na) 487 { 488 int error = 0; 489 490 switch (cmd) { 491 case NFS4ATTR_SUPPORTED: 492 if (sarg->op == NFS4ATTR_SETIT) 493 error = EINVAL; 494 break; /* this attr is supported */ 495 case NFS4ATTR_GETIT: 496 na->link_support = TRUE; 497 break; 498 case NFS4ATTR_SETIT: 499 /* 500 * read-only attr 501 */ 502 error = EINVAL; 503 break; 504 case NFS4ATTR_VERIT: 505 if (!na->link_support) 506 error = -1; /* no match */ 507 break; 508 case NFS4ATTR_FREEIT: 509 break; 510 } 511 return (error); 512 } 513 514 /* 515 * XXX - need VOP extension to ask file system (e.g. pcfs) if it supports 516 * sym links. 517 */ 518 /* ARGSUSED */ 519 static int 520 rfs4_fattr4_symlink_support(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 521 union nfs4_attr_u *na) 522 { 523 int error = 0; 524 525 switch (cmd) { 526 case NFS4ATTR_SUPPORTED: 527 if (sarg->op == NFS4ATTR_SETIT) 528 error = EINVAL; 529 break; /* this attr is supported */ 530 case NFS4ATTR_GETIT: 531 na->symlink_support = TRUE; 532 break; 533 case NFS4ATTR_SETIT: 534 /* 535 * read-only attr 536 */ 537 error = EINVAL; 538 break; 539 case NFS4ATTR_VERIT: 540 if (!na->symlink_support) 541 error = -1; /* no match */ 542 break; 543 case NFS4ATTR_FREEIT: 544 break; 545 } 546 return (error); 547 } 548 549 /* ARGSUSED */ 550 static int 551 rfs4_fattr4_named_attr(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 552 union nfs4_attr_u *na) 553 { 554 int error = 0; 555 ulong_t val; 556 557 switch (cmd) { 558 case NFS4ATTR_SUPPORTED: 559 if (sarg->op == NFS4ATTR_SETIT) 560 error = EINVAL; 561 break; /* this attr is supported */ 562 case NFS4ATTR_GETIT: 563 if (sarg->rdattr_error && (sarg->cs->vp == NULL)) { 564 error = -1; /* may be okay if rdattr_error */ 565 break; 566 } 567 ASSERT(sarg->cs->vp != NULL); 568 569 /* 570 * Solaris xattr model requires that VFS_XATTR is set 571 * in file systems enabled for generic xattr. If VFS_XATTR 572 * not set, no need to call pathconf for _PC_XATTR_EXISTS.. 573 * 574 * However the VFS_XATTR flag doesn't indicate sysattr support 575 * so always check for sysattrs and then only do the 576 * _PC_XATTR_EXISTS pathconf if needed. 577 */ 578 579 val = 0; 580 error = VOP_PATHCONF(sarg->cs->vp, _PC_SATTR_EXISTS, 581 &val, sarg->cs->cr, NULL); 582 if ((error || val == 0) && 583 sarg->cs->vp->v_vfsp->vfs_flag & VFS_XATTR) { 584 error = VOP_PATHCONF(sarg->cs->vp, 585 _PC_XATTR_EXISTS, &val, sarg->cs->cr, NULL); 586 if (error) 587 break; 588 } 589 na->named_attr = (val ? TRUE : FALSE); 590 break; 591 case NFS4ATTR_SETIT: 592 /* 593 * read-only attr 594 */ 595 error = EINVAL; 596 break; 597 case NFS4ATTR_VERIT: 598 ASSERT(sarg->cs->vp != NULL); 599 if (sarg->cs->vp->v_vfsp->vfs_flag & VFS_XATTR) { 600 error = VOP_PATHCONF(sarg->cs->vp, _PC_SATTR_EXISTS, 601 &val, sarg->cs->cr, NULL); 602 if (error || val == 0) 603 error = VOP_PATHCONF(sarg->cs->vp, 604 _PC_XATTR_EXISTS, &val, 605 sarg->cs->cr, NULL); 606 if (error) 607 break; 608 } else 609 val = 0; 610 if (na->named_attr != (val ? TRUE : FALSE)) 611 error = -1; /* no match */ 612 break; 613 case NFS4ATTR_FREEIT: 614 break; 615 } 616 return (error); 617 } 618 619 /* ARGSUSED */ 620 static int 621 rfs4_fattr4_fsid(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 622 union nfs4_attr_u *na) 623 { 624 int error = 0; 625 int *pmaj = (int *)&na->fsid.major; 626 627 /* 628 * fsid_t is 64bits so it fits completely in fattr4_fsid.major. 629 * fattr4_fsid.minor is always set to 0 since it isn't needed (yet). 630 */ 631 switch (cmd) { 632 case NFS4ATTR_SUPPORTED: 633 if (sarg->op == NFS4ATTR_SETIT) 634 error = EINVAL; 635 break; /* this attr is supported */ 636 case NFS4ATTR_GETIT: 637 if (sarg->cs->exi->exi_volatile_dev) { 638 pmaj[0] = sarg->cs->exi->exi_fsid.val[0]; 639 pmaj[1] = sarg->cs->exi->exi_fsid.val[1]; 640 na->fsid.minor = 0; 641 } else { 642 na->fsid.major = getmajor(sarg->vap->va_fsid); 643 na->fsid.minor = getminor(sarg->vap->va_fsid); 644 } 645 break; 646 case NFS4ATTR_SETIT: 647 error = EINVAL; 648 break; 649 case NFS4ATTR_VERIT: 650 if (sarg->cs->exi->exi_volatile_dev) { 651 if (pmaj[0] != sarg->cs->exi->exi_fsid.val[0] || 652 pmaj[1] != sarg->cs->exi->exi_fsid.val[1] || 653 na->fsid.minor != 0) 654 error = -1; 655 } else { 656 if (na->fsid.major != getmajor(sarg->vap->va_fsid) || 657 na->fsid.minor != getminor(sarg->vap->va_fsid)) 658 error = -1; 659 } 660 break; 661 case NFS4ATTR_FREEIT: 662 break; 663 } 664 return (error); 665 } 666 667 /* ARGSUSED */ 668 static int 669 rfs4_fattr4_unique_handles(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 670 union nfs4_attr_u *na) 671 { 672 /* 673 * XXX 674 * For now, we can't support this. Problem of /export, beinging 675 * a file system, /export/a and /export/b shared separately, 676 * and /export/a/l and /export/b/l are ahrd links of each other. 677 */ 678 int error = 0; 679 680 switch (cmd) { 681 case NFS4ATTR_SUPPORTED: 682 if (sarg->op == NFS4ATTR_SETIT) 683 error = EINVAL; 684 break; /* this attr is supported */ 685 case NFS4ATTR_GETIT: 686 na->unique_handles = FALSE; 687 break; 688 case NFS4ATTR_SETIT: 689 /* 690 * read-only attr 691 */ 692 error = EINVAL; 693 break; 694 case NFS4ATTR_VERIT: 695 if (na->unique_handles) 696 error = -1; /* no match */ 697 break; 698 case NFS4ATTR_FREEIT: 699 break; 700 } 701 return (error); 702 } 703 704 /* ARGSUSED */ 705 static int 706 rfs4_fattr4_lease_time(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 707 union nfs4_attr_u *na) 708 { 709 int error = 0; 710 711 switch (cmd) { 712 case NFS4ATTR_SUPPORTED: 713 if (sarg->op == NFS4ATTR_SETIT) 714 error = EINVAL; 715 break; /* this attr is supported */ 716 case NFS4ATTR_GETIT: 717 na->lease_time = rfs4_lease_time; 718 break; 719 case NFS4ATTR_SETIT: 720 /* 721 * read-only attr 722 */ 723 error = EINVAL; 724 break; 725 case NFS4ATTR_VERIT: 726 if (na->lease_time != rfs4_lease_time) 727 error = -1; /* no match */ 728 break; 729 case NFS4ATTR_FREEIT: 730 break; 731 } 732 return (error); 733 } 734 735 /* ARGSUSED */ 736 static int 737 rfs4_fattr4_rdattr_error(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 738 union nfs4_attr_u *na) 739 { 740 int error = 0; 741 742 switch (cmd) { 743 case NFS4ATTR_SUPPORTED: 744 if ((sarg->op == NFS4ATTR_SETIT) || 745 (sarg->op == NFS4ATTR_VERIT)) 746 error = EINVAL; 747 break; /* this attr is supported */ 748 case NFS4ATTR_GETIT: 749 ASSERT(sarg->rdattr_error_req); 750 na->rdattr_error = sarg->rdattr_error; 751 break; 752 case NFS4ATTR_SETIT: 753 case NFS4ATTR_VERIT: 754 /* 755 * read-only attr 756 */ 757 error = EINVAL; 758 break; 759 case NFS4ATTR_FREEIT: 760 break; 761 } 762 return (error); 763 } 764 765 /* 766 * Server side compare of a filehandle from the wire to a native 767 * server filehandle. 768 */ 769 static int 770 rfs4fhcmp(nfs_fh4 *wirefh, nfs_fh4 *srvfh) 771 { 772 nfs_fh4_fmt_t fh; 773 774 ASSERT(IS_P2ALIGNED(wirefh->nfs_fh4_val, sizeof (uint32_t))); 775 776 bzero(&fh, sizeof (nfs_fh4_fmt_t)); 777 if (!xdr_inline_decode_nfs_fh4((uint32_t *)wirefh->nfs_fh4_val, &fh, 778 wirefh->nfs_fh4_len)) 779 return (1); 780 781 return (bcmp(srvfh->nfs_fh4_val, &fh, srvfh->nfs_fh4_len)); 782 } 783 784 /* ARGSUSED */ 785 static int 786 rfs4_fattr4_filehandle(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 787 union nfs4_attr_u *na) 788 { 789 nfs_fh4 *fh; 790 791 switch (cmd) { 792 case NFS4ATTR_SUPPORTED: 793 if (sarg->op == NFS4ATTR_SETIT) 794 return (EINVAL); 795 return (0); /* this attr is supported */ 796 case NFS4ATTR_GETIT: 797 /* 798 * If sarg->cs->fh is all zeros then should makefh a new 799 * one, otherwise, copy that one over. 800 */ 801 fh = &sarg->cs->fh; 802 if (sarg->cs->fh.nfs_fh4_len == 0) { 803 if (sarg->rdattr_error && (sarg->cs->vp == NULL)) 804 return (-1); /* okay if rdattr_error */ 805 ASSERT(sarg->cs->vp != NULL); 806 na->filehandle.nfs_fh4_val = 807 kmem_alloc(NFS_FH4_LEN, KM_SLEEP); 808 return (makefh4(&na->filehandle, sarg->cs->vp, 809 sarg->cs->exi)); 810 } 811 na->filehandle.nfs_fh4_val = 812 kmem_alloc(fh->nfs_fh4_len, KM_SLEEP); 813 nfs_fh4_copy(fh, &na->filehandle); 814 return (0); 815 case NFS4ATTR_SETIT: 816 /* 817 * read-only attr 818 */ 819 return (EINVAL); 820 case NFS4ATTR_VERIT: 821 /* 822 * A verify of a filehandle will have the client sending 823 * the raw format which needs to be compared to the 824 * native format. 825 */ 826 if (rfs4fhcmp(&na->filehandle, &sarg->cs->fh) == 1) 827 return (-1); /* no match */ 828 return (0); 829 case NFS4ATTR_FREEIT: 830 if (sarg->op != NFS4ATTR_GETIT) 831 return (0); 832 if (na->filehandle.nfs_fh4_val == NULL) 833 return (0); 834 kmem_free(na->filehandle.nfs_fh4_val, 835 na->filehandle.nfs_fh4_len); 836 na->filehandle.nfs_fh4_val = NULL; 837 na->filehandle.nfs_fh4_len = 0; 838 return (0); 839 } 840 return (0); 841 } 842 843 /* 844 * Recommended attributes 845 */ 846 847 /* ARGSUSED */ 848 static int 849 rfs4_fattr4_acl(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 850 union nfs4_attr_u *na) 851 { 852 int error = 0; 853 vsecattr_t vs_native, vs_ace4; 854 ulong_t whichacl; 855 nfsstat4 status; 856 vattr_t va, *vap = sarg->vap; 857 vnode_t *vp = sarg->cs->vp; 858 859 if (RFS4_MANDATTR_ONLY) 860 return (ENOTSUP); 861 862 switch (cmd) { 863 case NFS4ATTR_SUPPORTED: 864 break; 865 866 case NFS4ATTR_VERIT: 867 case NFS4ATTR_GETIT: 868 if (sarg->rdattr_error && (vp == NULL)) { 869 return (-1); 870 } 871 ASSERT(vp != NULL); 872 bzero(&vs_native, sizeof (vs_native)); 873 874 /* see which ACLs fs supports */ 875 error = VOP_PATHCONF(vp, _PC_ACL_ENABLED, &whichacl, 876 sarg->cs->cr, NULL); 877 if (error != 0) { 878 /* 879 * If we got an error, then the filesystem 880 * likely does not understand the _PC_ACL_ENABLED 881 * pathconf. In this case, we fall back to trying 882 * POSIX-draft (aka UFS-style) ACLs, since that's 883 * the behavior used by earlier version of NFS. 884 */ 885 error = 0; 886 whichacl = _ACL_ACLENT_ENABLED; 887 } 888 889 if (!(whichacl & (_ACL_ACE_ENABLED | _ACL_ACLENT_ENABLED))) { 890 /* 891 * If the file system supports neither ACE nor 892 * ACLENT ACLs we will fall back to UFS-style ACLs 893 * like we did above if there was an error upon 894 * calling VOP_PATHCONF. 895 * 896 * ACE and ACLENT type ACLs are the only interfaces 897 * supported thus far. If any other bits are set on 898 * 'whichacl' upon return from VOP_PATHCONF, we will 899 * ignore them. 900 */ 901 whichacl = _ACL_ACLENT_ENABLED; 902 } 903 904 if (whichacl & _ACL_ACE_ENABLED) 905 vs_native.vsa_mask = VSA_ACE | VSA_ACECNT; 906 else if (whichacl & _ACL_ACLENT_ENABLED) 907 vs_native.vsa_mask = VSA_ACL | VSA_ACLCNT | 908 VSA_DFACL | VSA_DFACLCNT; 909 910 if (error != 0) 911 break; 912 913 /* get the ACL, and translate it into nfsace4 style */ 914 error = VOP_GETSECATTR(vp, &vs_native, 915 0, sarg->cs->cr, NULL); 916 if (error != 0) 917 break; 918 if (whichacl & _ACL_ACE_ENABLED) { 919 error = vs_acet_to_ace4(&vs_native, &vs_ace4, TRUE); 920 vs_acet_destroy(&vs_native); 921 } else { 922 error = vs_aent_to_ace4(&vs_native, &vs_ace4, 923 vp->v_type == VDIR, TRUE); 924 vs_aent_destroy(&vs_native); 925 } 926 if (error != 0) 927 break; 928 929 if (cmd == NFS4ATTR_GETIT) { 930 na->acl.fattr4_acl_len = vs_ace4.vsa_aclcnt; 931 /* see case NFS4ATTR_FREEIT for this being freed */ 932 na->acl.fattr4_acl_val = vs_ace4.vsa_aclentp; 933 } else { 934 if (na->acl.fattr4_acl_len != vs_ace4.vsa_aclcnt) 935 error = -1; /* no match */ 936 else if (ln_ace4_cmp(na->acl.fattr4_acl_val, 937 vs_ace4.vsa_aclentp, 938 vs_ace4.vsa_aclcnt) != 0) 939 error = -1; /* no match */ 940 } 941 942 break; 943 944 case NFS4ATTR_SETIT: 945 if (sarg->rdattr_error && (vp == NULL)) { 946 return (-1); 947 } 948 ASSERT(vp != NULL); 949 950 /* prepare vs_ace4 from fattr4 data */ 951 bzero(&vs_ace4, sizeof (vs_ace4)); 952 vs_ace4.vsa_mask = VSA_ACE | VSA_ACECNT; 953 vs_ace4.vsa_aclcnt = na->acl.fattr4_acl_len; 954 vs_ace4.vsa_aclentp = na->acl.fattr4_acl_val; 955 vs_ace4.vsa_aclentsz = vs_ace4.vsa_aclcnt * sizeof (ace_t); 956 /* make sure we have correct owner/group */ 957 if ((vap->va_mask & (AT_UID | AT_GID)) != 958 (AT_UID | AT_GID)) { 959 vap = &va; 960 vap->va_mask = AT_UID | AT_GID; 961 status = rfs4_vop_getattr(vp, 962 vap, 0, sarg->cs->cr); 963 if (status != NFS4_OK) 964 return (geterrno4(status)); 965 } 966 967 /* see which ACLs the fs supports */ 968 error = VOP_PATHCONF(vp, _PC_ACL_ENABLED, &whichacl, 969 sarg->cs->cr, NULL); 970 if (error != 0) { 971 /* 972 * If we got an error, then the filesystem 973 * likely does not understand the _PC_ACL_ENABLED 974 * pathconf. In this case, we fall back to trying 975 * POSIX-draft (aka UFS-style) ACLs, since that's 976 * the behavior used by earlier version of NFS. 977 */ 978 error = 0; 979 whichacl = _ACL_ACLENT_ENABLED; 980 } 981 982 if (!(whichacl & (_ACL_ACLENT_ENABLED | _ACL_ACE_ENABLED))) { 983 /* 984 * If the file system supports neither ACE nor 985 * ACLENT ACLs we will fall back to UFS-style ACLs 986 * like we did above if there was an error upon 987 * calling VOP_PATHCONF. 988 * 989 * ACE and ACLENT type ACLs are the only interfaces 990 * supported thus far. If any other bits are set on 991 * 'whichacl' upon return from VOP_PATHCONF, we will 992 * ignore them. 993 */ 994 whichacl = _ACL_ACLENT_ENABLED; 995 } 996 997 if (whichacl & _ACL_ACE_ENABLED) { 998 error = vs_ace4_to_acet(&vs_ace4, &vs_native, 999 vap->va_uid, vap->va_gid, TRUE, FALSE); 1000 if (error != 0) 1001 break; 1002 (void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL); 1003 error = VOP_SETSECATTR(vp, &vs_native, 1004 0, sarg->cs->cr, NULL); 1005 VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL); 1006 vs_acet_destroy(&vs_native); 1007 } else if (whichacl & _ACL_ACLENT_ENABLED) { 1008 error = vs_ace4_to_aent(&vs_ace4, &vs_native, 1009 vap->va_uid, vap->va_gid, vp->v_type == VDIR, TRUE, 1010 FALSE); 1011 if (error != 0) 1012 break; 1013 (void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL); 1014 error = VOP_SETSECATTR(vp, &vs_native, 1015 0, sarg->cs->cr, NULL); 1016 VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL); 1017 vs_aent_destroy(&vs_native); 1018 } 1019 break; 1020 1021 case NFS4ATTR_FREEIT: 1022 if (sarg->op == NFS4ATTR_GETIT) { 1023 vs_ace4.vsa_mask = VSA_ACE | VSA_ACECNT; 1024 vs_ace4.vsa_aclcnt = na->acl.fattr4_acl_len; 1025 vs_ace4.vsa_aclentp = na->acl.fattr4_acl_val; 1026 vs_ace4_destroy(&vs_ace4); 1027 } 1028 break; 1029 } 1030 1031 return (error); 1032 } 1033 1034 /* ARGSUSED */ 1035 static int 1036 rfs4_fattr4_aclsupport(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1037 union nfs4_attr_u *na) 1038 { 1039 int error = 0; 1040 1041 if (RFS4_MANDATTR_ONLY) 1042 return (ENOTSUP); 1043 1044 switch (cmd) { 1045 case NFS4ATTR_SUPPORTED: 1046 if (sarg->op == NFS4ATTR_SETIT) 1047 error = EINVAL; 1048 break; /* supported */ 1049 case NFS4ATTR_GETIT: 1050 na->aclsupport = ACL4_SUPPORT_ALLOW_ACL | 1051 ACL4_SUPPORT_DENY_ACL; 1052 break; 1053 case NFS4ATTR_SETIT: 1054 error = EINVAL; 1055 break; 1056 case NFS4ATTR_VERIT: 1057 if (na->aclsupport != (ACL4_SUPPORT_ALLOW_ACL | 1058 ACL4_SUPPORT_DENY_ACL)) 1059 error = -1; /* no match */ 1060 break; 1061 } 1062 1063 return (error); 1064 } 1065 1066 /* ARGSUSED */ 1067 static int 1068 rfs4_fattr4_archive(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1069 union nfs4_attr_u *na) 1070 { 1071 return (ENOTSUP); 1072 } 1073 1074 /* ARGSUSED */ 1075 static int 1076 rfs4_fattr4_cansettime(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1077 union nfs4_attr_u *na) 1078 { 1079 int error = 0; 1080 1081 if (RFS4_MANDATTR_ONLY) 1082 return (ENOTSUP); 1083 1084 switch (cmd) { 1085 case NFS4ATTR_SUPPORTED: 1086 if (sarg->op == NFS4ATTR_SETIT) 1087 error = EINVAL; 1088 break; /* this attr is supported */ 1089 case NFS4ATTR_GETIT: 1090 na->cansettime = TRUE; 1091 break; 1092 case NFS4ATTR_SETIT: 1093 /* 1094 * read-only attr 1095 */ 1096 error = EINVAL; 1097 break; 1098 case NFS4ATTR_VERIT: 1099 if (!na->cansettime) 1100 error = -1; /* no match */ 1101 break; 1102 case NFS4ATTR_FREEIT: 1103 break; 1104 } 1105 return (error); 1106 } 1107 1108 /* 1109 * XXX - need VOP extension to ask file system (e.g. pcfs) if it supports 1110 * case insensitive. 1111 */ 1112 /* ARGSUSED */ 1113 static int 1114 rfs4_fattr4_case_insensitive(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1115 union nfs4_attr_u *na) 1116 { 1117 int error = 0; 1118 1119 if (RFS4_MANDATTR_ONLY) 1120 return (ENOTSUP); 1121 1122 switch (cmd) { 1123 case NFS4ATTR_SUPPORTED: 1124 if (sarg->op == NFS4ATTR_SETIT) 1125 error = EINVAL; 1126 break; /* this attr is supported */ 1127 case NFS4ATTR_GETIT: 1128 na->case_insensitive = FALSE; 1129 break; 1130 case NFS4ATTR_SETIT: 1131 /* 1132 * read-only attr 1133 */ 1134 error = EINVAL; 1135 break; 1136 case NFS4ATTR_VERIT: 1137 if (!na->case_insensitive) 1138 error = -1; /* no match */ 1139 break; 1140 case NFS4ATTR_FREEIT: 1141 break; 1142 } 1143 return (error); 1144 } 1145 1146 /* ARGSUSED */ 1147 static int 1148 rfs4_fattr4_case_preserving(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1149 union nfs4_attr_u *na) 1150 { 1151 int error = 0; 1152 1153 if (RFS4_MANDATTR_ONLY) 1154 return (ENOTSUP); 1155 1156 switch (cmd) { 1157 case NFS4ATTR_SUPPORTED: 1158 if (sarg->op == NFS4ATTR_SETIT) 1159 error = EINVAL; 1160 break; /* this attr is supported */ 1161 case NFS4ATTR_GETIT: 1162 na->case_preserving = TRUE; 1163 break; 1164 case NFS4ATTR_SETIT: 1165 /* 1166 * read-only attr 1167 */ 1168 error = EINVAL; 1169 break; 1170 case NFS4ATTR_VERIT: 1171 if (!na->case_preserving) 1172 error = -1; /* no match */ 1173 break; 1174 case NFS4ATTR_FREEIT: 1175 break; 1176 } 1177 return (error); 1178 } 1179 1180 /* fattr4_chown_restricted should reall be fattr4_chown_allowed */ 1181 /* ARGSUSED */ 1182 static int 1183 rfs4_fattr4_chown_restricted(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1184 union nfs4_attr_u *na) 1185 { 1186 int error = 0; 1187 ulong_t val; 1188 1189 if (RFS4_MANDATTR_ONLY) 1190 return (ENOTSUP); 1191 1192 switch (cmd) { 1193 case NFS4ATTR_SUPPORTED: 1194 if (sarg->op == NFS4ATTR_SETIT) 1195 error = EINVAL; 1196 break; /* this attr is supported */ 1197 case NFS4ATTR_GETIT: 1198 if (sarg->rdattr_error && (sarg->cs->vp == NULL)) { 1199 error = -1; /* may be okay if rdattr_error */ 1200 break; 1201 } 1202 ASSERT(sarg->cs->vp != NULL); 1203 error = VOP_PATHCONF(sarg->cs->vp, 1204 _PC_CHOWN_RESTRICTED, &val, sarg->cs->cr, NULL); 1205 if (error) 1206 break; 1207 1208 na->chown_restricted = (val == 1); 1209 break; 1210 case NFS4ATTR_SETIT: 1211 /* 1212 * read-only attr 1213 */ 1214 error = EINVAL; 1215 break; 1216 case NFS4ATTR_VERIT: 1217 ASSERT(sarg->cs->vp != NULL); 1218 error = VOP_PATHCONF(sarg->cs->vp, 1219 _PC_CHOWN_RESTRICTED, &val, sarg->cs->cr, NULL); 1220 if (error) 1221 break; 1222 if (na->chown_restricted != (val == 1)) 1223 error = -1; /* no match */ 1224 break; 1225 case NFS4ATTR_FREEIT: 1226 break; 1227 } 1228 return (error); 1229 } 1230 1231 /* ARGSUSED */ 1232 static int 1233 rfs4_fattr4_fileid(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1234 union nfs4_attr_u *na) 1235 { 1236 int error = 0; 1237 1238 if (RFS4_MANDATTR_ONLY) 1239 return (ENOTSUP); 1240 1241 switch (cmd) { 1242 case NFS4ATTR_SUPPORTED: 1243 if (sarg->op == NFS4ATTR_SETIT) 1244 error = EINVAL; 1245 break; /* this attr is supported */ 1246 case NFS4ATTR_GETIT: 1247 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_NODEID)) { 1248 error = -1; /* may be okay if rdattr_error */ 1249 break; 1250 } 1251 ASSERT(sarg->vap->va_mask & AT_NODEID); 1252 na->fileid = sarg->vap->va_nodeid; 1253 break; 1254 case NFS4ATTR_SETIT: 1255 /* 1256 * read-only attr 1257 */ 1258 error = EINVAL; 1259 break; 1260 case NFS4ATTR_VERIT: 1261 ASSERT(sarg->vap->va_mask & AT_NODEID); 1262 if (sarg->vap->va_nodeid != na->fileid) 1263 error = -1; /* no match */ 1264 break; 1265 case NFS4ATTR_FREEIT: 1266 break; 1267 } 1268 return (error); 1269 } 1270 1271 /* ARGSUSED */ 1272 static int 1273 rfs4_get_mntdfileid(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg) 1274 { 1275 int error = 0; 1276 vattr_t *vap, va; 1277 vnode_t *stubvp = NULL, *vp; 1278 1279 vp = sarg->cs->vp; 1280 sarg->mntdfid_set = FALSE; 1281 1282 /* VROOT object, must untraverse */ 1283 if (vp->v_flag & VROOT) { 1284 1285 /* extra hold for vp since untraverse might rele */ 1286 VN_HOLD(vp); 1287 stubvp = untraverse(vp); 1288 1289 /* 1290 * If vp/stubvp are same, we must be at system 1291 * root because untraverse returned same vp 1292 * for a VROOT object. sarg->vap was setup 1293 * before we got here, so there's no need to do 1294 * another getattr -- just use the one in sarg. 1295 */ 1296 if (VN_CMP(vp, stubvp)) { 1297 ASSERT(VN_CMP(vp, rootdir)); 1298 vap = sarg->vap; 1299 } else { 1300 va.va_mask = AT_NODEID; 1301 vap = &va; 1302 error = rfs4_vop_getattr(stubvp, vap, 0, sarg->cs->cr); 1303 } 1304 1305 /* 1306 * Done with stub, time to rele. If vp and stubvp 1307 * were the same, then we need to rele either vp or 1308 * stubvp. If they weren't the same, then untraverse() 1309 * already took case of the extra hold on vp, and only 1310 * the stub needs to be rele'd. Both cases are handled 1311 * by unconditionally rele'ing the stub. 1312 */ 1313 VN_RELE(stubvp); 1314 } else 1315 vap = sarg->vap; 1316 1317 /* 1318 * At this point, vap should contain "correct" AT_NODEID -- 1319 * (for V_ROOT case, nodeid of stub, for non-VROOT case, 1320 * nodeid of vp). If error or AT_NODEID not available, then 1321 * make the obligatory (yet mysterious) rdattr_error 1322 * check that is so common in the attr code. 1323 */ 1324 if (!error && (vap->va_mask & AT_NODEID)) { 1325 sarg->mounted_on_fileid = vap->va_nodeid; 1326 sarg->mntdfid_set = TRUE; 1327 } else if (sarg->rdattr_error) 1328 error = -1; 1329 1330 /* 1331 * error describes these cases: 1332 * 0 : success 1333 * -1: failure due to previous attr processing error (rddir only). 1334 * * : new attr failure (if rddir, caller will set rdattr_error) 1335 */ 1336 return (error); 1337 } 1338 1339 /* ARGSUSED */ 1340 static int 1341 rfs4_fattr4_mounted_on_fileid(nfs4_attr_cmd_t cmd, 1342 struct nfs4_svgetit_arg *sarg, union nfs4_attr_u *na) 1343 { 1344 int error = 0; 1345 1346 if (RFS4_MANDATTR_ONLY) 1347 return (ENOTSUP); 1348 1349 switch (cmd) { 1350 case NFS4ATTR_SUPPORTED: 1351 if (sarg->op == NFS4ATTR_SETIT) 1352 error = EINVAL; 1353 break; /* this attr is supported */ 1354 case NFS4ATTR_GETIT: 1355 case NFS4ATTR_VERIT: 1356 if (! sarg->mntdfid_set) 1357 error = rfs4_get_mntdfileid(cmd, sarg); 1358 1359 if (! error && sarg->mntdfid_set) { 1360 if (cmd == NFS4ATTR_GETIT) 1361 na->mounted_on_fileid = sarg->mounted_on_fileid; 1362 else 1363 if (na->mounted_on_fileid != 1364 sarg->mounted_on_fileid) 1365 error = -1; 1366 } 1367 break; 1368 case NFS4ATTR_SETIT: 1369 /* read-only attr */ 1370 error = EINVAL; 1371 break; 1372 case NFS4ATTR_FREEIT: 1373 break; 1374 } 1375 return (error); 1376 } 1377 1378 /* ARGSUSED */ 1379 static int 1380 rfs4_fattr4_files_avail(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1381 union nfs4_attr_u *na) 1382 { 1383 int error = 0; 1384 1385 if (RFS4_MANDATTR_ONLY) 1386 return (ENOTSUP); 1387 1388 switch (cmd) { 1389 case NFS4ATTR_SUPPORTED: 1390 if (sarg->op == NFS4ATTR_SETIT) 1391 error = EINVAL; 1392 break; /* this attr is supported */ 1393 case NFS4ATTR_GETIT: 1394 if (sarg->rdattr_error && (sarg->sbp == NULL)) { 1395 error = -1; /* may be okay if rdattr_error */ 1396 break; 1397 } 1398 ASSERT(sarg->sbp != NULL); 1399 na->files_avail = sarg->sbp->f_favail; 1400 break; 1401 case NFS4ATTR_SETIT: 1402 /* 1403 * read-only attr 1404 */ 1405 error = EINVAL; 1406 break; 1407 case NFS4ATTR_VERIT: 1408 ASSERT(sarg->sbp != NULL); 1409 if (sarg->sbp->f_favail != na->files_avail) 1410 error = -1; /* no match */ 1411 break; 1412 case NFS4ATTR_FREEIT: 1413 break; 1414 } 1415 return (error); 1416 } 1417 1418 /* ARGSUSED */ 1419 static int 1420 rfs4_fattr4_files_free(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1421 union nfs4_attr_u *na) 1422 { 1423 int error = 0; 1424 1425 if (RFS4_MANDATTR_ONLY) 1426 return (ENOTSUP); 1427 1428 switch (cmd) { 1429 case NFS4ATTR_SUPPORTED: 1430 if (sarg->op == NFS4ATTR_SETIT) 1431 error = EINVAL; 1432 break; /* this attr is supported */ 1433 case NFS4ATTR_GETIT: 1434 if (sarg->rdattr_error && (sarg->sbp == NULL)) { 1435 error = -1; /* may be okay if rdattr_error */ 1436 break; 1437 } 1438 ASSERT(sarg->sbp != NULL); 1439 na->files_free = sarg->sbp->f_ffree; 1440 break; 1441 case NFS4ATTR_SETIT: 1442 /* 1443 * read-only attr 1444 */ 1445 error = EINVAL; 1446 break; 1447 case NFS4ATTR_VERIT: 1448 ASSERT(sarg->sbp != NULL); 1449 if (sarg->sbp->f_ffree != na->files_free) 1450 error = -1; /* no match */ 1451 break; 1452 case NFS4ATTR_FREEIT: 1453 break; 1454 } 1455 return (error); 1456 } 1457 1458 /* ARGSUSED */ 1459 static int 1460 rfs4_fattr4_files_total(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1461 union nfs4_attr_u *na) 1462 { 1463 int error = 0; 1464 1465 if (RFS4_MANDATTR_ONLY) 1466 return (ENOTSUP); 1467 1468 switch (cmd) { 1469 case NFS4ATTR_SUPPORTED: 1470 if (sarg->op == NFS4ATTR_SETIT) 1471 error = EINVAL; 1472 break; /* this attr is supported */ 1473 case NFS4ATTR_GETIT: 1474 if (sarg->rdattr_error && (sarg->sbp == NULL)) { 1475 error = -1; /* may be okay if rdattr_error */ 1476 break; 1477 } 1478 ASSERT(sarg->sbp != NULL); 1479 na->files_total = sarg->sbp->f_files; 1480 break; 1481 case NFS4ATTR_SETIT: 1482 /* 1483 * read-only attr 1484 */ 1485 error = EINVAL; 1486 break; 1487 case NFS4ATTR_VERIT: 1488 ASSERT(sarg->sbp != NULL); 1489 if (sarg->sbp->f_files != na->files_total) 1490 error = -1; /* no match */ 1491 break; 1492 case NFS4ATTR_FREEIT: 1493 break; 1494 } 1495 return (error); 1496 } 1497 1498 /* ARGSUSED */ 1499 static int 1500 rfs4_fattr4_fs_locations(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1501 union nfs4_attr_u *na) 1502 { 1503 return (ENOTSUP); 1504 } 1505 1506 /* ARGSUSED */ 1507 static int 1508 rfs4_fattr4_hidden(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1509 union nfs4_attr_u *na) 1510 { 1511 return (ENOTSUP); 1512 } 1513 1514 /* ARGSUSED */ 1515 static int 1516 rfs4_fattr4_homogeneous(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1517 union nfs4_attr_u *na) 1518 { 1519 int error = 0; 1520 1521 if (RFS4_MANDATTR_ONLY) 1522 return (ENOTSUP); 1523 1524 switch (cmd) { 1525 case NFS4ATTR_SUPPORTED: 1526 if (sarg->op == NFS4ATTR_SETIT) 1527 error = EINVAL; 1528 break; /* this attr is supported */ 1529 case NFS4ATTR_GETIT: 1530 na->homogeneous = TRUE; /* XXX - need a VOP extension */ 1531 break; 1532 case NFS4ATTR_SETIT: 1533 /* 1534 * read-only attr 1535 */ 1536 error = EINVAL; 1537 break; 1538 case NFS4ATTR_VERIT: 1539 if (!na->homogeneous) 1540 error = -1; /* no match */ 1541 break; 1542 case NFS4ATTR_FREEIT: 1543 break; 1544 } 1545 return (error); 1546 } 1547 1548 /* ARGSUSED */ 1549 static int 1550 rfs4_fattr4_maxfilesize(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1551 union nfs4_attr_u *na) 1552 { 1553 int error = 0; 1554 ulong_t val; 1555 fattr4_maxfilesize maxfilesize; 1556 1557 if (RFS4_MANDATTR_ONLY) 1558 return (ENOTSUP); 1559 1560 switch (cmd) { 1561 case NFS4ATTR_SUPPORTED: 1562 if (sarg->op == NFS4ATTR_SETIT) 1563 error = EINVAL; 1564 break; /* this attr is supported */ 1565 case NFS4ATTR_GETIT: 1566 if (sarg->rdattr_error && (sarg->cs->vp == NULL)) { 1567 error = -1; /* may be okay if rdattr_error */ 1568 break; 1569 } 1570 ASSERT(sarg->cs->vp != NULL); 1571 error = VOP_PATHCONF(sarg->cs->vp, _PC_FILESIZEBITS, &val, 1572 sarg->cs->cr, NULL); 1573 if (error) 1574 break; 1575 1576 /* 1577 * If the underlying file system does not support 1578 * _PC_FILESIZEBITS, return a reasonable default. Note that 1579 * error code on VOP_PATHCONF will be 0, even if the underlying 1580 * file system does not support _PC_FILESIZEBITS. 1581 */ 1582 if (val == (ulong_t)-1) { 1583 na->maxfilesize = MAXOFF32_T; 1584 } else { 1585 if (val >= (sizeof (uint64_t) * 8)) 1586 na->maxfilesize = INT64_MAX; 1587 else 1588 na->maxfilesize = ((1LL << (val - 1)) - 1); 1589 } 1590 break; 1591 case NFS4ATTR_SETIT: 1592 /* 1593 * read-only attr 1594 */ 1595 error = EINVAL; 1596 break; 1597 case NFS4ATTR_VERIT: 1598 ASSERT(sarg->cs->vp != NULL); 1599 error = VOP_PATHCONF(sarg->cs->vp, _PC_FILESIZEBITS, &val, 1600 sarg->cs->cr, NULL); 1601 if (error) 1602 break; 1603 /* 1604 * If the underlying file system does not support 1605 * _PC_FILESIZEBITS, return a reasonable default. Note that 1606 * error code on VOP_PATHCONF will be 0, even if the underlying 1607 * file system does not support _PC_FILESIZEBITS. 1608 */ 1609 if (val == (ulong_t)-1) { 1610 maxfilesize = MAXOFF32_T; 1611 } else { 1612 if (val >= (sizeof (uint64_t) * 8)) 1613 maxfilesize = INT64_MAX; 1614 else 1615 maxfilesize = ((1LL << (val - 1)) - 1); 1616 } 1617 if (na->maxfilesize != maxfilesize) 1618 error = -1; /* no match */ 1619 break; 1620 case NFS4ATTR_FREEIT: 1621 break; 1622 } 1623 return (error); 1624 } 1625 1626 /* ARGSUSED */ 1627 static int 1628 rfs4_fattr4_maxlink(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1629 union nfs4_attr_u *na) 1630 { 1631 int error = 0; 1632 ulong_t val; 1633 1634 if (RFS4_MANDATTR_ONLY) 1635 return (ENOTSUP); 1636 1637 switch (cmd) { 1638 case NFS4ATTR_SUPPORTED: 1639 if (sarg->op == NFS4ATTR_SETIT) 1640 error = EINVAL; 1641 break; /* this attr is supported */ 1642 case NFS4ATTR_GETIT: 1643 if (sarg->rdattr_error && (sarg->cs->vp == NULL)) { 1644 error = -1; /* may be okay if rdattr_error */ 1645 break; 1646 } 1647 ASSERT(sarg->cs->vp != NULL); 1648 error = VOP_PATHCONF(sarg->cs->vp, _PC_LINK_MAX, &val, 1649 sarg->cs->cr, NULL); 1650 if (error == 0) { 1651 na->maxlink = val; 1652 } 1653 break; 1654 case NFS4ATTR_SETIT: 1655 /* 1656 * read-only attr 1657 */ 1658 error = EINVAL; 1659 break; 1660 case NFS4ATTR_VERIT: 1661 ASSERT(sarg->cs->vp != NULL); 1662 error = VOP_PATHCONF(sarg->cs->vp, _PC_LINK_MAX, &val, 1663 sarg->cs->cr, NULL); 1664 if (!error && (na->maxlink != (uint32_t)val)) 1665 error = -1; /* no match */ 1666 break; 1667 case NFS4ATTR_FREEIT: 1668 break; 1669 } 1670 return (error); 1671 } 1672 1673 /* ARGSUSED */ 1674 static int 1675 rfs4_fattr4_maxname(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1676 union nfs4_attr_u *na) 1677 { 1678 int error = 0; 1679 ulong_t val; 1680 1681 if (RFS4_MANDATTR_ONLY) 1682 return (ENOTSUP); 1683 1684 switch (cmd) { 1685 case NFS4ATTR_SUPPORTED: 1686 if (sarg->op == NFS4ATTR_SETIT) 1687 error = EINVAL; 1688 break; /* this attr is supported */ 1689 case NFS4ATTR_GETIT: 1690 if (sarg->rdattr_error && (sarg->cs->vp == NULL)) { 1691 error = -1; /* may be okay if rdattr_error */ 1692 break; 1693 } 1694 ASSERT(sarg->cs->vp != NULL); 1695 error = VOP_PATHCONF(sarg->cs->vp, _PC_NAME_MAX, &val, 1696 sarg->cs->cr, NULL); 1697 if (error == 0) { 1698 na->maxname = val; 1699 } 1700 break; 1701 case NFS4ATTR_SETIT: 1702 /* 1703 * read-only attr 1704 */ 1705 error = EINVAL; 1706 break; 1707 case NFS4ATTR_VERIT: 1708 ASSERT(sarg->cs->vp != NULL); 1709 error = VOP_PATHCONF(sarg->cs->vp, _PC_NAME_MAX, &val, 1710 sarg->cs->cr, NULL); 1711 if (!error && (na->maxname != val)) 1712 error = -1; /* no match */ 1713 break; 1714 case NFS4ATTR_FREEIT: 1715 break; 1716 } 1717 return (error); 1718 } 1719 1720 /* ARGSUSED */ 1721 static int 1722 rfs4_fattr4_maxread(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1723 union nfs4_attr_u *na) 1724 { 1725 int error = 0; 1726 1727 if (RFS4_MANDATTR_ONLY) 1728 return (ENOTSUP); 1729 1730 switch (cmd) { 1731 case NFS4ATTR_SUPPORTED: 1732 if (sarg->op == NFS4ATTR_SETIT) 1733 error = EINVAL; 1734 break; /* this attr is supported */ 1735 case NFS4ATTR_GETIT: 1736 na->maxread = rfs4_tsize(sarg->cs->req); 1737 break; 1738 case NFS4ATTR_SETIT: 1739 /* 1740 * read-only attr 1741 */ 1742 error = EINVAL; 1743 break; 1744 case NFS4ATTR_VERIT: 1745 if (na->maxread != rfs4_tsize(sarg->cs->req)) 1746 error = -1; /* no match */ 1747 break; 1748 case NFS4ATTR_FREEIT: 1749 break; 1750 } 1751 return (error); 1752 } 1753 1754 /* ARGSUSED */ 1755 static int 1756 rfs4_fattr4_maxwrite(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1757 union nfs4_attr_u *na) 1758 { 1759 int error = 0; 1760 1761 if (RFS4_MANDATTR_ONLY) 1762 return (ENOTSUP); 1763 1764 switch (cmd) { 1765 case NFS4ATTR_SUPPORTED: 1766 if (sarg->op == NFS4ATTR_SETIT) 1767 error = EINVAL; 1768 break; /* this attr is supported */ 1769 case NFS4ATTR_GETIT: 1770 na->maxwrite = rfs4_tsize(sarg->cs->req); 1771 break; 1772 case NFS4ATTR_SETIT: 1773 /* 1774 * read-only attr 1775 */ 1776 error = EINVAL; 1777 break; 1778 case NFS4ATTR_VERIT: 1779 if (na->maxwrite != rfs4_tsize(sarg->cs->req)) 1780 error = -1; /* no match */ 1781 break; 1782 case NFS4ATTR_FREEIT: 1783 break; 1784 } 1785 return (error); 1786 } 1787 1788 /* ARGSUSED */ 1789 static int 1790 rfs4_fattr4_mimetype(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1791 union nfs4_attr_u *na) 1792 { 1793 return (ENOTSUP); 1794 } 1795 1796 /* ARGSUSED */ 1797 static int 1798 rfs4_fattr4_mode(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1799 union nfs4_attr_u *na) 1800 { 1801 int error = 0; 1802 1803 if (RFS4_MANDATTR_ONLY) 1804 return (ENOTSUP); 1805 1806 switch (cmd) { 1807 case NFS4ATTR_SUPPORTED: 1808 break; /* this attr is supported */ 1809 case NFS4ATTR_GETIT: 1810 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_MODE)) { 1811 error = -1; /* may be okay if rdattr_error */ 1812 break; 1813 } 1814 ASSERT(sarg->vap->va_mask & AT_MODE); 1815 na->mode = sarg->vap->va_mode; 1816 break; 1817 case NFS4ATTR_SETIT: 1818 ASSERT(sarg->vap->va_mask & AT_MODE); 1819 sarg->vap->va_mode = na->mode; 1820 /* 1821 * If the filesystem is exported with nosuid, then mask off 1822 * the setuid and setgid bits. 1823 */ 1824 if (sarg->cs->vp->v_type == VREG && 1825 (sarg->cs->exi->exi_export.ex_flags & EX_NOSUID)) 1826 sarg->vap->va_mode &= ~(VSUID | VSGID); 1827 break; 1828 case NFS4ATTR_VERIT: 1829 ASSERT(sarg->vap->va_mask & AT_MODE); 1830 if (sarg->vap->va_mode != na->mode) 1831 error = -1; /* no match */ 1832 break; 1833 case NFS4ATTR_FREEIT: 1834 break; 1835 } 1836 return (error); 1837 } 1838 1839 /* ARGSUSED */ 1840 static int 1841 rfs4_fattr4_no_trunc(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1842 union nfs4_attr_u *na) 1843 { 1844 int error = 0; 1845 1846 if (RFS4_MANDATTR_ONLY) 1847 return (ENOTSUP); 1848 1849 switch (cmd) { 1850 case NFS4ATTR_SUPPORTED: 1851 if (sarg->op == NFS4ATTR_SETIT) 1852 error = EINVAL; 1853 break; /* this attr is supported */ 1854 case NFS4ATTR_GETIT: 1855 na->no_trunc = TRUE; 1856 break; 1857 case NFS4ATTR_SETIT: 1858 /* 1859 * read-only attr 1860 */ 1861 error = EINVAL; 1862 break; 1863 case NFS4ATTR_VERIT: 1864 if (!na->no_trunc) 1865 error = -1; /* no match */ 1866 break; 1867 case NFS4ATTR_FREEIT: 1868 break; 1869 } 1870 return (error); 1871 } 1872 1873 /* ARGSUSED */ 1874 static int 1875 rfs4_fattr4_numlinks(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1876 union nfs4_attr_u *na) 1877 { 1878 int error = 0; 1879 1880 if (RFS4_MANDATTR_ONLY) 1881 return (ENOTSUP); 1882 1883 switch (cmd) { 1884 case NFS4ATTR_SUPPORTED: 1885 if (sarg->op == NFS4ATTR_SETIT) 1886 error = EINVAL; 1887 break; /* this attr is supported */ 1888 case NFS4ATTR_GETIT: 1889 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_NLINK)) { 1890 error = -1; /* may be okay if rdattr_error */ 1891 break; 1892 } 1893 ASSERT(sarg->vap->va_mask & AT_NLINK); 1894 na->numlinks = sarg->vap->va_nlink; 1895 break; 1896 case NFS4ATTR_SETIT: 1897 /* 1898 * read-only attr 1899 */ 1900 error = EINVAL; 1901 break; 1902 case NFS4ATTR_VERIT: 1903 ASSERT(sarg->vap->va_mask & AT_NLINK); 1904 if (sarg->vap->va_nlink != na->numlinks) 1905 error = -1; /* no match */ 1906 break; 1907 case NFS4ATTR_FREEIT: 1908 break; 1909 } 1910 return (error); 1911 } 1912 1913 /* ARGSUSED */ 1914 static int 1915 rfs4_fattr4_owner(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1916 union nfs4_attr_u *na) 1917 { 1918 int error = 0; 1919 uid_t uid; 1920 1921 if (RFS4_MANDATTR_ONLY) 1922 return (ENOTSUP); 1923 1924 switch (cmd) { 1925 case NFS4ATTR_SUPPORTED: 1926 break; /* this attr is supported */ 1927 case NFS4ATTR_GETIT: 1928 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_UID)) { 1929 error = -1; /* may be okay if rdattr_error */ 1930 break; 1931 } 1932 ASSERT(sarg->vap->va_mask & AT_UID); 1933 1934 /* 1935 * There are well defined polices for what happens on server- 1936 * side GETATTR when uid to attribute string conversion cannot 1937 * occur. Please refer to nfs4_idmap.c for details. 1938 */ 1939 error = nfs_idmap_uid_str(sarg->vap->va_uid, &na->owner, TRUE); 1940 switch (error) { 1941 case ECONNREFUSED: 1942 error = NFS4ERR_DELAY; 1943 break; 1944 default: 1945 break; 1946 } 1947 break; 1948 1949 case NFS4ATTR_SETIT: 1950 ASSERT(sarg->vap->va_mask & AT_UID); 1951 1952 /* 1953 * There are well defined policies for what happens on server- 1954 * side SETATTR of 'owner' when a "user@domain" mapping cannot 1955 * occur. Please refer to nfs4_idmap.c for details. 1956 * 1957 * Any other errors, such as the mapping not being found by 1958 * nfsmapid(1m), and interrupted clnt_call, etc, will result 1959 * in NFS4ERR_BADOWNER. 1960 * 1961 * XXX need to return consistent errors, perhaps all 1962 * server side attribute routines should return NFS4ERR*. 1963 */ 1964 error = nfs_idmap_str_uid(&na->owner, &sarg->vap->va_uid, TRUE); 1965 switch (error) { 1966 case NFS4_OK: 1967 case ENOTSUP: 1968 /* 1969 * Ignore warning that we are the 1970 * nfsmapid (can't happen on srv) 1971 */ 1972 error = 0; 1973 MSG_PRT_DEBUG = FALSE; 1974 break; 1975 1976 case ECOMM: 1977 case ECONNREFUSED: 1978 if (!MSG_PRT_DEBUG) { 1979 /* 1980 * printed just once per daemon death, 1981 * inform the user and then stay silent 1982 */ 1983 cmn_err(CE_WARN, "!Unable to contact " 1984 "nfsmapid"); 1985 MSG_PRT_DEBUG = TRUE; 1986 } 1987 error = NFS4ERR_DELAY; 1988 break; 1989 1990 case EINVAL: 1991 error = NFS4ERR_INVAL; 1992 break; 1993 1994 default: 1995 error = NFS4ERR_BADOWNER; 1996 break; 1997 } 1998 break; 1999 2000 case NFS4ATTR_VERIT: 2001 ASSERT(sarg->vap->va_mask & AT_UID); 2002 error = nfs_idmap_str_uid(&na->owner, &uid, TRUE); 2003 /* 2004 * Ignore warning that we are the nfsmapid (can't happen on srv) 2005 */ 2006 if (error == ENOTSUP) 2007 error = 0; 2008 if (error) 2009 error = -1; /* no match */ 2010 else if (sarg->vap->va_uid != uid) 2011 error = -1; /* no match */ 2012 break; 2013 case NFS4ATTR_FREEIT: 2014 if (sarg->op == NFS4ATTR_GETIT) { 2015 if (na->owner.utf8string_val) { 2016 UTF8STRING_FREE(na->owner) 2017 bzero(&na->owner, sizeof (na->owner)); 2018 } 2019 } 2020 break; 2021 } 2022 return (error); 2023 } 2024 2025 /* ARGSUSED */ 2026 static int 2027 rfs4_fattr4_owner_group(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2028 union nfs4_attr_u *na) 2029 { 2030 int error = 0; 2031 gid_t gid; 2032 2033 if (RFS4_MANDATTR_ONLY) 2034 return (ENOTSUP); 2035 2036 switch (cmd) { 2037 case NFS4ATTR_SUPPORTED: 2038 break; /* this attr is supported */ 2039 case NFS4ATTR_GETIT: 2040 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_GID)) { 2041 error = -1; /* may be okay if rdattr_error */ 2042 break; 2043 } 2044 ASSERT(sarg->vap->va_mask & AT_GID); 2045 2046 /* 2047 * There are well defined polices for what happens on server- 2048 * side GETATTR when gid to attribute string conversion cannot 2049 * occur. Please refer to nfs4_idmap.c for details. 2050 */ 2051 error = nfs_idmap_gid_str(sarg->vap->va_gid, &na->owner_group, 2052 TRUE); 2053 switch (error) { 2054 case ECONNREFUSED: 2055 error = NFS4ERR_DELAY; 2056 break; 2057 default: 2058 break; 2059 } 2060 break; 2061 2062 case NFS4ATTR_SETIT: 2063 ASSERT(sarg->vap->va_mask & AT_GID); 2064 2065 /* 2066 * There are well defined policies for what happens on server- 2067 * side SETATTR of 'owner_group' when a "group@domain" mapping 2068 * cannot occur. Please refer to nfs4_idmap.c for details. 2069 * 2070 * Any other errors, such as the mapping not being found by 2071 * nfsmapid(1m), and interrupted clnt_call, etc, will result 2072 * in NFS4ERR_BADOWNER. 2073 * 2074 * XXX need to return consistent errors, perhaps all 2075 * server side attribute routines should return NFS4ERR*. 2076 */ 2077 error = nfs_idmap_str_gid(&na->owner_group, &sarg->vap->va_gid, 2078 TRUE); 2079 switch (error) { 2080 case NFS4_OK: 2081 case ENOTSUP: 2082 /* 2083 * Ignore warning that we are the 2084 * nfsmapid (can't happen on srv) 2085 */ 2086 error = 0; 2087 MSG_PRT_DEBUG = FALSE; 2088 break; 2089 2090 case ECOMM: 2091 case ECONNREFUSED: 2092 if (!MSG_PRT_DEBUG) { 2093 /* 2094 * printed just once per daemon death, 2095 * inform the user and then stay silent 2096 */ 2097 cmn_err(CE_WARN, "!Unable to contact " 2098 "nfsmapid"); 2099 MSG_PRT_DEBUG = TRUE; 2100 } 2101 error = NFS4ERR_DELAY; 2102 break; 2103 2104 case EINVAL: 2105 error = NFS4ERR_INVAL; 2106 break; 2107 2108 default: 2109 error = NFS4ERR_BADOWNER; 2110 break; 2111 } 2112 break; 2113 2114 case NFS4ATTR_VERIT: 2115 ASSERT(sarg->vap->va_mask & AT_GID); 2116 error = nfs_idmap_str_gid(&na->owner_group, &gid, TRUE); 2117 /* 2118 * Ignore warning that we are the nfsmapid (can't happen on srv) 2119 */ 2120 if (error == ENOTSUP) 2121 error = 0; 2122 if (error) 2123 error = -1; /* no match */ 2124 else if (sarg->vap->va_gid != gid) 2125 error = -1; /* no match */ 2126 break; 2127 case NFS4ATTR_FREEIT: 2128 if (sarg->op == NFS4ATTR_GETIT) { 2129 if (na->owner_group.utf8string_val) { 2130 UTF8STRING_FREE(na->owner_group) 2131 bzero(&na->owner_group, 2132 sizeof (na->owner_group)); 2133 } 2134 } 2135 break; 2136 } 2137 return (error); 2138 } 2139 2140 /* XXX - quota attributes should be supportable on Solaris 2 */ 2141 /* ARGSUSED */ 2142 static int 2143 rfs4_fattr4_quota_avail_hard(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2144 union nfs4_attr_u *na) 2145 { 2146 return (ENOTSUP); 2147 } 2148 2149 /* ARGSUSED */ 2150 static int 2151 rfs4_fattr4_quota_avail_soft(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2152 union nfs4_attr_u *na) 2153 { 2154 return (ENOTSUP); 2155 } 2156 2157 /* ARGSUSED */ 2158 static int 2159 rfs4_fattr4_quota_used(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2160 union nfs4_attr_u *na) 2161 { 2162 return (ENOTSUP); 2163 } 2164 2165 /* ARGSUSED */ 2166 static int 2167 rfs4_fattr4_rawdev(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2168 union nfs4_attr_u *na) 2169 { 2170 int error = 0; 2171 2172 if (RFS4_MANDATTR_ONLY) 2173 return (ENOTSUP); 2174 2175 switch (cmd) { 2176 case NFS4ATTR_SUPPORTED: 2177 if (sarg->op == NFS4ATTR_SETIT) 2178 error = EINVAL; 2179 break; /* this attr is supported */ 2180 case NFS4ATTR_GETIT: 2181 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_RDEV)) { 2182 error = -1; /* may be okay if rdattr_error */ 2183 break; 2184 } 2185 ASSERT(sarg->vap->va_mask & AT_RDEV); 2186 na->rawdev.specdata1 = (uint32)getmajor(sarg->vap->va_rdev); 2187 na->rawdev.specdata2 = (uint32)getminor(sarg->vap->va_rdev); 2188 break; 2189 case NFS4ATTR_SETIT: 2190 /* 2191 * read-only attr 2192 */ 2193 error = EINVAL; 2194 break; 2195 case NFS4ATTR_VERIT: 2196 ASSERT(sarg->vap->va_mask & AT_RDEV); 2197 if ((na->rawdev.specdata1 != 2198 (uint32)getmajor(sarg->vap->va_rdev)) || 2199 (na->rawdev.specdata2 != 2200 (uint32)getminor(sarg->vap->va_rdev))) 2201 error = -1; /* no match */ 2202 break; 2203 case NFS4ATTR_FREEIT: 2204 break; 2205 } 2206 return (error); 2207 } 2208 2209 /* ARGSUSED */ 2210 static int 2211 rfs4_fattr4_space_avail(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2212 union nfs4_attr_u *na) 2213 { 2214 int error = 0; 2215 2216 if (RFS4_MANDATTR_ONLY) 2217 return (ENOTSUP); 2218 2219 switch (cmd) { 2220 case NFS4ATTR_SUPPORTED: 2221 if (sarg->op == NFS4ATTR_SETIT) 2222 error = EINVAL; 2223 break; /* this attr is supported */ 2224 case NFS4ATTR_GETIT: 2225 if (sarg->rdattr_error && (sarg->sbp == NULL)) { 2226 error = -1; /* may be okay if rdattr_error */ 2227 break; 2228 } 2229 ASSERT(sarg->sbp != NULL); 2230 if (sarg->sbp->f_bavail != (fsblkcnt64_t)-1) { 2231 na->space_avail = 2232 (fattr4_space_avail) sarg->sbp->f_frsize * 2233 (fattr4_space_avail) sarg->sbp->f_bavail; 2234 } else { 2235 na->space_avail = 2236 (fattr4_space_avail) sarg->sbp->f_bavail; 2237 } 2238 break; 2239 case NFS4ATTR_SETIT: 2240 /* 2241 * read-only attr 2242 */ 2243 error = EINVAL; 2244 break; 2245 case NFS4ATTR_VERIT: 2246 ASSERT(sarg->sbp != NULL); 2247 if (sarg->sbp->f_bavail != na->space_avail) 2248 error = -1; /* no match */ 2249 break; 2250 case NFS4ATTR_FREEIT: 2251 break; 2252 } 2253 return (error); 2254 } 2255 2256 /* ARGSUSED */ 2257 static int 2258 rfs4_fattr4_space_free(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2259 union nfs4_attr_u *na) 2260 { 2261 int error = 0; 2262 2263 if (RFS4_MANDATTR_ONLY) 2264 return (ENOTSUP); 2265 2266 switch (cmd) { 2267 case NFS4ATTR_SUPPORTED: 2268 if (sarg->op == NFS4ATTR_SETIT) 2269 error = EINVAL; 2270 break; /* this attr is supported */ 2271 case NFS4ATTR_GETIT: 2272 if (sarg->rdattr_error && (sarg->sbp == NULL)) { 2273 error = -1; /* may be okay if rdattr_error */ 2274 break; 2275 } 2276 ASSERT(sarg->sbp != NULL); 2277 if (sarg->sbp->f_bfree != (fsblkcnt64_t)-1) { 2278 na->space_free = 2279 (fattr4_space_free) sarg->sbp->f_frsize * 2280 (fattr4_space_free) sarg->sbp->f_bfree; 2281 } else { 2282 na->space_free = 2283 (fattr4_space_free) sarg->sbp->f_bfree; 2284 } 2285 break; 2286 case NFS4ATTR_SETIT: 2287 /* 2288 * read-only attr 2289 */ 2290 error = EINVAL; 2291 break; 2292 case NFS4ATTR_VERIT: 2293 ASSERT(sarg->sbp != NULL); 2294 if (sarg->sbp->f_bfree != na->space_free) 2295 error = -1; /* no match */ 2296 break; 2297 case NFS4ATTR_FREEIT: 2298 break; 2299 } 2300 return (error); 2301 } 2302 2303 /* ARGSUSED */ 2304 static int 2305 rfs4_fattr4_space_total(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2306 union nfs4_attr_u *na) 2307 { 2308 int error = 0; 2309 2310 if (RFS4_MANDATTR_ONLY) 2311 return (ENOTSUP); 2312 2313 switch (cmd) { 2314 case NFS4ATTR_SUPPORTED: 2315 if (sarg->op == NFS4ATTR_SETIT) 2316 error = EINVAL; 2317 break; /* this attr is supported */ 2318 case NFS4ATTR_GETIT: 2319 if (sarg->rdattr_error_req && (sarg->sbp == NULL)) { 2320 error = -1; /* may be okay if rdattr_error */ 2321 break; 2322 } 2323 ASSERT(sarg->sbp != NULL); 2324 if (sarg->sbp->f_blocks != (fsblkcnt64_t)-1) { 2325 na->space_total = 2326 (fattr4_space_total) sarg->sbp->f_frsize * 2327 (fattr4_space_total) sarg->sbp->f_blocks; 2328 } else { 2329 na->space_total = 2330 (fattr4_space_total) sarg->sbp->f_blocks; 2331 } 2332 break; 2333 case NFS4ATTR_SETIT: 2334 /* 2335 * read-only attr 2336 */ 2337 error = EINVAL; 2338 break; 2339 case NFS4ATTR_VERIT: 2340 ASSERT(sarg->sbp != NULL); 2341 if (sarg->sbp->f_blocks != na->space_total) 2342 error = -1; /* no match */ 2343 break; 2344 case NFS4ATTR_FREEIT: 2345 break; 2346 } 2347 return (error); 2348 } 2349 2350 /* ARGSUSED */ 2351 static int 2352 rfs4_fattr4_space_used(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2353 union nfs4_attr_u *na) 2354 { 2355 int error = 0; 2356 2357 if (RFS4_MANDATTR_ONLY) 2358 return (ENOTSUP); 2359 2360 switch (cmd) { 2361 case NFS4ATTR_SUPPORTED: 2362 if (sarg->op == NFS4ATTR_SETIT) 2363 error = EINVAL; 2364 break; /* this attr is supported */ 2365 case NFS4ATTR_GETIT: 2366 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_NBLOCKS)) { 2367 error = -1; /* may be okay if rdattr_error */ 2368 break; 2369 } 2370 ASSERT(sarg->vap->va_mask & AT_NBLOCKS); 2371 na->space_used = (fattr4_space_used) DEV_BSIZE * 2372 (fattr4_space_used) sarg->vap->va_nblocks; 2373 break; 2374 case NFS4ATTR_SETIT: 2375 /* 2376 * read-only attr 2377 */ 2378 error = EINVAL; 2379 break; 2380 case NFS4ATTR_VERIT: 2381 ASSERT(sarg->vap->va_mask & AT_NBLOCKS); 2382 if (sarg->vap->va_nblocks != na->space_used) 2383 error = -1; /* no match */ 2384 break; 2385 case NFS4ATTR_FREEIT: 2386 break; 2387 } 2388 return (error); 2389 } 2390 2391 /* ARGSUSED */ 2392 static int 2393 rfs4_fattr4_system(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2394 union nfs4_attr_u *na) 2395 { 2396 return (ENOTSUP); 2397 } 2398 2399 /* ARGSUSED */ 2400 static int 2401 rfs4_fattr4_time_access(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2402 union nfs4_attr_u *na) 2403 { 2404 int error = 0; 2405 timestruc_t atime; 2406 2407 if (RFS4_MANDATTR_ONLY) 2408 return (ENOTSUP); 2409 2410 switch (cmd) { 2411 case NFS4ATTR_SUPPORTED: 2412 if (sarg->op == NFS4ATTR_SETIT) 2413 error = EINVAL; 2414 break; /* this attr is supported */ 2415 case NFS4ATTR_GETIT: 2416 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_ATIME)) { 2417 error = -1; /* may be okay if rdattr_error */ 2418 break; 2419 } 2420 ASSERT(sarg->vap->va_mask & AT_ATIME); 2421 error = nfs4_time_vton(&sarg->vap->va_atime, &na->time_access); 2422 break; 2423 case NFS4ATTR_SETIT: 2424 /* 2425 * read-only attr 2426 */ 2427 error = EINVAL; 2428 break; 2429 case NFS4ATTR_VERIT: 2430 ASSERT(sarg->vap->va_mask & AT_ATIME); 2431 error = nfs4_time_ntov(&na->time_access, &atime); 2432 if (error) 2433 break; 2434 if (bcmp(&atime, &sarg->vap->va_atime, sizeof (atime))) 2435 error = -1; /* no match */ 2436 break; 2437 case NFS4ATTR_FREEIT: 2438 break; 2439 } 2440 return (error); 2441 } 2442 2443 /* 2444 * XXX - need to support the setting of access time 2445 */ 2446 /* ARGSUSED */ 2447 static int 2448 rfs4_fattr4_time_access_set(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2449 union nfs4_attr_u *na) 2450 { 2451 int error = 0; 2452 settime4 *ta; 2453 2454 if (RFS4_MANDATTR_ONLY) 2455 return (ENOTSUP); 2456 2457 switch (cmd) { 2458 case NFS4ATTR_SUPPORTED: 2459 if ((sarg->op == NFS4ATTR_GETIT) || 2460 (sarg->op == NFS4ATTR_VERIT)) 2461 error = EINVAL; 2462 break; /* this attr is supported */ 2463 case NFS4ATTR_GETIT: 2464 case NFS4ATTR_VERIT: 2465 /* 2466 * write only attr 2467 */ 2468 error = EINVAL; 2469 break; 2470 case NFS4ATTR_SETIT: 2471 ASSERT(sarg->vap->va_mask & AT_ATIME); 2472 /* 2473 * Set access time (by server or by client) 2474 */ 2475 ta = &na->time_access_set; 2476 if (ta->set_it == SET_TO_CLIENT_TIME4) { 2477 error = nfs4_time_ntov(&ta->time, &sarg->vap->va_atime); 2478 } else if (ta->set_it == SET_TO_SERVER_TIME4) { 2479 gethrestime(&sarg->vap->va_atime); 2480 } else { 2481 error = EINVAL; 2482 } 2483 break; 2484 case NFS4ATTR_FREEIT: 2485 break; 2486 } 2487 return (error); 2488 } 2489 2490 /* ARGSUSED */ 2491 static int 2492 rfs4_fattr4_time_backup(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2493 union nfs4_attr_u *na) 2494 { 2495 return (ENOTSUP); 2496 } 2497 2498 /* ARGSUSED */ 2499 static int 2500 rfs4_fattr4_time_create(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2501 union nfs4_attr_u *na) 2502 { 2503 return (ENOTSUP); 2504 } 2505 2506 /* ARGSUSED */ 2507 static int 2508 rfs4_fattr4_time_delta(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2509 union nfs4_attr_u *na) 2510 { 2511 int error = 0; 2512 2513 if (RFS4_MANDATTR_ONLY) 2514 return (ENOTSUP); 2515 2516 switch (cmd) { 2517 case NFS4ATTR_SUPPORTED: 2518 if (sarg->op == NFS4ATTR_SETIT) 2519 error = EINVAL; 2520 break; /* this attr is supported */ 2521 case NFS4ATTR_GETIT: 2522 na->time_delta.seconds = 0; 2523 na->time_delta.nseconds = 1000; 2524 break; 2525 case NFS4ATTR_SETIT: 2526 /* 2527 * write only attr 2528 */ 2529 error = EINVAL; 2530 break; 2531 case NFS4ATTR_VERIT: 2532 if ((na->time_delta.seconds != 0) || 2533 (na->time_delta.nseconds != 1000)) 2534 error = -1; /* no match */ 2535 break; 2536 case NFS4ATTR_FREEIT: 2537 break; 2538 } 2539 return (error); 2540 } 2541 2542 /* ARGSUSED */ 2543 static int 2544 rfs4_fattr4_time_metadata(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2545 union nfs4_attr_u *na) 2546 { 2547 int error = 0; 2548 timestruc_t ctime; 2549 2550 if (RFS4_MANDATTR_ONLY) 2551 return (ENOTSUP); 2552 2553 switch (cmd) { 2554 case NFS4ATTR_SUPPORTED: 2555 if (sarg->op == NFS4ATTR_SETIT) 2556 error = EINVAL; 2557 break; /* this attr is supported */ 2558 case NFS4ATTR_GETIT: 2559 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_CTIME)) { 2560 error = -1; /* may be okay if rdattr_error */ 2561 break; 2562 } 2563 ASSERT(sarg->vap->va_mask & AT_CTIME); 2564 error = nfs4_time_vton(&sarg->vap->va_ctime, 2565 &na->time_metadata); 2566 break; 2567 case NFS4ATTR_SETIT: 2568 /* 2569 * read-only attr 2570 */ 2571 error = EINVAL; 2572 break; 2573 case NFS4ATTR_VERIT: 2574 ASSERT(sarg->vap->va_mask & AT_CTIME); 2575 error = nfs4_time_ntov(&na->time_metadata, &ctime); 2576 if (error) 2577 break; 2578 if (bcmp(&ctime, &sarg->vap->va_ctime, sizeof (ctime))) 2579 error = -1; /* no match */ 2580 break; 2581 case NFS4ATTR_FREEIT: 2582 break; 2583 } 2584 return (error); 2585 } 2586 2587 /* ARGSUSED */ 2588 static int 2589 rfs4_fattr4_time_modify(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2590 union nfs4_attr_u *na) 2591 { 2592 int error = 0; 2593 timestruc_t mtime; 2594 2595 if (RFS4_MANDATTR_ONLY) 2596 return (ENOTSUP); 2597 2598 switch (cmd) { 2599 case NFS4ATTR_SUPPORTED: 2600 if (sarg->op == NFS4ATTR_SETIT) 2601 error = EINVAL; 2602 break; /* this attr is supported */ 2603 case NFS4ATTR_GETIT: 2604 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_MTIME)) { 2605 error = -1; /* may be okay if rdattr_error */ 2606 break; 2607 } 2608 ASSERT(sarg->vap->va_mask & AT_MTIME); 2609 error = nfs4_time_vton(&sarg->vap->va_mtime, &na->time_modify); 2610 break; 2611 case NFS4ATTR_SETIT: 2612 /* 2613 * read-only attr 2614 */ 2615 error = EINVAL; 2616 break; 2617 case NFS4ATTR_VERIT: 2618 ASSERT(sarg->vap->va_mask & AT_MTIME); 2619 error = nfs4_time_ntov(&na->time_modify, &mtime); 2620 if (error) 2621 break; 2622 if (bcmp(&mtime, &sarg->vap->va_mtime, sizeof (mtime))) 2623 error = -1; /* no match */ 2624 break; 2625 case NFS4ATTR_FREEIT: 2626 break; 2627 } 2628 return (error); 2629 } 2630 2631 /* 2632 * XXX - need to add support for setting modify time 2633 */ 2634 /* ARGSUSED */ 2635 static int 2636 rfs4_fattr4_time_modify_set(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2637 union nfs4_attr_u *na) 2638 { 2639 int error = 0; 2640 settime4 *tm; 2641 2642 if (RFS4_MANDATTR_ONLY) 2643 return (ENOTSUP); 2644 2645 switch (cmd) { 2646 case NFS4ATTR_SUPPORTED: 2647 if ((sarg->op == NFS4ATTR_GETIT) || 2648 (sarg->op == NFS4ATTR_VERIT)) 2649 error = EINVAL; 2650 break; /* this attr is supported */ 2651 case NFS4ATTR_GETIT: 2652 case NFS4ATTR_VERIT: 2653 /* 2654 * write only attr 2655 */ 2656 error = EINVAL; 2657 break; 2658 case NFS4ATTR_SETIT: 2659 ASSERT(sarg->vap->va_mask & AT_MTIME); 2660 /* 2661 * Set modify time (by server or by client) 2662 */ 2663 tm = &na->time_modify_set; 2664 if (tm->set_it == SET_TO_CLIENT_TIME4) { 2665 error = nfs4_time_ntov(&tm->time, &sarg->vap->va_mtime); 2666 sarg->flag = ATTR_UTIME; 2667 } else if (tm->set_it == SET_TO_SERVER_TIME4) { 2668 gethrestime(&sarg->vap->va_mtime); 2669 } else { 2670 error = EINVAL; 2671 } 2672 break; 2673 case NFS4ATTR_FREEIT: 2674 break; 2675 } 2676 return (error); 2677 } 2678 2679 2680 static void 2681 rfs4_ntov_init(void) 2682 { 2683 /* index must be same as corresponding FATTR4_* define */ 2684 nfs4_ntov_map[0].sv_getit = rfs4_fattr4_supported_attrs; 2685 nfs4_ntov_map[1].sv_getit = rfs4_fattr4_type; 2686 nfs4_ntov_map[2].sv_getit = rfs4_fattr4_fh_expire_type; 2687 nfs4_ntov_map[3].sv_getit = rfs4_fattr4_change; 2688 nfs4_ntov_map[4].sv_getit = rfs4_fattr4_size; 2689 nfs4_ntov_map[5].sv_getit = rfs4_fattr4_link_support; 2690 nfs4_ntov_map[6].sv_getit = rfs4_fattr4_symlink_support; 2691 nfs4_ntov_map[7].sv_getit = rfs4_fattr4_named_attr; 2692 nfs4_ntov_map[8].sv_getit = rfs4_fattr4_fsid; 2693 nfs4_ntov_map[9].sv_getit = rfs4_fattr4_unique_handles; 2694 nfs4_ntov_map[10].sv_getit = rfs4_fattr4_lease_time; 2695 nfs4_ntov_map[11].sv_getit = rfs4_fattr4_rdattr_error; 2696 nfs4_ntov_map[12].sv_getit = rfs4_fattr4_acl; 2697 nfs4_ntov_map[13].sv_getit = rfs4_fattr4_aclsupport; 2698 nfs4_ntov_map[14].sv_getit = rfs4_fattr4_archive; 2699 nfs4_ntov_map[15].sv_getit = rfs4_fattr4_cansettime; 2700 nfs4_ntov_map[16].sv_getit = rfs4_fattr4_case_insensitive; 2701 nfs4_ntov_map[17].sv_getit = rfs4_fattr4_case_preserving; 2702 nfs4_ntov_map[18].sv_getit = rfs4_fattr4_chown_restricted; 2703 nfs4_ntov_map[19].sv_getit = rfs4_fattr4_filehandle; 2704 nfs4_ntov_map[20].sv_getit = rfs4_fattr4_fileid; 2705 nfs4_ntov_map[21].sv_getit = rfs4_fattr4_files_avail; 2706 nfs4_ntov_map[22].sv_getit = rfs4_fattr4_files_free; 2707 nfs4_ntov_map[23].sv_getit = rfs4_fattr4_files_total; 2708 nfs4_ntov_map[24].sv_getit = rfs4_fattr4_fs_locations; 2709 nfs4_ntov_map[25].sv_getit = rfs4_fattr4_hidden; 2710 nfs4_ntov_map[26].sv_getit = rfs4_fattr4_homogeneous; 2711 nfs4_ntov_map[27].sv_getit = rfs4_fattr4_maxfilesize; 2712 nfs4_ntov_map[28].sv_getit = rfs4_fattr4_maxlink; 2713 nfs4_ntov_map[29].sv_getit = rfs4_fattr4_maxname; 2714 nfs4_ntov_map[30].sv_getit = rfs4_fattr4_maxread; 2715 nfs4_ntov_map[31].sv_getit = rfs4_fattr4_maxwrite; 2716 nfs4_ntov_map[32].sv_getit = rfs4_fattr4_mimetype; 2717 nfs4_ntov_map[33].sv_getit = rfs4_fattr4_mode; 2718 nfs4_ntov_map[34].sv_getit = rfs4_fattr4_no_trunc; 2719 nfs4_ntov_map[35].sv_getit = rfs4_fattr4_numlinks; 2720 nfs4_ntov_map[36].sv_getit = rfs4_fattr4_owner; 2721 nfs4_ntov_map[37].sv_getit = rfs4_fattr4_owner_group; 2722 nfs4_ntov_map[38].sv_getit = rfs4_fattr4_quota_avail_hard; 2723 nfs4_ntov_map[39].sv_getit = rfs4_fattr4_quota_avail_soft; 2724 nfs4_ntov_map[40].sv_getit = rfs4_fattr4_quota_used; 2725 nfs4_ntov_map[41].sv_getit = rfs4_fattr4_rawdev; 2726 nfs4_ntov_map[42].sv_getit = rfs4_fattr4_space_avail; 2727 nfs4_ntov_map[43].sv_getit = rfs4_fattr4_space_free; 2728 nfs4_ntov_map[44].sv_getit = rfs4_fattr4_space_total; 2729 nfs4_ntov_map[45].sv_getit = rfs4_fattr4_space_used; 2730 nfs4_ntov_map[46].sv_getit = rfs4_fattr4_system; 2731 nfs4_ntov_map[47].sv_getit = rfs4_fattr4_time_access; 2732 nfs4_ntov_map[48].sv_getit = rfs4_fattr4_time_access_set; 2733 nfs4_ntov_map[49].sv_getit = rfs4_fattr4_time_backup; 2734 nfs4_ntov_map[50].sv_getit = rfs4_fattr4_time_create; 2735 nfs4_ntov_map[51].sv_getit = rfs4_fattr4_time_delta; 2736 nfs4_ntov_map[52].sv_getit = rfs4_fattr4_time_metadata; 2737 nfs4_ntov_map[53].sv_getit = rfs4_fattr4_time_modify; 2738 nfs4_ntov_map[54].sv_getit = rfs4_fattr4_time_modify_set; 2739 nfs4_ntov_map[55].sv_getit = rfs4_fattr4_mounted_on_fileid; 2740 } 2741