LCOV - code coverage report
Current view: top level - nfs - nfs_serv.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 1776 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 24 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: nfs_serv.c,v 1.116 2018/06/13 14:57:24 visa Exp $     */
       2             : /*     $NetBSD: nfs_serv.c,v 1.34 1997/05/12 23:37:12 fvdl Exp $       */
       3             : 
       4             : /*
       5             :  * Copyright (c) 1989, 1993
       6             :  *      The Regents of the University of California.  All rights reserved.
       7             :  *
       8             :  * This code is derived from software contributed to Berkeley by
       9             :  * Rick Macklem at The University of Guelph.
      10             :  *
      11             :  * Redistribution and use in source and binary forms, with or without
      12             :  * modification, are permitted provided that the following conditions
      13             :  * are met:
      14             :  * 1. Redistributions of source code must retain the above copyright
      15             :  *    notice, this list of conditions and the following disclaimer.
      16             :  * 2. Redistributions in binary form must reproduce the above copyright
      17             :  *    notice, this list of conditions and the following disclaimer in the
      18             :  *    documentation and/or other materials provided with the distribution.
      19             :  * 3. Neither the name of the University nor the names of its contributors
      20             :  *    may be used to endorse or promote products derived from this software
      21             :  *    without specific prior written permission.
      22             :  *
      23             :  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      24             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      25             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      26             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      27             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      28             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      29             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      30             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      31             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      32             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      33             :  * SUCH DAMAGE.
      34             :  *
      35             :  *      @(#)nfs_serv.c  8.7 (Berkeley) 5/14/95
      36             :  */
      37             : 
      38             : /*
      39             :  * nfs version 2 and 3 server calls to vnode ops
      40             :  * - these routines generally have 3 phases
      41             :  *   1 - break down and validate rpc request in mbuf list
      42             :  *   2 - do the vnode ops for the request
      43             :  *       (surprisingly ?? many are very similar to syscalls in vfs_syscalls.c)
      44             :  *   3 - build the rpc reply in an mbuf list
      45             :  *   nb:
      46             :  *      - do not mix the phases, since the nfsm_?? macros can return failures
      47             :  *        on a bad rpc or similar and do not do any vrele() or vput()'s
      48             :  *
      49             :  *      - the nfsm_reply() macro generates an nfs rpc reply with the nfs
      50             :  *      error number iff error != 0 whereas
      51             :  *      returning an error from the server function implies a fatal error
      52             :  *      such as a badly constructed rpc request that should be dropped without
      53             :  *      a reply.
      54             :  *      For Version 3, nfsm_reply() does not return for the error case, since
      55             :  *      most version 3 rpcs return more than the status for error cases.
      56             :  */
      57             : 
      58             : #include <sys/param.h>
      59             : #include <sys/systm.h>
      60             : #include <sys/proc.h>
      61             : #include <sys/namei.h>
      62             : #include <sys/vnode.h>
      63             : #include <sys/lock.h>
      64             : #include <sys/mount.h>
      65             : #include <sys/socket.h>
      66             : #include <sys/socketvar.h>
      67             : #include <sys/mbuf.h>
      68             : #include <sys/dirent.h>
      69             : #include <sys/stat.h>
      70             : #include <sys/kernel.h>
      71             : #include <sys/pool.h>
      72             : #include <sys/queue.h>
      73             : #include <sys/unistd.h>
      74             : 
      75             : #include <ufs/ufs/dir.h>
      76             : 
      77             : #include <nfs/nfsproto.h>
      78             : #include <nfs/nfs.h>
      79             : #include <nfs/xdr_subs.h>
      80             : #include <nfs/nfsm_subs.h>
      81             : #include <nfs/nfs_var.h>
      82             : 
      83             : /* Global vars */
      84             : extern u_int32_t nfs_xdrneg1;
      85             : extern u_int32_t nfs_false, nfs_true;
      86             : extern enum vtype nv3tov_type[8];
      87             : extern struct nfsstats nfsstats;
      88             : extern nfstype nfsv2_type[9];
      89             : extern nfstype nfsv3_type[9];
      90             : 
      91             : int nfsrv_access(struct vnode *, int, struct ucred *, int, struct proc *, int);
      92             : 
      93             : /*
      94             :  * nfs v3 access service
      95             :  */
      96             : int
      97           0 : nfsrv3_access(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
      98             :     struct proc *procp, struct mbuf **mrq)
      99             : {
     100           0 :         struct mbuf *nam = nfsd->nd_nam;
     101           0 :         struct nfsm_info        info;
     102           0 :         struct ucred *cred = &nfsd->nd_cr;
     103           0 :         struct vnode *vp;
     104           0 :         nfsfh_t nfh;
     105             :         fhandle_t *fhp;
     106             :         u_int32_t *tl;
     107             :         int32_t t1;
     108           0 :         int error = 0, rdonly, getret;
     109           0 :         char *cp2;
     110           0 :         struct vattr va;
     111             :         u_long testmode, nfsmode;
     112             : 
     113           0 :         info.nmi_mreq = NULL;
     114           0 :         info.nmi_mrep = nfsd->nd_mrep;
     115           0 :         info.nmi_md = nfsd->nd_md;
     116           0 :         info.nmi_dpos = nfsd->nd_dpos;
     117             : 
     118           0 :         fhp = &nfh.fh_generic;
     119           0 :         nfsm_srvmtofh(fhp);
     120           0 :         nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
     121           0 :         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly);
     122           0 :         if (error) {
     123           0 :                 nfsm_reply(NFSX_UNSIGNED);
     124           0 :                 nfsm_srvpostop_attr(nfsd, 1, NULL, &info);
     125             :                 error = 0;
     126           0 :                 goto nfsmout;
     127             :         }
     128           0 :         nfsmode = fxdr_unsigned(u_int32_t, *tl);
     129           0 :         if ((nfsmode & NFSV3ACCESS_READ) &&
     130           0 :                 nfsrv_access(vp, VREAD, cred, rdonly, procp, 0))
     131           0 :                 nfsmode &= ~NFSV3ACCESS_READ;
     132           0 :         if (vp->v_type == VDIR)
     133           0 :                 testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
     134             :                         NFSV3ACCESS_DELETE);
     135             :         else
     136             :                 testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
     137           0 :         if ((nfsmode & testmode) &&
     138           0 :                 nfsrv_access(vp, VWRITE, cred, rdonly, procp, 0))
     139           0 :                 nfsmode &= ~testmode;
     140           0 :         if (vp->v_type == VDIR)
     141           0 :                 testmode = NFSV3ACCESS_LOOKUP;
     142             :         else
     143             :                 testmode = NFSV3ACCESS_EXECUTE;
     144           0 :         if ((nfsmode & testmode) &&
     145           0 :                 nfsrv_access(vp, VEXEC, cred, rdonly, procp, 0))
     146           0 :                 nfsmode &= ~testmode;
     147           0 :         getret = VOP_GETATTR(vp, &va, cred, procp);
     148           0 :         vput(vp);
     149           0 :         nfsm_reply(NFSX_POSTOPATTR(1) + NFSX_UNSIGNED);
     150           0 :         nfsm_srvpostop_attr(nfsd, getret, &va, &info);
     151           0 :         tl = nfsm_build(&info.nmi_mb, NFSX_UNSIGNED);
     152           0 :         *tl = txdr_unsigned(nfsmode);
     153             : nfsmout:
     154           0 :         return(error);
     155           0 : }
     156             : 
     157             : /*
     158             :  * nfs getattr service
     159             :  */
     160             : int
     161           0 : nfsrv_getattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
     162             :     struct proc *procp, struct mbuf **mrq)
     163             : {
     164           0 :         struct mbuf *nam = nfsd->nd_nam;
     165           0 :         struct nfsm_info        info;
     166           0 :         struct ucred *cred = &nfsd->nd_cr;
     167             :         struct nfs_fattr *fp;
     168           0 :         struct vattr va;
     169           0 :         struct vnode *vp;
     170           0 :         nfsfh_t nfh;
     171             :         fhandle_t *fhp;
     172             :         u_int32_t *tl;
     173             :         int32_t t1;
     174           0 :         int error = 0, rdonly;
     175           0 :         char *cp2;
     176             : 
     177           0 :         info.nmi_mreq = NULL;
     178           0 :         info.nmi_mrep = nfsd->nd_mrep;
     179           0 :         info.nmi_md = nfsd->nd_md;
     180           0 :         info.nmi_dpos = nfsd->nd_dpos;
     181           0 :         info.nmi_v3 = (nfsd->nd_flag & ND_NFSV3);
     182             : 
     183           0 :         fhp = &nfh.fh_generic;
     184           0 :         nfsm_srvmtofh(fhp);
     185           0 :         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly);
     186           0 :         if (error) {
     187           0 :                 nfsm_reply(0);
     188             :                 error = 0;
     189           0 :                 goto nfsmout;
     190             :         }
     191           0 :         error = VOP_GETATTR(vp, &va, cred, procp);
     192           0 :         vput(vp);
     193           0 :         nfsm_reply(NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
     194           0 :         if (error) {
     195             :                 error = 0;
     196           0 :                 goto nfsmout;
     197             :         }
     198           0 :         fp = nfsm_build(&info.nmi_mb, NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
     199           0 :         nfsm_srvfattr(nfsd, &va, fp);
     200             : nfsmout:
     201           0 :         return(error);
     202           0 : }
     203             : 
     204             : /*
     205             :  * nfs setattr service
     206             :  */
     207             : int
     208           0 : nfsrv_setattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
     209             :     struct proc *procp, struct mbuf **mrq)
     210             : {
     211           0 :         struct mbuf *nam = nfsd->nd_nam;
     212           0 :         struct nfsm_info        info;
     213           0 :         struct ucred *cred = &nfsd->nd_cr;
     214           0 :         struct vattr va, preat;
     215             :         struct nfsv2_sattr *sp;
     216             :         struct nfs_fattr *fp;
     217           0 :         struct vnode *vp;
     218           0 :         nfsfh_t nfh;
     219             :         fhandle_t *fhp;
     220             :         u_int32_t *tl;
     221             :         int32_t t1;
     222           0 :         int error = 0, rdonly, preat_ret = 1, postat_ret = 1;
     223             :         int gcheck = 0;
     224           0 :         char *cp2;
     225             :         struct timespec guard;
     226             : 
     227           0 :         info.nmi_mreq = NULL;
     228           0 :         info.nmi_mrep = nfsd->nd_mrep;
     229           0 :         info.nmi_md = nfsd->nd_md;
     230           0 :         info.nmi_dpos = nfsd->nd_dpos;
     231           0 :         info.nmi_v3 = (nfsd->nd_flag & ND_NFSV3);
     232             : 
     233           0 :         fhp = &nfh.fh_generic;
     234           0 :         nfsm_srvmtofh(fhp);
     235           0 :         VATTR_NULL(&va);
     236           0 :         if (info.nmi_v3) {
     237           0 :                 va.va_vaflags |= VA_UTIMES_NULL;
     238           0 :                 error = nfsm_srvsattr(&info.nmi_md, &va, info.nmi_mrep, &info.nmi_dpos);
     239           0 :                 if (error)
     240             :                         goto nfsmout;
     241           0 :                 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
     242           0 :                 gcheck = fxdr_unsigned(int, *tl);
     243           0 :                 if (gcheck) {
     244           0 :                         nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
     245           0 :                         fxdr_nfsv3time(tl, &guard);
     246           0 :                 }
     247             :         } else {
     248           0 :                 nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
     249             :                 /*
     250             :                  * Nah nah nah nah na nah
     251             :                  * There is a bug in the Sun client that puts 0xffff in the mode
     252             :                  * field of sattr when it should put in 0xffffffff. The u_short
     253             :                  * doesn't sign extend.
     254             :                  * --> check the low order 2 bytes for 0xffff
     255             :                  */
     256           0 :                 if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff)
     257           0 :                         va.va_mode = nfstov_mode(sp->sa_mode);
     258           0 :                 if (sp->sa_uid != nfs_xdrneg1)
     259           0 :                         va.va_uid = fxdr_unsigned(uid_t, sp->sa_uid);
     260           0 :                 if (sp->sa_gid != nfs_xdrneg1)
     261           0 :                         va.va_gid = fxdr_unsigned(gid_t, sp->sa_gid);
     262           0 :                 if (sp->sa_size != nfs_xdrneg1)
     263           0 :                         va.va_size = fxdr_unsigned(u_quad_t, sp->sa_size);
     264           0 :                 if (sp->sa_atime.nfsv2_sec != nfs_xdrneg1) {
     265             : #ifdef notyet
     266             :                         fxdr_nfsv2time(&sp->sa_atime, &va.va_atime);
     267             : #else
     268           0 :                         va.va_atime.tv_sec =
     269           0 :                                 fxdr_unsigned(u_int32_t,sp->sa_atime.nfsv2_sec);
     270           0 :                         va.va_atime.tv_nsec = 0;
     271             : #endif
     272           0 :                 }
     273           0 :                 if (sp->sa_mtime.nfsv2_sec != nfs_xdrneg1)
     274           0 :                         fxdr_nfsv2time(&sp->sa_mtime, &va.va_mtime);
     275             : 
     276             :         }
     277             : 
     278             :         /*
     279             :          * Now that we have all the fields, lets do it.
     280             :          */
     281           0 :         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly);
     282           0 :         if (error) {
     283           0 :                 nfsm_reply(2 * NFSX_UNSIGNED);
     284           0 :                 nfsm_srvwcc(nfsd, preat_ret, &preat, postat_ret, &va, &info);
     285             :                 error = 0;
     286           0 :                 goto nfsmout;
     287             :         }
     288           0 :         if (info.nmi_v3) {
     289           0 :                 error = preat_ret = VOP_GETATTR(vp, &preat, cred, procp);
     290           0 :                 if (!error && gcheck &&
     291           0 :                         (preat.va_ctime.tv_sec != guard.tv_sec ||
     292           0 :                          preat.va_ctime.tv_nsec != guard.tv_nsec))
     293           0 :                         error = NFSERR_NOT_SYNC;
     294           0 :                 if (error) {
     295           0 :                         vput(vp);
     296           0 :                         nfsm_reply(NFSX_WCCDATA(info.nmi_v3));
     297           0 :                         nfsm_srvwcc(nfsd, preat_ret, &preat, postat_ret, &va,
     298             :                             &info);
     299             :                         error = 0;
     300           0 :                         goto nfsmout;
     301             :                 }
     302             :         }
     303             : 
     304             :         /*
     305             :          * If the size is being changed write acces is required, otherwise
     306             :          * just check for a read only file system.
     307             :          */
     308           0 :         if (va.va_size == ((u_quad_t)((quad_t) -1))) {
     309           0 :                 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
     310             :                         error = EROFS;
     311           0 :                         goto out;
     312             :                 }
     313             :         } else {
     314           0 :                 if (vp->v_type == VDIR) {
     315             :                         error = EISDIR;
     316           0 :                         goto out;
     317           0 :                 } else if ((error = nfsrv_access(vp, VWRITE, cred, rdonly,
     318           0 :                         procp, 1)) != 0)
     319             :                         goto out;
     320             :         }
     321           0 :         error = VOP_SETATTR(vp, &va, cred, procp);
     322           0 :         postat_ret = VOP_GETATTR(vp, &va, cred, procp);
     323           0 :         if (!error)
     324           0 :                 error = postat_ret;
     325             : out:
     326           0 :         vput(vp);
     327           0 :         nfsm_reply(NFSX_WCCORFATTR(info.nmi_v3));
     328           0 :         if (info.nmi_v3) {
     329           0 :                 nfsm_srvwcc(nfsd, preat_ret, &preat, postat_ret, &va,
     330             :                     &info);
     331             :                 error = 0;
     332           0 :                 goto nfsmout;
     333             :         } else {
     334           0 :                 fp = nfsm_build(&info.nmi_mb, NFSX_V2FATTR);
     335           0 :                 nfsm_srvfattr(nfsd, &va, fp);
     336             :         }
     337             : nfsmout:
     338           0 :         return(error);
     339           0 : }
     340             : 
     341             : /*
     342             :  * nfs lookup rpc
     343             :  */
     344             : int
     345           0 : nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
     346             :     struct proc *procp, struct mbuf **mrq)
     347             : {
     348           0 :         struct mbuf *nam = nfsd->nd_nam;
     349           0 :         struct ucred *cred = &nfsd->nd_cr;
     350             :         struct nfs_fattr *fp;
     351           0 :         struct nameidata nd;
     352           0 :         struct vnode *vp, *dirp;
     353           0 :         struct nfsm_info        info;
     354           0 :         nfsfh_t nfh;
     355             :         fhandle_t *fhp;
     356             :         u_int32_t *tl;
     357             :         int32_t t1;
     358             :         int error = 0, len, dirattr_ret = 1;
     359           0 :         int v3 = (nfsd->nd_flag & ND_NFSV3);
     360           0 :         char *cp2;
     361           0 :         struct vattr va, dirattr;
     362             : 
     363           0 :         info.nmi_mrep = nfsd->nd_mrep;
     364           0 :         info.nmi_mreq = NULL;
     365           0 :         info.nmi_md = nfsd->nd_md;
     366           0 :         info.nmi_dpos = nfsd->nd_dpos;
     367           0 :         info.nmi_v3 = (nfsd->nd_flag & ND_NFSV3);
     368             : 
     369           0 :         fhp = &nfh.fh_generic;
     370           0 :         nfsm_srvmtofh(fhp);
     371           0 :         nfsm_srvnamesiz(len);
     372             : 
     373           0 :         NDINIT(&nd, LOOKUP, LOCKLEAF | SAVESTART, UIO_SYSSPACE, NULL, procp);
     374           0 :         nd.ni_cnd.cn_cred = cred;
     375           0 :         error = nfs_namei(&nd, fhp, len, slp, nam, &info.nmi_md, &info.nmi_dpos, &dirp, procp);
     376           0 :         if (dirp) {
     377           0 :                 if (info.nmi_v3)
     378           0 :                         dirattr_ret = VOP_GETATTR(dirp, &dirattr, cred,
     379             :                                 procp);
     380           0 :                 vrele(dirp);
     381           0 :         }
     382           0 :         if (error) {
     383           0 :                 nfsm_reply(NFSX_POSTOPATTR(info.nmi_v3));
     384           0 :                 nfsm_srvpostop_attr(nfsd, dirattr_ret, &dirattr, &info);
     385           0 :                 return (0);
     386             :         }
     387           0 :         vrele(nd.ni_startdir);
     388           0 :         pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
     389           0 :         vp = nd.ni_vp;
     390           0 :         memset(fhp, 0, sizeof(nfh));
     391           0 :         fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
     392           0 :         error = VFS_VPTOFH(vp, &fhp->fh_fid);
     393           0 :         if (!error)
     394           0 :                 error = VOP_GETATTR(vp, &va, cred, procp);
     395           0 :         vput(vp);
     396           0 :         nfsm_reply(NFSX_SRVFH(info.nmi_v3) + NFSX_POSTOPORFATTR(info.nmi_v3)
     397             :             + NFSX_POSTOPATTR(info.nmi_v3));
     398           0 :         if (error) {
     399           0 :                 nfsm_srvpostop_attr(nfsd, dirattr_ret, &dirattr, &info);
     400             :                 error = 0;
     401           0 :                 goto nfsmout;
     402             :         }
     403           0 :         nfsm_srvfhtom(&info.nmi_mb, fhp, info.nmi_v3);
     404           0 :         if (v3) {
     405           0 :                 nfsm_srvpostop_attr(nfsd, 0, &va, &info);
     406           0 :                 nfsm_srvpostop_attr(nfsd, dirattr_ret, &dirattr, &info);
     407           0 :         } else {
     408           0 :                 fp = nfsm_build(&info.nmi_mb, NFSX_V2FATTR);
     409           0 :                 nfsm_srvfattr(nfsd, &va, fp);
     410             :         }
     411             : nfsmout:
     412           0 :         return(error);
     413           0 : }
     414             : 
     415             : /*
     416             :  * nfs readlink service
     417             :  */
     418             : int
     419           0 : nfsrv_readlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
     420             :     struct proc *procp, struct mbuf **mrq)
     421             : {
     422           0 :         struct mbuf *nam = nfsd->nd_nam;
     423           0 :         struct ucred *cred = &nfsd->nd_cr;
     424           0 :         struct iovec iov;
     425             :         struct mbuf *mp = NULL;
     426           0 :         struct nfsm_info        info;
     427             :         u_int32_t *tl;
     428             :         int32_t t1;
     429           0 :         int error = 0, rdonly, tlen, len = 0, getret;
     430           0 :         char *cp2;
     431           0 :         struct vnode *vp;
     432           0 :         struct vattr attr;
     433           0 :         nfsfh_t nfh;
     434             :         fhandle_t *fhp;
     435           0 :         struct uio uio;
     436             : 
     437           0 :         info.nmi_mreq = NULL;
     438           0 :         info.nmi_mrep = nfsd->nd_mrep;
     439           0 :         info.nmi_md = nfsd->nd_md;
     440           0 :         info.nmi_dpos = nfsd->nd_dpos;
     441           0 :         info.nmi_v3 = (nfsd->nd_flag & ND_NFSV3);
     442             : 
     443           0 :         memset(&uio, 0, sizeof(uio));
     444             : 
     445           0 :         fhp = &nfh.fh_generic;
     446           0 :         nfsm_srvmtofh(fhp);
     447           0 :         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly);
     448           0 :         if (error) {
     449           0 :                 nfsm_reply(2 * NFSX_UNSIGNED);
     450           0 :                 nfsm_srvpostop_attr(nfsd, 1, NULL, &info);
     451             :                 error = 0;
     452           0 :                 goto nfsmout;
     453             :         }
     454           0 :         if (vp->v_type != VLNK) {
     455           0 :                 if (info.nmi_v3)
     456           0 :                         error = EINVAL;
     457             :                 else
     458             :                         error = ENXIO;
     459             :                 goto out;
     460             :         }
     461             : 
     462           0 :         MGET(mp, M_WAIT, MT_DATA);
     463           0 :         MCLGET(mp, M_WAIT);             /* MLEN < NFS_MAXPATHLEN < MCLBYTES */
     464           0 :         mp->m_len = NFS_MAXPATHLEN;
     465             :         len = NFS_MAXPATHLEN;
     466           0 :         iov.iov_base = mtod(mp, caddr_t);
     467           0 :         iov.iov_len = mp->m_len;
     468             : 
     469           0 :         uio.uio_iov = &iov;
     470           0 :         uio.uio_iovcnt = 1;
     471           0 :         uio.uio_offset = 0;
     472           0 :         uio.uio_resid = NFS_MAXPATHLEN;
     473           0 :         uio.uio_rw = UIO_READ;
     474           0 :         uio.uio_segflg = UIO_SYSSPACE;
     475           0 :         uio.uio_procp = NULL;
     476             : 
     477           0 :         error = VOP_READLINK(vp, &uio, cred);
     478             : out:
     479           0 :         getret = VOP_GETATTR(vp, &attr, cred, procp);
     480           0 :         vput(vp);
     481           0 :         if (error)
     482           0 :                 m_freem(mp);
     483           0 :         nfsm_reply(NFSX_POSTOPATTR(info.nmi_v3) + NFSX_UNSIGNED);
     484           0 :         if (info.nmi_v3) {
     485           0 :                 nfsm_srvpostop_attr(nfsd, getret, &attr, &info);
     486           0 :                 if (error) {
     487             :                         error = 0;
     488           0 :                         goto nfsmout;
     489             :                 }
     490             :         }
     491           0 :         if (uio.uio_resid > 0) {
     492           0 :                 len -= uio.uio_resid;
     493           0 :                 tlen = nfsm_rndup(len);
     494           0 :                 nfsm_adj(mp, NFS_MAXPATHLEN-tlen, tlen-len);
     495           0 :         }
     496           0 :         tl = nfsm_build(&info.nmi_mb, NFSX_UNSIGNED);
     497           0 :         *tl = txdr_unsigned(len);
     498           0 :         info.nmi_mb->m_next = mp;
     499             : 
     500             : nfsmout:
     501           0 :         return (error);
     502           0 : }
     503             : 
     504             : /*
     505             :  * nfs read service
     506             :  */
     507             : int
     508           0 : nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
     509             :     struct proc *procp, struct mbuf **mrq)
     510             : {
     511           0 :         struct mbuf *nam = nfsd->nd_nam;
     512           0 :         struct ucred *cred = &nfsd->nd_cr;
     513             :         struct mbuf *m;
     514             :         struct nfs_fattr *fp;
     515           0 :         struct nfsm_info        info;
     516             :         u_int32_t *tl;
     517             :         int32_t t1;
     518             :         int i, reqlen;
     519           0 :         int error = 0, rdonly, cnt, len, left, siz, tlen, getret = 1;
     520           0 :         char *cp2;
     521             :         struct mbuf *m2;
     522           0 :         struct vnode *vp;
     523           0 :         nfsfh_t nfh;
     524             :         fhandle_t *fhp;
     525           0 :         struct uio io, *uiop = &io;
     526           0 :         struct vattr va;
     527             :         off_t off;
     528             : 
     529           0 :         info.nmi_mreq = NULL;
     530           0 :         info.nmi_mrep = nfsd->nd_mrep;
     531           0 :         info.nmi_md = nfsd->nd_md;
     532           0 :         info.nmi_dpos = nfsd->nd_dpos;
     533           0 :         info.nmi_v3 = (nfsd->nd_flag & ND_NFSV3);
     534             : 
     535           0 :         fhp = &nfh.fh_generic;
     536           0 :         nfsm_srvmtofh(fhp);
     537           0 :         if (info.nmi_v3) {
     538           0 :                 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
     539           0 :                 off = fxdr_hyper(tl);
     540           0 :         } else {
     541           0 :                 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
     542           0 :                 off = (off_t)fxdr_unsigned(u_int32_t, *tl);
     543             :         }
     544             : 
     545           0 :         nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
     546           0 :         reqlen = fxdr_unsigned(int32_t, *tl);
     547           0 :         if (reqlen > (NFS_SRVMAXDATA(nfsd)) || reqlen <= 0) {
     548             :                 error = EBADRPC;
     549           0 :                 nfsm_reply(0);
     550             :         }
     551             : 
     552           0 :         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly);
     553           0 :         if (error)
     554             :                 goto bad;
     555             : 
     556           0 :         if (vp->v_type != VREG) {
     557           0 :                 if (info.nmi_v3)
     558           0 :                         error = EINVAL;
     559             :                 else
     560           0 :                         error = (vp->v_type == VDIR) ? EISDIR : EACCES;
     561             :         }
     562           0 :         if (!error) {
     563           0 :             if ((error = nfsrv_access(vp, VREAD, cred, rdonly, procp, 1)) != 0)
     564           0 :                 error = nfsrv_access(vp, VEXEC, cred, rdonly, procp, 1);
     565             :         }
     566           0 :         getret = VOP_GETATTR(vp, &va, cred, procp);
     567           0 :         if (!error)
     568           0 :                 error = getret;
     569           0 :         if (error)
     570             :                 goto vbad;
     571             : 
     572           0 :         if (off >= va.va_size)
     573           0 :                 cnt = 0;
     574           0 :         else if ((off + reqlen) > va.va_size)
     575           0 :                 cnt = va.va_size - off;
     576             :         else
     577             :                 cnt = reqlen;
     578           0 :         nfsm_reply(NFSX_POSTOPORFATTR(info.nmi_v3) + 3 * NFSX_UNSIGNED+nfsm_rndup(cnt));
     579           0 :         if (info.nmi_v3) {
     580           0 :                 tl = nfsm_build(&info.nmi_mb, NFSX_V3FATTR + 4 * NFSX_UNSIGNED);
     581           0 :                 *tl++ = nfs_true;
     582           0 :                 fp = (struct nfs_fattr *)tl;
     583           0 :                 tl += (NFSX_V3FATTR / sizeof (u_int32_t));
     584           0 :         } else {
     585           0 :                 tl = nfsm_build(&info.nmi_mb, NFSX_V2FATTR + NFSX_UNSIGNED);
     586           0 :                 fp = (struct nfs_fattr *)tl;
     587           0 :                 tl += (NFSX_V2FATTR / sizeof (u_int32_t));
     588             :         }
     589           0 :         len = left = nfsm_rndup (cnt);
     590           0 :         if (cnt > 0) {
     591             :                 struct iovec *iv, *iv2;
     592             :                 size_t ivlen;
     593             :                 /*
     594             :                  * Generate the mbuf list with the uio_iov ref. to it.
     595             :                  */
     596             :                 i = 0;
     597           0 :                 m = m2 = info.nmi_mb;
     598           0 :                 while (left > 0) {
     599           0 :                         siz = min(M_TRAILINGSPACE(m), left);
     600           0 :                         if (siz > 0) {
     601           0 :                                 left -= siz;
     602           0 :                                 i++;
     603           0 :                         }
     604           0 :                         if (left > 0) {
     605           0 :                                 MGET(m, M_WAIT, MT_DATA);
     606           0 :                                 if (left >= MINCLSIZE)
     607           0 :                                         MCLGET(m, M_WAIT);
     608           0 :                                 m->m_len = 0;
     609           0 :                                 m2->m_next = m;
     610             :                                 m2 = m;
     611           0 :                         }
     612             :                 }
     613           0 :                 iv = mallocarray(i, sizeof(*iv), M_TEMP, M_WAITOK);
     614           0 :                 ivlen = i * sizeof(*iv);
     615           0 :                 uiop->uio_iov = iv2 = iv;
     616           0 :                 m = info.nmi_mb;
     617             :                 left = len;
     618             :                 i = 0;
     619           0 :                 while (left > 0) {
     620           0 :                         if (m == NULL)
     621           0 :                                 panic("nfsrv_read iov");
     622           0 :                         siz = min(M_TRAILINGSPACE(m), left);
     623           0 :                         if (siz > 0) {
     624           0 :                                 iv->iov_base = mtod(m, caddr_t) + m->m_len;
     625           0 :                                 iv->iov_len = siz;
     626           0 :                                 m->m_len += siz;
     627           0 :                                 left -= siz;
     628           0 :                                 iv++;
     629           0 :                                 i++;
     630           0 :                         }
     631           0 :                         m = m->m_next;
     632             :                 }
     633           0 :                 uiop->uio_iovcnt = i;
     634           0 :                 uiop->uio_offset = off;
     635           0 :                 uiop->uio_resid = len;
     636           0 :                 uiop->uio_rw = UIO_READ;
     637           0 :                 uiop->uio_segflg = UIO_SYSSPACE;
     638           0 :                 error = VOP_READ(vp, uiop, IO_NODELOCKED, cred);
     639             :                 off = uiop->uio_offset;
     640           0 :                 free(iv2, M_TEMP, ivlen);
     641           0 :                 if (error || (getret = VOP_GETATTR(vp, &va, cred, procp)) != 0){
     642           0 :                         if (!error)
     643           0 :                                 error = getret;
     644           0 :                         m_freem(info.nmi_mreq);
     645           0 :                         goto vbad;
     646             :                 }
     647           0 :         } else
     648           0 :                 uiop->uio_resid = 0;
     649           0 :         vput(vp);
     650           0 :         nfsm_srvfattr(nfsd, &va, fp);
     651           0 :         tlen = len - uiop->uio_resid;
     652           0 :         cnt = cnt < tlen ? cnt : tlen;
     653           0 :         tlen = nfsm_rndup (cnt);
     654           0 :         if (len != tlen || tlen != cnt)
     655           0 :                 nfsm_adj(info.nmi_mb, len - tlen, tlen - cnt);
     656           0 :         if (info.nmi_v3) {
     657           0 :                 *tl++ = txdr_unsigned(cnt);
     658           0 :                 if (len < reqlen)
     659           0 :                         *tl++ = nfs_true;
     660             :                 else
     661           0 :                         *tl++ = nfs_false;
     662             :         }
     663           0 :         *tl = txdr_unsigned(cnt);
     664             : nfsmout:
     665           0 :         return(error);
     666             : 
     667             : vbad:
     668           0 :         vput(vp);
     669             : bad:
     670           0 :         nfsm_reply(0);
     671           0 :         nfsm_srvpostop_attr(nfsd, getret, &va, &info);
     672           0 :         return (0);
     673           0 : }
     674             : 
     675             : /*
     676             :  * nfs write service
     677             :  */
     678             : int
     679           0 : nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
     680             :     struct proc *procp, struct mbuf **mrq)
     681             : {
     682           0 :         struct mbuf *nam = nfsd->nd_nam;
     683           0 :         struct ucred *cred = &nfsd->nd_cr;
     684           0 :         struct nfsm_info        info;
     685             :         int i, cnt;
     686             :         struct mbuf *mp;
     687             :         struct nfs_fattr *fp;
     688           0 :         struct vattr va, forat;
     689             :         u_int32_t *tl;
     690             :         int32_t t1;
     691           0 :         int error = 0, rdonly, len, forat_ret = 1;
     692             :         int ioflags, aftat_ret = 1, retlen, zeroing, adjust;
     693             :         int stable = NFSV3WRITE_FILESYNC;
     694           0 :         char *cp2;
     695           0 :         struct vnode *vp;
     696           0 :         nfsfh_t nfh;
     697             :         fhandle_t *fhp;
     698           0 :         struct uio io, *uiop = &io;
     699             :         off_t off;
     700             : 
     701           0 :         info.nmi_mreq = NULL;
     702           0 :         info.nmi_mrep = nfsd->nd_mrep;
     703           0 :         info.nmi_md = nfsd->nd_md;
     704           0 :         info.nmi_dpos = nfsd->nd_dpos;
     705           0 :         info.nmi_v3 = (nfsd->nd_flag & ND_NFSV3);
     706             : 
     707           0 :         if (info.nmi_mrep == NULL) {
     708           0 :                 *mrq = NULL;
     709           0 :                 return (0);
     710             :         }
     711           0 :         fhp = &nfh.fh_generic;
     712           0 :         nfsm_srvmtofh(fhp);
     713           0 :         if (info.nmi_v3) {
     714           0 :                 nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
     715           0 :                 off = fxdr_hyper(tl);
     716           0 :                 tl += 3;
     717           0 :                 stable = fxdr_unsigned(int, *tl++);
     718           0 :         } else {
     719           0 :                 nfsm_dissect(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
     720           0 :                 off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
     721           0 :                 tl += 2;
     722             :         }
     723           0 :         retlen = len = fxdr_unsigned(int32_t, *tl);
     724             :         cnt = i = 0;
     725             : 
     726             :         /*
     727             :          * For NFS Version 2, it is not obvious what a write of zero length
     728             :          * should do, but I might as well be consistent with Version 3,
     729             :          * which is to return ok so long as there are no permission problems.
     730             :          */
     731           0 :         if (len > 0) {
     732             :             zeroing = 1;
     733           0 :             mp = info.nmi_mrep;
     734           0 :             while (mp) {
     735           0 :                 if (mp == info.nmi_md) {
     736             :                         zeroing = 0;
     737           0 :                         adjust = info.nmi_dpos - mtod(mp, caddr_t);
     738           0 :                         mp->m_len -= adjust;
     739           0 :                         if (mp->m_len > 0 && adjust > 0)
     740           0 :                                 mp->m_data += adjust;
     741             :                 }
     742           0 :                 if (zeroing)
     743           0 :                         mp->m_len = 0;
     744           0 :                 else if (mp->m_len > 0) {
     745           0 :                         i += mp->m_len;
     746           0 :                         if (i > len) {
     747           0 :                                 mp->m_len -= (i - len);
     748             :                                 zeroing = 1;
     749           0 :                         }
     750           0 :                         if (mp->m_len > 0)
     751           0 :                                 cnt++;
     752             :                 }
     753           0 :                 mp = mp->m_next;
     754             :             }
     755             :         }
     756           0 :         if (len > NFS_MAXDATA || len < 0 || i < len) {
     757             :                 error = EIO;
     758           0 :                 goto bad;
     759             :         }
     760           0 :         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly);
     761           0 :         if (error)
     762             :                 goto bad;
     763           0 :         if (info.nmi_v3)
     764           0 :                 forat_ret = VOP_GETATTR(vp, &forat, cred, procp);
     765           0 :         if (vp->v_type != VREG) {
     766           0 :                 if (info.nmi_v3)
     767           0 :                         error = EINVAL;
     768             :                 else
     769           0 :                         error = (vp->v_type == VDIR) ? EISDIR : EACCES;
     770             :                 goto vbad;
     771             :         }
     772           0 :         error = nfsrv_access(vp, VWRITE, cred, rdonly, procp, 1);
     773           0 :         if (error)
     774             :                 goto vbad;
     775             : 
     776           0 :         if (len > 0) {
     777             :             struct iovec *iv, *ivp;
     778             :             size_t ivlen;
     779             : 
     780           0 :             ivp = mallocarray(cnt, sizeof(*ivp), M_TEMP, M_WAITOK);
     781           0 :             ivlen = cnt * sizeof(*ivp);
     782           0 :             uiop->uio_iov = iv = ivp;
     783           0 :             uiop->uio_iovcnt = cnt;
     784           0 :             mp = info.nmi_mrep;
     785           0 :             while (mp) {
     786           0 :                 if (mp->m_len > 0) {
     787           0 :                         ivp->iov_base = mtod(mp, caddr_t);
     788           0 :                         ivp->iov_len = mp->m_len;
     789           0 :                         ivp++;
     790           0 :                 }
     791           0 :                 mp = mp->m_next;
     792             :             }
     793             : 
     794           0 :             if (stable == NFSV3WRITE_UNSTABLE)
     795           0 :                 ioflags = IO_NODELOCKED;
     796             :             else if (stable == NFSV3WRITE_DATASYNC)
     797             :                 ioflags = (IO_SYNC | IO_NODELOCKED);
     798             :             else
     799             :                 ioflags = (IO_SYNC | IO_NODELOCKED);
     800           0 :             uiop->uio_resid = len;
     801           0 :             uiop->uio_rw = UIO_WRITE;
     802           0 :             uiop->uio_segflg = UIO_SYSSPACE;
     803           0 :             uiop->uio_procp = NULL;
     804           0 :             uiop->uio_offset = off;
     805           0 :             error = VOP_WRITE(vp, uiop, ioflags, cred);
     806           0 :             nfsstats.srvvop_writes++;
     807           0 :             free(iv, M_TEMP, ivlen);
     808           0 :         }
     809           0 :         aftat_ret = VOP_GETATTR(vp, &va, cred, procp);
     810           0 :         vput(vp);
     811           0 :         if (!error)
     812           0 :                 error = aftat_ret;
     813           0 :         nfsm_reply(NFSX_PREOPATTR(info.nmi_v3) + NFSX_POSTOPORFATTR(info.nmi_v3) +
     814             :                 2 * NFSX_UNSIGNED + NFSX_WRITEVERF(info.nmi_v3));
     815           0 :         if (info.nmi_v3) {
     816           0 :                 nfsm_srvwcc(nfsd, forat_ret, &forat, aftat_ret, &va, &info);
     817           0 :                 if (error) {
     818             :                         error = 0;
     819           0 :                         goto nfsmout;
     820             :                 }
     821           0 :                 tl = nfsm_build(&info.nmi_mb, 4 * NFSX_UNSIGNED);
     822           0 :                 *tl++ = txdr_unsigned(retlen);
     823           0 :                 if (stable == NFSV3WRITE_UNSTABLE)
     824           0 :                         *tl++ = txdr_unsigned(stable);
     825             :                 else
     826           0 :                         *tl++ = txdr_unsigned(NFSV3WRITE_FILESYNC);
     827             :                 /*
     828             :                  * Actually, there is no need to txdr these fields,
     829             :                  * but it may make the values more human readable,
     830             :                  * for debugging purposes.
     831             :                  */
     832           0 :                 *tl++ = txdr_unsigned(boottime.tv_sec);
     833           0 :                 *tl = txdr_unsigned(boottime.tv_nsec/1000);
     834           0 :         } else {
     835           0 :                 fp = nfsm_build(&info.nmi_mb, NFSX_V2FATTR);
     836           0 :                 nfsm_srvfattr(nfsd, &va, fp);
     837             :         }
     838             : nfsmout:
     839           0 :         return(error);
     840             : 
     841             : vbad:
     842           0 :         vput(vp);
     843             : bad:
     844           0 :         nfsm_reply(0);
     845           0 :         nfsm_srvwcc(nfsd, forat_ret, &forat, aftat_ret, &va, &info);
     846           0 :         return (0);
     847           0 : }
     848             : 
     849             : /*
     850             :  * nfs create service
     851             :  * now does a truncate to 0 length via. setattr if it already exists
     852             :  */
     853             : int
     854           0 : nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
     855             :     struct proc *procp, struct mbuf **mrq)
     856             : {
     857           0 :         struct mbuf *nam = nfsd->nd_nam;
     858           0 :         struct ucred *cred = &nfsd->nd_cr;
     859             :         struct nfs_fattr *fp;
     860           0 :         struct vattr va, dirfor, diraft;
     861             :         struct nfsv2_sattr *sp;
     862           0 :         struct nfsm_info        info;
     863             :         u_int32_t *tl;
     864           0 :         struct nameidata nd;
     865             :         caddr_t cp;
     866             :         int32_t t1;
     867             :         int error = 0, len, tsize, dirfor_ret = 1, diraft_ret = 1;
     868             :         dev_t rdev = 0;
     869             :         int how, exclusive_flag = 0;
     870           0 :         char *cp2;
     871           0 :         struct vnode *vp = NULL, *dirp = NULL;
     872           0 :         nfsfh_t nfh;
     873             :         fhandle_t *fhp;
     874             :         u_quad_t tempsize;
     875           0 :         u_char cverf[NFSX_V3CREATEVERF];
     876             : 
     877           0 :         info.nmi_mreq = NULL;
     878           0 :         info.nmi_mrep = nfsd->nd_mrep;
     879           0 :         info.nmi_md = nfsd->nd_md;
     880           0 :         info.nmi_dpos = nfsd->nd_dpos;
     881           0 :         info.nmi_v3 = (nfsd->nd_flag & ND_NFSV3);
     882             : 
     883           0 :         fhp = &nfh.fh_generic;
     884           0 :         nfsm_srvmtofh(fhp);
     885           0 :         nfsm_srvnamesiz(len);
     886             : 
     887           0 :         NDINIT(&nd, CREATE, LOCKPARENT | LOCKLEAF | SAVESTART, UIO_SYSSPACE,
     888             :             NULL, procp);
     889           0 :         nd.ni_cnd.cn_cred = cred;
     890           0 :         error = nfs_namei(&nd, fhp, len, slp, nam, &info.nmi_md,
     891             :             &info.nmi_dpos, &dirp, procp);
     892           0 :         if (dirp) {
     893           0 :                 if (info.nmi_v3)
     894           0 :                         dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred, procp);
     895             :                 else {
     896           0 :                         vrele(dirp);
     897           0 :                         dirp = NULL;
     898             :                 }
     899             :         }
     900           0 :         if (error) {
     901           0 :                 nfsm_reply(NFSX_WCCDATA(info.nmi_v3));
     902           0 :                 nfsm_srvwcc(nfsd, dirfor_ret, &dirfor, diraft_ret, &diraft,
     903             :                     &info);
     904           0 :                 if (dirp)
     905           0 :                         vrele(dirp);
     906           0 :                 return (0);
     907             :         }
     908             : 
     909           0 :         VATTR_NULL(&va);
     910           0 :         if (info.nmi_v3) {
     911           0 :                 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
     912           0 :                 how = fxdr_unsigned(int, *tl);
     913           0 :                 switch (how) {
     914             :                 case NFSV3CREATE_GUARDED:
     915           0 :                         if (nd.ni_vp) {
     916             :                                 error = EEXIST;
     917           0 :                                 break;
     918             :                         }
     919             :                 case NFSV3CREATE_UNCHECKED:
     920           0 :                         error = nfsm_srvsattr(&info.nmi_md, &va, info.nmi_mrep,
     921             :                             &info.nmi_dpos);
     922           0 :                         if (error)
     923             :                                 goto nfsmout;
     924             :                         break;
     925             :                 case NFSV3CREATE_EXCLUSIVE:
     926           0 :                         nfsm_dissect(cp, caddr_t, NFSX_V3CREATEVERF);
     927           0 :                         bcopy(cp, cverf, NFSX_V3CREATEVERF);
     928             :                         exclusive_flag = 1;
     929           0 :                         if (nd.ni_vp == NULL)
     930           0 :                                 va.va_mode = 0;
     931             :                         break;
     932             :                 };
     933           0 :                 va.va_type = VREG;
     934           0 :         } else {
     935           0 :                 nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
     936           0 :                 va.va_type = IFTOVT(fxdr_unsigned(u_int32_t, sp->sa_mode));
     937           0 :                 if (va.va_type == VNON)
     938           0 :                         va.va_type = VREG;
     939           0 :                 va.va_mode = nfstov_mode(sp->sa_mode);
     940           0 :                 switch (va.va_type) {
     941             :                 case VREG:
     942           0 :                         tsize = fxdr_unsigned(int32_t, sp->sa_size);
     943           0 :                         if (tsize != -1)
     944           0 :                                 va.va_size = (u_quad_t)tsize;
     945             :                         break;
     946             :                 case VCHR:
     947             :                 case VBLK:
     948             :                 case VFIFO:
     949           0 :                         rdev = (dev_t)fxdr_unsigned(int32_t, sp->sa_size);
     950           0 :                         break;
     951             :                 default:
     952             :                         break;
     953             :                 };
     954             :         }
     955             : 
     956             :         /*
     957             :          * Iff doesn't exist, create it
     958             :          * otherwise just truncate to 0 length
     959             :          *   should I set the mode too ??
     960             :          */
     961           0 :         if (nd.ni_vp == NULL) {
     962           0 :                 if (va.va_type == VREG || va.va_type == VSOCK) {
     963           0 :                         vrele(nd.ni_startdir);
     964           0 :                         error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd,
     965             :                             &va);
     966           0 :                         vput(nd.ni_dvp);
     967           0 :                         if (!error) {
     968           0 :                                 pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
     969           0 :                                 if (exclusive_flag) {
     970             :                                         exclusive_flag = 0;
     971           0 :                                         VATTR_NULL(&va);
     972           0 :                                         bcopy(cverf, (caddr_t)&va.va_atime,
     973             :                                                 NFSX_V3CREATEVERF);
     974           0 :                                         error = VOP_SETATTR(nd.ni_vp, &va, cred,
     975             :                                                 procp);
     976           0 :                                 }
     977             :                         }
     978           0 :                 } else if (va.va_type == VCHR || va.va_type == VBLK ||
     979           0 :                         va.va_type == VFIFO) {
     980           0 :                         if (va.va_type == VCHR && rdev == 0xffffffff)
     981           0 :                                 va.va_type = VFIFO;
     982           0 :                         if (va.va_type != VFIFO &&
     983           0 :                             (error = suser_ucred(cred))) {
     984           0 :                                 vrele(nd.ni_startdir);
     985           0 :                                 if (nd.ni_cnd.cn_flags & HASBUF) {
     986           0 :                                         pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
     987           0 :                                         nd.ni_cnd.cn_flags &= ~HASBUF;
     988           0 :                                 }
     989           0 :                                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
     990           0 :                                 vput(nd.ni_dvp);
     991           0 :                                 nfsm_reply(0);
     992             :                                 error = 0;
     993           0 :                                 goto nfsmout;
     994             :                         } else
     995           0 :                                 va.va_rdev = (dev_t)rdev;
     996           0 :                         error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd,
     997             :                             &va);
     998           0 :                         vput(nd.ni_dvp);
     999           0 :                         if (error) {
    1000           0 :                                 vrele(nd.ni_startdir);
    1001           0 :                                 if (nd.ni_cnd.cn_flags & HASBUF) {
    1002           0 :                                         pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
    1003           0 :                                         nd.ni_cnd.cn_flags &= ~HASBUF;
    1004           0 :                                 }
    1005           0 :                                 nfsm_reply(0);
    1006             :                                 error = 0;
    1007           0 :                                 goto nfsmout;
    1008             :                         }
    1009           0 :                         nd.ni_cnd.cn_nameiop = LOOKUP;
    1010           0 :                         nd.ni_cnd.cn_flags &= ~(LOCKPARENT | SAVESTART);
    1011           0 :                         nd.ni_cnd.cn_proc = procp;
    1012           0 :                         nd.ni_cnd.cn_cred = cred;
    1013           0 :                         if ((error = vfs_lookup(&nd)) != 0) {
    1014           0 :                                 if (nd.ni_cnd.cn_flags & HASBUF) {
    1015           0 :                                         pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
    1016           0 :                                         nd.ni_cnd.cn_flags &= ~HASBUF;
    1017           0 :                                 }
    1018           0 :                                 nfsm_reply(0);
    1019             :                                 error = 0;
    1020           0 :                                 goto nfsmout;
    1021             :                         }
    1022             : 
    1023           0 :                         pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
    1024           0 :                         if (nd.ni_cnd.cn_flags & ISSYMLINK) {
    1025           0 :                                 vrele(nd.ni_dvp);
    1026           0 :                                 vput(nd.ni_vp);
    1027           0 :                                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
    1028             :                                 error = EINVAL;
    1029           0 :                                 nfsm_reply(0);
    1030             :                                 error = 0;
    1031           0 :                                 goto nfsmout;
    1032             :                         }
    1033             :                 } else {
    1034           0 :                         vrele(nd.ni_startdir);
    1035           0 :                         pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
    1036           0 :                         nd.ni_cnd.cn_flags &= ~HASBUF;
    1037           0 :                         VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
    1038           0 :                         vput(nd.ni_dvp);
    1039             :                         error = ENXIO;
    1040             :                 }
    1041           0 :                 vp = nd.ni_vp;
    1042           0 :         } else {
    1043           0 :                 vrele(nd.ni_startdir);
    1044           0 :                 pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
    1045           0 :                 nd.ni_cnd.cn_flags &= ~HASBUF;
    1046           0 :                 vp = nd.ni_vp;
    1047           0 :                 if (nd.ni_dvp == vp)
    1048           0 :                         vrele(nd.ni_dvp);
    1049             :                 else
    1050           0 :                         vput(nd.ni_dvp);
    1051           0 :                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
    1052           0 :                 if (va.va_size != -1) {
    1053           0 :                         error = nfsrv_access(vp, VWRITE, cred,
    1054           0 :                             (nd.ni_cnd.cn_flags & RDONLY), procp, 0);
    1055           0 :                         if (!error) {
    1056           0 :                                 tempsize = va.va_size;
    1057           0 :                                 VATTR_NULL(&va);
    1058           0 :                                 va.va_size = tempsize;
    1059           0 :                                 error = VOP_SETATTR(vp, &va, cred,
    1060             :                                          procp);
    1061           0 :                         }
    1062           0 :                         if (error)
    1063           0 :                                 vput(vp);
    1064             :                 }
    1065             :         }
    1066           0 :         if (!error) {
    1067           0 :                 memset(fhp, 0, sizeof(nfh));
    1068           0 :                 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
    1069           0 :                 error = VFS_VPTOFH(vp, &fhp->fh_fid);
    1070           0 :                 if (!error)
    1071           0 :                         error = VOP_GETATTR(vp, &va, cred, procp);
    1072           0 :                 vput(vp);
    1073           0 :         }
    1074           0 :         if (info.nmi_v3) {
    1075           0 :                 if (exclusive_flag && !error &&
    1076           0 :                         bcmp(cverf, (caddr_t)&va.va_atime, NFSX_V3CREATEVERF))
    1077           0 :                         error = EEXIST;
    1078           0 :                 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
    1079           0 :                 vrele(dirp);
    1080           0 :         }
    1081           0 :         nfsm_reply(NFSX_SRVFH(info.nmi_v3) + NFSX_FATTR(info.nmi_v3)
    1082             :             + NFSX_WCCDATA(info.nmi_v3));
    1083           0 :         if (info.nmi_v3) {
    1084           0 :                 if (!error) {
    1085           0 :                         nfsm_srvpostop_fh(fhp);
    1086           0 :                         nfsm_srvpostop_attr(nfsd, 0, &va, &info);
    1087           0 :                 }
    1088           0 :                 nfsm_srvwcc(nfsd, dirfor_ret, &dirfor, diraft_ret, &diraft,
    1089             :                     &info);
    1090           0 :         } else {
    1091           0 :                 nfsm_srvfhtom(&info.nmi_mb, fhp, info.nmi_v3);
    1092           0 :                 fp = nfsm_build(&info.nmi_mb, NFSX_V2FATTR);
    1093           0 :                 nfsm_srvfattr(nfsd, &va, fp);
    1094             :         }
    1095           0 :         return (0);
    1096             : nfsmout:
    1097           0 :         if (dirp)
    1098           0 :                 vrele(dirp);
    1099           0 :         if (nd.ni_cnd.cn_nameiop != LOOKUP) {
    1100           0 :                 vrele(nd.ni_startdir);
    1101           0 :                 if (nd.ni_cnd.cn_flags & HASBUF) {
    1102           0 :                         pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
    1103           0 :                         nd.ni_cnd.cn_flags &= ~HASBUF;
    1104           0 :                 }
    1105             :         }
    1106           0 :         VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
    1107           0 :         if (nd.ni_dvp == nd.ni_vp)
    1108           0 :                 vrele(nd.ni_dvp);
    1109             :         else
    1110           0 :                 vput(nd.ni_dvp);
    1111           0 :         if (nd.ni_vp)
    1112           0 :                 vput(nd.ni_vp);
    1113           0 :         return (error);
    1114           0 : }
    1115             : 
    1116             : /*
    1117             :  * nfs v3 mknod service
    1118             :  */
    1119             : int
    1120           0 : nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
    1121             :     struct proc *procp, struct mbuf **mrq)
    1122             : {
    1123           0 :         struct mbuf *nam = nfsd->nd_nam;
    1124           0 :         struct ucred *cred = &nfsd->nd_cr;
    1125           0 :         struct vattr va, dirfor, diraft;
    1126           0 :         struct nfsm_info        info;
    1127             :         u_int32_t *tl;
    1128           0 :         struct nameidata nd;
    1129             :         int32_t t1;
    1130             :         int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
    1131             :         u_int32_t major, minor;
    1132             :         enum vtype vtyp;
    1133           0 :         char *cp2;
    1134           0 :         struct vnode *vp, *dirp = NULL;
    1135           0 :         nfsfh_t nfh;
    1136             :         fhandle_t *fhp;
    1137             : 
    1138           0 :         info.nmi_mreq = NULL;
    1139           0 :         info.nmi_mrep = nfsd->nd_mrep;
    1140           0 :         info.nmi_md = nfsd->nd_md;
    1141           0 :         info.nmi_dpos = nfsd->nd_dpos;
    1142           0 :         info.nmi_v3 = (nfsd->nd_flag & ND_NFSV3);
    1143             : 
    1144           0 :         fhp = &nfh.fh_generic;
    1145           0 :         nfsm_srvmtofh(fhp);
    1146           0 :         nfsm_srvnamesiz(len);
    1147             : 
    1148           0 :         NDINIT(&nd, CREATE, LOCKPARENT | LOCKLEAF | SAVESTART, UIO_SYSSPACE,
    1149             :             NULL, procp);
    1150           0 :         nd.ni_cnd.cn_cred = cred;
    1151           0 :         error = nfs_namei(&nd, fhp, len, slp, nam, &info.nmi_md, &info.nmi_dpos, &dirp, procp);
    1152           0 :         if (dirp)
    1153           0 :                 dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred, procp);
    1154           0 :         if (error) {
    1155           0 :                 nfsm_reply(NFSX_WCCDATA(1));
    1156           0 :                 nfsm_srvwcc(nfsd, dirfor_ret, &dirfor, diraft_ret, &diraft,
    1157             :                     &info);
    1158           0 :                 if (dirp)
    1159           0 :                         vrele(dirp);
    1160           0 :                 return (0);
    1161             :         }
    1162             : 
    1163           0 :         nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
    1164           0 :         vtyp = nfsv3tov_type(*tl);
    1165           0 :         if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) {
    1166           0 :                 vrele(nd.ni_startdir);
    1167           0 :                 pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
    1168             :                 error = NFSERR_BADTYPE;
    1169           0 :                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
    1170           0 :                 if (nd.ni_dvp == nd.ni_vp)
    1171           0 :                         vrele(nd.ni_dvp);
    1172             :                 else
    1173           0 :                         vput(nd.ni_dvp);
    1174           0 :                 if (nd.ni_vp)
    1175           0 :                         vput(nd.ni_vp);
    1176             :                 goto out;
    1177             :         }
    1178           0 :         VATTR_NULL(&va);
    1179           0 :         error = nfsm_srvsattr(&info.nmi_md, &va, info.nmi_mrep, &info.nmi_dpos);
    1180           0 :         if (error)
    1181             :                 goto nfsmout;
    1182           0 :         if (vtyp == VCHR || vtyp == VBLK) {
    1183           0 :                 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
    1184           0 :                 major = fxdr_unsigned(u_int32_t, *tl++);
    1185           0 :                 minor = fxdr_unsigned(u_int32_t, *tl);
    1186           0 :                 va.va_rdev = makedev(major, minor);
    1187           0 :         }
    1188             : 
    1189             :         /*
    1190             :          * Iff doesn't exist, create it.
    1191             :          */
    1192           0 :         if (nd.ni_vp) {
    1193           0 :                 vrele(nd.ni_startdir);
    1194           0 :                 pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
    1195             :                 error = EEXIST;
    1196           0 :                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
    1197           0 :                 if (nd.ni_dvp == nd.ni_vp)
    1198           0 :                         vrele(nd.ni_dvp);
    1199             :                 else
    1200           0 :                         vput(nd.ni_dvp);
    1201           0 :                 vput(nd.ni_vp);
    1202           0 :                 goto out;
    1203             :         }
    1204           0 :         va.va_type = vtyp;
    1205           0 :         if (vtyp == VSOCK) {
    1206           0 :                 vrele(nd.ni_startdir);
    1207           0 :                 error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va);
    1208           0 :                 vput(nd.ni_dvp);
    1209           0 :                 if (!error)
    1210           0 :                         pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
    1211             :         } else {
    1212           0 :                 if (va.va_type != VFIFO &&
    1213           0 :                     (error = suser_ucred(cred))) {
    1214           0 :                         vrele(nd.ni_startdir);
    1215           0 :                         pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
    1216           0 :                         VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
    1217           0 :                         vput(nd.ni_dvp);
    1218           0 :                         goto out;
    1219             :                 }
    1220           0 :                 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va);
    1221           0 :                 vput(nd.ni_dvp);
    1222           0 :                 if (error) {
    1223           0 :                         vrele(nd.ni_startdir);
    1224           0 :                         goto out;
    1225             :                 }
    1226           0 :                 nd.ni_cnd.cn_nameiop = LOOKUP;
    1227           0 :                 nd.ni_cnd.cn_flags &= ~(LOCKPARENT | SAVESTART);
    1228           0 :                 nd.ni_cnd.cn_proc = procp;
    1229           0 :                 nd.ni_cnd.cn_cred = procp->p_ucred;
    1230           0 :                 error = vfs_lookup(&nd);
    1231           0 :                 pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
    1232           0 :                 if (error)
    1233             :                         goto out;
    1234           0 :                 if (nd.ni_cnd.cn_flags & ISSYMLINK) {
    1235           0 :                         vrele(nd.ni_dvp);
    1236           0 :                         vput(nd.ni_vp);
    1237           0 :                         VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
    1238             :                         error = EINVAL;
    1239           0 :                 }
    1240             :         }
    1241             : out:
    1242           0 :         vp = nd.ni_vp;
    1243           0 :         if (!error) {
    1244           0 :                 memset(fhp, 0, sizeof(nfh));
    1245           0 :                 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
    1246           0 :                 error = VFS_VPTOFH(vp, &fhp->fh_fid);
    1247           0 :                 if (!error)
    1248           0 :                         error = VOP_GETATTR(vp, &va, cred, procp);
    1249           0 :                 vput(vp);
    1250           0 :         }
    1251           0 :         diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
    1252           0 :         vrele(dirp);
    1253           0 :         nfsm_reply(NFSX_SRVFH(1) + NFSX_POSTOPATTR(1) + NFSX_WCCDATA(1));
    1254           0 :         if (!error) {
    1255           0 :                 nfsm_srvpostop_fh(fhp);
    1256           0 :                 nfsm_srvpostop_attr(nfsd, 0, &va, &info);
    1257           0 :         }
    1258           0 :         nfsm_srvwcc(nfsd, dirfor_ret, &dirfor, diraft_ret, &diraft, &info);
    1259           0 :         return (0);
    1260             : nfsmout:
    1261           0 :         if (dirp)
    1262           0 :                 vrele(dirp);
    1263           0 :         if (nd.ni_cnd.cn_nameiop) {
    1264           0 :                 vrele(nd.ni_startdir);
    1265           0 :                 pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
    1266           0 :         }
    1267           0 :         VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
    1268           0 :         if (nd.ni_dvp == nd.ni_vp)
    1269           0 :                 vrele(nd.ni_dvp);
    1270             :         else
    1271           0 :                 vput(nd.ni_dvp);
    1272           0 :         if (nd.ni_vp)
    1273           0 :                 vput(nd.ni_vp);
    1274           0 :         return (error);
    1275           0 : }
    1276             : 
    1277             : /*
    1278             :  * nfs remove service
    1279             :  */
    1280             : int
    1281           0 : nfsrv_remove(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
    1282             :     struct proc *procp, struct mbuf **mrq)
    1283             : {
    1284           0 :         struct mbuf *nam = nfsd->nd_nam;
    1285           0 :         struct ucred *cred = &nfsd->nd_cr;
    1286           0 :         struct nameidata nd;
    1287           0 :         struct nfsm_info        info;
    1288             :         u_int32_t *tl;
    1289             :         int32_t t1;
    1290             :         int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
    1291           0 :         char *cp2;
    1292           0 :         struct vnode *vp, *dirp;
    1293           0 :         struct vattr dirfor, diraft;
    1294           0 :         nfsfh_t nfh;
    1295             :         fhandle_t *fhp;
    1296             : 
    1297           0 :         info.nmi_mreq = NULL;
    1298           0 :         info.nmi_mrep = nfsd->nd_mrep;
    1299           0 :         info.nmi_md = nfsd->nd_md;
    1300           0 :         info.nmi_dpos = nfsd->nd_dpos;
    1301           0 :         info.nmi_v3 = (nfsd->nd_flag & ND_NFSV3);
    1302             : 
    1303             :         vp = NULL;
    1304             : 
    1305           0 :         fhp = &nfh.fh_generic;
    1306           0 :         nfsm_srvmtofh(fhp);
    1307           0 :         nfsm_srvnamesiz(len);
    1308             : 
    1309           0 :         NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_SYSSPACE, NULL, procp);
    1310           0 :         nd.ni_cnd.cn_cred = cred;
    1311           0 :         error = nfs_namei(&nd, fhp, len, slp, nam, &info.nmi_md, &info.nmi_dpos, &dirp, procp);
    1312           0 :         if (dirp) {
    1313           0 :                 if (info.nmi_v3)
    1314           0 :                         dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred, procp);
    1315             :                 else {
    1316           0 :                         vrele(dirp);
    1317           0 :                         dirp = NULL;
    1318             :                 }
    1319             :         }
    1320             : 
    1321           0 :         if (!error) {
    1322           0 :                 vp = nd.ni_vp;
    1323           0 :                 if (vp->v_type == VDIR &&
    1324           0 :                     (error = suser_ucred(cred)) != 0)
    1325             :                         goto out;
    1326             :                 /*
    1327             :                  * The root of a mounted filesystem cannot be deleted.
    1328             :                  */
    1329           0 :                 if (vp->v_flag & VROOT) {
    1330             :                         error = EBUSY;
    1331           0 :                         goto out;
    1332             :                 }
    1333           0 :                 if (vp->v_flag & VTEXT)
    1334           0 :                         uvm_vnp_uncache(vp);
    1335             : out:
    1336           0 :                 if (!error) {
    1337           0 :                         error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
    1338           0 :                 } else {
    1339           0 :                         VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
    1340           0 :                         if (nd.ni_dvp == vp)
    1341           0 :                                 vrele(nd.ni_dvp);
    1342             :                         else
    1343           0 :                                 vput(nd.ni_dvp);
    1344           0 :                         vput(vp);
    1345             :                 }
    1346             :         }
    1347           0 :         if (dirp && info.nmi_v3) {
    1348           0 :                 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
    1349           0 :                 vrele(dirp);
    1350           0 :         }
    1351           0 :         nfsm_reply(NFSX_WCCDATA(info.nmi_v3));
    1352           0 :         if (info.nmi_v3) {
    1353           0 :                 nfsm_srvwcc(nfsd, dirfor_ret, &dirfor, diraft_ret, &diraft,
    1354             :                     &info);
    1355           0 :                 return (0);
    1356             :         }
    1357             : 
    1358             : nfsmout:
    1359           0 :         return(error);
    1360           0 : }
    1361             : 
    1362             : /*
    1363             :  * nfs rename service
    1364             :  */
    1365             : int
    1366           0 : nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
    1367             :     struct proc *procp, struct mbuf **mrq)
    1368             : {
    1369           0 :         struct mbuf *nam = nfsd->nd_nam;
    1370           0 :         struct ucred *cred = &nfsd->nd_cr;
    1371           0 :         struct nfsm_info        info;
    1372             :         u_int32_t *tl;
    1373             :         int32_t t1;
    1374             :         int error = 0, len, len2, fdirfor_ret = 1, fdiraft_ret = 1;
    1375             :         int tdirfor_ret = 1, tdiraft_ret = 1;
    1376           0 :         char *cp2;
    1377           0 :         struct nameidata fromnd, tond;
    1378           0 :         struct vnode *fvp = NULL, *tvp, *tdvp, *fdirp = NULL;
    1379           0 :         struct vnode *tdirp = NULL;
    1380           0 :         struct vattr fdirfor, fdiraft, tdirfor, tdiraft;
    1381           0 :         nfsfh_t fnfh, tnfh;
    1382             :         fhandle_t *ffhp, *tfhp;
    1383             :         uid_t saved_uid;
    1384             : 
    1385           0 :         info.nmi_mreq = NULL;
    1386           0 :         info.nmi_mrep = nfsd->nd_mrep;
    1387           0 :         info.nmi_md = nfsd->nd_md;
    1388           0 :         info.nmi_dpos = nfsd->nd_dpos;
    1389           0 :         info.nmi_v3 = (nfsd->nd_flag & ND_NFSV3);
    1390             : 
    1391           0 :         ffhp = &fnfh.fh_generic;
    1392           0 :         tfhp = &tnfh.fh_generic;
    1393           0 :         nfsm_srvmtofh(ffhp);
    1394           0 :         nfsm_srvnamesiz(len);
    1395             : 
    1396             :         /*
    1397             :          * Remember our original uid so that we can reset cr_uid before
    1398             :          * the second nfs_namei() call, in case it is remapped.
    1399             :          */
    1400           0 :         saved_uid = cred->cr_uid;
    1401             : 
    1402           0 :         NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_SYSSPACE, NULL,
    1403             :             procp);
    1404           0 :         fromnd.ni_cnd.cn_cred = cred;
    1405           0 :         error = nfs_namei(&fromnd, ffhp, len, slp, nam, &info.nmi_md,
    1406             :             &info.nmi_dpos, &fdirp, procp);
    1407           0 :         if (fdirp) {
    1408           0 :                 if (info.nmi_v3)
    1409           0 :                         fdirfor_ret = VOP_GETATTR(fdirp, &fdirfor, cred,
    1410             :                                 procp);
    1411             :                 else {
    1412           0 :                         vrele(fdirp);
    1413           0 :                         fdirp = NULL;
    1414             :                 }
    1415             :         }
    1416           0 :         if (error) {
    1417           0 :                 nfsm_reply(2 * NFSX_WCCDATA(info.nmi_v3));
    1418           0 :                 nfsm_srvwcc(nfsd, fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft,
    1419             :                     &info);
    1420           0 :                 nfsm_srvwcc(nfsd, tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft,
    1421             :                     &info);
    1422           0 :                 if (fdirp)
    1423           0 :                         vrele(fdirp);
    1424           0 :                 return (0);
    1425             :         }
    1426             : 
    1427           0 :         fvp = fromnd.ni_vp;
    1428           0 :         nfsm_srvmtofh(tfhp);
    1429           0 :         nfsm_strsiz(len2, NFS_MAXNAMLEN);
    1430           0 :         cred->cr_uid = saved_uid;
    1431             : 
    1432           0 :         NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF| NOCACHE | SAVESTART,
    1433             :             UIO_SYSSPACE, NULL, procp);
    1434           0 :         tond.ni_cnd.cn_cred = cred;
    1435           0 :         error = nfs_namei(&tond, tfhp, len2, slp, nam, &info.nmi_md,
    1436             :             &info.nmi_dpos, &tdirp, procp);
    1437           0 :         if (tdirp) {
    1438           0 :                 if (info.nmi_v3)
    1439           0 :                         tdirfor_ret = VOP_GETATTR(tdirp, &tdirfor, cred,
    1440             :                                 procp);
    1441             :                 else {
    1442           0 :                         vrele(tdirp);
    1443           0 :                         tdirp = NULL;
    1444             :                 }
    1445             :         }
    1446           0 :         if (error) {
    1447           0 :                 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
    1448           0 :                 vrele(fromnd.ni_dvp);
    1449           0 :                 vrele(fvp);
    1450           0 :                 goto out1;
    1451             :         }
    1452           0 :         tdvp = tond.ni_dvp;
    1453           0 :         tvp = tond.ni_vp;
    1454           0 :         if (tvp != NULL) {
    1455           0 :                 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
    1456           0 :                         error = info.nmi_v3 ? EEXIST : EISDIR;
    1457           0 :                         goto out;
    1458           0 :                 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
    1459           0 :                         error = info.nmi_v3 ? EEXIST : ENOTDIR;
    1460           0 :                         goto out;
    1461             :                 }
    1462           0 :                 if (tvp->v_type == VDIR && tvp->v_mountedhere) {
    1463           0 :                         error = info.nmi_v3 ? EXDEV : ENOTEMPTY;
    1464           0 :                         goto out;
    1465             :                 }
    1466             :         }
    1467           0 :         if (fvp->v_type == VDIR && fvp->v_mountedhere) {
    1468           0 :                 error = info.nmi_v3 ? EXDEV : ENOTEMPTY;
    1469           0 :                 goto out;
    1470             :         }
    1471           0 :         if (fvp->v_mount != tdvp->v_mount) {
    1472           0 :                 error = info.nmi_v3 ? EXDEV : ENOTEMPTY;
    1473           0 :                 goto out;
    1474             :         }
    1475           0 :         if (fvp == tdvp)
    1476           0 :                 error = info.nmi_v3 ? EINVAL : ENOTEMPTY;
    1477             :         /*
    1478             :          * If source is the same as the destination (that is the
    1479             :          * same vnode with the same name in the same directory),
    1480             :          * then there is nothing to do.
    1481             :          */
    1482           0 :         if (fvp == tvp && fromnd.ni_dvp == tdvp &&
    1483           0 :             fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
    1484           0 :             !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
    1485             :               fromnd.ni_cnd.cn_namelen))
    1486           0 :                 error = -1;
    1487             : out:
    1488           0 :         if (!error) {
    1489           0 :                 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
    1490           0 :                                    tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
    1491           0 :         } else {
    1492           0 :                 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
    1493           0 :                 if (tdvp == tvp)
    1494           0 :                         vrele(tdvp);
    1495             :                 else
    1496           0 :                         vput(tdvp);
    1497           0 :                 if (tvp)
    1498           0 :                         vput(tvp);
    1499           0 :                 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
    1500           0 :                 vrele(fromnd.ni_dvp);
    1501           0 :                 vrele(fvp);
    1502           0 :                 if (error == -1)
    1503           0 :                         error = 0;
    1504             :         }
    1505           0 :         vrele(tond.ni_startdir);
    1506           0 :         pool_put(&namei_pool, tond.ni_cnd.cn_pnbuf);
    1507             : out1:
    1508           0 :         if (fdirp) {
    1509           0 :                 fdiraft_ret = VOP_GETATTR(fdirp, &fdiraft, cred, procp);
    1510           0 :                 vrele(fdirp);
    1511           0 :         }
    1512           0 :         if (tdirp) {
    1513           0 :                 tdiraft_ret = VOP_GETATTR(tdirp, &tdiraft, cred, procp);
    1514           0 :                 vrele(tdirp);
    1515           0 :         }
    1516           0 :         vrele(fromnd.ni_startdir);
    1517           0 :         pool_put(&namei_pool, fromnd.ni_cnd.cn_pnbuf);
    1518           0 :         nfsm_reply(2 * NFSX_WCCDATA(info.nmi_v3));
    1519           0 :         if (info.nmi_v3) {
    1520           0 :                 nfsm_srvwcc(nfsd, fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft,
    1521             :                     &info);
    1522           0 :                 nfsm_srvwcc(nfsd, tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft,
    1523             :                     &info);
    1524           0 :         }
    1525           0 :         return (0);
    1526             : 
    1527             : nfsmout:
    1528           0 :         if (fdirp)
    1529           0 :                 vrele(fdirp);
    1530           0 :         if (tdirp)
    1531           0 :                 vrele(tdirp);
    1532           0 :         if (tond.ni_cnd.cn_nameiop) {
    1533           0 :                 vrele(tond.ni_startdir);
    1534           0 :                 pool_put(&namei_pool, tond.ni_cnd.cn_pnbuf);
    1535           0 :         }
    1536           0 :         if (fromnd.ni_cnd.cn_nameiop) {
    1537           0 :                 if (fromnd.ni_startdir)
    1538           0 :                         vrele(fromnd.ni_startdir);
    1539           0 :                 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
    1540             : 
    1541             :                 /*
    1542             :                  * XXX: Workaround the fact that fromnd.ni_dvp can point
    1543             :                  * to the same vnode as fdirp.
    1544             :                  */
    1545           0 :                 if (fromnd.ni_dvp != NULL && fromnd.ni_dvp != fdirp)
    1546           0 :                         vrele(fromnd.ni_dvp);
    1547           0 :                 if (fvp)
    1548           0 :                         vrele(fvp);
    1549             :         }
    1550           0 :         return (error);
    1551           0 : }
    1552             : 
    1553             : /*
    1554             :  * nfs link service
    1555             :  */
    1556             : int
    1557           0 : nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
    1558             :     struct proc *procp, struct mbuf **mrq)
    1559             : {
    1560           0 :         struct mbuf *nam = nfsd->nd_nam;
    1561           0 :         struct nfsm_info        info;
    1562           0 :         struct ucred *cred = &nfsd->nd_cr;
    1563           0 :         struct nameidata nd;
    1564             :         u_int32_t *tl;
    1565             :         int32_t t1;
    1566           0 :         int error = 0, rdonly, len, dirfor_ret = 1, diraft_ret = 1;
    1567             :         int getret = 1;
    1568           0 :         char *cp2;
    1569           0 :         struct vnode *vp, *xp, *dirp = NULL;
    1570           0 :         struct vattr dirfor, diraft, at;
    1571           0 :         nfsfh_t nfh, dnfh;
    1572             :         fhandle_t *fhp, *dfhp;
    1573             : 
    1574           0 :         info.nmi_mreq = NULL;
    1575           0 :         info.nmi_mrep = nfsd->nd_mrep;
    1576           0 :         info.nmi_md = nfsd->nd_md;
    1577           0 :         info.nmi_dpos = nfsd->nd_dpos;
    1578           0 :         info.nmi_v3 = (nfsd->nd_flag & ND_NFSV3);
    1579             : 
    1580           0 :         fhp = &nfh.fh_generic;
    1581           0 :         dfhp = &dnfh.fh_generic;
    1582           0 :         nfsm_srvmtofh(fhp);
    1583           0 :         nfsm_srvmtofh(dfhp);
    1584           0 :         nfsm_srvnamesiz(len);
    1585             : 
    1586           0 :         error = nfsrv_fhtovp(fhp, 0, &vp, cred, slp, nam, &rdonly);
    1587           0 :         if (error) {
    1588           0 :                 nfsm_reply(NFSX_POSTOPATTR(info.nmi_v3) +
    1589             :                     NFSX_WCCDATA(info.nmi_v3));
    1590           0 :                 nfsm_srvpostop_attr(nfsd, getret, &at, &info);
    1591           0 :                 nfsm_srvwcc(nfsd, dirfor_ret, &dirfor, diraft_ret, &diraft,
    1592             :                     &info);
    1593             :                 error = 0;
    1594           0 :                 goto nfsmout;
    1595             :         }
    1596           0 :         if (vp->v_type == VDIR && (error = suser_ucred(cred)) != 0)
    1597             :                 goto out1;
    1598             : 
    1599           0 :         NDINIT(&nd, CREATE, LOCKPARENT, UIO_SYSSPACE, NULL, procp);
    1600           0 :         nd.ni_cnd.cn_cred = cred;
    1601           0 :         error = nfs_namei(&nd, dfhp, len, slp, nam, &info.nmi_md,
    1602             :             &info.nmi_dpos, &dirp, procp);
    1603           0 :         if (dirp) {
    1604           0 :                 if (info.nmi_v3)
    1605           0 :                         dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
    1606             :                                 procp);
    1607             :                 else {
    1608           0 :                         vrele(dirp);
    1609           0 :                         dirp = NULL;
    1610             :                 }
    1611             :         }
    1612           0 :         if (error)
    1613             :                 goto out1;
    1614           0 :         xp = nd.ni_vp;
    1615           0 :         if (xp != NULL) {
    1616             :                 error = EEXIST;
    1617           0 :                 goto out;
    1618             :         }
    1619           0 :         xp = nd.ni_dvp;
    1620           0 :         if (vp->v_mount != xp->v_mount)
    1621           0 :                 error = EXDEV;
    1622             : out:
    1623           0 :         if (!error) {
    1624           0 :                 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
    1625           0 :         } else {
    1626           0 :                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
    1627           0 :                 if (nd.ni_dvp == nd.ni_vp)
    1628           0 :                         vrele(nd.ni_dvp);
    1629             :                 else
    1630           0 :                         vput(nd.ni_dvp);
    1631           0 :                 if (nd.ni_vp)
    1632           0 :                         vrele(nd.ni_vp);
    1633             :         }
    1634             : out1:
    1635           0 :         if (info.nmi_v3)
    1636           0 :                 getret = VOP_GETATTR(vp, &at, cred, procp);
    1637           0 :         if (dirp) {
    1638           0 :                 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
    1639           0 :                 vrele(dirp);
    1640           0 :         }
    1641           0 :         vrele(vp);
    1642           0 :         nfsm_reply(NFSX_POSTOPATTR(info.nmi_v3) + NFSX_WCCDATA(info.nmi_v3));
    1643           0 :         if (info.nmi_v3) {
    1644           0 :                 nfsm_srvpostop_attr(nfsd, getret, &at, &info);
    1645           0 :                 nfsm_srvwcc(nfsd, dirfor_ret, &dirfor, diraft_ret, &diraft,
    1646             :                      &info);
    1647             :                 error = 0;
    1648           0 :         }
    1649             : nfsmout:
    1650           0 :         return(error);
    1651           0 : }
    1652             : 
    1653             : /*
    1654             :  * nfs symbolic link service
    1655             :  */
    1656             : int
    1657           0 : nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
    1658             :     struct proc *procp, struct mbuf **mrq)
    1659             : {
    1660           0 :         struct mbuf *nam = nfsd->nd_nam;
    1661           0 :         struct ucred *cred = &nfsd->nd_cr;
    1662           0 :         struct vattr va, dirfor, diraft;
    1663           0 :         struct nameidata nd;
    1664           0 :         struct nfsm_info        info;
    1665             :         u_int32_t *tl;
    1666             :         int32_t t1;
    1667             :         struct nfsv2_sattr *sp;
    1668           0 :         char *pathcp = NULL, *cp2;
    1669           0 :         struct uio io;
    1670           0 :         struct iovec iv;
    1671             :         int error = 0, len, pathlen, len2, dirfor_ret = 1, diraft_ret = 1;
    1672           0 :         struct vnode *dirp = NULL;
    1673           0 :         nfsfh_t nfh;
    1674             :         fhandle_t *fhp;
    1675             : 
    1676           0 :         info.nmi_mreq = NULL;
    1677           0 :         info.nmi_mrep = nfsd->nd_mrep;
    1678           0 :         info.nmi_md = nfsd->nd_md;
    1679           0 :         info.nmi_dpos = nfsd->nd_dpos;
    1680           0 :         info.nmi_v3 = (nfsd->nd_flag & ND_NFSV3);
    1681             : 
    1682           0 :         fhp = &nfh.fh_generic;
    1683           0 :         nfsm_srvmtofh(fhp);
    1684           0 :         nfsm_srvnamesiz(len);
    1685             : 
    1686           0 :         NDINIT(&nd, CREATE, LOCKPARENT | SAVESTART, UIO_SYSSPACE, NULL, procp);
    1687           0 :         nd.ni_cnd.cn_cred = cred;
    1688           0 :         error = nfs_namei(&nd, fhp, len, slp, nam, &info.nmi_md,
    1689             :             &info.nmi_dpos, &dirp, procp);
    1690           0 :         if (dirp) {
    1691           0 :                 if (info.nmi_v3)
    1692           0 :                         dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
    1693             :                                 procp);
    1694             :                 else {
    1695           0 :                         vrele(dirp);
    1696           0 :                         dirp = NULL;
    1697             :                 }
    1698             :         }
    1699           0 :         if (error)
    1700             :                 goto out;
    1701           0 :         VATTR_NULL(&va);
    1702           0 :         if (info.nmi_v3) {
    1703           0 :                 error = nfsm_srvsattr(&info.nmi_md, &va, info.nmi_mrep,
    1704             :                     &info.nmi_dpos);
    1705           0 :                 if (error)
    1706             :                         goto nfsmout;
    1707             :         }
    1708           0 :         nfsm_strsiz(len2, NFS_MAXPATHLEN);
    1709           0 :         pathlen = len2 + 1;
    1710           0 :         pathcp = malloc(pathlen, M_TEMP, M_WAITOK);
    1711           0 :         iv.iov_base = pathcp;
    1712           0 :         iv.iov_len = len2;
    1713           0 :         io.uio_resid = len2;
    1714           0 :         io.uio_offset = 0;
    1715           0 :         io.uio_iov = &iv;
    1716           0 :         io.uio_iovcnt = 1;
    1717           0 :         io.uio_segflg = UIO_SYSSPACE;
    1718           0 :         io.uio_rw = UIO_READ;
    1719           0 :         io.uio_procp = NULL;
    1720           0 :         nfsm_mtouio(&io, len2);
    1721           0 :         if (!info.nmi_v3) {
    1722           0 :                 nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
    1723           0 :                 va.va_mode = fxdr_unsigned(u_int16_t, sp->sa_mode);
    1724           0 :         }
    1725           0 :         *(pathcp + len2) = '\0';
    1726           0 :         if (nd.ni_vp) {
    1727           0 :                 vrele(nd.ni_startdir);
    1728           0 :                 pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
    1729           0 :                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
    1730           0 :                 if (nd.ni_dvp == nd.ni_vp)
    1731           0 :                         vrele(nd.ni_dvp);
    1732             :                 else
    1733           0 :                         vput(nd.ni_dvp);
    1734           0 :                 vrele(nd.ni_vp);
    1735             :                 error = EEXIST;
    1736           0 :                 goto out;
    1737             :         }
    1738           0 :         error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va, pathcp);
    1739           0 :         if (error)
    1740           0 :                 vrele(nd.ni_startdir);
    1741             :         else {
    1742           0 :                 if (info.nmi_v3) {
    1743           0 :                         nd.ni_cnd.cn_nameiop = LOOKUP;
    1744           0 :                         nd.ni_cnd.cn_flags &= ~(LOCKPARENT | SAVESTART |
    1745             :                             FOLLOW);
    1746           0 :                         nd.ni_cnd.cn_flags |= (NOFOLLOW | LOCKLEAF);
    1747           0 :                         nd.ni_cnd.cn_proc = procp;
    1748           0 :                         nd.ni_cnd.cn_cred = cred;
    1749           0 :                         error = vfs_lookup(&nd);
    1750           0 :                         if (!error) {
    1751           0 :                                 memset(fhp, 0, sizeof(nfh));
    1752           0 :                                 fhp->fh_fsid =
    1753           0 :                                     nd.ni_vp->v_mount->mnt_stat.f_fsid;
    1754           0 :                                 error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid);
    1755           0 :                                 if (!error)
    1756           0 :                                         error = VOP_GETATTR(nd.ni_vp, &va, cred,
    1757             :                                             procp);
    1758           0 :                                 vput(nd.ni_vp);
    1759           0 :                         }
    1760             :                 } else
    1761           0 :                         vrele(nd.ni_startdir);
    1762           0 :                 pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
    1763             :         }
    1764             : out:
    1765           0 :         if (pathcp)
    1766           0 :                 free(pathcp, M_TEMP, pathlen);
    1767           0 :         if (dirp) {
    1768           0 :                 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
    1769           0 :                 vrele(dirp);
    1770           0 :         }
    1771           0 :         nfsm_reply(NFSX_SRVFH(info.nmi_v3) + NFSX_POSTOPATTR(info.nmi_v3)
    1772             :             + NFSX_WCCDATA(info.nmi_v3));
    1773           0 :         if (info.nmi_v3) {
    1774           0 :                 if (!error) {
    1775           0 :                         nfsm_srvpostop_fh(fhp);
    1776           0 :                         nfsm_srvpostop_attr(nfsd, 0, &va, &info);
    1777           0 :                 }
    1778           0 :                 nfsm_srvwcc(nfsd, dirfor_ret, &dirfor, diraft_ret, &diraft,
    1779             :                     &info);
    1780           0 :         }
    1781           0 :         return (0);
    1782             : nfsmout:
    1783           0 :         if (nd.ni_cnd.cn_nameiop) {
    1784           0 :                 vrele(nd.ni_startdir);
    1785           0 :                 pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
    1786           0 :         }
    1787           0 :         if (dirp)
    1788           0 :                 vrele(dirp);
    1789           0 :         VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
    1790           0 :         if (nd.ni_dvp == nd.ni_vp)
    1791           0 :                 vrele(nd.ni_dvp);
    1792             :         else
    1793           0 :                 vput(nd.ni_dvp);
    1794           0 :         if (nd.ni_vp)
    1795           0 :                 vrele(nd.ni_vp);
    1796           0 :         if (pathcp)
    1797           0 :                 free(pathcp, M_TEMP, pathlen);
    1798           0 :         return (error);
    1799           0 : }
    1800             : 
    1801             : /*
    1802             :  * nfs mkdir service
    1803             :  */
    1804             : int
    1805           0 : nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
    1806             :     struct proc *procp, struct mbuf **mrq)
    1807             : {
    1808           0 :         struct mbuf *nam = nfsd->nd_nam;
    1809           0 :         struct ucred *cred = &nfsd->nd_cr;
    1810           0 :         struct vattr va, dirfor, diraft;
    1811             :         struct nfs_fattr *fp;
    1812           0 :         struct nameidata nd;
    1813           0 :         struct nfsm_info        info;
    1814             :         u_int32_t *tl;
    1815             :         int32_t t1;
    1816             :         int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
    1817           0 :         char *cp2;
    1818           0 :         struct vnode *vp, *dirp = NULL;
    1819           0 :         nfsfh_t nfh;
    1820             :         fhandle_t *fhp;
    1821             : 
    1822           0 :         info.nmi_mreq = NULL;
    1823           0 :         info.nmi_mrep = nfsd->nd_mrep;
    1824           0 :         info.nmi_md = nfsd->nd_md;
    1825           0 :         info.nmi_dpos = nfsd->nd_dpos;
    1826           0 :         info.nmi_v3 = (nfsd->nd_flag & ND_NFSV3);
    1827             : 
    1828           0 :         fhp = &nfh.fh_generic;
    1829           0 :         nfsm_srvmtofh(fhp);
    1830           0 :         nfsm_srvnamesiz(len);
    1831             : 
    1832           0 :         NDINIT(&nd, CREATE, LOCKPARENT, UIO_SYSSPACE, NULL, procp);
    1833           0 :         nd.ni_cnd.cn_cred = cred;
    1834           0 :         error = nfs_namei(&nd, fhp, len, slp, nam, &info.nmi_md,
    1835             :             &info.nmi_dpos, &dirp, procp);
    1836           0 :         if (dirp) {
    1837           0 :                 if (info.nmi_v3)
    1838           0 :                         dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred, procp);
    1839             :                 else {
    1840           0 :                         vrele(dirp);
    1841           0 :                         dirp = NULL;
    1842             :                 }
    1843             :         }
    1844           0 :         if (error) {
    1845           0 :                 nfsm_reply(NFSX_WCCDATA(info.nmi_v3));
    1846           0 :                 nfsm_srvwcc(nfsd, dirfor_ret, &dirfor, diraft_ret, &diraft,
    1847             :                     &info);
    1848           0 :                 if (dirp)
    1849           0 :                         vrele(dirp);
    1850           0 :                 return (0);
    1851             :         }
    1852             : 
    1853           0 :         VATTR_NULL(&va);
    1854           0 :         if (info.nmi_v3) {
    1855           0 :                 error = nfsm_srvsattr(&info.nmi_md, &va, info.nmi_mrep,
    1856             :                     &info.nmi_dpos);
    1857           0 :                 if (error)
    1858             :                         goto nfsmout;
    1859             :         } else {
    1860           0 :                 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
    1861           0 :                 va.va_mode = nfstov_mode(*tl++);
    1862             :         }
    1863           0 :         va.va_type = VDIR;
    1864           0 :         vp = nd.ni_vp;
    1865           0 :         if (vp != NULL) {
    1866           0 :                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
    1867           0 :                 if (nd.ni_dvp == vp)
    1868           0 :                         vrele(nd.ni_dvp);
    1869             :                 else
    1870           0 :                         vput(nd.ni_dvp);
    1871           0 :                 vrele(vp);
    1872             :                 error = EEXIST;
    1873           0 :                 goto out;
    1874             :         }
    1875           0 :         error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va);
    1876           0 :         if (!error) {
    1877           0 :                 vp = nd.ni_vp;
    1878           0 :                 memset(fhp, 0, sizeof(nfh));
    1879           0 :                 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
    1880           0 :                 error = VFS_VPTOFH(vp, &fhp->fh_fid);
    1881           0 :                 if (!error)
    1882           0 :                         error = VOP_GETATTR(vp, &va, cred, procp);
    1883           0 :                 vput(vp);
    1884           0 :         }
    1885             : out:
    1886           0 :         if (dirp) {
    1887           0 :                 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
    1888           0 :                 vrele(dirp);
    1889           0 :         }
    1890           0 :         nfsm_reply(NFSX_SRVFH(info.nmi_v3) + NFSX_POSTOPATTR(info.nmi_v3) +
    1891             :             NFSX_WCCDATA(info.nmi_v3));
    1892           0 :         if (info.nmi_v3) {
    1893           0 :                 if (!error) {
    1894           0 :                         nfsm_srvpostop_fh(fhp);
    1895           0 :                         nfsm_srvpostop_attr(nfsd, 0, &va, &info);
    1896           0 :                 }
    1897           0 :                 nfsm_srvwcc(nfsd, dirfor_ret, &dirfor, diraft_ret, &diraft,
    1898             :                     &info);
    1899           0 :         } else {
    1900           0 :                 nfsm_srvfhtom(&info.nmi_mb, fhp, info.nmi_v3);
    1901           0 :                 fp = nfsm_build(&info.nmi_mb, NFSX_V2FATTR);
    1902           0 :                 nfsm_srvfattr(nfsd, &va, fp);
    1903             :         }
    1904           0 :         return (0);
    1905             : nfsmout:
    1906           0 :         if (dirp)
    1907           0 :                 vrele(dirp);
    1908           0 :         VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
    1909           0 :         if (nd.ni_dvp == nd.ni_vp)
    1910           0 :                 vrele(nd.ni_dvp);
    1911             :         else
    1912           0 :                 vput(nd.ni_dvp);
    1913           0 :         if (nd.ni_vp)
    1914           0 :                 vrele(nd.ni_vp);
    1915           0 :         return (error);
    1916           0 : }
    1917             : 
    1918             : /*
    1919             :  * nfs rmdir service
    1920             :  */
    1921             : int
    1922           0 : nfsrv_rmdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
    1923             :     struct proc *procp, struct mbuf **mrq)
    1924             : {
    1925           0 :         struct mbuf *nam = nfsd->nd_nam;
    1926           0 :         struct ucred *cred = &nfsd->nd_cr;
    1927           0 :         struct nfsm_info        info;
    1928             :         u_int32_t *tl;
    1929             :         int32_t t1;
    1930             :         int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
    1931           0 :         char *cp2;
    1932           0 :         struct vnode *vp, *dirp = NULL;
    1933           0 :         struct vattr dirfor, diraft;
    1934           0 :         nfsfh_t nfh;
    1935             :         fhandle_t *fhp;
    1936           0 :         struct nameidata nd;
    1937             : 
    1938           0 :         info.nmi_mreq = NULL;
    1939           0 :         info.nmi_mrep = nfsd->nd_mrep;
    1940           0 :         info.nmi_md = nfsd->nd_md;
    1941           0 :         info.nmi_dpos = nfsd->nd_dpos;
    1942           0 :         info.nmi_v3 = (nfsd->nd_flag & ND_NFSV3);
    1943             : 
    1944           0 :         fhp = &nfh.fh_generic;
    1945           0 :         nfsm_srvmtofh(fhp);
    1946           0 :         nfsm_srvnamesiz(len);
    1947             : 
    1948           0 :         NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_SYSSPACE, NULL, procp);
    1949           0 :         nd.ni_cnd.cn_cred = cred;
    1950           0 :         error = nfs_namei(&nd, fhp, len, slp, nam, &info.nmi_md,
    1951             :             &info.nmi_dpos, &dirp, procp);
    1952           0 :         if (dirp) {
    1953           0 :                 if (info.nmi_v3)
    1954           0 :                         dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
    1955             :                                 procp);
    1956             :                 else {
    1957           0 :                         vrele(dirp);
    1958           0 :                         dirp = NULL;
    1959             :                 }
    1960             :         }
    1961           0 :         if (error) {
    1962           0 :                 nfsm_reply(NFSX_WCCDATA(info.nmi_v3));
    1963           0 :                 nfsm_srvwcc(nfsd, dirfor_ret, &dirfor, diraft_ret, &diraft,
    1964             :                     &info);
    1965           0 :                 if (dirp)
    1966           0 :                         vrele(dirp);
    1967           0 :                 return (0);
    1968             :         }
    1969           0 :         vp = nd.ni_vp;
    1970           0 :         if (vp->v_type != VDIR) {
    1971             :                 error = ENOTDIR;
    1972           0 :                 goto out;
    1973             :         }
    1974             :         /*
    1975             :          * No rmdir "." please.
    1976             :          */
    1977           0 :         if (nd.ni_dvp == vp) {
    1978             :                 error = EINVAL;
    1979           0 :                 goto out;
    1980             :         }
    1981             :         /*
    1982             :          * A mounted on directory cannot be deleted.
    1983             :          */
    1984           0 :         if (vp->v_mountedhere != NULL) {
    1985             :                 error = EBUSY;
    1986           0 :                 goto out;
    1987             :         }
    1988             :         /*
    1989             :          * The root of a mounted filesystem cannot be deleted.
    1990             :          */
    1991           0 :         if (vp->v_flag & VROOT)
    1992           0 :                 error = EBUSY;
    1993             : out:
    1994           0 :         if (!error) {
    1995           0 :                 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
    1996           0 :         } else {
    1997           0 :                 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
    1998           0 :                 if (nd.ni_dvp == nd.ni_vp)
    1999           0 :                         vrele(nd.ni_dvp);
    2000             :                 else
    2001           0 :                         vput(nd.ni_dvp);
    2002           0 :                 vput(vp);
    2003             :         }
    2004           0 :         if (dirp) {
    2005           0 :                 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
    2006           0 :                 vrele(dirp);
    2007           0 :         }
    2008           0 :         nfsm_reply(NFSX_WCCDATA(info.nmi_v3));
    2009           0 :         if (info.nmi_v3) {
    2010           0 :                 nfsm_srvwcc(nfsd, dirfor_ret, &dirfor, diraft_ret, &diraft,
    2011             :                     &info);
    2012             :                 error = 0;
    2013           0 :         }
    2014             : nfsmout:
    2015           0 :         return(error);
    2016           0 : }
    2017             : 
    2018             : /*
    2019             :  * nfs readdir service
    2020             :  * - mallocs what it thinks is enough to read
    2021             :  *      count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR
    2022             :  * - calls VOP_READDIR()
    2023             :  * - loops around building the reply
    2024             :  *      if the output generated exceeds count break out of loop
    2025             :  * - it only knows that it has encountered eof when the VOP_READDIR()
    2026             :  *      reads nothing
    2027             :  * - as such one readdir rpc will return eof false although you are there
    2028             :  *      and then the next will return eof
    2029             :  * - it trims out records with d_fileno == 0
    2030             :  *      this doesn't matter for Unix clients, but they might confuse clients
    2031             :  *      for other os'.
    2032             :  * NB: It is tempting to set eof to true if the VOP_READDIR() reads less
    2033             :  *      than requested, but this may not apply to all filesystems. For
    2034             :  *      example, client NFS does not { although it is never remote mounted
    2035             :  *      anyhow }
    2036             :  *     The alternate call nfsrv_readdirplus() does lookups as well.
    2037             :  * PS: The NFS protocol spec. does not clarify what the "count" byte
    2038             :  *      argument is a count of.. just name strings and file id's or the
    2039             :  *      entire reply rpc or ...
    2040             :  *      I tried just file name and id sizes and it confused the Sun client,
    2041             :  *      so I am using the full rpc size now. The "paranoia.." comment refers
    2042             :  *      to including the status longwords that are not a part of the dir.
    2043             :  *      "entry" structures, but are in the rpc.
    2044             :  */
    2045             : struct flrep {
    2046             :         nfsuint64 fl_off;
    2047             :         u_int32_t fl_postopok;
    2048             :         u_int32_t fl_fattr[NFSX_V3FATTR / sizeof (u_int32_t)];
    2049             :         u_int32_t fl_fhok;
    2050             :         u_int32_t fl_fhsize;
    2051             :         u_int32_t fl_nfh[NFSX_V3FH / sizeof (u_int32_t)];
    2052             : };
    2053             : 
    2054             : int
    2055           0 : nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
    2056             :     struct proc *procp, struct mbuf **mrq)
    2057             : {
    2058           0 :         struct mbuf *nam = nfsd->nd_nam;
    2059           0 :         struct ucred *cred = &nfsd->nd_cr;
    2060             :         struct dirent *dp;
    2061           0 :         struct nfsm_info        info;
    2062             :         u_int32_t *tl;
    2063             :         int32_t t1;
    2064           0 :         char *cpos, *cend, *cp2, *rbuf;
    2065           0 :         struct vnode *vp;
    2066           0 :         struct vattr at;
    2067           0 :         nfsfh_t nfh;
    2068             :         fhandle_t *fhp;
    2069           0 :         struct uio io;
    2070           0 :         struct iovec iv;
    2071             :         int len, nlen, pad, xfer, error = 0, getret = 1;
    2072           0 :         int siz, cnt, fullsiz, eofflag, rdonly;
    2073             :         u_quad_t off, toff, verf;
    2074             : 
    2075           0 :         info.nmi_mreq = NULL;
    2076           0 :         info.nmi_mrep = nfsd->nd_mrep;
    2077           0 :         info.nmi_md = nfsd->nd_md;
    2078           0 :         info.nmi_dpos = nfsd->nd_dpos;
    2079           0 :         info.nmi_v3 = (nfsd->nd_flag & ND_NFSV3);
    2080             : 
    2081           0 :         fhp = &nfh.fh_generic;
    2082           0 :         nfsm_srvmtofh(fhp);
    2083           0 :         if (info.nmi_v3) {
    2084           0 :                 nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
    2085           0 :                 toff = fxdr_hyper(tl);
    2086           0 :                 tl += 2;
    2087           0 :                 verf = fxdr_hyper(tl);
    2088           0 :                 tl += 2;
    2089           0 :         } else {
    2090           0 :                 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
    2091           0 :                 toff = fxdr_unsigned(u_quad_t, *tl++);
    2092             :         }
    2093             :         off = toff;
    2094           0 :         cnt = fxdr_unsigned(int, *tl);
    2095           0 :         siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
    2096           0 :         xfer = NFS_SRVMAXDATA(nfsd);
    2097           0 :         if (siz > xfer)
    2098           0 :                 siz = xfer;
    2099           0 :         if (cnt > xfer)
    2100           0 :                 cnt = xfer;
    2101             :         fullsiz = siz;
    2102           0 :         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly);
    2103           0 :         if (error) {
    2104           0 :                 nfsm_reply(NFSX_UNSIGNED);
    2105           0 :                 nfsm_srvpostop_attr(nfsd, getret, &at, &info);
    2106             :                 error = 0;
    2107           0 :                 goto nfsmout;
    2108             :         }
    2109           0 :         if (info.nmi_v3)
    2110           0 :                 error = getret = VOP_GETATTR(vp, &at, cred, procp);
    2111           0 :         if (!error)
    2112           0 :                 error = nfsrv_access(vp, VEXEC, cred, rdonly, procp, 0);
    2113           0 :         if (error) {
    2114           0 :                 vput(vp);
    2115           0 :                 nfsm_reply(NFSX_POSTOPATTR(info.nmi_v3));
    2116           0 :                 nfsm_srvpostop_attr(nfsd, getret, &at, &info);
    2117             :                 error = 0;
    2118           0 :                 goto nfsmout;
    2119             :         }
    2120           0 :         VOP_UNLOCK(vp);
    2121           0 :         rbuf = malloc(fullsiz, M_TEMP, M_WAITOK);
    2122             : again:
    2123           0 :         iv.iov_base = rbuf;
    2124           0 :         iv.iov_len = fullsiz;
    2125           0 :         io.uio_iov = &iv;
    2126           0 :         io.uio_iovcnt = 1;
    2127           0 :         io.uio_offset = (off_t)off;
    2128           0 :         io.uio_resid = fullsiz;
    2129           0 :         io.uio_segflg = UIO_SYSSPACE;
    2130           0 :         io.uio_rw = UIO_READ;
    2131           0 :         io.uio_procp = NULL;
    2132           0 :         eofflag = 0;
    2133             : 
    2134           0 :         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
    2135           0 :         error = VOP_READDIR(vp, &io, cred, &eofflag);
    2136             : 
    2137           0 :         off = (off_t)io.uio_offset;
    2138           0 :         if (info.nmi_v3) {
    2139           0 :                 getret = VOP_GETATTR(vp, &at, cred, procp);
    2140           0 :                 if (!error)
    2141           0 :                         error = getret;
    2142             :         }
    2143             : 
    2144           0 :         VOP_UNLOCK(vp);
    2145           0 :         if (error) {
    2146           0 :                 vrele(vp);
    2147           0 :                 free(rbuf, M_TEMP, fullsiz);
    2148           0 :                 nfsm_reply(NFSX_POSTOPATTR(info.nmi_v3));
    2149           0 :                 nfsm_srvpostop_attr(nfsd, getret, &at, &info);
    2150             :                 error = 0;
    2151           0 :                 goto nfsmout;
    2152             :         }
    2153           0 :         if (io.uio_resid) {
    2154           0 :                 siz -= io.uio_resid;
    2155             : 
    2156             :                 /*
    2157             :                  * If nothing read, return eof
    2158             :                  * rpc reply
    2159             :                  */
    2160           0 :                 if (siz == 0) {
    2161           0 :                         vrele(vp);
    2162           0 :                         nfsm_reply(NFSX_POSTOPATTR(info.nmi_v3) + NFSX_COOKIEVERF(info.nmi_v3) +
    2163             :                                 2 * NFSX_UNSIGNED);
    2164           0 :                         if (info.nmi_v3) {
    2165           0 :                                 nfsm_srvpostop_attr(nfsd, getret, &at, &info);
    2166           0 :                                 tl = nfsm_build(&info.nmi_mb, 4 * NFSX_UNSIGNED);
    2167           0 :                                 txdr_hyper(at.va_filerev, tl);
    2168           0 :                                 tl += 2;
    2169           0 :                         } else
    2170           0 :                                 tl = nfsm_build(&info.nmi_mb, 2 * NFSX_UNSIGNED);
    2171           0 :                         *tl++ = nfs_false;
    2172           0 :                         *tl = nfs_true;
    2173           0 :                         free(rbuf, M_TEMP, fullsiz);
    2174             :                         error = 0;
    2175           0 :                         goto nfsmout;
    2176             :                 }
    2177             :         }
    2178             : 
    2179             :         /*
    2180             :          * Check for degenerate cases of nothing useful read.
    2181             :          * If so go try again
    2182             :          */
    2183             :         cpos = rbuf;
    2184           0 :         cend = rbuf + siz;
    2185           0 :         dp = (struct dirent *)cpos;
    2186             : 
    2187           0 :         while (cpos < cend && dp->d_fileno == 0) {
    2188           0 :                 cpos += dp->d_reclen;
    2189           0 :                 dp = (struct dirent *)cpos;
    2190             :         }
    2191           0 :         if (cpos >= cend) {
    2192             :                 toff = off;
    2193             :                 siz = fullsiz;
    2194           0 :                 goto again;
    2195             :         }
    2196             : 
    2197             :         len = 3 * NFSX_UNSIGNED;        /* paranoia, probably can be 0 */
    2198           0 :         nfsm_reply(NFSX_POSTOPATTR(info.nmi_v3) + NFSX_COOKIEVERF(info.nmi_v3) + siz);
    2199           0 :         if (info.nmi_v3) {
    2200           0 :                 nfsm_srvpostop_attr(nfsd, getret, &at, &info);
    2201           0 :                 tl = nfsm_build(&info.nmi_mb, 2 * NFSX_UNSIGNED);
    2202           0 :                 txdr_hyper(at.va_filerev, tl);
    2203           0 :         }
    2204             : 
    2205             :         /* Loop through the records and build reply */
    2206           0 :         while (cpos < cend) {
    2207           0 :                 if (dp->d_fileno != 0) {
    2208           0 :                         nlen = dp->d_namlen;
    2209           0 :                         pad = nfsm_padlen(nlen);
    2210           0 :                         len += (4 * NFSX_UNSIGNED + nlen + pad);
    2211           0 :                         if (info.nmi_v3)
    2212           0 :                                 len += 2 * NFSX_UNSIGNED;
    2213           0 :                         if (len > cnt) {
    2214           0 :                                 eofflag = 0;
    2215           0 :                                 break;
    2216             :                         }
    2217             :                         /*
    2218             :                          * Build the directory record xdr from
    2219             :                          * the dirent entry.
    2220             :                          */
    2221           0 :                         tl = nfsm_build(&info.nmi_mb,
    2222           0 :                             (info.nmi_v3 ? 3 : 2) * NFSX_UNSIGNED);
    2223           0 :                         *tl++ = nfs_true;
    2224           0 :                         if (info.nmi_v3)
    2225           0 :                                 txdr_hyper(dp->d_fileno, tl);
    2226             :                         else
    2227           0 :                                 *tl = txdr_unsigned((u_int32_t)dp->d_fileno);
    2228             :         
    2229             :                         /* And copy the name */
    2230           0 :                         nfsm_strtombuf(&info.nmi_mb, dp->d_name, nlen);
    2231             :         
    2232             :                         /* Finish off the record */
    2233           0 :                         if (info.nmi_v3) {
    2234           0 :                                 tl = nfsm_build(&info.nmi_mb, 2*NFSX_UNSIGNED);
    2235           0 :                                 txdr_hyper(dp->d_off, tl);
    2236           0 :                         } else {
    2237           0 :                                 tl = nfsm_build(&info.nmi_mb, NFSX_UNSIGNED);
    2238           0 :                                 *tl = txdr_unsigned((u_int32_t)dp->d_off);
    2239             :                         }
    2240             :                 }
    2241           0 :                 cpos += dp->d_reclen;
    2242           0 :                 dp = (struct dirent *)cpos;
    2243             :         }
    2244           0 :         vrele(vp);
    2245           0 :         tl = nfsm_build(&info.nmi_mb, 2 * NFSX_UNSIGNED);
    2246           0 :         *tl++ = nfs_false;
    2247           0 :         if (eofflag)
    2248           0 :                 *tl = nfs_true;
    2249             :         else
    2250           0 :                 *tl = nfs_false;
    2251           0 :         free(rbuf, M_TEMP, fullsiz);
    2252             : nfsmout:
    2253           0 :         return(error);
    2254           0 : }
    2255             : 
    2256             : int
    2257           0 : nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
    2258             :     struct proc *procp, struct mbuf **mrq)
    2259             : {
    2260           0 :         struct mbuf *nam = nfsd->nd_nam;
    2261           0 :         struct ucred *cred = &nfsd->nd_cr;
    2262             :         struct dirent *dp;
    2263           0 :         struct nfsm_info        info;
    2264             :         u_int32_t *tl;
    2265             :         int32_t t1;
    2266           0 :         char *cpos, *cend, *cp2, *rbuf;
    2267           0 :         struct vnode *vp, *nvp;
    2268           0 :         struct flrep fl;
    2269           0 :         nfsfh_t nfh;
    2270           0 :         fhandle_t *fhp, *nfhp = (fhandle_t *)fl.fl_nfh;
    2271           0 :         struct uio io;
    2272           0 :         struct iovec iv;
    2273           0 :         struct vattr va, at, *vap = &va;
    2274             :         struct nfs_fattr *fp;
    2275             :         int len, nlen, pad, xfer, error = 0, getret = 1;
    2276           0 :         int siz, cnt, fullsiz, eofflag, rdonly, dirlen;
    2277             :         u_quad_t off, toff, verf;
    2278             : 
    2279           0 :         info.nmi_mreq = NULL;
    2280           0 :         info.nmi_mrep = nfsd->nd_mrep;
    2281           0 :         info.nmi_md = nfsd->nd_md;
    2282           0 :         info.nmi_dpos = nfsd->nd_dpos;
    2283           0 :         info.nmi_v3 = (nfsd->nd_flag & ND_NFSV3);
    2284             : 
    2285           0 :         fhp = &nfh.fh_generic;
    2286           0 :         nfsm_srvmtofh(fhp);
    2287           0 :         nfsm_dissect(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
    2288           0 :         toff = fxdr_hyper(tl);
    2289           0 :         tl += 2;
    2290           0 :         verf = fxdr_hyper(tl);
    2291           0 :         tl += 2;
    2292           0 :         siz = fxdr_unsigned(int, *tl++);
    2293           0 :         cnt = fxdr_unsigned(int, *tl);
    2294             :         off = toff;
    2295           0 :         siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
    2296           0 :         xfer = NFS_SRVMAXDATA(nfsd);
    2297           0 :         if (siz > xfer)
    2298           0 :                 siz = xfer;
    2299           0 :         if (cnt > xfer)
    2300           0 :                 cnt = xfer;
    2301             :         fullsiz = siz;
    2302           0 :         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly);
    2303           0 :         if (error) {
    2304           0 :                 nfsm_reply(NFSX_UNSIGNED);
    2305           0 :                 nfsm_srvpostop_attr(nfsd, getret, &at, &info);
    2306             :                 error = 0;
    2307           0 :                 goto nfsmout;
    2308             :         }
    2309           0 :         error = getret = VOP_GETATTR(vp, &at, cred, procp);
    2310           0 :         if (!error)
    2311           0 :                 error = nfsrv_access(vp, VEXEC, cred, rdonly, procp, 0);
    2312           0 :         if (error) {
    2313           0 :                 vput(vp);
    2314           0 :                 nfsm_reply(NFSX_V3POSTOPATTR);
    2315           0 :                 nfsm_srvpostop_attr(nfsd, getret, &at, &info);
    2316             :                 error = 0;
    2317           0 :                 goto nfsmout;
    2318             :         }
    2319           0 :         VOP_UNLOCK(vp);
    2320             : 
    2321           0 :         rbuf = malloc(fullsiz, M_TEMP, M_WAITOK);
    2322             : again:
    2323           0 :         iv.iov_base = rbuf;
    2324           0 :         iv.iov_len = fullsiz;
    2325           0 :         io.uio_iov = &iv;
    2326           0 :         io.uio_iovcnt = 1;
    2327           0 :         io.uio_offset = (off_t)off;
    2328           0 :         io.uio_resid = fullsiz;
    2329           0 :         io.uio_segflg = UIO_SYSSPACE;
    2330           0 :         io.uio_rw = UIO_READ;
    2331           0 :         io.uio_procp = NULL;
    2332           0 :         eofflag = 0;
    2333             : 
    2334           0 :         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
    2335           0 :         error = VOP_READDIR(vp, &io, cred, &eofflag);
    2336             : 
    2337           0 :         off = (u_quad_t)io.uio_offset;
    2338           0 :         getret = VOP_GETATTR(vp, &at, cred, procp);
    2339             : 
    2340           0 :         VOP_UNLOCK(vp);
    2341             : 
    2342           0 :         if (!error)
    2343           0 :                 error = getret;
    2344           0 :         if (error) {
    2345           0 :                 vrele(vp);
    2346           0 :                 free(rbuf, M_TEMP, fullsiz);
    2347           0 :                 nfsm_reply(NFSX_V3POSTOPATTR);
    2348           0 :                 nfsm_srvpostop_attr(nfsd, getret, &at, &info);
    2349             :                 error = 0;
    2350           0 :                 goto nfsmout;
    2351             :         }
    2352           0 :         if (io.uio_resid) {
    2353           0 :                 siz -= io.uio_resid;
    2354             : 
    2355             :                 /*
    2356             :                  * If nothing read, return eof
    2357             :                  * rpc reply
    2358             :                  */
    2359           0 :                 if (siz == 0) {
    2360           0 :                         vrele(vp);
    2361           0 :                         nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
    2362             :                                 2 * NFSX_UNSIGNED);
    2363           0 :                         nfsm_srvpostop_attr(nfsd, getret, &at, &info);
    2364           0 :                         tl = nfsm_build(&info.nmi_mb, 4 * NFSX_UNSIGNED);
    2365           0 :                         txdr_hyper(at.va_filerev, tl);
    2366           0 :                         tl += 2;
    2367           0 :                         *tl++ = nfs_false;
    2368           0 :                         *tl = nfs_true;
    2369           0 :                         free(rbuf, M_TEMP, fullsiz);
    2370             :                         error = 0;
    2371           0 :                         goto nfsmout;
    2372             :                 }
    2373             :         }
    2374             : 
    2375             :         /*
    2376             :          * Check for degenerate cases of nothing useful read.
    2377             :          * If so go try again
    2378             :          */
    2379             :         cpos = rbuf;
    2380           0 :         cend = rbuf + siz;
    2381           0 :         dp = (struct dirent *)cpos;
    2382             : 
    2383           0 :         while (cpos < cend && dp->d_fileno == 0) {
    2384           0 :                 cpos += dp->d_reclen;
    2385           0 :                 dp = (struct dirent *)cpos;
    2386             :         }
    2387           0 :         if (cpos >= cend) {
    2388             :                 toff = off;
    2389             :                 siz = fullsiz;
    2390           0 :                 goto again;
    2391             :         }
    2392             : 
    2393             :         /*
    2394             :          * struct READDIRPLUS3resok {
    2395             :          *     postop_attr dir_attributes;
    2396             :          *     cookieverf3 cookieverf;
    2397             :          *     dirlistplus3 reply;
    2398             :          * }
    2399             :          *
    2400             :          * struct dirlistplus3 {
    2401             :          *     entryplus3  *entries;
    2402             :          *     bool eof;
    2403             :          *  }
    2404             :          */     
    2405             :         dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF + 2 * NFSX_UNSIGNED;
    2406           0 :         nfsm_reply(cnt);
    2407           0 :         nfsm_srvpostop_attr(nfsd, getret, &at, &info);
    2408           0 :         tl = nfsm_build(&info.nmi_mb, 2 * NFSX_UNSIGNED);
    2409           0 :         txdr_hyper(at.va_filerev, tl);
    2410             : 
    2411             :         /* Loop through the records and build reply */
    2412           0 :         while (cpos < cend) {
    2413           0 :                 if (dp->d_fileno != 0) {
    2414           0 :                         nlen = dp->d_namlen;
    2415           0 :                         pad = nfsm_padlen(nlen);
    2416             : 
    2417             :                         /*
    2418             :                          * For readdir_and_lookup get the vnode using
    2419             :                          * the file number.
    2420             :                          */
    2421           0 :                         if (VFS_VGET(vp->v_mount, dp->d_fileno, &nvp))
    2422             :                                 goto invalid;
    2423           0 :                         memset(nfhp, 0, NFSX_V3FH);
    2424           0 :                         nfhp->fh_fsid =
    2425           0 :                                 nvp->v_mount->mnt_stat.f_fsid;
    2426           0 :                         if (VFS_VPTOFH(nvp, &nfhp->fh_fid)) {
    2427           0 :                                 vput(nvp);
    2428           0 :                                 goto invalid;
    2429             :                         }
    2430           0 :                         if (VOP_GETATTR(nvp, vap, cred, procp)) {
    2431             :                                 vput(nvp);
    2432             :                                 goto invalid;
    2433             :                         }
    2434             :                         vput(nvp);
    2435             : 
    2436             :                         /*
    2437             :                          * If either the dircount or maxcount will be
    2438             :                          * exceeded, get out now. Both of these lengths
    2439             :                          * are calculated conservatively, including all
    2440             :                          * XDR overheads.
    2441             :                          *
    2442             :                          * Each entry:
    2443             :                          * 2 * NFSX_UNSIGNED for fileid3
    2444             :                          * 1 * NFSX_UNSIGNED for length of name
    2445             :                          * nlen + pad == space the name takes up
    2446             :                          * 2 * NFSX_UNSIGNED for the cookie
    2447             :                          * 1 * NFSX_UNSIGNED to indicate if file handle present
    2448             :                          * 1 * NFSX_UNSIGNED for the file handle length
    2449             :                          * NFSX_V3FH == space our file handle takes up
    2450             :                          * NFSX_V3POSTOPATTR == space the attributes take up
    2451             :                          * 1 * NFSX_UNSIGNED for next pointer
    2452             :                          */
    2453           0 :                         len += (8 * NFSX_UNSIGNED + nlen + pad + NFSX_V3FH +
    2454             :                                 NFSX_V3POSTOPATTR);
    2455           0 :                         dirlen += (6 * NFSX_UNSIGNED + nlen + pad);
    2456           0 :                         if (len > cnt || dirlen > fullsiz) {
    2457           0 :                                 eofflag = 0;
    2458           0 :                                 break;
    2459             :                         }
    2460             : 
    2461           0 :                         tl = nfsm_build(&info.nmi_mb, 3 * NFSX_UNSIGNED);
    2462           0 :                         *tl++ = nfs_true;
    2463           0 :                         txdr_hyper(dp->d_fileno, tl);
    2464             : 
    2465             :                         /* And copy the name */
    2466           0 :                         nfsm_strtombuf(&info.nmi_mb, dp->d_name, nlen);
    2467             : 
    2468             :                         /*
    2469             :                          * Build the directory record xdr from
    2470             :                          * the dirent entry.
    2471             :                          */
    2472           0 :                         fp = (struct nfs_fattr *)&fl.fl_fattr;
    2473           0 :                         nfsm_srvfattr(nfsd, vap, fp);
    2474           0 :                         fl.fl_fhsize = txdr_unsigned(NFSX_V3FH);
    2475           0 :                         fl.fl_fhok = nfs_true;
    2476           0 :                         fl.fl_postopok = nfs_true;
    2477           0 :                         txdr_hyper(dp->d_off, fl.fl_off.nfsuquad);
    2478             : 
    2479             :                         /* Now copy the flrep structure out. */
    2480           0 :                         nfsm_buftombuf(&info.nmi_mb, &fl, sizeof(struct flrep));
    2481           0 :                 }
    2482             : invalid:
    2483           0 :                 cpos += dp->d_reclen;
    2484           0 :                 dp = (struct dirent *)cpos;
    2485             :         }
    2486           0 :         vrele(vp);
    2487           0 :         tl = nfsm_build(&info.nmi_mb, 2 * NFSX_UNSIGNED);
    2488           0 :         *tl++ = nfs_false;
    2489           0 :         if (eofflag)
    2490           0 :                 *tl = nfs_true;
    2491             :         else
    2492           0 :                 *tl = nfs_false;
    2493           0 :         free(rbuf, M_TEMP, fullsiz);
    2494             : nfsmout:
    2495           0 :         return(error);
    2496           0 : }
    2497             : 
    2498             : /*
    2499             :  * nfs commit service
    2500             :  */
    2501             : int
    2502           0 : nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
    2503             :     struct proc *procp, struct mbuf **mrq)
    2504             : {
    2505           0 :         struct mbuf *nam = nfsd->nd_nam;
    2506           0 :         struct ucred *cred = &nfsd->nd_cr;
    2507           0 :         struct vattr bfor, aft;
    2508           0 :         struct vnode *vp;
    2509           0 :         struct nfsm_info        info;
    2510           0 :         nfsfh_t nfh;
    2511             :         fhandle_t *fhp;
    2512             :         u_int32_t *tl;
    2513             :         int32_t t1;
    2514           0 :         int error = 0, rdonly, for_ret = 1, aft_ret = 1, cnt;
    2515           0 :         char *cp2;
    2516             :         u_quad_t off;
    2517             :         
    2518           0 :         info.nmi_mreq = NULL;
    2519           0 :         info.nmi_mrep = nfsd->nd_mrep;
    2520           0 :         info.nmi_md = nfsd->nd_md;
    2521           0 :         info.nmi_dpos = nfsd->nd_dpos;
    2522           0 :         info.nmi_v3 = (nfsd->nd_flag & ND_NFSV3);
    2523             : 
    2524           0 :         fhp = &nfh.fh_generic;
    2525           0 :         nfsm_srvmtofh(fhp);
    2526           0 :         nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
    2527             : 
    2528             :         /*
    2529             :          * XXX At this time VOP_FSYNC() does not accept offset and byte
    2530             :          * count parameters, so these arguments are useless (someday maybe).
    2531             :          */
    2532           0 :         off = fxdr_hyper(tl);
    2533           0 :         tl += 2;
    2534           0 :         cnt = fxdr_unsigned(int, *tl);
    2535           0 :         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly);
    2536           0 :         if (error) {
    2537           0 :                 nfsm_reply(2 * NFSX_UNSIGNED);
    2538           0 :                 nfsm_srvwcc(nfsd, for_ret, &bfor, aft_ret, &aft, &info);
    2539             :                 error = 0;
    2540           0 :                 goto nfsmout;
    2541             :         }
    2542           0 :         for_ret = VOP_GETATTR(vp, &bfor, cred, procp);
    2543           0 :         error = VOP_FSYNC(vp, cred, MNT_WAIT, procp);
    2544           0 :         aft_ret = VOP_GETATTR(vp, &aft, cred, procp);
    2545           0 :         vput(vp);
    2546           0 :         nfsm_reply(NFSX_V3WCCDATA + NFSX_V3WRITEVERF);
    2547           0 :         nfsm_srvwcc(nfsd, for_ret, &bfor, aft_ret, &aft, &info);
    2548           0 :         if (!error) {
    2549           0 :                 tl = nfsm_build(&info.nmi_mb, NFSX_V3WRITEVERF);
    2550           0 :                 *tl++ = txdr_unsigned(boottime.tv_sec);
    2551           0 :                 *tl = txdr_unsigned(boottime.tv_nsec/1000);
    2552           0 :         } else
    2553             :                 error = 0;
    2554             : nfsmout:
    2555           0 :         return(error);
    2556           0 : }
    2557             : 
    2558             : /*
    2559             :  * nfs statfs service
    2560             :  */
    2561             : int
    2562           0 : nfsrv_statfs(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
    2563             :     struct proc *procp, struct mbuf **mrq)
    2564             : {
    2565           0 :         struct mbuf *nam = nfsd->nd_nam;
    2566           0 :         struct ucred *cred = &nfsd->nd_cr;
    2567             :         struct statfs *sf;
    2568             :         struct nfs_statfs *sfp;
    2569           0 :         struct nfsm_info        info;
    2570             :         u_int32_t *tl;
    2571             :         int32_t t1;
    2572           0 :         int error = 0, rdonly, getret = 1;
    2573           0 :         char *cp2;
    2574           0 :         struct vnode *vp;
    2575           0 :         struct vattr at;
    2576           0 :         nfsfh_t nfh;
    2577             :         fhandle_t *fhp;
    2578           0 :         struct statfs statfs;
    2579             :         u_quad_t tval;
    2580             : 
    2581           0 :         info.nmi_mreq = NULL;
    2582           0 :         info.nmi_mrep = nfsd->nd_mrep;
    2583           0 :         info.nmi_md = nfsd->nd_md;
    2584           0 :         info.nmi_dpos = nfsd->nd_dpos;
    2585           0 :         info.nmi_v3 = (nfsd->nd_flag & ND_NFSV3);
    2586             : 
    2587           0 :         fhp = &nfh.fh_generic;
    2588           0 :         nfsm_srvmtofh(fhp);
    2589           0 :         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly);
    2590           0 :         if (error) {
    2591           0 :                 nfsm_reply(NFSX_UNSIGNED);
    2592           0 :                 nfsm_srvpostop_attr(nfsd, getret, &at, &info);
    2593             :                 error = 0;
    2594           0 :                 goto nfsmout;
    2595             :         }
    2596             :         sf = &statfs;
    2597           0 :         error = VFS_STATFS(vp->v_mount, sf, procp);
    2598           0 :         getret = VOP_GETATTR(vp, &at, cred, procp);
    2599           0 :         vput(vp);
    2600           0 :         nfsm_reply(NFSX_POSTOPATTR(info.nmi_v3) + NFSX_STATFS(info.nmi_v3));
    2601           0 :         if (info.nmi_v3)
    2602           0 :                 nfsm_srvpostop_attr(nfsd, getret, &at, &info);
    2603           0 :         if (error) {
    2604             :                 error = 0;
    2605           0 :                 goto nfsmout;
    2606             :         }
    2607           0 :         sfp = nfsm_build(&info.nmi_mb, NFSX_STATFS(info.nmi_v3));
    2608           0 :         if (info.nmi_v3) {
    2609           0 :                 tval = (u_quad_t)sf->f_blocks;
    2610           0 :                 tval *= (u_quad_t)sf->f_bsize;
    2611           0 :                 txdr_hyper(tval, &sfp->sf_tbytes);
    2612           0 :                 tval = (u_quad_t)sf->f_bfree;
    2613           0 :                 tval *= (u_quad_t)sf->f_bsize;
    2614           0 :                 txdr_hyper(tval, &sfp->sf_fbytes);
    2615           0 :                 tval = (u_quad_t)sf->f_bavail;
    2616           0 :                 tval *= (u_quad_t)sf->f_bsize;
    2617           0 :                 txdr_hyper(tval, &sfp->sf_abytes);
    2618           0 :                 tval = (u_quad_t)sf->f_files;
    2619           0 :                 txdr_hyper(tval, &sfp->sf_tfiles);
    2620           0 :                 tval = (u_quad_t)sf->f_ffree;
    2621           0 :                 txdr_hyper(tval, &sfp->sf_ffiles);
    2622           0 :                 txdr_hyper(tval, &sfp->sf_afiles);
    2623           0 :                 sfp->sf_invarsec = 0;
    2624           0 :         } else {
    2625           0 :                 sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA);
    2626           0 :                 sfp->sf_bsize = txdr_unsigned(sf->f_bsize);
    2627           0 :                 sfp->sf_blocks = txdr_unsigned(sf->f_blocks);
    2628           0 :                 sfp->sf_bfree = txdr_unsigned(sf->f_bfree);
    2629           0 :                 sfp->sf_bavail = txdr_unsigned(sf->f_bavail);
    2630             :         }
    2631             : nfsmout:
    2632           0 :         return(error);
    2633           0 : }
    2634             : 
    2635             : /*
    2636             :  * nfs fsinfo service
    2637             :  */
    2638             : int
    2639           0 : nfsrv_fsinfo(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
    2640             :     struct proc *procp, struct mbuf **mrq)
    2641             : {
    2642           0 :         struct mbuf *nam = nfsd->nd_nam;
    2643           0 :         struct ucred *cred = &nfsd->nd_cr;
    2644           0 :         struct nfsm_info        info;
    2645             :         u_int32_t *tl;
    2646             :         struct nfsv3_fsinfo *sip;
    2647             :         int32_t t1;
    2648           0 :         int error = 0, rdonly, getret = 1, pref;
    2649           0 :         char *cp2;
    2650           0 :         struct vnode *vp;
    2651           0 :         struct vattr at;
    2652           0 :         nfsfh_t nfh;
    2653             :         fhandle_t *fhp;
    2654             : 
    2655           0 :         info.nmi_mreq = NULL;
    2656           0 :         info.nmi_mrep = nfsd->nd_mrep;
    2657           0 :         info.nmi_md = nfsd->nd_md;
    2658           0 :         info.nmi_dpos = nfsd->nd_dpos;
    2659           0 :         info.nmi_v3 = (nfsd->nd_flag & ND_NFSV3);
    2660             : 
    2661           0 :         fhp = &nfh.fh_generic;
    2662           0 :         nfsm_srvmtofh(fhp);
    2663           0 :         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly);
    2664           0 :         if (error) {
    2665           0 :                 nfsm_reply(NFSX_UNSIGNED);
    2666           0 :                 nfsm_srvpostop_attr(nfsd, getret, &at, &info);
    2667             :                 error = 0;
    2668           0 :                 goto nfsmout;
    2669             :         }
    2670           0 :         getret = VOP_GETATTR(vp, &at, cred, procp);
    2671           0 :         vput(vp);
    2672           0 :         nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO);
    2673           0 :         nfsm_srvpostop_attr(nfsd, getret, &at, &info);
    2674           0 :         sip = nfsm_build(&info.nmi_mb, NFSX_V3FSINFO);
    2675             : 
    2676             :         /*
    2677             :          * XXX
    2678             :          * There should be file system VFS OP(s) to get this information.
    2679             :          * For now, assume ufs.
    2680             :          */
    2681           0 :         if (slp->ns_so->so_type == SOCK_DGRAM)
    2682           0 :                 pref = NFS_MAXDGRAMDATA;
    2683             :         else
    2684             :                 pref = NFS_MAXDATA;
    2685           0 :         sip->fs_rtmax = txdr_unsigned(NFS_MAXDATA);
    2686           0 :         sip->fs_rtpref = txdr_unsigned(pref);
    2687           0 :         sip->fs_rtmult = txdr_unsigned(NFS_FABLKSIZE);
    2688           0 :         sip->fs_wtmax = txdr_unsigned(NFS_MAXDATA);
    2689           0 :         sip->fs_wtpref = txdr_unsigned(pref);
    2690           0 :         sip->fs_wtmult = txdr_unsigned(NFS_FABLKSIZE);
    2691           0 :         sip->fs_dtpref = txdr_unsigned(pref);
    2692           0 :         sip->fs_maxfilesize.nfsuquad[0] = 0xffffffff;
    2693           0 :         sip->fs_maxfilesize.nfsuquad[1] = 0xffffffff;
    2694           0 :         sip->fs_timedelta.nfsv3_sec = 0;
    2695           0 :         sip->fs_timedelta.nfsv3_nsec = txdr_unsigned(1);
    2696           0 :         sip->fs_properties = txdr_unsigned(NFSV3FSINFO_LINK |
    2697             :                 NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS |
    2698             :                 NFSV3FSINFO_CANSETTIME);
    2699             : nfsmout:
    2700           0 :         return(error);
    2701           0 : }
    2702             : 
    2703             : /*
    2704             :  * nfs pathconf service
    2705             :  */
    2706             : int
    2707           0 : nfsrv_pathconf(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
    2708             :     struct proc *procp, struct mbuf **mrq)
    2709             : {
    2710           0 :         struct mbuf *nam = nfsd->nd_nam;
    2711           0 :         struct ucred *cred = &nfsd->nd_cr;
    2712           0 :         struct nfsm_info        info;
    2713             :         u_int32_t *tl;
    2714             :         struct nfsv3_pathconf *pc;
    2715             :         int32_t t1;
    2716           0 :         int error = 0, rdonly, getret = 1;
    2717           0 :         register_t linkmax, namemax, chownres, notrunc;
    2718           0 :         char *cp2;
    2719           0 :         struct vnode *vp;
    2720           0 :         struct vattr at;
    2721           0 :         nfsfh_t nfh;
    2722             :         fhandle_t *fhp;
    2723             : 
    2724           0 :         info.nmi_mreq = NULL;
    2725           0 :         info.nmi_mrep = nfsd->nd_mrep;
    2726           0 :         info.nmi_md = nfsd->nd_md;
    2727           0 :         info.nmi_dpos = nfsd->nd_dpos;
    2728           0 :         info.nmi_v3 = (nfsd->nd_flag & ND_NFSV3);
    2729             : 
    2730           0 :         fhp = &nfh.fh_generic;
    2731           0 :         nfsm_srvmtofh(fhp);
    2732           0 :         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly);
    2733           0 :         if (error) {
    2734           0 :                 nfsm_reply(NFSX_UNSIGNED);
    2735           0 :                 nfsm_srvpostop_attr(nfsd, getret, &at, &info);
    2736             :                 error = 0;
    2737           0 :                 goto nfsmout;
    2738             :         }
    2739           0 :         error = VOP_PATHCONF(vp, _PC_LINK_MAX, &linkmax);
    2740           0 :         if (!error)
    2741           0 :                 error = VOP_PATHCONF(vp, _PC_NAME_MAX, &namemax);
    2742           0 :         if (!error)
    2743           0 :                 error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &chownres);
    2744           0 :         if (!error)
    2745           0 :                 error = VOP_PATHCONF(vp, _PC_NO_TRUNC, &notrunc);
    2746           0 :         getret = VOP_GETATTR(vp, &at, cred, procp);
    2747           0 :         vput(vp);
    2748           0 :         nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3PATHCONF);
    2749           0 :         nfsm_srvpostop_attr(nfsd, getret, &at, &info);
    2750           0 :         if (error) {
    2751             :                 error = 0;
    2752           0 :                 goto nfsmout;
    2753             :         }
    2754           0 :         pc = nfsm_build(&info.nmi_mb, NFSX_V3PATHCONF);
    2755             : 
    2756           0 :         pc->pc_linkmax = txdr_unsigned(linkmax);
    2757           0 :         pc->pc_namemax = txdr_unsigned(namemax);
    2758           0 :         pc->pc_notrunc = txdr_unsigned(notrunc);
    2759           0 :         pc->pc_chownrestricted = txdr_unsigned(chownres);
    2760             : 
    2761             :         /*
    2762             :          * These should probably be supported by VOP_PATHCONF(), but
    2763             :          * until msdosfs is exportable (why would you want to?), the
    2764             :          * Unix defaults should be ok.
    2765             :          */
    2766           0 :         pc->pc_caseinsensitive = nfs_false;
    2767           0 :         pc->pc_casepreserving = nfs_true;
    2768             : nfsmout:
    2769           0 :         return(error);
    2770           0 : }
    2771             : 
    2772             : /*
    2773             :  * Null operation, used by clients to ping server
    2774             :  */
    2775             : /* ARGSUSED */
    2776             : int
    2777           0 : nfsrv_null(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
    2778             :     struct proc *procp, struct mbuf **mrq)
    2779             : {
    2780           0 :         struct nfsm_info        info;
    2781             :         int error = NFSERR_RETVOID;
    2782             : 
    2783           0 :         info.nmi_mreq = NULL;
    2784           0 :         info.nmi_mrep = nfsd->nd_mrep;
    2785           0 :         info.nmi_md = nfsd->nd_md;
    2786           0 :         info.nmi_dpos = nfsd->nd_dpos;
    2787           0 :         info.nmi_v3 = (nfsd->nd_flag & ND_NFSV3);
    2788             : 
    2789           0 :         nfsm_reply(0);
    2790           0 :         return (0);
    2791           0 : }
    2792             : 
    2793             : /*
    2794             :  * No operation, used for obsolete procedures
    2795             :  */
    2796             : /* ARGSUSED */
    2797             : int
    2798           0 : nfsrv_noop(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
    2799             :     struct proc *procp, struct mbuf **mrq)
    2800             : {       
    2801           0 :         struct nfsm_info        info;
    2802             :         int error;
    2803             : 
    2804           0 :         info.nmi_mreq = NULL;
    2805           0 :         info.nmi_mrep = nfsd->nd_mrep;
    2806           0 :         info.nmi_md = nfsd->nd_md;
    2807           0 :         info.nmi_dpos = nfsd->nd_dpos;
    2808           0 :         info.nmi_v3 = (nfsd->nd_flag & ND_NFSV3);
    2809             : 
    2810           0 :         if (nfsd->nd_repstat)
    2811           0 :                 error = nfsd->nd_repstat;
    2812             :         else
    2813             :                 error = EPROCUNAVAIL;
    2814           0 :         nfsm_reply(0);
    2815           0 :         return (0);
    2816           0 : }
    2817             : 
    2818             : /*
    2819             :  * Perform access checking for vnodes obtained from file handles that would
    2820             :  * refer to files already opened by a Unix client.
    2821             :  * You cannot just use vn_writechk() and VOP_ACCESS() for two reasons:
    2822             :  * 1 - You must check for exported rdonly as well as MNT_RDONLY for the
    2823             :  *     write case
    2824             :  * 2 - The owner is to be given access irrespective of mode bits for some
    2825             :  *     operations, so that processes that chmod after opening a file don't
    2826             :  *     break. I don't like this because it opens a security hole, but since
    2827             :  *     the nfs server opens a security hole the size of a barn door anyhow,
    2828             :  *     what the heck. A notable exception to this rule is when VOP_ACCESS()
    2829             :  *     returns EPERM (e.g. when a file is immutable) which is always an
    2830             :  *     error.
    2831             :  */
    2832             : int
    2833           0 : nfsrv_access(struct vnode *vp, int flags, struct ucred *cred, int rdonly,
    2834             :     struct proc *p, int override)
    2835             : {
    2836           0 :         struct vattr vattr;
    2837             :         int error;
    2838             : 
    2839           0 :         if (flags & VWRITE) {
    2840             :                 /* Just vn_writechk() changed to check rdonly */
    2841             :                 /*
    2842             :                  * Disallow write attempts on read-only file systems;
    2843             :                  * unless the file is a socket or a block or character
    2844             :                  * device resident on the file system.
    2845             :                  */
    2846           0 :                 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
    2847           0 :                         switch (vp->v_type) {
    2848             :                         case VREG:
    2849             :                         case VDIR:
    2850             :                         case VLNK:
    2851           0 :                                 return (EROFS);
    2852             :                         default:
    2853             :                                 break;
    2854             :                         }
    2855             :                 }
    2856             :                 /*
    2857             :                  * If there's shared text associated with
    2858             :                  * the inode, try to free it up once.  If
    2859             :                  * we fail, we can't allow writing.
    2860             :                  */
    2861           0 :                 if ((vp->v_flag & VTEXT) && !uvm_vnp_uncache(vp))
    2862           0 :                         return (ETXTBSY);
    2863             :         }
    2864           0 :         error = VOP_ACCESS(vp, flags, cred, p);
    2865             :         /*
    2866             :          * Allow certain operations for the owner (reads and writes
    2867             :          * on files that are already open).
    2868             :          */
    2869           0 :         if (override && error == EACCES &&
    2870           0 :             VOP_GETATTR(vp, &vattr, cred, p) == 0 &&
    2871           0 :             cred->cr_uid == vattr.va_uid)
    2872           0 :                 error = 0;
    2873           0 :         return error;
    2874           0 : }

Generated by: LCOV version 1.13