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