The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/nfsserver/nfs_nfsdserv.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-3-Clause
    3  *
    4  * Copyright (c) 1989, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * This code is derived from software contributed to Berkeley by
    8  * Rick Macklem at The University of Guelph.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. Neither the name of the University nor the names of its contributors
   19  *    may be used to endorse or promote products derived from this software
   20  *    without specific prior written permission.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  *
   34  */
   35 
   36 #include <sys/cdefs.h>
   37 __FBSDID("$FreeBSD$");
   38 
   39 #include "opt_inet.h"
   40 #include "opt_inet6.h"
   41 /*
   42  * nfs version 2, 3 and 4 server calls to vnode ops
   43  * - these routines generally have 3 phases
   44  *   1 - break down and validate rpc request in mbuf list
   45  *   2 - do the vnode ops for the request, usually by calling a nfsvno_XXX()
   46  *       function in nfsd_port.c
   47  *   3 - build the rpc reply in an mbuf list
   48  * For nfsv4, these functions are called for each Op within the Compound RPC.
   49  */
   50 
   51 #include <fs/nfs/nfsport.h>
   52 #include <sys/extattr.h>
   53 #include <sys/filio.h>
   54 
   55 /* Global vars */
   56 extern u_int32_t newnfs_false, newnfs_true;
   57 extern enum vtype nv34tov_type[8];
   58 extern struct timeval nfsboottime;
   59 extern int nfs_rootfhset;
   60 extern int nfsrv_enable_crossmntpt;
   61 extern int nfsrv_statehashsize;
   62 extern int nfsrv_layouthashsize;
   63 extern time_t nfsdev_time;
   64 extern volatile int nfsrv_devidcnt;
   65 extern int nfsd_debuglevel;
   66 extern u_long sb_max_adj;
   67 extern int nfsrv_pnfsatime;
   68 extern int nfsrv_maxpnfsmirror;
   69 extern int nfs_maxcopyrange;
   70 
   71 static int      nfs_async = 0;
   72 SYSCTL_DECL(_vfs_nfsd);
   73 SYSCTL_INT(_vfs_nfsd, OID_AUTO, async, CTLFLAG_RW, &nfs_async, 0,
   74     "Tell client that writes were synced even though they were not");
   75 extern int      nfsrv_doflexfile;
   76 SYSCTL_INT(_vfs_nfsd, OID_AUTO, default_flexfile, CTLFLAG_RW,
   77     &nfsrv_doflexfile, 0, "Make Flex File Layout the default for pNFS");
   78 static int      nfsrv_linux42server = 1;
   79 SYSCTL_INT(_vfs_nfsd, OID_AUTO, linux42server, CTLFLAG_RW,
   80     &nfsrv_linux42server, 0,
   81     "Enable Linux style NFSv4.2 server (non-RFC compliant)");
   82 static bool     nfsrv_openaccess = true;
   83 SYSCTL_BOOL(_vfs_nfsd, OID_AUTO, v4openaccess, CTLFLAG_RW,
   84     &nfsrv_openaccess, 0,
   85     "Enable Linux style NFSv4 Open access check");
   86 
   87 /*
   88  * This list defines the GSS mechanisms supported.
   89  * (Don't ask me how you get these strings from the RFC stuff like
   90  *  iso(1), org(3)... but someone did it, so I don't need to know.)
   91  */
   92 static struct nfsgss_mechlist nfsgss_mechlist[] = {
   93         { 9, "\052\206\110\206\367\022\001\002\002", 11 },
   94         { 0, "", 0 },
   95 };
   96 
   97 /* local functions */
   98 static void nfsrvd_symlinksub(struct nfsrv_descript *nd, struct nameidata *ndp,
   99     struct nfsvattr *nvap, fhandle_t *fhp, vnode_t *vpp,
  100     vnode_t dirp, struct nfsvattr *dirforp, struct nfsvattr *diraftp,
  101     int *diraft_retp, nfsattrbit_t *attrbitp,
  102     NFSACL_T *aclp, NFSPROC_T *p, struct nfsexstuff *exp, char *pathcp,
  103     int pathlen);
  104 static void nfsrvd_mkdirsub(struct nfsrv_descript *nd, struct nameidata *ndp,
  105     struct nfsvattr *nvap, fhandle_t *fhp, vnode_t *vpp,
  106     vnode_t dirp, struct nfsvattr *dirforp, struct nfsvattr *diraftp,
  107     int *diraft_retp, nfsattrbit_t *attrbitp, NFSACL_T *aclp,
  108     NFSPROC_T *p, struct nfsexstuff *exp);
  109 
  110 /*
  111  * nfs access service (not a part of NFS V2)
  112  */
  113 int
  114 nfsrvd_access(struct nfsrv_descript *nd, __unused int isdgram,
  115     vnode_t vp, struct nfsexstuff *exp)
  116 {
  117         u_int32_t *tl;
  118         int getret, error = 0;
  119         struct nfsvattr nva;
  120         u_int32_t testmode, nfsmode, supported = 0;
  121         accmode_t deletebit;
  122         struct thread *p = curthread;
  123 
  124         if (nd->nd_repstat) {
  125                 nfsrv_postopattr(nd, 1, &nva);
  126                 goto out;
  127         }
  128         NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
  129         nfsmode = fxdr_unsigned(u_int32_t, *tl);
  130         if ((nd->nd_flag & ND_NFSV4) &&
  131             (nfsmode & ~(NFSACCESS_READ | NFSACCESS_LOOKUP |
  132              NFSACCESS_MODIFY | NFSACCESS_EXTEND | NFSACCESS_DELETE |
  133              NFSACCESS_EXECUTE | NFSACCESS_XAREAD | NFSACCESS_XAWRITE |
  134              NFSACCESS_XALIST))) {
  135                 nd->nd_repstat = NFSERR_INVAL;
  136                 vput(vp);
  137                 goto out;
  138         }
  139         if (nfsmode & NFSACCESS_READ) {
  140                 supported |= NFSACCESS_READ;
  141                 if (nfsvno_accchk(vp, VREAD, nd->nd_cred, exp, p,
  142                     NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported))
  143                         nfsmode &= ~NFSACCESS_READ;
  144         }
  145         if (nfsmode & NFSACCESS_MODIFY) {
  146                 supported |= NFSACCESS_MODIFY;
  147                 if (nfsvno_accchk(vp, VWRITE, nd->nd_cred, exp, p,
  148                     NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported))
  149                         nfsmode &= ~NFSACCESS_MODIFY;
  150         }
  151         if (nfsmode & NFSACCESS_EXTEND) {
  152                 supported |= NFSACCESS_EXTEND;
  153                 if (nfsvno_accchk(vp, VWRITE | VAPPEND, nd->nd_cred, exp, p,
  154                     NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported))
  155                         nfsmode &= ~NFSACCESS_EXTEND;
  156         }
  157         if (nfsmode & NFSACCESS_XAREAD) {
  158                 supported |= NFSACCESS_XAREAD;
  159                 if (nfsvno_accchk(vp, VREAD, nd->nd_cred, exp, p,
  160                     NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported))
  161                         nfsmode &= ~NFSACCESS_XAREAD;
  162         }
  163         if (nfsmode & NFSACCESS_XAWRITE) {
  164                 supported |= NFSACCESS_XAWRITE;
  165                 if (nfsvno_accchk(vp, VWRITE, nd->nd_cred, exp, p,
  166                     NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported))
  167                         nfsmode &= ~NFSACCESS_XAWRITE;
  168         }
  169         if (nfsmode & NFSACCESS_XALIST) {
  170                 supported |= NFSACCESS_XALIST;
  171                 if (nfsvno_accchk(vp, VREAD, nd->nd_cred, exp, p,
  172                     NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported))
  173                         nfsmode &= ~NFSACCESS_XALIST;
  174         }
  175         if (nfsmode & NFSACCESS_DELETE) {
  176                 supported |= NFSACCESS_DELETE;
  177                 if (vp->v_type == VDIR)
  178                         deletebit = VDELETE_CHILD;
  179                 else
  180                         deletebit = VDELETE;
  181                 if (nfsvno_accchk(vp, deletebit, nd->nd_cred, exp, p,
  182                     NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported))
  183                         nfsmode &= ~NFSACCESS_DELETE;
  184         }
  185         if (vnode_vtype(vp) == VDIR)
  186                 testmode = NFSACCESS_LOOKUP;
  187         else
  188                 testmode = NFSACCESS_EXECUTE;
  189         if (nfsmode & testmode) {
  190                 supported |= (nfsmode & testmode);
  191                 if (nfsvno_accchk(vp, VEXEC, nd->nd_cred, exp, p,
  192                     NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported))
  193                         nfsmode &= ~testmode;
  194         }
  195         nfsmode &= supported;
  196         if (nd->nd_flag & ND_NFSV3) {
  197                 getret = nfsvno_getattr(vp, &nva, nd, p, 1, NULL);
  198                 nfsrv_postopattr(nd, getret, &nva);
  199         }
  200         vput(vp);
  201         if (nd->nd_flag & ND_NFSV4) {
  202                 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
  203                 *tl++ = txdr_unsigned(supported);
  204         } else
  205                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
  206         *tl = txdr_unsigned(nfsmode);
  207 
  208 out:
  209         NFSEXITCODE2(0, nd);
  210         return (0);
  211 nfsmout:
  212         vput(vp);
  213         NFSEXITCODE2(error, nd);
  214         return (error);
  215 }
  216 
  217 /*
  218  * nfs getattr service
  219  */
  220 int
  221 nfsrvd_getattr(struct nfsrv_descript *nd, int isdgram,
  222     vnode_t vp, __unused struct nfsexstuff *exp)
  223 {
  224         struct nfsvattr nva;
  225         fhandle_t fh;
  226         int at_root = 0, error = 0, supports_nfsv4acls;
  227         struct nfsreferral *refp;
  228         nfsattrbit_t attrbits, tmpbits;
  229         struct mount *mp;
  230         struct vnode *tvp = NULL;
  231         struct vattr va;
  232         uint64_t mounted_on_fileno = 0;
  233         accmode_t accmode;
  234         struct thread *p = curthread;
  235 
  236         if (nd->nd_repstat)
  237                 goto out;
  238         if (nd->nd_flag & ND_NFSV4) {
  239                 error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL);
  240                 if (error) {
  241                         vput(vp);
  242                         goto out;
  243                 }
  244 
  245                 /*
  246                  * Check for a referral.
  247                  */
  248                 refp = nfsv4root_getreferral(vp, NULL, 0);
  249                 if (refp != NULL) {
  250                         (void) nfsrv_putreferralattr(nd, &attrbits, refp, 1,
  251                             &nd->nd_repstat);
  252                         vput(vp);
  253                         goto out;
  254                 }
  255                 if (nd->nd_repstat == 0) {
  256                         accmode = 0;
  257                         NFSSET_ATTRBIT(&tmpbits, &attrbits);
  258 
  259                         /*
  260                          * GETATTR with write-only attr time_access_set and time_modify_set
  261                          * should return NFS4ERR_INVAL.
  262                          */
  263                         if (NFSISSET_ATTRBIT(&tmpbits, NFSATTRBIT_TIMEACCESSSET) ||
  264                                         NFSISSET_ATTRBIT(&tmpbits, NFSATTRBIT_TIMEMODIFYSET)){
  265                                 error = NFSERR_INVAL;
  266                                 vput(vp);
  267                                 goto out;
  268                         }
  269                         if (NFSISSET_ATTRBIT(&tmpbits, NFSATTRBIT_ACL)) {
  270                                 NFSCLRBIT_ATTRBIT(&tmpbits, NFSATTRBIT_ACL);
  271                                 accmode |= VREAD_ACL;
  272                         }
  273                         if (NFSNONZERO_ATTRBIT(&tmpbits))
  274                                 accmode |= VREAD_ATTRIBUTES;
  275                         if (accmode != 0)
  276                                 nd->nd_repstat = nfsvno_accchk(vp, accmode,
  277                                     nd->nd_cred, exp, p, NFSACCCHK_NOOVERRIDE,
  278                                     NFSACCCHK_VPISLOCKED, NULL);
  279                 }
  280         }
  281         if (!nd->nd_repstat)
  282                 nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1, &attrbits);
  283         if (!nd->nd_repstat) {
  284                 if (nd->nd_flag & ND_NFSV4) {
  285                         if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_FILEHANDLE))
  286                                 nd->nd_repstat = nfsvno_getfh(vp, &fh, p);
  287                         if (!nd->nd_repstat)
  288                                 nd->nd_repstat = nfsrv_checkgetattr(nd, vp,
  289                                     &nva, &attrbits, p);
  290                         if (nd->nd_repstat == 0) {
  291                                 supports_nfsv4acls = nfs_supportsnfsv4acls(vp);
  292                                 mp = vp->v_mount;
  293                                 if (nfsrv_enable_crossmntpt != 0 &&
  294                                     vp->v_type == VDIR &&
  295                                     (vp->v_vflag & VV_ROOT) != 0 &&
  296                                     vp != rootvnode) {
  297                                         tvp = mp->mnt_vnodecovered;
  298                                         VREF(tvp);
  299                                         at_root = 1;
  300                                 } else
  301                                         at_root = 0;
  302                                 vfs_ref(mp);
  303                                 NFSVOPUNLOCK(vp);
  304                                 if (at_root != 0) {
  305                                         if ((nd->nd_repstat =
  306                                              NFSVOPLOCK(tvp, LK_SHARED)) == 0) {
  307                                                 nd->nd_repstat = VOP_GETATTR(
  308                                                     tvp, &va, nd->nd_cred);
  309                                                 vput(tvp);
  310                                         } else
  311                                                 vrele(tvp);
  312                                         if (nd->nd_repstat == 0)
  313                                                 mounted_on_fileno = (uint64_t)
  314                                                     va.va_fileid;
  315                                         else
  316                                                 at_root = 0;
  317                                 }
  318                                 if (nd->nd_repstat == 0)
  319                                         nd->nd_repstat = vfs_busy(mp, 0);
  320                                 vfs_rel(mp);
  321                                 if (nd->nd_repstat == 0) {
  322                                         (void)nfsvno_fillattr(nd, mp, vp, &nva,
  323                                             &fh, 0, &attrbits, nd->nd_cred, p,
  324                                             isdgram, 1, supports_nfsv4acls,
  325                                             at_root, mounted_on_fileno);
  326                                         vfs_unbusy(mp);
  327                                 }
  328                                 vrele(vp);
  329                         } else
  330                                 vput(vp);
  331                 } else {
  332                         nfsrv_fillattr(nd, &nva);
  333                         vput(vp);
  334                 }
  335         } else {
  336                 vput(vp);
  337         }
  338 
  339 out:
  340         NFSEXITCODE2(error, nd);
  341         return (error);
  342 }
  343 
  344 /*
  345  * nfs setattr service
  346  */
  347 int
  348 nfsrvd_setattr(struct nfsrv_descript *nd, __unused int isdgram,
  349     vnode_t vp, struct nfsexstuff *exp)
  350 {
  351         struct nfsvattr nva, nva2;
  352         u_int32_t *tl;
  353         int preat_ret = 1, postat_ret = 1, gcheck = 0, error = 0;
  354         int gotproxystateid;
  355         struct timespec guard = { 0, 0 };
  356         nfsattrbit_t attrbits, retbits;
  357         nfsv4stateid_t stateid;
  358         NFSACL_T *aclp = NULL;
  359         struct thread *p = curthread;
  360 
  361         if (nd->nd_repstat) {
  362                 nfsrv_wcc(nd, preat_ret, &nva2, postat_ret, &nva);
  363                 goto out;
  364         }
  365 #ifdef NFS4_ACL_EXTATTR_NAME
  366         aclp = acl_alloc(M_WAITOK);
  367         aclp->acl_cnt = 0;
  368 #endif
  369         gotproxystateid = 0;
  370         NFSVNO_ATTRINIT(&nva);
  371         if (nd->nd_flag & ND_NFSV4) {
  372                 NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID);
  373                 stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
  374                 stateid.other[0] = *tl++;
  375                 stateid.other[1] = *tl++;
  376                 stateid.other[2] = *tl;
  377                 if (stateid.other[0] == 0x55555555 &&
  378                     stateid.other[1] == 0x55555555 &&
  379                     stateid.other[2] == 0x55555555 &&
  380                     stateid.seqid == 0xffffffff)
  381                         gotproxystateid = 1;
  382         }
  383         error = nfsrv_sattr(nd, vp, &nva, &attrbits, aclp, p);
  384         if (error)
  385                 goto nfsmout;
  386 
  387         /* For NFSv4, only va_uid is used from nva2. */
  388         NFSZERO_ATTRBIT(&retbits);
  389         NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_OWNER);
  390         preat_ret = nfsvno_getattr(vp, &nva2, nd, p, 1, &retbits);
  391         if (!nd->nd_repstat)
  392                 nd->nd_repstat = preat_ret;
  393 
  394         NFSZERO_ATTRBIT(&retbits);
  395         if (nd->nd_flag & ND_NFSV3) {
  396                 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
  397                 gcheck = fxdr_unsigned(int, *tl);
  398                 if (gcheck) {
  399                         NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
  400                         fxdr_nfsv3time(tl, &guard);
  401                 }
  402                 if (!nd->nd_repstat && gcheck &&
  403                     (nva2.na_ctime.tv_sec != guard.tv_sec ||
  404                      nva2.na_ctime.tv_nsec != guard.tv_nsec))
  405                         nd->nd_repstat = NFSERR_NOT_SYNC;
  406                 if (nd->nd_repstat) {
  407                         vput(vp);
  408 #ifdef NFS4_ACL_EXTATTR_NAME
  409                         acl_free(aclp);
  410 #endif
  411                         nfsrv_wcc(nd, preat_ret, &nva2, postat_ret, &nva);
  412                         goto out;
  413                 }
  414         } else if (!nd->nd_repstat && (nd->nd_flag & ND_NFSV4))
  415                 nd->nd_repstat = nfsrv_checkuidgid(nd, &nva);
  416 
  417         /*
  418          * Now that we have all the fields, lets do it.
  419          * If the size is being changed write access is required, otherwise
  420          * just check for a read only file system.
  421          */
  422         if (!nd->nd_repstat) {
  423                 if (NFSVNO_NOTSETSIZE(&nva)) {
  424                         if (NFSVNO_EXRDONLY(exp) ||
  425                             (vfs_flags(vp->v_mount) & MNT_RDONLY))
  426                                 nd->nd_repstat = EROFS;
  427                 } else {
  428                         if (vnode_vtype(vp) != VREG)
  429                                 nd->nd_repstat = EINVAL;
  430                         else if (nva2.na_uid != nd->nd_cred->cr_uid ||
  431                             NFSVNO_EXSTRICTACCESS(exp))
  432                                 nd->nd_repstat = nfsvno_accchk(vp,
  433                                     VWRITE, nd->nd_cred, exp, p,
  434                                     NFSACCCHK_NOOVERRIDE,
  435                                     NFSACCCHK_VPISLOCKED, NULL);
  436                 }
  437         }
  438         /*
  439          * Proxy operations from the MDS are allowed via the all 0s special
  440          * stateid.
  441          */
  442         if (nd->nd_repstat == 0 && (nd->nd_flag & ND_NFSV4) != 0 &&
  443             gotproxystateid == 0)
  444                 nd->nd_repstat = nfsrv_checksetattr(vp, nd, &stateid,
  445                     &nva, &attrbits, exp, p);
  446 
  447         if (!nd->nd_repstat && (nd->nd_flag & ND_NFSV4)) {
  448             /*
  449              * For V4, try setting the attrbutes in sets, so that the
  450              * reply bitmap will be correct for an error case.
  451              */
  452             if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_OWNER) ||
  453                 NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_OWNERGROUP)) {
  454                 NFSVNO_ATTRINIT(&nva2);
  455                 NFSVNO_SETATTRVAL(&nva2, uid, nva.na_uid);
  456                 NFSVNO_SETATTRVAL(&nva2, gid, nva.na_gid);
  457                 nd->nd_repstat = nfsvno_setattr(vp, &nva2, nd->nd_cred, p,
  458                     exp);
  459                 if (!nd->nd_repstat) {
  460                     if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_OWNER))
  461                         NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_OWNER);
  462                     if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_OWNERGROUP))
  463                         NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_OWNERGROUP);
  464                 }
  465             }
  466             if (!nd->nd_repstat &&
  467                 NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_SIZE)) {
  468                 NFSVNO_ATTRINIT(&nva2);
  469                 NFSVNO_SETATTRVAL(&nva2, size, nva.na_size);
  470                 nd->nd_repstat = nfsvno_setattr(vp, &nva2, nd->nd_cred, p,
  471                     exp);
  472                 if (!nd->nd_repstat)
  473                     NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_SIZE);
  474             }
  475             if (!nd->nd_repstat &&
  476                 (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_TIMEACCESSSET) ||
  477                  NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_TIMEMODIFYSET))) {
  478                 NFSVNO_ATTRINIT(&nva2);
  479                 NFSVNO_SETATTRVAL(&nva2, atime, nva.na_atime);
  480                 NFSVNO_SETATTRVAL(&nva2, mtime, nva.na_mtime);
  481                 if (nva.na_vaflags & VA_UTIMES_NULL) {
  482                         nva2.na_vaflags |= VA_UTIMES_NULL;
  483                         NFSVNO_SETACTIVE(&nva2, vaflags);
  484                 }
  485                 nd->nd_repstat = nfsvno_setattr(vp, &nva2, nd->nd_cred, p,
  486                     exp);
  487                 if (!nd->nd_repstat) {
  488                     if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_TIMEACCESSSET))
  489                         NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_TIMEACCESSSET);
  490                     if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_TIMEMODIFYSET))
  491                         NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_TIMEMODIFYSET);
  492                 }
  493             }
  494             if (!nd->nd_repstat &&
  495                 (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_MODE) ||
  496                  NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_MODESETMASKED))) {
  497                 NFSVNO_ATTRINIT(&nva2);
  498                 NFSVNO_SETATTRVAL(&nva2, mode, nva.na_mode);
  499                 nd->nd_repstat = nfsvno_setattr(vp, &nva2, nd->nd_cred, p,
  500                     exp);
  501                 if (!nd->nd_repstat) {
  502                     if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_MODE))
  503                         NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_MODE);
  504                     if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_MODESETMASKED))
  505                         NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_MODESETMASKED);
  506                 }
  507             }
  508 
  509 #ifdef NFS4_ACL_EXTATTR_NAME
  510             if (!nd->nd_repstat && aclp->acl_cnt > 0 &&
  511                 NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_ACL)) {
  512                 nd->nd_repstat = nfsrv_setacl(vp, aclp, nd->nd_cred, p);
  513                 if (!nd->nd_repstat) 
  514                     NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_ACL);
  515             }
  516 #endif
  517         } else if (!nd->nd_repstat) {
  518                 nd->nd_repstat = nfsvno_setattr(vp, &nva, nd->nd_cred, p,
  519                     exp);
  520         }
  521         if (nd->nd_flag & (ND_NFSV2 | ND_NFSV3)) {
  522                 postat_ret = nfsvno_getattr(vp, &nva, nd, p, 1, NULL);
  523                 if (!nd->nd_repstat)
  524                         nd->nd_repstat = postat_ret;
  525         }
  526         vput(vp);
  527 #ifdef NFS4_ACL_EXTATTR_NAME
  528         acl_free(aclp);
  529 #endif
  530         if (nd->nd_flag & ND_NFSV3)
  531                 nfsrv_wcc(nd, preat_ret, &nva2, postat_ret, &nva);
  532         else if (nd->nd_flag & ND_NFSV4)
  533                 (void) nfsrv_putattrbit(nd, &retbits);
  534         else if (!nd->nd_repstat)
  535                 nfsrv_fillattr(nd, &nva);
  536 
  537 out:
  538         NFSEXITCODE2(0, nd);
  539         return (0);
  540 nfsmout:
  541         vput(vp);
  542 #ifdef NFS4_ACL_EXTATTR_NAME
  543         acl_free(aclp);
  544 #endif
  545         if (nd->nd_flag & ND_NFSV4) {
  546                 /*
  547                  * For all nd_repstat, the V4 reply includes a bitmap,
  548                  * even NFSERR_BADXDR, which is what this will end up
  549                  * returning.
  550                  */
  551                 (void) nfsrv_putattrbit(nd, &retbits);
  552         }
  553         NFSEXITCODE2(error, nd);
  554         return (error);
  555 }
  556 
  557 /*
  558  * nfs lookup rpc
  559  * (Also performs lookup parent for v4)
  560  */
  561 int
  562 nfsrvd_lookup(struct nfsrv_descript *nd, __unused int isdgram,
  563     vnode_t dp, vnode_t *vpp, fhandle_t *fhp, struct nfsexstuff *exp)
  564 {
  565         struct nameidata named;
  566         vnode_t vp, dirp = NULL;
  567         int error = 0, dattr_ret = 1;
  568         struct nfsvattr nva, dattr;
  569         char *bufp;
  570         u_long *hashp;
  571         struct thread *p = curthread;
  572 
  573         if (nd->nd_repstat) {
  574                 nfsrv_postopattr(nd, dattr_ret, &dattr);
  575                 goto out;
  576         }
  577 
  578         /*
  579          * For some reason, if dp is a symlink, the error
  580          * returned is supposed to be NFSERR_SYMLINK and not NFSERR_NOTDIR.
  581          */
  582         if (dp->v_type == VLNK && (nd->nd_flag & ND_NFSV4)) {
  583                 nd->nd_repstat = NFSERR_SYMLINK;
  584                 vrele(dp);
  585                 goto out;
  586         }
  587 
  588         NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, LOOKUP,
  589             LOCKLEAF | SAVESTART);
  590         nfsvno_setpathbuf(&named, &bufp, &hashp);
  591         error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
  592         if (error) {
  593                 vrele(dp);
  594                 nfsvno_relpathbuf(&named);
  595                 goto out;
  596         }
  597         if (!nd->nd_repstat) {
  598                 nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp, p, &dirp);
  599         } else {
  600                 vrele(dp);
  601                 nfsvno_relpathbuf(&named);
  602         }
  603         if (nd->nd_repstat) {
  604                 if (dirp) {
  605                         if (nd->nd_flag & ND_NFSV3)
  606                                 dattr_ret = nfsvno_getattr(dirp, &dattr, nd, p,
  607                                     0, NULL);
  608                         vrele(dirp);
  609                 }
  610                 if (nd->nd_flag & ND_NFSV3)
  611                         nfsrv_postopattr(nd, dattr_ret, &dattr);
  612                 goto out;
  613         }
  614         if (named.ni_startdir)
  615                 vrele(named.ni_startdir);
  616         nfsvno_relpathbuf(&named);
  617         vp = named.ni_vp;
  618         if ((nd->nd_flag & ND_NFSV4) != 0 && !NFSVNO_EXPORTED(exp) &&
  619             vp->v_type != VDIR && vp->v_type != VLNK)
  620                 /*
  621                  * Only allow lookup of VDIR and VLNK for traversal of
  622                  * non-exported volumes during NFSv4 mounting.
  623                  */
  624                 nd->nd_repstat = ENOENT;
  625         if (nd->nd_repstat == 0)
  626                 nd->nd_repstat = nfsvno_getfh(vp, fhp, p);
  627         if (!(nd->nd_flag & ND_NFSV4) && !nd->nd_repstat)
  628                 nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1, NULL);
  629         if (vpp != NULL && nd->nd_repstat == 0)
  630                 *vpp = vp;
  631         else
  632                 vput(vp);
  633         if (dirp) {
  634                 if (nd->nd_flag & ND_NFSV3)
  635                         dattr_ret = nfsvno_getattr(dirp, &dattr, nd, p, 0,
  636                             NULL);
  637                 vrele(dirp);
  638         }
  639         if (nd->nd_repstat) {
  640                 if (nd->nd_flag & ND_NFSV3)
  641                         nfsrv_postopattr(nd, dattr_ret, &dattr);
  642                 goto out;
  643         }
  644         if (nd->nd_flag & ND_NFSV2) {
  645                 (void) nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 0);
  646                 nfsrv_fillattr(nd, &nva);
  647         } else if (nd->nd_flag & ND_NFSV3) {
  648                 (void) nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 0);
  649                 nfsrv_postopattr(nd, 0, &nva);
  650                 nfsrv_postopattr(nd, dattr_ret, &dattr);
  651         }
  652 
  653 out:
  654         NFSEXITCODE2(error, nd);
  655         return (error);
  656 }
  657 
  658 /*
  659  * nfs readlink service
  660  */
  661 int
  662 nfsrvd_readlink(struct nfsrv_descript *nd, __unused int isdgram,
  663     vnode_t vp, __unused struct nfsexstuff *exp)
  664 {
  665         u_int32_t *tl;
  666         struct mbuf *mp = NULL, *mpend = NULL;
  667         int getret = 1, len;
  668         struct nfsvattr nva;
  669         struct thread *p = curthread;
  670         uint16_t off;
  671 
  672         if (nd->nd_repstat) {
  673                 nfsrv_postopattr(nd, getret, &nva);
  674                 goto out;
  675         }
  676         if (vnode_vtype(vp) != VLNK) {
  677                 if (nd->nd_flag & ND_NFSV2)
  678                         nd->nd_repstat = ENXIO;
  679                 else
  680                         nd->nd_repstat = EINVAL;
  681         }
  682         if (nd->nd_repstat == 0) {
  683                 if ((nd->nd_flag & ND_EXTPG) != 0)
  684                         nd->nd_repstat = nfsvno_readlink(vp, nd->nd_cred,
  685                             nd->nd_maxextsiz, p, &mp, &mpend, &len);
  686                 else
  687                         nd->nd_repstat = nfsvno_readlink(vp, nd->nd_cred,
  688                             0, p, &mp, &mpend, &len);
  689         }
  690         if (nd->nd_flag & ND_NFSV3)
  691                 getret = nfsvno_getattr(vp, &nva, nd, p, 1, NULL);
  692         vput(vp);
  693         if (nd->nd_flag & ND_NFSV3)
  694                 nfsrv_postopattr(nd, getret, &nva);
  695         if (nd->nd_repstat)
  696                 goto out;
  697         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
  698         *tl = txdr_unsigned(len);
  699         if (mp != NULL) {
  700                 nd->nd_mb->m_next = mp;
  701                 nd->nd_mb = mpend;
  702                 if ((mpend->m_flags & M_EXTPG) != 0) {
  703                         nd->nd_bextpg = mpend->m_epg_npgs - 1;
  704                         nd->nd_bpos = (char *)(void *)
  705                             PHYS_TO_DMAP(mpend->m_epg_pa[nd->nd_bextpg]);
  706                         off = (nd->nd_bextpg == 0) ? mpend->m_epg_1st_off : 0;
  707                         nd->nd_bpos += off + mpend->m_epg_last_len;
  708                         nd->nd_bextpgsiz = PAGE_SIZE - mpend->m_epg_last_len -
  709                             off;
  710                 } else
  711                         nd->nd_bpos = mtod(mpend, char *) + mpend->m_len;
  712         }
  713 
  714 out:
  715         NFSEXITCODE2(0, nd);
  716         return (0);
  717 }
  718 
  719 /*
  720  * nfs read service
  721  */
  722 int
  723 nfsrvd_read(struct nfsrv_descript *nd, __unused int isdgram,
  724     vnode_t vp, struct nfsexstuff *exp)
  725 {
  726         u_int32_t *tl;
  727         int error = 0, cnt, getret = 1, gotproxystateid, reqlen, eof = 0;
  728         struct mbuf *m2, *m3;
  729         struct nfsvattr nva;
  730         off_t off = 0x0;
  731         struct nfsstate st, *stp = &st;
  732         struct nfslock lo, *lop = &lo;
  733         nfsv4stateid_t stateid;
  734         nfsquad_t clientid;
  735         struct thread *p = curthread;
  736         uint16_t poff;
  737 
  738         if (nd->nd_repstat) {
  739                 nfsrv_postopattr(nd, getret, &nva);
  740                 goto out;
  741         }
  742         if (nd->nd_flag & ND_NFSV2) {
  743                 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
  744                 off = (off_t)fxdr_unsigned(u_int32_t, *tl++);
  745                 reqlen = fxdr_unsigned(int, *tl);
  746         } else if (nd->nd_flag & ND_NFSV3) {
  747                 NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
  748                 off = fxdr_hyper(tl);
  749                 tl += 2;
  750                 reqlen = fxdr_unsigned(int, *tl);
  751         } else {
  752                 NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + 3*NFSX_UNSIGNED);
  753                 reqlen = fxdr_unsigned(int, *(tl + 6));
  754         }
  755         if (reqlen > NFS_SRVMAXDATA(nd)) {
  756                 reqlen = NFS_SRVMAXDATA(nd);
  757         } else if (reqlen < 0) {
  758                 error = EBADRPC;
  759                 goto nfsmout;
  760         }
  761         gotproxystateid = 0;
  762         if (nd->nd_flag & ND_NFSV4) {
  763                 stp->ls_flags = (NFSLCK_CHECK | NFSLCK_READACCESS);
  764                 lop->lo_flags = NFSLCK_READ;
  765                 stp->ls_ownerlen = 0;
  766                 stp->ls_op = NULL;
  767                 stp->ls_uid = nd->nd_cred->cr_uid;
  768                 stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
  769                 clientid.lval[0] = stp->ls_stateid.other[0] = *tl++;
  770                 clientid.lval[1] = stp->ls_stateid.other[1] = *tl++;
  771                 if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
  772                         if ((nd->nd_flag & ND_NFSV41) != 0)
  773                                 clientid.qval = nd->nd_clientid.qval;
  774                         else if (nd->nd_clientid.qval != clientid.qval)
  775                                 printf("EEK1 multiple clids\n");
  776                 } else {
  777                         if ((nd->nd_flag & ND_NFSV41) != 0)
  778                                 printf("EEK! no clientid from session\n");
  779                         nd->nd_flag |= ND_IMPLIEDCLID;
  780                         nd->nd_clientid.qval = clientid.qval;
  781                 }
  782                 stp->ls_stateid.other[2] = *tl++;
  783                 /*
  784                  * Don't allow the client to use a special stateid for a DS op.
  785                  */
  786                 if ((nd->nd_flag & ND_DSSERVER) != 0 &&
  787                     ((stp->ls_stateid.other[0] == 0x0 &&
  788                     stp->ls_stateid.other[1] == 0x0 &&
  789                     stp->ls_stateid.other[2] == 0x0) ||
  790                     (stp->ls_stateid.other[0] == 0xffffffff &&
  791                     stp->ls_stateid.other[1] == 0xffffffff &&
  792                     stp->ls_stateid.other[2] == 0xffffffff) ||
  793                     stp->ls_stateid.seqid != 0))
  794                         nd->nd_repstat = NFSERR_BADSTATEID;
  795                 /* However, allow the proxy stateid. */
  796                 if (stp->ls_stateid.seqid == 0xffffffff &&
  797                     stp->ls_stateid.other[0] == 0x55555555 &&
  798                     stp->ls_stateid.other[1] == 0x55555555 &&
  799                     stp->ls_stateid.other[2] == 0x55555555)
  800                         gotproxystateid = 1;
  801                 off = fxdr_hyper(tl);
  802                 lop->lo_first = off;
  803                 tl += 2;
  804                 lop->lo_end = off + reqlen;
  805                 /*
  806                  * Paranoia, just in case it wraps around.
  807                  */
  808                 if (lop->lo_end < off)
  809                         lop->lo_end = NFS64BITSSET;
  810         }
  811         if (vnode_vtype(vp) != VREG) {
  812                 if (nd->nd_flag & ND_NFSV3)
  813                         nd->nd_repstat = EINVAL;
  814                 else
  815                         nd->nd_repstat = (vnode_vtype(vp) == VDIR) ? EISDIR :
  816                             EINVAL;
  817         }
  818         getret = nfsvno_getattr(vp, &nva, nd, p, 1, NULL);
  819         if (!nd->nd_repstat)
  820                 nd->nd_repstat = getret;
  821         if (!nd->nd_repstat &&
  822             (nva.na_uid != nd->nd_cred->cr_uid ||
  823              NFSVNO_EXSTRICTACCESS(exp))) {
  824                 nd->nd_repstat = nfsvno_accchk(vp, VREAD,
  825                     nd->nd_cred, exp, p,
  826                     NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED, NULL);
  827                 if (nd->nd_repstat)
  828                         nd->nd_repstat = nfsvno_accchk(vp, VEXEC,
  829                             nd->nd_cred, exp, p, NFSACCCHK_ALLOWOWNER,
  830                             NFSACCCHK_VPISLOCKED, NULL);
  831         }
  832         /*
  833          * DS reads are marked by ND_DSSERVER or use the proxy special
  834          * stateid.
  835          */
  836         if (nd->nd_repstat == 0 && (nd->nd_flag & (ND_NFSV4 | ND_DSSERVER)) ==
  837             ND_NFSV4 && gotproxystateid == 0)
  838                 nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid,
  839                     &stateid, exp, nd, p);
  840         if (nd->nd_repstat) {
  841                 vput(vp);
  842                 if (nd->nd_flag & ND_NFSV3)
  843                         nfsrv_postopattr(nd, getret, &nva);
  844                 goto out;
  845         }
  846         if (off >= nva.na_size) {
  847                 cnt = 0;
  848                 eof = 1;
  849         } else if (reqlen == 0)
  850                 cnt = 0;
  851         else if ((off + reqlen) >= nva.na_size) {
  852                 cnt = nva.na_size - off;
  853                 eof = 1;
  854         } else
  855                 cnt = reqlen;
  856         m3 = NULL;
  857         if (cnt > 0) {
  858                 /*
  859                  * If cnt > MCLBYTES and the reply will not be saved, use
  860                  * ext_pgs mbufs for TLS.
  861                  * For NFSv4.0, we do not know for sure if the reply will
  862                  * be saved, so do not use ext_pgs mbufs for NFSv4.0.
  863                  * Always use ext_pgs mbufs if ND_EXTPG is set.
  864                  */
  865                 if ((nd->nd_flag & ND_EXTPG) != 0 || (cnt > MCLBYTES &&
  866                     (nd->nd_flag & (ND_TLS | ND_SAVEREPLY)) == ND_TLS &&
  867                     (nd->nd_flag & (ND_NFSV4 | ND_NFSV41)) != ND_NFSV4))
  868                         nd->nd_repstat = nfsvno_read(vp, off, cnt, nd->nd_cred,
  869                             nd->nd_maxextsiz, p, &m3, &m2);
  870                 else
  871                         nd->nd_repstat = nfsvno_read(vp, off, cnt, nd->nd_cred,
  872                             0, p, &m3, &m2);
  873                 if (!(nd->nd_flag & ND_NFSV4)) {
  874                         getret = nfsvno_getattr(vp, &nva, nd, p, 1, NULL);
  875                         if (!nd->nd_repstat)
  876                                 nd->nd_repstat = getret;
  877                 }
  878                 if (nd->nd_repstat) {
  879                         vput(vp);
  880                         if (m3)
  881                                 m_freem(m3);
  882                         if (nd->nd_flag & ND_NFSV3)
  883                                 nfsrv_postopattr(nd, getret, &nva);
  884                         goto out;
  885                 }
  886         }
  887         vput(vp);
  888         if (nd->nd_flag & ND_NFSV2) {
  889                 nfsrv_fillattr(nd, &nva);
  890                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
  891         } else {
  892                 if (nd->nd_flag & ND_NFSV3) {
  893                         nfsrv_postopattr(nd, getret, &nva);
  894                         NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
  895                         *tl++ = txdr_unsigned(cnt);
  896                 } else
  897                         NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
  898                 if (eof)
  899                         *tl++ = newnfs_true;
  900                 else
  901                         *tl++ = newnfs_false;
  902         }
  903         *tl = txdr_unsigned(cnt);
  904         if (m3) {
  905                 nd->nd_mb->m_next = m3;
  906                 nd->nd_mb = m2;
  907                 if ((m2->m_flags & M_EXTPG) != 0) {
  908                         nd->nd_flag |= ND_EXTPG;
  909                         nd->nd_bextpg = m2->m_epg_npgs - 1;
  910                         nd->nd_bpos = (char *)(void *)
  911                             PHYS_TO_DMAP(m2->m_epg_pa[nd->nd_bextpg]);
  912                         poff = (nd->nd_bextpg == 0) ? m2->m_epg_1st_off : 0;
  913                         nd->nd_bpos += poff + m2->m_epg_last_len;
  914                         nd->nd_bextpgsiz = PAGE_SIZE - m2->m_epg_last_len -
  915                             poff;
  916                 } else
  917                         nd->nd_bpos = mtod(m2, char *) + m2->m_len;
  918         }
  919 
  920 out:
  921         NFSEXITCODE2(0, nd);
  922         return (0);
  923 nfsmout:
  924         vput(vp);
  925         NFSEXITCODE2(error, nd);
  926         return (error);
  927 }
  928 
  929 /*
  930  * nfs write service
  931  */
  932 int
  933 nfsrvd_write(struct nfsrv_descript *nd, __unused int isdgram,
  934     vnode_t vp, struct nfsexstuff *exp)
  935 {
  936         u_int32_t *tl;
  937         struct nfsvattr nva, forat;
  938         int aftat_ret = 1, retlen, len, error = 0, forat_ret = 1;
  939         int gotproxystateid, stable = NFSWRITE_FILESYNC;
  940         off_t off;
  941         struct nfsstate st, *stp = &st;
  942         struct nfslock lo, *lop = &lo;
  943         nfsv4stateid_t stateid;
  944         nfsquad_t clientid;
  945         nfsattrbit_t attrbits;
  946         struct thread *p = curthread;
  947 
  948         if (nd->nd_repstat) {
  949                 nfsrv_wcc(nd, forat_ret, &forat, aftat_ret, &nva);
  950                 goto out;
  951         }
  952         gotproxystateid = 0;
  953         if (nd->nd_flag & ND_NFSV2) {
  954                 NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
  955                 off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
  956                 tl += 2;
  957                 retlen = len = fxdr_unsigned(int32_t, *tl);
  958         } else if (nd->nd_flag & ND_NFSV3) {
  959                 NFSM_DISSECT(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
  960                 off = fxdr_hyper(tl);
  961                 tl += 3;
  962                 stable = fxdr_unsigned(int, *tl++);
  963                 retlen = len = fxdr_unsigned(int32_t, *tl);
  964         } else {
  965                 NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + 4 * NFSX_UNSIGNED);
  966                 stp->ls_flags = (NFSLCK_CHECK | NFSLCK_WRITEACCESS);
  967                 lop->lo_flags = NFSLCK_WRITE;
  968                 stp->ls_ownerlen = 0;
  969                 stp->ls_op = NULL;
  970                 stp->ls_uid = nd->nd_cred->cr_uid;
  971                 stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
  972                 clientid.lval[0] = stp->ls_stateid.other[0] = *tl++;
  973                 clientid.lval[1] = stp->ls_stateid.other[1] = *tl++;
  974                 if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
  975                         if ((nd->nd_flag & ND_NFSV41) != 0)
  976                                 clientid.qval = nd->nd_clientid.qval;
  977                         else if (nd->nd_clientid.qval != clientid.qval)
  978                                 printf("EEK2 multiple clids\n");
  979                 } else {
  980                         if ((nd->nd_flag & ND_NFSV41) != 0)
  981                                 printf("EEK! no clientid from session\n");
  982                         nd->nd_flag |= ND_IMPLIEDCLID;
  983                         nd->nd_clientid.qval = clientid.qval;
  984                 }
  985                 stp->ls_stateid.other[2] = *tl++;
  986                 /*
  987                  * Don't allow the client to use a special stateid for a DS op.
  988                  */
  989                 if ((nd->nd_flag & ND_DSSERVER) != 0 &&
  990                     ((stp->ls_stateid.other[0] == 0x0 &&
  991                     stp->ls_stateid.other[1] == 0x0 &&
  992                     stp->ls_stateid.other[2] == 0x0) ||
  993                     (stp->ls_stateid.other[0] == 0xffffffff &&
  994                     stp->ls_stateid.other[1] == 0xffffffff &&
  995                     stp->ls_stateid.other[2] == 0xffffffff) ||
  996                     stp->ls_stateid.seqid != 0))
  997                         nd->nd_repstat = NFSERR_BADSTATEID;
  998                 /* However, allow the proxy stateid. */
  999                 if (stp->ls_stateid.seqid == 0xffffffff &&
 1000                     stp->ls_stateid.other[0] == 0x55555555 &&
 1001                     stp->ls_stateid.other[1] == 0x55555555 &&
 1002                     stp->ls_stateid.other[2] == 0x55555555)
 1003                         gotproxystateid = 1;
 1004                 off = fxdr_hyper(tl);
 1005                 lop->lo_first = off;
 1006                 tl += 2;
 1007                 stable = fxdr_unsigned(int, *tl++);
 1008                 retlen = len = fxdr_unsigned(int32_t, *tl);
 1009                 lop->lo_end = off + len;
 1010                 /*
 1011                  * Paranoia, just in case it wraps around, which shouldn't
 1012                  * ever happen anyhow.
 1013                  */
 1014                 if (lop->lo_end < lop->lo_first)
 1015                         lop->lo_end = NFS64BITSSET;
 1016         }
 1017 
 1018         if (retlen > NFS_SRVMAXIO || retlen < 0)
 1019                 nd->nd_repstat = EIO;
 1020         if (vnode_vtype(vp) != VREG && !nd->nd_repstat) {
 1021                 if (nd->nd_flag & ND_NFSV3)
 1022                         nd->nd_repstat = EINVAL;
 1023                 else
 1024                         nd->nd_repstat = (vnode_vtype(vp) == VDIR) ? EISDIR :
 1025                             EINVAL;
 1026         }
 1027         NFSZERO_ATTRBIT(&attrbits);
 1028         NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_OWNER);
 1029         forat_ret = nfsvno_getattr(vp, &forat, nd, p, 1, &attrbits);
 1030         if (!nd->nd_repstat)
 1031                 nd->nd_repstat = forat_ret;
 1032         if (!nd->nd_repstat &&
 1033             (forat.na_uid != nd->nd_cred->cr_uid ||
 1034              NFSVNO_EXSTRICTACCESS(exp)))
 1035                 nd->nd_repstat = nfsvno_accchk(vp, VWRITE,
 1036                     nd->nd_cred, exp, p,
 1037                     NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED, NULL);
 1038         /*
 1039          * DS reads are marked by ND_DSSERVER or use the proxy special
 1040          * stateid.
 1041          */
 1042         if (nd->nd_repstat == 0 && (nd->nd_flag & (ND_NFSV4 | ND_DSSERVER)) ==
 1043             ND_NFSV4 && gotproxystateid == 0)
 1044                 nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid,
 1045                     &stateid, exp, nd, p);
 1046         if (nd->nd_repstat) {
 1047                 vput(vp);
 1048                 if (nd->nd_flag & ND_NFSV3)
 1049                         nfsrv_wcc(nd, forat_ret, &forat, aftat_ret, &nva);
 1050                 goto out;
 1051         }
 1052 
 1053         /*
 1054          * For NFS Version 2, it is not obvious what a write of zero length
 1055          * should do, but I might as well be consistent with Version 3,
 1056          * which is to return ok so long as there are no permission problems.
 1057          */
 1058         if (retlen > 0) {
 1059                 nd->nd_repstat = nfsvno_write(vp, off, retlen, &stable,
 1060                     nd->nd_md, nd->nd_dpos, nd->nd_cred, p);
 1061                 error = nfsm_advance(nd, NFSM_RNDUP(retlen), -1);
 1062                 if (error)
 1063                         goto nfsmout;
 1064         }
 1065         if (nd->nd_flag & ND_NFSV4)
 1066                 aftat_ret = 0;
 1067         else
 1068                 aftat_ret = nfsvno_getattr(vp, &nva, nd, p, 1, NULL);
 1069         vput(vp);
 1070         if (!nd->nd_repstat)
 1071                 nd->nd_repstat = aftat_ret;
 1072         if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4)) {
 1073                 if (nd->nd_flag & ND_NFSV3)
 1074                         nfsrv_wcc(nd, forat_ret, &forat, aftat_ret, &nva);
 1075                 if (nd->nd_repstat)
 1076                         goto out;
 1077                 NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
 1078                 *tl++ = txdr_unsigned(retlen);
 1079                 /*
 1080                  * If nfs_async is set, then pretend the write was FILESYNC.
 1081                  * Warning: Doing this violates RFC1813 and runs a risk
 1082                  * of data written by a client being lost when the server
 1083                  * crashes/reboots.
 1084                  */
 1085                 if (stable == NFSWRITE_UNSTABLE && nfs_async == 0)
 1086                         *tl++ = txdr_unsigned(stable);
 1087                 else
 1088                         *tl++ = txdr_unsigned(NFSWRITE_FILESYNC);
 1089                 /*
 1090                  * Actually, there is no need to txdr these fields,
 1091                  * but it may make the values more human readable,
 1092                  * for debugging purposes.
 1093                  */
 1094                 *tl++ = txdr_unsigned(nfsboottime.tv_sec);
 1095                 *tl = txdr_unsigned(nfsboottime.tv_usec);
 1096         } else if (!nd->nd_repstat)
 1097                 nfsrv_fillattr(nd, &nva);
 1098 
 1099 out:
 1100         NFSEXITCODE2(0, nd);
 1101         return (0);
 1102 nfsmout:
 1103         vput(vp);
 1104         NFSEXITCODE2(error, nd);
 1105         return (error);
 1106 }
 1107 
 1108 /*
 1109  * nfs create service (creates regular files for V2 and V3. Spec. files for V2.)
 1110  * now does a truncate to 0 length via. setattr if it already exists
 1111  * The core creation routine has been extracted out into nfsrv_creatsub(),
 1112  * so it can also be used by nfsrv_open() for V4.
 1113  */
 1114 int
 1115 nfsrvd_create(struct nfsrv_descript *nd, __unused int isdgram,
 1116     vnode_t dp, struct nfsexstuff *exp)
 1117 {
 1118         struct nfsvattr nva, dirfor, diraft;
 1119         struct nfsv2_sattr *sp;
 1120         struct nameidata named;
 1121         u_int32_t *tl;
 1122         int error = 0, tsize, dirfor_ret = 1, diraft_ret = 1;
 1123         int how = NFSCREATE_UNCHECKED, exclusive_flag = 0;
 1124         NFSDEV_T rdev = 0;
 1125         vnode_t vp = NULL, dirp = NULL;
 1126         fhandle_t fh;
 1127         char *bufp;
 1128         u_long *hashp;
 1129         enum vtype vtyp;
 1130         int32_t cverf[2], tverf[2] = { 0, 0 };
 1131         struct thread *p = curthread;
 1132 
 1133         if (nd->nd_repstat) {
 1134                 nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
 1135                 goto out;
 1136         }
 1137         NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE,
 1138             LOCKPARENT | LOCKLEAF | SAVESTART | NOCACHE);
 1139         nfsvno_setpathbuf(&named, &bufp, &hashp);
 1140         error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
 1141         if (error)
 1142                 goto nfsmout;
 1143         if (!nd->nd_repstat) {
 1144                 NFSVNO_ATTRINIT(&nva);
 1145                 if (nd->nd_flag & ND_NFSV2) {
 1146                         NFSM_DISSECT(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
 1147                         vtyp = IFTOVT(fxdr_unsigned(u_int32_t, sp->sa_mode));
 1148                         if (vtyp == VNON)
 1149                                 vtyp = VREG;
 1150                         NFSVNO_SETATTRVAL(&nva, type, vtyp);
 1151                         NFSVNO_SETATTRVAL(&nva, mode,
 1152                             nfstov_mode(sp->sa_mode));
 1153                         switch (nva.na_type) {
 1154                         case VREG:
 1155                                 tsize = fxdr_unsigned(int32_t, sp->sa_size);
 1156                                 if (tsize != -1)
 1157                                         NFSVNO_SETATTRVAL(&nva, size,
 1158                                             (u_quad_t)tsize);
 1159                                 break;
 1160                         case VCHR:
 1161                         case VBLK:
 1162                         case VFIFO:
 1163                                 rdev = fxdr_unsigned(NFSDEV_T, sp->sa_size);
 1164                                 break;
 1165                         default:
 1166                                 break;
 1167                         }
 1168                 } else {
 1169                         NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 1170                         how = fxdr_unsigned(int, *tl);
 1171                         switch (how) {
 1172                         case NFSCREATE_GUARDED:
 1173                         case NFSCREATE_UNCHECKED:
 1174                                 error = nfsrv_sattr(nd, NULL, &nva, NULL, NULL, p);
 1175                                 if (error)
 1176                                         goto nfsmout;
 1177                                 break;
 1178                         case NFSCREATE_EXCLUSIVE:
 1179                                 NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF);
 1180                                 cverf[0] = *tl++;
 1181                                 cverf[1] = *tl;
 1182                                 exclusive_flag = 1;
 1183                                 break;
 1184                         }
 1185                         NFSVNO_SETATTRVAL(&nva, type, VREG);
 1186                 }
 1187         }
 1188         if (nd->nd_repstat) {
 1189                 nfsvno_relpathbuf(&named);
 1190                 if (nd->nd_flag & ND_NFSV3) {
 1191                         dirfor_ret = nfsvno_getattr(dp, &dirfor, nd, p, 1,
 1192                             NULL);
 1193                         nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret,
 1194                             &diraft);
 1195                 }
 1196                 vput(dp);
 1197                 goto out;
 1198         }
 1199 
 1200         nd->nd_repstat = nfsvno_namei(nd, &named, dp, 1, exp, p, &dirp);
 1201         if (dirp) {
 1202                 if (nd->nd_flag & ND_NFSV2) {
 1203                         vrele(dirp);
 1204                         dirp = NULL;
 1205                 } else {
 1206                         dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0,
 1207                             NULL);
 1208                 }
 1209         }
 1210         if (nd->nd_repstat) {
 1211                 if (nd->nd_flag & ND_NFSV3)
 1212                         nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret,
 1213                             &diraft);
 1214                 if (dirp)
 1215                         vrele(dirp);
 1216                 goto out;
 1217         }
 1218 
 1219         if (!(nd->nd_flag & ND_NFSV2)) {
 1220                 switch (how) {
 1221                 case NFSCREATE_GUARDED:
 1222                         if (named.ni_vp)
 1223                                 nd->nd_repstat = EEXIST;
 1224                         break;
 1225                 case NFSCREATE_UNCHECKED:
 1226                         break;
 1227                 case NFSCREATE_EXCLUSIVE:
 1228                         if (named.ni_vp == NULL)
 1229                                 NFSVNO_SETATTRVAL(&nva, mode, 0);
 1230                         break;
 1231                 }
 1232         }
 1233 
 1234         /*
 1235          * Iff doesn't exist, create it
 1236          * otherwise just truncate to 0 length
 1237          *   should I set the mode too ?
 1238          */
 1239         nd->nd_repstat = nfsvno_createsub(nd, &named, &vp, &nva,
 1240             &exclusive_flag, cverf, rdev, exp);
 1241 
 1242         if (!nd->nd_repstat) {
 1243                 nd->nd_repstat = nfsvno_getfh(vp, &fh, p);
 1244                 if (!nd->nd_repstat)
 1245                         nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1,
 1246                             NULL);
 1247                 vput(vp);
 1248                 if (!nd->nd_repstat) {
 1249                         tverf[0] = nva.na_atime.tv_sec;
 1250                         tverf[1] = nva.na_atime.tv_nsec;
 1251                 }
 1252         }
 1253         if (nd->nd_flag & ND_NFSV2) {
 1254                 if (!nd->nd_repstat) {
 1255                         (void) nfsm_fhtom(nd, (u_int8_t *)&fh, 0, 0);
 1256                         nfsrv_fillattr(nd, &nva);
 1257                 }
 1258         } else {
 1259                 if (exclusive_flag && !nd->nd_repstat && (cverf[0] != tverf[0]
 1260                     || cverf[1] != tverf[1]))
 1261                         nd->nd_repstat = EEXIST;
 1262                 diraft_ret = nfsvno_getattr(dirp, &diraft, nd, p, 0, NULL);
 1263                 vrele(dirp);
 1264                 if (!nd->nd_repstat) {
 1265                         (void) nfsm_fhtom(nd, (u_int8_t *)&fh, 0, 1);
 1266                         nfsrv_postopattr(nd, 0, &nva);
 1267                 }
 1268                 nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
 1269         }
 1270 
 1271 out:
 1272         NFSEXITCODE2(0, nd);
 1273         return (0);
 1274 nfsmout:
 1275         vput(dp);
 1276         nfsvno_relpathbuf(&named);
 1277         NFSEXITCODE2(error, nd);
 1278         return (error);
 1279 }
 1280 
 1281 /*
 1282  * nfs v3 mknod service (and v4 create)
 1283  */
 1284 int
 1285 nfsrvd_mknod(struct nfsrv_descript *nd, __unused int isdgram,
 1286     vnode_t dp, vnode_t *vpp, fhandle_t *fhp, struct nfsexstuff *exp)
 1287 {
 1288         struct nfsvattr nva, dirfor, diraft;
 1289         u_int32_t *tl;
 1290         struct nameidata named;
 1291         int error = 0, dirfor_ret = 1, diraft_ret = 1, pathlen;
 1292         u_int32_t major, minor;
 1293         enum vtype vtyp = VNON;
 1294         nfstype nfs4type = NFNON;
 1295         vnode_t vp, dirp = NULL;
 1296         nfsattrbit_t attrbits;
 1297         char *bufp = NULL, *pathcp = NULL;
 1298         u_long *hashp, cnflags;
 1299         NFSACL_T *aclp = NULL;
 1300         struct thread *p = curthread;
 1301 
 1302         NFSVNO_ATTRINIT(&nva);
 1303         cnflags = (LOCKPARENT | SAVESTART);
 1304         if (nd->nd_repstat) {
 1305                 nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
 1306                 goto out;
 1307         }
 1308 #ifdef NFS4_ACL_EXTATTR_NAME
 1309         aclp = acl_alloc(M_WAITOK);
 1310         aclp->acl_cnt = 0;
 1311 #endif
 1312 
 1313         /*
 1314          * For V4, the creation stuff is here, Yuck!
 1315          */
 1316         if (nd->nd_flag & ND_NFSV4) {
 1317                 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 1318                 vtyp = nfsv34tov_type(*tl);
 1319                 nfs4type = fxdr_unsigned(nfstype, *tl);
 1320                 switch (nfs4type) {
 1321                 case NFLNK:
 1322                         error = nfsvno_getsymlink(nd, &nva, p, &pathcp,
 1323                             &pathlen);
 1324                         if (error)
 1325                                 goto nfsmout;
 1326                         break;
 1327                 case NFCHR:
 1328                 case NFBLK:
 1329                         NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 1330                         major = fxdr_unsigned(u_int32_t, *tl++);
 1331                         minor = fxdr_unsigned(u_int32_t, *tl);
 1332                         nva.na_rdev = NFSMAKEDEV(major, minor);
 1333                         break;
 1334                 case NFSOCK:
 1335                 case NFFIFO:
 1336                         break;
 1337                 case NFDIR:
 1338                         cnflags = (LOCKPARENT | SAVENAME);
 1339                         break;
 1340                 default:
 1341                         nd->nd_repstat = NFSERR_BADTYPE;
 1342                         vrele(dp);
 1343 #ifdef NFS4_ACL_EXTATTR_NAME
 1344                         acl_free(aclp);
 1345 #endif
 1346                         goto out;
 1347                 }
 1348         }
 1349         NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE, cnflags | NOCACHE);
 1350         nfsvno_setpathbuf(&named, &bufp, &hashp);
 1351         error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
 1352         if (error)
 1353                 goto nfsmout;
 1354         if (!nd->nd_repstat) {
 1355                 if (nd->nd_flag & ND_NFSV3) {
 1356                         NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 1357                         vtyp = nfsv34tov_type(*tl);
 1358                 }
 1359                 error = nfsrv_sattr(nd, NULL, &nva, &attrbits, aclp, p);
 1360                 if (error)
 1361                         goto nfsmout;
 1362                 nva.na_type = vtyp;
 1363                 if (!nd->nd_repstat && (nd->nd_flag & ND_NFSV3) &&
 1364                     (vtyp == VCHR || vtyp == VBLK)) {
 1365                         NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 1366                         major = fxdr_unsigned(u_int32_t, *tl++);
 1367                         minor = fxdr_unsigned(u_int32_t, *tl);
 1368                         nva.na_rdev = NFSMAKEDEV(major, minor);
 1369                 }
 1370         }
 1371 
 1372         dirfor_ret = nfsvno_getattr(dp, &dirfor, nd, p, 0, NULL);
 1373         if (!nd->nd_repstat && (nd->nd_flag & ND_NFSV4)) {
 1374                 if (!dirfor_ret && NFSVNO_ISSETGID(&nva) &&
 1375                     dirfor.na_gid == nva.na_gid)
 1376                         NFSVNO_UNSET(&nva, gid);
 1377                 nd->nd_repstat = nfsrv_checkuidgid(nd, &nva);
 1378         }
 1379         if (nd->nd_repstat) {
 1380                 vrele(dp);
 1381 #ifdef NFS4_ACL_EXTATTR_NAME
 1382                 acl_free(aclp);
 1383 #endif
 1384                 nfsvno_relpathbuf(&named);
 1385                 if (pathcp)
 1386                         free(pathcp, M_TEMP);
 1387                 if (nd->nd_flag & ND_NFSV3)
 1388                         nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret,
 1389                             &diraft);
 1390                 goto out;
 1391         }
 1392 
 1393         /*
 1394          * Yuck! For V4, mkdir and link are here and some V4 clients don't fill
 1395          * in va_mode, so we'll have to set a default here.
 1396          */
 1397         if (NFSVNO_NOTSETMODE(&nva)) {
 1398                 if (vtyp == VLNK)
 1399                         nva.na_mode = 0755;
 1400                 else
 1401                         nva.na_mode = 0400;
 1402         }
 1403 
 1404         if (vtyp == VDIR)
 1405                 named.ni_cnd.cn_flags |= WILLBEDIR;
 1406         nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp, p, &dirp);
 1407         if (nd->nd_repstat) {
 1408                 if (dirp) {
 1409                         if (nd->nd_flag & ND_NFSV3)
 1410                                 dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd,
 1411                                     p, 0, NULL);
 1412                         vrele(dirp);
 1413                 }
 1414 #ifdef NFS4_ACL_EXTATTR_NAME
 1415                 acl_free(aclp);
 1416 #endif
 1417                 if (nd->nd_flag & ND_NFSV3)
 1418                         nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret,
 1419                             &diraft);
 1420                 goto out;
 1421         }
 1422         if (dirp)
 1423                 dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0, NULL);
 1424 
 1425         if ((nd->nd_flag & ND_NFSV4) && (vtyp == VDIR || vtyp == VLNK)) {
 1426                 if (vtyp == VDIR) {
 1427                         nfsrvd_mkdirsub(nd, &named, &nva, fhp, vpp, dirp,
 1428                             &dirfor, &diraft, &diraft_ret, &attrbits, aclp, p,
 1429                             exp);
 1430 #ifdef NFS4_ACL_EXTATTR_NAME
 1431                         acl_free(aclp);
 1432 #endif
 1433                         goto out;
 1434                 } else if (vtyp == VLNK) {
 1435                         nfsrvd_symlinksub(nd, &named, &nva, fhp, vpp, dirp,
 1436                             &dirfor, &diraft, &diraft_ret, &attrbits,
 1437                             aclp, p, exp, pathcp, pathlen);
 1438 #ifdef NFS4_ACL_EXTATTR_NAME
 1439                         acl_free(aclp);
 1440 #endif
 1441                         free(pathcp, M_TEMP);
 1442                         goto out;
 1443                 }
 1444         }
 1445 
 1446         nd->nd_repstat = nfsvno_mknod(&named, &nva, nd->nd_cred, p);
 1447         if (!nd->nd_repstat) {
 1448                 vp = named.ni_vp;
 1449                 nfsrv_fixattr(nd, vp, &nva, aclp, p, &attrbits, exp);
 1450                 nd->nd_repstat = nfsvno_getfh(vp, fhp, p);
 1451                 if ((nd->nd_flag & ND_NFSV3) && !nd->nd_repstat)
 1452                         nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1,
 1453                             NULL);
 1454                 if (vpp != NULL && nd->nd_repstat == 0) {
 1455                         NFSVOPUNLOCK(vp);
 1456                         *vpp = vp;
 1457                 } else
 1458                         vput(vp);
 1459         }
 1460 
 1461         diraft_ret = nfsvno_getattr(dirp, &diraft, nd, p, 0, NULL);
 1462         vrele(dirp);
 1463         if (!nd->nd_repstat) {
 1464                 if (nd->nd_flag & ND_NFSV3) {
 1465                         (void) nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 1);
 1466                         nfsrv_postopattr(nd, 0, &nva);
 1467                 } else {
 1468                         NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
 1469                         *tl++ = newnfs_false;
 1470                         txdr_hyper(dirfor.na_filerev, tl);
 1471                         tl += 2;
 1472                         txdr_hyper(diraft.na_filerev, tl);
 1473                         (void) nfsrv_putattrbit(nd, &attrbits);
 1474                 }
 1475         }
 1476         if (nd->nd_flag & ND_NFSV3)
 1477                 nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
 1478 #ifdef NFS4_ACL_EXTATTR_NAME
 1479         acl_free(aclp);
 1480 #endif
 1481 
 1482 out:
 1483         NFSEXITCODE2(0, nd);
 1484         return (0);
 1485 nfsmout:
 1486         vrele(dp);
 1487 #ifdef NFS4_ACL_EXTATTR_NAME
 1488         acl_free(aclp);
 1489 #endif
 1490         if (bufp)
 1491                 nfsvno_relpathbuf(&named);
 1492         if (pathcp)
 1493                 free(pathcp, M_TEMP);
 1494 
 1495         NFSEXITCODE2(error, nd);
 1496         return (error);
 1497 }
 1498 
 1499 /*
 1500  * nfs remove service
 1501  */
 1502 int
 1503 nfsrvd_remove(struct nfsrv_descript *nd, __unused int isdgram,
 1504     vnode_t dp, struct nfsexstuff *exp)
 1505 {
 1506         struct nameidata named;
 1507         u_int32_t *tl;
 1508         int error = 0, dirfor_ret = 1, diraft_ret = 1;
 1509         vnode_t dirp = NULL;
 1510         struct nfsvattr dirfor, diraft;
 1511         char *bufp;
 1512         u_long *hashp;
 1513         struct thread *p = curthread;
 1514 
 1515         if (nd->nd_repstat) {
 1516                 nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
 1517                 goto out;
 1518         }
 1519         NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, DELETE,
 1520             LOCKPARENT | LOCKLEAF);
 1521         nfsvno_setpathbuf(&named, &bufp, &hashp);
 1522         error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
 1523         if (error) {
 1524                 vput(dp);
 1525                 nfsvno_relpathbuf(&named);
 1526                 goto out;
 1527         }
 1528         if (!nd->nd_repstat) {
 1529                 nd->nd_repstat = nfsvno_namei(nd, &named, dp, 1, exp, p, &dirp);
 1530         } else {
 1531                 vput(dp);
 1532                 nfsvno_relpathbuf(&named);
 1533         }
 1534         if (dirp) {
 1535                 if (!(nd->nd_flag & ND_NFSV2)) {
 1536                         dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0,
 1537                             NULL);
 1538                 } else {
 1539                         vrele(dirp);
 1540                         dirp = NULL;
 1541                 }
 1542         }
 1543         if (!nd->nd_repstat) {
 1544                 if (nd->nd_flag & ND_NFSV4) {
 1545                         if (vnode_vtype(named.ni_vp) == VDIR)
 1546                                 nd->nd_repstat = nfsvno_rmdirsub(&named, 1,
 1547                                     nd->nd_cred, p, exp);
 1548                         else
 1549                                 nd->nd_repstat = nfsvno_removesub(&named, 1,
 1550                                     nd->nd_cred, p, exp);
 1551                 } else if (nd->nd_procnum == NFSPROC_RMDIR) {
 1552                         nd->nd_repstat = nfsvno_rmdirsub(&named, 0,
 1553                             nd->nd_cred, p, exp);
 1554                 } else {
 1555                         nd->nd_repstat = nfsvno_removesub(&named, 0,
 1556                             nd->nd_cred, p, exp);
 1557                 }
 1558         }
 1559         if (!(nd->nd_flag & ND_NFSV2)) {
 1560                 if (dirp) {
 1561                         diraft_ret = nfsvno_getattr(dirp, &diraft, nd, p, 0,
 1562                             NULL);
 1563                         vrele(dirp);
 1564                 }
 1565                 if (nd->nd_flag & ND_NFSV3) {
 1566                         nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret,
 1567                             &diraft);
 1568                 } else if (!nd->nd_repstat) {
 1569                         NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
 1570                         *tl++ = newnfs_false;
 1571                         txdr_hyper(dirfor.na_filerev, tl);
 1572                         tl += 2;
 1573                         txdr_hyper(diraft.na_filerev, tl);
 1574                 }
 1575         }
 1576 
 1577 out:
 1578         NFSEXITCODE2(error, nd);
 1579         return (error);
 1580 }
 1581 
 1582 /*
 1583  * nfs rename service
 1584  */
 1585 int
 1586 nfsrvd_rename(struct nfsrv_descript *nd, int isdgram,
 1587     vnode_t dp, vnode_t todp, struct nfsexstuff *exp, struct nfsexstuff *toexp)
 1588 {
 1589         u_int32_t *tl;
 1590         int error = 0, fdirfor_ret = 1, fdiraft_ret = 1;
 1591         int tdirfor_ret = 1, tdiraft_ret = 1;
 1592         struct nameidata fromnd, tond;
 1593         vnode_t fdirp = NULL, tdirp = NULL, tdp = NULL;
 1594         struct nfsvattr fdirfor, fdiraft, tdirfor, tdiraft;
 1595         struct nfsexstuff tnes;
 1596         struct nfsrvfh tfh;
 1597         char *bufp, *tbufp = NULL;
 1598         u_long *hashp;
 1599         fhandle_t fh;
 1600         struct thread *p = curthread;
 1601 
 1602         if (nd->nd_repstat) {
 1603                 nfsrv_wcc(nd, fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
 1604                 nfsrv_wcc(nd, tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
 1605                 goto out;
 1606         }
 1607         if (!(nd->nd_flag & ND_NFSV2))
 1608                 fdirfor_ret = nfsvno_getattr(dp, &fdirfor, nd, p, 1, NULL);
 1609         tond.ni_cnd.cn_nameiop = 0;
 1610         tond.ni_startdir = NULL;
 1611         NFSNAMEICNDSET(&fromnd.ni_cnd, nd->nd_cred, DELETE, WANTPARENT | SAVESTART);
 1612         nfsvno_setpathbuf(&fromnd, &bufp, &hashp);
 1613         error = nfsrv_parsename(nd, bufp, hashp, &fromnd.ni_pathlen);
 1614         if (error) {
 1615                 vput(dp);
 1616                 if (todp)
 1617                         vrele(todp);
 1618                 nfsvno_relpathbuf(&fromnd);
 1619                 goto out;
 1620         }
 1621         /*
 1622          * Unlock dp in this code section, so it is unlocked before
 1623          * tdp gets locked. This avoids a potential LOR if tdp is the
 1624          * parent directory of dp.
 1625          */
 1626         if (nd->nd_flag & ND_NFSV4) {
 1627                 tdp = todp;
 1628                 tnes = *toexp;
 1629                 if (dp != tdp) {
 1630                         NFSVOPUNLOCK(dp);
 1631                         /* Might lock tdp. */
 1632                         tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd, p, 0,
 1633                             NULL);
 1634                 } else {
 1635                         tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd, p, 1,
 1636                             NULL);
 1637                         NFSVOPUNLOCK(dp);
 1638                 }
 1639         } else {
 1640                 tfh.nfsrvfh_len = 0;
 1641                 error = nfsrv_mtofh(nd, &tfh);
 1642                 if (error == 0)
 1643                         error = nfsvno_getfh(dp, &fh, p);
 1644                 if (error) {
 1645                         vput(dp);
 1646                         /* todp is always NULL except NFSv4 */
 1647                         nfsvno_relpathbuf(&fromnd);
 1648                         goto out;
 1649                 }
 1650 
 1651                 /* If this is the same file handle, just VREF() the vnode. */
 1652                 if (tfh.nfsrvfh_len == NFSX_MYFH &&
 1653                     !NFSBCMP(tfh.nfsrvfh_data, &fh, NFSX_MYFH)) {
 1654                         VREF(dp);
 1655                         tdp = dp;
 1656                         tnes = *exp;
 1657                         tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd, p, 1,
 1658                             NULL);
 1659                         NFSVOPUNLOCK(dp);
 1660                 } else {
 1661                         NFSVOPUNLOCK(dp);
 1662                         nd->nd_cred->cr_uid = nd->nd_saveduid;
 1663                         nfsd_fhtovp(nd, &tfh, LK_EXCLUSIVE, &tdp, &tnes, NULL,
 1664                             0); /* Locks tdp. */
 1665                         if (tdp) {
 1666                                 tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd,
 1667                                     p, 1, NULL);
 1668                                 NFSVOPUNLOCK(tdp);
 1669                         }
 1670                 }
 1671         }
 1672         NFSNAMEICNDSET(&tond.ni_cnd, nd->nd_cred, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART);
 1673         nfsvno_setpathbuf(&tond, &tbufp, &hashp);
 1674         if (!nd->nd_repstat) {
 1675                 error = nfsrv_parsename(nd, tbufp, hashp, &tond.ni_pathlen);
 1676                 if (error) {
 1677                         if (tdp)
 1678                                 vrele(tdp);
 1679                         vrele(dp);
 1680                         nfsvno_relpathbuf(&fromnd);
 1681                         nfsvno_relpathbuf(&tond);
 1682                         goto out;
 1683                 }
 1684         }
 1685         if (nd->nd_repstat) {
 1686                 if (nd->nd_flag & ND_NFSV3) {
 1687                         nfsrv_wcc(nd, fdirfor_ret, &fdirfor, fdiraft_ret,
 1688                             &fdiraft);
 1689                         nfsrv_wcc(nd, tdirfor_ret, &tdirfor, tdiraft_ret,
 1690                             &tdiraft);
 1691                 }
 1692                 if (tdp)
 1693                         vrele(tdp);
 1694                 vrele(dp);
 1695                 nfsvno_relpathbuf(&fromnd);
 1696                 nfsvno_relpathbuf(&tond);
 1697                 goto out;
 1698         }
 1699 
 1700         /*
 1701          * Done parsing, now down to business.
 1702          */
 1703         nd->nd_repstat = nfsvno_namei(nd, &fromnd, dp, 0, exp, p, &fdirp);
 1704         if (nd->nd_repstat) {
 1705                 if (nd->nd_flag & ND_NFSV3) {
 1706                         nfsrv_wcc(nd, fdirfor_ret, &fdirfor, fdiraft_ret,
 1707                             &fdiraft);
 1708                         nfsrv_wcc(nd, tdirfor_ret, &tdirfor, tdiraft_ret,
 1709                             &tdiraft);
 1710                 }
 1711                 if (fdirp)
 1712                         vrele(fdirp);
 1713                 if (tdp)
 1714                         vrele(tdp);
 1715                 nfsvno_relpathbuf(&tond);
 1716                 goto out;
 1717         }
 1718         if (vnode_vtype(fromnd.ni_vp) == VDIR)
 1719                 tond.ni_cnd.cn_flags |= WILLBEDIR;
 1720         nd->nd_repstat = nfsvno_namei(nd, &tond, tdp, 0, &tnes, p, &tdirp);
 1721         nd->nd_repstat = nfsvno_rename(&fromnd, &tond, nd->nd_repstat,
 1722             nd->nd_flag, nd->nd_cred, p);
 1723         if (fdirp)
 1724                 fdiraft_ret = nfsvno_getattr(fdirp, &fdiraft, nd, p, 0, NULL);
 1725         if (tdirp)
 1726                 tdiraft_ret = nfsvno_getattr(tdirp, &tdiraft, nd, p, 0, NULL);
 1727         if (fdirp)
 1728                 vrele(fdirp);
 1729         if (tdirp)
 1730                 vrele(tdirp);
 1731         if (nd->nd_flag & ND_NFSV3) {
 1732                 nfsrv_wcc(nd, fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
 1733                 nfsrv_wcc(nd, tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
 1734         } else if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) {
 1735                 NFSM_BUILD(tl, u_int32_t *, 10 * NFSX_UNSIGNED);
 1736                 *tl++ = newnfs_false;
 1737                 txdr_hyper(fdirfor.na_filerev, tl);
 1738                 tl += 2;
 1739                 txdr_hyper(fdiraft.na_filerev, tl);
 1740                 tl += 2;
 1741                 *tl++ = newnfs_false;
 1742                 txdr_hyper(tdirfor.na_filerev, tl);
 1743                 tl += 2;
 1744                 txdr_hyper(tdiraft.na_filerev, tl);
 1745         }
 1746 
 1747 out:
 1748         NFSEXITCODE2(error, nd);
 1749         return (error);
 1750 }
 1751 
 1752 /*
 1753  * nfs link service
 1754  */
 1755 int
 1756 nfsrvd_link(struct nfsrv_descript *nd, int isdgram,
 1757     vnode_t vp, vnode_t tovp, struct nfsexstuff *exp, struct nfsexstuff *toexp)
 1758 {
 1759         struct nameidata named;
 1760         u_int32_t *tl;
 1761         int error = 0, dirfor_ret = 1, diraft_ret = 1, getret = 1;
 1762         vnode_t dirp = NULL, dp = NULL;
 1763         struct nfsvattr dirfor, diraft, at;
 1764         struct nfsexstuff tnes;
 1765         struct nfsrvfh dfh;
 1766         char *bufp;
 1767         u_long *hashp;
 1768         struct thread *p = curthread;
 1769 
 1770         if (nd->nd_repstat) {
 1771                 nfsrv_postopattr(nd, getret, &at);
 1772                 nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
 1773                 goto out;
 1774         }
 1775         NFSVOPUNLOCK(vp);
 1776         if (vnode_vtype(vp) == VDIR) {
 1777                 if (nd->nd_flag & ND_NFSV4)
 1778                         nd->nd_repstat = NFSERR_ISDIR;
 1779                 else
 1780                         nd->nd_repstat = NFSERR_INVAL;
 1781                 if (tovp)
 1782                         vrele(tovp);
 1783         }
 1784         if (!nd->nd_repstat) {
 1785                 if (nd->nd_flag & ND_NFSV4) {
 1786                         dp = tovp;
 1787                         tnes = *toexp;
 1788                 } else {
 1789                         error = nfsrv_mtofh(nd, &dfh);
 1790                         if (error) {
 1791                                 vrele(vp);
 1792                                 /* tovp is always NULL unless NFSv4 */
 1793                                 goto out;
 1794                         }
 1795                         nfsd_fhtovp(nd, &dfh, LK_EXCLUSIVE, &dp, &tnes, NULL, 0);
 1796                         if (dp)
 1797                                 NFSVOPUNLOCK(dp);
 1798                 }
 1799         }
 1800         NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE,
 1801             LOCKPARENT | SAVENAME | NOCACHE);
 1802         if (!nd->nd_repstat) {
 1803                 nfsvno_setpathbuf(&named, &bufp, &hashp);
 1804                 error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
 1805                 if (error) {
 1806                         vrele(vp);
 1807                         if (dp)
 1808                                 vrele(dp);
 1809                         nfsvno_relpathbuf(&named);
 1810                         goto out;
 1811                 }
 1812                 if (!nd->nd_repstat) {
 1813                         nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, &tnes,
 1814                             p, &dirp);
 1815                 } else {
 1816                         if (dp)
 1817                                 vrele(dp);
 1818                         nfsvno_relpathbuf(&named);
 1819                 }
 1820         }
 1821         if (dirp) {
 1822                 if (nd->nd_flag & ND_NFSV2) {
 1823                         vrele(dirp);
 1824                         dirp = NULL;
 1825                 } else {
 1826                         dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0,
 1827                             NULL);
 1828                 }
 1829         }
 1830         if (!nd->nd_repstat)
 1831                 nd->nd_repstat = nfsvno_link(&named, vp, nd->nd_cred, p, exp);
 1832         if (nd->nd_flag & ND_NFSV3)
 1833                 getret = nfsvno_getattr(vp, &at, nd, p, 0, NULL);
 1834         if (dirp) {
 1835                 diraft_ret = nfsvno_getattr(dirp, &diraft, nd, p, 0, NULL);
 1836                 vrele(dirp);
 1837         }
 1838         vrele(vp);
 1839         if (nd->nd_flag & ND_NFSV3) {
 1840                 nfsrv_postopattr(nd, getret, &at);
 1841                 nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
 1842         } else if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) {
 1843                 NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
 1844                 *tl++ = newnfs_false;
 1845                 txdr_hyper(dirfor.na_filerev, tl);
 1846                 tl += 2;
 1847                 txdr_hyper(diraft.na_filerev, tl);
 1848         }
 1849 
 1850 out:
 1851         NFSEXITCODE2(error, nd);
 1852         return (error);
 1853 }
 1854 
 1855 /*
 1856  * nfs symbolic link service
 1857  */
 1858 int
 1859 nfsrvd_symlink(struct nfsrv_descript *nd, __unused int isdgram,
 1860     vnode_t dp, vnode_t *vpp, fhandle_t *fhp, struct nfsexstuff *exp)
 1861 {
 1862         struct nfsvattr nva, dirfor, diraft;
 1863         struct nameidata named;
 1864         int error = 0, dirfor_ret = 1, diraft_ret = 1, pathlen;
 1865         vnode_t dirp = NULL;
 1866         char *bufp, *pathcp = NULL;
 1867         u_long *hashp;
 1868         struct thread *p = curthread;
 1869 
 1870         if (nd->nd_repstat) {
 1871                 nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
 1872                 goto out;
 1873         }
 1874         if (vpp)
 1875                 *vpp = NULL;
 1876         NFSVNO_ATTRINIT(&nva);
 1877         NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE,
 1878             LOCKPARENT | SAVESTART | NOCACHE);
 1879         nfsvno_setpathbuf(&named, &bufp, &hashp);
 1880         error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
 1881         if (!error && !nd->nd_repstat)
 1882                 error = nfsvno_getsymlink(nd, &nva, p, &pathcp, &pathlen);
 1883         if (error) {
 1884                 vrele(dp);
 1885                 nfsvno_relpathbuf(&named);
 1886                 goto out;
 1887         }
 1888         if (!nd->nd_repstat) {
 1889                 nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp, p, &dirp);
 1890         } else {
 1891                 vrele(dp);
 1892                 nfsvno_relpathbuf(&named);
 1893         }
 1894         if (dirp != NULL && !(nd->nd_flag & ND_NFSV3)) {
 1895                 vrele(dirp);
 1896                 dirp = NULL;
 1897         }
 1898 
 1899         /*
 1900          * And call nfsrvd_symlinksub() to do the common code. It will
 1901          * return EBADRPC upon a parsing error, 0 otherwise.
 1902          */
 1903         if (!nd->nd_repstat) {
 1904                 if (dirp != NULL)
 1905                         dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0,
 1906                             NULL);
 1907                 nfsrvd_symlinksub(nd, &named, &nva, fhp, vpp, dirp,
 1908                     &dirfor, &diraft, &diraft_ret, NULL, NULL, p, exp,
 1909                     pathcp, pathlen);
 1910         } else if (dirp != NULL) {
 1911                 dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0, NULL);
 1912                 vrele(dirp);
 1913         }
 1914         if (pathcp)
 1915                 free(pathcp, M_TEMP);
 1916 
 1917         if (nd->nd_flag & ND_NFSV3) {
 1918                 if (!nd->nd_repstat) {
 1919                         (void) nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 1);
 1920                         nfsrv_postopattr(nd, 0, &nva);
 1921                 }
 1922                 nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
 1923         }
 1924 
 1925 out:
 1926         NFSEXITCODE2(error, nd);
 1927         return (error);
 1928 }
 1929 
 1930 /*
 1931  * Common code for creating a symbolic link.
 1932  */
 1933 static void
 1934 nfsrvd_symlinksub(struct nfsrv_descript *nd, struct nameidata *ndp,
 1935     struct nfsvattr *nvap, fhandle_t *fhp, vnode_t *vpp,
 1936     vnode_t dirp, struct nfsvattr *dirforp, struct nfsvattr *diraftp,
 1937     int *diraft_retp, nfsattrbit_t *attrbitp,
 1938     NFSACL_T *aclp, NFSPROC_T *p, struct nfsexstuff *exp, char *pathcp,
 1939     int pathlen)
 1940 {
 1941         u_int32_t *tl;
 1942 
 1943         nd->nd_repstat = nfsvno_symlink(ndp, nvap, pathcp, pathlen,
 1944             !(nd->nd_flag & ND_NFSV2), nd->nd_saveduid, nd->nd_cred, p, exp);
 1945         if (!nd->nd_repstat && !(nd->nd_flag & ND_NFSV2)) {
 1946                 nfsrv_fixattr(nd, ndp->ni_vp, nvap, aclp, p, attrbitp, exp);
 1947                 if (nd->nd_flag & ND_NFSV3) {
 1948                         nd->nd_repstat = nfsvno_getfh(ndp->ni_vp, fhp, p);
 1949                         if (!nd->nd_repstat)
 1950                                 nd->nd_repstat = nfsvno_getattr(ndp->ni_vp,
 1951                                     nvap, nd, p, 1, NULL);
 1952                 }
 1953                 if (vpp != NULL && nd->nd_repstat == 0) {
 1954                         NFSVOPUNLOCK(ndp->ni_vp);
 1955                         *vpp = ndp->ni_vp;
 1956                 } else
 1957                         vput(ndp->ni_vp);
 1958         }
 1959         if (dirp) {
 1960                 *diraft_retp = nfsvno_getattr(dirp, diraftp, nd, p, 0, NULL);
 1961                 vrele(dirp);
 1962         }
 1963         if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) {
 1964                 NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
 1965                 *tl++ = newnfs_false;
 1966                 txdr_hyper(dirforp->na_filerev, tl);
 1967                 tl += 2;
 1968                 txdr_hyper(diraftp->na_filerev, tl);
 1969                 (void) nfsrv_putattrbit(nd, attrbitp);
 1970         }
 1971 
 1972         NFSEXITCODE2(0, nd);
 1973 }
 1974 
 1975 /*
 1976  * nfs mkdir service
 1977  */
 1978 int
 1979 nfsrvd_mkdir(struct nfsrv_descript *nd, __unused int isdgram,
 1980     vnode_t dp, vnode_t *vpp, fhandle_t *fhp, struct nfsexstuff *exp)
 1981 {
 1982         struct nfsvattr nva, dirfor, diraft;
 1983         struct nameidata named;
 1984         u_int32_t *tl;
 1985         int error = 0, dirfor_ret = 1, diraft_ret = 1;
 1986         vnode_t dirp = NULL;
 1987         char *bufp;
 1988         u_long *hashp;
 1989         struct thread *p = curthread;
 1990 
 1991         if (nd->nd_repstat) {
 1992                 nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
 1993                 goto out;
 1994         }
 1995         NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE,
 1996             LOCKPARENT | SAVENAME | NOCACHE);
 1997         nfsvno_setpathbuf(&named, &bufp, &hashp);
 1998         error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
 1999         if (error)
 2000                 goto nfsmout;
 2001         if (!nd->nd_repstat) {
 2002                 NFSVNO_ATTRINIT(&nva);
 2003                 if (nd->nd_flag & ND_NFSV3) {
 2004                         error = nfsrv_sattr(nd, NULL, &nva, NULL, NULL, p);
 2005                         if (error)
 2006                                 goto nfsmout;
 2007                 } else {
 2008                         NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 2009                         nva.na_mode = nfstov_mode(*tl++);
 2010                 }
 2011         }
 2012         if (!nd->nd_repstat) {
 2013                 nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp, p, &dirp);
 2014         } else {
 2015                 vrele(dp);
 2016                 nfsvno_relpathbuf(&named);
 2017         }
 2018         if (dirp != NULL && !(nd->nd_flag & ND_NFSV3)) {
 2019                 vrele(dirp);
 2020                 dirp = NULL;
 2021         }
 2022         if (nd->nd_repstat) {
 2023                 if (dirp != NULL) {
 2024                         dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0,
 2025                             NULL);
 2026                         vrele(dirp);
 2027                 }
 2028                 if (nd->nd_flag & ND_NFSV3)
 2029                         nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret,
 2030                             &diraft);
 2031                 goto out;
 2032         }
 2033         if (dirp != NULL)
 2034                 dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0, NULL);
 2035 
 2036         /*
 2037          * Call nfsrvd_mkdirsub() for the code common to V4 as well.
 2038          */
 2039         nfsrvd_mkdirsub(nd, &named, &nva, fhp, vpp, dirp, &dirfor, &diraft,
 2040             &diraft_ret, NULL, NULL, p, exp);
 2041 
 2042         if (nd->nd_flag & ND_NFSV3) {
 2043                 if (!nd->nd_repstat) {
 2044                         (void) nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 1);
 2045                         nfsrv_postopattr(nd, 0, &nva);
 2046                 }
 2047                 nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
 2048         } else if (!nd->nd_repstat) {
 2049                 (void) nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 0);
 2050                 nfsrv_fillattr(nd, &nva);
 2051         }
 2052 
 2053 out:
 2054         NFSEXITCODE2(0, nd);
 2055         return (0);
 2056 nfsmout:
 2057         vrele(dp);
 2058         nfsvno_relpathbuf(&named);
 2059         NFSEXITCODE2(error, nd);
 2060         return (error);
 2061 }
 2062 
 2063 /*
 2064  * Code common to mkdir for V2,3 and 4.
 2065  */
 2066 static void
 2067 nfsrvd_mkdirsub(struct nfsrv_descript *nd, struct nameidata *ndp,
 2068     struct nfsvattr *nvap, fhandle_t *fhp, vnode_t *vpp,
 2069     vnode_t dirp, struct nfsvattr *dirforp, struct nfsvattr *diraftp,
 2070     int *diraft_retp, nfsattrbit_t *attrbitp, NFSACL_T *aclp,
 2071     NFSPROC_T *p, struct nfsexstuff *exp)
 2072 {
 2073         vnode_t vp;
 2074         u_int32_t *tl;
 2075 
 2076         NFSVNO_SETATTRVAL(nvap, type, VDIR);
 2077         nd->nd_repstat = nfsvno_mkdir(ndp, nvap, nd->nd_saveduid,
 2078             nd->nd_cred, p, exp);
 2079         if (!nd->nd_repstat) {
 2080                 vp = ndp->ni_vp;
 2081                 nfsrv_fixattr(nd, vp, nvap, aclp, p, attrbitp, exp);
 2082                 nd->nd_repstat = nfsvno_getfh(vp, fhp, p);
 2083                 if (!(nd->nd_flag & ND_NFSV4) && !nd->nd_repstat)
 2084                         nd->nd_repstat = nfsvno_getattr(vp, nvap, nd, p, 1,
 2085                             NULL);
 2086                 if (vpp && !nd->nd_repstat) {
 2087                         NFSVOPUNLOCK(vp);
 2088                         *vpp = vp;
 2089                 } else {
 2090                         vput(vp);
 2091                 }
 2092         }
 2093         if (dirp) {
 2094                 *diraft_retp = nfsvno_getattr(dirp, diraftp, nd, p, 0, NULL);
 2095                 vrele(dirp);
 2096         }
 2097         if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) {
 2098                 NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
 2099                 *tl++ = newnfs_false;
 2100                 txdr_hyper(dirforp->na_filerev, tl);
 2101                 tl += 2;
 2102                 txdr_hyper(diraftp->na_filerev, tl);
 2103                 (void) nfsrv_putattrbit(nd, attrbitp);
 2104         }
 2105 
 2106         NFSEXITCODE2(0, nd);
 2107 }
 2108 
 2109 /*
 2110  * nfs commit service
 2111  */
 2112 int
 2113 nfsrvd_commit(struct nfsrv_descript *nd, __unused int isdgram,
 2114     vnode_t vp, __unused struct nfsexstuff *exp)
 2115 {
 2116         struct nfsvattr bfor, aft;
 2117         u_int32_t *tl;
 2118         int error = 0, for_ret = 1, aft_ret = 1, cnt;
 2119         u_int64_t off;
 2120         struct thread *p = curthread;
 2121 
 2122        if (nd->nd_repstat) {
 2123                 nfsrv_wcc(nd, for_ret, &bfor, aft_ret, &aft);
 2124                 goto out;
 2125         }
 2126 
 2127         /* Return NFSERR_ISDIR in NFSv4 when commit on a directory. */
 2128         if (vp->v_type != VREG) {
 2129                 if (nd->nd_flag & ND_NFSV3)
 2130                         error = NFSERR_NOTSUPP;
 2131                 else
 2132                         error = (vp->v_type == VDIR) ? NFSERR_ISDIR : NFSERR_INVAL;
 2133                 goto nfsmout;
 2134         }
 2135         NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
 2136 
 2137         /*
 2138          * XXX At this time VOP_FSYNC() does not accept offset and byte
 2139          * count parameters, so these arguments are useless (someday maybe).
 2140          */
 2141         off = fxdr_hyper(tl);
 2142         tl += 2;
 2143         cnt = fxdr_unsigned(int, *tl);
 2144         if (nd->nd_flag & ND_NFSV3)
 2145                 for_ret = nfsvno_getattr(vp, &bfor, nd, p, 1, NULL);
 2146         nd->nd_repstat = nfsvno_fsync(vp, off, cnt, nd->nd_cred, p);
 2147         if (nd->nd_flag & ND_NFSV3) {
 2148                 aft_ret = nfsvno_getattr(vp, &aft, nd, p, 1, NULL);
 2149                 nfsrv_wcc(nd, for_ret, &bfor, aft_ret, &aft);
 2150         }
 2151         vput(vp);
 2152         if (!nd->nd_repstat) {
 2153                 NFSM_BUILD(tl, u_int32_t *, NFSX_VERF);
 2154                 *tl++ = txdr_unsigned(nfsboottime.tv_sec);
 2155                 *tl = txdr_unsigned(nfsboottime.tv_usec);
 2156         }
 2157 
 2158 out:
 2159         NFSEXITCODE2(0, nd);
 2160         return (0);
 2161 nfsmout:
 2162         vput(vp);
 2163         NFSEXITCODE2(error, nd);
 2164         return (error);
 2165 }
 2166 
 2167 /*
 2168  * nfs statfs service
 2169  */
 2170 int
 2171 nfsrvd_statfs(struct nfsrv_descript *nd, __unused int isdgram,
 2172     vnode_t vp, __unused struct nfsexstuff *exp)
 2173 {
 2174         struct statfs *sf;
 2175         u_int32_t *tl;
 2176         int getret = 1;
 2177         struct nfsvattr at;
 2178         u_quad_t tval;
 2179         struct thread *p = curthread;
 2180 
 2181         sf = NULL;
 2182         if (nd->nd_repstat) {
 2183                 nfsrv_postopattr(nd, getret, &at);
 2184                 goto out;
 2185         }
 2186         sf = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
 2187         nd->nd_repstat = nfsvno_statfs(vp, sf);
 2188         getret = nfsvno_getattr(vp, &at, nd, p, 1, NULL);
 2189         vput(vp);
 2190         if (nd->nd_flag & ND_NFSV3)
 2191                 nfsrv_postopattr(nd, getret, &at);
 2192         if (nd->nd_repstat)
 2193                 goto out;
 2194         if (nd->nd_flag & ND_NFSV2) {
 2195                 NFSM_BUILD(tl, u_int32_t *, NFSX_V2STATFS);
 2196                 *tl++ = txdr_unsigned(NFS_V2MAXDATA);
 2197                 *tl++ = txdr_unsigned(sf->f_bsize);
 2198                 *tl++ = txdr_unsigned(sf->f_blocks);
 2199                 *tl++ = txdr_unsigned(sf->f_bfree);
 2200                 *tl = txdr_unsigned(sf->f_bavail);
 2201         } else {
 2202                 NFSM_BUILD(tl, u_int32_t *, NFSX_V3STATFS);
 2203                 tval = (u_quad_t)sf->f_blocks;
 2204                 tval *= (u_quad_t)sf->f_bsize;
 2205                 txdr_hyper(tval, tl); tl += 2;
 2206                 tval = (u_quad_t)sf->f_bfree;
 2207                 tval *= (u_quad_t)sf->f_bsize;
 2208                 txdr_hyper(tval, tl); tl += 2;
 2209                 tval = (u_quad_t)sf->f_bavail;
 2210                 tval *= (u_quad_t)sf->f_bsize;
 2211                 txdr_hyper(tval, tl); tl += 2;
 2212                 tval = (u_quad_t)sf->f_files;
 2213                 txdr_hyper(tval, tl); tl += 2;
 2214                 tval = (u_quad_t)sf->f_ffree;
 2215                 txdr_hyper(tval, tl); tl += 2;
 2216                 tval = (u_quad_t)sf->f_ffree;
 2217                 txdr_hyper(tval, tl); tl += 2;
 2218                 *tl = 0;
 2219         }
 2220 
 2221 out:
 2222         free(sf, M_STATFS);
 2223         NFSEXITCODE2(0, nd);
 2224         return (0);
 2225 }
 2226 
 2227 /*
 2228  * nfs fsinfo service
 2229  */
 2230 int
 2231 nfsrvd_fsinfo(struct nfsrv_descript *nd, int isdgram,
 2232     vnode_t vp, __unused struct nfsexstuff *exp)
 2233 {
 2234         u_int32_t *tl;
 2235         struct nfsfsinfo fs;
 2236         int getret = 1;
 2237         struct nfsvattr at;
 2238         struct thread *p = curthread;
 2239 
 2240         if (nd->nd_repstat) {
 2241                 nfsrv_postopattr(nd, getret, &at);
 2242                 goto out;
 2243         }
 2244         getret = nfsvno_getattr(vp, &at, nd, p, 1, NULL);
 2245         nfsvno_getfs(&fs, isdgram);
 2246         vput(vp);
 2247         nfsrv_postopattr(nd, getret, &at);
 2248         NFSM_BUILD(tl, u_int32_t *, NFSX_V3FSINFO);
 2249         *tl++ = txdr_unsigned(fs.fs_rtmax);
 2250         *tl++ = txdr_unsigned(fs.fs_rtpref);
 2251         *tl++ = txdr_unsigned(fs.fs_rtmult);
 2252         *tl++ = txdr_unsigned(fs.fs_wtmax);
 2253         *tl++ = txdr_unsigned(fs.fs_wtpref);
 2254         *tl++ = txdr_unsigned(fs.fs_wtmult);
 2255         *tl++ = txdr_unsigned(fs.fs_dtpref);
 2256         txdr_hyper(fs.fs_maxfilesize, tl);
 2257         tl += 2;
 2258         txdr_nfsv3time(&fs.fs_timedelta, tl);
 2259         tl += 2;
 2260         *tl = txdr_unsigned(fs.fs_properties);
 2261 
 2262 out:
 2263         NFSEXITCODE2(0, nd);
 2264         return (0);
 2265 }
 2266 
 2267 /*
 2268  * nfs pathconf service
 2269  */
 2270 int
 2271 nfsrvd_pathconf(struct nfsrv_descript *nd, __unused int isdgram,
 2272     vnode_t vp, __unused struct nfsexstuff *exp)
 2273 {
 2274         struct nfsv3_pathconf *pc;
 2275         int getret = 1;
 2276         long linkmax, namemax, chownres, notrunc;
 2277         struct nfsvattr at;
 2278         struct thread *p = curthread;
 2279 
 2280         if (nd->nd_repstat) {
 2281                 nfsrv_postopattr(nd, getret, &at);
 2282                 goto out;
 2283         }
 2284         nd->nd_repstat = nfsvno_pathconf(vp, _PC_LINK_MAX, &linkmax,
 2285             nd->nd_cred, p);
 2286         if (!nd->nd_repstat)
 2287                 nd->nd_repstat = nfsvno_pathconf(vp, _PC_NAME_MAX, &namemax,
 2288                     nd->nd_cred, p);
 2289         if (!nd->nd_repstat)
 2290                 nd->nd_repstat=nfsvno_pathconf(vp, _PC_CHOWN_RESTRICTED,
 2291                     &chownres, nd->nd_cred, p);
 2292         if (!nd->nd_repstat)
 2293                 nd->nd_repstat = nfsvno_pathconf(vp, _PC_NO_TRUNC, &notrunc,
 2294                     nd->nd_cred, p);
 2295         getret = nfsvno_getattr(vp, &at, nd, p, 1, NULL);
 2296         vput(vp);
 2297         nfsrv_postopattr(nd, getret, &at);
 2298         if (!nd->nd_repstat) {
 2299                 NFSM_BUILD(pc, struct nfsv3_pathconf *, NFSX_V3PATHCONF);
 2300                 pc->pc_linkmax = txdr_unsigned(linkmax);
 2301                 pc->pc_namemax = txdr_unsigned(namemax);
 2302                 pc->pc_notrunc = txdr_unsigned(notrunc);
 2303                 pc->pc_chownrestricted = txdr_unsigned(chownres);
 2304 
 2305                 /*
 2306                  * These should probably be supported by VOP_PATHCONF(), but
 2307                  * until msdosfs is exportable (why would you want to?), the
 2308                  * Unix defaults should be ok.
 2309                  */
 2310                 pc->pc_caseinsensitive = newnfs_false;
 2311                 pc->pc_casepreserving = newnfs_true;
 2312         }
 2313 
 2314 out:
 2315         NFSEXITCODE2(0, nd);
 2316         return (0);
 2317 }
 2318 
 2319 /*
 2320  * nfsv4 lock service
 2321  */
 2322 int
 2323 nfsrvd_lock(struct nfsrv_descript *nd, __unused int isdgram,
 2324     vnode_t vp, struct nfsexstuff *exp)
 2325 {
 2326         u_int32_t *tl;
 2327         int i;
 2328         struct nfsstate *stp = NULL;
 2329         struct nfslock *lop;
 2330         struct nfslockconflict cf;
 2331         int error = 0;
 2332         u_short flags = NFSLCK_LOCK, lflags;
 2333         u_int64_t offset, len;
 2334         nfsv4stateid_t stateid;
 2335         nfsquad_t clientid;
 2336         struct thread *p = curthread;
 2337 
 2338         NFSM_DISSECT(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
 2339         i = fxdr_unsigned(int, *tl++);
 2340         switch (i) {
 2341         case NFSV4LOCKT_READW:
 2342                 flags |= NFSLCK_BLOCKING;
 2343         case NFSV4LOCKT_READ:
 2344                 lflags = NFSLCK_READ;
 2345                 break;
 2346         case NFSV4LOCKT_WRITEW:
 2347                 flags |= NFSLCK_BLOCKING;
 2348         case NFSV4LOCKT_WRITE:
 2349                 lflags = NFSLCK_WRITE;
 2350                 break;
 2351         default:
 2352                 nd->nd_repstat = NFSERR_BADXDR;
 2353                 goto nfsmout;
 2354         }
 2355         if (*tl++ == newnfs_true)
 2356                 flags |= NFSLCK_RECLAIM;
 2357         offset = fxdr_hyper(tl);
 2358         tl += 2;
 2359         len = fxdr_hyper(tl);
 2360         tl += 2;
 2361         if (*tl == newnfs_true)
 2362                 flags |= NFSLCK_OPENTOLOCK;
 2363         if (flags & NFSLCK_OPENTOLOCK) {
 2364                 NFSM_DISSECT(tl, u_int32_t *, 5 * NFSX_UNSIGNED + NFSX_STATEID);
 2365                 i = fxdr_unsigned(int, *(tl+4+(NFSX_STATEID / NFSX_UNSIGNED)));
 2366                 if (i <= 0 || i > NFSV4_OPAQUELIMIT) {
 2367                         nd->nd_repstat = NFSERR_BADXDR;
 2368                         goto nfsmout;
 2369                 }
 2370                 stp = malloc(sizeof (struct nfsstate) + i,
 2371                         M_NFSDSTATE, M_WAITOK);
 2372                 stp->ls_ownerlen = i;
 2373                 stp->ls_op = nd->nd_rp;
 2374                 stp->ls_seq = fxdr_unsigned(int, *tl++);
 2375                 stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
 2376                 NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other,
 2377                         NFSX_STATEIDOTHER);
 2378                 tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
 2379 
 2380                 /*
 2381                  * For the special stateid of other all 0s and seqid == 1, set
 2382                  * the stateid to the current stateid, if it is set.
 2383                  */
 2384                 if ((nd->nd_flag & ND_NFSV41) != 0 &&
 2385                     stp->ls_stateid.seqid == 1 &&
 2386                     stp->ls_stateid.other[0] == 0 &&
 2387                     stp->ls_stateid.other[1] == 0 &&
 2388                     stp->ls_stateid.other[2] == 0) {
 2389                         if ((nd->nd_flag & ND_CURSTATEID) != 0) {
 2390                                 stp->ls_stateid = nd->nd_curstateid;
 2391                                 stp->ls_stateid.seqid = 0;
 2392                         } else {
 2393                                 nd->nd_repstat = NFSERR_BADSTATEID;
 2394                                 goto nfsmout;
 2395                         }
 2396                 }
 2397 
 2398                 stp->ls_opentolockseq = fxdr_unsigned(int, *tl++);
 2399                 clientid.lval[0] = *tl++;
 2400                 clientid.lval[1] = *tl++;
 2401                 if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
 2402                         if ((nd->nd_flag & ND_NFSV41) != 0)
 2403                                 clientid.qval = nd->nd_clientid.qval;
 2404                         else if (nd->nd_clientid.qval != clientid.qval)
 2405                                 printf("EEK3 multiple clids\n");
 2406                 } else {
 2407                         if ((nd->nd_flag & ND_NFSV41) != 0)
 2408                                 printf("EEK! no clientid from session\n");
 2409                         nd->nd_flag |= ND_IMPLIEDCLID;
 2410                         nd->nd_clientid.qval = clientid.qval;
 2411                 }
 2412                 error = nfsrv_mtostr(nd, stp->ls_owner, stp->ls_ownerlen);
 2413                 if (error)
 2414                         goto nfsmout;
 2415         } else {
 2416                 NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + NFSX_UNSIGNED);
 2417                 stp = malloc(sizeof (struct nfsstate),
 2418                         M_NFSDSTATE, M_WAITOK);
 2419                 stp->ls_ownerlen = 0;
 2420                 stp->ls_op = nd->nd_rp;
 2421                 stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
 2422                 NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other,
 2423                         NFSX_STATEIDOTHER);
 2424                 tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
 2425 
 2426                 /*
 2427                  * For the special stateid of other all 0s and seqid == 1, set
 2428                  * the stateid to the current stateid, if it is set.
 2429                  */
 2430                 if ((nd->nd_flag & ND_NFSV41) != 0 &&
 2431                     stp->ls_stateid.seqid == 1 &&
 2432                     stp->ls_stateid.other[0] == 0 &&
 2433                     stp->ls_stateid.other[1] == 0 &&
 2434                     stp->ls_stateid.other[2] == 0) {
 2435                         if ((nd->nd_flag & ND_CURSTATEID) != 0) {
 2436                                 stp->ls_stateid = nd->nd_curstateid;
 2437                                 stp->ls_stateid.seqid = 0;
 2438                         } else {
 2439                                 nd->nd_repstat = NFSERR_BADSTATEID;
 2440                                 goto nfsmout;
 2441                         }
 2442                 }
 2443 
 2444                 stp->ls_seq = fxdr_unsigned(int, *tl);
 2445                 clientid.lval[0] = stp->ls_stateid.other[0];
 2446                 clientid.lval[1] = stp->ls_stateid.other[1];
 2447                 if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
 2448                         if ((nd->nd_flag & ND_NFSV41) != 0)
 2449                                 clientid.qval = nd->nd_clientid.qval;
 2450                         else if (nd->nd_clientid.qval != clientid.qval)
 2451                                 printf("EEK4 multiple clids\n");
 2452                 } else {
 2453                         if ((nd->nd_flag & ND_NFSV41) != 0)
 2454                                 printf("EEK! no clientid from session\n");
 2455                         nd->nd_flag |= ND_IMPLIEDCLID;
 2456                         nd->nd_clientid.qval = clientid.qval;
 2457                 }
 2458         }
 2459         lop = malloc(sizeof (struct nfslock),
 2460                 M_NFSDLOCK, M_WAITOK);
 2461         lop->lo_first = offset;
 2462         if (len == NFS64BITSSET) {
 2463                 lop->lo_end = NFS64BITSSET;
 2464         } else {
 2465                 lop->lo_end = offset + len;
 2466                 if (lop->lo_end <= lop->lo_first)
 2467                         nd->nd_repstat = NFSERR_INVAL;
 2468         }
 2469         lop->lo_flags = lflags;
 2470         stp->ls_flags = flags;
 2471         stp->ls_uid = nd->nd_cred->cr_uid;
 2472 
 2473         /*
 2474          * Do basic access checking.
 2475          */
 2476         if (!nd->nd_repstat && vnode_vtype(vp) != VREG) {
 2477             if (vnode_vtype(vp) == VDIR)
 2478                 nd->nd_repstat = NFSERR_ISDIR;
 2479             else
 2480                 nd->nd_repstat = NFSERR_INVAL;
 2481         }
 2482         if (!nd->nd_repstat) {
 2483             if (lflags & NFSLCK_WRITE) {
 2484                 nd->nd_repstat = nfsvno_accchk(vp, VWRITE,
 2485                     nd->nd_cred, exp, p, NFSACCCHK_ALLOWOWNER,
 2486                     NFSACCCHK_VPISLOCKED, NULL);
 2487             } else {
 2488                 nd->nd_repstat = nfsvno_accchk(vp, VREAD,
 2489                     nd->nd_cred, exp, p, NFSACCCHK_ALLOWOWNER,
 2490                     NFSACCCHK_VPISLOCKED, NULL);
 2491                 if (nd->nd_repstat)
 2492                     nd->nd_repstat = nfsvno_accchk(vp, VEXEC,
 2493                         nd->nd_cred, exp, p, NFSACCCHK_ALLOWOWNER,
 2494                         NFSACCCHK_VPISLOCKED, NULL);
 2495             }
 2496         }
 2497 
 2498         /*
 2499          * We call nfsrv_lockctrl() even if nd_repstat set, so that the
 2500          * seqid# gets updated. nfsrv_lockctrl() will return the value
 2501          * of nd_repstat, if it gets that far.
 2502          */
 2503         nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, &cf, clientid, 
 2504                 &stateid, exp, nd, p);
 2505         if (lop)
 2506                 free(lop, M_NFSDLOCK);
 2507         if (stp)
 2508                 free(stp, M_NFSDSTATE);
 2509         if (!nd->nd_repstat) {
 2510                 /* For NFSv4.1, set the Current StateID. */
 2511                 if ((nd->nd_flag & ND_NFSV41) != 0) {
 2512                         nd->nd_curstateid = stateid;
 2513                         nd->nd_flag |= ND_CURSTATEID;
 2514                 }
 2515                 NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID);
 2516                 *tl++ = txdr_unsigned(stateid.seqid);
 2517                 NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER);
 2518         } else if (nd->nd_repstat == NFSERR_DENIED) {
 2519                 NFSM_BUILD(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
 2520                 txdr_hyper(cf.cl_first, tl);
 2521                 tl += 2;
 2522                 if (cf.cl_end == NFS64BITSSET)
 2523                         len = NFS64BITSSET;
 2524                 else
 2525                         len = cf.cl_end - cf.cl_first;
 2526                 txdr_hyper(len, tl);
 2527                 tl += 2;
 2528                 if (cf.cl_flags == NFSLCK_WRITE)
 2529                         *tl++ = txdr_unsigned(NFSV4LOCKT_WRITE);
 2530                 else
 2531                         *tl++ = txdr_unsigned(NFSV4LOCKT_READ);
 2532                 *tl++ = stateid.other[0];
 2533                 *tl = stateid.other[1];
 2534                 (void) nfsm_strtom(nd, cf.cl_owner, cf.cl_ownerlen);
 2535         }
 2536         vput(vp);
 2537         NFSEXITCODE2(0, nd);
 2538         return (0);
 2539 nfsmout:
 2540         vput(vp);
 2541         if (stp)
 2542                 free(stp, M_NFSDSTATE);
 2543         NFSEXITCODE2(error, nd);
 2544         return (error);
 2545 }
 2546 
 2547 /*
 2548  * nfsv4 lock test service
 2549  */
 2550 int
 2551 nfsrvd_lockt(struct nfsrv_descript *nd, __unused int isdgram,
 2552     vnode_t vp, struct nfsexstuff *exp)
 2553 {
 2554         u_int32_t *tl;
 2555         int i;
 2556         struct nfsstate *stp = NULL;
 2557         struct nfslock lo, *lop = &lo;
 2558         struct nfslockconflict cf;
 2559         int error = 0;
 2560         nfsv4stateid_t stateid;
 2561         nfsquad_t clientid;
 2562         u_int64_t len;
 2563         struct thread *p = curthread;
 2564 
 2565         NFSM_DISSECT(tl, u_int32_t *, 8 * NFSX_UNSIGNED);
 2566         i = fxdr_unsigned(int, *(tl + 7));
 2567         if (i <= 0 || i > NFSV4_OPAQUELIMIT) {
 2568                 nd->nd_repstat = NFSERR_BADXDR;
 2569                 goto nfsmout;
 2570         }
 2571         stp = malloc(sizeof (struct nfsstate) + i,
 2572             M_NFSDSTATE, M_WAITOK);
 2573         stp->ls_ownerlen = i;
 2574         stp->ls_op = NULL;
 2575         stp->ls_flags = NFSLCK_TEST;
 2576         stp->ls_uid = nd->nd_cred->cr_uid;
 2577         i = fxdr_unsigned(int, *tl++);
 2578         switch (i) {
 2579         case NFSV4LOCKT_READW:
 2580                 stp->ls_flags |= NFSLCK_BLOCKING;
 2581         case NFSV4LOCKT_READ:
 2582                 lo.lo_flags = NFSLCK_READ;
 2583                 break;
 2584         case NFSV4LOCKT_WRITEW:
 2585                 stp->ls_flags |= NFSLCK_BLOCKING;
 2586         case NFSV4LOCKT_WRITE:
 2587                 lo.lo_flags = NFSLCK_WRITE;
 2588                 break;
 2589         default:
 2590                 nd->nd_repstat = NFSERR_BADXDR;
 2591                 goto nfsmout;
 2592         }
 2593         lo.lo_first = fxdr_hyper(tl);
 2594         tl += 2;
 2595         len = fxdr_hyper(tl);
 2596         if (len == NFS64BITSSET) {
 2597                 lo.lo_end = NFS64BITSSET;
 2598         } else {
 2599                 lo.lo_end = lo.lo_first + len;
 2600                 if (lo.lo_end <= lo.lo_first)
 2601                         nd->nd_repstat = NFSERR_INVAL;
 2602         }
 2603         tl += 2;
 2604         clientid.lval[0] = *tl++;
 2605         clientid.lval[1] = *tl;
 2606         if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
 2607                 if ((nd->nd_flag & ND_NFSV41) != 0)
 2608                         clientid.qval = nd->nd_clientid.qval;
 2609                 else if (nd->nd_clientid.qval != clientid.qval)
 2610                         printf("EEK5 multiple clids\n");
 2611         } else {
 2612                 if ((nd->nd_flag & ND_NFSV41) != 0)
 2613                         printf("EEK! no clientid from session\n");
 2614                 nd->nd_flag |= ND_IMPLIEDCLID;
 2615                 nd->nd_clientid.qval = clientid.qval;
 2616         }
 2617         error = nfsrv_mtostr(nd, stp->ls_owner, stp->ls_ownerlen);
 2618         if (error)
 2619                 goto nfsmout;
 2620         if (!nd->nd_repstat && vnode_vtype(vp) != VREG) {
 2621             if (vnode_vtype(vp) == VDIR)
 2622                 nd->nd_repstat = NFSERR_ISDIR;
 2623             else
 2624                 nd->nd_repstat = NFSERR_INVAL;
 2625         }
 2626         if (!nd->nd_repstat)
 2627           nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, &cf, clientid,
 2628             &stateid, exp, nd, p);
 2629         if (nd->nd_repstat) {
 2630             if (nd->nd_repstat == NFSERR_DENIED) {
 2631                 NFSM_BUILD(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
 2632                 txdr_hyper(cf.cl_first, tl);
 2633                 tl += 2;
 2634                 if (cf.cl_end == NFS64BITSSET)
 2635                         len = NFS64BITSSET;
 2636                 else
 2637                         len = cf.cl_end - cf.cl_first;
 2638                 txdr_hyper(len, tl);
 2639                 tl += 2;
 2640                 if (cf.cl_flags == NFSLCK_WRITE)
 2641                         *tl++ = txdr_unsigned(NFSV4LOCKT_WRITE);
 2642                 else
 2643                         *tl++ = txdr_unsigned(NFSV4LOCKT_READ);
 2644                 *tl++ = stp->ls_stateid.other[0];
 2645                 *tl = stp->ls_stateid.other[1];
 2646                 (void) nfsm_strtom(nd, cf.cl_owner, cf.cl_ownerlen);
 2647             }
 2648         }
 2649         vput(vp);
 2650         if (stp)
 2651                 free(stp, M_NFSDSTATE);
 2652         NFSEXITCODE2(0, nd);
 2653         return (0);
 2654 nfsmout:
 2655         vput(vp);
 2656         if (stp)
 2657                 free(stp, M_NFSDSTATE);
 2658         NFSEXITCODE2(error, nd);
 2659         return (error);
 2660 }
 2661 
 2662 /*
 2663  * nfsv4 unlock service
 2664  */
 2665 int
 2666 nfsrvd_locku(struct nfsrv_descript *nd, __unused int isdgram,
 2667     vnode_t vp, struct nfsexstuff *exp)
 2668 {
 2669         u_int32_t *tl;
 2670         int i;
 2671         struct nfsstate *stp;
 2672         struct nfslock *lop;
 2673         int error = 0;
 2674         nfsv4stateid_t stateid;
 2675         nfsquad_t clientid;
 2676         u_int64_t len;
 2677         struct thread *p = curthread;
 2678 
 2679         NFSM_DISSECT(tl, u_int32_t *, 6 * NFSX_UNSIGNED + NFSX_STATEID);
 2680         stp = malloc(sizeof (struct nfsstate),
 2681             M_NFSDSTATE, M_WAITOK);
 2682         lop = malloc(sizeof (struct nfslock),
 2683             M_NFSDLOCK, M_WAITOK);
 2684         stp->ls_flags = NFSLCK_UNLOCK;
 2685         lop->lo_flags = NFSLCK_UNLOCK;
 2686         stp->ls_op = nd->nd_rp;
 2687         i = fxdr_unsigned(int, *tl++);
 2688         switch (i) {
 2689         case NFSV4LOCKT_READW:
 2690                 stp->ls_flags |= NFSLCK_BLOCKING;
 2691         case NFSV4LOCKT_READ:
 2692                 break;
 2693         case NFSV4LOCKT_WRITEW:
 2694                 stp->ls_flags |= NFSLCK_BLOCKING;
 2695         case NFSV4LOCKT_WRITE:
 2696                 break;
 2697         default:
 2698                 nd->nd_repstat = NFSERR_BADXDR;
 2699                 free(stp, M_NFSDSTATE);
 2700                 free(lop, M_NFSDLOCK);
 2701                 goto nfsmout;
 2702         }
 2703         stp->ls_ownerlen = 0;
 2704         stp->ls_uid = nd->nd_cred->cr_uid;
 2705         stp->ls_seq = fxdr_unsigned(int, *tl++);
 2706         stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
 2707         NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other,
 2708             NFSX_STATEIDOTHER);
 2709         tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
 2710 
 2711         /*
 2712          * For the special stateid of other all 0s and seqid == 1, set the
 2713          * stateid to the current stateid, if it is set.
 2714          */
 2715         if ((nd->nd_flag & ND_NFSV41) != 0 && stp->ls_stateid.seqid == 1 &&
 2716             stp->ls_stateid.other[0] == 0 && stp->ls_stateid.other[1] == 0 &&
 2717             stp->ls_stateid.other[2] == 0) {
 2718                 if ((nd->nd_flag & ND_CURSTATEID) != 0) {
 2719                         stp->ls_stateid = nd->nd_curstateid;
 2720                         stp->ls_stateid.seqid = 0;
 2721                 } else {
 2722                         nd->nd_repstat = NFSERR_BADSTATEID;
 2723                         free(stp, M_NFSDSTATE);
 2724                         free(lop, M_NFSDLOCK);
 2725                         goto nfsmout;
 2726                 }
 2727         }
 2728 
 2729         lop->lo_first = fxdr_hyper(tl);
 2730         tl += 2;
 2731         len = fxdr_hyper(tl);
 2732         if (len == NFS64BITSSET) {
 2733                 lop->lo_end = NFS64BITSSET;
 2734         } else {
 2735                 lop->lo_end = lop->lo_first + len;
 2736                 if (lop->lo_end <= lop->lo_first)
 2737                         nd->nd_repstat = NFSERR_INVAL;
 2738         }
 2739         clientid.lval[0] = stp->ls_stateid.other[0];
 2740         clientid.lval[1] = stp->ls_stateid.other[1];
 2741         if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
 2742                 if ((nd->nd_flag & ND_NFSV41) != 0)
 2743                         clientid.qval = nd->nd_clientid.qval;
 2744                 else if (nd->nd_clientid.qval != clientid.qval)
 2745                         printf("EEK6 multiple clids\n");
 2746         } else {
 2747                 if ((nd->nd_flag & ND_NFSV41) != 0)
 2748                         printf("EEK! no clientid from session\n");
 2749                 nd->nd_flag |= ND_IMPLIEDCLID;
 2750                 nd->nd_clientid.qval = clientid.qval;
 2751         }
 2752         if (!nd->nd_repstat && vnode_vtype(vp) != VREG) {
 2753             if (vnode_vtype(vp) == VDIR)
 2754                 nd->nd_repstat = NFSERR_ISDIR;
 2755             else
 2756                 nd->nd_repstat = NFSERR_INVAL;
 2757         }
 2758         /*
 2759          * Call nfsrv_lockctrl() even if nd_repstat is set, so that the
 2760          * seqid# gets incremented. nfsrv_lockctrl() will return the
 2761          * value of nd_repstat, if it gets that far.
 2762          */
 2763         nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid,
 2764             &stateid, exp, nd, p);
 2765         if (stp)
 2766                 free(stp, M_NFSDSTATE);
 2767         if (lop)
 2768                 free(lop, M_NFSDLOCK);
 2769         if (!nd->nd_repstat) {
 2770                 NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID);
 2771                 *tl++ = txdr_unsigned(stateid.seqid);
 2772                 NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER);
 2773         }
 2774 nfsmout:
 2775         vput(vp);
 2776         NFSEXITCODE2(error, nd);
 2777         return (error);
 2778 }
 2779 
 2780 /*
 2781  * nfsv4 open service
 2782  */
 2783 int
 2784 nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram,
 2785     vnode_t dp, vnode_t *vpp, __unused fhandle_t *fhp, struct nfsexstuff *exp)
 2786 {
 2787         u_int32_t *tl;
 2788         int i, retext;
 2789         struct nfsstate *stp = NULL;
 2790         int error = 0, create, claim, exclusive_flag = 0, override;
 2791         u_int32_t rflags = NFSV4OPEN_LOCKTYPEPOSIX, acemask;
 2792         int how = NFSCREATE_UNCHECKED;
 2793         int32_t cverf[2], tverf[2] = { 0, 0 };
 2794         vnode_t vp = NULL, dirp = NULL;
 2795         struct nfsvattr nva, dirfor, diraft;
 2796         struct nameidata named;
 2797         nfsv4stateid_t stateid, delegstateid;
 2798         nfsattrbit_t attrbits;
 2799         nfsquad_t clientid;
 2800         char *bufp = NULL;
 2801         u_long *hashp;
 2802         NFSACL_T *aclp = NULL;
 2803         struct thread *p = curthread;
 2804 
 2805 #ifdef NFS4_ACL_EXTATTR_NAME
 2806         aclp = acl_alloc(M_WAITOK);
 2807         aclp->acl_cnt = 0;
 2808 #endif
 2809         NFSZERO_ATTRBIT(&attrbits);
 2810         named.ni_startdir = NULL;
 2811         named.ni_cnd.cn_nameiop = 0;
 2812         NFSM_DISSECT(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
 2813         i = fxdr_unsigned(int, *(tl + 5));
 2814         if (i <= 0 || i > NFSV4_OPAQUELIMIT) {
 2815                 nd->nd_repstat = NFSERR_BADXDR;
 2816                 goto nfsmout;
 2817         }
 2818         stp = malloc(sizeof (struct nfsstate) + i,
 2819             M_NFSDSTATE, M_WAITOK);
 2820         stp->ls_ownerlen = i;
 2821         stp->ls_op = nd->nd_rp;
 2822         stp->ls_flags = NFSLCK_OPEN;
 2823         stp->ls_uid = nd->nd_cred->cr_uid;
 2824         stp->ls_seq = fxdr_unsigned(u_int32_t, *tl++);
 2825         i = fxdr_unsigned(int, *tl++);
 2826         retext = 0;
 2827         if ((i & (NFSV4OPEN_WANTDELEGMASK | NFSV4OPEN_WANTSIGNALDELEG |
 2828             NFSV4OPEN_WANTPUSHDELEG)) != 0 && (nd->nd_flag & ND_NFSV41) != 0) {
 2829                 retext = 1;
 2830                 /* For now, ignore these. */
 2831                 i &= ~(NFSV4OPEN_WANTPUSHDELEG | NFSV4OPEN_WANTSIGNALDELEG);
 2832                 switch (i & NFSV4OPEN_WANTDELEGMASK) {
 2833                 case NFSV4OPEN_WANTANYDELEG:
 2834                         stp->ls_flags |= (NFSLCK_WANTRDELEG |
 2835                             NFSLCK_WANTWDELEG);
 2836                         i &= ~NFSV4OPEN_WANTDELEGMASK;
 2837                         break;
 2838                 case NFSV4OPEN_WANTREADDELEG:
 2839                         stp->ls_flags |= NFSLCK_WANTRDELEG;
 2840                         i &= ~NFSV4OPEN_WANTDELEGMASK;
 2841                         break;
 2842                 case NFSV4OPEN_WANTWRITEDELEG:
 2843                         stp->ls_flags |= NFSLCK_WANTWDELEG;
 2844                         i &= ~NFSV4OPEN_WANTDELEGMASK;
 2845                         break;
 2846                 case NFSV4OPEN_WANTNODELEG:
 2847                         stp->ls_flags |= NFSLCK_WANTNODELEG;
 2848                         i &= ~NFSV4OPEN_WANTDELEGMASK;
 2849                         break;
 2850                 case NFSV4OPEN_WANTCANCEL:
 2851                         printf("NFSv4: ignore Open WantCancel\n");
 2852                         i &= ~NFSV4OPEN_WANTDELEGMASK;
 2853                         break;
 2854                 default:
 2855                         /* nd_repstat will be set to NFSERR_INVAL below. */
 2856                         break;
 2857                 }
 2858         }
 2859         switch (i) {
 2860         case NFSV4OPEN_ACCESSREAD:
 2861                 stp->ls_flags |= NFSLCK_READACCESS;
 2862                 break;
 2863         case NFSV4OPEN_ACCESSWRITE:
 2864                 stp->ls_flags |= NFSLCK_WRITEACCESS;
 2865                 break;
 2866         case NFSV4OPEN_ACCESSBOTH:
 2867                 stp->ls_flags |= (NFSLCK_READACCESS | NFSLCK_WRITEACCESS);
 2868                 break;
 2869         default:
 2870                 nd->nd_repstat = NFSERR_INVAL;
 2871         }
 2872         i = fxdr_unsigned(int, *tl++);
 2873         switch (i) {
 2874         case NFSV4OPEN_DENYNONE:
 2875                 break;
 2876         case NFSV4OPEN_DENYREAD:
 2877                 stp->ls_flags |= NFSLCK_READDENY;
 2878                 break;
 2879         case NFSV4OPEN_DENYWRITE:
 2880                 stp->ls_flags |= NFSLCK_WRITEDENY;
 2881                 break;
 2882         case NFSV4OPEN_DENYBOTH:
 2883                 stp->ls_flags |= (NFSLCK_READDENY | NFSLCK_WRITEDENY);
 2884                 break;
 2885         default:
 2886                 nd->nd_repstat = NFSERR_INVAL;
 2887         }
 2888         clientid.lval[0] = *tl++;
 2889         clientid.lval[1] = *tl;
 2890         if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
 2891                 if ((nd->nd_flag & ND_NFSV41) != 0)
 2892                         clientid.qval = nd->nd_clientid.qval;
 2893                 else if (nd->nd_clientid.qval != clientid.qval)
 2894                         printf("EEK7 multiple clids\n");
 2895         } else {
 2896                 if ((nd->nd_flag & ND_NFSV41) != 0)
 2897                         printf("EEK! no clientid from session\n");
 2898                 nd->nd_flag |= ND_IMPLIEDCLID;
 2899                 nd->nd_clientid.qval = clientid.qval;
 2900         }
 2901         error = nfsrv_mtostr(nd, stp->ls_owner, stp->ls_ownerlen);
 2902         if (error)
 2903                 goto nfsmout;
 2904         NFSVNO_ATTRINIT(&nva);
 2905         NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 2906         create = fxdr_unsigned(int, *tl);
 2907         if (!nd->nd_repstat)
 2908                 nd->nd_repstat = nfsvno_getattr(dp, &dirfor, nd, p, 0, NULL);
 2909         if (create == NFSV4OPEN_CREATE) {
 2910                 nva.na_type = VREG;
 2911                 nva.na_mode = 0;
 2912                 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 2913                 how = fxdr_unsigned(int, *tl);
 2914                 switch (how) {
 2915                 case NFSCREATE_UNCHECKED:
 2916                 case NFSCREATE_GUARDED:
 2917                         error = nfsv4_sattr(nd, NULL, &nva, &attrbits, aclp, p);
 2918                         if (error)
 2919                                 goto nfsmout;
 2920                         /*
 2921                          * If the na_gid being set is the same as that of
 2922                          * the directory it is going in, clear it, since
 2923                          * that is what will be set by default. This allows
 2924                          * a user that isn't in that group to do the create.
 2925                          */
 2926                         if (!nd->nd_repstat && NFSVNO_ISSETGID(&nva) &&
 2927                             nva.na_gid == dirfor.na_gid)
 2928                                 NFSVNO_UNSET(&nva, gid);
 2929                         if (!nd->nd_repstat)
 2930                                 nd->nd_repstat = nfsrv_checkuidgid(nd, &nva);
 2931                         break;
 2932                 case NFSCREATE_EXCLUSIVE:
 2933                         NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF);
 2934                         cverf[0] = *tl++;
 2935                         cverf[1] = *tl;
 2936                         break;
 2937                 case NFSCREATE_EXCLUSIVE41:
 2938                         NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF);
 2939                         cverf[0] = *tl++;
 2940                         cverf[1] = *tl;
 2941                         error = nfsv4_sattr(nd, NULL, &nva, &attrbits, aclp, p);
 2942                         if (error != 0)
 2943                                 goto nfsmout;
 2944                         if (NFSISSET_ATTRBIT(&attrbits,
 2945                             NFSATTRBIT_TIMEACCESSSET))
 2946                                 nd->nd_repstat = NFSERR_INVAL;
 2947                         /*
 2948                          * If the na_gid being set is the same as that of
 2949                          * the directory it is going in, clear it, since
 2950                          * that is what will be set by default. This allows
 2951                          * a user that isn't in that group to do the create.
 2952                          */
 2953                         if (nd->nd_repstat == 0 && NFSVNO_ISSETGID(&nva) &&
 2954                             nva.na_gid == dirfor.na_gid)
 2955                                 NFSVNO_UNSET(&nva, gid);
 2956                         if (nd->nd_repstat == 0)
 2957                                 nd->nd_repstat = nfsrv_checkuidgid(nd, &nva);
 2958                         break;
 2959                 default:
 2960                         nd->nd_repstat = NFSERR_BADXDR;
 2961                         goto nfsmout;
 2962                 }
 2963         } else if (create != NFSV4OPEN_NOCREATE) {
 2964                 nd->nd_repstat = NFSERR_BADXDR;
 2965                 goto nfsmout;
 2966         }
 2967 
 2968         /*
 2969          * Now, handle the claim, which usually includes looking up a
 2970          * name in the directory referenced by dp. The exception is
 2971          * NFSV4OPEN_CLAIMPREVIOUS.
 2972          */
 2973         NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 2974         claim = fxdr_unsigned(int, *tl);
 2975         if (claim == NFSV4OPEN_CLAIMDELEGATECUR) {
 2976                 NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID);
 2977                 stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
 2978                 NFSBCOPY((caddr_t)tl,(caddr_t)stateid.other,NFSX_STATEIDOTHER);
 2979                 stp->ls_flags |= NFSLCK_DELEGCUR;
 2980         } else if (claim == NFSV4OPEN_CLAIMDELEGATEPREV) {
 2981                 stp->ls_flags |= NFSLCK_DELEGPREV;
 2982         }
 2983         if (claim == NFSV4OPEN_CLAIMNULL || claim == NFSV4OPEN_CLAIMDELEGATECUR
 2984             || claim == NFSV4OPEN_CLAIMDELEGATEPREV) {
 2985                 if (!nd->nd_repstat && create == NFSV4OPEN_CREATE &&
 2986                     claim != NFSV4OPEN_CLAIMNULL)
 2987                         nd->nd_repstat = NFSERR_INVAL;
 2988                 if (nd->nd_repstat) {
 2989                         nd->nd_repstat = nfsrv_opencheck(clientid,
 2990                             &stateid, stp, NULL, nd, p, nd->nd_repstat);
 2991                         goto nfsmout;
 2992                 }
 2993                 if (create == NFSV4OPEN_CREATE)
 2994                     NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE,
 2995                         LOCKPARENT | LOCKLEAF | SAVESTART | NOCACHE);
 2996                 else
 2997                     NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, LOOKUP,
 2998                         LOCKLEAF | SAVESTART);
 2999                 nfsvno_setpathbuf(&named, &bufp, &hashp);
 3000                 error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
 3001                 if (error) {
 3002                         vrele(dp);
 3003 #ifdef NFS4_ACL_EXTATTR_NAME
 3004                         acl_free(aclp);
 3005 #endif
 3006                         free(stp, M_NFSDSTATE);
 3007                         nfsvno_relpathbuf(&named);
 3008                         NFSEXITCODE2(error, nd);
 3009                         return (error);
 3010                 }
 3011                 if (!nd->nd_repstat) {
 3012                         nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp,
 3013                             p, &dirp);
 3014                 } else {
 3015                         vrele(dp);
 3016                         nfsvno_relpathbuf(&named);
 3017                 }
 3018                 if (create == NFSV4OPEN_CREATE) {
 3019                     switch (how) {
 3020                     case NFSCREATE_UNCHECKED:
 3021                         if (named.ni_vp) {
 3022                                 /*
 3023                                  * Clear the setable attribute bits, except
 3024                                  * for Size, if it is being truncated.
 3025                                  */
 3026                                 NFSZERO_ATTRBIT(&attrbits);
 3027                                 if (NFSVNO_ISSETSIZE(&nva))
 3028                                         NFSSETBIT_ATTRBIT(&attrbits,
 3029                                             NFSATTRBIT_SIZE);
 3030                         }
 3031                         break;
 3032                     case NFSCREATE_GUARDED:
 3033                         if (named.ni_vp && !nd->nd_repstat)
 3034                                 nd->nd_repstat = EEXIST;
 3035                         break;
 3036                     case NFSCREATE_EXCLUSIVE:
 3037                         exclusive_flag = 1;
 3038                         if (!named.ni_vp)
 3039                                 nva.na_mode = 0;
 3040                         break;
 3041                     case NFSCREATE_EXCLUSIVE41:
 3042                         exclusive_flag = 1;
 3043                         break;
 3044                     }
 3045                 }
 3046                 nfsvno_open(nd, &named, clientid, &stateid, stp,
 3047                     &exclusive_flag, &nva, cverf, create, aclp, &attrbits,
 3048                     nd->nd_cred, exp, &vp);
 3049         } else if (claim == NFSV4OPEN_CLAIMPREVIOUS || claim ==
 3050             NFSV4OPEN_CLAIMFH) {
 3051                 if (claim == NFSV4OPEN_CLAIMPREVIOUS) {
 3052                         NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 3053                         i = fxdr_unsigned(int, *tl);
 3054                         switch (i) {
 3055                         case NFSV4OPEN_DELEGATEREAD:
 3056                                 stp->ls_flags |= NFSLCK_DELEGREAD;
 3057                                 break;
 3058                         case NFSV4OPEN_DELEGATEWRITE:
 3059                                 stp->ls_flags |= NFSLCK_DELEGWRITE;
 3060                         case NFSV4OPEN_DELEGATENONE:
 3061                                 break;
 3062                         default:
 3063                                 nd->nd_repstat = NFSERR_BADXDR;
 3064                                 goto nfsmout;
 3065                         }
 3066                         stp->ls_flags |= NFSLCK_RECLAIM;
 3067                 } else {
 3068                         /* CLAIM_NULL_FH */
 3069                         if (nd->nd_repstat == 0 && create == NFSV4OPEN_CREATE)
 3070                                 nd->nd_repstat = NFSERR_INVAL;
 3071                 }
 3072                 vp = dp;
 3073                 NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
 3074                 if (!VN_IS_DOOMED(vp))
 3075                         nd->nd_repstat = nfsrv_opencheck(clientid, &stateid,
 3076                             stp, vp, nd, p, nd->nd_repstat);
 3077                 else
 3078                         nd->nd_repstat = NFSERR_PERM;
 3079         } else {
 3080                 nd->nd_repstat = NFSERR_BADXDR;
 3081                 goto nfsmout;
 3082         }
 3083 
 3084         /*
 3085          * Do basic access checking.
 3086          */
 3087         if (!nd->nd_repstat && vnode_vtype(vp) != VREG) {
 3088                 /*
 3089                  * The IETF working group decided that this is the correct
 3090                  * error return for all non-regular files.
 3091                  */
 3092                 nd->nd_repstat = (vp->v_type == VDIR) ? NFSERR_ISDIR : NFSERR_SYMLINK;
 3093         }
 3094 
 3095         /*
 3096          * If the Open is being done for a file that already exists, apply
 3097          * normal permission checking including for the file owner, if
 3098          * vfs.nfsd.v4openaccess is set.
 3099          * Previously, the owner was always allowed to open the file to
 3100          * be consistent with the NFS tradition of always allowing the
 3101          * owner of the file to write to the file regardless of permissions.
 3102          * It now appears that the Linux client expects the owner
 3103          * permissions to be checked for opens that are not creating the
 3104          * file.  I believe the correct approach is to use the Access
 3105          * operation's results to be consistent with NFSv3, but that is
 3106          * not what the current Linux client appears to be doing.
 3107          * Since both the Linux and OpenSolaris NFSv4 servers do this check,
 3108          * I have enabled it by default.
 3109          * If this semantic change causes a problem, it can be disabled by
 3110          * setting the sysctl vfs.nfsd.v4openaccess to 0 to re-enable the
 3111          * previous semantics.
 3112          */
 3113         if (nfsrv_openaccess && create == NFSV4OPEN_NOCREATE)
 3114                 override = NFSACCCHK_NOOVERRIDE;
 3115         else
 3116                 override = NFSACCCHK_ALLOWOWNER;
 3117         if (!nd->nd_repstat && (stp->ls_flags & NFSLCK_WRITEACCESS))
 3118             nd->nd_repstat = nfsvno_accchk(vp, VWRITE, nd->nd_cred,
 3119                 exp, p, override, NFSACCCHK_VPISLOCKED, NULL);
 3120         if (!nd->nd_repstat && (stp->ls_flags & NFSLCK_READACCESS)) {
 3121             nd->nd_repstat = nfsvno_accchk(vp, VREAD, nd->nd_cred,
 3122                 exp, p, override, NFSACCCHK_VPISLOCKED, NULL);
 3123             if (nd->nd_repstat)
 3124                 nd->nd_repstat = nfsvno_accchk(vp, VEXEC,
 3125                     nd->nd_cred, exp, p, override,
 3126                     NFSACCCHK_VPISLOCKED, NULL);
 3127         }
 3128 
 3129         if (!nd->nd_repstat) {
 3130                 nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1, NULL);
 3131                 if (!nd->nd_repstat) {
 3132                         tverf[0] = nva.na_atime.tv_sec;
 3133                         tverf[1] = nva.na_atime.tv_nsec;
 3134                 }
 3135         }
 3136         if (!nd->nd_repstat && exclusive_flag && (cverf[0] != tverf[0] ||
 3137             cverf[1] != tverf[1]))
 3138                 nd->nd_repstat = EEXIST;
 3139         /*
 3140          * Do the open locking/delegation stuff.
 3141          */
 3142         if (!nd->nd_repstat)
 3143             nd->nd_repstat = nfsrv_openctrl(nd, vp, &stp, clientid, &stateid,
 3144                 &delegstateid, &rflags, exp, p, nva.na_filerev);
 3145 
 3146         /*
 3147          * vp must be unlocked before the call to nfsvno_getattr(dirp,...)
 3148          * below, to avoid a deadlock with the lookup in nfsvno_namei() above.
 3149          * (ie: Leave the NFSVOPUNLOCK() about here.)
 3150          */
 3151         if (vp)
 3152                 NFSVOPUNLOCK(vp);
 3153         if (stp)
 3154                 free(stp, M_NFSDSTATE);
 3155         if (!nd->nd_repstat && dirp)
 3156                 nd->nd_repstat = nfsvno_getattr(dirp, &diraft, nd, p, 0, NULL);
 3157         if (!nd->nd_repstat) {
 3158                 /* For NFSv4.1, set the Current StateID. */
 3159                 if ((nd->nd_flag & ND_NFSV41) != 0) {
 3160                         nd->nd_curstateid = stateid;
 3161                         nd->nd_flag |= ND_CURSTATEID;
 3162                 }
 3163                 NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID + 6 * NFSX_UNSIGNED);
 3164                 *tl++ = txdr_unsigned(stateid.seqid);
 3165                 NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER);
 3166                 tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
 3167                 if (claim == NFSV4OPEN_CLAIMPREVIOUS) {
 3168                         *tl++ = newnfs_true;
 3169                         *tl++ = 0;
 3170                         *tl++ = 0;
 3171                         *tl++ = 0;
 3172                         *tl++ = 0;
 3173                 } else {
 3174                         *tl++ = newnfs_false;   /* Since dirp is not locked */
 3175                         txdr_hyper(dirfor.na_filerev, tl);
 3176                         tl += 2;
 3177                         txdr_hyper(diraft.na_filerev, tl);
 3178                         tl += 2;
 3179                 }
 3180                 *tl = txdr_unsigned(rflags & NFSV4OPEN_RFLAGS);
 3181                 (void) nfsrv_putattrbit(nd, &attrbits);
 3182                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 3183                 if (rflags & NFSV4OPEN_READDELEGATE)
 3184                         *tl = txdr_unsigned(NFSV4OPEN_DELEGATEREAD);
 3185                 else if (rflags & NFSV4OPEN_WRITEDELEGATE)
 3186                         *tl = txdr_unsigned(NFSV4OPEN_DELEGATEWRITE);
 3187                 else if (retext != 0) {
 3188                         *tl = txdr_unsigned(NFSV4OPEN_DELEGATENONEEXT);
 3189                         if ((rflags & NFSV4OPEN_WDNOTWANTED) != 0) {
 3190                                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 3191                                 *tl = txdr_unsigned(NFSV4OPEN_NOTWANTED);
 3192                         } else if ((rflags & NFSV4OPEN_WDSUPPFTYPE) != 0) {
 3193                                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 3194                                 *tl = txdr_unsigned(NFSV4OPEN_NOTSUPPFTYPE);
 3195                         } else if ((rflags & NFSV4OPEN_WDCONTENTION) != 0) {
 3196                                 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 3197                                 *tl++ = txdr_unsigned(NFSV4OPEN_CONTENTION);
 3198                                 *tl = newnfs_false;
 3199                         } else if ((rflags & NFSV4OPEN_WDRESOURCE) != 0) {
 3200                                 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 3201                                 *tl++ = txdr_unsigned(NFSV4OPEN_RESOURCE);
 3202                                 *tl = newnfs_false;
 3203                         } else {
 3204                                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 3205                                 *tl = txdr_unsigned(NFSV4OPEN_NOTWANTED);
 3206                         }
 3207                 } else
 3208                         *tl = txdr_unsigned(NFSV4OPEN_DELEGATENONE);
 3209                 if (rflags & (NFSV4OPEN_READDELEGATE|NFSV4OPEN_WRITEDELEGATE)) {
 3210                         NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID+NFSX_UNSIGNED);
 3211                         *tl++ = txdr_unsigned(delegstateid.seqid);
 3212                         NFSBCOPY((caddr_t)delegstateid.other, (caddr_t)tl,
 3213                             NFSX_STATEIDOTHER);
 3214                         tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
 3215                         if (rflags & NFSV4OPEN_RECALL)
 3216                                 *tl = newnfs_true;
 3217                         else
 3218                                 *tl = newnfs_false;
 3219                         if (rflags & NFSV4OPEN_WRITEDELEGATE) {
 3220                                 NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
 3221                                 *tl++ = txdr_unsigned(NFSV4OPEN_LIMITSIZE);
 3222                                 txdr_hyper(nva.na_size, tl);
 3223                         }
 3224                         NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
 3225                         *tl++ = txdr_unsigned(NFSV4ACE_ALLOWEDTYPE);
 3226                         *tl++ = txdr_unsigned(0x0);
 3227                         acemask = NFSV4ACE_ALLFILESMASK;
 3228                         if (nva.na_mode & S_IRUSR)
 3229                             acemask |= NFSV4ACE_READMASK;
 3230                         if (nva.na_mode & S_IWUSR)
 3231                             acemask |= NFSV4ACE_WRITEMASK;
 3232                         if (nva.na_mode & S_IXUSR)
 3233                             acemask |= NFSV4ACE_EXECUTEMASK;
 3234                         *tl = txdr_unsigned(acemask);
 3235                         (void) nfsm_strtom(nd, "OWNER@", 6);
 3236                 }
 3237                 *vpp = vp;
 3238         } else if (vp) {
 3239                 vrele(vp);
 3240         }
 3241         if (dirp)
 3242                 vrele(dirp);
 3243 #ifdef NFS4_ACL_EXTATTR_NAME
 3244         acl_free(aclp);
 3245 #endif
 3246         NFSEXITCODE2(0, nd);
 3247         return (0);
 3248 nfsmout:
 3249         vrele(dp);
 3250 #ifdef NFS4_ACL_EXTATTR_NAME
 3251         acl_free(aclp);
 3252 #endif
 3253         if (stp)
 3254                 free(stp, M_NFSDSTATE);
 3255         NFSEXITCODE2(error, nd);
 3256         return (error);
 3257 }
 3258 
 3259 /*
 3260  * nfsv4 close service
 3261  */
 3262 int
 3263 nfsrvd_close(struct nfsrv_descript *nd, __unused int isdgram,
 3264     vnode_t vp, __unused struct nfsexstuff *exp)
 3265 {
 3266         u_int32_t *tl;
 3267         struct nfsstate st, *stp = &st;
 3268         int error = 0, writeacc;
 3269         nfsv4stateid_t stateid;
 3270         nfsquad_t clientid;
 3271         struct nfsvattr na;
 3272         struct thread *p = curthread;
 3273 
 3274         NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_STATEID);
 3275         stp->ls_seq = fxdr_unsigned(u_int32_t, *tl++);
 3276         stp->ls_ownerlen = 0;
 3277         stp->ls_op = nd->nd_rp;
 3278         stp->ls_uid = nd->nd_cred->cr_uid;
 3279         stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
 3280         NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other,
 3281             NFSX_STATEIDOTHER);
 3282 
 3283         /*
 3284          * For the special stateid of other all 0s and seqid == 1, set the
 3285          * stateid to the current stateid, if it is set.
 3286          */
 3287         if ((nd->nd_flag & ND_NFSV41) != 0 && stp->ls_stateid.seqid == 1 &&
 3288             stp->ls_stateid.other[0] == 0 && stp->ls_stateid.other[1] == 0 &&
 3289             stp->ls_stateid.other[2] == 0) {
 3290                 if ((nd->nd_flag & ND_CURSTATEID) != 0)
 3291                         stp->ls_stateid = nd->nd_curstateid;
 3292                 else {
 3293                         nd->nd_repstat = NFSERR_BADSTATEID;
 3294                         goto nfsmout;
 3295                 }
 3296         }
 3297 
 3298         stp->ls_flags = NFSLCK_CLOSE;
 3299         clientid.lval[0] = stp->ls_stateid.other[0];
 3300         clientid.lval[1] = stp->ls_stateid.other[1];
 3301         if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
 3302                 if ((nd->nd_flag & ND_NFSV41) != 0)
 3303                         clientid.qval = nd->nd_clientid.qval;
 3304                 else if (nd->nd_clientid.qval != clientid.qval)
 3305                         printf("EEK8 multiple clids\n");
 3306         } else {
 3307                 if ((nd->nd_flag & ND_NFSV41) != 0)
 3308                         printf("EEK! no clientid from session\n");
 3309                 nd->nd_flag |= ND_IMPLIEDCLID;
 3310                 nd->nd_clientid.qval = clientid.qval;
 3311         }
 3312         nd->nd_repstat = nfsrv_openupdate(vp, stp, clientid, &stateid, nd, p,
 3313             &writeacc);
 3314         /* For pNFS, update the attributes. */
 3315         if (writeacc != 0 || nfsrv_pnfsatime != 0)
 3316                 nfsrv_updatemdsattr(vp, &na, p);
 3317         vput(vp);
 3318         if (!nd->nd_repstat) {
 3319                 /*
 3320                  * If the stateid that has been closed is the current stateid,
 3321                  * unset it.
 3322                  */
 3323                 if ((nd->nd_flag & ND_CURSTATEID) != 0 &&
 3324                     stateid.other[0] == nd->nd_curstateid.other[0] &&
 3325                     stateid.other[1] == nd->nd_curstateid.other[1] &&
 3326                     stateid.other[2] == nd->nd_curstateid.other[2])
 3327                         nd->nd_flag &= ~ND_CURSTATEID;
 3328                 NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID);
 3329                 *tl++ = txdr_unsigned(stateid.seqid);
 3330                 NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER);
 3331         }
 3332         NFSEXITCODE2(0, nd);
 3333         return (0);
 3334 nfsmout:
 3335         vput(vp);
 3336         NFSEXITCODE2(error, nd);
 3337         return (error);
 3338 }
 3339 
 3340 /*
 3341  * nfsv4 delegpurge service
 3342  */
 3343 int
 3344 nfsrvd_delegpurge(struct nfsrv_descript *nd, __unused int isdgram,
 3345     __unused vnode_t vp, __unused struct nfsexstuff *exp)
 3346 {
 3347         u_int32_t *tl;
 3348         int error = 0;
 3349         nfsquad_t clientid;
 3350         struct thread *p = curthread;
 3351 
 3352         if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
 3353                 nd->nd_repstat = NFSERR_WRONGSEC;
 3354                 goto nfsmout;
 3355         }
 3356         NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 3357         clientid.lval[0] = *tl++;
 3358         clientid.lval[1] = *tl;
 3359         if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
 3360                 if ((nd->nd_flag & ND_NFSV41) != 0)
 3361                         clientid.qval = nd->nd_clientid.qval;
 3362                 else if (nd->nd_clientid.qval != clientid.qval)
 3363                         printf("EEK9 multiple clids\n");
 3364         } else {
 3365                 if ((nd->nd_flag & ND_NFSV41) != 0)
 3366                         printf("EEK! no clientid from session\n");
 3367                 nd->nd_flag |= ND_IMPLIEDCLID;
 3368                 nd->nd_clientid.qval = clientid.qval;
 3369         }
 3370         nd->nd_repstat = nfsrv_delegupdate(nd, clientid, NULL, NULL,
 3371             NFSV4OP_DELEGPURGE, nd->nd_cred, p, NULL);
 3372 nfsmout:
 3373         NFSEXITCODE2(error, nd);
 3374         return (error);
 3375 }
 3376 
 3377 /*
 3378  * nfsv4 delegreturn service
 3379  */
 3380 int
 3381 nfsrvd_delegreturn(struct nfsrv_descript *nd, __unused int isdgram,
 3382     vnode_t vp, __unused struct nfsexstuff *exp)
 3383 {
 3384         u_int32_t *tl;
 3385         int error = 0, writeacc;
 3386         nfsv4stateid_t stateid;
 3387         nfsquad_t clientid;
 3388         struct nfsvattr na;
 3389         struct thread *p = curthread;
 3390 
 3391         NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID);
 3392         stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
 3393         NFSBCOPY((caddr_t)tl, (caddr_t)stateid.other, NFSX_STATEIDOTHER);
 3394         clientid.lval[0] = stateid.other[0];
 3395         clientid.lval[1] = stateid.other[1];
 3396         if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
 3397                 if ((nd->nd_flag & ND_NFSV41) != 0)
 3398                         clientid.qval = nd->nd_clientid.qval;
 3399                 else if (nd->nd_clientid.qval != clientid.qval)
 3400                         printf("EEK10 multiple clids\n");
 3401         } else {
 3402                 if ((nd->nd_flag & ND_NFSV41) != 0)
 3403                         printf("EEK! no clientid from session\n");
 3404                 nd->nd_flag |= ND_IMPLIEDCLID;
 3405                 nd->nd_clientid.qval = clientid.qval;
 3406         }
 3407         nd->nd_repstat = nfsrv_delegupdate(nd, clientid, &stateid, vp,
 3408             NFSV4OP_DELEGRETURN, nd->nd_cred, p, &writeacc);
 3409         /* For pNFS, update the attributes. */
 3410         if (writeacc != 0 || nfsrv_pnfsatime != 0)
 3411                 nfsrv_updatemdsattr(vp, &na, p);
 3412 nfsmout:
 3413         vput(vp);
 3414         NFSEXITCODE2(error, nd);
 3415         return (error);
 3416 }
 3417 
 3418 /*
 3419  * nfsv4 get file handle service
 3420  */
 3421 int
 3422 nfsrvd_getfh(struct nfsrv_descript *nd, __unused int isdgram,
 3423     vnode_t vp, __unused struct nfsexstuff *exp)
 3424 {
 3425         fhandle_t fh;
 3426         struct thread *p = curthread;
 3427 
 3428         nd->nd_repstat = nfsvno_getfh(vp, &fh, p);
 3429         vput(vp);
 3430         if (!nd->nd_repstat)
 3431                 (void) nfsm_fhtom(nd, (u_int8_t *)&fh, 0, 0);
 3432         NFSEXITCODE2(0, nd);
 3433         return (0);
 3434 }
 3435 
 3436 /*
 3437  * nfsv4 open confirm service
 3438  */
 3439 int
 3440 nfsrvd_openconfirm(struct nfsrv_descript *nd, __unused int isdgram,
 3441     vnode_t vp, __unused struct nfsexstuff *exp)
 3442 {
 3443         u_int32_t *tl;
 3444         struct nfsstate st, *stp = &st;
 3445         int error = 0;
 3446         nfsv4stateid_t stateid;
 3447         nfsquad_t clientid;
 3448         struct thread *p = curthread;
 3449 
 3450         if ((nd->nd_flag & ND_NFSV41) != 0) {
 3451                 nd->nd_repstat = NFSERR_NOTSUPP;
 3452                 goto nfsmout;
 3453         }
 3454         NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + NFSX_UNSIGNED);
 3455         stp->ls_ownerlen = 0;
 3456         stp->ls_op = nd->nd_rp;
 3457         stp->ls_uid = nd->nd_cred->cr_uid;
 3458         stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
 3459         NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other,
 3460             NFSX_STATEIDOTHER);
 3461         tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
 3462         stp->ls_seq = fxdr_unsigned(u_int32_t, *tl);
 3463         stp->ls_flags = NFSLCK_CONFIRM;
 3464         clientid.lval[0] = stp->ls_stateid.other[0];
 3465         clientid.lval[1] = stp->ls_stateid.other[1];
 3466         if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
 3467                 if ((nd->nd_flag & ND_NFSV41) != 0)
 3468                         clientid.qval = nd->nd_clientid.qval;
 3469                 else if (nd->nd_clientid.qval != clientid.qval)
 3470                         printf("EEK11 multiple clids\n");
 3471         } else {
 3472                 if ((nd->nd_flag & ND_NFSV41) != 0)
 3473                         printf("EEK! no clientid from session\n");
 3474                 nd->nd_flag |= ND_IMPLIEDCLID;
 3475                 nd->nd_clientid.qval = clientid.qval;
 3476         }
 3477         nd->nd_repstat = nfsrv_openupdate(vp, stp, clientid, &stateid, nd, p,
 3478             NULL);
 3479         if (!nd->nd_repstat) {
 3480                 NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID);
 3481                 *tl++ = txdr_unsigned(stateid.seqid);
 3482                 NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER);
 3483         }
 3484 nfsmout:
 3485         vput(vp);
 3486         NFSEXITCODE2(error, nd);
 3487         return (error);
 3488 }
 3489 
 3490 /*
 3491  * nfsv4 open downgrade service
 3492  */
 3493 int
 3494 nfsrvd_opendowngrade(struct nfsrv_descript *nd, __unused int isdgram,
 3495     vnode_t vp, __unused struct nfsexstuff *exp)
 3496 {
 3497         u_int32_t *tl;
 3498         int i;
 3499         struct nfsstate st, *stp = &st;
 3500         int error = 0;
 3501         nfsv4stateid_t stateid;
 3502         nfsquad_t clientid;
 3503         struct thread *p = curthread;
 3504 
 3505         /* opendowngrade can only work on a file object.*/
 3506         if (vp->v_type != VREG) {
 3507                 error = NFSERR_INVAL;
 3508                 goto nfsmout;
 3509         }
 3510         NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + 3 * NFSX_UNSIGNED);
 3511         stp->ls_ownerlen = 0;
 3512         stp->ls_op = nd->nd_rp;
 3513         stp->ls_uid = nd->nd_cred->cr_uid;
 3514         stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
 3515         NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other,
 3516             NFSX_STATEIDOTHER);
 3517         tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
 3518 
 3519         /*
 3520          * For the special stateid of other all 0s and seqid == 1, set the
 3521          * stateid to the current stateid, if it is set.
 3522          */
 3523         if ((nd->nd_flag & ND_NFSV41) != 0 && stp->ls_stateid.seqid == 1 &&
 3524             stp->ls_stateid.other[0] == 0 && stp->ls_stateid.other[1] == 0 &&
 3525             stp->ls_stateid.other[2] == 0) {
 3526                 if ((nd->nd_flag & ND_CURSTATEID) != 0)
 3527                         stp->ls_stateid = nd->nd_curstateid;
 3528                 else {
 3529                         nd->nd_repstat = NFSERR_BADSTATEID;
 3530                         goto nfsmout;
 3531                 }
 3532         }
 3533 
 3534         stp->ls_seq = fxdr_unsigned(u_int32_t, *tl++);
 3535         i = fxdr_unsigned(int, *tl++);
 3536         if ((nd->nd_flag & ND_NFSV41) != 0)
 3537                 i &= ~NFSV4OPEN_WANTDELEGMASK;
 3538         switch (i) {
 3539         case NFSV4OPEN_ACCESSREAD:
 3540                 stp->ls_flags = (NFSLCK_READACCESS | NFSLCK_DOWNGRADE);
 3541                 break;
 3542         case NFSV4OPEN_ACCESSWRITE:
 3543                 stp->ls_flags = (NFSLCK_WRITEACCESS | NFSLCK_DOWNGRADE);
 3544                 break;
 3545         case NFSV4OPEN_ACCESSBOTH:
 3546                 stp->ls_flags = (NFSLCK_READACCESS | NFSLCK_WRITEACCESS |
 3547                     NFSLCK_DOWNGRADE);
 3548                 break;
 3549         default:
 3550                 nd->nd_repstat = NFSERR_INVAL;
 3551         }
 3552         i = fxdr_unsigned(int, *tl);
 3553         switch (i) {
 3554         case NFSV4OPEN_DENYNONE:
 3555                 break;
 3556         case NFSV4OPEN_DENYREAD:
 3557                 stp->ls_flags |= NFSLCK_READDENY;
 3558                 break;
 3559         case NFSV4OPEN_DENYWRITE:
 3560                 stp->ls_flags |= NFSLCK_WRITEDENY;
 3561                 break;
 3562         case NFSV4OPEN_DENYBOTH:
 3563                 stp->ls_flags |= (NFSLCK_READDENY | NFSLCK_WRITEDENY);
 3564                 break;
 3565         default:
 3566                 nd->nd_repstat = NFSERR_INVAL;
 3567         }
 3568 
 3569         clientid.lval[0] = stp->ls_stateid.other[0];
 3570         clientid.lval[1] = stp->ls_stateid.other[1];
 3571         if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
 3572                 if ((nd->nd_flag & ND_NFSV41) != 0)
 3573                         clientid.qval = nd->nd_clientid.qval;
 3574                 else if (nd->nd_clientid.qval != clientid.qval)
 3575                         printf("EEK12 multiple clids\n");
 3576         } else {
 3577                 if ((nd->nd_flag & ND_NFSV41) != 0)
 3578                         printf("EEK! no clientid from session\n");
 3579                 nd->nd_flag |= ND_IMPLIEDCLID;
 3580                 nd->nd_clientid.qval = clientid.qval;
 3581         }
 3582         if (!nd->nd_repstat)
 3583                 nd->nd_repstat = nfsrv_openupdate(vp, stp, clientid, &stateid,
 3584                     nd, p, NULL);
 3585         if (!nd->nd_repstat) {
 3586                 /* For NFSv4.1, set the Current StateID. */
 3587                 if ((nd->nd_flag & ND_NFSV41) != 0) {
 3588                         nd->nd_curstateid = stateid;
 3589                         nd->nd_flag |= ND_CURSTATEID;
 3590                 }
 3591                 NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID);
 3592                 *tl++ = txdr_unsigned(stateid.seqid);
 3593                 NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER);
 3594         }
 3595 nfsmout:
 3596         vput(vp);
 3597         NFSEXITCODE2(error, nd);
 3598         return (error);
 3599 }
 3600 
 3601 /*
 3602  * nfsv4 renew lease service
 3603  */
 3604 int
 3605 nfsrvd_renew(struct nfsrv_descript *nd, __unused int isdgram,
 3606     __unused vnode_t vp, __unused struct nfsexstuff *exp)
 3607 {
 3608         u_int32_t *tl;
 3609         int error = 0;
 3610         nfsquad_t clientid;
 3611         struct thread *p = curthread;
 3612 
 3613         if ((nd->nd_flag & ND_NFSV41) != 0) {
 3614                 nd->nd_repstat = NFSERR_NOTSUPP;
 3615                 goto nfsmout;
 3616         }
 3617         if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
 3618                 nd->nd_repstat = NFSERR_WRONGSEC;
 3619                 goto nfsmout;
 3620         }
 3621         NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
 3622         clientid.lval[0] = *tl++;
 3623         clientid.lval[1] = *tl;
 3624         if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
 3625                 if ((nd->nd_flag & ND_NFSV41) != 0)
 3626                         clientid.qval = nd->nd_clientid.qval;
 3627                 else if (nd->nd_clientid.qval != clientid.qval)
 3628                         printf("EEK13 multiple clids\n");
 3629         } else {
 3630                 if ((nd->nd_flag & ND_NFSV41) != 0)
 3631                         printf("EEK! no clientid from session\n");
 3632                 nd->nd_flag |= ND_IMPLIEDCLID;
 3633                 nd->nd_clientid.qval = clientid.qval;
 3634         }
 3635         nd->nd_repstat = nfsrv_getclient(clientid, (CLOPS_RENEWOP|CLOPS_RENEW),
 3636             NULL, NULL, (nfsquad_t)((u_quad_t)0), 0, nd, p);
 3637 nfsmout:
 3638         NFSEXITCODE2(error, nd);
 3639         return (error);
 3640 }
 3641 
 3642 /*
 3643  * nfsv4 security info service
 3644  */
 3645 int
 3646 nfsrvd_secinfo(struct nfsrv_descript *nd, int isdgram,
 3647     vnode_t dp, struct nfsexstuff *exp)
 3648 {
 3649         u_int32_t *tl;
 3650         int len;
 3651         struct nameidata named;
 3652         vnode_t dirp = NULL, vp;
 3653         struct nfsrvfh fh;
 3654         struct nfsexstuff retnes;
 3655         u_int32_t *sizp;
 3656         int error = 0, savflag, i;
 3657         char *bufp;
 3658         u_long *hashp;
 3659         struct thread *p = curthread;
 3660 
 3661         /*
 3662          * All this just to get the export flags for the name.
 3663          */
 3664         NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, LOOKUP,
 3665             LOCKLEAF | SAVESTART);
 3666         nfsvno_setpathbuf(&named, &bufp, &hashp);
 3667         error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
 3668         if (error) {
 3669                 vput(dp);
 3670                 nfsvno_relpathbuf(&named);
 3671                 goto out;
 3672         }
 3673         if (!nd->nd_repstat) {
 3674                 nd->nd_repstat = nfsvno_namei(nd, &named, dp, 1, exp, p, &dirp);
 3675         } else {
 3676                 vput(dp);
 3677                 nfsvno_relpathbuf(&named);
 3678         }
 3679         if (dirp)
 3680                 vrele(dirp);
 3681         if (nd->nd_repstat)
 3682                 goto out;
 3683         vrele(named.ni_startdir);
 3684         nfsvno_relpathbuf(&named);
 3685         fh.nfsrvfh_len = NFSX_MYFH;
 3686         vp = named.ni_vp;
 3687         nd->nd_repstat = nfsvno_getfh(vp, (fhandle_t *)fh.nfsrvfh_data, p);
 3688         vput(vp);
 3689         savflag = nd->nd_flag;
 3690         if (!nd->nd_repstat) {
 3691                 nfsd_fhtovp(nd, &fh, LK_SHARED, &vp, &retnes, NULL, 0);
 3692                 if (vp)
 3693                         vput(vp);
 3694         }
 3695         nd->nd_flag = savflag;
 3696         if (nd->nd_repstat)
 3697                 goto out;
 3698 
 3699         /*
 3700          * Finally have the export flags for name, so we can create
 3701          * the security info.
 3702          */
 3703         len = 0;
 3704         NFSM_BUILD(sizp, u_int32_t *, NFSX_UNSIGNED);
 3705         for (i = 0; i < retnes.nes_numsecflavor; i++) {
 3706                 if (retnes.nes_secflavors[i] == AUTH_SYS) {
 3707                         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 3708                         *tl = txdr_unsigned(RPCAUTH_UNIX);
 3709                         len++;
 3710                 } else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5) {
 3711                         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 3712                         *tl++ = txdr_unsigned(RPCAUTH_GSS);
 3713                         (void) nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str,
 3714                             nfsgss_mechlist[KERBV_MECH].len);
 3715                         NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 3716                         *tl++ = txdr_unsigned(GSS_KERBV_QOP);
 3717                         *tl = txdr_unsigned(RPCAUTHGSS_SVCNONE);
 3718                         len++;
 3719                 } else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5I) {
 3720                         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 3721                         *tl++ = txdr_unsigned(RPCAUTH_GSS);
 3722                         (void) nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str,
 3723                             nfsgss_mechlist[KERBV_MECH].len);
 3724                         NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 3725                         *tl++ = txdr_unsigned(GSS_KERBV_QOP);
 3726                         *tl = txdr_unsigned(RPCAUTHGSS_SVCINTEGRITY);
 3727                         len++;
 3728                 } else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5P) {
 3729                         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 3730                         *tl++ = txdr_unsigned(RPCAUTH_GSS);
 3731                         (void) nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str,
 3732                             nfsgss_mechlist[KERBV_MECH].len);
 3733                         NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 3734                         *tl++ = txdr_unsigned(GSS_KERBV_QOP);
 3735                         *tl = txdr_unsigned(RPCAUTHGSS_SVCPRIVACY);
 3736                         len++;
 3737                 }
 3738         }
 3739         *sizp = txdr_unsigned(len);
 3740 
 3741 out:
 3742         NFSEXITCODE2(error, nd);
 3743         return (error);
 3744 }
 3745 
 3746 /*
 3747  * nfsv4 set client id service
 3748  */
 3749 int
 3750 nfsrvd_setclientid(struct nfsrv_descript *nd, __unused int isdgram,
 3751     __unused vnode_t vp, __unused struct nfsexstuff *exp)
 3752 {
 3753         u_int32_t *tl;
 3754         int i;
 3755         int error = 0, idlen;
 3756         struct nfsclient *clp = NULL;
 3757 #ifdef INET
 3758         struct sockaddr_in *rin;
 3759 #endif
 3760 #ifdef INET6
 3761         struct sockaddr_in6 *rin6;
 3762 #endif
 3763 #if defined(INET) || defined(INET6)
 3764         u_char *ucp, *ucp2;
 3765 #endif
 3766         u_char *verf, *addrbuf;
 3767         nfsquad_t clientid, confirm;
 3768         struct thread *p = curthread;
 3769 
 3770         if ((nd->nd_flag & ND_NFSV41) != 0) {
 3771                 nd->nd_repstat = NFSERR_NOTSUPP;
 3772                 goto nfsmout;
 3773         }
 3774         if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
 3775                 nd->nd_repstat = NFSERR_WRONGSEC;
 3776                 goto out;
 3777         }
 3778         NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF + NFSX_UNSIGNED);
 3779         verf = (u_char *)tl;
 3780         tl += (NFSX_VERF / NFSX_UNSIGNED);
 3781         i = fxdr_unsigned(int, *tl);
 3782         if (i > NFSV4_OPAQUELIMIT || i <= 0) {
 3783                 nd->nd_repstat = NFSERR_BADXDR;
 3784                 goto nfsmout;
 3785         }
 3786         idlen = i;
 3787         if (nd->nd_flag & ND_GSS)
 3788                 i += nd->nd_princlen;
 3789         clp = malloc(sizeof(struct nfsclient) + i, M_NFSDCLIENT, M_WAITOK |
 3790             M_ZERO);
 3791         clp->lc_stateid = malloc(sizeof(struct nfsstatehead) *
 3792             nfsrv_statehashsize, M_NFSDCLIENT, M_WAITOK);
 3793         NFSINITSOCKMUTEX(&clp->lc_req.nr_mtx);
 3794         /* Allocated large enough for an AF_INET or AF_INET6 socket. */
 3795         clp->lc_req.nr_nam = malloc(sizeof(struct sockaddr_in6), M_SONAME,
 3796             M_WAITOK | M_ZERO);
 3797         clp->lc_req.nr_cred = NULL;
 3798         NFSBCOPY(verf, clp->lc_verf, NFSX_VERF);
 3799         clp->lc_idlen = idlen;
 3800         error = nfsrv_mtostr(nd, clp->lc_id, idlen);
 3801         if (error)
 3802                 goto nfsmout;
 3803         if (nd->nd_flag & ND_GSS) {
 3804                 clp->lc_flags = LCL_GSS;
 3805                 if (nd->nd_flag & ND_GSSINTEGRITY)
 3806                         clp->lc_flags |= LCL_GSSINTEGRITY;
 3807                 else if (nd->nd_flag & ND_GSSPRIVACY)
 3808                         clp->lc_flags |= LCL_GSSPRIVACY;
 3809         } else {
 3810                 clp->lc_flags = 0;
 3811         }
 3812         if ((nd->nd_flag & ND_GSS) && nd->nd_princlen > 0) {
 3813                 clp->lc_flags |= LCL_NAME;
 3814                 clp->lc_namelen = nd->nd_princlen;
 3815                 clp->lc_name = &clp->lc_id[idlen];
 3816                 NFSBCOPY(nd->nd_principal, clp->lc_name, clp->lc_namelen);
 3817         } else {
 3818                 clp->lc_uid = nd->nd_cred->cr_uid;
 3819                 clp->lc_gid = nd->nd_cred->cr_gid;
 3820         }
 3821 
 3822         /* If the client is using TLS, do so for the callback connection. */
 3823         if (nd->nd_flag & ND_TLS)
 3824                 clp->lc_flags |= LCL_TLSCB;
 3825 
 3826         NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 3827         clp->lc_program = fxdr_unsigned(u_int32_t, *tl);
 3828         error = nfsrv_getclientipaddr(nd, clp);
 3829         if (error)
 3830                 goto nfsmout;
 3831         NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 3832         clp->lc_callback = fxdr_unsigned(u_int32_t, *tl);
 3833 
 3834         /*
 3835          * nfsrv_setclient() does the actual work of adding it to the
 3836          * client list. If there is no error, the structure has been
 3837          * linked into the client list and clp should no longer be used
 3838          * here. When an error is returned, it has not been linked in,
 3839          * so it should be free'd.
 3840          */
 3841         nd->nd_repstat = nfsrv_setclient(nd, &clp, &clientid, &confirm, p);
 3842         if (nd->nd_repstat == NFSERR_CLIDINUSE) {
 3843                 /*
 3844                  * 8 is the maximum length of the port# string.
 3845                  */
 3846                 addrbuf = malloc(INET6_ADDRSTRLEN + 8, M_TEMP, M_WAITOK);
 3847                 switch (clp->lc_req.nr_nam->sa_family) {
 3848 #ifdef INET
 3849                 case AF_INET:
 3850                         if (clp->lc_flags & LCL_TCPCALLBACK)
 3851                                 (void) nfsm_strtom(nd, "tcp", 3);
 3852                         else 
 3853                                 (void) nfsm_strtom(nd, "udp", 3);
 3854                         rin = (struct sockaddr_in *)clp->lc_req.nr_nam;
 3855                         ucp = (u_char *)&rin->sin_addr.s_addr;
 3856                         ucp2 = (u_char *)&rin->sin_port;
 3857                         sprintf(addrbuf, "%d.%d.%d.%d.%d.%d", ucp[0] & 0xff,
 3858                             ucp[1] & 0xff, ucp[2] & 0xff, ucp[3] & 0xff,
 3859                             ucp2[0] & 0xff, ucp2[1] & 0xff);
 3860                         break;
 3861 #endif
 3862 #ifdef INET6
 3863                 case AF_INET6:
 3864                         if (clp->lc_flags & LCL_TCPCALLBACK)
 3865                                 (void) nfsm_strtom(nd, "tcp6", 4);
 3866                         else 
 3867                                 (void) nfsm_strtom(nd, "udp6", 4);
 3868                         rin6 = (struct sockaddr_in6 *)clp->lc_req.nr_nam;
 3869                         ucp = inet_ntop(AF_INET6, &rin6->sin6_addr, addrbuf,
 3870                             INET6_ADDRSTRLEN);
 3871                         if (ucp != NULL)
 3872                                 i = strlen(ucp);
 3873                         else
 3874                                 i = 0;
 3875                         ucp2 = (u_char *)&rin6->sin6_port;
 3876                         sprintf(&addrbuf[i], ".%d.%d", ucp2[0] & 0xff,
 3877                             ucp2[1] & 0xff);
 3878                         break;
 3879 #endif
 3880                 }
 3881                 (void) nfsm_strtom(nd, addrbuf, strlen(addrbuf));
 3882                 free(addrbuf, M_TEMP);
 3883         }
 3884         if (clp) {
 3885                 free(clp->lc_req.nr_nam, M_SONAME);
 3886                 NFSFREEMUTEX(&clp->lc_req.nr_mtx);
 3887                 free(clp->lc_stateid, M_NFSDCLIENT);
 3888                 free(clp, M_NFSDCLIENT);
 3889         }
 3890         if (!nd->nd_repstat) {
 3891                 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_HYPER);
 3892                 *tl++ = clientid.lval[0];
 3893                 *tl++ = clientid.lval[1];
 3894                 *tl++ = confirm.lval[0];
 3895                 *tl = confirm.lval[1];
 3896         }
 3897 
 3898 out:
 3899         NFSEXITCODE2(0, nd);
 3900         return (0);
 3901 nfsmout:
 3902         if (clp) {
 3903                 free(clp->lc_req.nr_nam, M_SONAME);
 3904                 NFSFREEMUTEX(&clp->lc_req.nr_mtx);
 3905                 free(clp->lc_stateid, M_NFSDCLIENT);
 3906                 free(clp, M_NFSDCLIENT);
 3907         }
 3908         NFSEXITCODE2(error, nd);
 3909         return (error);
 3910 }
 3911 
 3912 /*
 3913  * nfsv4 set client id confirm service
 3914  */
 3915 int
 3916 nfsrvd_setclientidcfrm(struct nfsrv_descript *nd,
 3917     __unused int isdgram, __unused vnode_t vp,
 3918     __unused struct nfsexstuff *exp)
 3919 {
 3920         u_int32_t *tl;
 3921         int error = 0;
 3922         nfsquad_t clientid, confirm;
 3923         struct thread *p = curthread;
 3924 
 3925         if ((nd->nd_flag & ND_NFSV41) != 0) {
 3926                 nd->nd_repstat = NFSERR_NOTSUPP;
 3927                 goto nfsmout;
 3928         }
 3929         if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
 3930                 nd->nd_repstat = NFSERR_WRONGSEC;
 3931                 goto nfsmout;
 3932         }
 3933         NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_HYPER);
 3934         clientid.lval[0] = *tl++;
 3935         clientid.lval[1] = *tl++;
 3936         confirm.lval[0] = *tl++;
 3937         confirm.lval[1] = *tl;
 3938 
 3939         /*
 3940          * nfsrv_getclient() searches the client list for a match and
 3941          * returns the appropriate NFSERR status.
 3942          */
 3943         nd->nd_repstat = nfsrv_getclient(clientid, (CLOPS_CONFIRM|CLOPS_RENEW),
 3944             NULL, NULL, confirm, 0, nd, p);
 3945 nfsmout:
 3946         NFSEXITCODE2(error, nd);
 3947         return (error);
 3948 }
 3949 
 3950 /*
 3951  * nfsv4 verify service
 3952  */
 3953 int
 3954 nfsrvd_verify(struct nfsrv_descript *nd, int isdgram,
 3955     vnode_t vp, __unused struct nfsexstuff *exp)
 3956 {
 3957         int error = 0, ret, fhsize = NFSX_MYFH;
 3958         struct nfsvattr nva;
 3959         struct statfs *sf;
 3960         struct nfsfsinfo fs;
 3961         fhandle_t fh;
 3962         struct thread *p = curthread;
 3963 
 3964         sf = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
 3965         nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1, NULL);
 3966         if (!nd->nd_repstat)
 3967                 nd->nd_repstat = nfsvno_statfs(vp, sf);
 3968         if (!nd->nd_repstat)
 3969                 nd->nd_repstat = nfsvno_getfh(vp, &fh, p);
 3970         if (!nd->nd_repstat) {
 3971                 nfsvno_getfs(&fs, isdgram);
 3972                 error = nfsv4_loadattr(nd, vp, &nva, NULL, &fh, fhsize, NULL,
 3973                     sf, NULL, &fs, NULL, 1, &ret, NULL, NULL, p, nd->nd_cred);
 3974                 if (!error) {
 3975                         if (nd->nd_procnum == NFSV4OP_NVERIFY) {
 3976                                 if (ret == 0)
 3977                                         nd->nd_repstat = NFSERR_SAME;
 3978                                 else if (ret != NFSERR_NOTSAME)
 3979                                         nd->nd_repstat = ret;
 3980                         } else if (ret)
 3981                                 nd->nd_repstat = ret;
 3982                 }
 3983         }
 3984         vput(vp);
 3985         free(sf, M_STATFS);
 3986         NFSEXITCODE2(error, nd);
 3987         return (error);
 3988 }
 3989 
 3990 /*
 3991  * nfs openattr rpc
 3992  */
 3993 int
 3994 nfsrvd_openattr(struct nfsrv_descript *nd, __unused int isdgram,
 3995     vnode_t dp, __unused vnode_t *vpp, __unused fhandle_t *fhp,
 3996     __unused struct nfsexstuff *exp)
 3997 {
 3998         u_int32_t *tl;
 3999         int error = 0, createdir __unused;
 4000 
 4001         NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 4002         createdir = fxdr_unsigned(int, *tl);
 4003         nd->nd_repstat = NFSERR_NOTSUPP;
 4004 nfsmout:
 4005         vrele(dp);
 4006         NFSEXITCODE2(error, nd);
 4007         return (error);
 4008 }
 4009 
 4010 /*
 4011  * nfsv4 release lock owner service
 4012  */
 4013 int
 4014 nfsrvd_releaselckown(struct nfsrv_descript *nd, __unused int isdgram,
 4015     __unused vnode_t vp, __unused struct nfsexstuff *exp)
 4016 {
 4017         u_int32_t *tl;
 4018         struct nfsstate *stp = NULL;
 4019         int error = 0, len;
 4020         nfsquad_t clientid;
 4021         struct thread *p = curthread;
 4022 
 4023         if ((nd->nd_flag & ND_NFSV41) != 0) {
 4024                 nd->nd_repstat = NFSERR_NOTSUPP;
 4025                 goto nfsmout;
 4026         }
 4027         if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
 4028                 nd->nd_repstat = NFSERR_WRONGSEC;
 4029                 goto nfsmout;
 4030         }
 4031         NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
 4032         len = fxdr_unsigned(int, *(tl + 2));
 4033         if (len <= 0 || len > NFSV4_OPAQUELIMIT) {
 4034                 nd->nd_repstat = NFSERR_BADXDR;
 4035                 goto nfsmout;
 4036         }
 4037         stp = malloc(sizeof (struct nfsstate) + len,
 4038             M_NFSDSTATE, M_WAITOK);
 4039         stp->ls_ownerlen = len;
 4040         stp->ls_op = NULL;
 4041         stp->ls_flags = NFSLCK_RELEASE;
 4042         stp->ls_uid = nd->nd_cred->cr_uid;
 4043         clientid.lval[0] = *tl++;
 4044         clientid.lval[1] = *tl;
 4045         if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
 4046                 if ((nd->nd_flag & ND_NFSV41) != 0)
 4047                         clientid.qval = nd->nd_clientid.qval;
 4048                 else if (nd->nd_clientid.qval != clientid.qval)
 4049                         printf("EEK14 multiple clids\n");
 4050         } else {
 4051                 if ((nd->nd_flag & ND_NFSV41) != 0)
 4052                         printf("EEK! no clientid from session\n");
 4053                 nd->nd_flag |= ND_IMPLIEDCLID;
 4054                 nd->nd_clientid.qval = clientid.qval;
 4055         }
 4056         error = nfsrv_mtostr(nd, stp->ls_owner, len);
 4057         if (error)
 4058                 goto nfsmout;
 4059         nd->nd_repstat = nfsrv_releaselckown(stp, clientid, p);
 4060         free(stp, M_NFSDSTATE);
 4061 
 4062         NFSEXITCODE2(0, nd);
 4063         return (0);
 4064 nfsmout:
 4065         if (stp)
 4066                 free(stp, M_NFSDSTATE);
 4067         NFSEXITCODE2(error, nd);
 4068         return (error);
 4069 }
 4070 
 4071 /*
 4072  * nfsv4 exchange_id service
 4073  */
 4074 int
 4075 nfsrvd_exchangeid(struct nfsrv_descript *nd, __unused int isdgram,
 4076     __unused vnode_t vp, __unused struct nfsexstuff *exp)
 4077 {
 4078         uint32_t *tl;
 4079         int error = 0, i, idlen;
 4080         struct nfsclient *clp = NULL;
 4081         nfsquad_t clientid, confirm;
 4082         uint8_t *verf;
 4083         uint32_t sp4type, v41flags;
 4084         uint64_t owner_minor;
 4085         struct timespec verstime;
 4086 #ifdef INET
 4087         struct sockaddr_in *sin, *rin;
 4088 #endif
 4089 #ifdef INET6
 4090         struct sockaddr_in6 *sin6, *rin6;
 4091 #endif
 4092         struct thread *p = curthread;
 4093 
 4094         if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
 4095                 nd->nd_repstat = NFSERR_WRONGSEC;
 4096                 goto nfsmout;
 4097         }
 4098         NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF + NFSX_UNSIGNED);
 4099         verf = (uint8_t *)tl;
 4100         tl += (NFSX_VERF / NFSX_UNSIGNED);
 4101         i = fxdr_unsigned(int, *tl);
 4102         if (i > NFSV4_OPAQUELIMIT || i <= 0) {
 4103                 nd->nd_repstat = NFSERR_BADXDR;
 4104                 goto nfsmout;
 4105         }
 4106         idlen = i;
 4107         if (nd->nd_flag & ND_GSS)
 4108                 i += nd->nd_princlen;
 4109         clp = malloc(sizeof(struct nfsclient) + i, M_NFSDCLIENT, M_WAITOK |
 4110             M_ZERO);
 4111         clp->lc_stateid = malloc(sizeof(struct nfsstatehead) *
 4112             nfsrv_statehashsize, M_NFSDCLIENT, M_WAITOK);
 4113         NFSINITSOCKMUTEX(&clp->lc_req.nr_mtx);
 4114         /* Allocated large enough for an AF_INET or AF_INET6 socket. */
 4115         clp->lc_req.nr_nam = malloc(sizeof(struct sockaddr_in6), M_SONAME,
 4116             M_WAITOK | M_ZERO);
 4117         switch (nd->nd_nam->sa_family) {
 4118 #ifdef INET
 4119         case AF_INET:
 4120                 rin = (struct sockaddr_in *)clp->lc_req.nr_nam;
 4121                 sin = (struct sockaddr_in *)nd->nd_nam;
 4122                 rin->sin_family = AF_INET;
 4123                 rin->sin_len = sizeof(struct sockaddr_in);
 4124                 rin->sin_port = 0;
 4125                 rin->sin_addr.s_addr = sin->sin_addr.s_addr;
 4126                 break;
 4127 #endif
 4128 #ifdef INET6
 4129         case AF_INET6:
 4130                 rin6 = (struct sockaddr_in6 *)clp->lc_req.nr_nam;
 4131                 sin6 = (struct sockaddr_in6 *)nd->nd_nam;
 4132                 rin6->sin6_family = AF_INET6;
 4133                 rin6->sin6_len = sizeof(struct sockaddr_in6);
 4134                 rin6->sin6_port = 0;
 4135                 rin6->sin6_addr = sin6->sin6_addr;
 4136                 break;
 4137 #endif
 4138         }
 4139         clp->lc_req.nr_cred = NULL;
 4140         NFSBCOPY(verf, clp->lc_verf, NFSX_VERF);
 4141         clp->lc_idlen = idlen;
 4142         error = nfsrv_mtostr(nd, clp->lc_id, idlen);
 4143         if (error != 0)
 4144                 goto nfsmout;
 4145         if ((nd->nd_flag & ND_GSS) != 0) {
 4146                 clp->lc_flags = LCL_GSS | LCL_NFSV41;
 4147                 if ((nd->nd_flag & ND_GSSINTEGRITY) != 0)
 4148                         clp->lc_flags |= LCL_GSSINTEGRITY;
 4149                 else if ((nd->nd_flag & ND_GSSPRIVACY) != 0)
 4150                         clp->lc_flags |= LCL_GSSPRIVACY;
 4151         } else
 4152                 clp->lc_flags = LCL_NFSV41;
 4153         if ((nd->nd_flag & ND_NFSV42) != 0)
 4154                 clp->lc_flags |= LCL_NFSV42;
 4155         if ((nd->nd_flag & ND_GSS) != 0 && nd->nd_princlen > 0) {
 4156                 clp->lc_flags |= LCL_NAME;
 4157                 clp->lc_namelen = nd->nd_princlen;
 4158                 clp->lc_name = &clp->lc_id[idlen];
 4159                 NFSBCOPY(nd->nd_principal, clp->lc_name, clp->lc_namelen);
 4160         } else {
 4161                 clp->lc_uid = nd->nd_cred->cr_uid;
 4162                 clp->lc_gid = nd->nd_cred->cr_gid;
 4163         }
 4164         NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 4165         v41flags = fxdr_unsigned(uint32_t, *tl++);
 4166         if ((v41flags & ~(NFSV4EXCH_SUPPMOVEDREFER | NFSV4EXCH_SUPPMOVEDMIGR |
 4167             NFSV4EXCH_BINDPRINCSTATEID | NFSV4EXCH_MASKPNFS |
 4168             NFSV4EXCH_UPDCONFIRMEDRECA)) != 0) {
 4169                 nd->nd_repstat = NFSERR_INVAL;
 4170                 goto nfsmout;
 4171         }
 4172         if ((v41flags & NFSV4EXCH_UPDCONFIRMEDRECA) != 0)
 4173                 confirm.lval[1] = 1;
 4174         else
 4175                 confirm.lval[1] = 0;
 4176         if (nfsrv_devidcnt == 0)
 4177                 v41flags = NFSV4EXCH_USENONPNFS | NFSV4EXCH_USEPNFSDS;
 4178         else
 4179                 v41flags = NFSV4EXCH_USEPNFSMDS;
 4180         sp4type = fxdr_unsigned(uint32_t, *tl);
 4181         if (sp4type != NFSV4EXCH_SP4NONE) {
 4182                 nd->nd_repstat = NFSERR_NOTSUPP;
 4183                 goto nfsmout;
 4184         }
 4185 
 4186         /*
 4187          * nfsrv_setclient() does the actual work of adding it to the
 4188          * client list. If there is no error, the structure has been
 4189          * linked into the client list and clp should no longer be used
 4190          * here. When an error is returned, it has not been linked in,
 4191          * so it should be free'd.
 4192          */
 4193         nd->nd_repstat = nfsrv_setclient(nd, &clp, &clientid, &confirm, p);
 4194         if (clp != NULL) {
 4195                 free(clp->lc_req.nr_nam, M_SONAME);
 4196                 NFSFREEMUTEX(&clp->lc_req.nr_mtx);
 4197                 free(clp->lc_stateid, M_NFSDCLIENT);
 4198                 free(clp, M_NFSDCLIENT);
 4199         }
 4200         if (nd->nd_repstat == 0) {
 4201                 if (confirm.lval[1] != 0)
 4202                         v41flags |= NFSV4EXCH_CONFIRMEDR;
 4203                 NFSM_BUILD(tl, uint32_t *, 2 * NFSX_HYPER + 3 * NFSX_UNSIGNED);
 4204                 *tl++ = clientid.lval[0];                       /* ClientID */
 4205                 *tl++ = clientid.lval[1];
 4206                 *tl++ = txdr_unsigned(confirm.lval[0]);         /* SequenceID */
 4207                 *tl++ = txdr_unsigned(v41flags);                /* Exch flags */
 4208                 *tl++ = txdr_unsigned(NFSV4EXCH_SP4NONE);       /* No SSV */
 4209                 owner_minor = 0;                                /* Owner */
 4210                 txdr_hyper(owner_minor, tl);                    /* Minor */
 4211                 (void)nfsm_strtom(nd, nd->nd_cred->cr_prison->pr_hostuuid,
 4212                     strlen(nd->nd_cred->cr_prison->pr_hostuuid)); /* Major */
 4213                 (void)nfsm_strtom(nd, nd->nd_cred->cr_prison->pr_hostuuid,
 4214                     strlen(nd->nd_cred->cr_prison->pr_hostuuid)); /* Scope */
 4215                 NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
 4216                 *tl = txdr_unsigned(1);
 4217                 (void)nfsm_strtom(nd, "freebsd.org", strlen("freebsd.org"));
 4218                 (void)nfsm_strtom(nd, version, strlen(version));
 4219                 NFSM_BUILD(tl, uint32_t *, NFSX_V4TIME);
 4220                 verstime.tv_sec = 1293840000;           /* Jan 1, 2011 */
 4221                 verstime.tv_nsec = 0;
 4222                 txdr_nfsv4time(&verstime, tl);
 4223         }
 4224         NFSEXITCODE2(0, nd);
 4225         return (0);
 4226 nfsmout:
 4227         if (clp != NULL) {
 4228                 free(clp->lc_req.nr_nam, M_SONAME);
 4229                 NFSFREEMUTEX(&clp->lc_req.nr_mtx);
 4230                 free(clp->lc_stateid, M_NFSDCLIENT);
 4231                 free(clp, M_NFSDCLIENT);
 4232         }
 4233         NFSEXITCODE2(error, nd);
 4234         return (error);
 4235 }
 4236 
 4237 /*
 4238  * nfsv4 create session service
 4239  */
 4240 int
 4241 nfsrvd_createsession(struct nfsrv_descript *nd, __unused int isdgram,
 4242     __unused vnode_t vp, __unused struct nfsexstuff *exp)
 4243 {
 4244         uint32_t *tl;
 4245         int error = 0;
 4246         nfsquad_t clientid, confirm;
 4247         struct nfsdsession *sep = NULL;
 4248         uint32_t rdmacnt;
 4249         struct thread *p = curthread;
 4250 
 4251         if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
 4252                 nd->nd_repstat = NFSERR_WRONGSEC;
 4253                 goto nfsmout;
 4254         }
 4255         sep = (struct nfsdsession *)malloc(sizeof(struct nfsdsession),
 4256             M_NFSDSESSION, M_WAITOK | M_ZERO);
 4257         sep->sess_refcnt = 1;
 4258         mtx_init(&sep->sess_cbsess.nfsess_mtx, "nfscbsession", NULL, MTX_DEF);
 4259         NFSM_DISSECT(tl, uint32_t *, NFSX_HYPER + 2 * NFSX_UNSIGNED);
 4260         clientid.lval[0] = *tl++;
 4261         clientid.lval[1] = *tl++;
 4262         confirm.lval[0] = fxdr_unsigned(uint32_t, *tl++);
 4263         sep->sess_crflags = fxdr_unsigned(uint32_t, *tl);
 4264         /* Persistent sessions and RDMA are not supported. */
 4265         sep->sess_crflags &= NFSV4CRSESS_CONNBACKCHAN;
 4266 
 4267         /* Fore channel attributes. */
 4268         NFSM_DISSECT(tl, uint32_t *, 7 * NFSX_UNSIGNED);
 4269         tl++;                                   /* Header pad always 0. */
 4270         sep->sess_maxreq = fxdr_unsigned(uint32_t, *tl++);
 4271         if (sep->sess_maxreq > sb_max_adj - NFS_MAXXDR) {
 4272                 sep->sess_maxreq = sb_max_adj - NFS_MAXXDR;
 4273                 printf("Consider increasing kern.ipc.maxsockbuf\n");
 4274         }
 4275         sep->sess_maxresp = fxdr_unsigned(uint32_t, *tl++);
 4276         if (sep->sess_maxresp > sb_max_adj - NFS_MAXXDR) {
 4277                 sep->sess_maxresp = sb_max_adj - NFS_MAXXDR;
 4278                 printf("Consider increasing kern.ipc.maxsockbuf\n");
 4279         }
 4280         sep->sess_maxrespcached = fxdr_unsigned(uint32_t, *tl++);
 4281         sep->sess_maxops = fxdr_unsigned(uint32_t, *tl++);
 4282         sep->sess_maxslots = fxdr_unsigned(uint32_t, *tl++);
 4283         if (sep->sess_maxslots > NFSV4_SLOTS)
 4284                 sep->sess_maxslots = NFSV4_SLOTS;
 4285         rdmacnt = fxdr_unsigned(uint32_t, *tl);
 4286         if (rdmacnt > 1) {
 4287                 nd->nd_repstat = NFSERR_BADXDR;
 4288                 goto nfsmout;
 4289         } else if (rdmacnt == 1)
 4290                 NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
 4291 
 4292         /* Back channel attributes. */
 4293         NFSM_DISSECT(tl, uint32_t *, 7 * NFSX_UNSIGNED);
 4294         tl++;                                   /* Header pad always 0. */
 4295         sep->sess_cbmaxreq = fxdr_unsigned(uint32_t, *tl++);
 4296         sep->sess_cbmaxresp = fxdr_unsigned(uint32_t, *tl++);
 4297         sep->sess_cbmaxrespcached = fxdr_unsigned(uint32_t, *tl++);
 4298         sep->sess_cbmaxops = fxdr_unsigned(uint32_t, *tl++);
 4299         sep->sess_cbsess.nfsess_foreslots = fxdr_unsigned(uint32_t, *tl++);
 4300         rdmacnt = fxdr_unsigned(uint32_t, *tl);
 4301         if (rdmacnt > 1) {
 4302                 nd->nd_repstat = NFSERR_BADXDR;
 4303                 goto nfsmout;
 4304         } else if (rdmacnt == 1)
 4305                 NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
 4306 
 4307         NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
 4308         sep->sess_cbprogram = fxdr_unsigned(uint32_t, *tl);
 4309 
 4310         /*
 4311          * nfsrv_getclient() searches the client list for a match and
 4312          * returns the appropriate NFSERR status.
 4313          */
 4314         nd->nd_repstat = nfsrv_getclient(clientid, CLOPS_CONFIRM | CLOPS_RENEW,
 4315             NULL, sep, confirm, sep->sess_cbprogram, nd, p);
 4316         if (nd->nd_repstat == 0) {
 4317                 NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID);
 4318                 NFSBCOPY(sep->sess_sessionid, tl, NFSX_V4SESSIONID);
 4319                 NFSM_BUILD(tl, uint32_t *, 18 * NFSX_UNSIGNED);
 4320                 *tl++ = txdr_unsigned(confirm.lval[0]); /* sequenceid */
 4321                 *tl++ = txdr_unsigned(sep->sess_crflags);
 4322 
 4323                 /* Fore channel attributes. */
 4324                 *tl++ = 0;
 4325                 *tl++ = txdr_unsigned(sep->sess_maxreq);
 4326                 *tl++ = txdr_unsigned(sep->sess_maxresp);
 4327                 *tl++ = txdr_unsigned(sep->sess_maxrespcached);
 4328                 *tl++ = txdr_unsigned(sep->sess_maxops);
 4329                 *tl++ = txdr_unsigned(sep->sess_maxslots);
 4330                 *tl++ = txdr_unsigned(1);
 4331                 *tl++ = txdr_unsigned(0);                       /* No RDMA. */
 4332 
 4333                 /* Back channel attributes. */
 4334                 *tl++ = 0;
 4335                 *tl++ = txdr_unsigned(sep->sess_cbmaxreq);
 4336                 *tl++ = txdr_unsigned(sep->sess_cbmaxresp);
 4337                 *tl++ = txdr_unsigned(sep->sess_cbmaxrespcached);
 4338                 *tl++ = txdr_unsigned(sep->sess_cbmaxops);
 4339                 *tl++ = txdr_unsigned(sep->sess_cbsess.nfsess_foreslots);
 4340                 *tl++ = txdr_unsigned(1);
 4341                 *tl = txdr_unsigned(0);                 /* No RDMA. */
 4342         }
 4343 nfsmout:
 4344         if (nd->nd_repstat != 0 && sep != NULL)
 4345                 free(sep, M_NFSDSESSION);
 4346         NFSEXITCODE2(error, nd);
 4347         return (error);
 4348 }
 4349 
 4350 /*
 4351  * nfsv4 sequence service
 4352  */
 4353 int
 4354 nfsrvd_sequence(struct nfsrv_descript *nd, __unused int isdgram,
 4355     __unused vnode_t vp, __unused struct nfsexstuff *exp)
 4356 {
 4357         uint32_t *tl;
 4358         uint32_t highest_slotid, sequenceid, sflags, target_highest_slotid;
 4359         int cache_this, error = 0;
 4360         struct thread *p = curthread;
 4361 
 4362         if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
 4363                 nd->nd_repstat = NFSERR_WRONGSEC;
 4364                 goto nfsmout;
 4365         }
 4366         NFSM_DISSECT(tl, uint32_t *, NFSX_V4SESSIONID);
 4367         NFSBCOPY(tl, nd->nd_sessionid, NFSX_V4SESSIONID);
 4368         NFSM_DISSECT(tl, uint32_t *, 4 * NFSX_UNSIGNED);
 4369         sequenceid = fxdr_unsigned(uint32_t, *tl++);
 4370         nd->nd_slotid = fxdr_unsigned(uint32_t, *tl++);
 4371         highest_slotid = fxdr_unsigned(uint32_t, *tl++);
 4372         if (*tl == newnfs_true)
 4373                 cache_this = 1;
 4374         else
 4375                 cache_this = 0;
 4376         nd->nd_flag |= ND_HASSEQUENCE;
 4377         nd->nd_repstat = nfsrv_checksequence(nd, sequenceid, &highest_slotid,
 4378             &target_highest_slotid, cache_this, &sflags, p);
 4379         if (nd->nd_repstat == 0) {
 4380                 NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID);
 4381                 NFSBCOPY(nd->nd_sessionid, tl, NFSX_V4SESSIONID);
 4382                 NFSM_BUILD(tl, uint32_t *, 5 * NFSX_UNSIGNED);
 4383                 *tl++ = txdr_unsigned(sequenceid);
 4384                 *tl++ = txdr_unsigned(nd->nd_slotid);
 4385                 *tl++ = txdr_unsigned(highest_slotid);
 4386                 *tl++ = txdr_unsigned(target_highest_slotid);
 4387                 *tl = txdr_unsigned(sflags);
 4388         }
 4389 nfsmout:
 4390         NFSEXITCODE2(error, nd);
 4391         return (error);
 4392 }
 4393 
 4394 /*
 4395  * nfsv4 reclaim complete service
 4396  */
 4397 int
 4398 nfsrvd_reclaimcomplete(struct nfsrv_descript *nd, __unused int isdgram,
 4399     __unused vnode_t vp, __unused struct nfsexstuff *exp)
 4400 {
 4401         uint32_t *tl;
 4402         int error = 0, onefs;
 4403 
 4404         if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
 4405                 nd->nd_repstat = NFSERR_WRONGSEC;
 4406                 goto nfsmout;
 4407         }
 4408         NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
 4409         /*
 4410          * I believe that a ReclaimComplete with rca_one_fs == TRUE is only
 4411          * to be used after a file system has been transferred to a different
 4412          * file server.  However, RFC5661 is somewhat vague w.r.t. this and
 4413          * the ESXi 6.7 client does both a ReclaimComplete with rca_one_fs
 4414          * == TRUE and one with ReclaimComplete with rca_one_fs == FALSE.
 4415          * Therefore, just ignore the rca_one_fs == TRUE operation and return
 4416          * NFS_OK without doing anything.
 4417          */
 4418         onefs = 0;
 4419         if (*tl == newnfs_true)
 4420                 onefs = 1;
 4421         nd->nd_repstat = nfsrv_checkreclaimcomplete(nd, onefs);
 4422 nfsmout:
 4423         NFSEXITCODE2(error, nd);
 4424         return (error);
 4425 }
 4426 
 4427 /*
 4428  * nfsv4 destroy clientid service
 4429  */
 4430 int
 4431 nfsrvd_destroyclientid(struct nfsrv_descript *nd, __unused int isdgram,
 4432     __unused vnode_t vp, __unused struct nfsexstuff *exp)
 4433 {
 4434         uint32_t *tl;
 4435         nfsquad_t clientid;
 4436         int error = 0;
 4437         struct thread *p = curthread;
 4438 
 4439         if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
 4440                 nd->nd_repstat = NFSERR_WRONGSEC;
 4441                 goto nfsmout;
 4442         }
 4443         NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 4444         clientid.lval[0] = *tl++;
 4445         clientid.lval[1] = *tl;
 4446         nd->nd_repstat = nfsrv_destroyclient(clientid, p);
 4447 nfsmout:
 4448         NFSEXITCODE2(error, nd);
 4449         return (error);
 4450 }
 4451 
 4452 /*
 4453  * nfsv4 bind connection to session service
 4454  */
 4455 int
 4456 nfsrvd_bindconnsess(struct nfsrv_descript *nd, __unused int isdgram,
 4457     __unused vnode_t vp, __unused struct nfsexstuff *exp)
 4458 {
 4459         uint32_t *tl;
 4460         uint8_t sessid[NFSX_V4SESSIONID];
 4461         int error = 0, foreaft;
 4462 
 4463         if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
 4464                 nd->nd_repstat = NFSERR_WRONGSEC;
 4465                 goto nfsmout;
 4466         }
 4467         NFSM_DISSECT(tl, uint32_t *, NFSX_V4SESSIONID + 2 * NFSX_UNSIGNED);
 4468         NFSBCOPY(tl, sessid, NFSX_V4SESSIONID);
 4469         tl += (NFSX_V4SESSIONID / NFSX_UNSIGNED);
 4470         foreaft = fxdr_unsigned(int, *tl++);
 4471         if (*tl == newnfs_true) {
 4472                 /* RDMA is not supported. */
 4473                 nd->nd_repstat = NFSERR_NOTSUPP;
 4474                 goto nfsmout;
 4475         }
 4476 
 4477         nd->nd_repstat = nfsrv_bindconnsess(nd, sessid, &foreaft);
 4478         if (nd->nd_repstat == 0) {
 4479                 NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID + 2 *
 4480                     NFSX_UNSIGNED);
 4481                 NFSBCOPY(sessid, tl, NFSX_V4SESSIONID);
 4482                 tl += (NFSX_V4SESSIONID / NFSX_UNSIGNED);
 4483                 *tl++ = txdr_unsigned(foreaft);
 4484                 *tl = newnfs_false;
 4485         }
 4486 nfsmout:
 4487         NFSEXITCODE2(error, nd);
 4488         return (error);
 4489 }
 4490 
 4491 /*
 4492  * nfsv4 destroy session service
 4493  */
 4494 int
 4495 nfsrvd_destroysession(struct nfsrv_descript *nd, __unused int isdgram,
 4496     __unused vnode_t vp, __unused struct nfsexstuff *exp)
 4497 {
 4498         uint8_t *cp, sessid[NFSX_V4SESSIONID];
 4499         int error = 0;
 4500 
 4501         if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
 4502                 nd->nd_repstat = NFSERR_WRONGSEC;
 4503                 goto nfsmout;
 4504         }
 4505         NFSM_DISSECT(cp, uint8_t *, NFSX_V4SESSIONID);
 4506         NFSBCOPY(cp, sessid, NFSX_V4SESSIONID);
 4507         nd->nd_repstat = nfsrv_destroysession(nd, sessid);
 4508 nfsmout:
 4509         NFSEXITCODE2(error, nd);
 4510         return (error);
 4511 }
 4512 
 4513 /*
 4514  * nfsv4 free stateid service
 4515  */
 4516 int
 4517 nfsrvd_freestateid(struct nfsrv_descript *nd, __unused int isdgram,
 4518     __unused vnode_t vp, __unused struct nfsexstuff *exp)
 4519 {
 4520         uint32_t *tl;
 4521         nfsv4stateid_t stateid;
 4522         int error = 0;
 4523         struct thread *p = curthread;
 4524 
 4525         if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
 4526                 nd->nd_repstat = NFSERR_WRONGSEC;
 4527                 goto nfsmout;
 4528         }
 4529         NFSM_DISSECT(tl, uint32_t *, NFSX_STATEID);
 4530         stateid.seqid = fxdr_unsigned(uint32_t, *tl++);
 4531         NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER);
 4532 
 4533         /*
 4534          * For the special stateid of other all 0s and seqid == 1, set the
 4535          * stateid to the current stateid, if it is set.
 4536          */
 4537         if (stateid.seqid == 1 && stateid.other[0] == 0 &&
 4538             stateid.other[1] == 0 && stateid.other[2] == 0) {
 4539                 if ((nd->nd_flag & ND_CURSTATEID) != 0) {
 4540                         stateid = nd->nd_curstateid;
 4541                         stateid.seqid = 0;
 4542                 } else {
 4543                         nd->nd_repstat = NFSERR_BADSTATEID;
 4544                         goto nfsmout;
 4545                 }
 4546         }
 4547 
 4548         nd->nd_repstat = nfsrv_freestateid(nd, &stateid, p);
 4549 
 4550         /* If the current stateid has been free'd, unset it. */
 4551         if (nd->nd_repstat == 0 && (nd->nd_flag & ND_CURSTATEID) != 0 &&
 4552             stateid.other[0] == nd->nd_curstateid.other[0] &&
 4553             stateid.other[1] == nd->nd_curstateid.other[1] &&
 4554             stateid.other[2] == nd->nd_curstateid.other[2])
 4555                 nd->nd_flag &= ~ND_CURSTATEID;
 4556 nfsmout:
 4557         NFSEXITCODE2(error, nd);
 4558         return (error);
 4559 }
 4560 
 4561 /*
 4562  * nfsv4 layoutget service
 4563  */
 4564 int
 4565 nfsrvd_layoutget(struct nfsrv_descript *nd, __unused int isdgram,
 4566     vnode_t vp, struct nfsexstuff *exp)
 4567 {
 4568         uint32_t *tl;
 4569         nfsv4stateid_t stateid;
 4570         int error = 0, layoutlen, layouttype, iomode, maxcnt, retonclose;
 4571         uint64_t offset, len, minlen;
 4572         char *layp;
 4573         struct thread *p = curthread;
 4574 
 4575         if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
 4576                 nd->nd_repstat = NFSERR_WRONGSEC;
 4577                 goto nfsmout;
 4578         }
 4579         NFSM_DISSECT(tl, uint32_t *, 4 * NFSX_UNSIGNED + 3 * NFSX_HYPER +
 4580             NFSX_STATEID);
 4581         tl++;           /* Signal layout available. Ignore for now. */
 4582         layouttype = fxdr_unsigned(int, *tl++);
 4583         iomode = fxdr_unsigned(int, *tl++);
 4584         offset = fxdr_hyper(tl); tl += 2;
 4585         len = fxdr_hyper(tl); tl += 2;
 4586         minlen = fxdr_hyper(tl); tl += 2;
 4587         stateid.seqid = fxdr_unsigned(uint32_t, *tl++);
 4588         NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER);
 4589         tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
 4590         maxcnt = fxdr_unsigned(int, *tl);
 4591         NFSD_DEBUG(4, "layoutget ltyp=%d iom=%d off=%ju len=%ju mlen=%ju\n",
 4592             layouttype, iomode, (uintmax_t)offset, (uintmax_t)len,
 4593             (uintmax_t)minlen);
 4594         if (len < minlen ||
 4595             (minlen != UINT64_MAX && offset + minlen < offset) ||
 4596             (len != UINT64_MAX && offset + len < offset)) {
 4597                 nd->nd_repstat = NFSERR_INVAL;
 4598                 goto nfsmout;
 4599         }
 4600 
 4601         /*
 4602          * For the special stateid of other all 0s and seqid == 1, set the
 4603          * stateid to the current stateid, if it is set.
 4604          */
 4605         if (stateid.seqid == 1 && stateid.other[0] == 0 &&
 4606             stateid.other[1] == 0 && stateid.other[2] == 0) {
 4607                 if ((nd->nd_flag & ND_CURSTATEID) != 0) {
 4608                         stateid = nd->nd_curstateid;
 4609                         stateid.seqid = 0;
 4610                 } else {
 4611                         nd->nd_repstat = NFSERR_BADSTATEID;
 4612                         goto nfsmout;
 4613                 }
 4614         }
 4615 
 4616         layp = NULL;
 4617         if (layouttype == NFSLAYOUT_NFSV4_1_FILES && nfsrv_maxpnfsmirror == 1)
 4618                 layp = malloc(NFSX_V4FILELAYOUT, M_TEMP, M_WAITOK);
 4619         else if (layouttype == NFSLAYOUT_FLEXFILE)
 4620                 layp = malloc(NFSX_V4FLEXLAYOUT(nfsrv_maxpnfsmirror), M_TEMP,
 4621                     M_WAITOK);
 4622         else
 4623                 nd->nd_repstat = NFSERR_UNKNLAYOUTTYPE;
 4624         if (layp != NULL)
 4625                 nd->nd_repstat = nfsrv_layoutget(nd, vp, exp, layouttype,
 4626                     &iomode, &offset, &len, minlen, &stateid, maxcnt,
 4627                     &retonclose, &layoutlen, layp, nd->nd_cred, p);
 4628         NFSD_DEBUG(4, "nfsrv_layoutget stat=%u layoutlen=%d\n", nd->nd_repstat,
 4629             layoutlen);
 4630         if (nd->nd_repstat == 0) {
 4631                 /* For NFSv4.1, set the Current StateID. */
 4632                 if ((nd->nd_flag & ND_NFSV41) != 0) {
 4633                         nd->nd_curstateid = stateid;
 4634                         nd->nd_flag |= ND_CURSTATEID;
 4635                 }
 4636                 NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED + NFSX_STATEID +
 4637                     2 * NFSX_HYPER);
 4638                 *tl++ = txdr_unsigned(retonclose);
 4639                 *tl++ = txdr_unsigned(stateid.seqid);
 4640                 NFSBCOPY(stateid.other, tl, NFSX_STATEIDOTHER);
 4641                 tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
 4642                 *tl++ = txdr_unsigned(1);       /* Only returns one layout. */
 4643                 txdr_hyper(offset, tl); tl += 2;
 4644                 txdr_hyper(len, tl); tl += 2;
 4645                 *tl++ = txdr_unsigned(iomode);
 4646                 *tl = txdr_unsigned(layouttype);
 4647                 nfsm_strtom(nd, layp, layoutlen);
 4648         } else if (nd->nd_repstat == NFSERR_LAYOUTTRYLATER) {
 4649                 NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
 4650                 *tl = newnfs_false;
 4651         }
 4652         free(layp, M_TEMP);
 4653 nfsmout:
 4654         vput(vp);
 4655         NFSEXITCODE2(error, nd);
 4656         return (error);
 4657 }
 4658 
 4659 /*
 4660  * nfsv4 layoutcommit service
 4661  */
 4662 int
 4663 nfsrvd_layoutcommit(struct nfsrv_descript *nd, __unused int isdgram,
 4664     vnode_t vp, struct nfsexstuff *exp)
 4665 {
 4666         uint32_t *tl;
 4667         nfsv4stateid_t stateid;
 4668         int error = 0, hasnewoff, hasnewmtime, layouttype, maxcnt, reclaim;
 4669         int hasnewsize;
 4670         uint64_t offset, len, newoff = 0, newsize;
 4671         struct timespec newmtime;
 4672         char *layp;
 4673         struct thread *p = curthread;
 4674 
 4675         layp = NULL;
 4676         if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
 4677                 nd->nd_repstat = NFSERR_WRONGSEC;
 4678                 goto nfsmout;
 4679         }
 4680         NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED + 2 * NFSX_HYPER +
 4681             NFSX_STATEID);
 4682         offset = fxdr_hyper(tl); tl += 2;
 4683         len = fxdr_hyper(tl); tl += 2;
 4684         reclaim = fxdr_unsigned(int, *tl++);
 4685         stateid.seqid = fxdr_unsigned(uint32_t, *tl++);
 4686         NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER);
 4687         tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
 4688         /*
 4689          * For the special stateid of other all 0s and seqid == 1, set the
 4690          * stateid to the current stateid, if it is set.
 4691          */
 4692         if (stateid.seqid == 1 && stateid.other[0] == 0 &&
 4693             stateid.other[1] == 0 && stateid.other[2] == 0) {
 4694                 if ((nd->nd_flag & ND_CURSTATEID) != 0) {
 4695                         stateid = nd->nd_curstateid;
 4696                         stateid.seqid = 0;
 4697                 } else {
 4698                         nd->nd_repstat = NFSERR_BADSTATEID;
 4699                         goto nfsmout;
 4700                 }
 4701         }
 4702 
 4703         hasnewoff = fxdr_unsigned(int, *tl);
 4704         if (hasnewoff != 0) {
 4705                 NFSM_DISSECT(tl, uint32_t *, NFSX_HYPER + NFSX_UNSIGNED);
 4706                 newoff = fxdr_hyper(tl); tl += 2;
 4707         } else
 4708                 NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
 4709         hasnewmtime = fxdr_unsigned(int, *tl);
 4710         if (hasnewmtime != 0) {
 4711                 NFSM_DISSECT(tl, uint32_t *, NFSX_V4TIME + 2 * NFSX_UNSIGNED);
 4712                 fxdr_nfsv4time(tl, &newmtime);
 4713                 tl += (NFSX_V4TIME / NFSX_UNSIGNED);
 4714         } else
 4715                 NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 4716         layouttype = fxdr_unsigned(int, *tl++);
 4717         maxcnt = fxdr_unsigned(int, *tl);
 4718         if (maxcnt > 0) {
 4719                 layp = malloc(maxcnt + 1, M_TEMP, M_WAITOK);
 4720                 error = nfsrv_mtostr(nd, layp, maxcnt);
 4721                 if (error != 0)
 4722                         goto nfsmout;
 4723         }
 4724         nd->nd_repstat = nfsrv_layoutcommit(nd, vp, layouttype, hasnewoff,
 4725             newoff, offset, len, hasnewmtime, &newmtime, reclaim, &stateid,
 4726             maxcnt, layp, &hasnewsize, &newsize, nd->nd_cred, p);
 4727         NFSD_DEBUG(4, "nfsrv_layoutcommit stat=%u\n", nd->nd_repstat);
 4728         if (nd->nd_repstat == 0) {
 4729                 if (hasnewsize != 0) {
 4730                         NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED + NFSX_HYPER);
 4731                         *tl++ = newnfs_true;
 4732                         txdr_hyper(newsize, tl);
 4733                 } else {
 4734                         NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
 4735                         *tl = newnfs_false;
 4736                 }
 4737         }
 4738 nfsmout:
 4739         free(layp, M_TEMP);
 4740         vput(vp);
 4741         NFSEXITCODE2(error, nd);
 4742         return (error);
 4743 }
 4744 
 4745 /*
 4746  * nfsv4 layoutreturn service
 4747  */
 4748 int
 4749 nfsrvd_layoutreturn(struct nfsrv_descript *nd, __unused int isdgram,
 4750     vnode_t vp, struct nfsexstuff *exp)
 4751 {
 4752         uint32_t *tl, *layp;
 4753         nfsv4stateid_t stateid;
 4754         int error = 0, fnd, kind, layouttype, iomode, maxcnt, reclaim;
 4755         uint64_t offset, len;
 4756         struct thread *p = curthread;
 4757 
 4758         layp = NULL;
 4759         if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
 4760                 nd->nd_repstat = NFSERR_WRONGSEC;
 4761                 goto nfsmout;
 4762         }
 4763         NFSM_DISSECT(tl, uint32_t *, 4 * NFSX_UNSIGNED);
 4764         reclaim = *tl++;
 4765         layouttype = fxdr_unsigned(int, *tl++);
 4766         iomode = fxdr_unsigned(int, *tl++);
 4767         kind = fxdr_unsigned(int, *tl);
 4768         NFSD_DEBUG(4, "layoutreturn recl=%d ltyp=%d iom=%d kind=%d\n", reclaim,
 4769             layouttype, iomode, kind);
 4770         if (kind == NFSV4LAYOUTRET_FILE) {
 4771                 NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_HYPER + NFSX_STATEID +
 4772                     NFSX_UNSIGNED);
 4773                 offset = fxdr_hyper(tl); tl += 2;
 4774                 len = fxdr_hyper(tl); tl += 2;
 4775                 stateid.seqid = fxdr_unsigned(uint32_t, *tl++);
 4776                 NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER);
 4777                 tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
 4778 
 4779                 /*
 4780                  * For the special stateid of other all 0s and seqid == 1, set
 4781                  * the stateid to the current stateid, if it is set.
 4782                  */
 4783                 if (stateid.seqid == 1 && stateid.other[0] == 0 &&
 4784                     stateid.other[1] == 0 && stateid.other[2] == 0) {
 4785                         if ((nd->nd_flag & ND_CURSTATEID) != 0) {
 4786                                 stateid = nd->nd_curstateid;
 4787                                 stateid.seqid = 0;
 4788                         } else {
 4789                                 nd->nd_repstat = NFSERR_BADSTATEID;
 4790                                 goto nfsmout;
 4791                         }
 4792                 }
 4793 
 4794                 maxcnt = fxdr_unsigned(int, *tl);
 4795                 if (maxcnt > 0) {
 4796                         layp = malloc(maxcnt + 1, M_TEMP, M_WAITOK);
 4797                         error = nfsrv_mtostr(nd, (char *)layp, maxcnt);
 4798                         if (error != 0)
 4799                                 goto nfsmout;
 4800                 }
 4801         } else {
 4802                 if (reclaim == newnfs_true) {
 4803                         nd->nd_repstat = NFSERR_INVAL;
 4804                         goto nfsmout;
 4805                 }
 4806                 offset = len = 0;
 4807                 maxcnt = 0;
 4808         }
 4809         nd->nd_repstat = nfsrv_layoutreturn(nd, vp, layouttype, iomode,
 4810             offset, len, reclaim, kind, &stateid, maxcnt, layp, &fnd,
 4811             nd->nd_cred, p);
 4812         NFSD_DEBUG(4, "nfsrv_layoutreturn stat=%u fnd=%d\n", nd->nd_repstat,
 4813             fnd);
 4814         if (nd->nd_repstat == 0) {
 4815                 NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
 4816                 if (fnd != 0) {
 4817                         *tl = newnfs_true;
 4818                         NFSM_BUILD(tl, uint32_t *, NFSX_STATEID);
 4819                         *tl++ = txdr_unsigned(stateid.seqid);
 4820                         NFSBCOPY(stateid.other, tl, NFSX_STATEIDOTHER);
 4821                 } else
 4822                         *tl = newnfs_false;
 4823         }
 4824 nfsmout:
 4825         free(layp, M_TEMP);
 4826         vput(vp);
 4827         NFSEXITCODE2(error, nd);
 4828         return (error);
 4829 }
 4830 
 4831 /*
 4832  * nfsv4 layout error service
 4833  */
 4834 int
 4835 nfsrvd_layouterror(struct nfsrv_descript *nd, __unused int isdgram,
 4836     vnode_t vp, struct nfsexstuff *exp)
 4837 {
 4838         uint32_t *tl;
 4839         nfsv4stateid_t stateid;
 4840         int cnt, error = 0, i, stat;
 4841         int opnum __unused;
 4842         char devid[NFSX_V4DEVICEID];
 4843         uint64_t offset, len;
 4844 
 4845         if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
 4846                 nd->nd_repstat = NFSERR_WRONGSEC;
 4847                 goto nfsmout;
 4848         }
 4849         NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_HYPER + NFSX_STATEID +
 4850             NFSX_UNSIGNED);
 4851         offset = fxdr_hyper(tl); tl += 2;
 4852         len = fxdr_hyper(tl); tl += 2;
 4853         stateid.seqid = fxdr_unsigned(uint32_t, *tl++);
 4854         NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER);
 4855         tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
 4856         cnt = fxdr_unsigned(int, *tl);
 4857         NFSD_DEBUG(4, "layouterror off=%ju len=%ju cnt=%d\n", (uintmax_t)offset,
 4858             (uintmax_t)len, cnt);
 4859         /*
 4860          * For the special stateid of other all 0s and seqid == 1, set
 4861          * the stateid to the current stateid, if it is set.
 4862          */
 4863         if (stateid.seqid == 1 && stateid.other[0] == 0 &&
 4864             stateid.other[1] == 0 && stateid.other[2] == 0) {
 4865                 if ((nd->nd_flag & ND_CURSTATEID) != 0) {
 4866                         stateid = nd->nd_curstateid;
 4867                         stateid.seqid = 0;
 4868                 } else {
 4869                         nd->nd_repstat = NFSERR_BADSTATEID;
 4870                         goto nfsmout;
 4871                 }
 4872         }
 4873 
 4874         /*
 4875          * Ignore offset, len and stateid for now.
 4876          */
 4877         for (i = 0; i < cnt; i++) {
 4878                 NFSM_DISSECT(tl, uint32_t *, NFSX_V4DEVICEID + 2 *
 4879                     NFSX_UNSIGNED);
 4880                 NFSBCOPY(tl, devid, NFSX_V4DEVICEID);
 4881                 tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED);
 4882                 stat = fxdr_unsigned(int, *tl++);
 4883                 opnum = fxdr_unsigned(int, *tl);
 4884                 NFSD_DEBUG(4, "nfsrvd_layouterr op=%d stat=%d\n", opnum, stat);
 4885                 /*
 4886                  * Except for NFSERR_ACCES and NFSERR_STALE errors,
 4887                  * disable the mirror.
 4888                  */
 4889                 if (stat != NFSERR_ACCES && stat != NFSERR_STALE)
 4890                         nfsrv_delds(devid, curthread);
 4891         }
 4892 nfsmout:
 4893         vput(vp);
 4894         NFSEXITCODE2(error, nd);
 4895         return (error);
 4896 }
 4897 
 4898 /*
 4899  * nfsv4 layout stats service
 4900  */
 4901 int
 4902 nfsrvd_layoutstats(struct nfsrv_descript *nd, __unused int isdgram,
 4903     vnode_t vp, struct nfsexstuff *exp)
 4904 {
 4905         uint32_t *tl;
 4906         nfsv4stateid_t stateid;
 4907         int cnt, error = 0;
 4908         int layouttype __unused;
 4909         char devid[NFSX_V4DEVICEID] __unused;
 4910         uint64_t offset, len, readcount, readbytes, writecount, writebytes
 4911             __unused;
 4912 
 4913         if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
 4914                 nd->nd_repstat = NFSERR_WRONGSEC;
 4915                 goto nfsmout;
 4916         }
 4917         NFSM_DISSECT(tl, uint32_t *, 6 * NFSX_HYPER + NFSX_STATEID +
 4918             NFSX_V4DEVICEID + 2 * NFSX_UNSIGNED);
 4919         offset = fxdr_hyper(tl); tl += 2;
 4920         len = fxdr_hyper(tl); tl += 2;
 4921         stateid.seqid = fxdr_unsigned(uint32_t, *tl++);
 4922         NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER);
 4923         tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
 4924         readcount = fxdr_hyper(tl); tl += 2;
 4925         readbytes = fxdr_hyper(tl); tl += 2;
 4926         writecount = fxdr_hyper(tl); tl += 2;
 4927         writebytes = fxdr_hyper(tl); tl += 2;
 4928         NFSBCOPY(tl, devid, NFSX_V4DEVICEID);
 4929         tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED);
 4930         layouttype = fxdr_unsigned(int, *tl++);
 4931         cnt = fxdr_unsigned(int, *tl);
 4932         error = nfsm_advance(nd, NFSM_RNDUP(cnt), -1);
 4933         if (error != 0)
 4934                 goto nfsmout;
 4935         NFSD_DEBUG(4, "layoutstats cnt=%d\n", cnt);
 4936         /*
 4937          * For the special stateid of other all 0s and seqid == 1, set
 4938          * the stateid to the current stateid, if it is set.
 4939          */
 4940         if (stateid.seqid == 1 && stateid.other[0] == 0 &&
 4941             stateid.other[1] == 0 && stateid.other[2] == 0) {
 4942                 if ((nd->nd_flag & ND_CURSTATEID) != 0) {
 4943                         stateid = nd->nd_curstateid;
 4944                         stateid.seqid = 0;
 4945                 } else {
 4946                         nd->nd_repstat = NFSERR_BADSTATEID;
 4947                         goto nfsmout;
 4948                 }
 4949         }
 4950 
 4951         /*
 4952          * No use for the stats for now.
 4953          */
 4954 nfsmout:
 4955         vput(vp);
 4956         NFSEXITCODE2(error, nd);
 4957         return (error);
 4958 }
 4959 
 4960 /*
 4961  * nfsv4 io_advise service
 4962  */
 4963 int
 4964 nfsrvd_ioadvise(struct nfsrv_descript *nd, __unused int isdgram,
 4965     vnode_t vp, struct nfsexstuff *exp)
 4966 {
 4967         uint32_t *tl;
 4968         nfsv4stateid_t stateid;
 4969         nfsattrbit_t hints;
 4970         int error = 0, ret;
 4971         off_t offset, len;
 4972 
 4973         if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
 4974                 nd->nd_repstat = NFSERR_WRONGSEC;
 4975                 goto nfsmout;
 4976         }
 4977         NFSM_DISSECT(tl, uint32_t *, NFSX_STATEID + 2 * NFSX_HYPER);
 4978         stateid.seqid = fxdr_unsigned(uint32_t, *tl++);
 4979         NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER);
 4980         tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
 4981         offset = fxdr_hyper(tl); tl += 2;
 4982         len = fxdr_hyper(tl);
 4983         error = nfsrv_getattrbits(nd, &hints, NULL, NULL);
 4984         if (error != 0)
 4985                 goto nfsmout;
 4986         /*
 4987          * For the special stateid of other all 0s and seqid == 1, set
 4988          * the stateid to the current stateid, if it is set.
 4989          */
 4990         if (stateid.seqid == 1 && stateid.other[0] == 0 &&
 4991             stateid.other[1] == 0 && stateid.other[2] == 0) {
 4992                 if ((nd->nd_flag & ND_CURSTATEID) != 0) {
 4993                         stateid = nd->nd_curstateid;
 4994                         stateid.seqid = 0;
 4995                 } else {
 4996                         nd->nd_repstat = NFSERR_BADSTATEID;
 4997                         goto nfsmout;
 4998                 }
 4999         }
 5000 
 5001         if (offset < 0) {
 5002                 nd->nd_repstat = NFSERR_INVAL;
 5003                 goto nfsmout;
 5004         }
 5005         if (len < 0)
 5006                 len = 0;
 5007         if (vp->v_type != VREG) {
 5008                 if (vp->v_type == VDIR)
 5009                         nd->nd_repstat = NFSERR_ISDIR;
 5010                 else
 5011                         nd->nd_repstat = NFSERR_WRONGTYPE;
 5012                 goto nfsmout;
 5013         }
 5014 
 5015         /*
 5016          * For now, we can only handle WILLNEED and DONTNEED and don't use
 5017          * the stateid.
 5018          */
 5019         if ((NFSISSET_ATTRBIT(&hints, NFSV4IOHINT_WILLNEED) &&
 5020             !NFSISSET_ATTRBIT(&hints, NFSV4IOHINT_DONTNEED)) ||
 5021             (NFSISSET_ATTRBIT(&hints, NFSV4IOHINT_DONTNEED) &&
 5022             !NFSISSET_ATTRBIT(&hints, NFSV4IOHINT_WILLNEED))) {
 5023                 NFSVOPUNLOCK(vp);
 5024                 if (NFSISSET_ATTRBIT(&hints, NFSV4IOHINT_WILLNEED)) {
 5025                         ret = VOP_ADVISE(vp, offset, len, POSIX_FADV_WILLNEED);
 5026                         NFSZERO_ATTRBIT(&hints);
 5027                         if (ret == 0)
 5028                                 NFSSETBIT_ATTRBIT(&hints, NFSV4IOHINT_WILLNEED);
 5029                         else
 5030                                 NFSSETBIT_ATTRBIT(&hints, NFSV4IOHINT_NORMAL);
 5031                 } else {
 5032                         ret = VOP_ADVISE(vp, offset, len, POSIX_FADV_DONTNEED);
 5033                         NFSZERO_ATTRBIT(&hints);
 5034                         if (ret == 0)
 5035                                 NFSSETBIT_ATTRBIT(&hints, NFSV4IOHINT_DONTNEED);
 5036                         else
 5037                                 NFSSETBIT_ATTRBIT(&hints, NFSV4IOHINT_NORMAL);
 5038                 }
 5039                 vrele(vp);
 5040         } else {
 5041                 NFSZERO_ATTRBIT(&hints);
 5042                 NFSSETBIT_ATTRBIT(&hints, NFSV4IOHINT_NORMAL);
 5043                 vput(vp);
 5044         }
 5045         nfsrv_putattrbit(nd, &hints);
 5046         NFSEXITCODE2(error, nd);
 5047         return (error);
 5048 nfsmout:
 5049         vput(vp);
 5050         NFSEXITCODE2(error, nd);
 5051         return (error);
 5052 }
 5053 
 5054 /*
 5055  * nfsv4 getdeviceinfo service
 5056  */
 5057 int
 5058 nfsrvd_getdevinfo(struct nfsrv_descript *nd, __unused int isdgram,
 5059     __unused vnode_t vp, __unused struct nfsexstuff *exp)
 5060 {
 5061         uint32_t *tl, maxcnt, notify[NFSV4_NOTIFYBITMAP];
 5062         int cnt, devaddrlen, error = 0, i, layouttype;
 5063         char devid[NFSX_V4DEVICEID], *devaddr;
 5064         time_t dev_time;
 5065 
 5066         if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
 5067                 nd->nd_repstat = NFSERR_WRONGSEC;
 5068                 goto nfsmout;
 5069         }
 5070         NFSM_DISSECT(tl, uint32_t *, 3 * NFSX_UNSIGNED + NFSX_V4DEVICEID);
 5071         NFSBCOPY(tl, devid, NFSX_V4DEVICEID);
 5072         tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED);
 5073         layouttype = fxdr_unsigned(int, *tl++);
 5074         maxcnt = fxdr_unsigned(uint32_t, *tl++);
 5075         cnt = fxdr_unsigned(int, *tl);
 5076         NFSD_DEBUG(4, "getdevinfo ltyp=%d maxcnt=%u bitcnt=%d\n", layouttype,
 5077             maxcnt, cnt);
 5078         if (cnt > NFSV4_NOTIFYBITMAP || cnt < 0) {
 5079                 nd->nd_repstat = NFSERR_INVAL;
 5080                 goto nfsmout;
 5081         }
 5082         if (cnt > 0) {
 5083                 NFSM_DISSECT(tl, uint32_t *, cnt * NFSX_UNSIGNED);
 5084                 for (i = 0; i < cnt; i++)
 5085                         notify[i] = fxdr_unsigned(uint32_t, *tl++);
 5086         }
 5087         for (i = cnt; i < NFSV4_NOTIFYBITMAP; i++)
 5088                 notify[i] = 0;
 5089 
 5090         /*
 5091          * Check that the device id is not stale.  Device ids are recreated
 5092          * each time the nfsd threads are restarted.
 5093          */
 5094         NFSBCOPY(devid, &dev_time, sizeof(dev_time));
 5095         if (dev_time != nfsdev_time) {
 5096                 nd->nd_repstat = NFSERR_NOENT;
 5097                 goto nfsmout;
 5098         }
 5099 
 5100         /* Look for the device id. */
 5101         nd->nd_repstat = nfsrv_getdevinfo(devid, layouttype, &maxcnt,
 5102             notify, &devaddrlen, &devaddr);
 5103         NFSD_DEBUG(4, "nfsrv_getdevinfo stat=%u\n", nd->nd_repstat);
 5104         if (nd->nd_repstat == 0) {
 5105                 NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
 5106                 *tl = txdr_unsigned(layouttype);
 5107                 nfsm_strtom(nd, devaddr, devaddrlen);
 5108                 cnt = 0;
 5109                 for (i = 0; i < NFSV4_NOTIFYBITMAP; i++) {
 5110                         if (notify[i] != 0)
 5111                                 cnt = i + 1;
 5112                 }
 5113                 NFSM_BUILD(tl, uint32_t *, (cnt + 1) * NFSX_UNSIGNED);
 5114                 *tl++ = txdr_unsigned(cnt);
 5115                 for (i = 0; i < cnt; i++)
 5116                         *tl++ = txdr_unsigned(notify[i]);
 5117         } else if (nd->nd_repstat == NFSERR_TOOSMALL) {
 5118                 NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
 5119                 *tl = txdr_unsigned(maxcnt);
 5120         }
 5121 nfsmout:
 5122         NFSEXITCODE2(error, nd);
 5123         return (error);
 5124 }
 5125 
 5126 /*
 5127  * nfsv4 test stateid service
 5128  */
 5129 int
 5130 nfsrvd_teststateid(struct nfsrv_descript *nd, __unused int isdgram,
 5131     __unused vnode_t vp, __unused struct nfsexstuff *exp)
 5132 {
 5133         uint32_t *tl;
 5134         nfsv4stateid_t *stateidp = NULL, *tstateidp;
 5135         int cnt, error = 0, i, ret;
 5136         struct thread *p = curthread;
 5137 
 5138         if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
 5139                 nd->nd_repstat = NFSERR_WRONGSEC;
 5140                 goto nfsmout;
 5141         }
 5142         NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
 5143         cnt = fxdr_unsigned(int, *tl);
 5144         if (cnt <= 0 || cnt > 1024) {
 5145                 nd->nd_repstat = NFSERR_BADXDR;
 5146                 goto nfsmout;
 5147         }
 5148         stateidp = mallocarray(cnt, sizeof(nfsv4stateid_t), M_TEMP, M_WAITOK);
 5149         tstateidp = stateidp;
 5150         for (i = 0; i < cnt; i++) {
 5151                 NFSM_DISSECT(tl, uint32_t *, NFSX_STATEID);
 5152                 tstateidp->seqid = fxdr_unsigned(uint32_t, *tl++);
 5153                 NFSBCOPY(tl, tstateidp->other, NFSX_STATEIDOTHER);
 5154                 tstateidp++;
 5155         }
 5156         NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
 5157         *tl = txdr_unsigned(cnt);
 5158         tstateidp = stateidp;
 5159         for (i = 0; i < cnt; i++) {
 5160                 ret = nfsrv_teststateid(nd, tstateidp, p);
 5161                 NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
 5162                 *tl = txdr_unsigned(ret);
 5163                 tstateidp++;
 5164         }
 5165 nfsmout:
 5166         free(stateidp, M_TEMP);
 5167         NFSEXITCODE2(error, nd);
 5168         return (error);
 5169 }
 5170 
 5171 /*
 5172  * nfs allocate service
 5173  */
 5174 int
 5175 nfsrvd_allocate(struct nfsrv_descript *nd, __unused int isdgram,
 5176     vnode_t vp, struct nfsexstuff *exp)
 5177 {
 5178         uint32_t *tl;
 5179         struct nfsvattr forat;
 5180         int error = 0, forat_ret = 1, gotproxystateid;
 5181         off_t off, len;
 5182         struct nfsstate st, *stp = &st;
 5183         struct nfslock lo, *lop = &lo;
 5184         nfsv4stateid_t stateid;
 5185         nfsquad_t clientid;
 5186         nfsattrbit_t attrbits;
 5187 
 5188         if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
 5189                 nd->nd_repstat = NFSERR_WRONGSEC;
 5190                 goto nfsmout;
 5191         }
 5192         gotproxystateid = 0;
 5193         NFSM_DISSECT(tl, uint32_t *, NFSX_STATEID + 2 * NFSX_HYPER);
 5194         stp->ls_flags = (NFSLCK_CHECK | NFSLCK_WRITEACCESS);
 5195         lop->lo_flags = NFSLCK_WRITE;
 5196         stp->ls_ownerlen = 0;
 5197         stp->ls_op = NULL;
 5198         stp->ls_uid = nd->nd_cred->cr_uid;
 5199         stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++);
 5200         clientid.lval[0] = stp->ls_stateid.other[0] = *tl++;
 5201         clientid.lval[1] = stp->ls_stateid.other[1] = *tl++;
 5202         if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) {
 5203                 if ((nd->nd_flag & ND_NFSV41) != 0)
 5204                         clientid.qval = nd->nd_clientid.qval;
 5205                 else if (nd->nd_clientid.qval != clientid.qval)
 5206                         printf("EEK2 multiple clids\n");
 5207         } else {
 5208                 if ((nd->nd_flag & ND_NFSV41) != 0)
 5209                         printf("EEK! no clientid from session\n");
 5210                 nd->nd_flag |= ND_IMPLIEDCLID;
 5211                 nd->nd_clientid.qval = clientid.qval;
 5212         }
 5213         stp->ls_stateid.other[2] = *tl++;
 5214         /*
 5215          * Don't allow this to be done for a DS.
 5216          */
 5217         if ((nd->nd_flag & ND_DSSERVER) != 0)
 5218                 nd->nd_repstat = NFSERR_NOTSUPP;
 5219         /* However, allow the proxy stateid. */
 5220         if (stp->ls_stateid.seqid == 0xffffffff &&
 5221             stp->ls_stateid.other[0] == 0x55555555 &&
 5222             stp->ls_stateid.other[1] == 0x55555555 &&
 5223             stp->ls_stateid.other[2] == 0x55555555)
 5224                 gotproxystateid = 1;
 5225         off = fxdr_hyper(tl); tl += 2;
 5226         lop->lo_first = off;
 5227         len = fxdr_hyper(tl);
 5228         lop->lo_end = off + len;
 5229         /*
 5230          * Paranoia, just in case it wraps around, which shouldn't
 5231          * ever happen anyhow.
 5232          */
 5233         if (nd->nd_repstat == 0 && (lop->lo_end < lop->lo_first || len <= 0))
 5234                 nd->nd_repstat = NFSERR_INVAL;
 5235 
 5236         if (nd->nd_repstat == 0 && vnode_vtype(vp) != VREG)
 5237                 nd->nd_repstat = NFSERR_WRONGTYPE;
 5238         NFSZERO_ATTRBIT(&attrbits);
 5239         NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_OWNER);
 5240         forat_ret = nfsvno_getattr(vp, &forat, nd, curthread, 1, &attrbits);
 5241         if (nd->nd_repstat == 0)
 5242                 nd->nd_repstat = forat_ret;
 5243         if (nd->nd_repstat == 0 && (forat.na_uid != nd->nd_cred->cr_uid ||
 5244              NFSVNO_EXSTRICTACCESS(exp)))
 5245                 nd->nd_repstat = nfsvno_accchk(vp, VWRITE, nd->nd_cred, exp,
 5246                     curthread, NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED,
 5247                     NULL);
 5248         if (nd->nd_repstat == 0 && gotproxystateid == 0)
 5249                 nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid,
 5250                     &stateid, exp, nd, curthread);
 5251 
 5252         if (nd->nd_repstat == 0)
 5253                 nd->nd_repstat = nfsvno_allocate(vp, off, len, nd->nd_cred,
 5254                     curthread);
 5255         vput(vp);
 5256         NFSEXITCODE2(0, nd);
 5257         return (0);
 5258 nfsmout:
 5259         vput(vp);
 5260         NFSEXITCODE2(error, nd);
 5261         return (error);
 5262 }
 5263 
 5264 /*
 5265  * nfs copy service
 5266  */
 5267 int
 5268 nfsrvd_copy_file_range(struct nfsrv_descript *nd, __unused int isdgram,
 5269     vnode_t vp, vnode_t tovp, struct nfsexstuff *exp, struct nfsexstuff *toexp)
 5270 {
 5271         uint32_t *tl;
 5272         struct nfsvattr at;
 5273         int cnt, error = 0, ret;
 5274         off_t inoff, outoff;
 5275         uint64_t len;
 5276         size_t xfer;
 5277         struct nfsstate inst, outst, *instp = &inst, *outstp = &outst;
 5278         struct nfslock inlo, outlo, *inlop = &inlo, *outlop = &outlo;
 5279         nfsquad_t clientid;
 5280         nfsv4stateid_t stateid;
 5281         nfsattrbit_t attrbits;
 5282         void *rl_rcookie, *rl_wcookie;
 5283 
 5284         rl_rcookie = rl_wcookie = NULL;
 5285         if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
 5286                 nd->nd_repstat = NFSERR_WRONGSEC;
 5287                 goto nfsmout;
 5288         }
 5289         if (nfsrv_devidcnt > 0) {
 5290                 /*
 5291                  * For a pNFS server, reply NFSERR_NOTSUPP so that the client
 5292                  * will do the copy via I/O on the DS(s).
 5293                  */
 5294                 nd->nd_repstat = NFSERR_NOTSUPP;
 5295                 goto nfsmout;
 5296         }
 5297         if (vp == tovp) {
 5298                 /* Copying a byte range within the same file is not allowed. */
 5299                 nd->nd_repstat = NFSERR_INVAL;
 5300                 goto nfsmout;
 5301         }
 5302         NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_STATEID + 3 * NFSX_HYPER +
 5303             3 * NFSX_UNSIGNED);
 5304         instp->ls_flags = (NFSLCK_CHECK | NFSLCK_READACCESS);
 5305         inlop->lo_flags = NFSLCK_READ;
 5306         instp->ls_ownerlen = 0;
 5307         instp->ls_op = NULL;
 5308         instp->ls_uid = nd->nd_cred->cr_uid;
 5309         instp->ls_stateid.seqid = fxdr_unsigned(uint32_t, *tl++);
 5310         clientid.lval[0] = instp->ls_stateid.other[0] = *tl++;
 5311         clientid.lval[1] = instp->ls_stateid.other[1] = *tl++;
 5312         if ((nd->nd_flag & ND_IMPLIEDCLID) != 0)
 5313                 clientid.qval = nd->nd_clientid.qval;
 5314         instp->ls_stateid.other[2] = *tl++;
 5315         outstp->ls_flags = (NFSLCK_CHECK | NFSLCK_WRITEACCESS);
 5316         outlop->lo_flags = NFSLCK_WRITE;
 5317         outstp->ls_ownerlen = 0;
 5318         outstp->ls_op = NULL;
 5319         outstp->ls_uid = nd->nd_cred->cr_uid;
 5320         outstp->ls_stateid.seqid = fxdr_unsigned(uint32_t, *tl++);
 5321         outstp->ls_stateid.other[0] = *tl++;
 5322         outstp->ls_stateid.other[1] = *tl++;
 5323         outstp->ls_stateid.other[2] = *tl++;
 5324         inoff = fxdr_hyper(tl); tl += 2;
 5325         inlop->lo_first = inoff;
 5326         outoff = fxdr_hyper(tl); tl += 2;
 5327         outlop->lo_first = outoff;
 5328         len = fxdr_hyper(tl); tl += 2;
 5329         if (len == 0) {
 5330                 /* len == 0 means to EOF. */
 5331                 inlop->lo_end = OFF_MAX;
 5332                 outlop->lo_end = OFF_MAX;
 5333         } else {
 5334                 inlop->lo_end = inlop->lo_first + len;
 5335                 outlop->lo_end = outlop->lo_first + len;
 5336         }
 5337 
 5338         /*
 5339          * At this time only consecutive, synchronous copy is supported,
 5340          * so ca_consecutive and ca_synchronous can be ignored.
 5341          */
 5342         tl += 2;
 5343 
 5344         cnt = fxdr_unsigned(int, *tl);
 5345         if ((nd->nd_flag & ND_DSSERVER) != 0 || cnt != 0)
 5346                 nd->nd_repstat = NFSERR_NOTSUPP;
 5347         if (nd->nd_repstat == 0 && (inoff > OFF_MAX || outoff > OFF_MAX ||
 5348             inlop->lo_end > OFF_MAX || outlop->lo_end > OFF_MAX ||
 5349             inlop->lo_end < inlop->lo_first || outlop->lo_end <
 5350             outlop->lo_first))
 5351                 nd->nd_repstat = NFSERR_INVAL;
 5352 
 5353         if (nd->nd_repstat == 0 && vnode_vtype(vp) != VREG)
 5354                 nd->nd_repstat = NFSERR_WRONGTYPE;
 5355 
 5356         /* Check permissions for the input file. */
 5357         NFSZERO_ATTRBIT(&attrbits);
 5358         NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_OWNER);
 5359         ret = nfsvno_getattr(vp, &at, nd, curthread, 1, &attrbits);
 5360         if (nd->nd_repstat == 0)
 5361                 nd->nd_repstat = ret;
 5362         if (nd->nd_repstat == 0 && (at.na_uid != nd->nd_cred->cr_uid ||
 5363              NFSVNO_EXSTRICTACCESS(exp)))
 5364                 nd->nd_repstat = nfsvno_accchk(vp, VREAD, nd->nd_cred, exp,
 5365                     curthread, NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED,
 5366                     NULL);
 5367         if (nd->nd_repstat == 0)
 5368                 nd->nd_repstat = nfsrv_lockctrl(vp, &instp, &inlop, NULL,
 5369                     clientid, &stateid, exp, nd, curthread);
 5370         NFSVOPUNLOCK(vp);
 5371         if (nd->nd_repstat != 0)
 5372                 goto out;
 5373 
 5374         error = NFSVOPLOCK(tovp, LK_SHARED);
 5375         if (error != 0)
 5376                 goto out;
 5377         if (vnode_vtype(tovp) != VREG)
 5378                 nd->nd_repstat = NFSERR_WRONGTYPE;
 5379 
 5380         /* For the output file, we only need the Owner attribute. */
 5381         ret = nfsvno_getattr(tovp, &at, nd, curthread, 1, &attrbits);
 5382         if (nd->nd_repstat == 0)
 5383                 nd->nd_repstat = ret;
 5384         if (nd->nd_repstat == 0 && (at.na_uid != nd->nd_cred->cr_uid ||
 5385              NFSVNO_EXSTRICTACCESS(exp)))
 5386                 nd->nd_repstat = nfsvno_accchk(tovp, VWRITE, nd->nd_cred, toexp,
 5387                     curthread, NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED,
 5388                     NULL);
 5389         if (nd->nd_repstat == 0)
 5390                 nd->nd_repstat = nfsrv_lockctrl(tovp, &outstp, &outlop, NULL,
 5391                     clientid, &stateid, toexp, nd, curthread);
 5392         NFSVOPUNLOCK(tovp);
 5393 
 5394         /* Range lock the byte ranges for both invp and outvp. */
 5395         if (nd->nd_repstat == 0) {
 5396                 for (;;) {
 5397                         if (len == 0) {
 5398                                 rl_wcookie = vn_rangelock_wlock(tovp, outoff,
 5399                                     OFF_MAX);
 5400                                 rl_rcookie = vn_rangelock_tryrlock(vp, inoff,
 5401                                     OFF_MAX);
 5402                         } else {
 5403                                 rl_wcookie = vn_rangelock_wlock(tovp, outoff,
 5404                                     outoff + len);
 5405                                 rl_rcookie = vn_rangelock_tryrlock(vp, inoff,
 5406                                     inoff + len);
 5407                         }
 5408                         if (rl_rcookie != NULL)
 5409                                 break;
 5410                         vn_rangelock_unlock(tovp, rl_wcookie);
 5411                         if (len == 0)
 5412                                 rl_rcookie = vn_rangelock_rlock(vp, inoff,
 5413                                     OFF_MAX);
 5414                         else
 5415                                 rl_rcookie = vn_rangelock_rlock(vp, inoff,
 5416                                     inoff + len);
 5417                         vn_rangelock_unlock(vp, rl_rcookie);
 5418                 }
 5419 
 5420                 error = NFSVOPLOCK(vp, LK_SHARED);
 5421                 if (error == 0) {
 5422                         ret = nfsvno_getattr(vp, &at, nd, curthread, 1, NULL);
 5423                         if (ret == 0) {
 5424                                 /*
 5425                                  * Since invp is range locked, na_size should
 5426                                  * not change.
 5427                                  */
 5428                                 if (len == 0 && at.na_size > inoff) {
 5429                                         /*
 5430                                          * If len == 0, set it based on invp's 
 5431                                          * size. If offset is past EOF, just
 5432                                          * leave len == 0.
 5433                                          */
 5434                                         len = at.na_size - inoff;
 5435                                 } else if (nfsrv_linux42server == 0 &&
 5436                                     inoff + len > at.na_size) {
 5437                                         /*
 5438                                          * RFC-7862 says that NFSERR_INVAL must
 5439                                          * be returned when inoff + len exceeds
 5440                                          * the file size, however the NFSv4.2
 5441                                          * Linux client likes to do this, so
 5442                                          * only check if nfsrv_linux42server
 5443                                          * is not set.
 5444                                          */
 5445                                         nd->nd_repstat = NFSERR_INVAL;
 5446                                 }
 5447                         }
 5448                         NFSVOPUNLOCK(vp);
 5449                         if (ret != 0 && nd->nd_repstat == 0)
 5450                                 nd->nd_repstat = ret;
 5451                 } else if (nd->nd_repstat == 0)
 5452                         nd->nd_repstat = error;
 5453         }
 5454 
 5455         /*
 5456          * Do the actual copy to an upper limit of vfs.nfs.maxcopyrange.
 5457          * This limit is applied to ensure that the RPC replies in a
 5458          * reasonable time.
 5459          */
 5460         if (len > nfs_maxcopyrange)
 5461                 xfer = nfs_maxcopyrange;
 5462         else
 5463                 xfer = len;
 5464         if (nd->nd_repstat == 0) {
 5465                 nd->nd_repstat = vn_copy_file_range(vp, &inoff, tovp, &outoff,
 5466                     &xfer, 0, nd->nd_cred, nd->nd_cred, NULL);
 5467                 if (nd->nd_repstat == 0)
 5468                         len = xfer;
 5469         }
 5470 
 5471         /* Unlock the ranges. */
 5472         if (rl_rcookie != NULL)
 5473                 vn_rangelock_unlock(vp, rl_rcookie);
 5474         if (rl_wcookie != NULL)
 5475                 vn_rangelock_unlock(tovp, rl_wcookie);
 5476 
 5477         if (nd->nd_repstat == 0) {
 5478                 NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED + NFSX_HYPER +
 5479                     NFSX_VERF);
 5480                 *tl++ = txdr_unsigned(0);       /* No callback ids. */
 5481                 txdr_hyper(len, tl); tl += 2;
 5482                 *tl++ = txdr_unsigned(NFSWRITE_UNSTABLE);
 5483                 *tl++ = txdr_unsigned(nfsboottime.tv_sec);
 5484                 *tl++ = txdr_unsigned(nfsboottime.tv_usec);
 5485                 *tl++ = newnfs_true;
 5486                 *tl = newnfs_true;
 5487         }
 5488 out:
 5489         vrele(vp);
 5490         vrele(tovp);
 5491         NFSEXITCODE2(error, nd);
 5492         return (error);
 5493 nfsmout:
 5494         vput(vp);
 5495         vrele(tovp);
 5496         NFSEXITCODE2(error, nd);
 5497         return (error);
 5498 }
 5499 
 5500 /*
 5501  * nfs seek service
 5502  */
 5503 int
 5504 nfsrvd_seek(struct nfsrv_descript *nd, __unused int isdgram,
 5505     vnode_t vp, struct nfsexstuff *exp)
 5506 {
 5507         uint32_t *tl;
 5508         struct nfsvattr at;
 5509         int content, error = 0;
 5510         off_t off;
 5511         u_long cmd;
 5512         nfsattrbit_t attrbits;
 5513         bool eof;
 5514 
 5515         if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
 5516                 nd->nd_repstat = NFSERR_WRONGSEC;
 5517                 goto nfsmout;
 5518         }
 5519         NFSM_DISSECT(tl, uint32_t *, NFSX_STATEID + NFSX_HYPER + NFSX_UNSIGNED);
 5520         /* Ignore the stateid for now. */
 5521         tl += (NFSX_STATEID / NFSX_UNSIGNED);
 5522         off = fxdr_hyper(tl); tl += 2;
 5523         content = fxdr_unsigned(int, *tl);
 5524         if (content == NFSV4CONTENT_DATA)
 5525                 cmd = FIOSEEKDATA;
 5526         else if (content == NFSV4CONTENT_HOLE)
 5527                 cmd = FIOSEEKHOLE;
 5528         else
 5529                 nd->nd_repstat = NFSERR_BADXDR;
 5530         if (nd->nd_repstat == 0 && vnode_vtype(vp) == VDIR)
 5531                 nd->nd_repstat = NFSERR_ISDIR;
 5532         if (nd->nd_repstat == 0 && vnode_vtype(vp) != VREG)
 5533                 nd->nd_repstat = NFSERR_WRONGTYPE;
 5534         if (nd->nd_repstat == 0 && off < 0)
 5535                 nd->nd_repstat = NFSERR_NXIO;
 5536         if (nd->nd_repstat == 0) {
 5537                 /* Check permissions for the input file. */
 5538                 NFSZERO_ATTRBIT(&attrbits);
 5539                 NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_OWNER);
 5540                 nd->nd_repstat = nfsvno_getattr(vp, &at, nd, curthread, 1,
 5541                     &attrbits);
 5542         }
 5543         if (nd->nd_repstat == 0 && (at.na_uid != nd->nd_cred->cr_uid ||
 5544              NFSVNO_EXSTRICTACCESS(exp)))
 5545                 nd->nd_repstat = nfsvno_accchk(vp, VREAD, nd->nd_cred, exp,
 5546                     curthread, NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED,
 5547                     NULL);
 5548         if (nd->nd_repstat != 0)
 5549                 goto nfsmout;
 5550 
 5551         /* nfsvno_seek() unlocks and vrele()s the vp. */
 5552         nd->nd_repstat = nfsvno_seek(nd, vp, cmd, &off, content, &eof,
 5553             nd->nd_cred, curthread);
 5554         if (nd->nd_repstat == 0 && eof && content == NFSV4CONTENT_DATA &&
 5555             nfsrv_linux42server != 0)
 5556                 nd->nd_repstat = NFSERR_NXIO;
 5557         if (nd->nd_repstat == 0) {
 5558                 NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED + NFSX_HYPER);
 5559                 if (eof)
 5560                         *tl++ = newnfs_true;
 5561                 else
 5562                         *tl++ = newnfs_false;
 5563                 txdr_hyper(off, tl);
 5564         }
 5565         NFSEXITCODE2(error, nd);
 5566         return (error);
 5567 nfsmout:
 5568         vput(vp);
 5569         NFSEXITCODE2(error, nd);
 5570         return (error);
 5571 }
 5572 
 5573 /*
 5574  * nfs get extended attribute service
 5575  */
 5576 int
 5577 nfsrvd_getxattr(struct nfsrv_descript *nd, __unused int isdgram,
 5578     vnode_t vp, __unused struct nfsexstuff *exp)
 5579 {
 5580         uint32_t *tl;
 5581         struct mbuf *mp = NULL, *mpend = NULL;
 5582         int error, len;
 5583         char *name;
 5584         struct thread *p = curthread;
 5585         uint16_t off;
 5586 
 5587         error = 0;
 5588         if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
 5589                 nd->nd_repstat = NFSERR_WRONGSEC;
 5590                 goto nfsmout;
 5591         }
 5592         NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
 5593         len = fxdr_unsigned(int, *tl);
 5594         if (len <= 0) {
 5595                 nd->nd_repstat = NFSERR_BADXDR;
 5596                 goto nfsmout;
 5597         }
 5598         if (len > EXTATTR_MAXNAMELEN) {
 5599                 nd->nd_repstat = NFSERR_NOXATTR;
 5600                 goto nfsmout;
 5601         }
 5602         name = malloc(len + 1, M_TEMP, M_WAITOK);
 5603         nd->nd_repstat = nfsrv_mtostr(nd, name, len);
 5604         if (nd->nd_repstat == 0)
 5605                 nd->nd_repstat = nfsvno_getxattr(vp, name,
 5606                     nd->nd_maxresp, nd->nd_cred, nd->nd_flag,
 5607                     nd->nd_maxextsiz, p, &mp, &mpend, &len);
 5608         if (nd->nd_repstat == ENOATTR)
 5609                 nd->nd_repstat = NFSERR_NOXATTR;
 5610         else if (nd->nd_repstat == EOPNOTSUPP)
 5611                 nd->nd_repstat = NFSERR_NOTSUPP;
 5612         if (nd->nd_repstat == 0) {
 5613                 NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
 5614                 *tl = txdr_unsigned(len);
 5615                 if (len > 0) {
 5616                         nd->nd_mb->m_next = mp;
 5617                         nd->nd_mb = mpend;
 5618                         if ((mpend->m_flags & M_EXTPG) != 0) {
 5619                                 nd->nd_flag |= ND_EXTPG;
 5620                                 nd->nd_bextpg = mpend->m_epg_npgs - 1;
 5621                                 nd->nd_bpos = (char *)(void *)
 5622                                    PHYS_TO_DMAP(mpend->m_epg_pa[nd->nd_bextpg]);
 5623                                 off = (nd->nd_bextpg == 0) ?
 5624                                     mpend->m_epg_1st_off : 0;
 5625                                 nd->nd_bpos += off + mpend->m_epg_last_len;
 5626                                 nd->nd_bextpgsiz = PAGE_SIZE -
 5627                                     mpend->m_epg_last_len - off;
 5628                         } else
 5629                                 nd->nd_bpos = mtod(mpend, char *) +
 5630                                     mpend->m_len;
 5631                 }
 5632         }
 5633         free(name, M_TEMP);
 5634 
 5635 nfsmout:
 5636         if (nd->nd_repstat == 0)
 5637                 nd->nd_repstat = error;
 5638         vput(vp);
 5639         NFSEXITCODE2(0, nd);
 5640         return (0);
 5641 }
 5642 
 5643 /*
 5644  * nfs set extended attribute service
 5645  */
 5646 int
 5647 nfsrvd_setxattr(struct nfsrv_descript *nd, __unused int isdgram,
 5648     vnode_t vp, __unused struct nfsexstuff *exp)
 5649 {
 5650         uint32_t *tl;
 5651         struct nfsvattr ova, nva;
 5652         nfsattrbit_t attrbits;
 5653         int error, len, opt;
 5654         char *name;
 5655         size_t siz;
 5656         struct thread *p = curthread;
 5657 
 5658         error = 0;
 5659         name = NULL;
 5660         if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
 5661                 nd->nd_repstat = NFSERR_WRONGSEC;
 5662                 goto nfsmout;
 5663         }
 5664         NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 5665         opt = fxdr_unsigned(int, *tl++);
 5666         len = fxdr_unsigned(int, *tl);
 5667         if (len <= 0) {
 5668                 nd->nd_repstat = NFSERR_BADXDR;
 5669                 goto nfsmout;
 5670         }
 5671         if (len > EXTATTR_MAXNAMELEN) {
 5672                 nd->nd_repstat = NFSERR_NOXATTR;
 5673                 goto nfsmout;
 5674         }
 5675         name = malloc(len + 1, M_TEMP, M_WAITOK);
 5676         error = nfsrv_mtostr(nd, name, len);
 5677         if (error != 0)
 5678                 goto nfsmout;
 5679         NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
 5680         len = fxdr_unsigned(int, *tl);
 5681         if (len < 0 || len > IOSIZE_MAX) {
 5682                 nd->nd_repstat = NFSERR_XATTR2BIG;
 5683                 goto nfsmout;
 5684         }
 5685         switch (opt) {
 5686         case NFSV4SXATTR_CREATE:
 5687                 error = VOP_GETEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, NULL,
 5688                     &siz, nd->nd_cred, p);
 5689                 if (error != ENOATTR)
 5690                         nd->nd_repstat = NFSERR_EXIST;
 5691                 error = 0;
 5692                 break;
 5693         case NFSV4SXATTR_REPLACE:
 5694                 error = VOP_GETEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, NULL,
 5695                     &siz, nd->nd_cred, p);
 5696                 if (error != 0)
 5697                         nd->nd_repstat = NFSERR_NOXATTR;
 5698                 break;
 5699         case NFSV4SXATTR_EITHER