X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/39236c6e673c41db228275375ab7fdb0f837b292..eee3565979933af707c711411001ba11fe406a3c:/bsd/nfs/nfs_subs.c diff --git a/bsd/nfs/nfs_subs.c b/bsd/nfs/nfs_subs.c index 2ed209532..8496093a9 100644 --- a/bsd/nfs/nfs_subs.c +++ b/bsd/nfs/nfs_subs.c @@ -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) {