/*
- * Copyright (c) 2000-2013 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2014 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
int isdir;
uint32_t timeo;
- if (!(nmp = NFSTONMP(np)))
+ nmp = NFSTONMP(np);
+ if (nfs_mount_gone(nmp))
return (0);
isdir = vnode_isdir(NFSTOV(np));
struct nfs_vattr *nvap;
struct timeval nowup;
int32_t timeo;
+ struct nfsmount *nmp;
/* Check if the attributes are valid. */
if (!NATTRVALID(np) || ((flags & NGA_ACL) && !NACLVALID(np))) {
return (ENOENT);
}
- /* Verify the cached attributes haven't timed out. */
- timeo = nfs_attrcachetimeout(np);
- microuptime(&nowup);
- if ((nowup.tv_sec - np->n_attrstamp) >= timeo) {
- FSDBG(528, np, 0, 0xffffff02, ENOENT);
- OSAddAtomic64(1, &nfsstats.attrcache_misses);
- return (ENOENT);
- }
- if ((flags & NGA_ACL) && ((nowup.tv_sec - np->n_aclstamp) >= timeo)) {
- FSDBG(528, np, 0, 0xffffff02, ENOENT);
- OSAddAtomic64(1, &nfsstats.attrcache_misses);
- return (ENOENT);
+ nmp = NFSTONMP(np);
+ if (nfs_mount_gone(nmp))
+ return (ENXIO);
+ /*
+ * Verify the cached attributes haven't timed out.
+ * If the server isn't responding, skip the check
+ * and return cached attributes.
+ */
+ if (!nfs_use_cache(nmp)) {
+ timeo = nfs_attrcachetimeout(np);
+ microuptime(&nowup);
+ if ((nowup.tv_sec - np->n_attrstamp) >= timeo) {
+ FSDBG(528, np, 0, 0xffffff02, ENOENT);
+ OSAddAtomic64(1, &nfsstats.attrcache_misses);
+ return (ENOENT);
+ }
+ if ((flags & NGA_ACL) && ((nowup.tv_sec - np->n_aclstamp) >= timeo)) {
+ FSDBG(528, np, 0, 0xffffff02, ENOENT);
+ OSAddAtomic64(1, &nfsstats.attrcache_misses);
+ return (ENOENT);
+ }
}
nvap = &np->n_vattr;
va_end(ap);
}
+/* Is a mount gone away? */
+int
+nfs_mount_gone(struct nfsmount *nmp)
+{
+ return (!nmp || vfs_isforce(nmp->nm_mountp) || (nmp->nm_state & (NFSSTA_FORCE | NFSSTA_DEAD)));
+}
+
+/*
+ * Return some of the more significant mount options
+ * as a string, e.g. "'ro,hard,intr,tcp,vers=3,sec=krb5,deadtimeout=0'
+ */
+int
+nfs_mountopts(struct nfsmount *nmp, char *buf, int buflen)
+{
+ int c;
+
+ c = snprintf(buf, buflen, "%s,%s,%s,%s,vers=%d,sec=%s,%sdeadtimeout=%d",
+ (vfs_flags(nmp->nm_mountp) & MNT_RDONLY) ? "ro" : "rw",
+ NMFLAG(nmp, SOFT) ? "soft" : "hard",
+ NMFLAG(nmp, INTR) ? "intr" : "nointr",
+ nmp->nm_sotype == SOCK_STREAM ? "tcp" : "udp",
+ nmp->nm_vers,
+ nmp->nm_auth == RPCAUTH_KRB5 ? "krb5" :
+ nmp->nm_auth == RPCAUTH_KRB5I ? "krb5i" :
+ nmp->nm_auth == RPCAUTH_KRB5P ? "krb5p" :
+ nmp->nm_auth == RPCAUTH_SYS ? "sys" : "none",
+ nmp->nm_lockmode == NFS_LOCK_MODE_ENABLED ? "locks," :
+ nmp->nm_lockmode == NFS_LOCK_MODE_DISABLED ? "nolocks," :
+ nmp->nm_lockmode == NFS_LOCK_MODE_LOCAL ? "locallocks," : "",
+ nmp->nm_deadtimeout);
+
+ return (c > buflen ? ENOMEM : 0);
+}
+
#endif /* NFSCLIENT */
/*
if (error)
return (error);
+ if (nxna.nxna_addr.ss_len > sizeof(struct sockaddr_storage) ||
+ nxna.nxna_mask.ss_len > sizeof(struct sockaddr_storage) ||
+ nxna.nxna_addr.ss_family > AF_MAX ||
+ nxna.nxna_mask.ss_family > AF_MAX)
+ return (EINVAL);
+
if (nxna.nxna_flags & (NX_MAPROOT|NX_MAPALL)) {
struct posix_cred temp_pcred;
bzero(&temp_pcred, sizeof(temp_pcred));
return (error);
}
+/*
+ * Check if there is a least one export that will allow this address.
+ *
+ * Return 0, if there is an export that will allow this address,
+ * else return EACCES
+ */
+int
+nfsrv_check_exports_allow_address(mbuf_t nam)
+{
+ struct nfs_exportfs *nxfs;
+ struct nfs_export *nx;
+ struct nfs_export_options *nxo;
+
+ if (nam == NULL)
+ return (EACCES);
+
+ lck_rw_lock_shared(&nfsrv_export_rwlock);
+ LIST_FOREACH(nxfs, &nfsrv_exports, nxfs_next) {
+ LIST_FOREACH(nx, &nxfs->nxfs_exports, nx_next) {
+ /* A little optimizing by checking for the default first */
+ if (nx->nx_flags & NX_DEFAULTEXPORT)
+ nxo = &nx->nx_defopt;
+ if (nxo || (nxo = nfsrv_export_lookup(nx, nam)))
+ goto found;
+ }
+ }
+found:
+ lck_rw_done(&nfsrv_export_rwlock);
+
+ return (nxo ? 0 : EACCES);
+}
+
struct nfs_export_options *
nfsrv_export_lookup(struct nfs_export *nx, mbuf_t nam)
{