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