1*8d80561bSjsg /* $OpenBSD: nfs_srvsubs.c,v 1.2 2024/09/18 05:21:19 jsg Exp $ */ 2d2b6e45eSjsg /* $NetBSD: nfs_subs.c,v 1.27.4.3 1996/07/08 20:34:24 jtc Exp $ */ 3d2b6e45eSjsg 4d2b6e45eSjsg /* 5d2b6e45eSjsg * Copyright (c) 1989, 1993 6d2b6e45eSjsg * The Regents of the University of California. All rights reserved. 7d2b6e45eSjsg * 8d2b6e45eSjsg * This code is derived from software contributed to Berkeley by 9d2b6e45eSjsg * Rick Macklem at The University of Guelph. 10d2b6e45eSjsg * 11d2b6e45eSjsg * Redistribution and use in source and binary forms, with or without 12d2b6e45eSjsg * modification, are permitted provided that the following conditions 13d2b6e45eSjsg * are met: 14d2b6e45eSjsg * 1. Redistributions of source code must retain the above copyright 15d2b6e45eSjsg * notice, this list of conditions and the following disclaimer. 16d2b6e45eSjsg * 2. Redistributions in binary form must reproduce the above copyright 17d2b6e45eSjsg * notice, this list of conditions and the following disclaimer in the 18d2b6e45eSjsg * documentation and/or other materials provided with the distribution. 19d2b6e45eSjsg * 3. Neither the name of the University nor the names of its contributors 20d2b6e45eSjsg * may be used to endorse or promote products derived from this software 21d2b6e45eSjsg * without specific prior written permission. 22d2b6e45eSjsg * 23d2b6e45eSjsg * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24d2b6e45eSjsg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25d2b6e45eSjsg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26d2b6e45eSjsg * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27d2b6e45eSjsg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28d2b6e45eSjsg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29d2b6e45eSjsg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30d2b6e45eSjsg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31d2b6e45eSjsg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32d2b6e45eSjsg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33d2b6e45eSjsg * SUCH DAMAGE. 34d2b6e45eSjsg * 35d2b6e45eSjsg * @(#)nfs_subs.c 8.8 (Berkeley) 5/22/95 36d2b6e45eSjsg */ 37d2b6e45eSjsg 38d2b6e45eSjsg 39d2b6e45eSjsg /* 40d2b6e45eSjsg * These functions support the nfsm_subs.h inline functions and help fiddle 41d2b6e45eSjsg * mbuf chains for the nfs op functions. They do things such as creating the 42d2b6e45eSjsg * rpc header and copying data between mbuf chains and uio lists. 43d2b6e45eSjsg */ 44d2b6e45eSjsg #include <sys/param.h> 45d2b6e45eSjsg #include <sys/systm.h> 46d2b6e45eSjsg #include <sys/mount.h> 47d2b6e45eSjsg #include <sys/vnode.h> 48d2b6e45eSjsg #include <sys/namei.h> 49d2b6e45eSjsg #include <sys/mbuf.h> 50d2b6e45eSjsg #include <sys/socket.h> 51d2b6e45eSjsg #include <sys/socketvar.h> 52d2b6e45eSjsg #include <sys/pool.h> 53d2b6e45eSjsg 54d2b6e45eSjsg #include <nfs/rpcv2.h> 55d2b6e45eSjsg #include <nfs/nfsproto.h> 56d2b6e45eSjsg #include <nfs/nfs.h> 57d2b6e45eSjsg #include <nfs/xdr_subs.h> 58d2b6e45eSjsg #include <nfs/nfs_var.h> 59d2b6e45eSjsg #include <nfs/nfsm_subs.h> 60d2b6e45eSjsg 61d2b6e45eSjsg #include <netinet/in.h> 62d2b6e45eSjsg 63d2b6e45eSjsg /* Global vars */ 64d2b6e45eSjsg extern u_int32_t nfs_false, nfs_true; 65d2b6e45eSjsg extern const nfstype nfsv2_type[9]; 66d2b6e45eSjsg extern const nfstype nfsv3_type[9]; 67d2b6e45eSjsg 68d2b6e45eSjsg /* 69d2b6e45eSjsg * Set up nameidata for a lookup() call and do it 70d2b6e45eSjsg */ 71d2b6e45eSjsg int 72d2b6e45eSjsg nfs_namei(struct nameidata *ndp, fhandle_t *fhp, int len, 73d2b6e45eSjsg struct nfssvc_sock *slp, struct mbuf *nam, struct mbuf **mdp, 74d2b6e45eSjsg caddr_t *dposp, struct vnode **retdirp, struct proc *p) 75d2b6e45eSjsg { 76d2b6e45eSjsg int i, rem; 77d2b6e45eSjsg struct mbuf *md; 78d2b6e45eSjsg char *fromcp, *tocp; 79d2b6e45eSjsg struct vnode *dp; 80d2b6e45eSjsg int error, rdonly; 81d2b6e45eSjsg struct componentname *cnp = &ndp->ni_cnd; 82d2b6e45eSjsg 83d2b6e45eSjsg *retdirp = NULL; 84d2b6e45eSjsg cnp->cn_pnbuf = pool_get(&namei_pool, PR_WAITOK); 85d2b6e45eSjsg /* 86d2b6e45eSjsg * Copy the name from the mbuf list to ndp->ni_pnbuf 87d2b6e45eSjsg * and set the various ndp fields appropriately. 88d2b6e45eSjsg */ 89d2b6e45eSjsg fromcp = *dposp; 90d2b6e45eSjsg tocp = cnp->cn_pnbuf; 91d2b6e45eSjsg md = *mdp; 92d2b6e45eSjsg rem = mtod(md, caddr_t) + md->m_len - fromcp; 93d2b6e45eSjsg for (i = 0; i < len; i++) { 94d2b6e45eSjsg while (rem == 0) { 95d2b6e45eSjsg md = md->m_next; 96d2b6e45eSjsg if (md == NULL) { 97d2b6e45eSjsg error = EBADRPC; 98d2b6e45eSjsg goto out; 99d2b6e45eSjsg } 100d2b6e45eSjsg fromcp = mtod(md, caddr_t); 101d2b6e45eSjsg rem = md->m_len; 102d2b6e45eSjsg } 103d2b6e45eSjsg if (*fromcp == '\0' || *fromcp == '/') { 104d2b6e45eSjsg error = EACCES; 105d2b6e45eSjsg goto out; 106d2b6e45eSjsg } 107d2b6e45eSjsg *tocp++ = *fromcp++; 108d2b6e45eSjsg rem--; 109d2b6e45eSjsg } 110d2b6e45eSjsg *tocp = '\0'; 111d2b6e45eSjsg *mdp = md; 112d2b6e45eSjsg *dposp = fromcp; 113d2b6e45eSjsg len = nfsm_padlen(len); 114d2b6e45eSjsg if (len > 0) { 115d2b6e45eSjsg if (rem >= len) 116d2b6e45eSjsg *dposp += len; 117d2b6e45eSjsg else if ((error = nfs_adv(mdp, dposp, len, rem)) != 0) 118d2b6e45eSjsg goto out; 119d2b6e45eSjsg } 120d2b6e45eSjsg ndp->ni_pathlen = tocp - cnp->cn_pnbuf; 121d2b6e45eSjsg cnp->cn_nameptr = cnp->cn_pnbuf; 122d2b6e45eSjsg /* 123d2b6e45eSjsg * Extract and set starting directory. 124d2b6e45eSjsg */ 125d2b6e45eSjsg error = nfsrv_fhtovp(fhp, 0, &dp, ndp->ni_cnd.cn_cred, slp, 126d2b6e45eSjsg nam, &rdonly); 127d2b6e45eSjsg if (error) 128d2b6e45eSjsg goto out; 129d2b6e45eSjsg if (dp->v_type != VDIR) { 130d2b6e45eSjsg vrele(dp); 131d2b6e45eSjsg error = ENOTDIR; 132d2b6e45eSjsg goto out; 133d2b6e45eSjsg } 134d2b6e45eSjsg vref(dp); 135d2b6e45eSjsg *retdirp = dp; 136d2b6e45eSjsg ndp->ni_startdir = dp; 137d2b6e45eSjsg if (rdonly) 138d2b6e45eSjsg cnp->cn_flags |= (NOCROSSMOUNT | RDONLY); 139d2b6e45eSjsg else 140d2b6e45eSjsg cnp->cn_flags |= NOCROSSMOUNT; 141d2b6e45eSjsg 142d2b6e45eSjsg /* 143d2b6e45eSjsg * And call lookup() to do the real work 144d2b6e45eSjsg */ 145d2b6e45eSjsg cnp->cn_proc = p; 146d2b6e45eSjsg error = vfs_lookup(ndp); 147d2b6e45eSjsg if (error) 148d2b6e45eSjsg goto out; 149d2b6e45eSjsg /* 150d2b6e45eSjsg * Check for encountering a symbolic link 151d2b6e45eSjsg */ 152d2b6e45eSjsg if (cnp->cn_flags & ISSYMLINK) { 153d2b6e45eSjsg if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1) 154d2b6e45eSjsg vput(ndp->ni_dvp); 155d2b6e45eSjsg else 156d2b6e45eSjsg vrele(ndp->ni_dvp); 157d2b6e45eSjsg vput(ndp->ni_vp); 158d2b6e45eSjsg ndp->ni_vp = NULL; 159d2b6e45eSjsg error = EINVAL; 160d2b6e45eSjsg goto out; 161d2b6e45eSjsg } 162d2b6e45eSjsg /* 163d2b6e45eSjsg * Check for saved name request 164d2b6e45eSjsg */ 165d2b6e45eSjsg if (cnp->cn_flags & (SAVENAME | SAVESTART)) { 166d2b6e45eSjsg cnp->cn_flags |= HASBUF; 167d2b6e45eSjsg return (0); 168d2b6e45eSjsg } 169d2b6e45eSjsg out: 170d2b6e45eSjsg pool_put(&namei_pool, cnp->cn_pnbuf); 171d2b6e45eSjsg return (error); 172d2b6e45eSjsg } 173d2b6e45eSjsg 174d2b6e45eSjsg /* 175d2b6e45eSjsg * A fiddled version of m_adj() that ensures null fill to a long 176d2b6e45eSjsg * boundary and only trims off the back end 177d2b6e45eSjsg */ 178d2b6e45eSjsg void 179d2b6e45eSjsg nfsm_adj(struct mbuf *mp, int len, int nul) 180d2b6e45eSjsg { 181d2b6e45eSjsg struct mbuf *m; 182d2b6e45eSjsg int count, i; 183d2b6e45eSjsg char *cp; 184d2b6e45eSjsg 185d2b6e45eSjsg /* 186d2b6e45eSjsg * Trim from tail. Scan the mbuf chain, 187d2b6e45eSjsg * calculating its length and finding the last mbuf. 188d2b6e45eSjsg * If the adjustment only affects this mbuf, then just 189d2b6e45eSjsg * adjust and return. Otherwise, rescan and truncate 190d2b6e45eSjsg * after the remaining size. 191d2b6e45eSjsg */ 192d2b6e45eSjsg count = 0; 193d2b6e45eSjsg m = mp; 194d2b6e45eSjsg for (;;) { 195d2b6e45eSjsg count += m->m_len; 196d2b6e45eSjsg if (m->m_next == NULL) 197d2b6e45eSjsg break; 198d2b6e45eSjsg m = m->m_next; 199d2b6e45eSjsg } 200d2b6e45eSjsg if (m->m_len > len) { 201d2b6e45eSjsg m->m_len -= len; 202d2b6e45eSjsg if (nul > 0) { 203d2b6e45eSjsg cp = mtod(m, caddr_t)+m->m_len-nul; 204d2b6e45eSjsg for (i = 0; i < nul; i++) 205d2b6e45eSjsg *cp++ = '\0'; 206d2b6e45eSjsg } 207d2b6e45eSjsg return; 208d2b6e45eSjsg } 209d2b6e45eSjsg count -= len; 210d2b6e45eSjsg if (count < 0) 211d2b6e45eSjsg count = 0; 212d2b6e45eSjsg /* 213d2b6e45eSjsg * Correct length for chain is "count". 214d2b6e45eSjsg * Find the mbuf with last data, adjust its length, 215d2b6e45eSjsg * and toss data from remaining mbufs on chain. 216d2b6e45eSjsg */ 217d2b6e45eSjsg for (m = mp; m; m = m->m_next) { 218d2b6e45eSjsg if (m->m_len >= count) { 219d2b6e45eSjsg m->m_len = count; 220d2b6e45eSjsg if (nul > 0) { 221d2b6e45eSjsg cp = mtod(m, caddr_t)+m->m_len-nul; 222d2b6e45eSjsg for (i = 0; i < nul; i++) 223d2b6e45eSjsg *cp++ = '\0'; 224d2b6e45eSjsg } 225d2b6e45eSjsg break; 226d2b6e45eSjsg } 227d2b6e45eSjsg count -= m->m_len; 228d2b6e45eSjsg } 229d2b6e45eSjsg for (m = m->m_next;m;m = m->m_next) 230d2b6e45eSjsg m->m_len = 0; 231d2b6e45eSjsg } 232d2b6e45eSjsg 233d2b6e45eSjsg /* 234d2b6e45eSjsg * Make these non-inline functions, so that the kernel text size 235d2b6e45eSjsg * doesn't get too big... 236d2b6e45eSjsg */ 237d2b6e45eSjsg void 238d2b6e45eSjsg nfsm_srvwcc(struct nfsrv_descript *nfsd, int before_ret, 239d2b6e45eSjsg struct vattr *before_vap, int after_ret, struct vattr *after_vap, 240d2b6e45eSjsg struct nfsm_info *info) 241d2b6e45eSjsg { 242d2b6e45eSjsg u_int32_t *tl; 243d2b6e45eSjsg 244d2b6e45eSjsg if (before_ret) { 245d2b6e45eSjsg tl = nfsm_build(&info->nmi_mb, NFSX_UNSIGNED); 246d2b6e45eSjsg *tl = nfs_false; 247d2b6e45eSjsg } else { 248d2b6e45eSjsg tl = nfsm_build(&info->nmi_mb, 7 * NFSX_UNSIGNED); 249d2b6e45eSjsg *tl++ = nfs_true; 250d2b6e45eSjsg txdr_hyper(before_vap->va_size, tl); 251d2b6e45eSjsg tl += 2; 252d2b6e45eSjsg txdr_nfsv3time(&(before_vap->va_mtime), tl); 253d2b6e45eSjsg tl += 2; 254d2b6e45eSjsg txdr_nfsv3time(&(before_vap->va_ctime), tl); 255d2b6e45eSjsg } 256d2b6e45eSjsg nfsm_srvpostop_attr(nfsd, after_ret, after_vap, info); 257d2b6e45eSjsg } 258d2b6e45eSjsg 259d2b6e45eSjsg void 260d2b6e45eSjsg nfsm_srvpostop_attr(struct nfsrv_descript *nfsd, int after_ret, 261d2b6e45eSjsg struct vattr *after_vap, struct nfsm_info *info) 262d2b6e45eSjsg { 263d2b6e45eSjsg u_int32_t *tl; 264d2b6e45eSjsg struct nfs_fattr *fp; 265d2b6e45eSjsg 266d2b6e45eSjsg if (after_ret) { 267d2b6e45eSjsg tl = nfsm_build(&info->nmi_mb, NFSX_UNSIGNED); 268d2b6e45eSjsg *tl = nfs_false; 269d2b6e45eSjsg } else { 270d2b6e45eSjsg tl = nfsm_build(&info->nmi_mb, NFSX_UNSIGNED + NFSX_V3FATTR); 271d2b6e45eSjsg *tl++ = nfs_true; 272d2b6e45eSjsg fp = (struct nfs_fattr *)tl; 273d2b6e45eSjsg nfsm_srvfattr(nfsd, after_vap, fp); 274d2b6e45eSjsg } 275d2b6e45eSjsg } 276d2b6e45eSjsg 277d2b6e45eSjsg void 278d2b6e45eSjsg nfsm_srvfattr(struct nfsrv_descript *nfsd, struct vattr *vap, 279d2b6e45eSjsg struct nfs_fattr *fp) 280d2b6e45eSjsg { 281d2b6e45eSjsg 282d2b6e45eSjsg fp->fa_nlink = txdr_unsigned(vap->va_nlink); 283d2b6e45eSjsg fp->fa_uid = txdr_unsigned(vap->va_uid); 284d2b6e45eSjsg fp->fa_gid = txdr_unsigned(vap->va_gid); 285d2b6e45eSjsg if (nfsd->nd_flag & ND_NFSV3) { 286d2b6e45eSjsg fp->fa_type = vtonfsv3_type(vap->va_type); 287d2b6e45eSjsg fp->fa_mode = vtonfsv3_mode(vap->va_mode); 288d2b6e45eSjsg txdr_hyper(vap->va_size, &fp->fa3_size); 289d2b6e45eSjsg txdr_hyper(vap->va_bytes, &fp->fa3_used); 290d2b6e45eSjsg fp->fa3_rdev.specdata1 = txdr_unsigned(major(vap->va_rdev)); 291d2b6e45eSjsg fp->fa3_rdev.specdata2 = txdr_unsigned(minor(vap->va_rdev)); 292d2b6e45eSjsg fp->fa3_fsid.nfsuquad[0] = 0; 293d2b6e45eSjsg fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(vap->va_fsid); 294d2b6e45eSjsg txdr_hyper(vap->va_fileid, &fp->fa3_fileid); 295d2b6e45eSjsg txdr_nfsv3time(&vap->va_atime, &fp->fa3_atime); 296d2b6e45eSjsg txdr_nfsv3time(&vap->va_mtime, &fp->fa3_mtime); 297d2b6e45eSjsg txdr_nfsv3time(&vap->va_ctime, &fp->fa3_ctime); 298d2b6e45eSjsg } else { 299d2b6e45eSjsg fp->fa_type = vtonfsv2_type(vap->va_type); 300d2b6e45eSjsg fp->fa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode); 301d2b6e45eSjsg fp->fa2_size = txdr_unsigned(vap->va_size); 302d2b6e45eSjsg fp->fa2_blocksize = txdr_unsigned(vap->va_blocksize); 303d2b6e45eSjsg if (vap->va_type == VFIFO) 304d2b6e45eSjsg fp->fa2_rdev = 0xffffffff; 305d2b6e45eSjsg else 306d2b6e45eSjsg fp->fa2_rdev = txdr_unsigned(vap->va_rdev); 307d2b6e45eSjsg fp->fa2_blocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE); 308d2b6e45eSjsg fp->fa2_fsid = txdr_unsigned(vap->va_fsid); 309d2b6e45eSjsg fp->fa2_fileid = txdr_unsigned((u_int32_t)vap->va_fileid); 310d2b6e45eSjsg txdr_nfsv2time(&vap->va_atime, &fp->fa2_atime); 311d2b6e45eSjsg txdr_nfsv2time(&vap->va_mtime, &fp->fa2_mtime); 312d2b6e45eSjsg txdr_nfsv2time(&vap->va_ctime, &fp->fa2_ctime); 313d2b6e45eSjsg } 314d2b6e45eSjsg } 315d2b6e45eSjsg 316d2b6e45eSjsg /* 317d2b6e45eSjsg * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked) 318d2b6e45eSjsg * - look up fsid in mount list (if not found ret error) 319d2b6e45eSjsg * - get vp and export rights by calling VFS_FHTOVP() and VFS_CHECKEXP() 320d2b6e45eSjsg * - if cred->cr_uid == 0 or MNT_EXPORTANON set it to credanon 321d2b6e45eSjsg * - if not lockflag unlock it with VOP_UNLOCK() 322d2b6e45eSjsg */ 323d2b6e45eSjsg int 324d2b6e45eSjsg nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp, 325d2b6e45eSjsg struct ucred *cred, struct nfssvc_sock *slp, struct mbuf *nam, 326d2b6e45eSjsg int *rdonlyp) 327d2b6e45eSjsg { 328d2b6e45eSjsg struct mount *mp; 329d2b6e45eSjsg int i; 330d2b6e45eSjsg struct ucred *credanon; 331d2b6e45eSjsg int error, exflags; 332d2b6e45eSjsg struct sockaddr_in *saddr; 333d2b6e45eSjsg 334d2b6e45eSjsg *vpp = NULL; 335d2b6e45eSjsg mp = vfs_getvfs(&fhp->fh_fsid); 336d2b6e45eSjsg 337d2b6e45eSjsg if (!mp) 338d2b6e45eSjsg return (ESTALE); 339d2b6e45eSjsg error = VFS_CHECKEXP(mp, nam, &exflags, &credanon); 340d2b6e45eSjsg if (error) 341d2b6e45eSjsg return (error); 342d2b6e45eSjsg error = VFS_FHTOVP(mp, &fhp->fh_fid, vpp); 343d2b6e45eSjsg if (error) 344d2b6e45eSjsg return (error); 345d2b6e45eSjsg 346d2b6e45eSjsg saddr = mtod(nam, struct sockaddr_in *); 347d2b6e45eSjsg if (saddr->sin_family == AF_INET && 348d2b6e45eSjsg (ntohs(saddr->sin_port) >= IPPORT_RESERVED || 349d2b6e45eSjsg (slp->ns_so->so_type == SOCK_STREAM && ntohs(saddr->sin_port) == 20))) { 350d2b6e45eSjsg vput(*vpp); 351d2b6e45eSjsg return (NFSERR_AUTHERR | AUTH_TOOWEAK); 352d2b6e45eSjsg } 353d2b6e45eSjsg 354d2b6e45eSjsg /* Check/setup credentials. */ 355d2b6e45eSjsg if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) { 356d2b6e45eSjsg cred->cr_uid = credanon->cr_uid; 357d2b6e45eSjsg cred->cr_gid = credanon->cr_gid; 358d2b6e45eSjsg for (i = 0; i < credanon->cr_ngroups && i < NGROUPS_MAX; i++) 359d2b6e45eSjsg cred->cr_groups[i] = credanon->cr_groups[i]; 360d2b6e45eSjsg cred->cr_ngroups = i; 361d2b6e45eSjsg } 362d2b6e45eSjsg if (exflags & MNT_EXRDONLY) 363d2b6e45eSjsg *rdonlyp = 1; 364d2b6e45eSjsg else 365d2b6e45eSjsg *rdonlyp = 0; 366d2b6e45eSjsg if (!lockflag) 367d2b6e45eSjsg VOP_UNLOCK(*vpp); 368d2b6e45eSjsg 369d2b6e45eSjsg return (0); 370d2b6e45eSjsg } 371d2b6e45eSjsg 372d2b6e45eSjsg /* 373d2b6e45eSjsg * This function compares two net addresses by family and returns non zero 374d2b6e45eSjsg * if they are the same host, or if there is any doubt it returns 0. 375d2b6e45eSjsg * The AF_INET family is handled as a special case so that address mbufs 376d2b6e45eSjsg * don't need to be saved to store "struct in_addr", which is only 4 bytes. 377d2b6e45eSjsg */ 378d2b6e45eSjsg int 379d2b6e45eSjsg netaddr_match(int family, union nethostaddr *haddr, struct mbuf *nam) 380d2b6e45eSjsg { 381d2b6e45eSjsg struct sockaddr_in *inetaddr; 382d2b6e45eSjsg 383d2b6e45eSjsg switch (family) { 384d2b6e45eSjsg case AF_INET: 385d2b6e45eSjsg inetaddr = mtod(nam, struct sockaddr_in *); 386d2b6e45eSjsg if (inetaddr->sin_family == AF_INET && 387d2b6e45eSjsg inetaddr->sin_addr.s_addr == haddr->had_inetaddr) 388d2b6e45eSjsg return (1); 389d2b6e45eSjsg break; 390d2b6e45eSjsg default: 391d2b6e45eSjsg break; 392*8d80561bSjsg } 393d2b6e45eSjsg return (0); 394d2b6e45eSjsg } 395d2b6e45eSjsg 396d2b6e45eSjsg int 397d2b6e45eSjsg nfsm_srvsattr(struct mbuf **mp, struct vattr *va, struct mbuf *mrep, 398d2b6e45eSjsg caddr_t *dposp) 399d2b6e45eSjsg { 400d2b6e45eSjsg struct nfsm_info info; 401d2b6e45eSjsg int error = 0; 402d2b6e45eSjsg uint32_t *tl; 403d2b6e45eSjsg 404d2b6e45eSjsg info.nmi_md = *mp; 405d2b6e45eSjsg info.nmi_dpos = *dposp; 406d2b6e45eSjsg info.nmi_mrep = mrep; 407d2b6e45eSjsg info.nmi_errorp = &error; 408d2b6e45eSjsg 409d2b6e45eSjsg tl = (uint32_t *)nfsm_dissect(&info, NFSX_UNSIGNED); 410d2b6e45eSjsg if (tl == NULL) 411d2b6e45eSjsg return error; 412d2b6e45eSjsg if (*tl == nfs_true) { 413d2b6e45eSjsg tl = (uint32_t *)nfsm_dissect(&info, NFSX_UNSIGNED); 414d2b6e45eSjsg if (tl == NULL) 415d2b6e45eSjsg return error; 416d2b6e45eSjsg va->va_mode = nfstov_mode(*tl); 417d2b6e45eSjsg } 418d2b6e45eSjsg 419d2b6e45eSjsg tl = (uint32_t *)nfsm_dissect(&info, NFSX_UNSIGNED); 420d2b6e45eSjsg if (tl == NULL) 421d2b6e45eSjsg return error; 422d2b6e45eSjsg if (*tl == nfs_true) { 423d2b6e45eSjsg tl = (uint32_t *)nfsm_dissect(&info, NFSX_UNSIGNED); 424d2b6e45eSjsg if (tl == NULL) 425d2b6e45eSjsg return error; 426d2b6e45eSjsg va->va_uid = fxdr_unsigned(uid_t, *tl); 427d2b6e45eSjsg } 428d2b6e45eSjsg 429d2b6e45eSjsg tl = (uint32_t *)nfsm_dissect(&info, NFSX_UNSIGNED); 430d2b6e45eSjsg if (tl == NULL) 431d2b6e45eSjsg return error; 432d2b6e45eSjsg if (*tl == nfs_true) { 433d2b6e45eSjsg tl = (uint32_t *)nfsm_dissect(&info, NFSX_UNSIGNED); 434d2b6e45eSjsg if (tl == NULL) 435d2b6e45eSjsg return error; 436d2b6e45eSjsg va->va_gid = fxdr_unsigned(gid_t, *tl); 437d2b6e45eSjsg } 438d2b6e45eSjsg 439d2b6e45eSjsg tl = (uint32_t *)nfsm_dissect(&info, NFSX_UNSIGNED); 440d2b6e45eSjsg if (tl == NULL) 441d2b6e45eSjsg return error; 442d2b6e45eSjsg if (*tl == nfs_true) { 443d2b6e45eSjsg tl = (uint32_t *)nfsm_dissect(&info, 2 * NFSX_UNSIGNED); 444d2b6e45eSjsg if (tl == NULL) 445d2b6e45eSjsg return error; 446d2b6e45eSjsg va->va_size = fxdr_hyper(tl); 447d2b6e45eSjsg } 448d2b6e45eSjsg 449d2b6e45eSjsg tl = (uint32_t *)nfsm_dissect(&info, NFSX_UNSIGNED); 450d2b6e45eSjsg if (tl == NULL) 451d2b6e45eSjsg return error; 452d2b6e45eSjsg switch (fxdr_unsigned(int, *tl)) { 453d2b6e45eSjsg case NFSV3SATTRTIME_TOCLIENT: 454d2b6e45eSjsg va->va_vaflags |= VA_UTIMES_CHANGE; 455d2b6e45eSjsg va->va_vaflags &= ~VA_UTIMES_NULL; 456d2b6e45eSjsg tl = (uint32_t *)nfsm_dissect(&info, 2 * NFSX_UNSIGNED); 457d2b6e45eSjsg if (tl == NULL) 458d2b6e45eSjsg return error; 459d2b6e45eSjsg fxdr_nfsv3time(tl, &va->va_atime); 460d2b6e45eSjsg break; 461d2b6e45eSjsg case NFSV3SATTRTIME_TOSERVER: 462d2b6e45eSjsg va->va_vaflags |= VA_UTIMES_CHANGE; 463d2b6e45eSjsg getnanotime(&va->va_atime); 464d2b6e45eSjsg break; 465*8d80561bSjsg } 466d2b6e45eSjsg 467d2b6e45eSjsg tl = (uint32_t *)nfsm_dissect(&info, NFSX_UNSIGNED); 468d2b6e45eSjsg if (tl == NULL) 469d2b6e45eSjsg return error; 470d2b6e45eSjsg switch (fxdr_unsigned(int, *tl)) { 471d2b6e45eSjsg case NFSV3SATTRTIME_TOCLIENT: 472d2b6e45eSjsg va->va_vaflags |= VA_UTIMES_CHANGE; 473d2b6e45eSjsg va->va_vaflags &= ~VA_UTIMES_NULL; 474d2b6e45eSjsg tl = (uint32_t *)nfsm_dissect(&info, 2 * NFSX_UNSIGNED); 475d2b6e45eSjsg if (tl == NULL) 476d2b6e45eSjsg return error; 477d2b6e45eSjsg fxdr_nfsv3time(tl, &va->va_mtime); 478d2b6e45eSjsg break; 479d2b6e45eSjsg case NFSV3SATTRTIME_TOSERVER: 480d2b6e45eSjsg va->va_vaflags |= VA_UTIMES_CHANGE; 481d2b6e45eSjsg getnanotime(&va->va_mtime); 482d2b6e45eSjsg break; 483*8d80561bSjsg } 484d2b6e45eSjsg 485d2b6e45eSjsg *dposp = info.nmi_dpos; 486d2b6e45eSjsg *mp = info.nmi_md; 487d2b6e45eSjsg return 0; 488d2b6e45eSjsg } 489