17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5d394a754Sxs  * Common Development and Distribution License (the "License").
6d394a754Sxs  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
210dfe541eSEvan Layton 
227c478bd9Sstevel@tonic-gate /*
23e913d9ecSLisa Week  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
260dfe541eSEvan Layton 
27e073d6a4SDaniil Lunev /*
280dfe541eSEvan Layton  * Copyright 2018 Nexenta Systems, Inc.
29*f44e1126SVitaliy Gusev  * Copyright 2020 RackTop Systems, Inc.
30e073d6a4SDaniil Lunev  */
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include <sys/systm.h>
337c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
347c478bd9Sstevel@tonic-gate #include <nfs/nfs.h>
357c478bd9Sstevel@tonic-gate #include <nfs/export.h>
367c478bd9Sstevel@tonic-gate #include <nfs/nfs4.h>
377c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
382f172c55SRobert Thurlow #include <sys/door.h>
392f172c55SRobert Thurlow #include <sys/sdt.h>
402f172c55SRobert Thurlow #include <nfs/nfssys.h>
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate void	rfs4_init_compound_state(struct compound_state *);
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate bitmap4 rfs4_supported_attrs;
457c478bd9Sstevel@tonic-gate int MSG_PRT_DEBUG = FALSE;
467c478bd9Sstevel@tonic-gate 
47da6c28aaSamw /* If building with DEBUG enabled, enable mandattr tunable by default */
487c478bd9Sstevel@tonic-gate #ifdef DEBUG
497c478bd9Sstevel@tonic-gate #ifndef RFS4_SUPPORT_MANDATTR_ONLY
507c478bd9Sstevel@tonic-gate #define	RFS4_SUPPORT_MANDATTR_ONLY
517c478bd9Sstevel@tonic-gate #endif
527c478bd9Sstevel@tonic-gate #endif
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate /*
557c478bd9Sstevel@tonic-gate  * If building with mandattr only code, disable it by default.
567c478bd9Sstevel@tonic-gate  * To enable, set rfs4_mandattr_only in /etc/system and reboot.
577c478bd9Sstevel@tonic-gate  * When building without mandattr ifdef, the compiler should
587c478bd9Sstevel@tonic-gate  * optimize away the the comparisons because RFS4_MANDATTR_ONLY
597c478bd9Sstevel@tonic-gate  * is defined to be 0.
607c478bd9Sstevel@tonic-gate  */
617c478bd9Sstevel@tonic-gate #ifdef RFS4_SUPPORT_MANDATTR_ONLY
627c478bd9Sstevel@tonic-gate #define	NFS4_LAST_MANDATTR FATTR4_RDATTR_ERROR
637c478bd9Sstevel@tonic-gate #define	RFS4_MANDATTR_ONLY rfs4_mandattr_only
647c478bd9Sstevel@tonic-gate int rfs4_mandattr_only = 0;
657c478bd9Sstevel@tonic-gate #else
667c478bd9Sstevel@tonic-gate #define	RFS4_MANDATTR_ONLY 0
677c478bd9Sstevel@tonic-gate #endif
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate static void rfs4_ntov_init(void);
717c478bd9Sstevel@tonic-gate static int rfs4_fattr4_supported_attrs();
727c478bd9Sstevel@tonic-gate static int rfs4_fattr4_type();
737c478bd9Sstevel@tonic-gate static int rfs4_fattr4_fh_expire_type();
747c478bd9Sstevel@tonic-gate static int rfs4_fattr4_change();
757c478bd9Sstevel@tonic-gate static int rfs4_fattr4_size();
767c478bd9Sstevel@tonic-gate static int rfs4_fattr4_link_support();
777c478bd9Sstevel@tonic-gate static int rfs4_fattr4_symlink_support();
787c478bd9Sstevel@tonic-gate static int rfs4_fattr4_named_attr();
797c478bd9Sstevel@tonic-gate static int rfs4_fattr4_fsid();
807c478bd9Sstevel@tonic-gate static int rfs4_fattr4_unique_handles();
817c478bd9Sstevel@tonic-gate static int rfs4_fattr4_lease_time();
827c478bd9Sstevel@tonic-gate static int rfs4_fattr4_rdattr_error();
837c478bd9Sstevel@tonic-gate static int rfs4_fattr4_acl();
847c478bd9Sstevel@tonic-gate static int rfs4_fattr4_aclsupport();
857c478bd9Sstevel@tonic-gate static int rfs4_fattr4_archive();
867c478bd9Sstevel@tonic-gate static int rfs4_fattr4_cansettime();
877c478bd9Sstevel@tonic-gate static int rfs4_fattr4_case_insensitive();
887c478bd9Sstevel@tonic-gate static int rfs4_fattr4_case_preserving();
897c478bd9Sstevel@tonic-gate static int rfs4_fattr4_chown_restricted();
907c478bd9Sstevel@tonic-gate static int rfs4_fattr4_filehandle();
917c478bd9Sstevel@tonic-gate static int rfs4_fattr4_fileid();
927c478bd9Sstevel@tonic-gate static int rfs4_fattr4_files_avail();
937c478bd9Sstevel@tonic-gate static int rfs4_fattr4_files_free();
947c478bd9Sstevel@tonic-gate static int rfs4_fattr4_files_total();
957c478bd9Sstevel@tonic-gate static int rfs4_fattr4_fs_locations();
967c478bd9Sstevel@tonic-gate static int rfs4_fattr4_hidden();
977c478bd9Sstevel@tonic-gate static int rfs4_fattr4_homogeneous();
987c478bd9Sstevel@tonic-gate static int rfs4_fattr4_maxfilesize();
997c478bd9Sstevel@tonic-gate static int rfs4_fattr4_maxlink();
1007c478bd9Sstevel@tonic-gate static int rfs4_fattr4_maxname();
1017c478bd9Sstevel@tonic-gate static int rfs4_fattr4_maxread();
1027c478bd9Sstevel@tonic-gate static int rfs4_fattr4_maxwrite();
1037c478bd9Sstevel@tonic-gate static int rfs4_fattr4_mimetype();
1047c478bd9Sstevel@tonic-gate static int rfs4_fattr4_mode();
1057c478bd9Sstevel@tonic-gate static int rfs4_fattr4_no_trunc();
1067c478bd9Sstevel@tonic-gate static int rfs4_fattr4_numlinks();
1077c478bd9Sstevel@tonic-gate static int rfs4_fattr4_owner();
1087c478bd9Sstevel@tonic-gate static int rfs4_fattr4_owner_group();
1097c478bd9Sstevel@tonic-gate static int rfs4_fattr4_quota_avail_hard();
1107c478bd9Sstevel@tonic-gate static int rfs4_fattr4_quota_avail_soft();
1117c478bd9Sstevel@tonic-gate static int rfs4_fattr4_quota_used();
1127c478bd9Sstevel@tonic-gate static int rfs4_fattr4_rawdev();
1137c478bd9Sstevel@tonic-gate static int rfs4_fattr4_space_avail();
1147c478bd9Sstevel@tonic-gate static int rfs4_fattr4_space_free();
1157c478bd9Sstevel@tonic-gate static int rfs4_fattr4_space_total();
1167c478bd9Sstevel@tonic-gate static int rfs4_fattr4_space_used();
1177c478bd9Sstevel@tonic-gate static int rfs4_fattr4_system();
1187c478bd9Sstevel@tonic-gate static int rfs4_fattr4_time_access();
1197c478bd9Sstevel@tonic-gate static int rfs4_fattr4_time_access_set();
1207c478bd9Sstevel@tonic-gate static int rfs4_fattr4_time_backup();
1217c478bd9Sstevel@tonic-gate static int rfs4_fattr4_time_create();
1227c478bd9Sstevel@tonic-gate static int rfs4_fattr4_time_delta();
1237c478bd9Sstevel@tonic-gate static int rfs4_fattr4_time_metadata();
1247c478bd9Sstevel@tonic-gate static int rfs4_fattr4_time_modify();
1257c478bd9Sstevel@tonic-gate static int rfs4_fattr4_time_modify_set();
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate /*
1287c478bd9Sstevel@tonic-gate  * Initialize the supported attributes
1297c478bd9Sstevel@tonic-gate  */
130*f44e1126SVitaliy Gusev bitmap4 supported_attrs[3];
131*f44e1126SVitaliy Gusev 
132*f44e1126SVitaliy Gusev static void
init_supported_attrs(void)133*f44e1126SVitaliy Gusev init_supported_attrs(void)
134*f44e1126SVitaliy Gusev {
135*f44e1126SVitaliy Gusev 	supported_attrs[0] = supported_attrs[1] = supported_attrs[2] =
136*f44e1126SVitaliy Gusev 	    rfs4_supported_attrs;
137*f44e1126SVitaliy Gusev 
138*f44e1126SVitaliy Gusev 	/* restrict to nfsv4.0 */
139*f44e1126SVitaliy Gusev 	supported_attrs[0] &= ~(FATTR4_SUPPATTR_EXCLCREAT_MASK_LOCAL |
140*f44e1126SVitaliy Gusev 	    FATTR4_SEC_LABEL_MASK_LOCAL);
141*f44e1126SVitaliy Gusev 
142*f44e1126SVitaliy Gusev 	/* restrict to nfsv4.1 */
143*f44e1126SVitaliy Gusev 	supported_attrs[1] &= ~FATTR4_SEC_LABEL_MASK_LOCAL;
144*f44e1126SVitaliy Gusev }
145*f44e1126SVitaliy Gusev 
1467c478bd9Sstevel@tonic-gate void
rfs4_attr_init(void)147*f44e1126SVitaliy Gusev rfs4_attr_init(void)
1487c478bd9Sstevel@tonic-gate {
1497c478bd9Sstevel@tonic-gate 	int i;
1507c478bd9Sstevel@tonic-gate 	struct nfs4_svgetit_arg sarg;
1517c478bd9Sstevel@tonic-gate 	struct compound_state cs;
1527c478bd9Sstevel@tonic-gate 	struct statvfs64 sb;
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 	rfs4_init_compound_state(&cs);
1550dfe541eSEvan Layton 	/*
1560dfe541eSEvan Layton 	 * This is global state checking, called once. We might be in
1570dfe541eSEvan Layton 	 * non-global-zone context here (say a modload happens from a zone
1580dfe541eSEvan Layton 	 * process) so in this case, we want the global-zone root vnode.
1590dfe541eSEvan Layton 	 */
1607c478bd9Sstevel@tonic-gate 	cs.vp = rootvp;
1617c478bd9Sstevel@tonic-gate 	cs.fh.nfs_fh4_val = NULL;
1627c478bd9Sstevel@tonic-gate 	cs.cr = kcred;
163*f44e1126SVitaliy Gusev 	cs.minorversion = NFS_PROT_V4_MINORVERSION(NFS_VERS_4_2);
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 	/*
1667c478bd9Sstevel@tonic-gate 	 * Get all the supported attributes
1677c478bd9Sstevel@tonic-gate 	 */
1687c478bd9Sstevel@tonic-gate 	sarg.op = NFS4ATTR_SUPPORTED;
1697c478bd9Sstevel@tonic-gate 	sarg.cs = &cs;
1707c478bd9Sstevel@tonic-gate 	sarg.vap->va_mask = AT_ALL;
1717c478bd9Sstevel@tonic-gate 	sarg.sbp = &sb;
1727c478bd9Sstevel@tonic-gate 	sarg.flag = 0;
1737c478bd9Sstevel@tonic-gate 	sarg.rdattr_error = NFS4_OK;
1747c478bd9Sstevel@tonic-gate 	sarg.rdattr_error_req = FALSE;
1752f172c55SRobert Thurlow 	sarg.is_referral = B_FALSE;
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate 	rfs4_ntov_init();
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate 	rfs4_supported_attrs = 0;
1807c478bd9Sstevel@tonic-gate 	for (i = 0; i < NFS4_MAXNUM_ATTRS; i++) {
1817c478bd9Sstevel@tonic-gate #ifdef RFS4_SUPPORT_MANDATTR_ONLY
1827c478bd9Sstevel@tonic-gate 		if (rfs4_mandattr_only == TRUE && i > NFS4_LAST_MANDATTR)
1837c478bd9Sstevel@tonic-gate 			continue;
1847c478bd9Sstevel@tonic-gate #endif
1857c478bd9Sstevel@tonic-gate 		if ((*nfs4_ntov_map[i].sv_getit)(NFS4ATTR_SUPPORTED,
1867c478bd9Sstevel@tonic-gate 		    &sarg, NULL) == 0) {
1877c478bd9Sstevel@tonic-gate 			rfs4_supported_attrs |= nfs4_ntov_map[i].fbit;
1887c478bd9Sstevel@tonic-gate 		}
1897c478bd9Sstevel@tonic-gate 	}
190*f44e1126SVitaliy Gusev 
191*f44e1126SVitaliy Gusev 	init_supported_attrs();
1927c478bd9Sstevel@tonic-gate }
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate /*
1957c478bd9Sstevel@tonic-gate  * The following rfs4_fattr4_* functions convert between the fattr4
1967c478bd9Sstevel@tonic-gate  * arguments/attributes and the system (e.g. vattr) values. The following
1977c478bd9Sstevel@tonic-gate  * commands are currently in use:
1987c478bd9Sstevel@tonic-gate  *
1997c478bd9Sstevel@tonic-gate  * NFS4ATTR_SUPPORTED: checks if the attribute in question is supported:
2007c478bd9Sstevel@tonic-gate  *	sarg.op = SUPPORTED - all supported attrs
2017c478bd9Sstevel@tonic-gate  *	sarg.op = GETIT - only supported readable attrs
2027c478bd9Sstevel@tonic-gate  *	sarg.op = SETIT - only supported writable attrs
2037c478bd9Sstevel@tonic-gate  *
2047c478bd9Sstevel@tonic-gate  * NFS4ATTR_GETIT: getattr type conversion - convert system values
2057c478bd9Sstevel@tonic-gate  * (e.g. vattr struct) to fattr4 type values to be returned to the
2067c478bd9Sstevel@tonic-gate  * user - usually in response to nfsv4 getattr request.
2077c478bd9Sstevel@tonic-gate  *
2087c478bd9Sstevel@tonic-gate  * NFS4ATTR_SETIT: convert fattr4 type values to system values to use by
2097c478bd9Sstevel@tonic-gate  * setattr. Allows only read/write and write attributes,
2107c478bd9Sstevel@tonic-gate  * even if not supported by the filesystem. Note that ufs only allows setattr
2117c478bd9Sstevel@tonic-gate  * of owner/group, mode, size, atime/mtime.
2127c478bd9Sstevel@tonic-gate  *
2137c478bd9Sstevel@tonic-gate  * NFS4ATTR_VERIT: convert fattr4 type values to system values to use by
2147c478bd9Sstevel@tonic-gate  * verify/nverify. Implemented to allow
2157c478bd9Sstevel@tonic-gate  * almost everything that can be returned by getattr into known structs
2167c478bd9Sstevel@tonic-gate  * (like vfsstat64 or vattr_t), that is, both read only and read/write attrs.
2177c478bd9Sstevel@tonic-gate  * The function will return -1 if it found that the arguments don't match.
2187c478bd9Sstevel@tonic-gate  * This applies to system-wide values that don't require a VOP_GETATTR
2197c478bd9Sstevel@tonic-gate  * or other further checks to verify. It will return no error if they
2207c478bd9Sstevel@tonic-gate  * either match or were retrieved successfully for later checking.
2217c478bd9Sstevel@tonic-gate  *
2227c478bd9Sstevel@tonic-gate  * NFS4ATTR_FREEIT: free up any space allocated by either of the above.
2237c478bd9Sstevel@tonic-gate  * The sargp->op should be either NFS4ATTR_GETIT or NFS4ATTR_SETIT
2247c478bd9Sstevel@tonic-gate  * to indicate which op was used to allocate the space.
2257c478bd9Sstevel@tonic-gate  *
2267c478bd9Sstevel@tonic-gate  * XXX Note: these functions are currently used by the server only. A
2277c478bd9Sstevel@tonic-gate  * XXX different method of conversion is used on the client side.
2287c478bd9Sstevel@tonic-gate  * XXX Eventually combining the two (possibly by adding NFS4ATTR_CLNT_GETIT
2297c478bd9Sstevel@tonic-gate  * XXX and SETIT) may be a cleaner approach.
2307c478bd9Sstevel@tonic-gate  */
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate /*
2337c478bd9Sstevel@tonic-gate  * Mandatory attributes
2347c478bd9Sstevel@tonic-gate  */
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate /* ARGSUSED */
2377c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_supported_attrs(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)2387c478bd9Sstevel@tonic-gate rfs4_fattr4_supported_attrs(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2394a695956SMarcel Telka     union nfs4_attr_u *na)
2407c478bd9Sstevel@tonic-gate {
2417c478bd9Sstevel@tonic-gate 	int	error = 0;
242*f44e1126SVitaliy Gusev 	bitmap4 supported = supported_attrs[sarg->cs->minorversion];
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 	switch (cmd) {
2457c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
2467c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
2477c478bd9Sstevel@tonic-gate 			error = EINVAL;
2487c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
2497c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
250*f44e1126SVitaliy Gusev 		na->supported_attrs = supported;
2517c478bd9Sstevel@tonic-gate 		break;
2527c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
2537c478bd9Sstevel@tonic-gate 		/*
2547c478bd9Sstevel@tonic-gate 		 * read-only attr
2557c478bd9Sstevel@tonic-gate 		 */
2567c478bd9Sstevel@tonic-gate 		error = EINVAL;
2577c478bd9Sstevel@tonic-gate 		break;
2587c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
2597c478bd9Sstevel@tonic-gate 		/*
2607c478bd9Sstevel@tonic-gate 		 * Compare the input bitmap to the server's bitmap
2617c478bd9Sstevel@tonic-gate 		 */
262*f44e1126SVitaliy Gusev 		if (na->supported_attrs != supported) {
2637c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
2647c478bd9Sstevel@tonic-gate 		}
2657c478bd9Sstevel@tonic-gate 		break;
2667c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
2677c478bd9Sstevel@tonic-gate 		break;
2687c478bd9Sstevel@tonic-gate 	}
2697c478bd9Sstevel@tonic-gate 	return (error);
2707c478bd9Sstevel@tonic-gate }
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate /*
2737c478bd9Sstevel@tonic-gate  * Translate vnode vtype to nfsv4_ftype.
2747c478bd9Sstevel@tonic-gate  */
2757c478bd9Sstevel@tonic-gate static nfs_ftype4 vt_to_nf4[] = {
2767c478bd9Sstevel@tonic-gate 	0, NF4REG, NF4DIR, NF4BLK, NF4CHR, NF4LNK, NF4FIFO, 0, 0, NF4SOCK, 0
2777c478bd9Sstevel@tonic-gate };
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate /* ARGSUSED */
2807c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_type(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)2817c478bd9Sstevel@tonic-gate rfs4_fattr4_type(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2824a695956SMarcel Telka     union nfs4_attr_u *na)
2837c478bd9Sstevel@tonic-gate {
2847c478bd9Sstevel@tonic-gate 	int		error = 0;
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate 	switch (cmd) {
2877c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
2887c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
2897c478bd9Sstevel@tonic-gate 			error = EINVAL;
2907c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
2917c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
2927c478bd9Sstevel@tonic-gate 		if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_TYPE)) {
2937c478bd9Sstevel@tonic-gate 			error = -1;	/* may be okay if rdattr_error */
2947c478bd9Sstevel@tonic-gate 			break;
2957c478bd9Sstevel@tonic-gate 		}
2967c478bd9Sstevel@tonic-gate 		ASSERT(sarg->vap->va_mask & AT_TYPE);
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate 		/*
2997c478bd9Sstevel@tonic-gate 		 * if xattr flag not set, use v4_to_nf4 mapping;
3007c478bd9Sstevel@tonic-gate 		 * otherwise verify xattr flag is in sync with va_type
3017c478bd9Sstevel@tonic-gate 		 * and set xattr types.
3027c478bd9Sstevel@tonic-gate 		 */
3037c478bd9Sstevel@tonic-gate 		if (! (sarg->xattr & (FH4_NAMEDATTR | FH4_ATTRDIR)))
3047c478bd9Sstevel@tonic-gate 			na->type = vt_to_nf4[sarg->vap->va_type];
3057c478bd9Sstevel@tonic-gate 		else {
3067c478bd9Sstevel@tonic-gate 			/*
3077c478bd9Sstevel@tonic-gate 			 * FH4 flag was set.  Dir type maps to attrdir,
3087c478bd9Sstevel@tonic-gate 			 * and all other types map to namedattr.
3097c478bd9Sstevel@tonic-gate 			 */
3107c478bd9Sstevel@tonic-gate 			if (sarg->vap->va_type == VDIR)
3117c478bd9Sstevel@tonic-gate 				na->type = NF4ATTRDIR;
3127c478bd9Sstevel@tonic-gate 			else
3137c478bd9Sstevel@tonic-gate 				na->type = NF4NAMEDATTR;
3147c478bd9Sstevel@tonic-gate 		}
3157c478bd9Sstevel@tonic-gate 		break;
3167c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
3177c478bd9Sstevel@tonic-gate 		/*
3187c478bd9Sstevel@tonic-gate 		 * read-only attr
3197c478bd9Sstevel@tonic-gate 		 */
3207c478bd9Sstevel@tonic-gate 		error = EINVAL;
3217c478bd9Sstevel@tonic-gate 		break;
3227c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
3237c478bd9Sstevel@tonic-gate 		/*
3247c478bd9Sstevel@tonic-gate 		 * Compare the input type to the object type on server
3257c478bd9Sstevel@tonic-gate 		 */
3267c478bd9Sstevel@tonic-gate 		ASSERT(sarg->vap->va_mask & AT_TYPE);
3277c478bd9Sstevel@tonic-gate 		if (sarg->vap->va_type != nf4_to_vt[na->type])
3287c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
3297c478bd9Sstevel@tonic-gate 		break;
3307c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
3317c478bd9Sstevel@tonic-gate 		break;
3327c478bd9Sstevel@tonic-gate 	}
3337c478bd9Sstevel@tonic-gate 	return (error);
3347c478bd9Sstevel@tonic-gate }
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate /* ARGSUSED */
3377c478bd9Sstevel@tonic-gate static int
fattr4_get_fh_expire_type(struct exportinfo * exi,uint32_t * fh_expire_typep)3387c478bd9Sstevel@tonic-gate fattr4_get_fh_expire_type(struct exportinfo *exi, uint32_t *fh_expire_typep)
3397c478bd9Sstevel@tonic-gate {
3407c478bd9Sstevel@tonic-gate #ifdef	VOLATILE_FH_TEST
3417c478bd9Sstevel@tonic-gate 	int	ex_flags;
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate 	if (exi == NULL)
3447c478bd9Sstevel@tonic-gate 		return (ESTALE);
3457c478bd9Sstevel@tonic-gate 	ex_flags = exi->exi_export.ex_flags;
3467c478bd9Sstevel@tonic-gate 	if ((ex_flags & (EX_VOLFH | EX_VOLRNM | EX_VOLMIG | EX_NOEXPOPEN))
34793aeed83Smarks 	    == 0) {
3487c478bd9Sstevel@tonic-gate 		*fh_expire_typep = FH4_PERSISTENT;
3497c478bd9Sstevel@tonic-gate 		return (0);
3507c478bd9Sstevel@tonic-gate 	}
3517c478bd9Sstevel@tonic-gate 	*fh_expire_typep = 0;
3527c478bd9Sstevel@tonic-gate 
3537c478bd9Sstevel@tonic-gate 	if (ex_flags & EX_NOEXPOPEN) {
3547c478bd9Sstevel@tonic-gate 		/* file handles should not expire with open - not used */
3557c478bd9Sstevel@tonic-gate 		*fh_expire_typep = FH4_NOEXPIRE_WITH_OPEN;
3567c478bd9Sstevel@tonic-gate 	}
3577c478bd9Sstevel@tonic-gate 	if (ex_flags & EX_VOLFH) {
3587c478bd9Sstevel@tonic-gate 		/*
3597c478bd9Sstevel@tonic-gate 		 * file handles may expire any time - on share here.
3607c478bd9Sstevel@tonic-gate 		 * If volatile any, no need to check other flags.
3617c478bd9Sstevel@tonic-gate 		 */
3627c478bd9Sstevel@tonic-gate 		*fh_expire_typep |= FH4_VOLATILE_ANY;
3637c478bd9Sstevel@tonic-gate 		return (0);
3647c478bd9Sstevel@tonic-gate 	}
3657c478bd9Sstevel@tonic-gate 	if (ex_flags & EX_VOLRNM) {
3667c478bd9Sstevel@tonic-gate 		/* file handles may expire on rename */
3677c478bd9Sstevel@tonic-gate 		*fh_expire_typep |= FH4_VOL_RENAME;
3687c478bd9Sstevel@tonic-gate 	}
3697c478bd9Sstevel@tonic-gate 	if (ex_flags & EX_VOLMIG) {
3707c478bd9Sstevel@tonic-gate 		/* file handles may expire on migration - not used */
3717c478bd9Sstevel@tonic-gate 		*fh_expire_typep |= FH4_VOL_MIGRATION;
3727c478bd9Sstevel@tonic-gate 	}
3737c478bd9Sstevel@tonic-gate #else	/* not VOLATILE_FH_TEST */
3747c478bd9Sstevel@tonic-gate 	*fh_expire_typep = FH4_PERSISTENT;
3757c478bd9Sstevel@tonic-gate #endif	/* VOLATILE_FH_TEST */
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 	return (0);
3787c478bd9Sstevel@tonic-gate }
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate /*
3817c478bd9Sstevel@tonic-gate  * At this point the only volatile filehandles we allow (for test purposes
3827c478bd9Sstevel@tonic-gate  * only) are either fh's that expire when the filesystem is shared (reshared),
3837c478bd9Sstevel@tonic-gate  * fh's that expire on a rename and persistent ones.
3847c478bd9Sstevel@tonic-gate  */
3857c478bd9Sstevel@tonic-gate /* ARGSUSED */
3867c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_fh_expire_type(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)3877c478bd9Sstevel@tonic-gate rfs4_fattr4_fh_expire_type(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
3884a695956SMarcel Telka     union nfs4_attr_u *na)
3897c478bd9Sstevel@tonic-gate {
3907c478bd9Sstevel@tonic-gate 	uint32_t fh_expire_type;
3917c478bd9Sstevel@tonic-gate 	int error = 0;
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate 	switch (cmd) {
3947c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
3957c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
3967c478bd9Sstevel@tonic-gate 			error = EINVAL;
3977c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
3987c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
3997c478bd9Sstevel@tonic-gate 		error = fattr4_get_fh_expire_type(sarg->cs->exi,
40093aeed83Smarks 		    &na->fh_expire_type);
4017c478bd9Sstevel@tonic-gate 		break;
4027c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
4037c478bd9Sstevel@tonic-gate 		/*
4047c478bd9Sstevel@tonic-gate 		 * read-only attr
4057c478bd9Sstevel@tonic-gate 		 */
4067c478bd9Sstevel@tonic-gate 		error = EINVAL;
4077c478bd9Sstevel@tonic-gate 		break;
4087c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
4097c478bd9Sstevel@tonic-gate 		error = fattr4_get_fh_expire_type(sarg->cs->exi,
41093aeed83Smarks 		    &fh_expire_type);
4117c478bd9Sstevel@tonic-gate 		if (!error && (na->fh_expire_type != fh_expire_type))
4127c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
4137c478bd9Sstevel@tonic-gate 		break;
4147c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
4157c478bd9Sstevel@tonic-gate 		break;
4167c478bd9Sstevel@tonic-gate 	}
4177c478bd9Sstevel@tonic-gate 	return (error);
4187c478bd9Sstevel@tonic-gate }
4197c478bd9Sstevel@tonic-gate 
4207c478bd9Sstevel@tonic-gate static int
fattr4_get_change(struct nfs4_svgetit_arg * sarg,fattr4_change * changep)4217c478bd9Sstevel@tonic-gate fattr4_get_change(struct nfs4_svgetit_arg *sarg, fattr4_change *changep)
4227c478bd9Sstevel@tonic-gate {
4237c478bd9Sstevel@tonic-gate 	vattr_t vap2[1], *vap = sarg->vap;
4247c478bd9Sstevel@tonic-gate 	struct compound_state *cs = sarg->cs;
4257c478bd9Sstevel@tonic-gate 	vnode_t *vp = cs->vp;
4267c478bd9Sstevel@tonic-gate 	nfsstat4 status;
4274a695956SMarcel Telka 	timespec_t vis_change;
4287c478bd9Sstevel@tonic-gate 
4297c478bd9Sstevel@tonic-gate 	if ((vap->va_mask & AT_CTIME) == 0) {
4307c478bd9Sstevel@tonic-gate 		if (sarg->rdattr_error && (vp == NULL)) {
4317c478bd9Sstevel@tonic-gate 			return (-1);	/* may be okay if rdattr_error */
4327c478bd9Sstevel@tonic-gate 		}
4337c478bd9Sstevel@tonic-gate 		ASSERT(vp != NULL);
4347c478bd9Sstevel@tonic-gate 		vap = vap2;
4357c478bd9Sstevel@tonic-gate 		vap->va_mask = AT_CTIME;
4367c478bd9Sstevel@tonic-gate 		status = rfs4_vop_getattr(vp, vap, 0, cs->cr);
4377c478bd9Sstevel@tonic-gate 		if (status != NFS4_OK)
4387c478bd9Sstevel@tonic-gate 			return (geterrno4(status));
4397c478bd9Sstevel@tonic-gate 	}
4404a695956SMarcel Telka 	NFS4_SET_FATTR4_CHANGE(*changep, vap->va_ctime);
4414a695956SMarcel Telka 
4424a695956SMarcel Telka 	if (nfs_visible_change(cs->exi, vp, &vis_change)) {
4434a695956SMarcel Telka 		fattr4_change visch;
4444a695956SMarcel Telka 		NFS4_SET_FATTR4_CHANGE(visch, vis_change);
4454a695956SMarcel Telka 		if (visch > *changep)
4464a695956SMarcel Telka 			*changep = visch;
4474a695956SMarcel Telka 	}
4484a695956SMarcel Telka 
4497c478bd9Sstevel@tonic-gate 	return (0);
4507c478bd9Sstevel@tonic-gate }
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate /* ARGSUSED */
4537c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_change(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)4547c478bd9Sstevel@tonic-gate rfs4_fattr4_change(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
4554a695956SMarcel Telka     union nfs4_attr_u *na)
4567c478bd9Sstevel@tonic-gate {
4577c478bd9Sstevel@tonic-gate 	int error = 0;
4587c478bd9Sstevel@tonic-gate 	fattr4_change change;
4597c478bd9Sstevel@tonic-gate 	uint_t mask;
4607c478bd9Sstevel@tonic-gate 	vattr_t *vap = sarg->vap;
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate 	switch (cmd) {
4637c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
4647c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
4657c478bd9Sstevel@tonic-gate 			error = EINVAL;
4667c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
4677c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
4687c478bd9Sstevel@tonic-gate 		error = fattr4_get_change(sarg, &na->change);
4697c478bd9Sstevel@tonic-gate 		break;
4707c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
4717c478bd9Sstevel@tonic-gate 		/*
4727c478bd9Sstevel@tonic-gate 		 * read-only attr
4737c478bd9Sstevel@tonic-gate 		 */
4747c478bd9Sstevel@tonic-gate 		error = EINVAL;
4757c478bd9Sstevel@tonic-gate 		break;
4767c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
4777c478bd9Sstevel@tonic-gate 		mask = vap->va_mask;
4787c478bd9Sstevel@tonic-gate 		vap->va_mask &= ~AT_CTIME;	/* force a VOP_GETATTR */
4797c478bd9Sstevel@tonic-gate 		error = fattr4_get_change(sarg, &change);
4807c478bd9Sstevel@tonic-gate 		vap->va_mask = mask;
4817c478bd9Sstevel@tonic-gate 		if (!error && (na->change != change))
4827c478bd9Sstevel@tonic-gate 			error = -1;
4837c478bd9Sstevel@tonic-gate 		break;
4847c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
4857c478bd9Sstevel@tonic-gate 		break;
4867c478bd9Sstevel@tonic-gate 	}
4877c478bd9Sstevel@tonic-gate 	return (error);
4887c478bd9Sstevel@tonic-gate }
4897c478bd9Sstevel@tonic-gate 
4907c478bd9Sstevel@tonic-gate /* ARGSUSED */
4917c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_size(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)4927c478bd9Sstevel@tonic-gate rfs4_fattr4_size(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
4934a695956SMarcel Telka     union nfs4_attr_u *na)
4947c478bd9Sstevel@tonic-gate {
4957c478bd9Sstevel@tonic-gate 	int	error = 0;
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate 	switch (cmd) {
4987c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
4997c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
5007c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
5017c478bd9Sstevel@tonic-gate 		if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_SIZE)) {
5027c478bd9Sstevel@tonic-gate 			error = -1;	/* may be okay if rdattr_error */
5037c478bd9Sstevel@tonic-gate 			break;
5047c478bd9Sstevel@tonic-gate 		}
5057c478bd9Sstevel@tonic-gate 		ASSERT(sarg->vap->va_mask & AT_SIZE);
5067c478bd9Sstevel@tonic-gate 		na->size = sarg->vap->va_size;
5077c478bd9Sstevel@tonic-gate 		break;
5087c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
5097c478bd9Sstevel@tonic-gate 		ASSERT(sarg->vap->va_mask & AT_SIZE);
5107c478bd9Sstevel@tonic-gate 		sarg->vap->va_size = na->size;
5117c478bd9Sstevel@tonic-gate 		break;
5127c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
5137c478bd9Sstevel@tonic-gate 		ASSERT(sarg->vap->va_mask & AT_SIZE);
5147c478bd9Sstevel@tonic-gate 		if (sarg->vap->va_size != na->size)
5157c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
5167c478bd9Sstevel@tonic-gate 		break;
5177c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
5187c478bd9Sstevel@tonic-gate 		break;
5197c478bd9Sstevel@tonic-gate 	}
5207c478bd9Sstevel@tonic-gate 	return (error);
5217c478bd9Sstevel@tonic-gate }
5227c478bd9Sstevel@tonic-gate 
5237c478bd9Sstevel@tonic-gate /*
5247c478bd9Sstevel@tonic-gate  * XXX - need VOP extension to ask file system (e.g. pcfs) if it supports
5257c478bd9Sstevel@tonic-gate  * hard links.
5267c478bd9Sstevel@tonic-gate  */
5277c478bd9Sstevel@tonic-gate /* ARGSUSED */
5287c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_link_support(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)5297c478bd9Sstevel@tonic-gate rfs4_fattr4_link_support(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
5304a695956SMarcel Telka     union nfs4_attr_u *na)
5317c478bd9Sstevel@tonic-gate {
5327c478bd9Sstevel@tonic-gate 	int error = 0;
5337c478bd9Sstevel@tonic-gate 
5347c478bd9Sstevel@tonic-gate 	switch (cmd) {
5357c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
5367c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
5377c478bd9Sstevel@tonic-gate 			error = EINVAL;
5387c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
5397c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
5407c478bd9Sstevel@tonic-gate 		na->link_support = TRUE;
5417c478bd9Sstevel@tonic-gate 		break;
5427c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
5437c478bd9Sstevel@tonic-gate 		/*
5447c478bd9Sstevel@tonic-gate 		 * read-only attr
5457c478bd9Sstevel@tonic-gate 		 */
5467c478bd9Sstevel@tonic-gate 		error = EINVAL;
5477c478bd9Sstevel@tonic-gate 		break;
5487c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
5497c478bd9Sstevel@tonic-gate 		if (!na->link_support)
5507c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
5517c478bd9Sstevel@tonic-gate 		break;
5527c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
5537c478bd9Sstevel@tonic-gate 		break;
5547c478bd9Sstevel@tonic-gate 	}
5557c478bd9Sstevel@tonic-gate 	return (error);
5567c478bd9Sstevel@tonic-gate }
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate /*
5597c478bd9Sstevel@tonic-gate  * XXX - need VOP extension to ask file system (e.g. pcfs) if it supports
5607c478bd9Sstevel@tonic-gate  * sym links.
5617c478bd9Sstevel@tonic-gate  */
5627c478bd9Sstevel@tonic-gate /* ARGSUSED */
5637c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_symlink_support(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)5647c478bd9Sstevel@tonic-gate rfs4_fattr4_symlink_support(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
5654a695956SMarcel Telka     union nfs4_attr_u *na)
5667c478bd9Sstevel@tonic-gate {
5677c478bd9Sstevel@tonic-gate 	int error = 0;
5687c478bd9Sstevel@tonic-gate 
5697c478bd9Sstevel@tonic-gate 	switch (cmd) {
5707c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
5717c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
5727c478bd9Sstevel@tonic-gate 			error = EINVAL;
5737c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
5747c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
5757c478bd9Sstevel@tonic-gate 		na->symlink_support = TRUE;
5767c478bd9Sstevel@tonic-gate 		break;
5777c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
5787c478bd9Sstevel@tonic-gate 		/*
5797c478bd9Sstevel@tonic-gate 		 * read-only attr
5807c478bd9Sstevel@tonic-gate 		 */
5817c478bd9Sstevel@tonic-gate 		error = EINVAL;
5827c478bd9Sstevel@tonic-gate 		break;
5837c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
5847c478bd9Sstevel@tonic-gate 		if (!na->symlink_support)
5857c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
5867c478bd9Sstevel@tonic-gate 		break;
5877c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
5887c478bd9Sstevel@tonic-gate 		break;
5897c478bd9Sstevel@tonic-gate 	}
5907c478bd9Sstevel@tonic-gate 	return (error);
5917c478bd9Sstevel@tonic-gate }
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate /* ARGSUSED */
5947c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_named_attr(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)5957c478bd9Sstevel@tonic-gate rfs4_fattr4_named_attr(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
5964a695956SMarcel Telka     union nfs4_attr_u *na)
5977c478bd9Sstevel@tonic-gate {
5987c478bd9Sstevel@tonic-gate 	int error = 0;
5997c478bd9Sstevel@tonic-gate 	ulong_t val;
6007c478bd9Sstevel@tonic-gate 
6017c478bd9Sstevel@tonic-gate 	switch (cmd) {
6027c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
6037c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
6047c478bd9Sstevel@tonic-gate 			error = EINVAL;
6057c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
6067c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
6077c478bd9Sstevel@tonic-gate 		if (sarg->rdattr_error && (sarg->cs->vp == NULL)) {
6087c478bd9Sstevel@tonic-gate 			error = -1;	/* may be okay if rdattr_error */
6097c478bd9Sstevel@tonic-gate 			break;
6107c478bd9Sstevel@tonic-gate 		}
6117c478bd9Sstevel@tonic-gate 		ASSERT(sarg->cs->vp != NULL);
6127c478bd9Sstevel@tonic-gate 
6137c478bd9Sstevel@tonic-gate 		/*
6147c478bd9Sstevel@tonic-gate 		 * Solaris xattr model requires that VFS_XATTR is set
61593aeed83Smarks 		 * in file systems enabled for generic xattr.  If VFS_XATTR
61693aeed83Smarks 		 * not set, no need to call pathconf for _PC_XATTR_EXISTS..
61793aeed83Smarks 		 *
61893aeed83Smarks 		 * However the VFS_XATTR flag doesn't indicate sysattr support
61993aeed83Smarks 		 * so always check for sysattrs and then only do the
62093aeed83Smarks 		 * _PC_XATTR_EXISTS pathconf if needed.
6217c478bd9Sstevel@tonic-gate 		 */
62293aeed83Smarks 
62393aeed83Smarks 		val = 0;
62493aeed83Smarks 		error = VOP_PATHCONF(sarg->cs->vp, _PC_SATTR_EXISTS,
62593aeed83Smarks 		    &val, sarg->cs->cr, NULL);
62693aeed83Smarks 		if ((error || val == 0) &&
62793aeed83Smarks 		    sarg->cs->vp->v_vfsp->vfs_flag & VFS_XATTR) {
62893aeed83Smarks 			error = VOP_PATHCONF(sarg->cs->vp,
62993aeed83Smarks 			    _PC_XATTR_EXISTS, &val, sarg->cs->cr, NULL);
6307c478bd9Sstevel@tonic-gate 			if (error)
6317c478bd9Sstevel@tonic-gate 				break;
63293aeed83Smarks 		}
6337c478bd9Sstevel@tonic-gate 		na->named_attr = (val ? TRUE : FALSE);
6347c478bd9Sstevel@tonic-gate 		break;
6357c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
6367c478bd9Sstevel@tonic-gate 		/*
6377c478bd9Sstevel@tonic-gate 		 * read-only attr
6387c478bd9Sstevel@tonic-gate 		 */
6397c478bd9Sstevel@tonic-gate 		error = EINVAL;
6407c478bd9Sstevel@tonic-gate 		break;
6417c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
6427c478bd9Sstevel@tonic-gate 		ASSERT(sarg->cs->vp != NULL);
6437c478bd9Sstevel@tonic-gate 		if (sarg->cs->vp->v_vfsp->vfs_flag & VFS_XATTR) {
6445535ab6eSmarks 			error = VOP_PATHCONF(sarg->cs->vp, _PC_SATTR_EXISTS,
64593aeed83Smarks 			    &val, sarg->cs->cr, NULL);
6465535ab6eSmarks 			if (error || val == 0)
6475535ab6eSmarks 				error = VOP_PATHCONF(sarg->cs->vp,
6485535ab6eSmarks 				    _PC_XATTR_EXISTS, &val,
6495535ab6eSmarks 				    sarg->cs->cr, NULL);
6507c478bd9Sstevel@tonic-gate 			if (error)
6517c478bd9Sstevel@tonic-gate 				break;
6527c478bd9Sstevel@tonic-gate 		} else
6537c478bd9Sstevel@tonic-gate 			val = 0;
6547c478bd9Sstevel@tonic-gate 		if (na->named_attr != (val ? TRUE : FALSE))
6557c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
6567c478bd9Sstevel@tonic-gate 		break;
6577c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
6587c478bd9Sstevel@tonic-gate 		break;
6597c478bd9Sstevel@tonic-gate 	}
6607c478bd9Sstevel@tonic-gate 	return (error);
6617c478bd9Sstevel@tonic-gate }
6627c478bd9Sstevel@tonic-gate 
6637c478bd9Sstevel@tonic-gate /* ARGSUSED */
6647c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_fsid(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)6657c478bd9Sstevel@tonic-gate rfs4_fattr4_fsid(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
6664a695956SMarcel Telka     union nfs4_attr_u *na)
6677c478bd9Sstevel@tonic-gate {
6687c478bd9Sstevel@tonic-gate 	int error = 0;
6697c478bd9Sstevel@tonic-gate 	int *pmaj = (int *)&na->fsid.major;
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate 	/*
6727c478bd9Sstevel@tonic-gate 	 * fsid_t is 64bits so it fits completely in fattr4_fsid.major.
6737c478bd9Sstevel@tonic-gate 	 * fattr4_fsid.minor is always set to 0 since it isn't needed (yet).
6747c478bd9Sstevel@tonic-gate 	 */
6757c478bd9Sstevel@tonic-gate 	switch (cmd) {
6767c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
6777c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
6787c478bd9Sstevel@tonic-gate 			error = EINVAL;
6797c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
6807c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
6812f172c55SRobert Thurlow 		if (sarg->is_referral) {
6822f172c55SRobert Thurlow 			na->fsid.major = 1;
6832f172c55SRobert Thurlow 			na->fsid.minor = 0;
6842f172c55SRobert Thurlow 		} else if (sarg->cs->exi->exi_volatile_dev) {
6857c478bd9Sstevel@tonic-gate 			pmaj[0] = sarg->cs->exi->exi_fsid.val[0];
6867c478bd9Sstevel@tonic-gate 			pmaj[1] = sarg->cs->exi->exi_fsid.val[1];
6877c478bd9Sstevel@tonic-gate 			na->fsid.minor = 0;
6887c478bd9Sstevel@tonic-gate 		} else {
6897c478bd9Sstevel@tonic-gate 			na->fsid.major = getmajor(sarg->vap->va_fsid);
6907c478bd9Sstevel@tonic-gate 			na->fsid.minor = getminor(sarg->vap->va_fsid);
6917c478bd9Sstevel@tonic-gate 		}
6927c478bd9Sstevel@tonic-gate 		break;
6937c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
6947c478bd9Sstevel@tonic-gate 		error = EINVAL;
6957c478bd9Sstevel@tonic-gate 		break;
6967c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
6972f172c55SRobert Thurlow 		if (sarg->is_referral) {
6982f172c55SRobert Thurlow 			if (na->fsid.major != 1 ||
6992f172c55SRobert Thurlow 			    na->fsid.minor != 0)
7002f172c55SRobert Thurlow 				error = -1;
7012f172c55SRobert Thurlow 		} else if (sarg->cs->exi->exi_volatile_dev) {
7027c478bd9Sstevel@tonic-gate 			if (pmaj[0] != sarg->cs->exi->exi_fsid.val[0] ||
7037c478bd9Sstevel@tonic-gate 			    pmaj[1] != sarg->cs->exi->exi_fsid.val[1] ||
7047c478bd9Sstevel@tonic-gate 			    na->fsid.minor != 0)
7057c478bd9Sstevel@tonic-gate 				error = -1;
7067c478bd9Sstevel@tonic-gate 		} else {
7077c478bd9Sstevel@tonic-gate 			if (na->fsid.major != getmajor(sarg->vap->va_fsid) ||
7087c478bd9Sstevel@tonic-gate 			    na->fsid.minor != getminor(sarg->vap->va_fsid))
7097c478bd9Sstevel@tonic-gate 				error = -1;
7107c478bd9Sstevel@tonic-gate 		}
7117c478bd9Sstevel@tonic-gate 		break;
7127c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
7137c478bd9Sstevel@tonic-gate 		break;
7147c478bd9Sstevel@tonic-gate 	}
7157c478bd9Sstevel@tonic-gate 	return (error);
7167c478bd9Sstevel@tonic-gate }
7177c478bd9Sstevel@tonic-gate 
7187c478bd9Sstevel@tonic-gate /* ARGSUSED */
7197c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_unique_handles(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)7207c478bd9Sstevel@tonic-gate rfs4_fattr4_unique_handles(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
7214a695956SMarcel Telka     union nfs4_attr_u *na)
7227c478bd9Sstevel@tonic-gate {
7237c478bd9Sstevel@tonic-gate 	/*
7247c478bd9Sstevel@tonic-gate 	 * XXX
7257c478bd9Sstevel@tonic-gate 	 * For now, we can't support this. Problem of /export, beinging
7267c478bd9Sstevel@tonic-gate 	 * a file system, /export/a and /export/b shared separately,
7277c478bd9Sstevel@tonic-gate 	 * and /export/a/l and /export/b/l are ahrd links of each other.
7287c478bd9Sstevel@tonic-gate 	 */
7297c478bd9Sstevel@tonic-gate 	int error = 0;
7307c478bd9Sstevel@tonic-gate 
7317c478bd9Sstevel@tonic-gate 	switch (cmd) {
7327c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
7337c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
7347c478bd9Sstevel@tonic-gate 			error = EINVAL;
7357c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
7367c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
7377c478bd9Sstevel@tonic-gate 		na->unique_handles = FALSE;
7387c478bd9Sstevel@tonic-gate 		break;
7397c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
7407c478bd9Sstevel@tonic-gate 		/*
7417c478bd9Sstevel@tonic-gate 		 * read-only attr
7427c478bd9Sstevel@tonic-gate 		 */
7437c478bd9Sstevel@tonic-gate 		error = EINVAL;
7447c478bd9Sstevel@tonic-gate 		break;
7457c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
7467c478bd9Sstevel@tonic-gate 		if (na->unique_handles)
7477c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
7487c478bd9Sstevel@tonic-gate 		break;
7497c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
7507c478bd9Sstevel@tonic-gate 		break;
7517c478bd9Sstevel@tonic-gate 	}
7527c478bd9Sstevel@tonic-gate 	return (error);
7537c478bd9Sstevel@tonic-gate }
7547c478bd9Sstevel@tonic-gate 
7557c478bd9Sstevel@tonic-gate /* ARGSUSED */
7567c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_lease_time(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)7577c478bd9Sstevel@tonic-gate rfs4_fattr4_lease_time(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
7584a695956SMarcel Telka     union nfs4_attr_u *na)
7597c478bd9Sstevel@tonic-gate {
7607c478bd9Sstevel@tonic-gate 	int error = 0;
7617c478bd9Sstevel@tonic-gate 
7627c478bd9Sstevel@tonic-gate 	switch (cmd) {
7637c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
7647c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
7657c478bd9Sstevel@tonic-gate 			error = EINVAL;
7667c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
7677c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
7687c478bd9Sstevel@tonic-gate 		na->lease_time = rfs4_lease_time;
7697c478bd9Sstevel@tonic-gate 		break;
7707c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
7717c478bd9Sstevel@tonic-gate 		/*
7727c478bd9Sstevel@tonic-gate 		 * read-only attr
7737c478bd9Sstevel@tonic-gate 		 */
7747c478bd9Sstevel@tonic-gate 		error = EINVAL;
7757c478bd9Sstevel@tonic-gate 		break;
7767c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
7777c478bd9Sstevel@tonic-gate 		if (na->lease_time != rfs4_lease_time)
7787c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
7797c478bd9Sstevel@tonic-gate 		break;
7807c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
7817c478bd9Sstevel@tonic-gate 		break;
7827c478bd9Sstevel@tonic-gate 	}
7837c478bd9Sstevel@tonic-gate 	return (error);
7847c478bd9Sstevel@tonic-gate }
7857c478bd9Sstevel@tonic-gate 
7867c478bd9Sstevel@tonic-gate /* ARGSUSED */
7877c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_rdattr_error(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)7887c478bd9Sstevel@tonic-gate rfs4_fattr4_rdattr_error(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
7894a695956SMarcel Telka     union nfs4_attr_u *na)
7907c478bd9Sstevel@tonic-gate {
7917c478bd9Sstevel@tonic-gate 	int error = 0;
7927c478bd9Sstevel@tonic-gate 
7937c478bd9Sstevel@tonic-gate 	switch (cmd) {
7947c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
7957c478bd9Sstevel@tonic-gate 		if ((sarg->op == NFS4ATTR_SETIT) ||
79693aeed83Smarks 		    (sarg->op == NFS4ATTR_VERIT))
7977c478bd9Sstevel@tonic-gate 			error = EINVAL;
7987c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
7997c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
8007c478bd9Sstevel@tonic-gate 		ASSERT(sarg->rdattr_error_req);
8017c478bd9Sstevel@tonic-gate 		na->rdattr_error = sarg->rdattr_error;
8027c478bd9Sstevel@tonic-gate 		break;
8037c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
8047c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
8057c478bd9Sstevel@tonic-gate 		/*
8067c478bd9Sstevel@tonic-gate 		 * read-only attr
8077c478bd9Sstevel@tonic-gate 		 */
8087c478bd9Sstevel@tonic-gate 		error = EINVAL;
8097c478bd9Sstevel@tonic-gate 		break;
8107c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
8117c478bd9Sstevel@tonic-gate 		break;
8127c478bd9Sstevel@tonic-gate 	}
8137c478bd9Sstevel@tonic-gate 	return (error);
8147c478bd9Sstevel@tonic-gate }
8157c478bd9Sstevel@tonic-gate 
816eac3aab7Srobinson /*
817eac3aab7Srobinson  * Server side compare of a filehandle from the wire to a native
818eac3aab7Srobinson  * server filehandle.
819eac3aab7Srobinson  */
820eac3aab7Srobinson static int
rfs4fhcmp(nfs_fh4 * wirefh,nfs_fh4 * srvfh)821eac3aab7Srobinson rfs4fhcmp(nfs_fh4 *wirefh, nfs_fh4 *srvfh)
822eac3aab7Srobinson {
823eac3aab7Srobinson 	nfs_fh4_fmt_t fh;
824eac3aab7Srobinson 
825eac3aab7Srobinson 	ASSERT(IS_P2ALIGNED(wirefh->nfs_fh4_val, sizeof (uint32_t)));
826eac3aab7Srobinson 
827eac3aab7Srobinson 	bzero(&fh, sizeof (nfs_fh4_fmt_t));
828eac3aab7Srobinson 	if (!xdr_inline_decode_nfs_fh4((uint32_t *)wirefh->nfs_fh4_val, &fh,
829eac3aab7Srobinson 	    wirefh->nfs_fh4_len))
830eac3aab7Srobinson 		return (1);
831eac3aab7Srobinson 
832eac3aab7Srobinson 	return (bcmp(srvfh->nfs_fh4_val, &fh, srvfh->nfs_fh4_len));
833eac3aab7Srobinson }
834eac3aab7Srobinson 
8357c478bd9Sstevel@tonic-gate /* ARGSUSED */
8367c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_filehandle(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)8377c478bd9Sstevel@tonic-gate rfs4_fattr4_filehandle(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
8384a695956SMarcel Telka     union nfs4_attr_u *na)
8397c478bd9Sstevel@tonic-gate {
8407c478bd9Sstevel@tonic-gate 	nfs_fh4 *fh;
8417c478bd9Sstevel@tonic-gate 
8427c478bd9Sstevel@tonic-gate 	switch (cmd) {
8437c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
8447c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
845eac3aab7Srobinson 			return (EINVAL);
846eac3aab7Srobinson 		return (0);	/* this attr is supported */
8477c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
8487c478bd9Sstevel@tonic-gate 		/*
8497c478bd9Sstevel@tonic-gate 		 * If sarg->cs->fh is all zeros then should makefh a new
8507c478bd9Sstevel@tonic-gate 		 * one, otherwise, copy that one over.
8517c478bd9Sstevel@tonic-gate 		 */
8527c478bd9Sstevel@tonic-gate 		fh = &sarg->cs->fh;
8537c478bd9Sstevel@tonic-gate 		if (sarg->cs->fh.nfs_fh4_len == 0) {
854eac3aab7Srobinson 			if (sarg->rdattr_error && (sarg->cs->vp == NULL))
855eac3aab7Srobinson 				return (-1);	/* okay if rdattr_error */
8567c478bd9Sstevel@tonic-gate 			ASSERT(sarg->cs->vp != NULL);
8577c478bd9Sstevel@tonic-gate 			na->filehandle.nfs_fh4_val =
858eac3aab7Srobinson 			    kmem_alloc(NFS_FH4_LEN, KM_SLEEP);
859eac3aab7Srobinson 			return (makefh4(&na->filehandle, sarg->cs->vp,
860eac3aab7Srobinson 			    sarg->cs->exi));
8617c478bd9Sstevel@tonic-gate 		}
862eac3aab7Srobinson 		na->filehandle.nfs_fh4_val =
863eac3aab7Srobinson 		    kmem_alloc(fh->nfs_fh4_len, KM_SLEEP);
864eac3aab7Srobinson 		nfs_fh4_copy(fh, &na->filehandle);
865eac3aab7Srobinson 		return (0);
8667c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
8677c478bd9Sstevel@tonic-gate 		/*
8687c478bd9Sstevel@tonic-gate 		 * read-only attr
8697c478bd9Sstevel@tonic-gate 		 */
870eac3aab7Srobinson 		return (EINVAL);
8717c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
872eac3aab7Srobinson 		/*
873eac3aab7Srobinson 		 * A verify of a filehandle will have the client sending
874eac3aab7Srobinson 		 * the raw format which needs to be compared to the
875eac3aab7Srobinson 		 * native format.
876eac3aab7Srobinson 		 */
877eac3aab7Srobinson 		if (rfs4fhcmp(&na->filehandle, &sarg->cs->fh) == 1)
878eac3aab7Srobinson 			return (-1);	/* no match */
879eac3aab7Srobinson 		return (0);
8807c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
881eac3aab7Srobinson 		if (sarg->op != NFS4ATTR_GETIT)
882eac3aab7Srobinson 			return (0);
883eac3aab7Srobinson 		if (na->filehandle.nfs_fh4_val == NULL)
884eac3aab7Srobinson 			return (0);
885eac3aab7Srobinson 		kmem_free(na->filehandle.nfs_fh4_val,
886eac3aab7Srobinson 		    na->filehandle.nfs_fh4_len);
887eac3aab7Srobinson 		na->filehandle.nfs_fh4_val = NULL;
888eac3aab7Srobinson 		na->filehandle.nfs_fh4_len = 0;
889eac3aab7Srobinson 		return (0);
8907c478bd9Sstevel@tonic-gate 	}
891eac3aab7Srobinson 	return (0);
8927c478bd9Sstevel@tonic-gate }
8937c478bd9Sstevel@tonic-gate 
8947c478bd9Sstevel@tonic-gate /*
8957c478bd9Sstevel@tonic-gate  * Recommended attributes
8967c478bd9Sstevel@tonic-gate  */
8977c478bd9Sstevel@tonic-gate 
8987c478bd9Sstevel@tonic-gate /* ARGSUSED */
8997c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_acl(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)9007c478bd9Sstevel@tonic-gate rfs4_fattr4_acl(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
9014a695956SMarcel Telka     union nfs4_attr_u *na)
9027c478bd9Sstevel@tonic-gate {
9037c478bd9Sstevel@tonic-gate 	int error = 0;
9047c478bd9Sstevel@tonic-gate 	vsecattr_t vs_native, vs_ace4;
9057c478bd9Sstevel@tonic-gate 	ulong_t whichacl;
9067c478bd9Sstevel@tonic-gate 	nfsstat4 status;
9077c478bd9Sstevel@tonic-gate 	vattr_t va, *vap = sarg->vap;
9087c478bd9Sstevel@tonic-gate 	vnode_t *vp = sarg->cs->vp;
9097c478bd9Sstevel@tonic-gate 
9107c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
9117c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
9127c478bd9Sstevel@tonic-gate 
9137c478bd9Sstevel@tonic-gate 	switch (cmd) {
9147c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
9157c478bd9Sstevel@tonic-gate 		break;
9167c478bd9Sstevel@tonic-gate 
9177c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
9187c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
9197c478bd9Sstevel@tonic-gate 		if (sarg->rdattr_error && (vp == NULL)) {
9207c478bd9Sstevel@tonic-gate 			return (-1);
9217c478bd9Sstevel@tonic-gate 		}
9227c478bd9Sstevel@tonic-gate 		ASSERT(vp != NULL);
9237c478bd9Sstevel@tonic-gate 		bzero(&vs_native, sizeof (vs_native));
9247c478bd9Sstevel@tonic-gate 
9257c478bd9Sstevel@tonic-gate 		/* see which ACLs fs supports */
9267c478bd9Sstevel@tonic-gate 		error = VOP_PATHCONF(vp, _PC_ACL_ENABLED, &whichacl,
927da6c28aaSamw 		    sarg->cs->cr, NULL);
9287c478bd9Sstevel@tonic-gate 		if (error != 0) {
9297c478bd9Sstevel@tonic-gate 			/*
9307c478bd9Sstevel@tonic-gate 			 * If we got an error, then the filesystem
9317c478bd9Sstevel@tonic-gate 			 * likely does not understand the _PC_ACL_ENABLED
9327c478bd9Sstevel@tonic-gate 			 * pathconf.  In this case, we fall back to trying
9337c478bd9Sstevel@tonic-gate 			 * POSIX-draft (aka UFS-style) ACLs, since that's
9347c478bd9Sstevel@tonic-gate 			 * the behavior used by earlier version of NFS.
9357c478bd9Sstevel@tonic-gate 			 */
9367c478bd9Sstevel@tonic-gate 			error = 0;
9377c478bd9Sstevel@tonic-gate 			whichacl = _ACL_ACLENT_ENABLED;
9387c478bd9Sstevel@tonic-gate 		}
9397c478bd9Sstevel@tonic-gate 
9407c478bd9Sstevel@tonic-gate 		if (!(whichacl & (_ACL_ACE_ENABLED | _ACL_ACLENT_ENABLED))) {
9417c478bd9Sstevel@tonic-gate 			/*
9427c478bd9Sstevel@tonic-gate 			 * If the file system supports neither ACE nor
9437c478bd9Sstevel@tonic-gate 			 * ACLENT ACLs we will fall back to UFS-style ACLs
9447c478bd9Sstevel@tonic-gate 			 * like we did above if there was an error upon
9457c478bd9Sstevel@tonic-gate 			 * calling VOP_PATHCONF.
9467c478bd9Sstevel@tonic-gate 			 *
9477c478bd9Sstevel@tonic-gate 			 * ACE and ACLENT type ACLs are the only interfaces
9487c478bd9Sstevel@tonic-gate 			 * supported thus far.  If any other bits are set on
9497c478bd9Sstevel@tonic-gate 			 * 'whichacl' upon return from VOP_PATHCONF, we will
9507c478bd9Sstevel@tonic-gate 			 * ignore them.
9517c478bd9Sstevel@tonic-gate 			 */
9527c478bd9Sstevel@tonic-gate 			whichacl = _ACL_ACLENT_ENABLED;
9537c478bd9Sstevel@tonic-gate 		}
9547c478bd9Sstevel@tonic-gate 
9557c478bd9Sstevel@tonic-gate 		if (whichacl & _ACL_ACE_ENABLED)
9567c478bd9Sstevel@tonic-gate 			vs_native.vsa_mask = VSA_ACE | VSA_ACECNT;
9577c478bd9Sstevel@tonic-gate 		else if (whichacl & _ACL_ACLENT_ENABLED)
9587c478bd9Sstevel@tonic-gate 			vs_native.vsa_mask = VSA_ACL | VSA_ACLCNT |
9597c478bd9Sstevel@tonic-gate 			    VSA_DFACL | VSA_DFACLCNT;
9607c478bd9Sstevel@tonic-gate 
9617c478bd9Sstevel@tonic-gate 		if (error != 0)
9627c478bd9Sstevel@tonic-gate 			break;
9637c478bd9Sstevel@tonic-gate 
9647c478bd9Sstevel@tonic-gate 		/* get the ACL, and translate it into nfsace4 style */
9657c478bd9Sstevel@tonic-gate 		error = VOP_GETSECATTR(vp, &vs_native,
966da6c28aaSamw 		    0, sarg->cs->cr, NULL);
9677c478bd9Sstevel@tonic-gate 		if (error != 0)
9687c478bd9Sstevel@tonic-gate 			break;
9697c478bd9Sstevel@tonic-gate 		if (whichacl & _ACL_ACE_ENABLED) {
970fa9e4066Sahrens 			error = vs_acet_to_ace4(&vs_native, &vs_ace4, TRUE);
9717c478bd9Sstevel@tonic-gate 			vs_acet_destroy(&vs_native);
9727c478bd9Sstevel@tonic-gate 		} else {
9737c478bd9Sstevel@tonic-gate 			error = vs_aent_to_ace4(&vs_native, &vs_ace4,
9747c478bd9Sstevel@tonic-gate 			    vp->v_type == VDIR, TRUE);
9757c478bd9Sstevel@tonic-gate 			vs_aent_destroy(&vs_native);
9767c478bd9Sstevel@tonic-gate 		}
9777c478bd9Sstevel@tonic-gate 		if (error != 0)
9787c478bd9Sstevel@tonic-gate 			break;
9797c478bd9Sstevel@tonic-gate 
9807c478bd9Sstevel@tonic-gate 		if (cmd == NFS4ATTR_GETIT) {
9817c478bd9Sstevel@tonic-gate 			na->acl.fattr4_acl_len = vs_ace4.vsa_aclcnt;
9827c478bd9Sstevel@tonic-gate 			/* see case NFS4ATTR_FREEIT for this being freed */
9837c478bd9Sstevel@tonic-gate 			na->acl.fattr4_acl_val = vs_ace4.vsa_aclentp;
9847c478bd9Sstevel@tonic-gate 		} else {
9857c478bd9Sstevel@tonic-gate 			if (na->acl.fattr4_acl_len != vs_ace4.vsa_aclcnt)
9867c478bd9Sstevel@tonic-gate 				error = -1; /* no match */
9877c478bd9Sstevel@tonic-gate 			else if (ln_ace4_cmp(na->acl.fattr4_acl_val,
9887c478bd9Sstevel@tonic-gate 			    vs_ace4.vsa_aclentp,
9897c478bd9Sstevel@tonic-gate 			    vs_ace4.vsa_aclcnt) != 0)
9907c478bd9Sstevel@tonic-gate 				error = -1; /* no match */
9917c478bd9Sstevel@tonic-gate 		}
9927c478bd9Sstevel@tonic-gate 
9937c478bd9Sstevel@tonic-gate 		break;
9947c478bd9Sstevel@tonic-gate 
9957c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
9967c478bd9Sstevel@tonic-gate 		if (sarg->rdattr_error && (vp == NULL)) {
9977c478bd9Sstevel@tonic-gate 			return (-1);
9987c478bd9Sstevel@tonic-gate 		}
9997c478bd9Sstevel@tonic-gate 		ASSERT(vp != NULL);
10007c478bd9Sstevel@tonic-gate 
10017c478bd9Sstevel@tonic-gate 		/* prepare vs_ace4 from fattr4 data */
10027c478bd9Sstevel@tonic-gate 		bzero(&vs_ace4, sizeof (vs_ace4));
10037c478bd9Sstevel@tonic-gate 		vs_ace4.vsa_mask = VSA_ACE | VSA_ACECNT;
10047c478bd9Sstevel@tonic-gate 		vs_ace4.vsa_aclcnt = na->acl.fattr4_acl_len;
10057c478bd9Sstevel@tonic-gate 		vs_ace4.vsa_aclentp = na->acl.fattr4_acl_val;
1006da6c28aaSamw 		vs_ace4.vsa_aclentsz = vs_ace4.vsa_aclcnt * sizeof (ace_t);
10077c478bd9Sstevel@tonic-gate 		/* make sure we have correct owner/group */
10087c478bd9Sstevel@tonic-gate 		if ((vap->va_mask & (AT_UID | AT_GID)) !=
10097c478bd9Sstevel@tonic-gate 		    (AT_UID | AT_GID)) {
10107c478bd9Sstevel@tonic-gate 			vap = &va;
10117c478bd9Sstevel@tonic-gate 			vap->va_mask = AT_UID | AT_GID;
10127c478bd9Sstevel@tonic-gate 			status = rfs4_vop_getattr(vp,
10137c478bd9Sstevel@tonic-gate 			    vap, 0, sarg->cs->cr);
10147c478bd9Sstevel@tonic-gate 			if (status != NFS4_OK)
10157c478bd9Sstevel@tonic-gate 				return (geterrno4(status));
10167c478bd9Sstevel@tonic-gate 		}
10177c478bd9Sstevel@tonic-gate 
10187c478bd9Sstevel@tonic-gate 		/* see which ACLs the fs supports */
10197c478bd9Sstevel@tonic-gate 		error = VOP_PATHCONF(vp, _PC_ACL_ENABLED, &whichacl,
1020da6c28aaSamw 		    sarg->cs->cr, NULL);
10217c478bd9Sstevel@tonic-gate 		if (error != 0) {
10227c478bd9Sstevel@tonic-gate 			/*
10237c478bd9Sstevel@tonic-gate 			 * If we got an error, then the filesystem
10247c478bd9Sstevel@tonic-gate 			 * likely does not understand the _PC_ACL_ENABLED
10257c478bd9Sstevel@tonic-gate 			 * pathconf.  In this case, we fall back to trying
10267c478bd9Sstevel@tonic-gate 			 * POSIX-draft (aka UFS-style) ACLs, since that's
10277c478bd9Sstevel@tonic-gate 			 * the behavior used by earlier version of NFS.
10287c478bd9Sstevel@tonic-gate 			 */
10297c478bd9Sstevel@tonic-gate 			error = 0;
10307c478bd9Sstevel@tonic-gate 			whichacl = _ACL_ACLENT_ENABLED;
10317c478bd9Sstevel@tonic-gate 		}
10327c478bd9Sstevel@tonic-gate 
10337c478bd9Sstevel@tonic-gate 		if (!(whichacl & (_ACL_ACLENT_ENABLED | _ACL_ACE_ENABLED))) {
10347c478bd9Sstevel@tonic-gate 			/*
10357c478bd9Sstevel@tonic-gate 			 * If the file system supports neither ACE nor
10367c478bd9Sstevel@tonic-gate 			 * ACLENT ACLs we will fall back to UFS-style ACLs
10377c478bd9Sstevel@tonic-gate 			 * like we did above if there was an error upon
10387c478bd9Sstevel@tonic-gate 			 * calling VOP_PATHCONF.
10397c478bd9Sstevel@tonic-gate 			 *
10407c478bd9Sstevel@tonic-gate 			 * ACE and ACLENT type ACLs are the only interfaces
10417c478bd9Sstevel@tonic-gate 			 * supported thus far.  If any other bits are set on
10427c478bd9Sstevel@tonic-gate 			 * 'whichacl' upon return from VOP_PATHCONF, we will
10437c478bd9Sstevel@tonic-gate 			 * ignore them.
10447c478bd9Sstevel@tonic-gate 			 */
10457c478bd9Sstevel@tonic-gate 			whichacl = _ACL_ACLENT_ENABLED;
10467c478bd9Sstevel@tonic-gate 		}
10477c478bd9Sstevel@tonic-gate 
10487c478bd9Sstevel@tonic-gate 		if (whichacl & _ACL_ACE_ENABLED) {
10497c478bd9Sstevel@tonic-gate 			error = vs_ace4_to_acet(&vs_ace4, &vs_native,
1050e913d9ecSLisa Week 			    vap->va_uid, vap->va_gid, TRUE);
10517c478bd9Sstevel@tonic-gate 			if (error != 0)
10527c478bd9Sstevel@tonic-gate 				break;
10537c478bd9Sstevel@tonic-gate 			(void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL);
10547c478bd9Sstevel@tonic-gate 			error = VOP_SETSECATTR(vp, &vs_native,
1055da6c28aaSamw 			    0, sarg->cs->cr, NULL);
10567c478bd9Sstevel@tonic-gate 			VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL);
10577c478bd9Sstevel@tonic-gate 			vs_acet_destroy(&vs_native);
10587c478bd9Sstevel@tonic-gate 		} else if (whichacl & _ACL_ACLENT_ENABLED) {
10597c478bd9Sstevel@tonic-gate 			error = vs_ace4_to_aent(&vs_ace4, &vs_native,
1060e913d9ecSLisa Week 			    vap->va_uid, vap->va_gid, vp->v_type == VDIR, TRUE);
10617c478bd9Sstevel@tonic-gate 			if (error != 0)
10627c478bd9Sstevel@tonic-gate 				break;
10637c478bd9Sstevel@tonic-gate 			(void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL);
10647c478bd9Sstevel@tonic-gate 			error = VOP_SETSECATTR(vp, &vs_native,
1065da6c28aaSamw 			    0, sarg->cs->cr, NULL);
10667c478bd9Sstevel@tonic-gate 			VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL);
10677c478bd9Sstevel@tonic-gate 			vs_aent_destroy(&vs_native);
10687c478bd9Sstevel@tonic-gate 		}
10697c478bd9Sstevel@tonic-gate 		break;
10707c478bd9Sstevel@tonic-gate 
10717c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
10727c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_GETIT) {
10737c478bd9Sstevel@tonic-gate 			vs_ace4.vsa_mask = VSA_ACE | VSA_ACECNT;
10747c478bd9Sstevel@tonic-gate 			vs_ace4.vsa_aclcnt = na->acl.fattr4_acl_len;
10757c478bd9Sstevel@tonic-gate 			vs_ace4.vsa_aclentp = na->acl.fattr4_acl_val;
10767c478bd9Sstevel@tonic-gate 			vs_ace4_destroy(&vs_ace4);
10777c478bd9Sstevel@tonic-gate 		}
10787c478bd9Sstevel@tonic-gate 		break;
10797c478bd9Sstevel@tonic-gate 	}
10807c478bd9Sstevel@tonic-gate 
10817c478bd9Sstevel@tonic-gate 	return (error);
10827c478bd9Sstevel@tonic-gate }
10837c478bd9Sstevel@tonic-gate 
10847c478bd9Sstevel@tonic-gate /* ARGSUSED */
10857c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_aclsupport(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)10867c478bd9Sstevel@tonic-gate rfs4_fattr4_aclsupport(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
10874a695956SMarcel Telka     union nfs4_attr_u *na)
10887c478bd9Sstevel@tonic-gate {
10897c478bd9Sstevel@tonic-gate 	int error = 0;
10907c478bd9Sstevel@tonic-gate 
10917c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
10927c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
10937c478bd9Sstevel@tonic-gate 
10947c478bd9Sstevel@tonic-gate 	switch (cmd) {
10957c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
10967c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
10977c478bd9Sstevel@tonic-gate 			error = EINVAL;
10987c478bd9Sstevel@tonic-gate 		break;	/* supported */
10997c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
11007c478bd9Sstevel@tonic-gate 		na->aclsupport = ACL4_SUPPORT_ALLOW_ACL |
11017c478bd9Sstevel@tonic-gate 		    ACL4_SUPPORT_DENY_ACL;
11027c478bd9Sstevel@tonic-gate 		break;
11037c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
11047c478bd9Sstevel@tonic-gate 		error = EINVAL;
11057c478bd9Sstevel@tonic-gate 		break;
11067c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
11077c478bd9Sstevel@tonic-gate 		if (na->aclsupport != (ACL4_SUPPORT_ALLOW_ACL |
11087c478bd9Sstevel@tonic-gate 		    ACL4_SUPPORT_DENY_ACL))
11097c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
11107c478bd9Sstevel@tonic-gate 		break;
11117c478bd9Sstevel@tonic-gate 	}
11127c478bd9Sstevel@tonic-gate 
11137c478bd9Sstevel@tonic-gate 	return (error);
11147c478bd9Sstevel@tonic-gate }
11157c478bd9Sstevel@tonic-gate 
11167c478bd9Sstevel@tonic-gate /* ARGSUSED */
11177c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_archive(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)11187c478bd9Sstevel@tonic-gate rfs4_fattr4_archive(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
11194a695956SMarcel Telka     union nfs4_attr_u *na)
11207c478bd9Sstevel@tonic-gate {
11217c478bd9Sstevel@tonic-gate 	return (ENOTSUP);
11227c478bd9Sstevel@tonic-gate }
11237c478bd9Sstevel@tonic-gate 
11247c478bd9Sstevel@tonic-gate /* ARGSUSED */
11257c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_cansettime(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)11267c478bd9Sstevel@tonic-gate rfs4_fattr4_cansettime(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
11274a695956SMarcel Telka     union nfs4_attr_u *na)
11287c478bd9Sstevel@tonic-gate {
11297c478bd9Sstevel@tonic-gate 	int error = 0;
11307c478bd9Sstevel@tonic-gate 
11317c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
11327c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
11337c478bd9Sstevel@tonic-gate 
11347c478bd9Sstevel@tonic-gate 	switch (cmd) {
11357c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
11367c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
11377c478bd9Sstevel@tonic-gate 			error = EINVAL;
11387c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
11397c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
11407c478bd9Sstevel@tonic-gate 		na->cansettime = TRUE;
11417c478bd9Sstevel@tonic-gate 		break;
11427c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
11437c478bd9Sstevel@tonic-gate 		/*
11447c478bd9Sstevel@tonic-gate 		 * read-only attr
11457c478bd9Sstevel@tonic-gate 		 */
11467c478bd9Sstevel@tonic-gate 		error = EINVAL;
11477c478bd9Sstevel@tonic-gate 		break;
11487c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
11497c478bd9Sstevel@tonic-gate 		if (!na->cansettime)
11507c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
11517c478bd9Sstevel@tonic-gate 		break;
11527c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
11537c478bd9Sstevel@tonic-gate 		break;
11547c478bd9Sstevel@tonic-gate 	}
11557c478bd9Sstevel@tonic-gate 	return (error);
11567c478bd9Sstevel@tonic-gate }
11577c478bd9Sstevel@tonic-gate 
11587c478bd9Sstevel@tonic-gate /*
11597c478bd9Sstevel@tonic-gate  * XXX - need VOP extension to ask file system (e.g. pcfs) if it supports
1160da6c28aaSamw  * case insensitive.
11617c478bd9Sstevel@tonic-gate  */
11627c478bd9Sstevel@tonic-gate /* ARGSUSED */
11637c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_case_insensitive(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)11647c478bd9Sstevel@tonic-gate rfs4_fattr4_case_insensitive(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
11654a695956SMarcel Telka     union nfs4_attr_u *na)
11667c478bd9Sstevel@tonic-gate {
11677c478bd9Sstevel@tonic-gate 	int error = 0;
11687c478bd9Sstevel@tonic-gate 
11697c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
11707c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
11717c478bd9Sstevel@tonic-gate 
11727c478bd9Sstevel@tonic-gate 	switch (cmd) {
11737c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
11747c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
11757c478bd9Sstevel@tonic-gate 			error = EINVAL;
11767c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
11777c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
11787c478bd9Sstevel@tonic-gate 		na->case_insensitive = FALSE;
11797c478bd9Sstevel@tonic-gate 		break;
11807c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
11817c478bd9Sstevel@tonic-gate 		/*
11827c478bd9Sstevel@tonic-gate 		 * read-only attr
11837c478bd9Sstevel@tonic-gate 		 */
11847c478bd9Sstevel@tonic-gate 		error = EINVAL;
11857c478bd9Sstevel@tonic-gate 		break;
11867c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
11877c478bd9Sstevel@tonic-gate 		if (!na->case_insensitive)
11887c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
11897c478bd9Sstevel@tonic-gate 		break;
11907c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
11917c478bd9Sstevel@tonic-gate 		break;
11927c478bd9Sstevel@tonic-gate 	}
11937c478bd9Sstevel@tonic-gate 	return (error);
11947c478bd9Sstevel@tonic-gate }
11957c478bd9Sstevel@tonic-gate 
11967c478bd9Sstevel@tonic-gate /* ARGSUSED */
11977c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_case_preserving(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)11987c478bd9Sstevel@tonic-gate rfs4_fattr4_case_preserving(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
11994a695956SMarcel Telka     union nfs4_attr_u *na)
12007c478bd9Sstevel@tonic-gate {
12017c478bd9Sstevel@tonic-gate 	int error = 0;
12027c478bd9Sstevel@tonic-gate 
12037c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
12047c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
12057c478bd9Sstevel@tonic-gate 
12067c478bd9Sstevel@tonic-gate 	switch (cmd) {
12077c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
12087c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
12097c478bd9Sstevel@tonic-gate 			error = EINVAL;
12107c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
12117c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
12127c478bd9Sstevel@tonic-gate 		na->case_preserving = TRUE;
12137c478bd9Sstevel@tonic-gate 		break;
12147c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
12157c478bd9Sstevel@tonic-gate 		/*
12167c478bd9Sstevel@tonic-gate 		 * read-only attr
12177c478bd9Sstevel@tonic-gate 		 */
12187c478bd9Sstevel@tonic-gate 		error = EINVAL;
12197c478bd9Sstevel@tonic-gate 		break;
12207c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
12217c478bd9Sstevel@tonic-gate 		if (!na->case_preserving)
12227c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
12237c478bd9Sstevel@tonic-gate 		break;
12247c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
12257c478bd9Sstevel@tonic-gate 		break;
12267c478bd9Sstevel@tonic-gate 	}
12277c478bd9Sstevel@tonic-gate 	return (error);
12287c478bd9Sstevel@tonic-gate }
12297c478bd9Sstevel@tonic-gate 
12307c478bd9Sstevel@tonic-gate /* fattr4_chown_restricted should reall be fattr4_chown_allowed */
12317c478bd9Sstevel@tonic-gate /* ARGSUSED */
12327c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_chown_restricted(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)12337c478bd9Sstevel@tonic-gate rfs4_fattr4_chown_restricted(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
12344a695956SMarcel Telka     union nfs4_attr_u *na)
12357c478bd9Sstevel@tonic-gate {
12367c478bd9Sstevel@tonic-gate 	int error = 0;
12377c478bd9Sstevel@tonic-gate 	ulong_t val;
12387c478bd9Sstevel@tonic-gate 
12397c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
12407c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
12417c478bd9Sstevel@tonic-gate 
12427c478bd9Sstevel@tonic-gate 	switch (cmd) {
12437c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
12447c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
12457c478bd9Sstevel@tonic-gate 			error = EINVAL;
12467c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
12477c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
12487c478bd9Sstevel@tonic-gate 		if (sarg->rdattr_error && (sarg->cs->vp == NULL)) {
12497c478bd9Sstevel@tonic-gate 			error = -1;	/* may be okay if rdattr_error */
12507c478bd9Sstevel@tonic-gate 			break;
12517c478bd9Sstevel@tonic-gate 		}
12527c478bd9Sstevel@tonic-gate 		ASSERT(sarg->cs->vp != NULL);
12537c478bd9Sstevel@tonic-gate 		error = VOP_PATHCONF(sarg->cs->vp,
125493aeed83Smarks 		    _PC_CHOWN_RESTRICTED, &val, sarg->cs->cr, NULL);
12557c478bd9Sstevel@tonic-gate 		if (error)
12567c478bd9Sstevel@tonic-gate 			break;
12577c478bd9Sstevel@tonic-gate 
12587c478bd9Sstevel@tonic-gate 		na->chown_restricted = (val == 1);
12597c478bd9Sstevel@tonic-gate 		break;
12607c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
12617c478bd9Sstevel@tonic-gate 		/*
12627c478bd9Sstevel@tonic-gate 		 * read-only attr
12637c478bd9Sstevel@tonic-gate 		 */
12647c478bd9Sstevel@tonic-gate 		error = EINVAL;
12657c478bd9Sstevel@tonic-gate 		break;
12667c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
12677c478bd9Sstevel@tonic-gate 		ASSERT(sarg->cs->vp != NULL);
12687c478bd9Sstevel@tonic-gate 		error = VOP_PATHCONF(sarg->cs->vp,
126993aeed83Smarks 		    _PC_CHOWN_RESTRICTED, &val, sarg->cs->cr, NULL);
12707c478bd9Sstevel@tonic-gate 		if (error)
12717c478bd9Sstevel@tonic-gate 			break;
12727c478bd9Sstevel@tonic-gate 		if (na->chown_restricted != (val == 1))
12737c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
12747c478bd9Sstevel@tonic-gate 		break;
12757c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
12767c478bd9Sstevel@tonic-gate 		break;
12777c478bd9Sstevel@tonic-gate 	}
12787c478bd9Sstevel@tonic-gate 	return (error);
12797c478bd9Sstevel@tonic-gate }
12807c478bd9Sstevel@tonic-gate 
12817c478bd9Sstevel@tonic-gate /* ARGSUSED */
12827c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_fileid(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)12837c478bd9Sstevel@tonic-gate rfs4_fattr4_fileid(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
12844a695956SMarcel Telka     union nfs4_attr_u *na)
12857c478bd9Sstevel@tonic-gate {
12867c478bd9Sstevel@tonic-gate 	int	error = 0;
12877c478bd9Sstevel@tonic-gate 
12887c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
12897c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
12907c478bd9Sstevel@tonic-gate 
12917c478bd9Sstevel@tonic-gate 	switch (cmd) {
12927c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
12937c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
12947c478bd9Sstevel@tonic-gate 			error = EINVAL;
12957c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
12967c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
12977c478bd9Sstevel@tonic-gate 		if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_NODEID)) {
12987c478bd9Sstevel@tonic-gate 			error = -1;	/* may be okay if rdattr_error */
12997c478bd9Sstevel@tonic-gate 			break;
13007c478bd9Sstevel@tonic-gate 		}
13017c478bd9Sstevel@tonic-gate 		ASSERT(sarg->vap->va_mask & AT_NODEID);
13027c478bd9Sstevel@tonic-gate 		na->fileid = sarg->vap->va_nodeid;
13037c478bd9Sstevel@tonic-gate 		break;
13047c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
13057c478bd9Sstevel@tonic-gate 		/*
13067c478bd9Sstevel@tonic-gate 		 * read-only attr
13077c478bd9Sstevel@tonic-gate 		 */
13087c478bd9Sstevel@tonic-gate 		error = EINVAL;
13097c478bd9Sstevel@tonic-gate 		break;
13107c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
13117c478bd9Sstevel@tonic-gate 		ASSERT(sarg->vap->va_mask & AT_NODEID);
13127c478bd9Sstevel@tonic-gate 		if (sarg->vap->va_nodeid != na->fileid)
13137c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
13147c478bd9Sstevel@tonic-gate 		break;
13157c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
13167c478bd9Sstevel@tonic-gate 		break;
13177c478bd9Sstevel@tonic-gate 	}
13187c478bd9Sstevel@tonic-gate 	return (error);
13197c478bd9Sstevel@tonic-gate }
13207c478bd9Sstevel@tonic-gate 
13217c478bd9Sstevel@tonic-gate /* ARGSUSED */
13227c478bd9Sstevel@tonic-gate static int
rfs4_get_mntdfileid(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg)13237c478bd9Sstevel@tonic-gate rfs4_get_mntdfileid(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg)
13247c478bd9Sstevel@tonic-gate {
13257c478bd9Sstevel@tonic-gate 	int error = 0;
13267c478bd9Sstevel@tonic-gate 	vattr_t	*vap, va;
13277c478bd9Sstevel@tonic-gate 	vnode_t *stubvp = NULL, *vp;
13287c478bd9Sstevel@tonic-gate 
13297c478bd9Sstevel@tonic-gate 	vp = sarg->cs->vp;
13307c478bd9Sstevel@tonic-gate 	sarg->mntdfid_set = FALSE;
13317c478bd9Sstevel@tonic-gate 
13320dfe541eSEvan Layton 	/*
13330dfe541eSEvan Layton 	 * VROOT object or zone's root, must untraverse.
13340dfe541eSEvan Layton 	 *
13350dfe541eSEvan Layton 	 * NOTE: Not doing reality checks on curzone vs. compound
13360dfe541eSEvan Layton 	 * state vnode because it will mismatch once at initialization
13370dfe541eSEvan Layton 	 * if a non-global-zone triggers the module load, BUT in that case
13380dfe541eSEvan Layton 	 * the vp is literally "/" which has VROOT set.
13390dfe541eSEvan Layton 	 */
13400dfe541eSEvan Layton 	if ((vp->v_flag & VROOT) || VN_IS_CURZONEROOT(vp)) {
13417c478bd9Sstevel@tonic-gate 
13427c478bd9Sstevel@tonic-gate 		/* extra hold for vp since untraverse might rele */
13437c478bd9Sstevel@tonic-gate 		VN_HOLD(vp);
13440dfe541eSEvan Layton 		stubvp = untraverse(vp, ZONE_ROOTVP());
13457c478bd9Sstevel@tonic-gate 
13467c478bd9Sstevel@tonic-gate 		/*
13470dfe541eSEvan Layton 		 * If vp/stubvp are same, we must be at system-or-zone
13487c478bd9Sstevel@tonic-gate 		 * root because untraverse returned same vp
13497c478bd9Sstevel@tonic-gate 		 * for a VROOT object.  sarg->vap was setup
13507c478bd9Sstevel@tonic-gate 		 * before we got here, so there's no need to do
13517c478bd9Sstevel@tonic-gate 		 * another getattr -- just use the one in sarg.
13527c478bd9Sstevel@tonic-gate 		 */
13537c478bd9Sstevel@tonic-gate 		if (VN_CMP(vp, stubvp)) {
13540dfe541eSEvan Layton 			ASSERT(VN_IS_CURZONEROOT(vp));
13557c478bd9Sstevel@tonic-gate 			vap = sarg->vap;
13567c478bd9Sstevel@tonic-gate 		} else {
13577c478bd9Sstevel@tonic-gate 			va.va_mask = AT_NODEID;
13587c478bd9Sstevel@tonic-gate 			vap = &va;
13597c478bd9Sstevel@tonic-gate 			error = rfs4_vop_getattr(stubvp, vap, 0, sarg->cs->cr);
13607c478bd9Sstevel@tonic-gate 		}
13617c478bd9Sstevel@tonic-gate 
13627c478bd9Sstevel@tonic-gate 		/*
13637c478bd9Sstevel@tonic-gate 		 * Done with stub, time to rele.  If vp and stubvp
13647c478bd9Sstevel@tonic-gate 		 * were the same, then we need to rele either vp or
13657c478bd9Sstevel@tonic-gate 		 * stubvp.  If they weren't the same, then untraverse()
13667c478bd9Sstevel@tonic-gate 		 * already took case of the extra hold on vp, and only
13677c478bd9Sstevel@tonic-gate 		 * the stub needs to be rele'd.  Both cases are handled
13687c478bd9Sstevel@tonic-gate 		 * by unconditionally rele'ing the stub.
13697c478bd9Sstevel@tonic-gate 		 */
13707c478bd9Sstevel@tonic-gate 		VN_RELE(stubvp);
13717c478bd9Sstevel@tonic-gate 	} else
13727c478bd9Sstevel@tonic-gate 		vap = sarg->vap;
13737c478bd9Sstevel@tonic-gate 
13747c478bd9Sstevel@tonic-gate 	/*
13757c478bd9Sstevel@tonic-gate 	 * At this point, vap should contain "correct" AT_NODEID --
13767c478bd9Sstevel@tonic-gate 	 * (for V_ROOT case, nodeid of stub, for non-VROOT case,
13777c478bd9Sstevel@tonic-gate 	 * nodeid of vp).  If error or AT_NODEID not available, then
13787c478bd9Sstevel@tonic-gate 	 * make the obligatory (yet mysterious) rdattr_error
13797c478bd9Sstevel@tonic-gate 	 * check that is so common in the attr code.
13807c478bd9Sstevel@tonic-gate 	 */
13817c478bd9Sstevel@tonic-gate 	if (!error && (vap->va_mask & AT_NODEID)) {
13827c478bd9Sstevel@tonic-gate 		sarg->mounted_on_fileid = vap->va_nodeid;
13837c478bd9Sstevel@tonic-gate 		sarg->mntdfid_set = TRUE;
13847c478bd9Sstevel@tonic-gate 	} else if (sarg->rdattr_error)
13857c478bd9Sstevel@tonic-gate 		error = -1;
13867c478bd9Sstevel@tonic-gate 
13877c478bd9Sstevel@tonic-gate 	/*
13887c478bd9Sstevel@tonic-gate 	 * error describes these cases:
13897c478bd9Sstevel@tonic-gate 	 *	0 : success
13907c478bd9Sstevel@tonic-gate 	 *	-1: failure due to previous attr processing error (rddir only).
13917c478bd9Sstevel@tonic-gate 	 *	* : new attr failure  (if rddir, caller will set rdattr_error)
13927c478bd9Sstevel@tonic-gate 	 */
13937c478bd9Sstevel@tonic-gate 	return (error);
13947c478bd9Sstevel@tonic-gate }
13957c478bd9Sstevel@tonic-gate 
13967c478bd9Sstevel@tonic-gate /* ARGSUSED */
13977c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_mounted_on_fileid(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)13987c478bd9Sstevel@tonic-gate rfs4_fattr4_mounted_on_fileid(nfs4_attr_cmd_t cmd,
13994a695956SMarcel Telka     struct nfs4_svgetit_arg *sarg, union nfs4_attr_u *na)
14007c478bd9Sstevel@tonic-gate {
14017c478bd9Sstevel@tonic-gate 	int	error = 0;
14027c478bd9Sstevel@tonic-gate 
14037c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
14047c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
14057c478bd9Sstevel@tonic-gate 
14067c478bd9Sstevel@tonic-gate 	switch (cmd) {
14077c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
14087c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
14097c478bd9Sstevel@tonic-gate 			error = EINVAL;
14107c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
14117c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
14127c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
14130dfe541eSEvan Layton 		if (!sarg->mntdfid_set)
14147c478bd9Sstevel@tonic-gate 			error = rfs4_get_mntdfileid(cmd, sarg);
14157c478bd9Sstevel@tonic-gate 
14160dfe541eSEvan Layton 		if (!error && sarg->mntdfid_set) {
14177c478bd9Sstevel@tonic-gate 			if (cmd == NFS4ATTR_GETIT)
14187c478bd9Sstevel@tonic-gate 				na->mounted_on_fileid = sarg->mounted_on_fileid;
14197c478bd9Sstevel@tonic-gate 			else
14207c478bd9Sstevel@tonic-gate 				if (na->mounted_on_fileid !=
14217c478bd9Sstevel@tonic-gate 				    sarg->mounted_on_fileid)
14227c478bd9Sstevel@tonic-gate 					error = -1;
14237c478bd9Sstevel@tonic-gate 		}
14247c478bd9Sstevel@tonic-gate 		break;
14257c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
14267c478bd9Sstevel@tonic-gate 		/* read-only attr */
14277c478bd9Sstevel@tonic-gate 		error = EINVAL;
14287c478bd9Sstevel@tonic-gate 		break;
14297c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
14307c478bd9Sstevel@tonic-gate 		break;
14317c478bd9Sstevel@tonic-gate 	}
14327c478bd9Sstevel@tonic-gate 	return (error);
14337c478bd9Sstevel@tonic-gate }
14347c478bd9Sstevel@tonic-gate 
14357c478bd9Sstevel@tonic-gate /* ARGSUSED */
14367c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_files_avail(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)14377c478bd9Sstevel@tonic-gate rfs4_fattr4_files_avail(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
14384a695956SMarcel Telka     union nfs4_attr_u *na)
14397c478bd9Sstevel@tonic-gate {
14407c478bd9Sstevel@tonic-gate 	int	error = 0;
14417c478bd9Sstevel@tonic-gate 
14427c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
14437c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
14447c478bd9Sstevel@tonic-gate 
14457c478bd9Sstevel@tonic-gate 	switch (cmd) {
14467c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
14477c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
14487c478bd9Sstevel@tonic-gate 			error = EINVAL;
14497c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
14507c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
14517c478bd9Sstevel@tonic-gate 		if (sarg->rdattr_error && (sarg->sbp == NULL)) {
14527c478bd9Sstevel@tonic-gate 			error = -1;	/* may be okay if rdattr_error */
14537c478bd9Sstevel@tonic-gate 			break;
14547c478bd9Sstevel@tonic-gate 		}
14557c478bd9Sstevel@tonic-gate 		ASSERT(sarg->sbp != NULL);
14567c478bd9Sstevel@tonic-gate 		na->files_avail = sarg->sbp->f_favail;
14577c478bd9Sstevel@tonic-gate 		break;
14587c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
14597c478bd9Sstevel@tonic-gate 		/*
14607c478bd9Sstevel@tonic-gate 		 * read-only attr
14617c478bd9Sstevel@tonic-gate 		 */
14627c478bd9Sstevel@tonic-gate 		error = EINVAL;
14637c478bd9Sstevel@tonic-gate 		break;
14647c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
14657c478bd9Sstevel@tonic-gate 		ASSERT(sarg->sbp != NULL);
14667c478bd9Sstevel@tonic-gate 		if (sarg->sbp->f_favail != na->files_avail)
14677c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
14687c478bd9Sstevel@tonic-gate 		break;
14697c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
14707c478bd9Sstevel@tonic-gate 		break;
14717c478bd9Sstevel@tonic-gate 	}
14727c478bd9Sstevel@tonic-gate 	return (error);
14737c478bd9Sstevel@tonic-gate }
14747c478bd9Sstevel@tonic-gate 
14757c478bd9Sstevel@tonic-gate /* ARGSUSED */
14767c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_files_free(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)14777c478bd9Sstevel@tonic-gate rfs4_fattr4_files_free(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
14784a695956SMarcel Telka     union nfs4_attr_u *na)
14797c478bd9Sstevel@tonic-gate {
14807c478bd9Sstevel@tonic-gate 	int	error = 0;
14817c478bd9Sstevel@tonic-gate 
14827c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
14837c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
14847c478bd9Sstevel@tonic-gate 
14857c478bd9Sstevel@tonic-gate 	switch (cmd) {
14867c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
14877c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
14887c478bd9Sstevel@tonic-gate 			error = EINVAL;
14897c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
14907c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
14917c478bd9Sstevel@tonic-gate 		if (sarg->rdattr_error && (sarg->sbp == NULL)) {
14927c478bd9Sstevel@tonic-gate 			error = -1;	/* may be okay if rdattr_error */
14937c478bd9Sstevel@tonic-gate 			break;
14947c478bd9Sstevel@tonic-gate 		}
14957c478bd9Sstevel@tonic-gate 		ASSERT(sarg->sbp != NULL);
14967c478bd9Sstevel@tonic-gate 		na->files_free = sarg->sbp->f_ffree;
14977c478bd9Sstevel@tonic-gate 		break;
14987c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
14997c478bd9Sstevel@tonic-gate 		/*
15007c478bd9Sstevel@tonic-gate 		 * read-only attr
15017c478bd9Sstevel@tonic-gate 		 */
15027c478bd9Sstevel@tonic-gate 		error = EINVAL;
15037c478bd9Sstevel@tonic-gate 		break;
15047c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
15057c478bd9Sstevel@tonic-gate 		ASSERT(sarg->sbp != NULL);
15067c478bd9Sstevel@tonic-gate 		if (sarg->sbp->f_ffree != na->files_free)
15077c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
15087c478bd9Sstevel@tonic-gate 		break;
15097c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
15107c478bd9Sstevel@tonic-gate 		break;
15117c478bd9Sstevel@tonic-gate 	}
15127c478bd9Sstevel@tonic-gate 	return (error);
15137c478bd9Sstevel@tonic-gate }
15147c478bd9Sstevel@tonic-gate 
15157c478bd9Sstevel@tonic-gate /* ARGSUSED */
15167c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_files_total(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)15177c478bd9Sstevel@tonic-gate rfs4_fattr4_files_total(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
15184a695956SMarcel Telka     union nfs4_attr_u *na)
15197c478bd9Sstevel@tonic-gate {
15207c478bd9Sstevel@tonic-gate 	int	error = 0;
15217c478bd9Sstevel@tonic-gate 
15227c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
15237c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
15247c478bd9Sstevel@tonic-gate 
15257c478bd9Sstevel@tonic-gate 	switch (cmd) {
15267c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
15277c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
15287c478bd9Sstevel@tonic-gate 			error = EINVAL;
15297c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
15307c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
15317c478bd9Sstevel@tonic-gate 		if (sarg->rdattr_error && (sarg->sbp == NULL)) {
15327c478bd9Sstevel@tonic-gate 			error = -1;	/* may be okay if rdattr_error */
15337c478bd9Sstevel@tonic-gate 			break;
15347c478bd9Sstevel@tonic-gate 		}
15357c478bd9Sstevel@tonic-gate 		ASSERT(sarg->sbp != NULL);
15367c478bd9Sstevel@tonic-gate 		na->files_total = sarg->sbp->f_files;
15377c478bd9Sstevel@tonic-gate 		break;
15387c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
15397c478bd9Sstevel@tonic-gate 		/*
15407c478bd9Sstevel@tonic-gate 		 * read-only attr
15417c478bd9Sstevel@tonic-gate 		 */
15427c478bd9Sstevel@tonic-gate 		error = EINVAL;
15437c478bd9Sstevel@tonic-gate 		break;
15447c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
15457c478bd9Sstevel@tonic-gate 		ASSERT(sarg->sbp != NULL);
15467c478bd9Sstevel@tonic-gate 		if (sarg->sbp->f_files != na->files_total)
15477c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
15487c478bd9Sstevel@tonic-gate 		break;
15497c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
15507c478bd9Sstevel@tonic-gate 		break;
15517c478bd9Sstevel@tonic-gate 	}
15527c478bd9Sstevel@tonic-gate 	return (error);
15537c478bd9Sstevel@tonic-gate }
15547c478bd9Sstevel@tonic-gate 
15552f172c55SRobert Thurlow static void
rfs4_free_pathname4(pathname4 * pn4)15562f172c55SRobert Thurlow rfs4_free_pathname4(pathname4 *pn4)
15572f172c55SRobert Thurlow {
15582f172c55SRobert Thurlow 	int i, len;
15592f172c55SRobert Thurlow 	utf8string *utf8s;
15602f172c55SRobert Thurlow 
15612f172c55SRobert Thurlow 	if (pn4 == NULL || (len = pn4->pathname4_len) == 0 ||
15622f172c55SRobert Thurlow 	    (utf8s = pn4->pathname4_val) == NULL)
15632f172c55SRobert Thurlow 		return;
15642f172c55SRobert Thurlow 
15652f172c55SRobert Thurlow 	for (i = 0; i < len; i++, utf8s++) {
15662f172c55SRobert Thurlow 		if (utf8s->utf8string_val == NULL ||
15672f172c55SRobert Thurlow 		    utf8s->utf8string_len == 0)
15682f172c55SRobert Thurlow 			continue;
15692f172c55SRobert Thurlow 
15702f172c55SRobert Thurlow 		kmem_free(utf8s->utf8string_val, utf8s->utf8string_len);
15712f172c55SRobert Thurlow 		utf8s->utf8string_val = NULL;
15722f172c55SRobert Thurlow 	}
15732f172c55SRobert Thurlow 
15742f172c55SRobert Thurlow 	kmem_free(pn4->pathname4_val,
15752f172c55SRobert Thurlow 	    sizeof (utf8string) * pn4->pathname4_len);
15762f172c55SRobert Thurlow 	pn4->pathname4_val = 0;
15772f172c55SRobert Thurlow }
15782f172c55SRobert Thurlow 
15792f172c55SRobert Thurlow static void
rfs4_free_fs_location4(fs_location4 * fsl4)15802f172c55SRobert Thurlow rfs4_free_fs_location4(fs_location4 *fsl4)
15812f172c55SRobert Thurlow {
15822f172c55SRobert Thurlow 	if (fsl4 == NULL)
15832f172c55SRobert Thurlow 		return;
15842f172c55SRobert Thurlow 
15852f172c55SRobert Thurlow 	rfs4_free_pathname4((pathname4 *)&fsl4->server_len);
15862f172c55SRobert Thurlow 	rfs4_free_pathname4(&fsl4->rootpath);
15872f172c55SRobert Thurlow }
15882f172c55SRobert Thurlow 
15892f172c55SRobert Thurlow void
rfs4_free_fs_locations4(fs_locations4 * fsls4)15902f172c55SRobert Thurlow rfs4_free_fs_locations4(fs_locations4 *fsls4)
15912f172c55SRobert Thurlow {
15922f172c55SRobert Thurlow 	int i, len;
15932f172c55SRobert Thurlow 	fs_location4 *fsl4;
15942f172c55SRobert Thurlow 
15952f172c55SRobert Thurlow 	if (fsls4 == NULL)
15962f172c55SRobert Thurlow 		return;
15972f172c55SRobert Thurlow 
15982f172c55SRobert Thurlow 	/* free fs_root */
15992f172c55SRobert Thurlow 	rfs4_free_pathname4(&fsls4->fs_root);
16002f172c55SRobert Thurlow 
16012f172c55SRobert Thurlow 	if ((len = fsls4->locations_len) == 0 ||
16022f172c55SRobert Thurlow 	    (fsl4 = fsls4->locations_val) == NULL)
16032f172c55SRobert Thurlow 		return;
16042f172c55SRobert Thurlow 
16052f172c55SRobert Thurlow 	/* free fs_location4 */
16062f172c55SRobert Thurlow 	for (i = 0; i < len; i++) {
16072f172c55SRobert Thurlow 		rfs4_free_fs_location4(fsl4);
16082f172c55SRobert Thurlow 		fsl4++;
16092f172c55SRobert Thurlow 	}
16102f172c55SRobert Thurlow 
16112f172c55SRobert Thurlow 	kmem_free(fsls4->locations_val, sizeof (fs_location4) * len);
16122f172c55SRobert Thurlow 	fsls4->locations_val = NULL;
16132f172c55SRobert Thurlow }
16142f172c55SRobert Thurlow 
16157c478bd9Sstevel@tonic-gate /* ARGSUSED */
16167c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_fs_locations(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)16177c478bd9Sstevel@tonic-gate rfs4_fattr4_fs_locations(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
16184a695956SMarcel Telka     union nfs4_attr_u *na)
16197c478bd9Sstevel@tonic-gate {
16202f172c55SRobert Thurlow 	int error = 0;
16212f172c55SRobert Thurlow 	fs_locations4 *fsl;
16222f172c55SRobert Thurlow 
16232f172c55SRobert Thurlow 	if (RFS4_MANDATTR_ONLY)
16242f172c55SRobert Thurlow 		return (ENOTSUP);
16252f172c55SRobert Thurlow 
16262f172c55SRobert Thurlow 	switch (cmd) {
16272f172c55SRobert Thurlow 	case NFS4ATTR_SUPPORTED:
16282f172c55SRobert Thurlow 		if (sarg->op == NFS4ATTR_SETIT || sarg->op == NFS4ATTR_VERIT)
16292f172c55SRobert Thurlow 			error = EINVAL;
16302f172c55SRobert Thurlow 		break;  /* this attr is supported */
16312f172c55SRobert Thurlow 
16322f172c55SRobert Thurlow 	case NFS4ATTR_GETIT:
16330dfe541eSEvan Layton 	{
16340dfe541eSEvan Layton 		kstat_named_t *stat =
16350dfe541eSEvan Layton 		    sarg->cs->exi->exi_ne->ne_globals->svstat[NFS_V4];
16360dfe541eSEvan Layton 
16372f172c55SRobert Thurlow 		fsl = fetch_referral(sarg->cs->vp, sarg->cs->cr);
16382f172c55SRobert Thurlow 		if (fsl == NULL)
1639e073d6a4SDaniil Lunev 			(void) memset(&(na->fs_locations), 0,
1640e073d6a4SDaniil Lunev 			    sizeof (fs_locations4));
16412f172c55SRobert Thurlow 		else {
16422f172c55SRobert Thurlow 			na->fs_locations = *fsl;
16432f172c55SRobert Thurlow 			kmem_free(fsl, sizeof (fs_locations4));
16442f172c55SRobert Thurlow 		}
16450dfe541eSEvan Layton 		stat[NFS_REFERRALS].value.ui64++;
16462f172c55SRobert Thurlow 		break;
16470dfe541eSEvan Layton 	}
16482f172c55SRobert Thurlow 	case NFS4ATTR_FREEIT:
16492f172c55SRobert Thurlow 		if (sarg->op == NFS4ATTR_SETIT || sarg->op == NFS4ATTR_VERIT)
16502f172c55SRobert Thurlow 			error = EINVAL;
16512f172c55SRobert Thurlow 		rfs4_free_fs_locations4(&na->fs_locations);
16522f172c55SRobert Thurlow 		break;
16532f172c55SRobert Thurlow 
16542f172c55SRobert Thurlow 	case NFS4ATTR_SETIT:
16552f172c55SRobert Thurlow 	case NFS4ATTR_VERIT:
16562f172c55SRobert Thurlow 		/*
16572f172c55SRobert Thurlow 		 * read-only attr
16582f172c55SRobert Thurlow 		 */
16592f172c55SRobert Thurlow 		error = EINVAL;
16602f172c55SRobert Thurlow 		break;
16612f172c55SRobert Thurlow 	}
16622f172c55SRobert Thurlow 	return (error);
16637c478bd9Sstevel@tonic-gate }
16647c478bd9Sstevel@tonic-gate 
16657c478bd9Sstevel@tonic-gate /* ARGSUSED */
16667c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_hidden(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)16677c478bd9Sstevel@tonic-gate rfs4_fattr4_hidden(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
16684a695956SMarcel Telka     union nfs4_attr_u *na)
16697c478bd9Sstevel@tonic-gate {
16707c478bd9Sstevel@tonic-gate 	return (ENOTSUP);
16717c478bd9Sstevel@tonic-gate }
16727c478bd9Sstevel@tonic-gate 
16737c478bd9Sstevel@tonic-gate /* ARGSUSED */
16747c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_homogeneous(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)16757c478bd9Sstevel@tonic-gate rfs4_fattr4_homogeneous(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
16764a695956SMarcel Telka     union nfs4_attr_u *na)
16777c478bd9Sstevel@tonic-gate {
16787c478bd9Sstevel@tonic-gate 	int error = 0;
16797c478bd9Sstevel@tonic-gate 
16807c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
16817c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
16827c478bd9Sstevel@tonic-gate 
16837c478bd9Sstevel@tonic-gate 	switch (cmd) {
16847c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
16857c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
16867c478bd9Sstevel@tonic-gate 			error = EINVAL;
16877c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
16887c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
16897c478bd9Sstevel@tonic-gate 		na->homogeneous = TRUE; /* XXX - need a VOP extension */
16907c478bd9Sstevel@tonic-gate 		break;
16917c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
16927c478bd9Sstevel@tonic-gate 		/*
16937c478bd9Sstevel@tonic-gate 		 * read-only attr
16947c478bd9Sstevel@tonic-gate 		 */
16957c478bd9Sstevel@tonic-gate 		error = EINVAL;
16967c478bd9Sstevel@tonic-gate 		break;
16977c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
16987c478bd9Sstevel@tonic-gate 		if (!na->homogeneous)
16997c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
17007c478bd9Sstevel@tonic-gate 		break;
17017c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
17027c478bd9Sstevel@tonic-gate 		break;
17037c478bd9Sstevel@tonic-gate 	}
17047c478bd9Sstevel@tonic-gate 	return (error);
17057c478bd9Sstevel@tonic-gate }
17067c478bd9Sstevel@tonic-gate 
17077c478bd9Sstevel@tonic-gate /* ARGSUSED */
17087c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_maxfilesize(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)17097c478bd9Sstevel@tonic-gate rfs4_fattr4_maxfilesize(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
17104a695956SMarcel Telka     union nfs4_attr_u *na)
17117c478bd9Sstevel@tonic-gate {
17127c478bd9Sstevel@tonic-gate 	int error = 0;
17137c478bd9Sstevel@tonic-gate 	ulong_t val;
17147c478bd9Sstevel@tonic-gate 	fattr4_maxfilesize maxfilesize;
17157c478bd9Sstevel@tonic-gate 
17167c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
17177c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
17187c478bd9Sstevel@tonic-gate 
17197c478bd9Sstevel@tonic-gate 	switch (cmd) {
17207c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
17217c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
17227c478bd9Sstevel@tonic-gate 			error = EINVAL;
17237c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
17247c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
17257c478bd9Sstevel@tonic-gate 		if (sarg->rdattr_error && (sarg->cs->vp == NULL)) {
17267c478bd9Sstevel@tonic-gate 			error = -1;	/* may be okay if rdattr_error */
17277c478bd9Sstevel@tonic-gate 			break;
17287c478bd9Sstevel@tonic-gate 		}
17297c478bd9Sstevel@tonic-gate 		ASSERT(sarg->cs->vp != NULL);
17307c478bd9Sstevel@tonic-gate 		error = VOP_PATHCONF(sarg->cs->vp, _PC_FILESIZEBITS, &val,
173193aeed83Smarks 		    sarg->cs->cr, NULL);
17327c478bd9Sstevel@tonic-gate 		if (error)
17337c478bd9Sstevel@tonic-gate 			break;
1734710f82c5SPiyush Shivam 
1735710f82c5SPiyush Shivam 		/*
1736710f82c5SPiyush Shivam 		 * If the underlying file system does not support
1737710f82c5SPiyush Shivam 		 * _PC_FILESIZEBITS, return a reasonable default. Note that
1738710f82c5SPiyush Shivam 		 * error code on VOP_PATHCONF will be 0, even if the underlying
1739710f82c5SPiyush Shivam 		 * file system does not support _PC_FILESIZEBITS.
1740710f82c5SPiyush Shivam 		 */
1741710f82c5SPiyush Shivam 		if (val == (ulong_t)-1) {
1742710f82c5SPiyush Shivam 			na->maxfilesize = MAXOFF32_T;
1743710f82c5SPiyush Shivam 		} else {
1744710f82c5SPiyush Shivam 			if (val >= (sizeof (uint64_t) * 8))
1745710f82c5SPiyush Shivam 				na->maxfilesize = INT64_MAX;
1746710f82c5SPiyush Shivam 			else
1747710f82c5SPiyush Shivam 				na->maxfilesize = ((1LL << (val - 1)) - 1);
1748710f82c5SPiyush Shivam 		}
17497c478bd9Sstevel@tonic-gate 		break;
17507c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
17517c478bd9Sstevel@tonic-gate 		/*
17527c478bd9Sstevel@tonic-gate 		 * read-only attr
17537c478bd9Sstevel@tonic-gate 		 */
17547c478bd9Sstevel@tonic-gate 		error = EINVAL;
17557c478bd9Sstevel@tonic-gate 		break;
17567c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
17577c478bd9Sstevel@tonic-gate 		ASSERT(sarg->cs->vp != NULL);
17587c478bd9Sstevel@tonic-gate 		error = VOP_PATHCONF(sarg->cs->vp, _PC_FILESIZEBITS, &val,
175993aeed83Smarks 		    sarg->cs->cr, NULL);
17607c478bd9Sstevel@tonic-gate 		if (error)
17617c478bd9Sstevel@tonic-gate 			break;
1762710f82c5SPiyush Shivam 		/*
1763710f82c5SPiyush Shivam 		 * If the underlying file system does not support
1764710f82c5SPiyush Shivam 		 * _PC_FILESIZEBITS, return a reasonable default. Note that
1765710f82c5SPiyush Shivam 		 * error code on VOP_PATHCONF will be 0, even if the underlying
1766710f82c5SPiyush Shivam 		 * file system does not support _PC_FILESIZEBITS.
1767710f82c5SPiyush Shivam 		 */
1768710f82c5SPiyush Shivam 		if (val == (ulong_t)-1) {
1769710f82c5SPiyush Shivam 			maxfilesize = MAXOFF32_T;
1770710f82c5SPiyush Shivam 		} else {
1771710f82c5SPiyush Shivam 			if (val >= (sizeof (uint64_t) * 8))
1772710f82c5SPiyush Shivam 				maxfilesize = INT64_MAX;
1773710f82c5SPiyush Shivam 			else
1774710f82c5SPiyush Shivam 				maxfilesize = ((1LL << (val - 1)) - 1);
1775710f82c5SPiyush Shivam 		}
17767c478bd9Sstevel@tonic-gate 		if (na->maxfilesize != maxfilesize)
17777c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
17787c478bd9Sstevel@tonic-gate 		break;
17797c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
17807c478bd9Sstevel@tonic-gate 		break;
17817c478bd9Sstevel@tonic-gate 	}
17827c478bd9Sstevel@tonic-gate 	return (error);
17837c478bd9Sstevel@tonic-gate }
17847c478bd9Sstevel@tonic-gate 
17857c478bd9Sstevel@tonic-gate /* ARGSUSED */
17867c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_maxlink(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)17877c478bd9Sstevel@tonic-gate rfs4_fattr4_maxlink(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
17884a695956SMarcel Telka     union nfs4_attr_u *na)
17897c478bd9Sstevel@tonic-gate {
17907c478bd9Sstevel@tonic-gate 	int error = 0;
17917c478bd9Sstevel@tonic-gate 	ulong_t val;
17927c478bd9Sstevel@tonic-gate 
17937c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
17947c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
17957c478bd9Sstevel@tonic-gate 
17967c478bd9Sstevel@tonic-gate 	switch (cmd) {
17977c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
17987c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
17997c478bd9Sstevel@tonic-gate 			error = EINVAL;
18007c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
18017c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
18027c478bd9Sstevel@tonic-gate 		if (sarg->rdattr_error && (sarg->cs->vp == NULL)) {
18037c478bd9Sstevel@tonic-gate 			error = -1;	/* may be okay if rdattr_error */
18047c478bd9Sstevel@tonic-gate 			break;
18057c478bd9Sstevel@tonic-gate 		}
18067c478bd9Sstevel@tonic-gate 		ASSERT(sarg->cs->vp != NULL);
18077c478bd9Sstevel@tonic-gate 		error = VOP_PATHCONF(sarg->cs->vp, _PC_LINK_MAX, &val,
180893aeed83Smarks 		    sarg->cs->cr, NULL);
18097c478bd9Sstevel@tonic-gate 		if (error == 0) {
18107c478bd9Sstevel@tonic-gate 			na->maxlink = val;
18117c478bd9Sstevel@tonic-gate 		}
18127c478bd9Sstevel@tonic-gate 		break;
18137c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
18147c478bd9Sstevel@tonic-gate 		/*
18157c478bd9Sstevel@tonic-gate 		 * read-only attr
18167c478bd9Sstevel@tonic-gate 		 */
18177c478bd9Sstevel@tonic-gate 		error = EINVAL;
18187c478bd9Sstevel@tonic-gate 		break;
18197c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
18207c478bd9Sstevel@tonic-gate 		ASSERT(sarg->cs->vp != NULL);
18217c478bd9Sstevel@tonic-gate 		error = VOP_PATHCONF(sarg->cs->vp, _PC_LINK_MAX, &val,
182293aeed83Smarks 		    sarg->cs->cr, NULL);
1823d394a754Sxs 		if (!error && (na->maxlink != (uint32_t)val))
18247c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
18257c478bd9Sstevel@tonic-gate 		break;
18267c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
18277c478bd9Sstevel@tonic-gate 		break;
18287c478bd9Sstevel@tonic-gate 	}
18297c478bd9Sstevel@tonic-gate 	return (error);
18307c478bd9Sstevel@tonic-gate }
18317c478bd9Sstevel@tonic-gate 
18327c478bd9Sstevel@tonic-gate /* ARGSUSED */
18337c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_maxname(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)18347c478bd9Sstevel@tonic-gate rfs4_fattr4_maxname(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
18354a695956SMarcel Telka     union nfs4_attr_u *na)
18367c478bd9Sstevel@tonic-gate {
18377c478bd9Sstevel@tonic-gate 	int error = 0;
18387c478bd9Sstevel@tonic-gate 	ulong_t val;
18397c478bd9Sstevel@tonic-gate 
18407c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
18417c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
18427c478bd9Sstevel@tonic-gate 
18437c478bd9Sstevel@tonic-gate 	switch (cmd) {
18447c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
18457c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
18467c478bd9Sstevel@tonic-gate 			error = EINVAL;
18477c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
18487c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
18497c478bd9Sstevel@tonic-gate 		if (sarg->rdattr_error && (sarg->cs->vp == NULL)) {
18507c478bd9Sstevel@tonic-gate 			error = -1;	/* may be okay if rdattr_error */
18517c478bd9Sstevel@tonic-gate 			break;
18527c478bd9Sstevel@tonic-gate 		}
18537c478bd9Sstevel@tonic-gate 		ASSERT(sarg->cs->vp != NULL);
18547c478bd9Sstevel@tonic-gate 		error = VOP_PATHCONF(sarg->cs->vp, _PC_NAME_MAX, &val,
185593aeed83Smarks 		    sarg->cs->cr, NULL);
18567c478bd9Sstevel@tonic-gate 		if (error == 0) {
18577c478bd9Sstevel@tonic-gate 			na->maxname = val;
18587c478bd9Sstevel@tonic-gate 		}
18597c478bd9Sstevel@tonic-gate 		break;
18607c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
18617c478bd9Sstevel@tonic-gate 		/*
18627c478bd9Sstevel@tonic-gate 		 * read-only attr
18637c478bd9Sstevel@tonic-gate 		 */
18647c478bd9Sstevel@tonic-gate 		error = EINVAL;
18657c478bd9Sstevel@tonic-gate 		break;
18667c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
18677c478bd9Sstevel@tonic-gate 		ASSERT(sarg->cs->vp != NULL);
18687c478bd9Sstevel@tonic-gate 		error = VOP_PATHCONF(sarg->cs->vp, _PC_NAME_MAX, &val,
186993aeed83Smarks 		    sarg->cs->cr, NULL);
18707c478bd9Sstevel@tonic-gate 		if (!error && (na->maxname != val))
18717c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
18727c478bd9Sstevel@tonic-gate 		break;
18737c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
18747c478bd9Sstevel@tonic-gate 		break;
18757c478bd9Sstevel@tonic-gate 	}
18767c478bd9Sstevel@tonic-gate 	return (error);
18777c478bd9Sstevel@tonic-gate }
18787c478bd9Sstevel@tonic-gate 
18797c478bd9Sstevel@tonic-gate /* ARGSUSED */
18807c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_maxread(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)18817c478bd9Sstevel@tonic-gate rfs4_fattr4_maxread(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
18824a695956SMarcel Telka     union nfs4_attr_u *na)
18837c478bd9Sstevel@tonic-gate {
18847c478bd9Sstevel@tonic-gate 	int error = 0;
18857c478bd9Sstevel@tonic-gate 
18867c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
18877c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
18887c478bd9Sstevel@tonic-gate 
18897c478bd9Sstevel@tonic-gate 	switch (cmd) {
18907c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
18917c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
18927c478bd9Sstevel@tonic-gate 			error = EINVAL;
18937c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
18947c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
18957c478bd9Sstevel@tonic-gate 		na->maxread = rfs4_tsize(sarg->cs->req);
18967c478bd9Sstevel@tonic-gate 		break;
18977c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
18987c478bd9Sstevel@tonic-gate 		/*
18997c478bd9Sstevel@tonic-gate 		 * read-only attr
19007c478bd9Sstevel@tonic-gate 		 */
19017c478bd9Sstevel@tonic-gate 		error = EINVAL;
19027c478bd9Sstevel@tonic-gate 		break;
19037c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
19047c478bd9Sstevel@tonic-gate 		if (na->maxread != rfs4_tsize(sarg->cs->req))
19057c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
19067c478bd9Sstevel@tonic-gate 		break;
19077c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
19087c478bd9Sstevel@tonic-gate 		break;
19097c478bd9Sstevel@tonic-gate 	}
19107c478bd9Sstevel@tonic-gate 	return (error);
19117c478bd9Sstevel@tonic-gate }
19127c478bd9Sstevel@tonic-gate 
19137c478bd9Sstevel@tonic-gate /* ARGSUSED */
19147c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_maxwrite(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)19157c478bd9Sstevel@tonic-gate rfs4_fattr4_maxwrite(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
19164a695956SMarcel Telka     union nfs4_attr_u *na)
19177c478bd9Sstevel@tonic-gate {
19187c478bd9Sstevel@tonic-gate 	int error = 0;
19197c478bd9Sstevel@tonic-gate 
19207c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
19217c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
19227c478bd9Sstevel@tonic-gate 
19237c478bd9Sstevel@tonic-gate 	switch (cmd) {
19247c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
19257c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
19267c478bd9Sstevel@tonic-gate 			error = EINVAL;
19277c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
19287c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
19297c478bd9Sstevel@tonic-gate 		na->maxwrite = rfs4_tsize(sarg->cs->req);
19307c478bd9Sstevel@tonic-gate 		break;
19317c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
19327c478bd9Sstevel@tonic-gate 		/*
19337c478bd9Sstevel@tonic-gate 		 * read-only attr
19347c478bd9Sstevel@tonic-gate 		 */
19357c478bd9Sstevel@tonic-gate 		error = EINVAL;
19367c478bd9Sstevel@tonic-gate 		break;
19377c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
19387c478bd9Sstevel@tonic-gate 		if (na->maxwrite != rfs4_tsize(sarg->cs->req))
19397c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
19407c478bd9Sstevel@tonic-gate 		break;
19417c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
19427c478bd9Sstevel@tonic-gate 		break;
19437c478bd9Sstevel@tonic-gate 	}
19447c478bd9Sstevel@tonic-gate 	return (error);
19457c478bd9Sstevel@tonic-gate }
19467c478bd9Sstevel@tonic-gate 
19477c478bd9Sstevel@tonic-gate /* ARGSUSED */
19487c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_mimetype(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)19497c478bd9Sstevel@tonic-gate rfs4_fattr4_mimetype(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
19504a695956SMarcel Telka     union nfs4_attr_u *na)
19517c478bd9Sstevel@tonic-gate {
19527c478bd9Sstevel@tonic-gate 	return (ENOTSUP);
19537c478bd9Sstevel@tonic-gate }
19547c478bd9Sstevel@tonic-gate 
19557c478bd9Sstevel@tonic-gate /* ARGSUSED */
19567c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_mode(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)19577c478bd9Sstevel@tonic-gate rfs4_fattr4_mode(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
19584a695956SMarcel Telka     union nfs4_attr_u *na)
19597c478bd9Sstevel@tonic-gate {
19607c478bd9Sstevel@tonic-gate 	int	error = 0;
19617c478bd9Sstevel@tonic-gate 
19627c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
19637c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
19647c478bd9Sstevel@tonic-gate 
19657c478bd9Sstevel@tonic-gate 	switch (cmd) {
19667c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
19677c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
19687c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
19697c478bd9Sstevel@tonic-gate 		if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_MODE)) {
19707c478bd9Sstevel@tonic-gate 			error = -1;	/* may be okay if rdattr_error */
19717c478bd9Sstevel@tonic-gate 			break;
19727c478bd9Sstevel@tonic-gate 		}
19737c478bd9Sstevel@tonic-gate 		ASSERT(sarg->vap->va_mask & AT_MODE);
19747c478bd9Sstevel@tonic-gate 		na->mode = sarg->vap->va_mode;
19757c478bd9Sstevel@tonic-gate 		break;
19767c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
19777c478bd9Sstevel@tonic-gate 		ASSERT(sarg->vap->va_mask & AT_MODE);
19787c478bd9Sstevel@tonic-gate 		sarg->vap->va_mode = na->mode;
19797c478bd9Sstevel@tonic-gate 		/*
19807c478bd9Sstevel@tonic-gate 		 * If the filesystem is exported with nosuid, then mask off
19817c478bd9Sstevel@tonic-gate 		 * the setuid and setgid bits.
19827c478bd9Sstevel@tonic-gate 		 */
19837c478bd9Sstevel@tonic-gate 		if (sarg->cs->vp->v_type == VREG &&
198493aeed83Smarks 		    (sarg->cs->exi->exi_export.ex_flags & EX_NOSUID))
19857c478bd9Sstevel@tonic-gate 			sarg->vap->va_mode &= ~(VSUID | VSGID);
19867c478bd9Sstevel@tonic-gate 		break;
19877c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
19887c478bd9Sstevel@tonic-gate 		ASSERT(sarg->vap->va_mask & AT_MODE);
19897c478bd9Sstevel@tonic-gate 		if (sarg->vap->va_mode != na->mode)
19907c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
19917c478bd9Sstevel@tonic-gate 		break;
19927c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
19937c478bd9Sstevel@tonic-gate 		break;
19947c478bd9Sstevel@tonic-gate 	}
19957c478bd9Sstevel@tonic-gate 	return (error);
19967c478bd9Sstevel@tonic-gate }
19977c478bd9Sstevel@tonic-gate 
19987c478bd9Sstevel@tonic-gate /* ARGSUSED */
19997c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_no_trunc(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)20007c478bd9Sstevel@tonic-gate rfs4_fattr4_no_trunc(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
20014a695956SMarcel Telka     union nfs4_attr_u *na)
20027c478bd9Sstevel@tonic-gate {
20037c478bd9Sstevel@tonic-gate 	int error = 0;
20047c478bd9Sstevel@tonic-gate 
20057c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
20067c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
20077c478bd9Sstevel@tonic-gate 
20087c478bd9Sstevel@tonic-gate 	switch (cmd) {
20097c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
20107c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
20117c478bd9Sstevel@tonic-gate 			error = EINVAL;
20127c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
20137c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
20147c478bd9Sstevel@tonic-gate 		na->no_trunc = TRUE;
20157c478bd9Sstevel@tonic-gate 		break;
20167c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
20177c478bd9Sstevel@tonic-gate 		/*
20187c478bd9Sstevel@tonic-gate 		 * read-only attr
20197c478bd9Sstevel@tonic-gate 		 */
20207c478bd9Sstevel@tonic-gate 		error = EINVAL;
20217c478bd9Sstevel@tonic-gate 		break;
20227c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
20237c478bd9Sstevel@tonic-gate 		if (!na->no_trunc)
20247c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
20257c478bd9Sstevel@tonic-gate 		break;
20267c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
20277c478bd9Sstevel@tonic-gate 		break;
20287c478bd9Sstevel@tonic-gate 	}
20297c478bd9Sstevel@tonic-gate 	return (error);
20307c478bd9Sstevel@tonic-gate }
20317c478bd9Sstevel@tonic-gate 
20327c478bd9Sstevel@tonic-gate /* ARGSUSED */
20337c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_numlinks(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)20347c478bd9Sstevel@tonic-gate rfs4_fattr4_numlinks(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
20354a695956SMarcel Telka     union nfs4_attr_u *na)
20367c478bd9Sstevel@tonic-gate {
20377c478bd9Sstevel@tonic-gate 	int	error = 0;
20387c478bd9Sstevel@tonic-gate 
20397c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
20407c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
20417c478bd9Sstevel@tonic-gate 
20427c478bd9Sstevel@tonic-gate 	switch (cmd) {
20437c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
20447c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
20457c478bd9Sstevel@tonic-gate 			error = EINVAL;
20467c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
20477c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
20487c478bd9Sstevel@tonic-gate 		if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_NLINK)) {
20497c478bd9Sstevel@tonic-gate 			error = -1;	/* may be okay if rdattr_error */
20507c478bd9Sstevel@tonic-gate 			break;
20517c478bd9Sstevel@tonic-gate 		}
20527c478bd9Sstevel@tonic-gate 		ASSERT(sarg->vap->va_mask & AT_NLINK);
20537c478bd9Sstevel@tonic-gate 		na->numlinks = sarg->vap->va_nlink;
20547c478bd9Sstevel@tonic-gate 		break;
20557c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
20567c478bd9Sstevel@tonic-gate 		/*
20577c478bd9Sstevel@tonic-gate 		 * read-only attr
20587c478bd9Sstevel@tonic-gate 		 */
20597c478bd9Sstevel@tonic-gate 		error = EINVAL;
20607c478bd9Sstevel@tonic-gate 		break;
20617c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
20627c478bd9Sstevel@tonic-gate 		ASSERT(sarg->vap->va_mask & AT_NLINK);
20637c478bd9Sstevel@tonic-gate 		if (sarg->vap->va_nlink != na->numlinks)
20647c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
20657c478bd9Sstevel@tonic-gate 		break;
20667c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
20677c478bd9Sstevel@tonic-gate 		break;
20687c478bd9Sstevel@tonic-gate 	}
20697c478bd9Sstevel@tonic-gate 	return (error);
20707c478bd9Sstevel@tonic-gate }
20717c478bd9Sstevel@tonic-gate 
20727c478bd9Sstevel@tonic-gate /* ARGSUSED */
20737c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_owner(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)20747c478bd9Sstevel@tonic-gate rfs4_fattr4_owner(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
20754a695956SMarcel Telka     union nfs4_attr_u *na)
20767c478bd9Sstevel@tonic-gate {
20777c478bd9Sstevel@tonic-gate 	int	error = 0;
20787c478bd9Sstevel@tonic-gate 	uid_t	uid;
20797c478bd9Sstevel@tonic-gate 
20807c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
20817c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
20827c478bd9Sstevel@tonic-gate 
20837c478bd9Sstevel@tonic-gate 	switch (cmd) {
20847c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
20857c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
20867c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
20877c478bd9Sstevel@tonic-gate 		if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_UID)) {
20887c478bd9Sstevel@tonic-gate 			error = -1;	/* may be okay if rdattr_error */
20897c478bd9Sstevel@tonic-gate 			break;
20907c478bd9Sstevel@tonic-gate 		}
20917c478bd9Sstevel@tonic-gate 		ASSERT(sarg->vap->va_mask & AT_UID);
20927c478bd9Sstevel@tonic-gate 
20937c478bd9Sstevel@tonic-gate 		/*
20947c478bd9Sstevel@tonic-gate 		 * There are well defined polices for what happens on server-
20957c478bd9Sstevel@tonic-gate 		 * side GETATTR when uid to attribute string conversion cannot
20967c478bd9Sstevel@tonic-gate 		 * occur. Please refer to nfs4_idmap.c for details.
20977c478bd9Sstevel@tonic-gate 		 */
20987c478bd9Sstevel@tonic-gate 		error = nfs_idmap_uid_str(sarg->vap->va_uid, &na->owner, TRUE);
20997c478bd9Sstevel@tonic-gate 		switch (error) {
21007c478bd9Sstevel@tonic-gate 		case ECONNREFUSED:
21017c478bd9Sstevel@tonic-gate 			error = NFS4ERR_DELAY;
21027c478bd9Sstevel@tonic-gate 			break;
21037c478bd9Sstevel@tonic-gate 		default:
21047c478bd9Sstevel@tonic-gate 			break;
21057c478bd9Sstevel@tonic-gate 		}
21067c478bd9Sstevel@tonic-gate 		break;
21077c478bd9Sstevel@tonic-gate 
21087c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
21097c478bd9Sstevel@tonic-gate 		ASSERT(sarg->vap->va_mask & AT_UID);
21107c478bd9Sstevel@tonic-gate 
21117c478bd9Sstevel@tonic-gate 		/*
21127c478bd9Sstevel@tonic-gate 		 * There are well defined policies for what happens on server-
21137c478bd9Sstevel@tonic-gate 		 * side SETATTR of 'owner' when a "user@domain" mapping cannot
21147c478bd9Sstevel@tonic-gate 		 * occur. Please refer to nfs4_idmap.c for details.
21157c478bd9Sstevel@tonic-gate 		 *
21167c478bd9Sstevel@tonic-gate 		 * Any other errors, such as the mapping not being found by
2117bbf21555SRichard Lowe 		 * nfsmapid(8), and interrupted clnt_call, etc, will result
21187c478bd9Sstevel@tonic-gate 		 * in NFS4ERR_BADOWNER.
21197c478bd9Sstevel@tonic-gate 		 *
21207c478bd9Sstevel@tonic-gate 		 * XXX need to return consistent errors, perhaps all
21217c478bd9Sstevel@tonic-gate 		 * server side attribute routines should return NFS4ERR*.
21227c478bd9Sstevel@tonic-gate 		 */
21237c478bd9Sstevel@tonic-gate 		error = nfs_idmap_str_uid(&na->owner, &sarg->vap->va_uid, TRUE);
21247c478bd9Sstevel@tonic-gate 		switch (error) {
21257c478bd9Sstevel@tonic-gate 		case NFS4_OK:
21267c478bd9Sstevel@tonic-gate 		case ENOTSUP:
21277c478bd9Sstevel@tonic-gate 			/*
21287c478bd9Sstevel@tonic-gate 			 * Ignore warning that we are the
21297c478bd9Sstevel@tonic-gate 			 * nfsmapid (can't happen on srv)
21307c478bd9Sstevel@tonic-gate 			 */
21317c478bd9Sstevel@tonic-gate 			error = 0;
21327c478bd9Sstevel@tonic-gate 			MSG_PRT_DEBUG = FALSE;
21337c478bd9Sstevel@tonic-gate 			break;
21347c478bd9Sstevel@tonic-gate 
21357c478bd9Sstevel@tonic-gate 		case ECOMM:
21367c478bd9Sstevel@tonic-gate 		case ECONNREFUSED:
21377c478bd9Sstevel@tonic-gate 			if (!MSG_PRT_DEBUG) {
21387c478bd9Sstevel@tonic-gate 				/*
21397c478bd9Sstevel@tonic-gate 				 * printed just once per daemon death,
21407c478bd9Sstevel@tonic-gate 				 * inform the user and then stay silent
21417c478bd9Sstevel@tonic-gate 				 */
21427c478bd9Sstevel@tonic-gate 				cmn_err(CE_WARN, "!Unable to contact "
21437c478bd9Sstevel@tonic-gate 				    "nfsmapid");
21447c478bd9Sstevel@tonic-gate 				MSG_PRT_DEBUG = TRUE;
21457c478bd9Sstevel@tonic-gate 			}
21467c478bd9Sstevel@tonic-gate 			error = NFS4ERR_DELAY;
21477c478bd9Sstevel@tonic-gate 			break;
21487c478bd9Sstevel@tonic-gate 
21497c478bd9Sstevel@tonic-gate 		case EINVAL:
21507c478bd9Sstevel@tonic-gate 			error = NFS4ERR_INVAL;
21517c478bd9Sstevel@tonic-gate 			break;
21527c478bd9Sstevel@tonic-gate 
21537c478bd9Sstevel@tonic-gate 		default:
21547c478bd9Sstevel@tonic-gate 			error = NFS4ERR_BADOWNER;
21557c478bd9Sstevel@tonic-gate 			break;
21567c478bd9Sstevel@tonic-gate 		}
21577c478bd9Sstevel@tonic-gate 		break;
21587c478bd9Sstevel@tonic-gate 
21597c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
21607c478bd9Sstevel@tonic-gate 		ASSERT(sarg->vap->va_mask & AT_UID);
21617c478bd9Sstevel@tonic-gate 		error = nfs_idmap_str_uid(&na->owner, &uid, TRUE);
21627c478bd9Sstevel@tonic-gate 		/*
21637c478bd9Sstevel@tonic-gate 		 * Ignore warning that we are the nfsmapid (can't happen on srv)
21647c478bd9Sstevel@tonic-gate 		 */
21657c478bd9Sstevel@tonic-gate 		if (error == ENOTSUP)
21667c478bd9Sstevel@tonic-gate 			error = 0;
21677c478bd9Sstevel@tonic-gate 		if (error)
21687c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
21697c478bd9Sstevel@tonic-gate 		else if (sarg->vap->va_uid != uid)
21707c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
21717c478bd9Sstevel@tonic-gate 		break;
21727c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
21737c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_GETIT) {
21747c478bd9Sstevel@tonic-gate 			if (na->owner.utf8string_val) {
21757c478bd9Sstevel@tonic-gate 				UTF8STRING_FREE(na->owner)
21767c478bd9Sstevel@tonic-gate 				bzero(&na->owner, sizeof (na->owner));
21777c478bd9Sstevel@tonic-gate 			}
21787c478bd9Sstevel@tonic-gate 		}
21797c478bd9Sstevel@tonic-gate 		break;
21807c478bd9Sstevel@tonic-gate 	}
21817c478bd9Sstevel@tonic-gate 	return (error);
21827c478bd9Sstevel@tonic-gate }
21837c478bd9Sstevel@tonic-gate 
21847c478bd9Sstevel@tonic-gate /* ARGSUSED */
21857c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_owner_group(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)21867c478bd9Sstevel@tonic-gate rfs4_fattr4_owner_group(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
21874a695956SMarcel Telka     union nfs4_attr_u *na)
21887c478bd9Sstevel@tonic-gate {
21897c478bd9Sstevel@tonic-gate 	int	error = 0;
21907c478bd9Sstevel@tonic-gate 	gid_t	gid;
21917c478bd9Sstevel@tonic-gate 
21927c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
21937c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
21947c478bd9Sstevel@tonic-gate 
21957c478bd9Sstevel@tonic-gate 	switch (cmd) {
21967c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
21977c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
21987c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
21997c478bd9Sstevel@tonic-gate 		if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_GID)) {
22007c478bd9Sstevel@tonic-gate 			error = -1;	/* may be okay if rdattr_error */
22017c478bd9Sstevel@tonic-gate 			break;
22027c478bd9Sstevel@tonic-gate 		}
22037c478bd9Sstevel@tonic-gate 		ASSERT(sarg->vap->va_mask & AT_GID);
22047c478bd9Sstevel@tonic-gate 
22057c478bd9Sstevel@tonic-gate 		/*
22067c478bd9Sstevel@tonic-gate 		 * There are well defined polices for what happens on server-
22077c478bd9Sstevel@tonic-gate 		 * side GETATTR when gid to attribute string conversion cannot
22087c478bd9Sstevel@tonic-gate 		 * occur. Please refer to nfs4_idmap.c for details.
22097c478bd9Sstevel@tonic-gate 		 */
22107c478bd9Sstevel@tonic-gate 		error = nfs_idmap_gid_str(sarg->vap->va_gid, &na->owner_group,
22117c478bd9Sstevel@tonic-gate 		    TRUE);
22127c478bd9Sstevel@tonic-gate 		switch (error) {
22137c478bd9Sstevel@tonic-gate 		case ECONNREFUSED:
22147c478bd9Sstevel@tonic-gate 			error = NFS4ERR_DELAY;
22157c478bd9Sstevel@tonic-gate 			break;
22167c478bd9Sstevel@tonic-gate 		default:
22177c478bd9Sstevel@tonic-gate 			break;
22187c478bd9Sstevel@tonic-gate 		}
22197c478bd9Sstevel@tonic-gate 		break;
22207c478bd9Sstevel@tonic-gate 
22217c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
22227c478bd9Sstevel@tonic-gate 		ASSERT(sarg->vap->va_mask & AT_GID);
22237c478bd9Sstevel@tonic-gate 
22247c478bd9Sstevel@tonic-gate 		/*
22257c478bd9Sstevel@tonic-gate 		 * There are well defined policies for what happens on server-
22267c478bd9Sstevel@tonic-gate 		 * side SETATTR of 'owner_group' when a "group@domain" mapping
22277c478bd9Sstevel@tonic-gate 		 * cannot occur. Please refer to nfs4_idmap.c for details.
22287c478bd9Sstevel@tonic-gate 		 *
22297c478bd9Sstevel@tonic-gate 		 * Any other errors, such as the mapping not being found by
2230bbf21555SRichard Lowe 		 * nfsmapid(8), and interrupted clnt_call, etc, will result
22317c478bd9Sstevel@tonic-gate 		 * in NFS4ERR_BADOWNER.
22327c478bd9Sstevel@tonic-gate 		 *
22337c478bd9Sstevel@tonic-gate 		 * XXX need to return consistent errors, perhaps all
22347c478bd9Sstevel@tonic-gate 		 * server side attribute routines should return NFS4ERR*.
22357c478bd9Sstevel@tonic-gate 		 */
22367c478bd9Sstevel@tonic-gate 		error = nfs_idmap_str_gid(&na->owner_group, &sarg->vap->va_gid,
22377c478bd9Sstevel@tonic-gate 		    TRUE);
22387c478bd9Sstevel@tonic-gate 		switch (error) {
22397c478bd9Sstevel@tonic-gate 		case NFS4_OK:
22407c478bd9Sstevel@tonic-gate 		case ENOTSUP:
22417c478bd9Sstevel@tonic-gate 			/*
22427c478bd9Sstevel@tonic-gate 			 * Ignore warning that we are the
22437c478bd9Sstevel@tonic-gate 			 * nfsmapid (can't happen on srv)
22447c478bd9Sstevel@tonic-gate 			 */
22457c478bd9Sstevel@tonic-gate 			error = 0;
22467c478bd9Sstevel@tonic-gate 			MSG_PRT_DEBUG = FALSE;
22477c478bd9Sstevel@tonic-gate 			break;
22487c478bd9Sstevel@tonic-gate 
22497c478bd9Sstevel@tonic-gate 		case ECOMM:
22507c478bd9Sstevel@tonic-gate 		case ECONNREFUSED:
22517c478bd9Sstevel@tonic-gate 			if (!MSG_PRT_DEBUG) {
22527c478bd9Sstevel@tonic-gate 				/*
22537c478bd9Sstevel@tonic-gate 				 * printed just once per daemon death,
22547c478bd9Sstevel@tonic-gate 				 * inform the user and then stay silent
22557c478bd9Sstevel@tonic-gate 				 */
22567c478bd9Sstevel@tonic-gate 				cmn_err(CE_WARN, "!Unable to contact "
22577c478bd9Sstevel@tonic-gate 				    "nfsmapid");
22587c478bd9Sstevel@tonic-gate 				MSG_PRT_DEBUG = TRUE;
22597c478bd9Sstevel@tonic-gate 			}
22607c478bd9Sstevel@tonic-gate 			error = NFS4ERR_DELAY;
22617c478bd9Sstevel@tonic-gate 			break;
22627c478bd9Sstevel@tonic-gate 
22637c478bd9Sstevel@tonic-gate 		case EINVAL:
22647c478bd9Sstevel@tonic-gate 			error = NFS4ERR_INVAL;
22657c478bd9Sstevel@tonic-gate 			break;
22667c478bd9Sstevel@tonic-gate 
22677c478bd9Sstevel@tonic-gate 		default:
22687c478bd9Sstevel@tonic-gate 			error = NFS4ERR_BADOWNER;
22697c478bd9Sstevel@tonic-gate 			break;
22707c478bd9Sstevel@tonic-gate 		}
22717c478bd9Sstevel@tonic-gate 		break;
22727c478bd9Sstevel@tonic-gate 
22737c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
22747c478bd9Sstevel@tonic-gate 		ASSERT(sarg->vap->va_mask & AT_GID);
22757c478bd9Sstevel@tonic-gate 		error = nfs_idmap_str_gid(&na->owner_group, &gid, TRUE);
22767c478bd9Sstevel@tonic-gate 		/*
22777c478bd9Sstevel@tonic-gate 		 * Ignore warning that we are the nfsmapid (can't happen on srv)
22787c478bd9Sstevel@tonic-gate 		 */
22797c478bd9Sstevel@tonic-gate 		if (error == ENOTSUP)
22807c478bd9Sstevel@tonic-gate 			error = 0;
22817c478bd9Sstevel@tonic-gate 		if (error)
22827c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
22837c478bd9Sstevel@tonic-gate 		else if (sarg->vap->va_gid != gid)
22847c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
22857c478bd9Sstevel@tonic-gate 		break;
22867c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
22877c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_GETIT) {
22887c478bd9Sstevel@tonic-gate 			if (na->owner_group.utf8string_val) {
22897c478bd9Sstevel@tonic-gate 				UTF8STRING_FREE(na->owner_group)
22907c478bd9Sstevel@tonic-gate 				bzero(&na->owner_group,
229193aeed83Smarks 				    sizeof (na->owner_group));
22927c478bd9Sstevel@tonic-gate 			}
22937c478bd9Sstevel@tonic-gate 		}
22947c478bd9Sstevel@tonic-gate 		break;
22957c478bd9Sstevel@tonic-gate 	}
22967c478bd9Sstevel@tonic-gate 	return (error);
22977c478bd9Sstevel@tonic-gate }
22987c478bd9Sstevel@tonic-gate 
22997c478bd9Sstevel@tonic-gate /* XXX - quota attributes should be supportable on Solaris 2 */
23007c478bd9Sstevel@tonic-gate /* ARGSUSED */
23017c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_quota_avail_hard(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)23027c478bd9Sstevel@tonic-gate rfs4_fattr4_quota_avail_hard(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
23034a695956SMarcel Telka     union nfs4_attr_u *na)
23047c478bd9Sstevel@tonic-gate {
23057c478bd9Sstevel@tonic-gate 	return (ENOTSUP);
23067c478bd9Sstevel@tonic-gate }
23077c478bd9Sstevel@tonic-gate 
23087c478bd9Sstevel@tonic-gate /* ARGSUSED */
23097c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_quota_avail_soft(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)23107c478bd9Sstevel@tonic-gate rfs4_fattr4_quota_avail_soft(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
23114a695956SMarcel Telka     union nfs4_attr_u *na)
23127c478bd9Sstevel@tonic-gate {
23137c478bd9Sstevel@tonic-gate 	return (ENOTSUP);
23147c478bd9Sstevel@tonic-gate }
23157c478bd9Sstevel@tonic-gate 
23167c478bd9Sstevel@tonic-gate /* ARGSUSED */
23177c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_quota_used(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)23187c478bd9Sstevel@tonic-gate rfs4_fattr4_quota_used(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
23194a695956SMarcel Telka     union nfs4_attr_u *na)
23207c478bd9Sstevel@tonic-gate {
23217c478bd9Sstevel@tonic-gate 	return (ENOTSUP);
23227c478bd9Sstevel@tonic-gate }
23237c478bd9Sstevel@tonic-gate 
23247c478bd9Sstevel@tonic-gate /* ARGSUSED */
23257c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_rawdev(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)23267c478bd9Sstevel@tonic-gate rfs4_fattr4_rawdev(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
23274a695956SMarcel Telka     union nfs4_attr_u *na)
23287c478bd9Sstevel@tonic-gate {
23297c478bd9Sstevel@tonic-gate 	int	error = 0;
23307c478bd9Sstevel@tonic-gate 
23317c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
23327c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
23337c478bd9Sstevel@tonic-gate 
23347c478bd9Sstevel@tonic-gate 	switch (cmd) {
23357c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
23367c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
23377c478bd9Sstevel@tonic-gate 			error = EINVAL;
23387c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
23397c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
23407c478bd9Sstevel@tonic-gate 		if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_RDEV)) {
23417c478bd9Sstevel@tonic-gate 			error = -1;	/* may be okay if rdattr_error */
23427c478bd9Sstevel@tonic-gate 			break;
23437c478bd9Sstevel@tonic-gate 		}
23447c478bd9Sstevel@tonic-gate 		ASSERT(sarg->vap->va_mask & AT_RDEV);
23457c478bd9Sstevel@tonic-gate 		na->rawdev.specdata1 =  (uint32)getmajor(sarg->vap->va_rdev);
23467c478bd9Sstevel@tonic-gate 		na->rawdev.specdata2 =  (uint32)getminor(sarg->vap->va_rdev);
23477c478bd9Sstevel@tonic-gate 		break;
23487c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
23497c478bd9Sstevel@tonic-gate 		/*
23507c478bd9Sstevel@tonic-gate 		 * read-only attr
23517c478bd9Sstevel@tonic-gate 		 */
23527c478bd9Sstevel@tonic-gate 		error = EINVAL;
23537c478bd9Sstevel@tonic-gate 		break;
23547c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
23557c478bd9Sstevel@tonic-gate 		ASSERT(sarg->vap->va_mask & AT_RDEV);
23567c478bd9Sstevel@tonic-gate 		if ((na->rawdev.specdata1 !=
235793aeed83Smarks 		    (uint32)getmajor(sarg->vap->va_rdev)) ||
23587c478bd9Sstevel@tonic-gate 		    (na->rawdev.specdata2 !=
235993aeed83Smarks 		    (uint32)getminor(sarg->vap->va_rdev)))
23607c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
23617c478bd9Sstevel@tonic-gate 		break;
23627c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
23637c478bd9Sstevel@tonic-gate 		break;
23647c478bd9Sstevel@tonic-gate 	}
23657c478bd9Sstevel@tonic-gate 	return (error);
23667c478bd9Sstevel@tonic-gate }
23677c478bd9Sstevel@tonic-gate 
23687c478bd9Sstevel@tonic-gate /* ARGSUSED */
23697c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_space_avail(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)23707c478bd9Sstevel@tonic-gate rfs4_fattr4_space_avail(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
23714a695956SMarcel Telka     union nfs4_attr_u *na)
23727c478bd9Sstevel@tonic-gate {
23737c478bd9Sstevel@tonic-gate 	int	error = 0;
23747c478bd9Sstevel@tonic-gate 
23757c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
23767c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
23777c478bd9Sstevel@tonic-gate 
23787c478bd9Sstevel@tonic-gate 	switch (cmd) {
23797c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
23807c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
23817c478bd9Sstevel@tonic-gate 			error = EINVAL;
23827c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
23837c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
23847c478bd9Sstevel@tonic-gate 		if (sarg->rdattr_error && (sarg->sbp == NULL)) {
23857c478bd9Sstevel@tonic-gate 			error = -1;	/* may be okay if rdattr_error */
23867c478bd9Sstevel@tonic-gate 			break;
23877c478bd9Sstevel@tonic-gate 		}
23887c478bd9Sstevel@tonic-gate 		ASSERT(sarg->sbp != NULL);
23897c478bd9Sstevel@tonic-gate 		if (sarg->sbp->f_bavail != (fsblkcnt64_t)-1) {
23907c478bd9Sstevel@tonic-gate 			na->space_avail =
239193aeed83Smarks 			    (fattr4_space_avail) sarg->sbp->f_frsize *
239293aeed83Smarks 			    (fattr4_space_avail) sarg->sbp->f_bavail;
23937c478bd9Sstevel@tonic-gate 		} else {
23947c478bd9Sstevel@tonic-gate 			na->space_avail =
239593aeed83Smarks 			    (fattr4_space_avail) sarg->sbp->f_bavail;
23967c478bd9Sstevel@tonic-gate 		}
23977c478bd9Sstevel@tonic-gate 		break;
23987c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
23997c478bd9Sstevel@tonic-gate 		/*
24007c478bd9Sstevel@tonic-gate 		 * read-only attr
24017c478bd9Sstevel@tonic-gate 		 */
24027c478bd9Sstevel@tonic-gate 		error = EINVAL;
24037c478bd9Sstevel@tonic-gate 		break;
24047c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
24057c478bd9Sstevel@tonic-gate 		ASSERT(sarg->sbp != NULL);
24067c478bd9Sstevel@tonic-gate 		if (sarg->sbp->f_bavail != na->space_avail)
24077c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
24087c478bd9Sstevel@tonic-gate 		break;
24097c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
24107c478bd9Sstevel@tonic-gate 		break;
24117c478bd9Sstevel@tonic-gate 	}
24127c478bd9Sstevel@tonic-gate 	return (error);
24137c478bd9Sstevel@tonic-gate }
24147c478bd9Sstevel@tonic-gate 
24157c478bd9Sstevel@tonic-gate /* ARGSUSED */
24167c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_space_free(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)24177c478bd9Sstevel@tonic-gate rfs4_fattr4_space_free(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
24184a695956SMarcel Telka     union nfs4_attr_u *na)
24197c478bd9Sstevel@tonic-gate {
24207c478bd9Sstevel@tonic-gate 	int	error = 0;
24217c478bd9Sstevel@tonic-gate 
24227c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
24237c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
24247c478bd9Sstevel@tonic-gate 
24257c478bd9Sstevel@tonic-gate 	switch (cmd) {
24267c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
24277c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
24287c478bd9Sstevel@tonic-gate 			error = EINVAL;
24297c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
24307c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
24317c478bd9Sstevel@tonic-gate 		if (sarg->rdattr_error && (sarg->sbp == NULL)) {
24327c478bd9Sstevel@tonic-gate 			error = -1;	/* may be okay if rdattr_error */
24337c478bd9Sstevel@tonic-gate 			break;
24347c478bd9Sstevel@tonic-gate 		}
24357c478bd9Sstevel@tonic-gate 		ASSERT(sarg->sbp != NULL);
24367c478bd9Sstevel@tonic-gate 		if (sarg->sbp->f_bfree != (fsblkcnt64_t)-1) {
24377c478bd9Sstevel@tonic-gate 			na->space_free =
243893aeed83Smarks 			    (fattr4_space_free) sarg->sbp->f_frsize *
243993aeed83Smarks 			    (fattr4_space_free) sarg->sbp->f_bfree;
24407c478bd9Sstevel@tonic-gate 		} else {
24417c478bd9Sstevel@tonic-gate 			na->space_free =
244293aeed83Smarks 			    (fattr4_space_free) sarg->sbp->f_bfree;
24437c478bd9Sstevel@tonic-gate 		}
24447c478bd9Sstevel@tonic-gate 		break;
24457c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
24467c478bd9Sstevel@tonic-gate 		/*
24477c478bd9Sstevel@tonic-gate 		 * read-only attr
24487c478bd9Sstevel@tonic-gate 		 */
24497c478bd9Sstevel@tonic-gate 		error = EINVAL;
24507c478bd9Sstevel@tonic-gate 		break;
24517c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
24527c478bd9Sstevel@tonic-gate 		ASSERT(sarg->sbp != NULL);
24537c478bd9Sstevel@tonic-gate 		if (sarg->sbp->f_bfree != na->space_free)
24547c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
24557c478bd9Sstevel@tonic-gate 		break;
24567c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
24577c478bd9Sstevel@tonic-gate 		break;
24587c478bd9Sstevel@tonic-gate 	}
24597c478bd9Sstevel@tonic-gate 	return (error);
24607c478bd9Sstevel@tonic-gate }
24617c478bd9Sstevel@tonic-gate 
24627c478bd9Sstevel@tonic-gate /* ARGSUSED */
24637c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_space_total(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)24647c478bd9Sstevel@tonic-gate rfs4_fattr4_space_total(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
24654a695956SMarcel Telka     union nfs4_attr_u *na)
24667c478bd9Sstevel@tonic-gate {
24677c478bd9Sstevel@tonic-gate 	int	error = 0;
24687c478bd9Sstevel@tonic-gate 
24697c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
24707c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
24717c478bd9Sstevel@tonic-gate 
24727c478bd9Sstevel@tonic-gate 	switch (cmd) {
24737c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
24747c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
24757c478bd9Sstevel@tonic-gate 			error = EINVAL;
24767c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
24777c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
24787c478bd9Sstevel@tonic-gate 		if (sarg->rdattr_error_req && (sarg->sbp == NULL)) {
24797c478bd9Sstevel@tonic-gate 			error = -1;	/* may be okay if rdattr_error */
24807c478bd9Sstevel@tonic-gate 			break;
24817c478bd9Sstevel@tonic-gate 		}
24827c478bd9Sstevel@tonic-gate 		ASSERT(sarg->sbp != NULL);
24837c478bd9Sstevel@tonic-gate 		if (sarg->sbp->f_blocks != (fsblkcnt64_t)-1) {
24847c478bd9Sstevel@tonic-gate 			na->space_total =
248593aeed83Smarks 			    (fattr4_space_total) sarg->sbp->f_frsize *
248693aeed83Smarks 			    (fattr4_space_total) sarg->sbp->f_blocks;
24877c478bd9Sstevel@tonic-gate 		} else {
24887c478bd9Sstevel@tonic-gate 			na->space_total =
248993aeed83Smarks 			    (fattr4_space_total) sarg->sbp->f_blocks;
24907c478bd9Sstevel@tonic-gate 		}
24917c478bd9Sstevel@tonic-gate 		break;
24927c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
24937c478bd9Sstevel@tonic-gate 		/*
24947c478bd9Sstevel@tonic-gate 		 * read-only attr
24957c478bd9Sstevel@tonic-gate 		 */
24967c478bd9Sstevel@tonic-gate 		error = EINVAL;
24977c478bd9Sstevel@tonic-gate 		break;
24987c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
24997c478bd9Sstevel@tonic-gate 		ASSERT(sarg->sbp != NULL);
25007c478bd9Sstevel@tonic-gate 		if (sarg->sbp->f_blocks != na->space_total)
25017c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
25027c478bd9Sstevel@tonic-gate 		break;
25037c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
25047c478bd9Sstevel@tonic-gate 		break;
25057c478bd9Sstevel@tonic-gate 	}
25067c478bd9Sstevel@tonic-gate 	return (error);
25077c478bd9Sstevel@tonic-gate }
25087c478bd9Sstevel@tonic-gate 
25097c478bd9Sstevel@tonic-gate /* ARGSUSED */
25107c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_space_used(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)25117c478bd9Sstevel@tonic-gate rfs4_fattr4_space_used(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
25124a695956SMarcel Telka     union nfs4_attr_u *na)
25137c478bd9Sstevel@tonic-gate {
25147c478bd9Sstevel@tonic-gate 	int	error = 0;
25157c478bd9Sstevel@tonic-gate 
25167c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
25177c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
25187c478bd9Sstevel@tonic-gate 
25197c478bd9Sstevel@tonic-gate 	switch (cmd) {
25207c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
25217c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
25227c478bd9Sstevel@tonic-gate 			error = EINVAL;
25237c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
25247c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
25257c478bd9Sstevel@tonic-gate 		if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_NBLOCKS)) {
25267c478bd9Sstevel@tonic-gate 			error = -1;	/* may be okay if rdattr_error */
25277c478bd9Sstevel@tonic-gate 			break;
25287c478bd9Sstevel@tonic-gate 		}
25297c478bd9Sstevel@tonic-gate 		ASSERT(sarg->vap->va_mask & AT_NBLOCKS);
25307c478bd9Sstevel@tonic-gate 		na->space_used =  (fattr4_space_used) DEV_BSIZE *
253193aeed83Smarks 		    (fattr4_space_used) sarg->vap->va_nblocks;
25327c478bd9Sstevel@tonic-gate 		break;
25337c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
25347c478bd9Sstevel@tonic-gate 		/*
25357c478bd9Sstevel@tonic-gate 		 * read-only attr
25367c478bd9Sstevel@tonic-gate 		 */
25377c478bd9Sstevel@tonic-gate 		error = EINVAL;
25387c478bd9Sstevel@tonic-gate 		break;
25397c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
25407c478bd9Sstevel@tonic-gate 		ASSERT(sarg->vap->va_mask & AT_NBLOCKS);
25417c478bd9Sstevel@tonic-gate 		if (sarg->vap->va_nblocks != na->space_used)
25427c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
25437c478bd9Sstevel@tonic-gate 		break;
25447c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
25457c478bd9Sstevel@tonic-gate 		break;
25467c478bd9Sstevel@tonic-gate 	}
25477c478bd9Sstevel@tonic-gate 	return (error);
25487c478bd9Sstevel@tonic-gate }
25497c478bd9Sstevel@tonic-gate 
25507c478bd9Sstevel@tonic-gate /* ARGSUSED */
25517c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_system(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)25527c478bd9Sstevel@tonic-gate rfs4_fattr4_system(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
25534a695956SMarcel Telka     union nfs4_attr_u *na)
25547c478bd9Sstevel@tonic-gate {
25557c478bd9Sstevel@tonic-gate 	return (ENOTSUP);
25567c478bd9Sstevel@tonic-gate }
25577c478bd9Sstevel@tonic-gate 
25587c478bd9Sstevel@tonic-gate /* ARGSUSED */
25597c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_time_access(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)25607c478bd9Sstevel@tonic-gate rfs4_fattr4_time_access(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
25614a695956SMarcel Telka     union nfs4_attr_u *na)
25627c478bd9Sstevel@tonic-gate {
25637c478bd9Sstevel@tonic-gate 	int	error = 0;
25647c478bd9Sstevel@tonic-gate 	timestruc_t atime;
25657c478bd9Sstevel@tonic-gate 
25667c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
25677c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
25687c478bd9Sstevel@tonic-gate 
25697c478bd9Sstevel@tonic-gate 	switch (cmd) {
25707c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
25717c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
25727c478bd9Sstevel@tonic-gate 			error = EINVAL;
25737c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
25747c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
25757c478bd9Sstevel@tonic-gate 		if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_ATIME)) {
25767c478bd9Sstevel@tonic-gate 			error = -1;	/* may be okay if rdattr_error */
25777c478bd9Sstevel@tonic-gate 			break;
25787c478bd9Sstevel@tonic-gate 		}
25797c478bd9Sstevel@tonic-gate 		ASSERT(sarg->vap->va_mask & AT_ATIME);
25807c478bd9Sstevel@tonic-gate 		error = nfs4_time_vton(&sarg->vap->va_atime, &na->time_access);
25817c478bd9Sstevel@tonic-gate 		break;
25827c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
25837c478bd9Sstevel@tonic-gate 		/*
25847c478bd9Sstevel@tonic-gate 		 * read-only attr
25857c478bd9Sstevel@tonic-gate 		 */
25867c478bd9Sstevel@tonic-gate 		error = EINVAL;
25877c478bd9Sstevel@tonic-gate 		break;
25887c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
25897c478bd9Sstevel@tonic-gate 		ASSERT(sarg->vap->va_mask & AT_ATIME);
25907c478bd9Sstevel@tonic-gate 		error = nfs4_time_ntov(&na->time_access, &atime);
25917c478bd9Sstevel@tonic-gate 		if (error)
25927c478bd9Sstevel@tonic-gate 			break;
25937c478bd9Sstevel@tonic-gate 		if (bcmp(&atime, &sarg->vap->va_atime, sizeof (atime)))
25947c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
25957c478bd9Sstevel@tonic-gate 		break;
25967c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
25977c478bd9Sstevel@tonic-gate 		break;
25987c478bd9Sstevel@tonic-gate 	}
25997c478bd9Sstevel@tonic-gate 	return (error);
26007c478bd9Sstevel@tonic-gate }
26017c478bd9Sstevel@tonic-gate 
26027c478bd9Sstevel@tonic-gate /*
26037c478bd9Sstevel@tonic-gate  * XXX - need to support the setting of access time
26047c478bd9Sstevel@tonic-gate  */
26057c478bd9Sstevel@tonic-gate /* ARGSUSED */
26067c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_time_access_set(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)26077c478bd9Sstevel@tonic-gate rfs4_fattr4_time_access_set(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
26084a695956SMarcel Telka     union nfs4_attr_u *na)
26097c478bd9Sstevel@tonic-gate {
26107c478bd9Sstevel@tonic-gate 	int	error = 0;
26117c478bd9Sstevel@tonic-gate 	settime4 *ta;
26127c478bd9Sstevel@tonic-gate 
26137c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
26147c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
26157c478bd9Sstevel@tonic-gate 
26167c478bd9Sstevel@tonic-gate 	switch (cmd) {
26177c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
26187c478bd9Sstevel@tonic-gate 		if ((sarg->op == NFS4ATTR_GETIT) ||
26197c478bd9Sstevel@tonic-gate 		    (sarg->op == NFS4ATTR_VERIT))
26207c478bd9Sstevel@tonic-gate 			error = EINVAL;
26217c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
26227c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
26237c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
26247c478bd9Sstevel@tonic-gate 		/*
26257c478bd9Sstevel@tonic-gate 		 * write only attr
26267c478bd9Sstevel@tonic-gate 		 */
26277c478bd9Sstevel@tonic-gate 		error = EINVAL;
26287c478bd9Sstevel@tonic-gate 		break;
26297c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
26307c478bd9Sstevel@tonic-gate 		ASSERT(sarg->vap->va_mask & AT_ATIME);
26317c478bd9Sstevel@tonic-gate 		/*
26327c478bd9Sstevel@tonic-gate 		 * Set access time (by server or by client)
26337c478bd9Sstevel@tonic-gate 		 */
26347c478bd9Sstevel@tonic-gate 		ta = &na->time_access_set;
26357c478bd9Sstevel@tonic-gate 		if (ta->set_it == SET_TO_CLIENT_TIME4) {
26367c478bd9Sstevel@tonic-gate 			error = nfs4_time_ntov(&ta->time, &sarg->vap->va_atime);
26377c478bd9Sstevel@tonic-gate 		} else if (ta->set_it == SET_TO_SERVER_TIME4) {
26387c478bd9Sstevel@tonic-gate 			gethrestime(&sarg->vap->va_atime);
26397c478bd9Sstevel@tonic-gate 		} else {
26407c478bd9Sstevel@tonic-gate 			error = EINVAL;
26417c478bd9Sstevel@tonic-gate 		}
26427c478bd9Sstevel@tonic-gate 		break;
26437c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
26447c478bd9Sstevel@tonic-gate 		break;
26457c478bd9Sstevel@tonic-gate 	}
26467c478bd9Sstevel@tonic-gate 	return (error);
26477c478bd9Sstevel@tonic-gate }
26487c478bd9Sstevel@tonic-gate 
26497c478bd9Sstevel@tonic-gate /* ARGSUSED */
26507c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_time_backup(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)26517c478bd9Sstevel@tonic-gate rfs4_fattr4_time_backup(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
26524a695956SMarcel Telka     union nfs4_attr_u *na)
26537c478bd9Sstevel@tonic-gate {
26547c478bd9Sstevel@tonic-gate 	return (ENOTSUP);
26557c478bd9Sstevel@tonic-gate }
26567c478bd9Sstevel@tonic-gate 
26577c478bd9Sstevel@tonic-gate /* ARGSUSED */
26587c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_time_create(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)26597c478bd9Sstevel@tonic-gate rfs4_fattr4_time_create(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
26604a695956SMarcel Telka     union nfs4_attr_u *na)
26617c478bd9Sstevel@tonic-gate {
26627c478bd9Sstevel@tonic-gate 	return (ENOTSUP);
26637c478bd9Sstevel@tonic-gate }
26647c478bd9Sstevel@tonic-gate 
26657c478bd9Sstevel@tonic-gate /* ARGSUSED */
26667c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_time_delta(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)26677c478bd9Sstevel@tonic-gate rfs4_fattr4_time_delta(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
26684a695956SMarcel Telka     union nfs4_attr_u *na)
26697c478bd9Sstevel@tonic-gate {
26707c478bd9Sstevel@tonic-gate 	int error = 0;
26717c478bd9Sstevel@tonic-gate 
26727c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
26737c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
26747c478bd9Sstevel@tonic-gate 
26757c478bd9Sstevel@tonic-gate 	switch (cmd) {
26767c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
26777c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
26787c478bd9Sstevel@tonic-gate 			error = EINVAL;
26797c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
26807c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
26817c478bd9Sstevel@tonic-gate 		na->time_delta.seconds = 0;
26827c478bd9Sstevel@tonic-gate 		na->time_delta.nseconds = 1000;
26837c478bd9Sstevel@tonic-gate 		break;
26847c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
26857c478bd9Sstevel@tonic-gate 		/*
26867c478bd9Sstevel@tonic-gate 		 * write only attr
26877c478bd9Sstevel@tonic-gate 		 */
26887c478bd9Sstevel@tonic-gate 		error = EINVAL;
26897c478bd9Sstevel@tonic-gate 		break;
26907c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
26917c478bd9Sstevel@tonic-gate 		if ((na->time_delta.seconds != 0) ||
26927c478bd9Sstevel@tonic-gate 		    (na->time_delta.nseconds != 1000))
26937c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
26947c478bd9Sstevel@tonic-gate 		break;
26957c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
26967c478bd9Sstevel@tonic-gate 		break;
26977c478bd9Sstevel@tonic-gate 	}
26987c478bd9Sstevel@tonic-gate 	return (error);
26997c478bd9Sstevel@tonic-gate }
27007c478bd9Sstevel@tonic-gate 
27017c478bd9Sstevel@tonic-gate /* ARGSUSED */
27027c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_time_metadata(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)27037c478bd9Sstevel@tonic-gate rfs4_fattr4_time_metadata(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
27044a695956SMarcel Telka     union nfs4_attr_u *na)
27057c478bd9Sstevel@tonic-gate {
27067c478bd9Sstevel@tonic-gate 	int	error = 0;
27077c478bd9Sstevel@tonic-gate 	timestruc_t ctime;
27087c478bd9Sstevel@tonic-gate 
27097c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
27107c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
27117c478bd9Sstevel@tonic-gate 
27127c478bd9Sstevel@tonic-gate 	switch (cmd) {
27137c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
27147c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
27157c478bd9Sstevel@tonic-gate 			error = EINVAL;
27167c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
27177c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
27187c478bd9Sstevel@tonic-gate 		if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_CTIME)) {
27197c478bd9Sstevel@tonic-gate 			error = -1;	/* may be okay if rdattr_error */
27207c478bd9Sstevel@tonic-gate 			break;
27217c478bd9Sstevel@tonic-gate 		}
27227c478bd9Sstevel@tonic-gate 		ASSERT(sarg->vap->va_mask & AT_CTIME);
27237c478bd9Sstevel@tonic-gate 		error = nfs4_time_vton(&sarg->vap->va_ctime,
272493aeed83Smarks 		    &na->time_metadata);
27257c478bd9Sstevel@tonic-gate 		break;
27267c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
27277c478bd9Sstevel@tonic-gate 		/*
27287c478bd9Sstevel@tonic-gate 		 * read-only attr
27297c478bd9Sstevel@tonic-gate 		 */
27307c478bd9Sstevel@tonic-gate 		error = EINVAL;
27317c478bd9Sstevel@tonic-gate 		break;
27327c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
27337c478bd9Sstevel@tonic-gate 		ASSERT(sarg->vap->va_mask & AT_CTIME);
27347c478bd9Sstevel@tonic-gate 		error = nfs4_time_ntov(&na->time_metadata, &ctime);
27357c478bd9Sstevel@tonic-gate 		if (error)
27367c478bd9Sstevel@tonic-gate 			break;
27377c478bd9Sstevel@tonic-gate 		if (bcmp(&ctime, &sarg->vap->va_ctime, sizeof (ctime)))
27387c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
27397c478bd9Sstevel@tonic-gate 		break;
27407c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
27417c478bd9Sstevel@tonic-gate 		break;
27427c478bd9Sstevel@tonic-gate 	}
27437c478bd9Sstevel@tonic-gate 	return (error);
27447c478bd9Sstevel@tonic-gate }
27457c478bd9Sstevel@tonic-gate 
27467c478bd9Sstevel@tonic-gate /* ARGSUSED */
27477c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_time_modify(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)27487c478bd9Sstevel@tonic-gate rfs4_fattr4_time_modify(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
27494a695956SMarcel Telka     union nfs4_attr_u *na)
27507c478bd9Sstevel@tonic-gate {
27517c478bd9Sstevel@tonic-gate 	int	error = 0;
27527c478bd9Sstevel@tonic-gate 	timestruc_t mtime;
27537c478bd9Sstevel@tonic-gate 
27547c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
27557c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
27567c478bd9Sstevel@tonic-gate 
27577c478bd9Sstevel@tonic-gate 	switch (cmd) {
27587c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
27597c478bd9Sstevel@tonic-gate 		if (sarg->op == NFS4ATTR_SETIT)
27607c478bd9Sstevel@tonic-gate 			error = EINVAL;
27617c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
27627c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
27637c478bd9Sstevel@tonic-gate 		if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_MTIME)) {
27647c478bd9Sstevel@tonic-gate 			error = -1;	/* may be okay if rdattr_error */
27657c478bd9Sstevel@tonic-gate 			break;
27667c478bd9Sstevel@tonic-gate 		}
27677c478bd9Sstevel@tonic-gate 		ASSERT(sarg->vap->va_mask & AT_MTIME);
27687c478bd9Sstevel@tonic-gate 		error = nfs4_time_vton(&sarg->vap->va_mtime, &na->time_modify);
27697c478bd9Sstevel@tonic-gate 		break;
27707c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
27717c478bd9Sstevel@tonic-gate 		/*
27727c478bd9Sstevel@tonic-gate 		 * read-only attr
27737c478bd9Sstevel@tonic-gate 		 */
27747c478bd9Sstevel@tonic-gate 		error = EINVAL;
27757c478bd9Sstevel@tonic-gate 		break;
27767c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
27777c478bd9Sstevel@tonic-gate 		ASSERT(sarg->vap->va_mask & AT_MTIME);
27787c478bd9Sstevel@tonic-gate 		error = nfs4_time_ntov(&na->time_modify, &mtime);
27797c478bd9Sstevel@tonic-gate 		if (error)
27807c478bd9Sstevel@tonic-gate 			break;
27817c478bd9Sstevel@tonic-gate 		if (bcmp(&mtime, &sarg->vap->va_mtime, sizeof (mtime)))
27827c478bd9Sstevel@tonic-gate 			error = -1;	/* no match */
27837c478bd9Sstevel@tonic-gate 		break;
27847c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
27857c478bd9Sstevel@tonic-gate 		break;
27867c478bd9Sstevel@tonic-gate 	}
27877c478bd9Sstevel@tonic-gate 	return (error);
27887c478bd9Sstevel@tonic-gate }
27897c478bd9Sstevel@tonic-gate 
27907c478bd9Sstevel@tonic-gate /*
27917c478bd9Sstevel@tonic-gate  * XXX - need to add support for setting modify time
27927c478bd9Sstevel@tonic-gate  */
27937c478bd9Sstevel@tonic-gate /* ARGSUSED */
27947c478bd9Sstevel@tonic-gate static int
rfs4_fattr4_time_modify_set(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)27957c478bd9Sstevel@tonic-gate rfs4_fattr4_time_modify_set(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
27964a695956SMarcel Telka     union nfs4_attr_u *na)
27977c478bd9Sstevel@tonic-gate {
27987c478bd9Sstevel@tonic-gate 	int	error = 0;
27997c478bd9Sstevel@tonic-gate 	settime4 *tm;
28007c478bd9Sstevel@tonic-gate 
28017c478bd9Sstevel@tonic-gate 	if (RFS4_MANDATTR_ONLY)
28027c478bd9Sstevel@tonic-gate 		return (ENOTSUP);
28037c478bd9Sstevel@tonic-gate 
28047c478bd9Sstevel@tonic-gate 	switch (cmd) {
28057c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SUPPORTED:
28067c478bd9Sstevel@tonic-gate 		if ((sarg->op == NFS4ATTR_GETIT) ||
28077c478bd9Sstevel@tonic-gate 		    (sarg->op == NFS4ATTR_VERIT))
28087c478bd9Sstevel@tonic-gate 			error = EINVAL;
28097c478bd9Sstevel@tonic-gate 		break;		/* this attr is supported */
28107c478bd9Sstevel@tonic-gate 	case NFS4ATTR_GETIT:
28117c478bd9Sstevel@tonic-gate 	case NFS4ATTR_VERIT:
28127c478bd9Sstevel@tonic-gate 		/*
28137c478bd9Sstevel@tonic-gate 		 * write only attr
28147c478bd9Sstevel@tonic-gate 		 */
28157c478bd9Sstevel@tonic-gate 		error = EINVAL;
28167c478bd9Sstevel@tonic-gate 		break;
28177c478bd9Sstevel@tonic-gate 	case NFS4ATTR_SETIT:
28187c478bd9Sstevel@tonic-gate 		ASSERT(sarg->vap->va_mask & AT_MTIME);
28197c478bd9Sstevel@tonic-gate 		/*
28207c478bd9Sstevel@tonic-gate 		 * Set modify time (by server or by client)
28217c478bd9Sstevel@tonic-gate 		 */
28227c478bd9Sstevel@tonic-gate 		tm = &na->time_modify_set;
28237c478bd9Sstevel@tonic-gate 		if (tm->set_it == SET_TO_CLIENT_TIME4) {
28247c478bd9Sstevel@tonic-gate 			error = nfs4_time_ntov(&tm->time, &sarg->vap->va_mtime);
28257c478bd9Sstevel@tonic-gate 			sarg->flag = ATTR_UTIME;
28267c478bd9Sstevel@tonic-gate 		} else if (tm->set_it == SET_TO_SERVER_TIME4) {
28277c478bd9Sstevel@tonic-gate 			gethrestime(&sarg->vap->va_mtime);
28287c478bd9Sstevel@tonic-gate 		} else {
28297c478bd9Sstevel@tonic-gate 			error = EINVAL;
28307c478bd9Sstevel@tonic-gate 		}
28317c478bd9Sstevel@tonic-gate 		break;
28327c478bd9Sstevel@tonic-gate 	case NFS4ATTR_FREEIT:
28337c478bd9Sstevel@tonic-gate 		break;
28347c478bd9Sstevel@tonic-gate 	}
28357c478bd9Sstevel@tonic-gate 	return (error);
28367c478bd9Sstevel@tonic-gate }
28377c478bd9Sstevel@tonic-gate 
2838*f44e1126SVitaliy Gusev /* ARGSUSED */
2839*f44e1126SVitaliy Gusev static int
rfs4_fattr4_suppattr_exclcreat(nfs4_attr_cmd_t cmd,struct nfs4_svgetit_arg * sarg,union nfs4_attr_u * na)2840*f44e1126SVitaliy Gusev rfs4_fattr4_suppattr_exclcreat(nfs4_attr_cmd_t cmd,
2841*f44e1126SVitaliy Gusev     struct nfs4_svgetit_arg *sarg, union nfs4_attr_u *na)
2842*f44e1126SVitaliy Gusev {
2843*f44e1126SVitaliy Gusev 	int error = 0;
2844*f44e1126SVitaliy Gusev 
2845*f44e1126SVitaliy Gusev 	/* Not supported for nfs4.0 */
2846*f44e1126SVitaliy Gusev 	if (sarg->cs->minorversion == 0)
2847*f44e1126SVitaliy Gusev 		return (ENOTSUP);
2848*f44e1126SVitaliy Gusev 
2849*f44e1126SVitaliy Gusev 	switch (cmd) {
2850*f44e1126SVitaliy Gusev 	case NFS4ATTR_SUPPORTED:
2851*f44e1126SVitaliy Gusev 		if (sarg->op == NFS4ATTR_SETIT)
2852*f44e1126SVitaliy Gusev 			error = EINVAL;
2853*f44e1126SVitaliy Gusev 		break;		/* this attr is supported */
2854*f44e1126SVitaliy Gusev 	case NFS4ATTR_GETIT:
2855*f44e1126SVitaliy Gusev 		na->supp_exclcreat = RFS4_SUPPATTR_EXCLCREAT;
2856*f44e1126SVitaliy Gusev 		break;
2857*f44e1126SVitaliy Gusev 	case NFS4ATTR_SETIT:
2858*f44e1126SVitaliy Gusev 		/*
2859*f44e1126SVitaliy Gusev 		 * read-only attr
2860*f44e1126SVitaliy Gusev 		 */
2861*f44e1126SVitaliy Gusev 		error = EINVAL;
2862*f44e1126SVitaliy Gusev 		break;
2863*f44e1126SVitaliy Gusev 	case NFS4ATTR_VERIT:
2864*f44e1126SVitaliy Gusev 		if (na->supp_exclcreat != RFS4_SUPPATTR_EXCLCREAT)
2865*f44e1126SVitaliy Gusev 			error = -1; /* no match */
2866*f44e1126SVitaliy Gusev 		break;
2867*f44e1126SVitaliy Gusev 	case NFS4ATTR_FREEIT:
2868*f44e1126SVitaliy Gusev 		break;
2869*f44e1126SVitaliy Gusev 	}
2870*f44e1126SVitaliy Gusev 	return (error);
2871*f44e1126SVitaliy Gusev }
28727c478bd9Sstevel@tonic-gate 
28737c478bd9Sstevel@tonic-gate static void
rfs4_ntov_init(void)28747c478bd9Sstevel@tonic-gate rfs4_ntov_init(void)
28757c478bd9Sstevel@tonic-gate {
28767c478bd9Sstevel@tonic-gate 	/* index must be same as corresponding FATTR4_* define */
28777c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[0].sv_getit = rfs4_fattr4_supported_attrs;
28787c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[1].sv_getit = rfs4_fattr4_type;
28797c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[2].sv_getit = rfs4_fattr4_fh_expire_type;
28807c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[3].sv_getit = rfs4_fattr4_change;
28817c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[4].sv_getit = rfs4_fattr4_size;
28827c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[5].sv_getit = rfs4_fattr4_link_support;
28837c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[6].sv_getit = rfs4_fattr4_symlink_support;
28847c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[7].sv_getit = rfs4_fattr4_named_attr;
28857c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[8].sv_getit = rfs4_fattr4_fsid;
28867c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[9].sv_getit = rfs4_fattr4_unique_handles;
28877c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[10].sv_getit = rfs4_fattr4_lease_time;
28887c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[11].sv_getit = rfs4_fattr4_rdattr_error;
28897c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[12].sv_getit = rfs4_fattr4_acl;
28907c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[13].sv_getit = rfs4_fattr4_aclsupport;
28917c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[14].sv_getit = rfs4_fattr4_archive;
28927c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[15].sv_getit = rfs4_fattr4_cansettime;
28937c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[16].sv_getit = rfs4_fattr4_case_insensitive;
28947c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[17].sv_getit = rfs4_fattr4_case_preserving;
28957c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[18].sv_getit = rfs4_fattr4_chown_restricted;
28967c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[19].sv_getit = rfs4_fattr4_filehandle;
28977c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[20].sv_getit = rfs4_fattr4_fileid;
28987c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[21].sv_getit = rfs4_fattr4_files_avail;
28997c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[22].sv_getit = rfs4_fattr4_files_free;
29007c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[23].sv_getit = rfs4_fattr4_files_total;
29017c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[24].sv_getit = rfs4_fattr4_fs_locations;
29027c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[25].sv_getit = rfs4_fattr4_hidden;
29037c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[26].sv_getit = rfs4_fattr4_homogeneous;
29047c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[27].sv_getit = rfs4_fattr4_maxfilesize;
29057c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[28].sv_getit = rfs4_fattr4_maxlink;
29067c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[29].sv_getit = rfs4_fattr4_maxname;
29077c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[30].sv_getit = rfs4_fattr4_maxread;
29087c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[31].sv_getit = rfs4_fattr4_maxwrite;
29097c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[32].sv_getit = rfs4_fattr4_mimetype;
29107c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[33].sv_getit = rfs4_fattr4_mode;
29117c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[34].sv_getit = rfs4_fattr4_no_trunc;
29127c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[35].sv_getit = rfs4_fattr4_numlinks;
29137c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[36].sv_getit = rfs4_fattr4_owner;
29147c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[37].sv_getit = rfs4_fattr4_owner_group;
29157c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[38].sv_getit = rfs4_fattr4_quota_avail_hard;
29167c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[39].sv_getit = rfs4_fattr4_quota_avail_soft;
29177c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[40].sv_getit = rfs4_fattr4_quota_used;
29187c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[41].sv_getit = rfs4_fattr4_rawdev;
29197c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[42].sv_getit = rfs4_fattr4_space_avail;
29207c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[43].sv_getit = rfs4_fattr4_space_free;
29217c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[44].sv_getit = rfs4_fattr4_space_total;
29227c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[45].sv_getit = rfs4_fattr4_space_used;
29237c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[46].sv_getit = rfs4_fattr4_system;
29247c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[47].sv_getit = rfs4_fattr4_time_access;
29257c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[48].sv_getit = rfs4_fattr4_time_access_set;
29267c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[49].sv_getit = rfs4_fattr4_time_backup;
29277c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[50].sv_getit = rfs4_fattr4_time_create;
29287c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[51].sv_getit = rfs4_fattr4_time_delta;
29297c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[52].sv_getit = rfs4_fattr4_time_metadata;
29307c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[53].sv_getit = rfs4_fattr4_time_modify;
29317c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[54].sv_getit = rfs4_fattr4_time_modify_set;
29327c478bd9Sstevel@tonic-gate 	nfs4_ntov_map[55].sv_getit = rfs4_fattr4_mounted_on_fileid;
2933*f44e1126SVitaliy Gusev 	nfs4_ntov_map[56].sv_getit = rfs4_fattr4_suppattr_exclcreat;
29347c478bd9Sstevel@tonic-gate }
2935