]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/nfs/nfs_subs.c
xnu-3789.41.3.tar.gz
[apple/xnu.git] / bsd / nfs / nfs_subs.c
index 2ed209532d40a0ab3761fe5ae8501b2a8e11af35..8496093a9fac2230ec36d2b81f5772ba6ac027ea 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2013 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2014 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
@@ -1624,7 +1624,8 @@ nfs_attrcachetimeout(nfsnode_t np)
        int isdir;
        uint32_t timeo;
 
-       if (!(nmp = NFSTONMP(np)))
+       nmp = NFSTONMP(np);
+       if (nfs_mount_gone(nmp))
                return (0);
 
        isdir = vnode_isdir(NFSTOV(np));
@@ -1669,6 +1670,7 @@ nfs_getattrcache(nfsnode_t np, struct nfs_vattr *nvaper, int flags)
        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))) {
@@ -1677,18 +1679,27 @@ nfs_getattrcache(nfsnode_t np, struct nfs_vattr *nvaper, int flags)
                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;
@@ -1997,6 +2008,40 @@ nfs_printf(int facility, int level, const char *fmt, ...)
        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 */
 
 /*
@@ -2482,6 +2527,12 @@ nfsrv_hang_addrlist(struct nfs_export *nx, struct user_nfs_export_args *unxa)
                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));
@@ -3176,6 +3227,38 @@ unlock_out:
        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)
 {