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