xref: /freebsd/sys/fs/nfsserver/nfs_nfsdsocket.c (revision c59e4cc3)
19ec7b004SRick Macklem /*-
29ec7b004SRick Macklem  * Copyright (c) 1989, 1993
39ec7b004SRick Macklem  *	The Regents of the University of California.  All rights reserved.
49ec7b004SRick Macklem  *
59ec7b004SRick Macklem  * This code is derived from software contributed to Berkeley by
69ec7b004SRick Macklem  * Rick Macklem at The University of Guelph.
79ec7b004SRick Macklem  *
89ec7b004SRick Macklem  * Redistribution and use in source and binary forms, with or without
99ec7b004SRick Macklem  * modification, are permitted provided that the following conditions
109ec7b004SRick Macklem  * are met:
119ec7b004SRick Macklem  * 1. Redistributions of source code must retain the above copyright
129ec7b004SRick Macklem  *    notice, this list of conditions and the following disclaimer.
139ec7b004SRick Macklem  * 2. Redistributions in binary form must reproduce the above copyright
149ec7b004SRick Macklem  *    notice, this list of conditions and the following disclaimer in the
159ec7b004SRick Macklem  *    documentation and/or other materials provided with the distribution.
169ec7b004SRick Macklem  * 4. Neither the name of the University nor the names of its contributors
179ec7b004SRick Macklem  *    may be used to endorse or promote products derived from this software
189ec7b004SRick Macklem  *    without specific prior written permission.
199ec7b004SRick Macklem  *
209ec7b004SRick Macklem  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
219ec7b004SRick Macklem  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
229ec7b004SRick Macklem  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
239ec7b004SRick Macklem  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
249ec7b004SRick Macklem  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
259ec7b004SRick Macklem  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
269ec7b004SRick Macklem  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
279ec7b004SRick Macklem  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
289ec7b004SRick Macklem  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
299ec7b004SRick Macklem  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
309ec7b004SRick Macklem  * SUCH DAMAGE.
319ec7b004SRick Macklem  *
329ec7b004SRick Macklem  */
339ec7b004SRick Macklem 
349ec7b004SRick Macklem #include <sys/cdefs.h>
359ec7b004SRick Macklem __FBSDID("$FreeBSD$");
369ec7b004SRick Macklem 
379ec7b004SRick Macklem /*
389ec7b004SRick Macklem  * Socket operations for use by the nfs server.
399ec7b004SRick Macklem  */
409ec7b004SRick Macklem 
419ec7b004SRick Macklem #ifndef APPLEKEXT
429ec7b004SRick Macklem #include <fs/nfs/nfsport.h>
439ec7b004SRick Macklem 
449ec7b004SRick Macklem extern struct nfsstats newnfsstats;
459ec7b004SRick Macklem extern struct nfsrvfh nfs_pubfh, nfs_rootfh;
469ec7b004SRick Macklem extern int nfs_pubfhset, nfs_rootfhset;
479ec7b004SRick Macklem extern struct nfsv4lock nfsv4rootfs_lock;
489ec7b004SRick Macklem extern struct nfsrv_stablefirst nfsrv_stablefirst;
499ec7b004SRick Macklem extern struct nfsclienthashhead nfsclienthash[NFSCLIENTHASHSIZE];
509ec7b004SRick Macklem extern int nfsrc_floodlevel, nfsrc_tcpsavedreplies;
51c59e4cc3SRick Macklem extern int nfsd_debuglevel;
529ec7b004SRick Macklem NFSV4ROOTLOCKMUTEX;
539ec7b004SRick Macklem NFSSTATESPINLOCK;
549ec7b004SRick Macklem 
559ec7b004SRick Macklem int (*nfsrv3_procs0[NFS_V3NPROCS])(struct nfsrv_descript *,
569ec7b004SRick Macklem     int, vnode_t , NFSPROC_T *, struct nfsexstuff *) = {
579ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
589ec7b004SRick Macklem 	nfsrvd_getattr,
599ec7b004SRick Macklem 	nfsrvd_setattr,
609ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
619ec7b004SRick Macklem 	nfsrvd_access,
629ec7b004SRick Macklem 	nfsrvd_readlink,
639ec7b004SRick Macklem 	nfsrvd_read,
649ec7b004SRick Macklem 	nfsrvd_write,
659ec7b004SRick Macklem 	nfsrvd_create,
669ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
679ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
689ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
699ec7b004SRick Macklem 	nfsrvd_remove,
709ec7b004SRick Macklem 	nfsrvd_remove,
719ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
729ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
739ec7b004SRick Macklem 	nfsrvd_readdir,
749ec7b004SRick Macklem 	nfsrvd_readdirplus,
759ec7b004SRick Macklem 	nfsrvd_statfs,
769ec7b004SRick Macklem 	nfsrvd_fsinfo,
779ec7b004SRick Macklem 	nfsrvd_pathconf,
789ec7b004SRick Macklem 	nfsrvd_commit,
799ec7b004SRick Macklem };
809ec7b004SRick Macklem 
819ec7b004SRick Macklem int (*nfsrv3_procs1[NFS_V3NPROCS])(struct nfsrv_descript *,
829ec7b004SRick Macklem     int, vnode_t , vnode_t *, fhandle_t *,
839ec7b004SRick Macklem     NFSPROC_T *, struct nfsexstuff *) = {
849ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
859ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
869ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
879ec7b004SRick Macklem 	nfsrvd_lookup,
889ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
899ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
909ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
919ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
929ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
939ec7b004SRick Macklem 	nfsrvd_mkdir,
949ec7b004SRick Macklem 	nfsrvd_symlink,
959ec7b004SRick Macklem 	nfsrvd_mknod,
969ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
979ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
989ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
999ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
1009ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
1019ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
1029ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
1039ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
1049ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
1059ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
1069ec7b004SRick Macklem };
1079ec7b004SRick Macklem 
1089ec7b004SRick Macklem int (*nfsrv3_procs2[NFS_V3NPROCS])(struct nfsrv_descript *,
1099ec7b004SRick Macklem     int, vnode_t , vnode_t , NFSPROC_T *,
1109ec7b004SRick Macklem     struct nfsexstuff *, struct nfsexstuff *) = {
1119ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1129ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1139ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1149ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1159ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1169ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1179ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1189ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1199ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1209ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1219ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1229ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1239ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1249ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1259ec7b004SRick Macklem 	nfsrvd_rename,
1269ec7b004SRick Macklem 	nfsrvd_link,
1279ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1289ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1299ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1309ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1319ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1329ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
1339ec7b004SRick Macklem };
1349ec7b004SRick Macklem 
135c59e4cc3SRick Macklem int (*nfsrv4_ops0[NFSV41_NOPS])(struct nfsrv_descript *,
1369ec7b004SRick Macklem     int, vnode_t , NFSPROC_T *, struct nfsexstuff *) = {
1379ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
1389ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
1399ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
1409ec7b004SRick Macklem 	nfsrvd_access,
1419ec7b004SRick Macklem 	nfsrvd_close,
1429ec7b004SRick Macklem 	nfsrvd_commit,
1439ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
1449ec7b004SRick Macklem 	nfsrvd_delegpurge,
1459ec7b004SRick Macklem 	nfsrvd_delegreturn,
1469ec7b004SRick Macklem 	nfsrvd_getattr,
1479ec7b004SRick Macklem 	nfsrvd_getfh,
1489ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
1499ec7b004SRick Macklem 	nfsrvd_lock,
1509ec7b004SRick Macklem 	nfsrvd_lockt,
1519ec7b004SRick Macklem 	nfsrvd_locku,
1529ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
1539ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
1549ec7b004SRick Macklem 	nfsrvd_verify,
1559ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
1569ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
1579ec7b004SRick Macklem 	nfsrvd_openconfirm,
1589ec7b004SRick Macklem 	nfsrvd_opendowngrade,
1599ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
1609ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
1619ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
1629ec7b004SRick Macklem 	nfsrvd_read,
1639ec7b004SRick Macklem 	nfsrvd_readdirplus,
1649ec7b004SRick Macklem 	nfsrvd_readlink,
1659ec7b004SRick Macklem 	nfsrvd_remove,
1669ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
1679ec7b004SRick Macklem 	nfsrvd_renew,
1689ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
1699ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
1709ec7b004SRick Macklem 	nfsrvd_secinfo,
1719ec7b004SRick Macklem 	nfsrvd_setattr,
1729ec7b004SRick Macklem 	nfsrvd_setclientid,
1739ec7b004SRick Macklem 	nfsrvd_setclientidcfrm,
1749ec7b004SRick Macklem 	nfsrvd_verify,
1759ec7b004SRick Macklem 	nfsrvd_write,
1769ec7b004SRick Macklem 	nfsrvd_releaselckown,
177c59e4cc3SRick Macklem 	nfsrvd_notsupp,
178c59e4cc3SRick Macklem 	nfsrvd_notsupp,
179c59e4cc3SRick Macklem 	nfsrvd_exchangeid,
180c59e4cc3SRick Macklem 	nfsrvd_createsession,
181c59e4cc3SRick Macklem 	nfsrvd_destroysession,
182c59e4cc3SRick Macklem 	nfsrvd_freestateid,
183c59e4cc3SRick Macklem 	nfsrvd_notsupp,
184c59e4cc3SRick Macklem 	nfsrvd_notsupp,
185c59e4cc3SRick Macklem 	nfsrvd_notsupp,
186c59e4cc3SRick Macklem 	nfsrvd_notsupp,
187c59e4cc3SRick Macklem 	nfsrvd_notsupp,
188c59e4cc3SRick Macklem 	nfsrvd_notsupp,
189c59e4cc3SRick Macklem 	nfsrvd_notsupp,
190c59e4cc3SRick Macklem 	nfsrvd_sequence,
191c59e4cc3SRick Macklem 	nfsrvd_notsupp,
192c59e4cc3SRick Macklem 	nfsrvd_notsupp,
193c59e4cc3SRick Macklem 	nfsrvd_notsupp,
194c59e4cc3SRick Macklem 	nfsrvd_destroyclientid,
195c59e4cc3SRick Macklem 	nfsrvd_reclaimcomplete,
1969ec7b004SRick Macklem };
1979ec7b004SRick Macklem 
198c59e4cc3SRick Macklem int (*nfsrv4_ops1[NFSV41_NOPS])(struct nfsrv_descript *,
1999ec7b004SRick Macklem     int, vnode_t , vnode_t *, fhandle_t *,
2009ec7b004SRick Macklem     NFSPROC_T *, struct nfsexstuff *) = {
2019ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2029ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2039ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2049ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2059ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2069ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2079ec7b004SRick Macklem 	nfsrvd_mknod,
2089ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2099ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2109ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2119ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2129ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2139ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2149ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2159ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2169ec7b004SRick Macklem 	nfsrvd_lookup,
2179ec7b004SRick Macklem 	nfsrvd_lookup,
2189ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2199ec7b004SRick Macklem 	nfsrvd_open,
2209ec7b004SRick Macklem 	nfsrvd_openattr,
2219ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2229ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2239ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2249ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2259ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2269ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2279ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2289ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2299ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2309ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2319ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2329ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2339ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2349ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2359ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2369ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2379ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2389ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2399ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2409ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
241c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
242c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
243c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
244c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
245c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
246c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
247c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
248c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
249c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
250c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
251c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
252c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
253c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
254c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
255c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
256c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
257c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
258c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
259c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
2609ec7b004SRick Macklem };
2619ec7b004SRick Macklem 
262c59e4cc3SRick Macklem int (*nfsrv4_ops2[NFSV41_NOPS])(struct nfsrv_descript *,
2639ec7b004SRick Macklem     int, vnode_t , vnode_t , NFSPROC_T *,
2649ec7b004SRick Macklem     struct nfsexstuff *, struct nfsexstuff *) = {
2659ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2669ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2679ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2689ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2699ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2709ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2719ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2729ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2739ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2749ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2759ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2769ec7b004SRick Macklem 	nfsrvd_link,
2779ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2789ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2799ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2809ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2819ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2829ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2839ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2849ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2859ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2869ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2879ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2889ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2899ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2909ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2919ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2929ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2939ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2949ec7b004SRick Macklem 	nfsrvd_rename,
2959ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2969ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2979ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2989ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
2999ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
3009ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
3019ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
3029ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
3039ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
3049ec7b004SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
305c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
306c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
307c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
308c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
309c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
310c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
311c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
312c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
313c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
314c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
315c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
316c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
317c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
318c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
319c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
320c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
321c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
322c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
323c59e4cc3SRick Macklem 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
3249ec7b004SRick Macklem };
3259ec7b004SRick Macklem #endif	/* !APPLEKEXT */
3269ec7b004SRick Macklem 
3279ec7b004SRick Macklem /*
3289ec7b004SRick Macklem  * Static array that defines which nfs rpc's are nonidempotent
3299ec7b004SRick Macklem  */
3309ec7b004SRick Macklem static int nfsrv_nonidempotent[NFS_V3NPROCS] = {
3319ec7b004SRick Macklem 	FALSE,
3329ec7b004SRick Macklem 	FALSE,
3339ec7b004SRick Macklem 	TRUE,
3349ec7b004SRick Macklem 	FALSE,
3359ec7b004SRick Macklem 	FALSE,
3369ec7b004SRick Macklem 	FALSE,
3379ec7b004SRick Macklem 	FALSE,
3389ec7b004SRick Macklem 	TRUE,
3399ec7b004SRick Macklem 	TRUE,
3409ec7b004SRick Macklem 	TRUE,
3419ec7b004SRick Macklem 	TRUE,
3429ec7b004SRick Macklem 	TRUE,
3439ec7b004SRick Macklem 	TRUE,
3449ec7b004SRick Macklem 	TRUE,
3459ec7b004SRick Macklem 	TRUE,
3469ec7b004SRick Macklem 	TRUE,
3479ec7b004SRick Macklem 	FALSE,
3489ec7b004SRick Macklem 	FALSE,
3499ec7b004SRick Macklem 	FALSE,
3509ec7b004SRick Macklem 	FALSE,
3519ec7b004SRick Macklem 	FALSE,
3529ec7b004SRick Macklem 	FALSE,
3539ec7b004SRick Macklem };
3549ec7b004SRick Macklem 
3559ec7b004SRick Macklem /*
3569ec7b004SRick Macklem  * This static array indicates whether or not the RPC modifies the
3579ec7b004SRick Macklem  * file system.
3589ec7b004SRick Macklem  */
3599ec7b004SRick Macklem static int nfs_writerpc[NFS_NPROCS] = { 0, 0, 1, 0, 0, 0, 0,
3609ec7b004SRick Macklem     1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
3619ec7b004SRick Macklem     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
3629ec7b004SRick Macklem 
3639ec7b004SRick Macklem /* local functions */
3649ec7b004SRick Macklem static void nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
365c59e4cc3SRick Macklem     u_char *tag, int taglen, u_int32_t minorvers, NFSPROC_T *p);
3669ec7b004SRick Macklem 
3679ec7b004SRick Macklem 
3689ec7b004SRick Macklem /*
3699ec7b004SRick Macklem  * This static array indicates which server procedures require the extra
3709ec7b004SRick Macklem  * arguments to return the current file handle for V2, 3.
3719ec7b004SRick Macklem  */
3729ec7b004SRick Macklem static int nfs_retfh[NFS_V3NPROCS] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1,
3739ec7b004SRick Macklem 	1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0 };
3749ec7b004SRick Macklem 
375c59e4cc3SRick Macklem extern struct nfsv4_opflag nfsv4_opflag[NFSV41_NOPS];
3769ec7b004SRick Macklem 
3779ec7b004SRick Macklem static int nfsv3to4op[NFS_V3NPROCS] = {
3789ec7b004SRick Macklem 	NFSPROC_NULL,
3799ec7b004SRick Macklem 	NFSV4OP_GETATTR,
3809ec7b004SRick Macklem 	NFSV4OP_SETATTR,
3819ec7b004SRick Macklem 	NFSV4OP_LOOKUP,
3829ec7b004SRick Macklem 	NFSV4OP_ACCESS,
3839ec7b004SRick Macklem 	NFSV4OP_READLINK,
3849ec7b004SRick Macklem 	NFSV4OP_READ,
3859ec7b004SRick Macklem 	NFSV4OP_WRITE,
3869ec7b004SRick Macklem 	NFSV4OP_V3CREATE,
3879ec7b004SRick Macklem 	NFSV4OP_MKDIR,
3889ec7b004SRick Macklem 	NFSV4OP_SYMLINK,
3899ec7b004SRick Macklem 	NFSV4OP_MKNOD,
3909ec7b004SRick Macklem 	NFSV4OP_REMOVE,
3919ec7b004SRick Macklem 	NFSV4OP_RMDIR,
3929ec7b004SRick Macklem 	NFSV4OP_RENAME,
3939ec7b004SRick Macklem 	NFSV4OP_LINK,
3949ec7b004SRick Macklem 	NFSV4OP_READDIR,
3959ec7b004SRick Macklem 	NFSV4OP_READDIRPLUS,
3969ec7b004SRick Macklem 	NFSV4OP_FSSTAT,
3979ec7b004SRick Macklem 	NFSV4OP_FSINFO,
3989ec7b004SRick Macklem 	NFSV4OP_PATHCONF,
3999ec7b004SRick Macklem 	NFSV4OP_COMMIT,
4009ec7b004SRick Macklem };
4019ec7b004SRick Macklem 
4029ec7b004SRick Macklem /*
4039ec7b004SRick Macklem  * Do an RPC. Basically, get the file handles translated to vnode pointers
4049ec7b004SRick Macklem  * and then call the appropriate server routine. The server routines are
4059ec7b004SRick Macklem  * split into groups, based on whether they use a file handle or file
4069ec7b004SRick Macklem  * handle plus name or ...
4079ec7b004SRick Macklem  * The NFS V4 Compound RPC is performed separately by nfsrvd_compound().
4089ec7b004SRick Macklem  */
4099ec7b004SRick Macklem APPLESTATIC void
410c59e4cc3SRick Macklem nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, u_char *tag, int taglen,
411c59e4cc3SRick Macklem     u_int32_t minorvers, NFSPROC_T *p)
4129ec7b004SRick Macklem {
41317891d00SRick Macklem 	int error = 0, lktype;
4149ec7b004SRick Macklem 	vnode_t vp;
4159ec7b004SRick Macklem 	mount_t mp = NULL;
4169ec7b004SRick Macklem 	struct nfsrvfh fh;
4179ec7b004SRick Macklem 	struct nfsexstuff nes;
4189ec7b004SRick Macklem 
4199ec7b004SRick Macklem 	/*
4209ec7b004SRick Macklem 	 * Get a locked vnode for the first file handle
4219ec7b004SRick Macklem 	 */
4229ec7b004SRick Macklem 	if (!(nd->nd_flag & ND_NFSV4)) {
423b38f7723SKonstantin Belousov 		KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc"));
4249ec7b004SRick Macklem 		/*
4259ec7b004SRick Macklem 		 * For NFSv3, if the malloc/mget allocation is near limits,
4269ec7b004SRick Macklem 		 * return NFSERR_DELAY.
4279ec7b004SRick Macklem 		 */
4289ec7b004SRick Macklem 		if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) {
4299ec7b004SRick Macklem 			nd->nd_repstat = NFSERR_DELAY;
4309ec7b004SRick Macklem 			vp = NULL;
4319ec7b004SRick Macklem 		} else {
4329ec7b004SRick Macklem 			error = nfsrv_mtofh(nd, &fh);
4339ec7b004SRick Macklem 			if (error) {
4349ec7b004SRick Macklem 				if (error != EBADRPC)
4359ec7b004SRick Macklem 					printf("nfs dorpc err1=%d\n", error);
4369ec7b004SRick Macklem 				nd->nd_repstat = NFSERR_GARBAGE;
437a9285ae5SZack Kirsch 				goto out;
4389ec7b004SRick Macklem 			}
43917891d00SRick Macklem 			if (nd->nd_procnum == NFSPROC_READ ||
440d96b98a3SKenneth D. Merry 			    nd->nd_procnum == NFSPROC_WRITE ||
44117891d00SRick Macklem 			    nd->nd_procnum == NFSPROC_READDIR ||
44217891d00SRick Macklem 			    nd->nd_procnum == NFSPROC_READLINK ||
44317891d00SRick Macklem 			    nd->nd_procnum == NFSPROC_GETATTR ||
44417891d00SRick Macklem 			    nd->nd_procnum == NFSPROC_ACCESS)
44517891d00SRick Macklem 				lktype = LK_SHARED;
44617891d00SRick Macklem 			else
44717891d00SRick Macklem 				lktype = LK_EXCLUSIVE;
4489ec7b004SRick Macklem 			if (nd->nd_flag & ND_PUBLOOKUP)
44917891d00SRick Macklem 				nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes,
4509ec7b004SRick Macklem 				    &mp, nfs_writerpc[nd->nd_procnum], p);
4519ec7b004SRick Macklem 			else
45217891d00SRick Macklem 				nfsd_fhtovp(nd, &fh, lktype, &vp, &nes,
4539ec7b004SRick Macklem 				    &mp, nfs_writerpc[nd->nd_procnum], p);
4549ec7b004SRick Macklem 			if (nd->nd_repstat == NFSERR_PROGNOTV4)
455a9285ae5SZack Kirsch 				goto out;
4569ec7b004SRick Macklem 		}
4579ec7b004SRick Macklem 	}
4589ec7b004SRick Macklem 
4599ec7b004SRick Macklem 	/*
4609ec7b004SRick Macklem 	 * For V2 and 3, set the ND_SAVEREPLY flag for the recent request
4619ec7b004SRick Macklem 	 * cache, as required.
4629ec7b004SRick Macklem 	 * For V4, nfsrvd_compound() does this.
4639ec7b004SRick Macklem 	 */
4649ec7b004SRick Macklem 	if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum])
4659ec7b004SRick Macklem 		nd->nd_flag |= ND_SAVEREPLY;
4669ec7b004SRick Macklem 
4679ec7b004SRick Macklem 	nfsrvd_rephead(nd);
4689ec7b004SRick Macklem 	/*
4699ec7b004SRick Macklem 	 * If nd_repstat is non-zero, just fill in the reply status
4709ec7b004SRick Macklem 	 * to complete the RPC reply for V2. Otherwise, you must do
4719ec7b004SRick Macklem 	 * the RPC.
4729ec7b004SRick Macklem 	 */
4739ec7b004SRick Macklem 	if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) {
4749ec7b004SRick Macklem 		*nd->nd_errp = nfsd_errmap(nd);
4759ec7b004SRick Macklem 		NFSINCRGLOBAL(newnfsstats.srvrpccnt[nfsv3to4op[nd->nd_procnum]]);
4768974bc2fSRick Macklem 		if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0)
4778974bc2fSRick Macklem 			vn_finished_write(mp);
478a9285ae5SZack Kirsch 		goto out;
4799ec7b004SRick Macklem 	}
4809ec7b004SRick Macklem 
4819ec7b004SRick Macklem 	/*
4829ec7b004SRick Macklem 	 * Now the procedure can be performed. For V4, nfsrvd_compound()
4839ec7b004SRick Macklem 	 * works through the sub-rpcs, otherwise just call the procedure.
4849ec7b004SRick Macklem 	 * The procedures are in three groups with different arguments.
4859ec7b004SRick Macklem 	 * The group is indicated by the value in nfs_retfh[].
4869ec7b004SRick Macklem 	 */
4879ec7b004SRick Macklem 	if (nd->nd_flag & ND_NFSV4) {
488c59e4cc3SRick Macklem 		nfsrvd_compound(nd, isdgram, tag, taglen, minorvers, p);
4899ec7b004SRick Macklem 	} else {
4909ec7b004SRick Macklem 		if (nfs_retfh[nd->nd_procnum] == 1) {
4919ec7b004SRick Macklem 			if (vp)
492c383087cSZack Kirsch 				NFSVOPUNLOCK(vp, 0);
4939ec7b004SRick Macklem 			error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram,
4949ec7b004SRick Macklem 			    vp, NULL, (fhandle_t *)fh.nfsrvfh_data, p, &nes);
4959ec7b004SRick Macklem 		} else if (nfs_retfh[nd->nd_procnum] == 2) {
4969ec7b004SRick Macklem 			error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram,
4979ec7b004SRick Macklem 			    vp, NULL, p, &nes, NULL);
4989ec7b004SRick Macklem 		} else {
4999ec7b004SRick Macklem 			error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
5009ec7b004SRick Macklem 			    vp, p, &nes);
5019ec7b004SRick Macklem 		}
5028974bc2fSRick Macklem 		if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0)
5038974bc2fSRick Macklem 			vn_finished_write(mp);
5049ec7b004SRick Macklem 		NFSINCRGLOBAL(newnfsstats.srvrpccnt[nfsv3to4op[nd->nd_procnum]]);
5059ec7b004SRick Macklem 	}
5069ec7b004SRick Macklem 	if (error) {
5079ec7b004SRick Macklem 		if (error != EBADRPC)
5089ec7b004SRick Macklem 			printf("nfs dorpc err2=%d\n", error);
5099ec7b004SRick Macklem 		nd->nd_repstat = NFSERR_GARBAGE;
5109ec7b004SRick Macklem 	}
5119ec7b004SRick Macklem 	*nd->nd_errp = nfsd_errmap(nd);
5129ec7b004SRick Macklem 
5139ec7b004SRick Macklem 	/*
5149ec7b004SRick Macklem 	 * Don't cache certain reply status values.
5159ec7b004SRick Macklem 	 */
5169ec7b004SRick Macklem 	if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) &&
5179ec7b004SRick Macklem 	    (nd->nd_repstat == NFSERR_GARBAGE ||
5189ec7b004SRick Macklem 	     nd->nd_repstat == NFSERR_BADXDR ||
5199ec7b004SRick Macklem 	     nd->nd_repstat == NFSERR_MOVED ||
5209ec7b004SRick Macklem 	     nd->nd_repstat == NFSERR_DELAY ||
5219ec7b004SRick Macklem 	     nd->nd_repstat == NFSERR_BADSEQID ||
5229ec7b004SRick Macklem 	     nd->nd_repstat == NFSERR_RESOURCE ||
5239ec7b004SRick Macklem 	     nd->nd_repstat == NFSERR_SERVERFAULT ||
5249ec7b004SRick Macklem 	     nd->nd_repstat == NFSERR_STALECLIENTID ||
5259ec7b004SRick Macklem 	     nd->nd_repstat == NFSERR_STALESTATEID ||
5269ec7b004SRick Macklem 	     nd->nd_repstat == NFSERR_OLDSTATEID ||
5279ec7b004SRick Macklem 	     nd->nd_repstat == NFSERR_BADSTATEID ||
5289ec7b004SRick Macklem 	     nd->nd_repstat == NFSERR_GRACE ||
5299ec7b004SRick Macklem 	     nd->nd_repstat == NFSERR_NOGRACE))
5309ec7b004SRick Macklem 		nd->nd_flag &= ~ND_SAVEREPLY;
531a9285ae5SZack Kirsch 
532a9285ae5SZack Kirsch out:
533a9285ae5SZack Kirsch 	NFSEXITCODE2(0, nd);
5349ec7b004SRick Macklem }
5359ec7b004SRick Macklem 
5369ec7b004SRick Macklem /*
5379ec7b004SRick Macklem  * Breaks down a compound RPC request and calls the server routines for
5389ec7b004SRick Macklem  * the subprocedures.
5399ec7b004SRick Macklem  * Some suboperations are performed directly here to simplify file handle<-->
5409ec7b004SRick Macklem  * vnode pointer handling.
5419ec7b004SRick Macklem  */
5429ec7b004SRick Macklem static void
543c59e4cc3SRick Macklem nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,
544c59e4cc3SRick Macklem     int taglen, u_int32_t minorvers, NFSPROC_T *p)
5459ec7b004SRick Macklem {
546c59e4cc3SRick Macklem 	int i, op, op0 = 0;
5479ec7b004SRick Macklem 	u_int32_t *tl;
5489ec7b004SRick Macklem 	struct nfsclient *clp, *nclp;
549c59e4cc3SRick Macklem 	int numops, error = 0, igotlock;
550c59e4cc3SRick Macklem 	u_int32_t retops = 0, *retopsp = NULL, *repp;
5519ec7b004SRick Macklem 	vnode_t vp, nvp, savevp;
5529ec7b004SRick Macklem 	struct nfsrvfh fh;
5538974bc2fSRick Macklem 	mount_t new_mp, temp_mp = NULL;
5549ec7b004SRick Macklem 	struct ucred *credanon;
5559ec7b004SRick Macklem 	struct nfsexstuff nes, vpnes, savevpnes;
5568974bc2fSRick Macklem 	fsid_t cur_fsid, save_fsid;
5579ec7b004SRick Macklem 	static u_int64_t compref = 0;
5589ec7b004SRick Macklem 
5599ec7b004SRick Macklem 	NFSVNO_EXINIT(&vpnes);
5609ec7b004SRick Macklem 	NFSVNO_EXINIT(&savevpnes);
5619ec7b004SRick Macklem 	/*
5629ec7b004SRick Macklem 	 * Put the seq# of the current compound RPC in nfsrv_descript.
5639ec7b004SRick Macklem 	 * (This is used by nfsrv_checkgetattr(), to see if the write
5649ec7b004SRick Macklem 	 *  delegation was created by the same compound RPC as the one
5659ec7b004SRick Macklem 	 *  with that Getattr in it.)
5669ec7b004SRick Macklem 	 * Don't worry about the 64bit number wrapping around. It ain't
5679ec7b004SRick Macklem 	 * gonna happen before this server gets shut down/rebooted.
5689ec7b004SRick Macklem 	 */
5699ec7b004SRick Macklem 	nd->nd_compref = compref++;
5709ec7b004SRick Macklem 
5719ec7b004SRick Macklem 	/*
5729ec7b004SRick Macklem 	 * Check for and optionally get a lock on the root. This lock means that
5739ec7b004SRick Macklem 	 * no nfsd will be fiddling with the V4 file system and state stuff. It
5749ec7b004SRick Macklem 	 * is required when the V4 root is being changed, the stable storage
5759ec7b004SRick Macklem 	 * restart file is being updated, or callbacks are being done.
5769ec7b004SRick Macklem 	 * When any of the nfsd are processing an NFSv4 compound RPC, they must
5779ec7b004SRick Macklem 	 * either hold a reference count (nfs_usecnt) or the lock. When
5789ec7b004SRick Macklem 	 * nfsrv_unlock() is called to release the lock, it can optionally
5799ec7b004SRick Macklem 	 * also get a reference count, which saves the need for a call to
5809ec7b004SRick Macklem 	 * nfsrv_getref() after nfsrv_unlock().
5819ec7b004SRick Macklem 	 */
5829ec7b004SRick Macklem 	/*
5839ec7b004SRick Macklem 	 * First, check to see if we need to wait for an update lock.
5849ec7b004SRick Macklem 	 */
5859ec7b004SRick Macklem 	igotlock = 0;
5869ec7b004SRick Macklem 	NFSLOCKV4ROOTMUTEX();
5879ec7b004SRick Macklem 	if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK)
5889ec7b004SRick Macklem 		igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
589ff29f3b2SRick Macklem 		    NFSV4ROOTLOCKMUTEXPTR, NULL);
5909ec7b004SRick Macklem 	else
5919ec7b004SRick Macklem 		igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
592ff29f3b2SRick Macklem 		    NFSV4ROOTLOCKMUTEXPTR, NULL);
5939ec7b004SRick Macklem 	NFSUNLOCKV4ROOTMUTEX();
5949ec7b004SRick Macklem 	if (igotlock) {
5959ec7b004SRick Macklem 		/*
5969ec7b004SRick Macklem 		 * If I got the lock, I can update the stable storage file.
5979ec7b004SRick Macklem 		 * Done when the grace period is over or a client has long
5989ec7b004SRick Macklem 		 * since expired.
5999ec7b004SRick Macklem 		 */
6009ec7b004SRick Macklem 		nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK;
6019ec7b004SRick Macklem 		if ((nfsrv_stablefirst.nsf_flags &
6029ec7b004SRick Macklem 		    (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
6039ec7b004SRick Macklem 			nfsrv_updatestable(p);
6049ec7b004SRick Macklem 
6059ec7b004SRick Macklem 		/*
6069ec7b004SRick Macklem 		 * If at least one client has long since expired, search
6079ec7b004SRick Macklem 		 * the client list for them, write a REVOKE record on the
6089ec7b004SRick Macklem 		 * stable storage file and then remove them from the client
6099ec7b004SRick Macklem 		 * list.
6109ec7b004SRick Macklem 		 */
6119ec7b004SRick Macklem 		if (nfsrv_stablefirst.nsf_flags & NFSNSF_EXPIREDCLIENT) {
6129ec7b004SRick Macklem 			nfsrv_stablefirst.nsf_flags &= ~NFSNSF_EXPIREDCLIENT;
6139ec7b004SRick Macklem 			for (i = 0; i < NFSCLIENTHASHSIZE; i++) {
6149ec7b004SRick Macklem 			    LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash,
6159ec7b004SRick Macklem 				nclp) {
6169ec7b004SRick Macklem 				if (clp->lc_flags & LCL_EXPIREIT) {
6179ec7b004SRick Macklem 				    if (!LIST_EMPTY(&clp->lc_open) ||
6189ec7b004SRick Macklem 					!LIST_EMPTY(&clp->lc_deleg))
6199ec7b004SRick Macklem 					nfsrv_writestable(clp->lc_id,
6209ec7b004SRick Macklem 					    clp->lc_idlen, NFSNST_REVOKE, p);
6219ec7b004SRick Macklem 				    nfsrv_cleanclient(clp, p);
6229ec7b004SRick Macklem 				    nfsrv_freedeleglist(&clp->lc_deleg);
6239ec7b004SRick Macklem 				    nfsrv_freedeleglist(&clp->lc_olddeleg);
6249ec7b004SRick Macklem 				    LIST_REMOVE(clp, lc_hash);
6259ec7b004SRick Macklem 				    nfsrv_zapclient(clp, p);
6269ec7b004SRick Macklem 				}
6279ec7b004SRick Macklem 			    }
6289ec7b004SRick Macklem 			}
6299ec7b004SRick Macklem 		}
6309ec7b004SRick Macklem 		NFSLOCKV4ROOTMUTEX();
6319ec7b004SRick Macklem 		nfsv4_unlock(&nfsv4rootfs_lock, 1);
6329ec7b004SRick Macklem 		NFSUNLOCKV4ROOTMUTEX();
6339ec7b004SRick Macklem 	} else {
6349ec7b004SRick Macklem 		/*
6359ec7b004SRick Macklem 		 * If we didn't get the lock, we need to get a refcnt,
6369ec7b004SRick Macklem 		 * which also checks for and waits for the lock.
6379ec7b004SRick Macklem 		 */
6389ec7b004SRick Macklem 		NFSLOCKV4ROOTMUTEX();
6399ec7b004SRick Macklem 		nfsv4_getref(&nfsv4rootfs_lock, NULL,
640ff29f3b2SRick Macklem 		    NFSV4ROOTLOCKMUTEXPTR, NULL);
6419ec7b004SRick Macklem 		NFSUNLOCKV4ROOTMUTEX();
6429ec7b004SRick Macklem 	}
6439ec7b004SRick Macklem 
6449ec7b004SRick Macklem 	/*
6459ec7b004SRick Macklem 	 * If flagged, search for open owners that haven't had any opens
6469ec7b004SRick Macklem 	 * for a long time.
6479ec7b004SRick Macklem 	 */
6489ec7b004SRick Macklem 	if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) {
6499ec7b004SRick Macklem 		nfsrv_throwawayopens(p);
6509ec7b004SRick Macklem 	}
6519ec7b004SRick Macklem 
6529ec7b004SRick Macklem 	savevp = vp = NULL;
6538974bc2fSRick Macklem 	save_fsid.val[0] = save_fsid.val[1] = 0;
6548974bc2fSRick Macklem 	cur_fsid.val[0] = cur_fsid.val[1] = 0;
655c59e4cc3SRick Macklem 
656c59e4cc3SRick Macklem 	/* If taglen < 0, there was a parsing error in nfsd_getminorvers(). */
6579ec7b004SRick Macklem 	if (taglen < 0) {
6589ec7b004SRick Macklem 		error = EBADRPC;
6599ec7b004SRick Macklem 		goto nfsmout;
6609ec7b004SRick Macklem 	}
661c59e4cc3SRick Macklem 
6629ec7b004SRick Macklem 	(void) nfsm_strtom(nd, tag, taglen);
6639ec7b004SRick Macklem 	NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED);
664c59e4cc3SRick Macklem 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
665c59e4cc3SRick Macklem 	if (minorvers != NFSV4_MINORVERSION && minorvers != NFSV41_MINORVERSION)
6669ec7b004SRick Macklem 		nd->nd_repstat = NFSERR_MINORVERMISMATCH;
6679ec7b004SRick Macklem 	if (nd->nd_repstat)
6689ec7b004SRick Macklem 		numops = 0;
6699ec7b004SRick Macklem 	else
6709ec7b004SRick Macklem 		numops = fxdr_unsigned(int, *tl);
6719ec7b004SRick Macklem 	/*
6729ec7b004SRick Macklem 	 * Loop around doing the sub ops.
6739ec7b004SRick Macklem 	 * vp - is an unlocked vnode pointer for the CFH
6749ec7b004SRick Macklem 	 * savevp - is an unlocked vnode pointer for the SAVEDFH
6759ec7b004SRick Macklem 	 * (at some future date, it might turn out to be more appropriate
6769ec7b004SRick Macklem 	 *  to keep the file handles instead of vnode pointers?)
6779ec7b004SRick Macklem 	 * savevpnes and vpnes - are the export flags for the above.
6789ec7b004SRick Macklem 	 */
6799ec7b004SRick Macklem 	for (i = 0; i < numops; i++) {
6809ec7b004SRick Macklem 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
6819ec7b004SRick Macklem 		NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED);
6829183a2a3SRick Macklem 		*repp = *tl;
6839ec7b004SRick Macklem 		op = fxdr_unsigned(int, *tl);
684c59e4cc3SRick Macklem 		NFSD_DEBUG(4, "op=%d\n", op);
685c59e4cc3SRick Macklem 		if (op < NFSV4OP_ACCESS ||
686c59e4cc3SRick Macklem 		    (op >= NFSV4OP_NOPS && (nd->nd_flag & ND_NFSV41) == 0) ||
687c59e4cc3SRick Macklem 		    (op >= NFSV41_NOPS && (nd->nd_flag & ND_NFSV41) != 0)) {
6889ec7b004SRick Macklem 			nd->nd_repstat = NFSERR_OPILLEGAL;
6899183a2a3SRick Macklem 			*repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL);
6909ec7b004SRick Macklem 			*repp = nfsd_errmap(nd);
6919ec7b004SRick Macklem 			retops++;
6929ec7b004SRick Macklem 			break;
6939183a2a3SRick Macklem 		} else {
6949183a2a3SRick Macklem 			repp++;
6959ec7b004SRick Macklem 		}
696c59e4cc3SRick Macklem 		if (i == 0)
697c59e4cc3SRick Macklem 			op0 = op;
698c59e4cc3SRick Macklem 		if (i == numops - 1)
699c59e4cc3SRick Macklem 			nd->nd_flag |= ND_LASTOP;
7009ec7b004SRick Macklem 
7019ec7b004SRick Macklem 		/*
7029ec7b004SRick Macklem 		 * Check for a referral on the current FH and, if so, return
7039ec7b004SRick Macklem 		 * NFSERR_MOVED for all ops that allow it, except Getattr.
7049ec7b004SRick Macklem 		 */
7059ec7b004SRick Macklem 		if (vp != NULL && op != NFSV4OP_GETATTR &&
7069ec7b004SRick Macklem 		    nfsv4root_getreferral(vp, NULL, 0) != NULL &&
7079ec7b004SRick Macklem 		    nfsrv_errmoved(op)) {
7089ec7b004SRick Macklem 			nd->nd_repstat = NFSERR_MOVED;
7099ec7b004SRick Macklem 			*repp = nfsd_errmap(nd);
7109ec7b004SRick Macklem 			retops++;
7119ec7b004SRick Macklem 			break;
7129ec7b004SRick Macklem 		}
7139ec7b004SRick Macklem 
714c59e4cc3SRick Macklem 		/*
715c59e4cc3SRick Macklem 		 * For NFSv4.1, check for a Sequence Operation being first
716c59e4cc3SRick Macklem 		 * or one of the other allowed operations by itself.
717c59e4cc3SRick Macklem 		 */
718c59e4cc3SRick Macklem 		if ((nd->nd_flag & ND_NFSV41) != 0) {
719c59e4cc3SRick Macklem 			if (i != 0 && op == NFSV4OP_SEQUENCE)
720c59e4cc3SRick Macklem 				nd->nd_repstat = NFSERR_SEQUENCEPOS;
721c59e4cc3SRick Macklem 			else if (i == 0 && op != NFSV4OP_SEQUENCE &&
722c59e4cc3SRick Macklem 			    op != NFSV4OP_EXCHANGEID &&
723c59e4cc3SRick Macklem 			    op != NFSV4OP_CREATESESSION &&
724c59e4cc3SRick Macklem 			    op != NFSV4OP_BINDCONNTOSESS &&
725c59e4cc3SRick Macklem 			    op != NFSV4OP_DESTROYCLIENTID &&
726c59e4cc3SRick Macklem 			    op != NFSV4OP_DESTROYSESSION)
727c59e4cc3SRick Macklem 				nd->nd_repstat = NFSERR_OPNOTINSESS;
728c59e4cc3SRick Macklem 			else if (i != 0 && op0 != NFSV4OP_SEQUENCE)
729c59e4cc3SRick Macklem 				nd->nd_repstat = NFSERR_NOTONLYOP;
730c59e4cc3SRick Macklem 			if (nd->nd_repstat != 0) {
731c59e4cc3SRick Macklem 				*repp = nfsd_errmap(nd);
732c59e4cc3SRick Macklem 				retops++;
733c59e4cc3SRick Macklem 				break;
734c59e4cc3SRick Macklem 			}
735c59e4cc3SRick Macklem 		}
736c59e4cc3SRick Macklem 
7379ec7b004SRick Macklem 		nd->nd_procnum = op;
7389ec7b004SRick Macklem 		/*
7399ec7b004SRick Macklem 		 * If over flood level, reply NFSERR_RESOURCE, if at the first
7409ec7b004SRick Macklem 		 * Op. (Since a client recovery from NFSERR_RESOURCE can get
7419ec7b004SRick Macklem 		 * really nasty for certain Op sequences, I'll play it safe
7429ec7b004SRick Macklem 		 * and only return the error at the beginning.) The cache
7439ec7b004SRick Macklem 		 * will still function over flood level, but uses lots of
7449ec7b004SRick Macklem 		 * mbufs.)
7459ec7b004SRick Macklem 		 * If nfsrv_mallocmget_limit() returns True, the system is near
7469ec7b004SRick Macklem 		 * to its limit for memory that malloc()/mget() can allocate.
7479ec7b004SRick Macklem 		 */
748c59e4cc3SRick Macklem 		if (i == 0 && (nd->nd_rp == NULL ||
749c59e4cc3SRick Macklem 		    nd->nd_rp->rc_refcnt == 0) &&
7509ec7b004SRick Macklem 		    (nfsrv_mallocmget_limit() ||
7519ec7b004SRick Macklem 		     nfsrc_tcpsavedreplies > nfsrc_floodlevel)) {
7529ec7b004SRick Macklem 			if (nfsrc_tcpsavedreplies > nfsrc_floodlevel) {
7539ec7b004SRick Macklem 				printf("nfsd server cache flooded, try to");
7549ec7b004SRick Macklem 				printf(" increase nfsrc_floodlevel\n");
7559ec7b004SRick Macklem 			}
7569ec7b004SRick Macklem 			nd->nd_repstat = NFSERR_RESOURCE;
7579ec7b004SRick Macklem 			*repp = nfsd_errmap(nd);
7589ec7b004SRick Macklem 			if (op == NFSV4OP_SETATTR) {
7599ec7b004SRick Macklem 				/*
7609ec7b004SRick Macklem 				 * Setattr replies require a bitmap.
7619ec7b004SRick Macklem 				 * even for errors like these.
7629ec7b004SRick Macklem 				 */
7639ec7b004SRick Macklem 				NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
7649ec7b004SRick Macklem 				*tl = 0;
7659ec7b004SRick Macklem 			}
7669ec7b004SRick Macklem 			retops++;
7679ec7b004SRick Macklem 			break;
7689ec7b004SRick Macklem 		}
7699ec7b004SRick Macklem 		if (nfsv4_opflag[op].savereply)
7709ec7b004SRick Macklem 			nd->nd_flag |= ND_SAVEREPLY;
7719ec7b004SRick Macklem 		NFSINCRGLOBAL(newnfsstats.srvrpccnt[nd->nd_procnum]);
7729ec7b004SRick Macklem 		switch (op) {
7739ec7b004SRick Macklem 		case NFSV4OP_PUTFH:
7749ec7b004SRick Macklem 			error = nfsrv_mtofh(nd, &fh);
7759ec7b004SRick Macklem 			if (error)
7769ec7b004SRick Macklem 				goto nfsmout;
7778974bc2fSRick Macklem 			if (!nd->nd_repstat)
7788974bc2fSRick Macklem 				nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
7798974bc2fSRick Macklem 				    NULL, 0, p);
7809ec7b004SRick Macklem 			/* For now, allow this for non-export FHs */
7819ec7b004SRick Macklem 			if (!nd->nd_repstat) {
7829ec7b004SRick Macklem 				if (vp)
7839ec7b004SRick Macklem 					vrele(vp);
7849ec7b004SRick Macklem 				vp = nvp;
7858974bc2fSRick Macklem 				cur_fsid = vp->v_mount->mnt_stat.f_fsid;
786a9989634SZack Kirsch 				NFSVOPUNLOCK(vp, 0);
7879ec7b004SRick Macklem 				vpnes = nes;
7889ec7b004SRick Macklem 			}
7899ec7b004SRick Macklem 			break;
7909ec7b004SRick Macklem 		case NFSV4OP_PUTPUBFH:
7918974bc2fSRick Macklem 			if (nfs_pubfhset)
79217891d00SRick Macklem 			    nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
7938974bc2fSRick Macklem 				&nes, NULL, 0, p);
7948974bc2fSRick Macklem 			else
7959ec7b004SRick Macklem 			    nd->nd_repstat = NFSERR_NOFILEHANDLE;
7969ec7b004SRick Macklem 			if (!nd->nd_repstat) {
7979ec7b004SRick Macklem 				if (vp)
7989ec7b004SRick Macklem 					vrele(vp);
7999ec7b004SRick Macklem 				vp = nvp;
8008974bc2fSRick Macklem 				cur_fsid = vp->v_mount->mnt_stat.f_fsid;
801a9989634SZack Kirsch 				NFSVOPUNLOCK(vp, 0);
8029ec7b004SRick Macklem 				vpnes = nes;
8039ec7b004SRick Macklem 			}
8049ec7b004SRick Macklem 			break;
8059ec7b004SRick Macklem 		case NFSV4OP_PUTROOTFH:
8069ec7b004SRick Macklem 			if (nfs_rootfhset) {
80717891d00SRick Macklem 				nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp,
8088974bc2fSRick Macklem 				    &nes, NULL, 0, p);
8099ec7b004SRick Macklem 				if (!nd->nd_repstat) {
8109ec7b004SRick Macklem 					if (vp)
8119ec7b004SRick Macklem 						vrele(vp);
8129ec7b004SRick Macklem 					vp = nvp;
8138974bc2fSRick Macklem 					cur_fsid = vp->v_mount->mnt_stat.f_fsid;
814a9989634SZack Kirsch 					NFSVOPUNLOCK(vp, 0);
8159ec7b004SRick Macklem 					vpnes = nes;
8169ec7b004SRick Macklem 				}
817c9aad40fSRick Macklem 			} else
8189ec7b004SRick Macklem 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
8199ec7b004SRick Macklem 			break;
8209ec7b004SRick Macklem 		case NFSV4OP_SAVEFH:
8219ec7b004SRick Macklem 			if (vp && NFSVNO_EXPORTED(&vpnes)) {
8229ec7b004SRick Macklem 				nd->nd_repstat = 0;
8239ec7b004SRick Macklem 				/* If vp == savevp, a no-op */
8249ec7b004SRick Macklem 				if (vp != savevp) {
8259ec7b004SRick Macklem 					if (savevp)
8269ec7b004SRick Macklem 						vrele(savevp);
8279ec7b004SRick Macklem 					VREF(vp);
8289ec7b004SRick Macklem 					savevp = vp;
8299ec7b004SRick Macklem 					savevpnes = vpnes;
8308974bc2fSRick Macklem 					save_fsid = cur_fsid;
8319ec7b004SRick Macklem 				}
8329ec7b004SRick Macklem 			} else {
8339ec7b004SRick Macklem 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
8349ec7b004SRick Macklem 			}
8359ec7b004SRick Macklem 			break;
8369ec7b004SRick Macklem 		case NFSV4OP_RESTOREFH:
8379ec7b004SRick Macklem 			if (savevp) {
8389ec7b004SRick Macklem 				nd->nd_repstat = 0;
8399ec7b004SRick Macklem 				/* If vp == savevp, a no-op */
8409ec7b004SRick Macklem 				if (vp != savevp) {
8419ec7b004SRick Macklem 					VREF(savevp);
8429ec7b004SRick Macklem 					vrele(vp);
8439ec7b004SRick Macklem 					vp = savevp;
8449ec7b004SRick Macklem 					vpnes = savevpnes;
8458974bc2fSRick Macklem 					cur_fsid = save_fsid;
8469ec7b004SRick Macklem 				}
8479ec7b004SRick Macklem 			} else {
8489ec7b004SRick Macklem 				nd->nd_repstat = NFSERR_RESTOREFH;
8499ec7b004SRick Macklem 			}
8509ec7b004SRick Macklem 			break;
8519ec7b004SRick Macklem 		default:
8529ec7b004SRick Macklem 		    /*
8539ec7b004SRick Macklem 		     * Allow a Lookup, Getattr, GetFH, Secinfo on an
8549ec7b004SRick Macklem 		     * non-exported directory if
8559ec7b004SRick Macklem 		     * nfs_rootfhset. Do I need to allow any other Ops?
8569ec7b004SRick Macklem 		     * (You can only have a non-exported vpnes if
8579ec7b004SRick Macklem 		     *  nfs_rootfhset is true. See nfsd_fhtovp())
8589ec7b004SRick Macklem 		     * Allow AUTH_SYS to be used for file systems
8599ec7b004SRick Macklem 		     * exported GSS only for certain Ops, to allow
8609ec7b004SRick Macklem 		     * clients to do mounts more easily.
8619ec7b004SRick Macklem 		     */
8629ec7b004SRick Macklem 		    if (nfsv4_opflag[op].needscfh && vp) {
8639ec7b004SRick Macklem 			if (!NFSVNO_EXPORTED(&vpnes) &&
8649ec7b004SRick Macklem 			    op != NFSV4OP_LOOKUP &&
8659ec7b004SRick Macklem 			    op != NFSV4OP_GETATTR &&
8669ec7b004SRick Macklem 			    op != NFSV4OP_GETFH &&
8675a55e04fSRick Macklem 			    op != NFSV4OP_ACCESS &&
8685a55e04fSRick Macklem 			    op != NFSV4OP_READLINK &&
8699ec7b004SRick Macklem 			    op != NFSV4OP_SECINFO)
8709ec7b004SRick Macklem 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
87198ad4453SRick Macklem 			else if (nfsvno_testexp(nd, &vpnes) &&
8729ec7b004SRick Macklem 			    op != NFSV4OP_LOOKUP &&
8739ec7b004SRick Macklem 			    op != NFSV4OP_GETFH &&
8749ec7b004SRick Macklem 			    op != NFSV4OP_GETATTR &&
8759ec7b004SRick Macklem 			    op != NFSV4OP_SECINFO)
8769ec7b004SRick Macklem 				nd->nd_repstat = NFSERR_WRONGSEC;
8779ec7b004SRick Macklem 			if (nd->nd_repstat) {
8789ec7b004SRick Macklem 				if (op == NFSV4OP_SETATTR) {
8799ec7b004SRick Macklem 				    /*
8809ec7b004SRick Macklem 				     * Setattr reply requires a bitmap
8819ec7b004SRick Macklem 				     * even for errors like these.
8829ec7b004SRick Macklem 				     */
8839ec7b004SRick Macklem 				    NFSM_BUILD(tl, u_int32_t *,
8849ec7b004SRick Macklem 					NFSX_UNSIGNED);
8859ec7b004SRick Macklem 				    *tl = 0;
8869ec7b004SRick Macklem 				}
8879ec7b004SRick Macklem 				break;
8889ec7b004SRick Macklem 			}
8899ec7b004SRick Macklem 		    }
8909ec7b004SRick Macklem 		    if (nfsv4_opflag[op].retfh == 1) {
8919ec7b004SRick Macklem 			if (!vp) {
8929ec7b004SRick Macklem 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
8939ec7b004SRick Macklem 				break;
8949ec7b004SRick Macklem 			}
8959ec7b004SRick Macklem 			VREF(vp);
8969ec7b004SRick Macklem 			if (nfsv4_opflag[op].modifyfs)
897785f073bSRick Macklem 				vn_start_write(vp, &temp_mp, V_WAIT);
8989ec7b004SRick Macklem 			error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
8999ec7b004SRick Macklem 			    &nvp, (fhandle_t *)fh.nfsrvfh_data, p, &vpnes);
9009ec7b004SRick Macklem 			if (!error && !nd->nd_repstat) {
9018974bc2fSRick Macklem 			    if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) {
9028974bc2fSRick Macklem 				new_mp = nvp->v_mount;
9038974bc2fSRick Macklem 				if (cur_fsid.val[0] !=
9048974bc2fSRick Macklem 				    new_mp->mnt_stat.f_fsid.val[0] ||
9058974bc2fSRick Macklem 				    cur_fsid.val[1] !=
9068974bc2fSRick Macklem 				    new_mp->mnt_stat.f_fsid.val[1]) {
9078974bc2fSRick Macklem 				    /* crossed a server mount point */
9088974bc2fSRick Macklem 				    nd->nd_repstat = nfsvno_checkexp(new_mp,
9099ec7b004SRick Macklem 					nd->nd_nam, &nes, &credanon);
9109ec7b004SRick Macklem 				    if (!nd->nd_repstat)
9119ec7b004SRick Macklem 					nd->nd_repstat = nfsd_excred(nd,
9129ec7b004SRick Macklem 					    &nes, credanon);
9135679fe19SAlexander Kabaev 				    if (credanon != NULL)
9145679fe19SAlexander Kabaev 					crfree(credanon);
9159ec7b004SRick Macklem 				    if (!nd->nd_repstat) {
9169ec7b004SRick Macklem 					vpnes = nes;
9178974bc2fSRick Macklem 					cur_fsid = new_mp->mnt_stat.f_fsid;
9189ec7b004SRick Macklem 				    }
9199ec7b004SRick Macklem 				}
92081f78d99SRick Macklem 				/* Lookup ops return a locked vnode */
921a9989634SZack Kirsch 				NFSVOPUNLOCK(nvp, 0);
9228974bc2fSRick Macklem 			    }
9239ec7b004SRick Macklem 			    if (!nd->nd_repstat) {
9249ec7b004SRick Macklem 				    vrele(vp);
9259ec7b004SRick Macklem 				    vp = nvp;
92681f78d99SRick Macklem 			    } else
92781f78d99SRick Macklem 				    vrele(nvp);
9289ec7b004SRick Macklem 			}
9299ec7b004SRick Macklem 			if (nfsv4_opflag[op].modifyfs)
930785f073bSRick Macklem 				vn_finished_write(temp_mp);
9319ec7b004SRick Macklem 		    } else if (nfsv4_opflag[op].retfh == 2) {
9329ec7b004SRick Macklem 			if (vp == NULL || savevp == NULL) {
9339ec7b004SRick Macklem 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
9349ec7b004SRick Macklem 				break;
9358974bc2fSRick Macklem 			} else if (cur_fsid.val[0] != save_fsid.val[0] ||
9368974bc2fSRick Macklem 			    cur_fsid.val[1] != save_fsid.val[1]) {
9379ec7b004SRick Macklem 				nd->nd_repstat = NFSERR_XDEV;
9389ec7b004SRick Macklem 				break;
9399ec7b004SRick Macklem 			}
9409ec7b004SRick Macklem 			if (nfsv4_opflag[op].modifyfs)
941785f073bSRick Macklem 				vn_start_write(savevp, &temp_mp, V_WAIT);
94298f234f3SZack Kirsch 			if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
943629fa50eSRick Macklem 				VREF(vp);
944629fa50eSRick Macklem 				VREF(savevp);
945629fa50eSRick Macklem 				error = (*(nfsrv4_ops2[op]))(nd, isdgram,
946629fa50eSRick Macklem 				    savevp, vp, p, &savevpnes, &vpnes);
947629fa50eSRick Macklem 			} else
948629fa50eSRick Macklem 				nd->nd_repstat = NFSERR_PERM;
9499ec7b004SRick Macklem 			if (nfsv4_opflag[op].modifyfs)
950785f073bSRick Macklem 				vn_finished_write(temp_mp);
9519ec7b004SRick Macklem 		    } else {
9529ec7b004SRick Macklem 			if (nfsv4_opflag[op].retfh != 0)
9539ec7b004SRick Macklem 				panic("nfsrvd_compound");
9549ec7b004SRick Macklem 			if (nfsv4_opflag[op].needscfh) {
95517891d00SRick Macklem 				if (vp != NULL) {
956629fa50eSRick Macklem 					if (nfsv4_opflag[op].modifyfs)
957785f073bSRick Macklem 						vn_start_write(vp, &temp_mp,
958785f073bSRick Macklem 						    V_WAIT);
95998f234f3SZack Kirsch 					if (NFSVOPLOCK(vp, nfsv4_opflag[op].lktype)
960629fa50eSRick Macklem 					    == 0)
961629fa50eSRick Macklem 						VREF(vp);
962629fa50eSRick Macklem 					else
96317891d00SRick Macklem 						nd->nd_repstat = NFSERR_PERM;
964629fa50eSRick Macklem 				} else {
9659ec7b004SRick Macklem 					nd->nd_repstat = NFSERR_NOFILEHANDLE;
9669ec7b004SRick Macklem 					if (op == NFSV4OP_SETATTR) {
9679ec7b004SRick Macklem 						/*
96817891d00SRick Macklem 						 * Setattr reply requires a
96917891d00SRick Macklem 						 * bitmap even for errors like
97017891d00SRick Macklem 						 * these.
9719ec7b004SRick Macklem 						 */
9729ec7b004SRick Macklem 						NFSM_BUILD(tl, u_int32_t *,
9739ec7b004SRick Macklem 						    NFSX_UNSIGNED);
9749ec7b004SRick Macklem 						*tl = 0;
9759ec7b004SRick Macklem 					}
9769ec7b004SRick Macklem 					break;
9779ec7b004SRick Macklem 				}
978629fa50eSRick Macklem 				if (nd->nd_repstat == 0)
979629fa50eSRick Macklem 					error = (*(nfsrv4_ops0[op]))(nd,
980629fa50eSRick Macklem 					    isdgram, vp, p, &vpnes);
9819ec7b004SRick Macklem 				if (nfsv4_opflag[op].modifyfs)
982785f073bSRick Macklem 					vn_finished_write(temp_mp);
9839ec7b004SRick Macklem 			} else {
9849ec7b004SRick Macklem 				error = (*(nfsrv4_ops0[op]))(nd, isdgram,
9859ec7b004SRick Macklem 				    NULL, p, &vpnes);
9869ec7b004SRick Macklem 			}
9879ec7b004SRick Macklem 		    }
9889ec7b004SRick Macklem 		};
9899ec7b004SRick Macklem 		if (error) {
9909ec7b004SRick Macklem 			if (error == EBADRPC || error == NFSERR_BADXDR) {
9919ec7b004SRick Macklem 				nd->nd_repstat = NFSERR_BADXDR;
9929ec7b004SRick Macklem 			} else {
9939ec7b004SRick Macklem 				nd->nd_repstat = error;
9949ec7b004SRick Macklem 				printf("nfsv4 comperr0=%d\n", error);
9959ec7b004SRick Macklem 			}
9969ec7b004SRick Macklem 			error = 0;
9979ec7b004SRick Macklem 		}
9989ec7b004SRick Macklem 		retops++;
9999ec7b004SRick Macklem 		if (nd->nd_repstat) {
10009ec7b004SRick Macklem 			*repp = nfsd_errmap(nd);
10019ec7b004SRick Macklem 			break;
10029ec7b004SRick Macklem 		} else {
10039ec7b004SRick Macklem 			*repp = 0;	/* NFS4_OK */
10049ec7b004SRick Macklem 		}
10059ec7b004SRick Macklem 	}
10069ec7b004SRick Macklem nfsmout:
10079ec7b004SRick Macklem 	if (error) {
10089ec7b004SRick Macklem 		if (error == EBADRPC || error == NFSERR_BADXDR)
10099ec7b004SRick Macklem 			nd->nd_repstat = NFSERR_BADXDR;
10109ec7b004SRick Macklem 		else
10119ec7b004SRick Macklem 			printf("nfsv4 comperr1=%d\n", error);
10129ec7b004SRick Macklem 	}
10139ec7b004SRick Macklem 	if (taglen == -1) {
10149ec7b004SRick Macklem 		NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
10159ec7b004SRick Macklem 		*tl++ = 0;
10169ec7b004SRick Macklem 		*tl = 0;
10179ec7b004SRick Macklem 	} else {
10189ec7b004SRick Macklem 		*retopsp = txdr_unsigned(retops);
10199ec7b004SRick Macklem 	}
10209ec7b004SRick Macklem 	if (vp)
10219ec7b004SRick Macklem 		vrele(vp);
10229ec7b004SRick Macklem 	if (savevp)
10239ec7b004SRick Macklem 		vrele(savevp);
10249ec7b004SRick Macklem 	NFSLOCKV4ROOTMUTEX();
10259ec7b004SRick Macklem 	nfsv4_relref(&nfsv4rootfs_lock);
10269ec7b004SRick Macklem 	NFSUNLOCKV4ROOTMUTEX();
1027a9285ae5SZack Kirsch 
1028a9285ae5SZack Kirsch 	NFSEXITCODE2(0, nd);
10299ec7b004SRick Macklem }
1030