diff options
-rw-r--r-- | sys/conf/files | 5 | ||||
-rw-r--r-- | sys/nfs/nfs_srvsubs.c | 488 | ||||
-rw-r--r-- | sys/nfs/nfs_subs.c | 424 | ||||
-rw-r--r-- | sys/nfs/nfs_var.h | 32 |
4 files changed, 509 insertions, 440 deletions
diff --git a/sys/conf/files b/sys/conf/files index accdb2d9836..60913cd12e3 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,4 +1,4 @@ -# $OpenBSD: files,v 1.737 2024/09/04 07:45:08 jsg Exp $ +# $OpenBSD: files,v 1.738 2024/09/09 03:50:14 jsg Exp $ # $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $ # @(#)files.newconf 7.5 (Berkeley) 5/10/93 @@ -957,11 +957,12 @@ file nfs/krpc_subr.c nfsclient file nfs/nfs_bio.c nfsclient file nfs/nfs_boot.c nfsclient file nfs/nfs_debug.c nfsclient & ddb -file nfs/nfs_node.c nfsclient file nfs/nfs_kq.c nfsclient +file nfs/nfs_node.c nfsclient file nfs/nfs_serv.c nfsserver file nfs/nfs_socket.c nfsserver | nfsclient file nfs/nfs_srvcache.c nfsserver +file nfs/nfs_srvsubs.c nfsserver file nfs/nfs_subs.c nfsserver | nfsclient file nfs/nfs_syscalls.c nfsserver | nfsclient file nfs/nfs_vfsops.c nfsclient diff --git a/sys/nfs/nfs_srvsubs.c b/sys/nfs/nfs_srvsubs.c new file mode 100644 index 00000000000..def0bc7ef6b --- /dev/null +++ b/sys/nfs/nfs_srvsubs.c @@ -0,0 +1,488 @@ +/* $OpenBSD: nfs_srvsubs.c,v 1.1 2024/09/09 03:50:14 jsg Exp $ */ +/* $NetBSD: nfs_subs.c,v 1.27.4.3 1996/07/08 20:34:24 jtc Exp $ */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Macklem at The University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)nfs_subs.c 8.8 (Berkeley) 5/22/95 + */ + + +/* + * These functions support the nfsm_subs.h inline functions and help fiddle + * mbuf chains for the nfs op functions. They do things such as creating the + * rpc header and copying data between mbuf chains and uio lists. + */ +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/mount.h> +#include <sys/vnode.h> +#include <sys/namei.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/pool.h> + +#include <nfs/rpcv2.h> +#include <nfs/nfsproto.h> +#include <nfs/nfs.h> +#include <nfs/xdr_subs.h> +#include <nfs/nfs_var.h> +#include <nfs/nfsm_subs.h> + +#include <netinet/in.h> + +/* Global vars */ +extern u_int32_t nfs_false, nfs_true; +extern const nfstype nfsv2_type[9]; +extern const nfstype nfsv3_type[9]; + +/* + * Set up nameidata for a lookup() call and do it + */ +int +nfs_namei(struct nameidata *ndp, fhandle_t *fhp, int len, + struct nfssvc_sock *slp, struct mbuf *nam, struct mbuf **mdp, + caddr_t *dposp, struct vnode **retdirp, struct proc *p) +{ + int i, rem; + struct mbuf *md; + char *fromcp, *tocp; + struct vnode *dp; + int error, rdonly; + struct componentname *cnp = &ndp->ni_cnd; + + *retdirp = NULL; + cnp->cn_pnbuf = pool_get(&namei_pool, PR_WAITOK); + /* + * Copy the name from the mbuf list to ndp->ni_pnbuf + * and set the various ndp fields appropriately. + */ + fromcp = *dposp; + tocp = cnp->cn_pnbuf; + md = *mdp; + rem = mtod(md, caddr_t) + md->m_len - fromcp; + for (i = 0; i < len; i++) { + while (rem == 0) { + md = md->m_next; + if (md == NULL) { + error = EBADRPC; + goto out; + } + fromcp = mtod(md, caddr_t); + rem = md->m_len; + } + if (*fromcp == '\0' || *fromcp == '/') { + error = EACCES; + goto out; + } + *tocp++ = *fromcp++; + rem--; + } + *tocp = '\0'; + *mdp = md; + *dposp = fromcp; + len = nfsm_padlen(len); + if (len > 0) { + if (rem >= len) + *dposp += len; + else if ((error = nfs_adv(mdp, dposp, len, rem)) != 0) + goto out; + } + ndp->ni_pathlen = tocp - cnp->cn_pnbuf; + cnp->cn_nameptr = cnp->cn_pnbuf; + /* + * Extract and set starting directory. + */ + error = nfsrv_fhtovp(fhp, 0, &dp, ndp->ni_cnd.cn_cred, slp, + nam, &rdonly); + if (error) + goto out; + if (dp->v_type != VDIR) { + vrele(dp); + error = ENOTDIR; + goto out; + } + vref(dp); + *retdirp = dp; + ndp->ni_startdir = dp; + if (rdonly) + cnp->cn_flags |= (NOCROSSMOUNT | RDONLY); + else + cnp->cn_flags |= NOCROSSMOUNT; + + /* + * And call lookup() to do the real work + */ + cnp->cn_proc = p; + error = vfs_lookup(ndp); + if (error) + goto out; + /* + * Check for encountering a symbolic link + */ + if (cnp->cn_flags & ISSYMLINK) { + if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1) + vput(ndp->ni_dvp); + else + vrele(ndp->ni_dvp); + vput(ndp->ni_vp); + ndp->ni_vp = NULL; + error = EINVAL; + goto out; + } + /* + * Check for saved name request + */ + if (cnp->cn_flags & (SAVENAME | SAVESTART)) { + cnp->cn_flags |= HASBUF; + return (0); + } +out: + pool_put(&namei_pool, cnp->cn_pnbuf); + return (error); +} + +/* + * A fiddled version of m_adj() that ensures null fill to a long + * boundary and only trims off the back end + */ +void +nfsm_adj(struct mbuf *mp, int len, int nul) +{ + struct mbuf *m; + int count, i; + char *cp; + + /* + * Trim from tail. Scan the mbuf chain, + * calculating its length and finding the last mbuf. + * If the adjustment only affects this mbuf, then just + * adjust and return. Otherwise, rescan and truncate + * after the remaining size. + */ + count = 0; + m = mp; + for (;;) { + count += m->m_len; + if (m->m_next == NULL) + break; + m = m->m_next; + } + if (m->m_len > len) { + m->m_len -= len; + if (nul > 0) { + cp = mtod(m, caddr_t)+m->m_len-nul; + for (i = 0; i < nul; i++) + *cp++ = '\0'; + } + return; + } + count -= len; + if (count < 0) + count = 0; + /* + * Correct length for chain is "count". + * Find the mbuf with last data, adjust its length, + * and toss data from remaining mbufs on chain. + */ + for (m = mp; m; m = m->m_next) { + if (m->m_len >= count) { + m->m_len = count; + if (nul > 0) { + cp = mtod(m, caddr_t)+m->m_len-nul; + for (i = 0; i < nul; i++) + *cp++ = '\0'; + } + break; + } + count -= m->m_len; + } + for (m = m->m_next;m;m = m->m_next) + m->m_len = 0; +} + +/* + * Make these non-inline functions, so that the kernel text size + * doesn't get too big... + */ +void +nfsm_srvwcc(struct nfsrv_descript *nfsd, int before_ret, + struct vattr *before_vap, int after_ret, struct vattr *after_vap, + struct nfsm_info *info) +{ + u_int32_t *tl; + + if (before_ret) { + tl = nfsm_build(&info->nmi_mb, NFSX_UNSIGNED); + *tl = nfs_false; + } else { + tl = nfsm_build(&info->nmi_mb, 7 * NFSX_UNSIGNED); + *tl++ = nfs_true; + txdr_hyper(before_vap->va_size, tl); + tl += 2; + txdr_nfsv3time(&(before_vap->va_mtime), tl); + tl += 2; + txdr_nfsv3time(&(before_vap->va_ctime), tl); + } + nfsm_srvpostop_attr(nfsd, after_ret, after_vap, info); +} + +void +nfsm_srvpostop_attr(struct nfsrv_descript *nfsd, int after_ret, + struct vattr *after_vap, struct nfsm_info *info) +{ + u_int32_t *tl; + struct nfs_fattr *fp; + + if (after_ret) { + tl = nfsm_build(&info->nmi_mb, NFSX_UNSIGNED); + *tl = nfs_false; + } else { + tl = nfsm_build(&info->nmi_mb, NFSX_UNSIGNED + NFSX_V3FATTR); + *tl++ = nfs_true; + fp = (struct nfs_fattr *)tl; + nfsm_srvfattr(nfsd, after_vap, fp); + } +} + +void +nfsm_srvfattr(struct nfsrv_descript *nfsd, struct vattr *vap, + struct nfs_fattr *fp) +{ + + fp->fa_nlink = txdr_unsigned(vap->va_nlink); + fp->fa_uid = txdr_unsigned(vap->va_uid); + fp->fa_gid = txdr_unsigned(vap->va_gid); + if (nfsd->nd_flag & ND_NFSV3) { + fp->fa_type = vtonfsv3_type(vap->va_type); + fp->fa_mode = vtonfsv3_mode(vap->va_mode); + txdr_hyper(vap->va_size, &fp->fa3_size); + txdr_hyper(vap->va_bytes, &fp->fa3_used); + fp->fa3_rdev.specdata1 = txdr_unsigned(major(vap->va_rdev)); + fp->fa3_rdev.specdata2 = txdr_unsigned(minor(vap->va_rdev)); + fp->fa3_fsid.nfsuquad[0] = 0; + fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(vap->va_fsid); + txdr_hyper(vap->va_fileid, &fp->fa3_fileid); + txdr_nfsv3time(&vap->va_atime, &fp->fa3_atime); + txdr_nfsv3time(&vap->va_mtime, &fp->fa3_mtime); + txdr_nfsv3time(&vap->va_ctime, &fp->fa3_ctime); + } else { + fp->fa_type = vtonfsv2_type(vap->va_type); + fp->fa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode); + fp->fa2_size = txdr_unsigned(vap->va_size); + fp->fa2_blocksize = txdr_unsigned(vap->va_blocksize); + if (vap->va_type == VFIFO) + fp->fa2_rdev = 0xffffffff; + else + fp->fa2_rdev = txdr_unsigned(vap->va_rdev); + fp->fa2_blocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE); + fp->fa2_fsid = txdr_unsigned(vap->va_fsid); + fp->fa2_fileid = txdr_unsigned((u_int32_t)vap->va_fileid); + txdr_nfsv2time(&vap->va_atime, &fp->fa2_atime); + txdr_nfsv2time(&vap->va_mtime, &fp->fa2_mtime); + txdr_nfsv2time(&vap->va_ctime, &fp->fa2_ctime); + } +} + +/* + * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked) + * - look up fsid in mount list (if not found ret error) + * - get vp and export rights by calling VFS_FHTOVP() and VFS_CHECKEXP() + * - if cred->cr_uid == 0 or MNT_EXPORTANON set it to credanon + * - if not lockflag unlock it with VOP_UNLOCK() + */ +int +nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp, + struct ucred *cred, struct nfssvc_sock *slp, struct mbuf *nam, + int *rdonlyp) +{ + struct mount *mp; + int i; + struct ucred *credanon; + int error, exflags; + struct sockaddr_in *saddr; + + *vpp = NULL; + mp = vfs_getvfs(&fhp->fh_fsid); + + if (!mp) + return (ESTALE); + error = VFS_CHECKEXP(mp, nam, &exflags, &credanon); + if (error) + return (error); + error = VFS_FHTOVP(mp, &fhp->fh_fid, vpp); + if (error) + return (error); + + saddr = mtod(nam, struct sockaddr_in *); + if (saddr->sin_family == AF_INET && + (ntohs(saddr->sin_port) >= IPPORT_RESERVED || + (slp->ns_so->so_type == SOCK_STREAM && ntohs(saddr->sin_port) == 20))) { + vput(*vpp); + return (NFSERR_AUTHERR | AUTH_TOOWEAK); + } + + /* Check/setup credentials. */ + if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) { + cred->cr_uid = credanon->cr_uid; + cred->cr_gid = credanon->cr_gid; + for (i = 0; i < credanon->cr_ngroups && i < NGROUPS_MAX; i++) + cred->cr_groups[i] = credanon->cr_groups[i]; + cred->cr_ngroups = i; + } + if (exflags & MNT_EXRDONLY) + *rdonlyp = 1; + else + *rdonlyp = 0; + if (!lockflag) + VOP_UNLOCK(*vpp); + + return (0); +} + +/* + * This function compares two net addresses by family and returns non zero + * if they are the same host, or if there is any doubt it returns 0. + * The AF_INET family is handled as a special case so that address mbufs + * don't need to be saved to store "struct in_addr", which is only 4 bytes. + */ +int +netaddr_match(int family, union nethostaddr *haddr, struct mbuf *nam) +{ + struct sockaddr_in *inetaddr; + + switch (family) { + case AF_INET: + inetaddr = mtod(nam, struct sockaddr_in *); + if (inetaddr->sin_family == AF_INET && + inetaddr->sin_addr.s_addr == haddr->had_inetaddr) + return (1); + break; + default: + break; + }; + return (0); +} + +int +nfsm_srvsattr(struct mbuf **mp, struct vattr *va, struct mbuf *mrep, + caddr_t *dposp) +{ + struct nfsm_info info; + int error = 0; + uint32_t *tl; + + info.nmi_md = *mp; + info.nmi_dpos = *dposp; + info.nmi_mrep = mrep; + info.nmi_errorp = &error; + + tl = (uint32_t *)nfsm_dissect(&info, NFSX_UNSIGNED); + if (tl == NULL) + return error; + if (*tl == nfs_true) { + tl = (uint32_t *)nfsm_dissect(&info, NFSX_UNSIGNED); + if (tl == NULL) + return error; + va->va_mode = nfstov_mode(*tl); + } + + tl = (uint32_t *)nfsm_dissect(&info, NFSX_UNSIGNED); + if (tl == NULL) + return error; + if (*tl == nfs_true) { + tl = (uint32_t *)nfsm_dissect(&info, NFSX_UNSIGNED); + if (tl == NULL) + return error; + va->va_uid = fxdr_unsigned(uid_t, *tl); + } + + tl = (uint32_t *)nfsm_dissect(&info, NFSX_UNSIGNED); + if (tl == NULL) + return error; + if (*tl == nfs_true) { + tl = (uint32_t *)nfsm_dissect(&info, NFSX_UNSIGNED); + if (tl == NULL) + return error; + va->va_gid = fxdr_unsigned(gid_t, *tl); + } + + tl = (uint32_t *)nfsm_dissect(&info, NFSX_UNSIGNED); + if (tl == NULL) + return error; + if (*tl == nfs_true) { + tl = (uint32_t *)nfsm_dissect(&info, 2 * NFSX_UNSIGNED); + if (tl == NULL) + return error; + va->va_size = fxdr_hyper(tl); + } + + tl = (uint32_t *)nfsm_dissect(&info, NFSX_UNSIGNED); + if (tl == NULL) + return error; + switch (fxdr_unsigned(int, *tl)) { + case NFSV3SATTRTIME_TOCLIENT: + va->va_vaflags |= VA_UTIMES_CHANGE; + va->va_vaflags &= ~VA_UTIMES_NULL; + tl = (uint32_t *)nfsm_dissect(&info, 2 * NFSX_UNSIGNED); + if (tl == NULL) + return error; + fxdr_nfsv3time(tl, &va->va_atime); + break; + case NFSV3SATTRTIME_TOSERVER: + va->va_vaflags |= VA_UTIMES_CHANGE; + getnanotime(&va->va_atime); + break; + }; + + tl = (uint32_t *)nfsm_dissect(&info, NFSX_UNSIGNED); + if (tl == NULL) + return error; + switch (fxdr_unsigned(int, *tl)) { + case NFSV3SATTRTIME_TOCLIENT: + va->va_vaflags |= VA_UTIMES_CHANGE; + va->va_vaflags &= ~VA_UTIMES_NULL; + tl = (uint32_t *)nfsm_dissect(&info, 2 * NFSX_UNSIGNED); + if (tl == NULL) + return error; + fxdr_nfsv3time(tl, &va->va_mtime); + break; + case NFSV3SATTRTIME_TOSERVER: + va->va_vaflags |= VA_UTIMES_CHANGE; + getnanotime(&va->va_mtime); + break; + }; + + *dposp = info.nmi_dpos; + *mp = info.nmi_md; + return 0; +} diff --git a/sys/nfs/nfs_subs.c b/sys/nfs/nfs_subs.c index df0a4c542eb..aeb3949ab67 100644 --- a/sys/nfs/nfs_subs.c +++ b/sys/nfs/nfs_subs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nfs_subs.c,v 1.150 2024/09/04 07:54:53 mglocker Exp $ */ +/* $OpenBSD: nfs_subs.c,v 1.151 2024/09/09 03:50:14 jsg Exp $ */ /* $NetBSD: nfs_subs.c,v 1.27.4.3 1996/07/08 20:34:24 jtc Exp $ */ /* @@ -1164,334 +1164,6 @@ nfs_getattrcache(struct vnode *vp, struct vattr *vaper) #endif /* NFSCLIENT */ /* - * Set up nameidata for a lookup() call and do it - */ -int -nfs_namei(struct nameidata *ndp, fhandle_t *fhp, int len, - struct nfssvc_sock *slp, struct mbuf *nam, struct mbuf **mdp, - caddr_t *dposp, struct vnode **retdirp, struct proc *p) -{ - int i, rem; - struct mbuf *md; - char *fromcp, *tocp; - struct vnode *dp; - int error, rdonly; - struct componentname *cnp = &ndp->ni_cnd; - - *retdirp = NULL; - cnp->cn_pnbuf = pool_get(&namei_pool, PR_WAITOK); - /* - * Copy the name from the mbuf list to ndp->ni_pnbuf - * and set the various ndp fields appropriately. - */ - fromcp = *dposp; - tocp = cnp->cn_pnbuf; - md = *mdp; - rem = mtod(md, caddr_t) + md->m_len - fromcp; - for (i = 0; i < len; i++) { - while (rem == 0) { - md = md->m_next; - if (md == NULL) { - error = EBADRPC; - goto out; - } - fromcp = mtod(md, caddr_t); - rem = md->m_len; - } - if (*fromcp == '\0' || *fromcp == '/') { - error = EACCES; - goto out; - } - *tocp++ = *fromcp++; - rem--; - } - *tocp = '\0'; - *mdp = md; - *dposp = fromcp; - len = nfsm_padlen(len); - if (len > 0) { - if (rem >= len) - *dposp += len; - else if ((error = nfs_adv(mdp, dposp, len, rem)) != 0) - goto out; - } - ndp->ni_pathlen = tocp - cnp->cn_pnbuf; - cnp->cn_nameptr = cnp->cn_pnbuf; - /* - * Extract and set starting directory. - */ - error = nfsrv_fhtovp(fhp, 0, &dp, ndp->ni_cnd.cn_cred, slp, - nam, &rdonly); - if (error) - goto out; - if (dp->v_type != VDIR) { - vrele(dp); - error = ENOTDIR; - goto out; - } - vref(dp); - *retdirp = dp; - ndp->ni_startdir = dp; - if (rdonly) - cnp->cn_flags |= (NOCROSSMOUNT | RDONLY); - else - cnp->cn_flags |= NOCROSSMOUNT; - - /* - * And call lookup() to do the real work - */ - cnp->cn_proc = p; - error = vfs_lookup(ndp); - if (error) - goto out; - /* - * Check for encountering a symbolic link - */ - if (cnp->cn_flags & ISSYMLINK) { - if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1) - vput(ndp->ni_dvp); - else - vrele(ndp->ni_dvp); - vput(ndp->ni_vp); - ndp->ni_vp = NULL; - error = EINVAL; - goto out; - } - /* - * Check for saved name request - */ - if (cnp->cn_flags & (SAVENAME | SAVESTART)) { - cnp->cn_flags |= HASBUF; - return (0); - } -out: - pool_put(&namei_pool, cnp->cn_pnbuf); - return (error); -} - -/* - * A fiddled version of m_adj() that ensures null fill to a long - * boundary and only trims off the back end - */ -void -nfsm_adj(struct mbuf *mp, int len, int nul) -{ - struct mbuf *m; - int count, i; - char *cp; - - /* - * Trim from tail. Scan the mbuf chain, - * calculating its length and finding the last mbuf. - * If the adjustment only affects this mbuf, then just - * adjust and return. Otherwise, rescan and truncate - * after the remaining size. - */ - count = 0; - m = mp; - for (;;) { - count += m->m_len; - if (m->m_next == NULL) - break; - m = m->m_next; - } - if (m->m_len > len) { - m->m_len -= len; - if (nul > 0) { - cp = mtod(m, caddr_t)+m->m_len-nul; - for (i = 0; i < nul; i++) - *cp++ = '\0'; - } - return; - } - count -= len; - if (count < 0) - count = 0; - /* - * Correct length for chain is "count". - * Find the mbuf with last data, adjust its length, - * and toss data from remaining mbufs on chain. - */ - for (m = mp; m; m = m->m_next) { - if (m->m_len >= count) { - m->m_len = count; - if (nul > 0) { - cp = mtod(m, caddr_t)+m->m_len-nul; - for (i = 0; i < nul; i++) - *cp++ = '\0'; - } - break; - } - count -= m->m_len; - } - for (m = m->m_next;m;m = m->m_next) - m->m_len = 0; -} - -/* - * Make these non-inline functions, so that the kernel text size - * doesn't get too big... - */ -void -nfsm_srvwcc(struct nfsrv_descript *nfsd, int before_ret, - struct vattr *before_vap, int after_ret, struct vattr *after_vap, - struct nfsm_info *info) -{ - u_int32_t *tl; - - if (before_ret) { - tl = nfsm_build(&info->nmi_mb, NFSX_UNSIGNED); - *tl = nfs_false; - } else { - tl = nfsm_build(&info->nmi_mb, 7 * NFSX_UNSIGNED); - *tl++ = nfs_true; - txdr_hyper(before_vap->va_size, tl); - tl += 2; - txdr_nfsv3time(&(before_vap->va_mtime), tl); - tl += 2; - txdr_nfsv3time(&(before_vap->va_ctime), tl); - } - nfsm_srvpostop_attr(nfsd, after_ret, after_vap, info); -} - -void -nfsm_srvpostop_attr(struct nfsrv_descript *nfsd, int after_ret, - struct vattr *after_vap, struct nfsm_info *info) -{ - u_int32_t *tl; - struct nfs_fattr *fp; - - if (after_ret) { - tl = nfsm_build(&info->nmi_mb, NFSX_UNSIGNED); - *tl = nfs_false; - } else { - tl = nfsm_build(&info->nmi_mb, NFSX_UNSIGNED + NFSX_V3FATTR); - *tl++ = nfs_true; - fp = (struct nfs_fattr *)tl; - nfsm_srvfattr(nfsd, after_vap, fp); - } -} - -void -nfsm_srvfattr(struct nfsrv_descript *nfsd, struct vattr *vap, - struct nfs_fattr *fp) -{ - - fp->fa_nlink = txdr_unsigned(vap->va_nlink); - fp->fa_uid = txdr_unsigned(vap->va_uid); - fp->fa_gid = txdr_unsigned(vap->va_gid); - if (nfsd->nd_flag & ND_NFSV3) { - fp->fa_type = vtonfsv3_type(vap->va_type); - fp->fa_mode = vtonfsv3_mode(vap->va_mode); - txdr_hyper(vap->va_size, &fp->fa3_size); - txdr_hyper(vap->va_bytes, &fp->fa3_used); - fp->fa3_rdev.specdata1 = txdr_unsigned(major(vap->va_rdev)); - fp->fa3_rdev.specdata2 = txdr_unsigned(minor(vap->va_rdev)); - fp->fa3_fsid.nfsuquad[0] = 0; - fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(vap->va_fsid); - txdr_hyper(vap->va_fileid, &fp->fa3_fileid); - txdr_nfsv3time(&vap->va_atime, &fp->fa3_atime); - txdr_nfsv3time(&vap->va_mtime, &fp->fa3_mtime); - txdr_nfsv3time(&vap->va_ctime, &fp->fa3_ctime); - } else { - fp->fa_type = vtonfsv2_type(vap->va_type); - fp->fa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode); - fp->fa2_size = txdr_unsigned(vap->va_size); - fp->fa2_blocksize = txdr_unsigned(vap->va_blocksize); - if (vap->va_type == VFIFO) - fp->fa2_rdev = 0xffffffff; - else - fp->fa2_rdev = txdr_unsigned(vap->va_rdev); - fp->fa2_blocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE); - fp->fa2_fsid = txdr_unsigned(vap->va_fsid); - fp->fa2_fileid = txdr_unsigned((u_int32_t)vap->va_fileid); - txdr_nfsv2time(&vap->va_atime, &fp->fa2_atime); - txdr_nfsv2time(&vap->va_mtime, &fp->fa2_mtime); - txdr_nfsv2time(&vap->va_ctime, &fp->fa2_ctime); - } -} - -/* - * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked) - * - look up fsid in mount list (if not found ret error) - * - get vp and export rights by calling VFS_FHTOVP() and VFS_CHECKEXP() - * - if cred->cr_uid == 0 or MNT_EXPORTANON set it to credanon - * - if not lockflag unlock it with VOP_UNLOCK() - */ -int -nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp, - struct ucred *cred, struct nfssvc_sock *slp, struct mbuf *nam, - int *rdonlyp) -{ - struct mount *mp; - int i; - struct ucred *credanon; - int error, exflags; - struct sockaddr_in *saddr; - - *vpp = NULL; - mp = vfs_getvfs(&fhp->fh_fsid); - - if (!mp) - return (ESTALE); - error = VFS_CHECKEXP(mp, nam, &exflags, &credanon); - if (error) - return (error); - error = VFS_FHTOVP(mp, &fhp->fh_fid, vpp); - if (error) - return (error); - - saddr = mtod(nam, struct sockaddr_in *); - if (saddr->sin_family == AF_INET && - (ntohs(saddr->sin_port) >= IPPORT_RESERVED || - (slp->ns_so->so_type == SOCK_STREAM && ntohs(saddr->sin_port) == 20))) { - vput(*vpp); - return (NFSERR_AUTHERR | AUTH_TOOWEAK); - } - - /* Check/setup credentials. */ - if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) { - cred->cr_uid = credanon->cr_uid; - cred->cr_gid = credanon->cr_gid; - for (i = 0; i < credanon->cr_ngroups && i < NGROUPS_MAX; i++) - cred->cr_groups[i] = credanon->cr_groups[i]; - cred->cr_ngroups = i; - } - if (exflags & MNT_EXRDONLY) - *rdonlyp = 1; - else - *rdonlyp = 0; - if (!lockflag) - VOP_UNLOCK(*vpp); - - return (0); -} - -/* - * This function compares two net addresses by family and returns non zero - * if they are the same host, or if there is any doubt it returns 0. - * The AF_INET family is handled as a special case so that address mbufs - * don't need to be saved to store "struct in_addr", which is only 4 bytes. - */ -int -netaddr_match(int family, union nethostaddr *haddr, struct mbuf *nam) -{ - struct sockaddr_in *inetaddr; - - switch (family) { - case AF_INET: - inetaddr = mtod(nam, struct sockaddr_in *); - if (inetaddr->sin_family == AF_INET && - inetaddr->sin_addr.s_addr == haddr->had_inetaddr) - return (1); - break; - default: - break; - }; - return (0); -} - -/* * The write verifier has changed (probably due to a server reboot), so all * B_NEEDCOMMIT blocks will have to be written again. Since they are on the * dirty block list as B_DELWRI, all this takes is clearing the B_NEEDCOMMIT @@ -1821,100 +1493,6 @@ nfsm_srvfhtom(struct mbuf **mp, fhandle_t *f, int v3) } } -int -nfsm_srvsattr(struct mbuf **mp, struct vattr *va, struct mbuf *mrep, - caddr_t *dposp) -{ - struct nfsm_info info; - int error = 0; - uint32_t *tl; - - info.nmi_md = *mp; - info.nmi_dpos = *dposp; - info.nmi_mrep = mrep; - info.nmi_errorp = &error; - - tl = (uint32_t *)nfsm_dissect(&info, NFSX_UNSIGNED); - if (tl == NULL) - return error; - if (*tl == nfs_true) { - tl = (uint32_t *)nfsm_dissect(&info, NFSX_UNSIGNED); - if (tl == NULL) - return error; - va->va_mode = nfstov_mode(*tl); - } - - tl = (uint32_t *)nfsm_dissect(&info, NFSX_UNSIGNED); - if (tl == NULL) - return error; - if (*tl == nfs_true) { - tl = (uint32_t *)nfsm_dissect(&info, NFSX_UNSIGNED); - if (tl == NULL) - return error; - va->va_uid = fxdr_unsigned(uid_t, *tl); - } - - tl = (uint32_t *)nfsm_dissect(&info, NFSX_UNSIGNED); - if (tl == NULL) - return error; - if (*tl == nfs_true) { - tl = (uint32_t *)nfsm_dissect(&info, NFSX_UNSIGNED); - if (tl == NULL) - return error; - va->va_gid = fxdr_unsigned(gid_t, *tl); - } - - tl = (uint32_t *)nfsm_dissect(&info, NFSX_UNSIGNED); - if (tl == NULL) - return error; - if (*tl == nfs_true) { - tl = (uint32_t *)nfsm_dissect(&info, 2 * NFSX_UNSIGNED); - if (tl == NULL) - return error; - va->va_size = fxdr_hyper(tl); - } - - tl = (uint32_t *)nfsm_dissect(&info, NFSX_UNSIGNED); - if (tl == NULL) - return error; - switch (fxdr_unsigned(int, *tl)) { - case NFSV3SATTRTIME_TOCLIENT: - va->va_vaflags |= VA_UTIMES_CHANGE; - va->va_vaflags &= ~VA_UTIMES_NULL; - tl = (uint32_t *)nfsm_dissect(&info, 2 * NFSX_UNSIGNED); - if (tl == NULL) - return error; - fxdr_nfsv3time(tl, &va->va_atime); - break; - case NFSV3SATTRTIME_TOSERVER: - va->va_vaflags |= VA_UTIMES_CHANGE; - getnanotime(&va->va_atime); - break; - }; - - tl = (uint32_t *)nfsm_dissect(&info, NFSX_UNSIGNED); - if (tl == NULL) - return error; - switch (fxdr_unsigned(int, *tl)) { - case NFSV3SATTRTIME_TOCLIENT: - va->va_vaflags |= VA_UTIMES_CHANGE; - va->va_vaflags &= ~VA_UTIMES_NULL; - tl = (uint32_t *)nfsm_dissect(&info, 2 * NFSX_UNSIGNED); - if (tl == NULL) - return error; - fxdr_nfsv3time(tl, &va->va_mtime); - break; - case NFSV3SATTRTIME_TOSERVER: - va->va_vaflags |= VA_UTIMES_CHANGE; - getnanotime(&va->va_mtime); - break; - }; - - *dposp = info.nmi_dpos; - *mp = info.nmi_md; - return 0; -} - void txdr_nfsv2time(const struct timespec *from, struct nfsv2_time *to) { diff --git a/sys/nfs/nfs_var.h b/sys/nfs/nfs_var.h index 36e74ca2d45..62ec268f1d8 100644 --- a/sys/nfs/nfs_var.h +++ b/sys/nfs/nfs_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: nfs_var.h,v 1.65 2024/05/04 11:25:24 jsg Exp $ */ +/* $OpenBSD: nfs_var.h,v 1.66 2024/09/09 03:50:14 jsg Exp $ */ /* $NetBSD: nfs_var.h,v 1.3 1996/02/18 11:53:54 fvdl Exp $ */ /* @@ -142,6 +142,22 @@ int nfsrv_getcache(struct nfsrv_descript *, struct nfssvc_sock *, void nfsrv_updatecache(struct nfsrv_descript *, int, struct mbuf *); void nfsrv_cleancache(void); +/* nfs_srvsubs.c */ +int nfs_namei(struct nameidata *, fhandle_t *, int, struct nfssvc_sock *, + struct mbuf *, struct mbuf **, caddr_t *, struct vnode **, + struct proc *); +void nfsm_adj(struct mbuf *, int, int); +void nfsm_srvwcc(struct nfsrv_descript *, int, struct vattr *, int, + struct vattr *, struct nfsm_info *); +void nfsm_srvpostop_attr(struct nfsrv_descript *, int, struct vattr *, + struct nfsm_info *); +void nfsm_srvfattr(struct nfsrv_descript *, struct vattr *, + struct nfs_fattr *); +int nfsrv_fhtovp(fhandle_t *, int, struct vnode **, struct ucred *, + struct nfssvc_sock *, struct mbuf *, int *); +int netaddr_match(int, union nethostaddr *, struct mbuf *); +int nfsm_srvsattr(struct mbuf **, struct vattr *, struct mbuf *, caddr_t *); + /* nfs_subs.c */ struct mbuf *nfsm_reqhead(int); void nfsm_rpchead(struct nfsreq *, struct ucred *, int); @@ -156,21 +172,8 @@ int nfs_attrtimeo(struct nfsnode *); int nfs_loadattrcache(struct vnode **, struct mbuf **, caddr_t *, struct vattr *); int nfs_getattrcache(struct vnode *, struct vattr *); -int nfs_namei(struct nameidata *, fhandle_t *, int, struct nfssvc_sock *, - struct mbuf *, struct mbuf **, caddr_t *, struct vnode **, - struct proc *); void nfsm_v3attrbuild(struct mbuf **, struct vattr *, int); int nfsm_disct(struct mbuf **, caddr_t *, int, int, caddr_t *); -void nfsm_adj(struct mbuf *, int, int); -void nfsm_srvwcc(struct nfsrv_descript *, int, struct vattr *, int, - struct vattr *, struct nfsm_info *); -void nfsm_srvpostop_attr(struct nfsrv_descript *, int, struct vattr *, - struct nfsm_info *); -void nfsm_srvfattr(struct nfsrv_descript *, struct vattr *, - struct nfs_fattr *); -int nfsrv_fhtovp(fhandle_t *, int, struct vnode **, struct ucred *, - struct nfssvc_sock *, struct mbuf *, int *); -int netaddr_match(int, union nethostaddr *, struct mbuf *); void nfs_clearcommit(struct mount *); int nfs_in_committed_range(struct vnode *, struct buf *); int nfs_in_tobecommitted_range(struct vnode *, struct buf *); @@ -180,7 +183,6 @@ void nfs_add_tobecommitted_range(struct vnode *, struct buf *); void nfs_del_tobecommitted_range(struct vnode *, struct buf *); void nfs_merge_commit_ranges(struct vnode *); int nfsrv_errmap(struct nfsrv_descript *, int); -int nfsm_srvsattr(struct mbuf **, struct vattr *, struct mbuf *, caddr_t *); void nfsm_fhtom(struct nfsm_info *, struct vnode *, int); void nfsm_srvfhtom(struct mbuf **, fhandle_t *, int); |