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