1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/systm.h> 27 #include <sys/cmn_err.h> 28 #include <nfs/nfs.h> 29 #include <nfs/export.h> 30 #include <nfs/nfs4.h> 31 #include <sys/ddi.h> 32 #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, FALSE); 1011 if (error != 0) 1012 break; 1013 (void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL); 1014 error = VOP_SETSECATTR(vp, &vs_native, 1015 0, sarg->cs->cr, NULL); 1016 VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL); 1017 vs_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 FALSE); 1022 if (error != 0) 1023 break; 1024 (void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL); 1025 error = VOP_SETSECATTR(vp, &vs_native, 1026 0, sarg->cs->cr, NULL); 1027 VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL); 1028 vs_aent_destroy(&vs_native); 1029 } 1030 break; 1031 1032 case NFS4ATTR_FREEIT: 1033 if (sarg->op == NFS4ATTR_GETIT) { 1034 vs_ace4.vsa_mask = VSA_ACE | VSA_ACECNT; 1035 vs_ace4.vsa_aclcnt = na->acl.fattr4_acl_len; 1036 vs_ace4.vsa_aclentp = na->acl.fattr4_acl_val; 1037 vs_ace4_destroy(&vs_ace4); 1038 } 1039 break; 1040 } 1041 1042 return (error); 1043 } 1044 1045 /* ARGSUSED */ 1046 static int 1047 rfs4_fattr4_aclsupport(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1048 union nfs4_attr_u *na) 1049 { 1050 int error = 0; 1051 1052 if (RFS4_MANDATTR_ONLY) 1053 return (ENOTSUP); 1054 1055 switch (cmd) { 1056 case NFS4ATTR_SUPPORTED: 1057 if (sarg->op == NFS4ATTR_SETIT) 1058 error = EINVAL; 1059 break; /* supported */ 1060 case NFS4ATTR_GETIT: 1061 na->aclsupport = ACL4_SUPPORT_ALLOW_ACL | 1062 ACL4_SUPPORT_DENY_ACL; 1063 break; 1064 case NFS4ATTR_SETIT: 1065 error = EINVAL; 1066 break; 1067 case NFS4ATTR_VERIT: 1068 if (na->aclsupport != (ACL4_SUPPORT_ALLOW_ACL | 1069 ACL4_SUPPORT_DENY_ACL)) 1070 error = -1; /* no match */ 1071 break; 1072 } 1073 1074 return (error); 1075 } 1076 1077 /* ARGSUSED */ 1078 static int 1079 rfs4_fattr4_archive(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1080 union nfs4_attr_u *na) 1081 { 1082 return (ENOTSUP); 1083 } 1084 1085 /* ARGSUSED */ 1086 static int 1087 rfs4_fattr4_cansettime(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1088 union nfs4_attr_u *na) 1089 { 1090 int error = 0; 1091 1092 if (RFS4_MANDATTR_ONLY) 1093 return (ENOTSUP); 1094 1095 switch (cmd) { 1096 case NFS4ATTR_SUPPORTED: 1097 if (sarg->op == NFS4ATTR_SETIT) 1098 error = EINVAL; 1099 break; /* this attr is supported */ 1100 case NFS4ATTR_GETIT: 1101 na->cansettime = TRUE; 1102 break; 1103 case NFS4ATTR_SETIT: 1104 /* 1105 * read-only attr 1106 */ 1107 error = EINVAL; 1108 break; 1109 case NFS4ATTR_VERIT: 1110 if (!na->cansettime) 1111 error = -1; /* no match */ 1112 break; 1113 case NFS4ATTR_FREEIT: 1114 break; 1115 } 1116 return (error); 1117 } 1118 1119 /* 1120 * XXX - need VOP extension to ask file system (e.g. pcfs) if it supports 1121 * case insensitive. 1122 */ 1123 /* ARGSUSED */ 1124 static int 1125 rfs4_fattr4_case_insensitive(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1126 union nfs4_attr_u *na) 1127 { 1128 int error = 0; 1129 1130 if (RFS4_MANDATTR_ONLY) 1131 return (ENOTSUP); 1132 1133 switch (cmd) { 1134 case NFS4ATTR_SUPPORTED: 1135 if (sarg->op == NFS4ATTR_SETIT) 1136 error = EINVAL; 1137 break; /* this attr is supported */ 1138 case NFS4ATTR_GETIT: 1139 na->case_insensitive = FALSE; 1140 break; 1141 case NFS4ATTR_SETIT: 1142 /* 1143 * read-only attr 1144 */ 1145 error = EINVAL; 1146 break; 1147 case NFS4ATTR_VERIT: 1148 if (!na->case_insensitive) 1149 error = -1; /* no match */ 1150 break; 1151 case NFS4ATTR_FREEIT: 1152 break; 1153 } 1154 return (error); 1155 } 1156 1157 /* ARGSUSED */ 1158 static int 1159 rfs4_fattr4_case_preserving(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1160 union nfs4_attr_u *na) 1161 { 1162 int error = 0; 1163 1164 if (RFS4_MANDATTR_ONLY) 1165 return (ENOTSUP); 1166 1167 switch (cmd) { 1168 case NFS4ATTR_SUPPORTED: 1169 if (sarg->op == NFS4ATTR_SETIT) 1170 error = EINVAL; 1171 break; /* this attr is supported */ 1172 case NFS4ATTR_GETIT: 1173 na->case_preserving = TRUE; 1174 break; 1175 case NFS4ATTR_SETIT: 1176 /* 1177 * read-only attr 1178 */ 1179 error = EINVAL; 1180 break; 1181 case NFS4ATTR_VERIT: 1182 if (!na->case_preserving) 1183 error = -1; /* no match */ 1184 break; 1185 case NFS4ATTR_FREEIT: 1186 break; 1187 } 1188 return (error); 1189 } 1190 1191 /* fattr4_chown_restricted should reall be fattr4_chown_allowed */ 1192 /* ARGSUSED */ 1193 static int 1194 rfs4_fattr4_chown_restricted(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1195 union nfs4_attr_u *na) 1196 { 1197 int error = 0; 1198 ulong_t val; 1199 1200 if (RFS4_MANDATTR_ONLY) 1201 return (ENOTSUP); 1202 1203 switch (cmd) { 1204 case NFS4ATTR_SUPPORTED: 1205 if (sarg->op == NFS4ATTR_SETIT) 1206 error = EINVAL; 1207 break; /* this attr is supported */ 1208 case NFS4ATTR_GETIT: 1209 if (sarg->rdattr_error && (sarg->cs->vp == NULL)) { 1210 error = -1; /* may be okay if rdattr_error */ 1211 break; 1212 } 1213 ASSERT(sarg->cs->vp != NULL); 1214 error = VOP_PATHCONF(sarg->cs->vp, 1215 _PC_CHOWN_RESTRICTED, &val, sarg->cs->cr, NULL); 1216 if (error) 1217 break; 1218 1219 na->chown_restricted = (val == 1); 1220 break; 1221 case NFS4ATTR_SETIT: 1222 /* 1223 * read-only attr 1224 */ 1225 error = EINVAL; 1226 break; 1227 case NFS4ATTR_VERIT: 1228 ASSERT(sarg->cs->vp != NULL); 1229 error = VOP_PATHCONF(sarg->cs->vp, 1230 _PC_CHOWN_RESTRICTED, &val, sarg->cs->cr, NULL); 1231 if (error) 1232 break; 1233 if (na->chown_restricted != (val == 1)) 1234 error = -1; /* no match */ 1235 break; 1236 case NFS4ATTR_FREEIT: 1237 break; 1238 } 1239 return (error); 1240 } 1241 1242 /* ARGSUSED */ 1243 static int 1244 rfs4_fattr4_fileid(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1245 union nfs4_attr_u *na) 1246 { 1247 int error = 0; 1248 1249 if (RFS4_MANDATTR_ONLY) 1250 return (ENOTSUP); 1251 1252 switch (cmd) { 1253 case NFS4ATTR_SUPPORTED: 1254 if (sarg->op == NFS4ATTR_SETIT) 1255 error = EINVAL; 1256 break; /* this attr is supported */ 1257 case NFS4ATTR_GETIT: 1258 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_NODEID)) { 1259 error = -1; /* may be okay if rdattr_error */ 1260 break; 1261 } 1262 ASSERT(sarg->vap->va_mask & AT_NODEID); 1263 na->fileid = sarg->vap->va_nodeid; 1264 break; 1265 case NFS4ATTR_SETIT: 1266 /* 1267 * read-only attr 1268 */ 1269 error = EINVAL; 1270 break; 1271 case NFS4ATTR_VERIT: 1272 ASSERT(sarg->vap->va_mask & AT_NODEID); 1273 if (sarg->vap->va_nodeid != na->fileid) 1274 error = -1; /* no match */ 1275 break; 1276 case NFS4ATTR_FREEIT: 1277 break; 1278 } 1279 return (error); 1280 } 1281 1282 /* ARGSUSED */ 1283 static int 1284 rfs4_get_mntdfileid(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg) 1285 { 1286 int error = 0; 1287 vattr_t *vap, va; 1288 vnode_t *stubvp = NULL, *vp; 1289 1290 vp = sarg->cs->vp; 1291 sarg->mntdfid_set = FALSE; 1292 1293 /* VROOT object, must untraverse */ 1294 if (vp->v_flag & VROOT) { 1295 1296 /* extra hold for vp since untraverse might rele */ 1297 VN_HOLD(vp); 1298 stubvp = untraverse(vp); 1299 1300 /* 1301 * If vp/stubvp are same, we must be at system 1302 * root because untraverse returned same vp 1303 * for a VROOT object. sarg->vap was setup 1304 * before we got here, so there's no need to do 1305 * another getattr -- just use the one in sarg. 1306 */ 1307 if (VN_CMP(vp, stubvp)) { 1308 ASSERT(VN_CMP(vp, rootdir)); 1309 vap = sarg->vap; 1310 } else { 1311 va.va_mask = AT_NODEID; 1312 vap = &va; 1313 error = rfs4_vop_getattr(stubvp, vap, 0, sarg->cs->cr); 1314 } 1315 1316 /* 1317 * Done with stub, time to rele. If vp and stubvp 1318 * were the same, then we need to rele either vp or 1319 * stubvp. If they weren't the same, then untraverse() 1320 * already took case of the extra hold on vp, and only 1321 * the stub needs to be rele'd. Both cases are handled 1322 * by unconditionally rele'ing the stub. 1323 */ 1324 VN_RELE(stubvp); 1325 } else 1326 vap = sarg->vap; 1327 1328 /* 1329 * At this point, vap should contain "correct" AT_NODEID -- 1330 * (for V_ROOT case, nodeid of stub, for non-VROOT case, 1331 * nodeid of vp). If error or AT_NODEID not available, then 1332 * make the obligatory (yet mysterious) rdattr_error 1333 * check that is so common in the attr code. 1334 */ 1335 if (!error && (vap->va_mask & AT_NODEID)) { 1336 sarg->mounted_on_fileid = vap->va_nodeid; 1337 sarg->mntdfid_set = TRUE; 1338 } else if (sarg->rdattr_error) 1339 error = -1; 1340 1341 /* 1342 * error describes these cases: 1343 * 0 : success 1344 * -1: failure due to previous attr processing error (rddir only). 1345 * * : new attr failure (if rddir, caller will set rdattr_error) 1346 */ 1347 return (error); 1348 } 1349 1350 /* ARGSUSED */ 1351 static int 1352 rfs4_fattr4_mounted_on_fileid(nfs4_attr_cmd_t cmd, 1353 struct nfs4_svgetit_arg *sarg, union nfs4_attr_u *na) 1354 { 1355 int error = 0; 1356 1357 if (RFS4_MANDATTR_ONLY) 1358 return (ENOTSUP); 1359 1360 switch (cmd) { 1361 case NFS4ATTR_SUPPORTED: 1362 if (sarg->op == NFS4ATTR_SETIT) 1363 error = EINVAL; 1364 break; /* this attr is supported */ 1365 case NFS4ATTR_GETIT: 1366 case NFS4ATTR_VERIT: 1367 if (! sarg->mntdfid_set) 1368 error = rfs4_get_mntdfileid(cmd, sarg); 1369 1370 if (! error && sarg->mntdfid_set) { 1371 if (cmd == NFS4ATTR_GETIT) 1372 na->mounted_on_fileid = sarg->mounted_on_fileid; 1373 else 1374 if (na->mounted_on_fileid != 1375 sarg->mounted_on_fileid) 1376 error = -1; 1377 } 1378 break; 1379 case NFS4ATTR_SETIT: 1380 /* read-only attr */ 1381 error = EINVAL; 1382 break; 1383 case NFS4ATTR_FREEIT: 1384 break; 1385 } 1386 return (error); 1387 } 1388 1389 /* ARGSUSED */ 1390 static int 1391 rfs4_fattr4_files_avail(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1392 union nfs4_attr_u *na) 1393 { 1394 int error = 0; 1395 1396 if (RFS4_MANDATTR_ONLY) 1397 return (ENOTSUP); 1398 1399 switch (cmd) { 1400 case NFS4ATTR_SUPPORTED: 1401 if (sarg->op == NFS4ATTR_SETIT) 1402 error = EINVAL; 1403 break; /* this attr is supported */ 1404 case NFS4ATTR_GETIT: 1405 if (sarg->rdattr_error && (sarg->sbp == NULL)) { 1406 error = -1; /* may be okay if rdattr_error */ 1407 break; 1408 } 1409 ASSERT(sarg->sbp != NULL); 1410 na->files_avail = sarg->sbp->f_favail; 1411 break; 1412 case NFS4ATTR_SETIT: 1413 /* 1414 * read-only attr 1415 */ 1416 error = EINVAL; 1417 break; 1418 case NFS4ATTR_VERIT: 1419 ASSERT(sarg->sbp != NULL); 1420 if (sarg->sbp->f_favail != na->files_avail) 1421 error = -1; /* no match */ 1422 break; 1423 case NFS4ATTR_FREEIT: 1424 break; 1425 } 1426 return (error); 1427 } 1428 1429 /* ARGSUSED */ 1430 static int 1431 rfs4_fattr4_files_free(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1432 union nfs4_attr_u *na) 1433 { 1434 int error = 0; 1435 1436 if (RFS4_MANDATTR_ONLY) 1437 return (ENOTSUP); 1438 1439 switch (cmd) { 1440 case NFS4ATTR_SUPPORTED: 1441 if (sarg->op == NFS4ATTR_SETIT) 1442 error = EINVAL; 1443 break; /* this attr is supported */ 1444 case NFS4ATTR_GETIT: 1445 if (sarg->rdattr_error && (sarg->sbp == NULL)) { 1446 error = -1; /* may be okay if rdattr_error */ 1447 break; 1448 } 1449 ASSERT(sarg->sbp != NULL); 1450 na->files_free = sarg->sbp->f_ffree; 1451 break; 1452 case NFS4ATTR_SETIT: 1453 /* 1454 * read-only attr 1455 */ 1456 error = EINVAL; 1457 break; 1458 case NFS4ATTR_VERIT: 1459 ASSERT(sarg->sbp != NULL); 1460 if (sarg->sbp->f_ffree != na->files_free) 1461 error = -1; /* no match */ 1462 break; 1463 case NFS4ATTR_FREEIT: 1464 break; 1465 } 1466 return (error); 1467 } 1468 1469 /* ARGSUSED */ 1470 static int 1471 rfs4_fattr4_files_total(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1472 union nfs4_attr_u *na) 1473 { 1474 int error = 0; 1475 1476 if (RFS4_MANDATTR_ONLY) 1477 return (ENOTSUP); 1478 1479 switch (cmd) { 1480 case NFS4ATTR_SUPPORTED: 1481 if (sarg->op == NFS4ATTR_SETIT) 1482 error = EINVAL; 1483 break; /* this attr is supported */ 1484 case NFS4ATTR_GETIT: 1485 if (sarg->rdattr_error && (sarg->sbp == NULL)) { 1486 error = -1; /* may be okay if rdattr_error */ 1487 break; 1488 } 1489 ASSERT(sarg->sbp != NULL); 1490 na->files_total = sarg->sbp->f_files; 1491 break; 1492 case NFS4ATTR_SETIT: 1493 /* 1494 * read-only attr 1495 */ 1496 error = EINVAL; 1497 break; 1498 case NFS4ATTR_VERIT: 1499 ASSERT(sarg->sbp != NULL); 1500 if (sarg->sbp->f_files != na->files_total) 1501 error = -1; /* no match */ 1502 break; 1503 case NFS4ATTR_FREEIT: 1504 break; 1505 } 1506 return (error); 1507 } 1508 1509 static void 1510 rfs4_free_pathname4(pathname4 *pn4) 1511 { 1512 int i, len; 1513 utf8string *utf8s; 1514 1515 if (pn4 == NULL || (len = pn4->pathname4_len) == 0 || 1516 (utf8s = pn4->pathname4_val) == NULL) 1517 return; 1518 1519 for (i = 0; i < len; i++, utf8s++) { 1520 if (utf8s->utf8string_val == NULL || 1521 utf8s->utf8string_len == 0) 1522 continue; 1523 1524 kmem_free(utf8s->utf8string_val, utf8s->utf8string_len); 1525 utf8s->utf8string_val = NULL; 1526 } 1527 1528 kmem_free(pn4->pathname4_val, 1529 sizeof (utf8string) * pn4->pathname4_len); 1530 pn4->pathname4_val = 0; 1531 } 1532 1533 static void 1534 rfs4_free_fs_location4(fs_location4 *fsl4) 1535 { 1536 if (fsl4 == NULL) 1537 return; 1538 1539 rfs4_free_pathname4((pathname4 *)&fsl4->server_len); 1540 rfs4_free_pathname4(&fsl4->rootpath); 1541 } 1542 1543 void 1544 rfs4_free_fs_locations4(fs_locations4 *fsls4) 1545 { 1546 int i, len; 1547 fs_location4 *fsl4; 1548 1549 if (fsls4 == NULL) 1550 return; 1551 1552 /* free fs_root */ 1553 rfs4_free_pathname4(&fsls4->fs_root); 1554 1555 if ((len = fsls4->locations_len) == 0 || 1556 (fsl4 = fsls4->locations_val) == NULL) 1557 return; 1558 1559 /* free fs_location4 */ 1560 for (i = 0; i < len; i++) { 1561 rfs4_free_fs_location4(fsl4); 1562 fsl4++; 1563 } 1564 1565 kmem_free(fsls4->locations_val, sizeof (fs_location4) * len); 1566 fsls4->locations_val = NULL; 1567 } 1568 1569 /* ARGSUSED */ 1570 static int 1571 rfs4_fattr4_fs_locations(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1572 union nfs4_attr_u *na) 1573 { 1574 int error = 0; 1575 fs_locations4 *fsl; 1576 1577 if (RFS4_MANDATTR_ONLY) 1578 return (ENOTSUP); 1579 1580 switch (cmd) { 1581 case NFS4ATTR_SUPPORTED: 1582 if (sarg->op == NFS4ATTR_SETIT || sarg->op == NFS4ATTR_VERIT) 1583 error = EINVAL; 1584 break; /* this attr is supported */ 1585 1586 case NFS4ATTR_GETIT: 1587 fsl = fetch_referral(sarg->cs->vp, sarg->cs->cr); 1588 if (fsl == NULL) 1589 error = EINVAL; 1590 else { 1591 na->fs_locations = *fsl; 1592 kmem_free(fsl, sizeof (fs_locations4)); 1593 } 1594 global_svstat_ptr[4][NFS_REFERRALS].value.ui64++; 1595 break; 1596 1597 case NFS4ATTR_FREEIT: 1598 if (sarg->op == NFS4ATTR_SETIT || sarg->op == NFS4ATTR_VERIT) 1599 error = EINVAL; 1600 rfs4_free_fs_locations4(&na->fs_locations); 1601 break; 1602 1603 case NFS4ATTR_SETIT: 1604 case NFS4ATTR_VERIT: 1605 /* 1606 * read-only attr 1607 */ 1608 error = EINVAL; 1609 break; 1610 } 1611 return (error); 1612 } 1613 1614 /* ARGSUSED */ 1615 static int 1616 rfs4_fattr4_hidden(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1617 union nfs4_attr_u *na) 1618 { 1619 return (ENOTSUP); 1620 } 1621 1622 /* ARGSUSED */ 1623 static int 1624 rfs4_fattr4_homogeneous(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1625 union nfs4_attr_u *na) 1626 { 1627 int error = 0; 1628 1629 if (RFS4_MANDATTR_ONLY) 1630 return (ENOTSUP); 1631 1632 switch (cmd) { 1633 case NFS4ATTR_SUPPORTED: 1634 if (sarg->op == NFS4ATTR_SETIT) 1635 error = EINVAL; 1636 break; /* this attr is supported */ 1637 case NFS4ATTR_GETIT: 1638 na->homogeneous = TRUE; /* XXX - need a VOP extension */ 1639 break; 1640 case NFS4ATTR_SETIT: 1641 /* 1642 * read-only attr 1643 */ 1644 error = EINVAL; 1645 break; 1646 case NFS4ATTR_VERIT: 1647 if (!na->homogeneous) 1648 error = -1; /* no match */ 1649 break; 1650 case NFS4ATTR_FREEIT: 1651 break; 1652 } 1653 return (error); 1654 } 1655 1656 /* ARGSUSED */ 1657 static int 1658 rfs4_fattr4_maxfilesize(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1659 union nfs4_attr_u *na) 1660 { 1661 int error = 0; 1662 ulong_t val; 1663 fattr4_maxfilesize maxfilesize; 1664 1665 if (RFS4_MANDATTR_ONLY) 1666 return (ENOTSUP); 1667 1668 switch (cmd) { 1669 case NFS4ATTR_SUPPORTED: 1670 if (sarg->op == NFS4ATTR_SETIT) 1671 error = EINVAL; 1672 break; /* this attr is supported */ 1673 case NFS4ATTR_GETIT: 1674 if (sarg->rdattr_error && (sarg->cs->vp == NULL)) { 1675 error = -1; /* may be okay if rdattr_error */ 1676 break; 1677 } 1678 ASSERT(sarg->cs->vp != NULL); 1679 error = VOP_PATHCONF(sarg->cs->vp, _PC_FILESIZEBITS, &val, 1680 sarg->cs->cr, NULL); 1681 if (error) 1682 break; 1683 1684 /* 1685 * If the underlying file system does not support 1686 * _PC_FILESIZEBITS, return a reasonable default. Note that 1687 * error code on VOP_PATHCONF will be 0, even if the underlying 1688 * file system does not support _PC_FILESIZEBITS. 1689 */ 1690 if (val == (ulong_t)-1) { 1691 na->maxfilesize = MAXOFF32_T; 1692 } else { 1693 if (val >= (sizeof (uint64_t) * 8)) 1694 na->maxfilesize = INT64_MAX; 1695 else 1696 na->maxfilesize = ((1LL << (val - 1)) - 1); 1697 } 1698 break; 1699 case NFS4ATTR_SETIT: 1700 /* 1701 * read-only attr 1702 */ 1703 error = EINVAL; 1704 break; 1705 case NFS4ATTR_VERIT: 1706 ASSERT(sarg->cs->vp != NULL); 1707 error = VOP_PATHCONF(sarg->cs->vp, _PC_FILESIZEBITS, &val, 1708 sarg->cs->cr, NULL); 1709 if (error) 1710 break; 1711 /* 1712 * If the underlying file system does not support 1713 * _PC_FILESIZEBITS, return a reasonable default. Note that 1714 * error code on VOP_PATHCONF will be 0, even if the underlying 1715 * file system does not support _PC_FILESIZEBITS. 1716 */ 1717 if (val == (ulong_t)-1) { 1718 maxfilesize = MAXOFF32_T; 1719 } else { 1720 if (val >= (sizeof (uint64_t) * 8)) 1721 maxfilesize = INT64_MAX; 1722 else 1723 maxfilesize = ((1LL << (val - 1)) - 1); 1724 } 1725 if (na->maxfilesize != maxfilesize) 1726 error = -1; /* no match */ 1727 break; 1728 case NFS4ATTR_FREEIT: 1729 break; 1730 } 1731 return (error); 1732 } 1733 1734 /* ARGSUSED */ 1735 static int 1736 rfs4_fattr4_maxlink(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1737 union nfs4_attr_u *na) 1738 { 1739 int error = 0; 1740 ulong_t val; 1741 1742 if (RFS4_MANDATTR_ONLY) 1743 return (ENOTSUP); 1744 1745 switch (cmd) { 1746 case NFS4ATTR_SUPPORTED: 1747 if (sarg->op == NFS4ATTR_SETIT) 1748 error = EINVAL; 1749 break; /* this attr is supported */ 1750 case NFS4ATTR_GETIT: 1751 if (sarg->rdattr_error && (sarg->cs->vp == NULL)) { 1752 error = -1; /* may be okay if rdattr_error */ 1753 break; 1754 } 1755 ASSERT(sarg->cs->vp != NULL); 1756 error = VOP_PATHCONF(sarg->cs->vp, _PC_LINK_MAX, &val, 1757 sarg->cs->cr, NULL); 1758 if (error == 0) { 1759 na->maxlink = val; 1760 } 1761 break; 1762 case NFS4ATTR_SETIT: 1763 /* 1764 * read-only attr 1765 */ 1766 error = EINVAL; 1767 break; 1768 case NFS4ATTR_VERIT: 1769 ASSERT(sarg->cs->vp != NULL); 1770 error = VOP_PATHCONF(sarg->cs->vp, _PC_LINK_MAX, &val, 1771 sarg->cs->cr, NULL); 1772 if (!error && (na->maxlink != (uint32_t)val)) 1773 error = -1; /* no match */ 1774 break; 1775 case NFS4ATTR_FREEIT: 1776 break; 1777 } 1778 return (error); 1779 } 1780 1781 /* ARGSUSED */ 1782 static int 1783 rfs4_fattr4_maxname(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1784 union nfs4_attr_u *na) 1785 { 1786 int error = 0; 1787 ulong_t val; 1788 1789 if (RFS4_MANDATTR_ONLY) 1790 return (ENOTSUP); 1791 1792 switch (cmd) { 1793 case NFS4ATTR_SUPPORTED: 1794 if (sarg->op == NFS4ATTR_SETIT) 1795 error = EINVAL; 1796 break; /* this attr is supported */ 1797 case NFS4ATTR_GETIT: 1798 if (sarg->rdattr_error && (sarg->cs->vp == NULL)) { 1799 error = -1; /* may be okay if rdattr_error */ 1800 break; 1801 } 1802 ASSERT(sarg->cs->vp != NULL); 1803 error = VOP_PATHCONF(sarg->cs->vp, _PC_NAME_MAX, &val, 1804 sarg->cs->cr, NULL); 1805 if (error == 0) { 1806 na->maxname = val; 1807 } 1808 break; 1809 case NFS4ATTR_SETIT: 1810 /* 1811 * read-only attr 1812 */ 1813 error = EINVAL; 1814 break; 1815 case NFS4ATTR_VERIT: 1816 ASSERT(sarg->cs->vp != NULL); 1817 error = VOP_PATHCONF(sarg->cs->vp, _PC_NAME_MAX, &val, 1818 sarg->cs->cr, NULL); 1819 if (!error && (na->maxname != val)) 1820 error = -1; /* no match */ 1821 break; 1822 case NFS4ATTR_FREEIT: 1823 break; 1824 } 1825 return (error); 1826 } 1827 1828 /* ARGSUSED */ 1829 static int 1830 rfs4_fattr4_maxread(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1831 union nfs4_attr_u *na) 1832 { 1833 int error = 0; 1834 1835 if (RFS4_MANDATTR_ONLY) 1836 return (ENOTSUP); 1837 1838 switch (cmd) { 1839 case NFS4ATTR_SUPPORTED: 1840 if (sarg->op == NFS4ATTR_SETIT) 1841 error = EINVAL; 1842 break; /* this attr is supported */ 1843 case NFS4ATTR_GETIT: 1844 na->maxread = rfs4_tsize(sarg->cs->req); 1845 break; 1846 case NFS4ATTR_SETIT: 1847 /* 1848 * read-only attr 1849 */ 1850 error = EINVAL; 1851 break; 1852 case NFS4ATTR_VERIT: 1853 if (na->maxread != rfs4_tsize(sarg->cs->req)) 1854 error = -1; /* no match */ 1855 break; 1856 case NFS4ATTR_FREEIT: 1857 break; 1858 } 1859 return (error); 1860 } 1861 1862 /* ARGSUSED */ 1863 static int 1864 rfs4_fattr4_maxwrite(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1865 union nfs4_attr_u *na) 1866 { 1867 int error = 0; 1868 1869 if (RFS4_MANDATTR_ONLY) 1870 return (ENOTSUP); 1871 1872 switch (cmd) { 1873 case NFS4ATTR_SUPPORTED: 1874 if (sarg->op == NFS4ATTR_SETIT) 1875 error = EINVAL; 1876 break; /* this attr is supported */ 1877 case NFS4ATTR_GETIT: 1878 na->maxwrite = rfs4_tsize(sarg->cs->req); 1879 break; 1880 case NFS4ATTR_SETIT: 1881 /* 1882 * read-only attr 1883 */ 1884 error = EINVAL; 1885 break; 1886 case NFS4ATTR_VERIT: 1887 if (na->maxwrite != rfs4_tsize(sarg->cs->req)) 1888 error = -1; /* no match */ 1889 break; 1890 case NFS4ATTR_FREEIT: 1891 break; 1892 } 1893 return (error); 1894 } 1895 1896 /* ARGSUSED */ 1897 static int 1898 rfs4_fattr4_mimetype(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1899 union nfs4_attr_u *na) 1900 { 1901 return (ENOTSUP); 1902 } 1903 1904 /* ARGSUSED */ 1905 static int 1906 rfs4_fattr4_mode(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1907 union nfs4_attr_u *na) 1908 { 1909 int error = 0; 1910 1911 if (RFS4_MANDATTR_ONLY) 1912 return (ENOTSUP); 1913 1914 switch (cmd) { 1915 case NFS4ATTR_SUPPORTED: 1916 break; /* this attr is supported */ 1917 case NFS4ATTR_GETIT: 1918 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_MODE)) { 1919 error = -1; /* may be okay if rdattr_error */ 1920 break; 1921 } 1922 ASSERT(sarg->vap->va_mask & AT_MODE); 1923 na->mode = sarg->vap->va_mode; 1924 break; 1925 case NFS4ATTR_SETIT: 1926 ASSERT(sarg->vap->va_mask & AT_MODE); 1927 sarg->vap->va_mode = na->mode; 1928 /* 1929 * If the filesystem is exported with nosuid, then mask off 1930 * the setuid and setgid bits. 1931 */ 1932 if (sarg->cs->vp->v_type == VREG && 1933 (sarg->cs->exi->exi_export.ex_flags & EX_NOSUID)) 1934 sarg->vap->va_mode &= ~(VSUID | VSGID); 1935 break; 1936 case NFS4ATTR_VERIT: 1937 ASSERT(sarg->vap->va_mask & AT_MODE); 1938 if (sarg->vap->va_mode != na->mode) 1939 error = -1; /* no match */ 1940 break; 1941 case NFS4ATTR_FREEIT: 1942 break; 1943 } 1944 return (error); 1945 } 1946 1947 /* ARGSUSED */ 1948 static int 1949 rfs4_fattr4_no_trunc(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1950 union nfs4_attr_u *na) 1951 { 1952 int error = 0; 1953 1954 if (RFS4_MANDATTR_ONLY) 1955 return (ENOTSUP); 1956 1957 switch (cmd) { 1958 case NFS4ATTR_SUPPORTED: 1959 if (sarg->op == NFS4ATTR_SETIT) 1960 error = EINVAL; 1961 break; /* this attr is supported */ 1962 case NFS4ATTR_GETIT: 1963 na->no_trunc = TRUE; 1964 break; 1965 case NFS4ATTR_SETIT: 1966 /* 1967 * read-only attr 1968 */ 1969 error = EINVAL; 1970 break; 1971 case NFS4ATTR_VERIT: 1972 if (!na->no_trunc) 1973 error = -1; /* no match */ 1974 break; 1975 case NFS4ATTR_FREEIT: 1976 break; 1977 } 1978 return (error); 1979 } 1980 1981 /* ARGSUSED */ 1982 static int 1983 rfs4_fattr4_numlinks(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1984 union nfs4_attr_u *na) 1985 { 1986 int error = 0; 1987 1988 if (RFS4_MANDATTR_ONLY) 1989 return (ENOTSUP); 1990 1991 switch (cmd) { 1992 case NFS4ATTR_SUPPORTED: 1993 if (sarg->op == NFS4ATTR_SETIT) 1994 error = EINVAL; 1995 break; /* this attr is supported */ 1996 case NFS4ATTR_GETIT: 1997 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_NLINK)) { 1998 error = -1; /* may be okay if rdattr_error */ 1999 break; 2000 } 2001 ASSERT(sarg->vap->va_mask & AT_NLINK); 2002 na->numlinks = sarg->vap->va_nlink; 2003 break; 2004 case NFS4ATTR_SETIT: 2005 /* 2006 * read-only attr 2007 */ 2008 error = EINVAL; 2009 break; 2010 case NFS4ATTR_VERIT: 2011 ASSERT(sarg->vap->va_mask & AT_NLINK); 2012 if (sarg->vap->va_nlink != na->numlinks) 2013 error = -1; /* no match */ 2014 break; 2015 case NFS4ATTR_FREEIT: 2016 break; 2017 } 2018 return (error); 2019 } 2020 2021 /* ARGSUSED */ 2022 static int 2023 rfs4_fattr4_owner(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2024 union nfs4_attr_u *na) 2025 { 2026 int error = 0; 2027 uid_t uid; 2028 2029 if (RFS4_MANDATTR_ONLY) 2030 return (ENOTSUP); 2031 2032 switch (cmd) { 2033 case NFS4ATTR_SUPPORTED: 2034 break; /* this attr is supported */ 2035 case NFS4ATTR_GETIT: 2036 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_UID)) { 2037 error = -1; /* may be okay if rdattr_error */ 2038 break; 2039 } 2040 ASSERT(sarg->vap->va_mask & AT_UID); 2041 2042 /* 2043 * There are well defined polices for what happens on server- 2044 * side GETATTR when uid to attribute string conversion cannot 2045 * occur. Please refer to nfs4_idmap.c for details. 2046 */ 2047 error = nfs_idmap_uid_str(sarg->vap->va_uid, &na->owner, TRUE); 2048 switch (error) { 2049 case ECONNREFUSED: 2050 error = NFS4ERR_DELAY; 2051 break; 2052 default: 2053 break; 2054 } 2055 break; 2056 2057 case NFS4ATTR_SETIT: 2058 ASSERT(sarg->vap->va_mask & AT_UID); 2059 2060 /* 2061 * There are well defined policies for what happens on server- 2062 * side SETATTR of 'owner' when a "user@domain" mapping cannot 2063 * occur. Please refer to nfs4_idmap.c for details. 2064 * 2065 * Any other errors, such as the mapping not being found by 2066 * nfsmapid(1m), and interrupted clnt_call, etc, will result 2067 * in NFS4ERR_BADOWNER. 2068 * 2069 * XXX need to return consistent errors, perhaps all 2070 * server side attribute routines should return NFS4ERR*. 2071 */ 2072 error = nfs_idmap_str_uid(&na->owner, &sarg->vap->va_uid, TRUE); 2073 switch (error) { 2074 case NFS4_OK: 2075 case ENOTSUP: 2076 /* 2077 * Ignore warning that we are the 2078 * nfsmapid (can't happen on srv) 2079 */ 2080 error = 0; 2081 MSG_PRT_DEBUG = FALSE; 2082 break; 2083 2084 case ECOMM: 2085 case ECONNREFUSED: 2086 if (!MSG_PRT_DEBUG) { 2087 /* 2088 * printed just once per daemon death, 2089 * inform the user and then stay silent 2090 */ 2091 cmn_err(CE_WARN, "!Unable to contact " 2092 "nfsmapid"); 2093 MSG_PRT_DEBUG = TRUE; 2094 } 2095 error = NFS4ERR_DELAY; 2096 break; 2097 2098 case EINVAL: 2099 error = NFS4ERR_INVAL; 2100 break; 2101 2102 default: 2103 error = NFS4ERR_BADOWNER; 2104 break; 2105 } 2106 break; 2107 2108 case NFS4ATTR_VERIT: 2109 ASSERT(sarg->vap->va_mask & AT_UID); 2110 error = nfs_idmap_str_uid(&na->owner, &uid, TRUE); 2111 /* 2112 * Ignore warning that we are the nfsmapid (can't happen on srv) 2113 */ 2114 if (error == ENOTSUP) 2115 error = 0; 2116 if (error) 2117 error = -1; /* no match */ 2118 else if (sarg->vap->va_uid != uid) 2119 error = -1; /* no match */ 2120 break; 2121 case NFS4ATTR_FREEIT: 2122 if (sarg->op == NFS4ATTR_GETIT) { 2123 if (na->owner.utf8string_val) { 2124 UTF8STRING_FREE(na->owner) 2125 bzero(&na->owner, sizeof (na->owner)); 2126 } 2127 } 2128 break; 2129 } 2130 return (error); 2131 } 2132 2133 /* ARGSUSED */ 2134 static int 2135 rfs4_fattr4_owner_group(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2136 union nfs4_attr_u *na) 2137 { 2138 int error = 0; 2139 gid_t gid; 2140 2141 if (RFS4_MANDATTR_ONLY) 2142 return (ENOTSUP); 2143 2144 switch (cmd) { 2145 case NFS4ATTR_SUPPORTED: 2146 break; /* this attr is supported */ 2147 case NFS4ATTR_GETIT: 2148 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_GID)) { 2149 error = -1; /* may be okay if rdattr_error */ 2150 break; 2151 } 2152 ASSERT(sarg->vap->va_mask & AT_GID); 2153 2154 /* 2155 * There are well defined polices for what happens on server- 2156 * side GETATTR when gid to attribute string conversion cannot 2157 * occur. Please refer to nfs4_idmap.c for details. 2158 */ 2159 error = nfs_idmap_gid_str(sarg->vap->va_gid, &na->owner_group, 2160 TRUE); 2161 switch (error) { 2162 case ECONNREFUSED: 2163 error = NFS4ERR_DELAY; 2164 break; 2165 default: 2166 break; 2167 } 2168 break; 2169 2170 case NFS4ATTR_SETIT: 2171 ASSERT(sarg->vap->va_mask & AT_GID); 2172 2173 /* 2174 * There are well defined policies for what happens on server- 2175 * side SETATTR of 'owner_group' when a "group@domain" mapping 2176 * cannot occur. Please refer to nfs4_idmap.c for details. 2177 * 2178 * Any other errors, such as the mapping not being found by 2179 * nfsmapid(1m), and interrupted clnt_call, etc, will result 2180 * in NFS4ERR_BADOWNER. 2181 * 2182 * XXX need to return consistent errors, perhaps all 2183 * server side attribute routines should return NFS4ERR*. 2184 */ 2185 error = nfs_idmap_str_gid(&na->owner_group, &sarg->vap->va_gid, 2186 TRUE); 2187 switch (error) { 2188 case NFS4_OK: 2189 case ENOTSUP: 2190 /* 2191 * Ignore warning that we are the 2192 * nfsmapid (can't happen on srv) 2193 */ 2194 error = 0; 2195 MSG_PRT_DEBUG = FALSE; 2196 break; 2197 2198 case ECOMM: 2199 case ECONNREFUSED: 2200 if (!MSG_PRT_DEBUG) { 2201 /* 2202 * printed just once per daemon death, 2203 * inform the user and then stay silent 2204 */ 2205 cmn_err(CE_WARN, "!Unable to contact " 2206 "nfsmapid"); 2207 MSG_PRT_DEBUG = TRUE; 2208 } 2209 error = NFS4ERR_DELAY; 2210 break; 2211 2212 case EINVAL: 2213 error = NFS4ERR_INVAL; 2214 break; 2215 2216 default: 2217 error = NFS4ERR_BADOWNER; 2218 break; 2219 } 2220 break; 2221 2222 case NFS4ATTR_VERIT: 2223 ASSERT(sarg->vap->va_mask & AT_GID); 2224 error = nfs_idmap_str_gid(&na->owner_group, &gid, TRUE); 2225 /* 2226 * Ignore warning that we are the nfsmapid (can't happen on srv) 2227 */ 2228 if (error == ENOTSUP) 2229 error = 0; 2230 if (error) 2231 error = -1; /* no match */ 2232 else if (sarg->vap->va_gid != gid) 2233 error = -1; /* no match */ 2234 break; 2235 case NFS4ATTR_FREEIT: 2236 if (sarg->op == NFS4ATTR_GETIT) { 2237 if (na->owner_group.utf8string_val) { 2238 UTF8STRING_FREE(na->owner_group) 2239 bzero(&na->owner_group, 2240 sizeof (na->owner_group)); 2241 } 2242 } 2243 break; 2244 } 2245 return (error); 2246 } 2247 2248 /* XXX - quota attributes should be supportable on Solaris 2 */ 2249 /* ARGSUSED */ 2250 static int 2251 rfs4_fattr4_quota_avail_hard(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2252 union nfs4_attr_u *na) 2253 { 2254 return (ENOTSUP); 2255 } 2256 2257 /* ARGSUSED */ 2258 static int 2259 rfs4_fattr4_quota_avail_soft(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2260 union nfs4_attr_u *na) 2261 { 2262 return (ENOTSUP); 2263 } 2264 2265 /* ARGSUSED */ 2266 static int 2267 rfs4_fattr4_quota_used(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2268 union nfs4_attr_u *na) 2269 { 2270 return (ENOTSUP); 2271 } 2272 2273 /* ARGSUSED */ 2274 static int 2275 rfs4_fattr4_rawdev(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2276 union nfs4_attr_u *na) 2277 { 2278 int error = 0; 2279 2280 if (RFS4_MANDATTR_ONLY) 2281 return (ENOTSUP); 2282 2283 switch (cmd) { 2284 case NFS4ATTR_SUPPORTED: 2285 if (sarg->op == NFS4ATTR_SETIT) 2286 error = EINVAL; 2287 break; /* this attr is supported */ 2288 case NFS4ATTR_GETIT: 2289 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_RDEV)) { 2290 error = -1; /* may be okay if rdattr_error */ 2291 break; 2292 } 2293 ASSERT(sarg->vap->va_mask & AT_RDEV); 2294 na->rawdev.specdata1 = (uint32)getmajor(sarg->vap->va_rdev); 2295 na->rawdev.specdata2 = (uint32)getminor(sarg->vap->va_rdev); 2296 break; 2297 case NFS4ATTR_SETIT: 2298 /* 2299 * read-only attr 2300 */ 2301 error = EINVAL; 2302 break; 2303 case NFS4ATTR_VERIT: 2304 ASSERT(sarg->vap->va_mask & AT_RDEV); 2305 if ((na->rawdev.specdata1 != 2306 (uint32)getmajor(sarg->vap->va_rdev)) || 2307 (na->rawdev.specdata2 != 2308 (uint32)getminor(sarg->vap->va_rdev))) 2309 error = -1; /* no match */ 2310 break; 2311 case NFS4ATTR_FREEIT: 2312 break; 2313 } 2314 return (error); 2315 } 2316 2317 /* ARGSUSED */ 2318 static int 2319 rfs4_fattr4_space_avail(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2320 union nfs4_attr_u *na) 2321 { 2322 int error = 0; 2323 2324 if (RFS4_MANDATTR_ONLY) 2325 return (ENOTSUP); 2326 2327 switch (cmd) { 2328 case NFS4ATTR_SUPPORTED: 2329 if (sarg->op == NFS4ATTR_SETIT) 2330 error = EINVAL; 2331 break; /* this attr is supported */ 2332 case NFS4ATTR_GETIT: 2333 if (sarg->rdattr_error && (sarg->sbp == NULL)) { 2334 error = -1; /* may be okay if rdattr_error */ 2335 break; 2336 } 2337 ASSERT(sarg->sbp != NULL); 2338 if (sarg->sbp->f_bavail != (fsblkcnt64_t)-1) { 2339 na->space_avail = 2340 (fattr4_space_avail) sarg->sbp->f_frsize * 2341 (fattr4_space_avail) sarg->sbp->f_bavail; 2342 } else { 2343 na->space_avail = 2344 (fattr4_space_avail) sarg->sbp->f_bavail; 2345 } 2346 break; 2347 case NFS4ATTR_SETIT: 2348 /* 2349 * read-only attr 2350 */ 2351 error = EINVAL; 2352 break; 2353 case NFS4ATTR_VERIT: 2354 ASSERT(sarg->sbp != NULL); 2355 if (sarg->sbp->f_bavail != na->space_avail) 2356 error = -1; /* no match */ 2357 break; 2358 case NFS4ATTR_FREEIT: 2359 break; 2360 } 2361 return (error); 2362 } 2363 2364 /* ARGSUSED */ 2365 static int 2366 rfs4_fattr4_space_free(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2367 union nfs4_attr_u *na) 2368 { 2369 int error = 0; 2370 2371 if (RFS4_MANDATTR_ONLY) 2372 return (ENOTSUP); 2373 2374 switch (cmd) { 2375 case NFS4ATTR_SUPPORTED: 2376 if (sarg->op == NFS4ATTR_SETIT) 2377 error = EINVAL; 2378 break; /* this attr is supported */ 2379 case NFS4ATTR_GETIT: 2380 if (sarg->rdattr_error && (sarg->sbp == NULL)) { 2381 error = -1; /* may be okay if rdattr_error */ 2382 break; 2383 } 2384 ASSERT(sarg->sbp != NULL); 2385 if (sarg->sbp->f_bfree != (fsblkcnt64_t)-1) { 2386 na->space_free = 2387 (fattr4_space_free) sarg->sbp->f_frsize * 2388 (fattr4_space_free) sarg->sbp->f_bfree; 2389 } else { 2390 na->space_free = 2391 (fattr4_space_free) sarg->sbp->f_bfree; 2392 } 2393 break; 2394 case NFS4ATTR_SETIT: 2395 /* 2396 * read-only attr 2397 */ 2398 error = EINVAL; 2399 break; 2400 case NFS4ATTR_VERIT: 2401 ASSERT(sarg->sbp != NULL); 2402 if (sarg->sbp->f_bfree != na->space_free) 2403 error = -1; /* no match */ 2404 break; 2405 case NFS4ATTR_FREEIT: 2406 break; 2407 } 2408 return (error); 2409 } 2410 2411 /* ARGSUSED */ 2412 static int 2413 rfs4_fattr4_space_total(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2414 union nfs4_attr_u *na) 2415 { 2416 int error = 0; 2417 2418 if (RFS4_MANDATTR_ONLY) 2419 return (ENOTSUP); 2420 2421 switch (cmd) { 2422 case NFS4ATTR_SUPPORTED: 2423 if (sarg->op == NFS4ATTR_SETIT) 2424 error = EINVAL; 2425 break; /* this attr is supported */ 2426 case NFS4ATTR_GETIT: 2427 if (sarg->rdattr_error_req && (sarg->sbp == NULL)) { 2428 error = -1; /* may be okay if rdattr_error */ 2429 break; 2430 } 2431 ASSERT(sarg->sbp != NULL); 2432 if (sarg->sbp->f_blocks != (fsblkcnt64_t)-1) { 2433 na->space_total = 2434 (fattr4_space_total) sarg->sbp->f_frsize * 2435 (fattr4_space_total) sarg->sbp->f_blocks; 2436 } else { 2437 na->space_total = 2438 (fattr4_space_total) sarg->sbp->f_blocks; 2439 } 2440 break; 2441 case NFS4ATTR_SETIT: 2442 /* 2443 * read-only attr 2444 */ 2445 error = EINVAL; 2446 break; 2447 case NFS4ATTR_VERIT: 2448 ASSERT(sarg->sbp != NULL); 2449 if (sarg->sbp->f_blocks != na->space_total) 2450 error = -1; /* no match */ 2451 break; 2452 case NFS4ATTR_FREEIT: 2453 break; 2454 } 2455 return (error); 2456 } 2457 2458 /* ARGSUSED */ 2459 static int 2460 rfs4_fattr4_space_used(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2461 union nfs4_attr_u *na) 2462 { 2463 int error = 0; 2464 2465 if (RFS4_MANDATTR_ONLY) 2466 return (ENOTSUP); 2467 2468 switch (cmd) { 2469 case NFS4ATTR_SUPPORTED: 2470 if (sarg->op == NFS4ATTR_SETIT) 2471 error = EINVAL; 2472 break; /* this attr is supported */ 2473 case NFS4ATTR_GETIT: 2474 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_NBLOCKS)) { 2475 error = -1; /* may be okay if rdattr_error */ 2476 break; 2477 } 2478 ASSERT(sarg->vap->va_mask & AT_NBLOCKS); 2479 na->space_used = (fattr4_space_used) DEV_BSIZE * 2480 (fattr4_space_used) sarg->vap->va_nblocks; 2481 break; 2482 case NFS4ATTR_SETIT: 2483 /* 2484 * read-only attr 2485 */ 2486 error = EINVAL; 2487 break; 2488 case NFS4ATTR_VERIT: 2489 ASSERT(sarg->vap->va_mask & AT_NBLOCKS); 2490 if (sarg->vap->va_nblocks != na->space_used) 2491 error = -1; /* no match */ 2492 break; 2493 case NFS4ATTR_FREEIT: 2494 break; 2495 } 2496 return (error); 2497 } 2498 2499 /* ARGSUSED */ 2500 static int 2501 rfs4_fattr4_system(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2502 union nfs4_attr_u *na) 2503 { 2504 return (ENOTSUP); 2505 } 2506 2507 /* ARGSUSED */ 2508 static int 2509 rfs4_fattr4_time_access(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2510 union nfs4_attr_u *na) 2511 { 2512 int error = 0; 2513 timestruc_t atime; 2514 2515 if (RFS4_MANDATTR_ONLY) 2516 return (ENOTSUP); 2517 2518 switch (cmd) { 2519 case NFS4ATTR_SUPPORTED: 2520 if (sarg->op == NFS4ATTR_SETIT) 2521 error = EINVAL; 2522 break; /* this attr is supported */ 2523 case NFS4ATTR_GETIT: 2524 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_ATIME)) { 2525 error = -1; /* may be okay if rdattr_error */ 2526 break; 2527 } 2528 ASSERT(sarg->vap->va_mask & AT_ATIME); 2529 error = nfs4_time_vton(&sarg->vap->va_atime, &na->time_access); 2530 break; 2531 case NFS4ATTR_SETIT: 2532 /* 2533 * read-only attr 2534 */ 2535 error = EINVAL; 2536 break; 2537 case NFS4ATTR_VERIT: 2538 ASSERT(sarg->vap->va_mask & AT_ATIME); 2539 error = nfs4_time_ntov(&na->time_access, &atime); 2540 if (error) 2541 break; 2542 if (bcmp(&atime, &sarg->vap->va_atime, sizeof (atime))) 2543 error = -1; /* no match */ 2544 break; 2545 case NFS4ATTR_FREEIT: 2546 break; 2547 } 2548 return (error); 2549 } 2550 2551 /* 2552 * XXX - need to support the setting of access time 2553 */ 2554 /* ARGSUSED */ 2555 static int 2556 rfs4_fattr4_time_access_set(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2557 union nfs4_attr_u *na) 2558 { 2559 int error = 0; 2560 settime4 *ta; 2561 2562 if (RFS4_MANDATTR_ONLY) 2563 return (ENOTSUP); 2564 2565 switch (cmd) { 2566 case NFS4ATTR_SUPPORTED: 2567 if ((sarg->op == NFS4ATTR_GETIT) || 2568 (sarg->op == NFS4ATTR_VERIT)) 2569 error = EINVAL; 2570 break; /* this attr is supported */ 2571 case NFS4ATTR_GETIT: 2572 case NFS4ATTR_VERIT: 2573 /* 2574 * write only attr 2575 */ 2576 error = EINVAL; 2577 break; 2578 case NFS4ATTR_SETIT: 2579 ASSERT(sarg->vap->va_mask & AT_ATIME); 2580 /* 2581 * Set access time (by server or by client) 2582 */ 2583 ta = &na->time_access_set; 2584 if (ta->set_it == SET_TO_CLIENT_TIME4) { 2585 error = nfs4_time_ntov(&ta->time, &sarg->vap->va_atime); 2586 } else if (ta->set_it == SET_TO_SERVER_TIME4) { 2587 gethrestime(&sarg->vap->va_atime); 2588 } else { 2589 error = EINVAL; 2590 } 2591 break; 2592 case NFS4ATTR_FREEIT: 2593 break; 2594 } 2595 return (error); 2596 } 2597 2598 /* ARGSUSED */ 2599 static int 2600 rfs4_fattr4_time_backup(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2601 union nfs4_attr_u *na) 2602 { 2603 return (ENOTSUP); 2604 } 2605 2606 /* ARGSUSED */ 2607 static int 2608 rfs4_fattr4_time_create(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2609 union nfs4_attr_u *na) 2610 { 2611 return (ENOTSUP); 2612 } 2613 2614 /* ARGSUSED */ 2615 static int 2616 rfs4_fattr4_time_delta(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2617 union nfs4_attr_u *na) 2618 { 2619 int error = 0; 2620 2621 if (RFS4_MANDATTR_ONLY) 2622 return (ENOTSUP); 2623 2624 switch (cmd) { 2625 case NFS4ATTR_SUPPORTED: 2626 if (sarg->op == NFS4ATTR_SETIT) 2627 error = EINVAL; 2628 break; /* this attr is supported */ 2629 case NFS4ATTR_GETIT: 2630 na->time_delta.seconds = 0; 2631 na->time_delta.nseconds = 1000; 2632 break; 2633 case NFS4ATTR_SETIT: 2634 /* 2635 * write only attr 2636 */ 2637 error = EINVAL; 2638 break; 2639 case NFS4ATTR_VERIT: 2640 if ((na->time_delta.seconds != 0) || 2641 (na->time_delta.nseconds != 1000)) 2642 error = -1; /* no match */ 2643 break; 2644 case NFS4ATTR_FREEIT: 2645 break; 2646 } 2647 return (error); 2648 } 2649 2650 /* ARGSUSED */ 2651 static int 2652 rfs4_fattr4_time_metadata(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2653 union nfs4_attr_u *na) 2654 { 2655 int error = 0; 2656 timestruc_t ctime; 2657 2658 if (RFS4_MANDATTR_ONLY) 2659 return (ENOTSUP); 2660 2661 switch (cmd) { 2662 case NFS4ATTR_SUPPORTED: 2663 if (sarg->op == NFS4ATTR_SETIT) 2664 error = EINVAL; 2665 break; /* this attr is supported */ 2666 case NFS4ATTR_GETIT: 2667 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_CTIME)) { 2668 error = -1; /* may be okay if rdattr_error */ 2669 break; 2670 } 2671 ASSERT(sarg->vap->va_mask & AT_CTIME); 2672 error = nfs4_time_vton(&sarg->vap->va_ctime, 2673 &na->time_metadata); 2674 break; 2675 case NFS4ATTR_SETIT: 2676 /* 2677 * read-only attr 2678 */ 2679 error = EINVAL; 2680 break; 2681 case NFS4ATTR_VERIT: 2682 ASSERT(sarg->vap->va_mask & AT_CTIME); 2683 error = nfs4_time_ntov(&na->time_metadata, &ctime); 2684 if (error) 2685 break; 2686 if (bcmp(&ctime, &sarg->vap->va_ctime, sizeof (ctime))) 2687 error = -1; /* no match */ 2688 break; 2689 case NFS4ATTR_FREEIT: 2690 break; 2691 } 2692 return (error); 2693 } 2694 2695 /* ARGSUSED */ 2696 static int 2697 rfs4_fattr4_time_modify(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2698 union nfs4_attr_u *na) 2699 { 2700 int error = 0; 2701 timestruc_t mtime; 2702 2703 if (RFS4_MANDATTR_ONLY) 2704 return (ENOTSUP); 2705 2706 switch (cmd) { 2707 case NFS4ATTR_SUPPORTED: 2708 if (sarg->op == NFS4ATTR_SETIT) 2709 error = EINVAL; 2710 break; /* this attr is supported */ 2711 case NFS4ATTR_GETIT: 2712 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_MTIME)) { 2713 error = -1; /* may be okay if rdattr_error */ 2714 break; 2715 } 2716 ASSERT(sarg->vap->va_mask & AT_MTIME); 2717 error = nfs4_time_vton(&sarg->vap->va_mtime, &na->time_modify); 2718 break; 2719 case NFS4ATTR_SETIT: 2720 /* 2721 * read-only attr 2722 */ 2723 error = EINVAL; 2724 break; 2725 case NFS4ATTR_VERIT: 2726 ASSERT(sarg->vap->va_mask & AT_MTIME); 2727 error = nfs4_time_ntov(&na->time_modify, &mtime); 2728 if (error) 2729 break; 2730 if (bcmp(&mtime, &sarg->vap->va_mtime, sizeof (mtime))) 2731 error = -1; /* no match */ 2732 break; 2733 case NFS4ATTR_FREEIT: 2734 break; 2735 } 2736 return (error); 2737 } 2738 2739 /* 2740 * XXX - need to add support for setting modify time 2741 */ 2742 /* ARGSUSED */ 2743 static int 2744 rfs4_fattr4_time_modify_set(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2745 union nfs4_attr_u *na) 2746 { 2747 int error = 0; 2748 settime4 *tm; 2749 2750 if (RFS4_MANDATTR_ONLY) 2751 return (ENOTSUP); 2752 2753 switch (cmd) { 2754 case NFS4ATTR_SUPPORTED: 2755 if ((sarg->op == NFS4ATTR_GETIT) || 2756 (sarg->op == NFS4ATTR_VERIT)) 2757 error = EINVAL; 2758 break; /* this attr is supported */ 2759 case NFS4ATTR_GETIT: 2760 case NFS4ATTR_VERIT: 2761 /* 2762 * write only attr 2763 */ 2764 error = EINVAL; 2765 break; 2766 case NFS4ATTR_SETIT: 2767 ASSERT(sarg->vap->va_mask & AT_MTIME); 2768 /* 2769 * Set modify time (by server or by client) 2770 */ 2771 tm = &na->time_modify_set; 2772 if (tm->set_it == SET_TO_CLIENT_TIME4) { 2773 error = nfs4_time_ntov(&tm->time, &sarg->vap->va_mtime); 2774 sarg->flag = ATTR_UTIME; 2775 } else if (tm->set_it == SET_TO_SERVER_TIME4) { 2776 gethrestime(&sarg->vap->va_mtime); 2777 } else { 2778 error = EINVAL; 2779 } 2780 break; 2781 case NFS4ATTR_FREEIT: 2782 break; 2783 } 2784 return (error); 2785 } 2786 2787 2788 static void 2789 rfs4_ntov_init(void) 2790 { 2791 /* index must be same as corresponding FATTR4_* define */ 2792 nfs4_ntov_map[0].sv_getit = rfs4_fattr4_supported_attrs; 2793 nfs4_ntov_map[1].sv_getit = rfs4_fattr4_type; 2794 nfs4_ntov_map[2].sv_getit = rfs4_fattr4_fh_expire_type; 2795 nfs4_ntov_map[3].sv_getit = rfs4_fattr4_change; 2796 nfs4_ntov_map[4].sv_getit = rfs4_fattr4_size; 2797 nfs4_ntov_map[5].sv_getit = rfs4_fattr4_link_support; 2798 nfs4_ntov_map[6].sv_getit = rfs4_fattr4_symlink_support; 2799 nfs4_ntov_map[7].sv_getit = rfs4_fattr4_named_attr; 2800 nfs4_ntov_map[8].sv_getit = rfs4_fattr4_fsid; 2801 nfs4_ntov_map[9].sv_getit = rfs4_fattr4_unique_handles; 2802 nfs4_ntov_map[10].sv_getit = rfs4_fattr4_lease_time; 2803 nfs4_ntov_map[11].sv_getit = rfs4_fattr4_rdattr_error; 2804 nfs4_ntov_map[12].sv_getit = rfs4_fattr4_acl; 2805 nfs4_ntov_map[13].sv_getit = rfs4_fattr4_aclsupport; 2806 nfs4_ntov_map[14].sv_getit = rfs4_fattr4_archive; 2807 nfs4_ntov_map[15].sv_getit = rfs4_fattr4_cansettime; 2808 nfs4_ntov_map[16].sv_getit = rfs4_fattr4_case_insensitive; 2809 nfs4_ntov_map[17].sv_getit = rfs4_fattr4_case_preserving; 2810 nfs4_ntov_map[18].sv_getit = rfs4_fattr4_chown_restricted; 2811 nfs4_ntov_map[19].sv_getit = rfs4_fattr4_filehandle; 2812 nfs4_ntov_map[20].sv_getit = rfs4_fattr4_fileid; 2813 nfs4_ntov_map[21].sv_getit = rfs4_fattr4_files_avail; 2814 nfs4_ntov_map[22].sv_getit = rfs4_fattr4_files_free; 2815 nfs4_ntov_map[23].sv_getit = rfs4_fattr4_files_total; 2816 nfs4_ntov_map[24].sv_getit = rfs4_fattr4_fs_locations; 2817 nfs4_ntov_map[25].sv_getit = rfs4_fattr4_hidden; 2818 nfs4_ntov_map[26].sv_getit = rfs4_fattr4_homogeneous; 2819 nfs4_ntov_map[27].sv_getit = rfs4_fattr4_maxfilesize; 2820 nfs4_ntov_map[28].sv_getit = rfs4_fattr4_maxlink; 2821 nfs4_ntov_map[29].sv_getit = rfs4_fattr4_maxname; 2822 nfs4_ntov_map[30].sv_getit = rfs4_fattr4_maxread; 2823 nfs4_ntov_map[31].sv_getit = rfs4_fattr4_maxwrite; 2824 nfs4_ntov_map[32].sv_getit = rfs4_fattr4_mimetype; 2825 nfs4_ntov_map[33].sv_getit = rfs4_fattr4_mode; 2826 nfs4_ntov_map[34].sv_getit = rfs4_fattr4_no_trunc; 2827 nfs4_ntov_map[35].sv_getit = rfs4_fattr4_numlinks; 2828 nfs4_ntov_map[36].sv_getit = rfs4_fattr4_owner; 2829 nfs4_ntov_map[37].sv_getit = rfs4_fattr4_owner_group; 2830 nfs4_ntov_map[38].sv_getit = rfs4_fattr4_quota_avail_hard; 2831 nfs4_ntov_map[39].sv_getit = rfs4_fattr4_quota_avail_soft; 2832 nfs4_ntov_map[40].sv_getit = rfs4_fattr4_quota_used; 2833 nfs4_ntov_map[41].sv_getit = rfs4_fattr4_rawdev; 2834 nfs4_ntov_map[42].sv_getit = rfs4_fattr4_space_avail; 2835 nfs4_ntov_map[43].sv_getit = rfs4_fattr4_space_free; 2836 nfs4_ntov_map[44].sv_getit = rfs4_fattr4_space_total; 2837 nfs4_ntov_map[45].sv_getit = rfs4_fattr4_space_used; 2838 nfs4_ntov_map[46].sv_getit = rfs4_fattr4_system; 2839 nfs4_ntov_map[47].sv_getit = rfs4_fattr4_time_access; 2840 nfs4_ntov_map[48].sv_getit = rfs4_fattr4_time_access_set; 2841 nfs4_ntov_map[49].sv_getit = rfs4_fattr4_time_backup; 2842 nfs4_ntov_map[50].sv_getit = rfs4_fattr4_time_create; 2843 nfs4_ntov_map[51].sv_getit = rfs4_fattr4_time_delta; 2844 nfs4_ntov_map[52].sv_getit = rfs4_fattr4_time_metadata; 2845 nfs4_ntov_map[53].sv_getit = rfs4_fattr4_time_modify; 2846 nfs4_ntov_map[54].sv_getit = rfs4_fattr4_time_modify_set; 2847 nfs4_ntov_map[55].sv_getit = rfs4_fattr4_mounted_on_fileid; 2848 } 2849