19ec7b004SRick Macklem /*-
251369649SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause
351369649SPedro F. Giffuni *
49ec7b004SRick Macklem * Copyright (c) 1989, 1993
59ec7b004SRick Macklem * The Regents of the University of California. All rights reserved.
69ec7b004SRick Macklem *
79ec7b004SRick Macklem * This code is derived from software contributed to Berkeley by
89ec7b004SRick Macklem * Rick Macklem at The University of Guelph.
99ec7b004SRick Macklem *
109ec7b004SRick Macklem * Redistribution and use in source and binary forms, with or without
119ec7b004SRick Macklem * modification, are permitted provided that the following conditions
129ec7b004SRick Macklem * are met:
139ec7b004SRick Macklem * 1. Redistributions of source code must retain the above copyright
149ec7b004SRick Macklem * notice, this list of conditions and the following disclaimer.
159ec7b004SRick Macklem * 2. Redistributions in binary form must reproduce the above copyright
169ec7b004SRick Macklem * notice, this list of conditions and the following disclaimer in the
179ec7b004SRick Macklem * documentation and/or other materials provided with the distribution.
18fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors
199ec7b004SRick Macklem * may be used to endorse or promote products derived from this software
209ec7b004SRick Macklem * without specific prior written permission.
219ec7b004SRick Macklem *
229ec7b004SRick Macklem * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
239ec7b004SRick Macklem * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
249ec7b004SRick Macklem * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
259ec7b004SRick Macklem * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
269ec7b004SRick Macklem * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
279ec7b004SRick Macklem * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
289ec7b004SRick Macklem * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
299ec7b004SRick Macklem * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
309ec7b004SRick Macklem * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
319ec7b004SRick Macklem * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
329ec7b004SRick Macklem * SUCH DAMAGE.
339ec7b004SRick Macklem *
349ec7b004SRick Macklem */
359ec7b004SRick Macklem
369ec7b004SRick Macklem #include <sys/cdefs.h>
379ec7b004SRick Macklem /*
389ec7b004SRick Macklem * Socket operations for use by the nfs server.
399ec7b004SRick Macklem */
409ec7b004SRick Macklem
419ec7b004SRick Macklem #include <fs/nfs/nfsport.h>
429ec7b004SRick Macklem
43ff2f1f69SRick Macklem #include <security/mac/mac_framework.h>
44ff2f1f69SRick Macklem
457e44856eSRick Macklem extern struct nfsrvfh nfs_pubfh;
467e44856eSRick Macklem extern int nfs_pubfhset;
479ec7b004SRick Macklem extern struct nfsv4lock nfsv4rootfs_lock;
481f54e596SRick Macklem extern int nfsrv_clienthashsize;
49c59e4cc3SRick Macklem extern int nfsd_debuglevel;
5090d2dfabSRick Macklem extern int nfsrv_layouthighwater;
5190d2dfabSRick Macklem extern volatile int nfsrv_layoutcnt;
529ec7b004SRick Macklem NFSV4ROOTLOCKMUTEX;
539ec7b004SRick Macklem NFSSTATESPINLOCK;
549ec7b004SRick Macklem
557e44856eSRick Macklem NFSD_VNET_DECLARE(struct nfsrv_stablefirst, nfsrv_stablefirst);
567e44856eSRick Macklem NFSD_VNET_DECLARE(struct nfsclienthashhead *, nfsclienthash);
577e44856eSRick Macklem NFSD_VNET_DECLARE(int, nfsrc_floodlevel);
587e44856eSRick Macklem NFSD_VNET_DECLARE(int, nfsrc_tcpsavedreplies);
597e44856eSRick Macklem NFSD_VNET_DECLARE(struct nfsrvfh, nfs_rootfh);
607e44856eSRick Macklem NFSD_VNET_DECLARE(int, nfs_rootfhset);
617e44856eSRick Macklem NFSD_VNET_DECLARE(struct nfsstatsv1 *, nfsstatsv1_p);
627e44856eSRick Macklem
639ec7b004SRick Macklem int (*nfsrv3_procs0[NFS_V3NPROCS])(struct nfsrv_descript *,
64af444b18SEdward Tomasz Napierala int, vnode_t , struct nfsexstuff *) = {
65af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
669ec7b004SRick Macklem nfsrvd_getattr,
679ec7b004SRick Macklem nfsrvd_setattr,
68af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
699ec7b004SRick Macklem nfsrvd_access,
709ec7b004SRick Macklem nfsrvd_readlink,
719ec7b004SRick Macklem nfsrvd_read,
729ec7b004SRick Macklem nfsrvd_write,
739ec7b004SRick Macklem nfsrvd_create,
74af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
75af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
76af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
779ec7b004SRick Macklem nfsrvd_remove,
789ec7b004SRick Macklem nfsrvd_remove,
79af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
80af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
819ec7b004SRick Macklem nfsrvd_readdir,
829ec7b004SRick Macklem nfsrvd_readdirplus,
839ec7b004SRick Macklem nfsrvd_statfs,
849ec7b004SRick Macklem nfsrvd_fsinfo,
859ec7b004SRick Macklem nfsrvd_pathconf,
869ec7b004SRick Macklem nfsrvd_commit,
879ec7b004SRick Macklem };
889ec7b004SRick Macklem
899ec7b004SRick Macklem int (*nfsrv3_procs1[NFS_V3NPROCS])(struct nfsrv_descript *,
90af444b18SEdward Tomasz Napierala int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *) = {
91af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
92af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
93af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
949ec7b004SRick Macklem nfsrvd_lookup,
95af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
96af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
97af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
98af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
99af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
1009ec7b004SRick Macklem nfsrvd_mkdir,
1019ec7b004SRick Macklem nfsrvd_symlink,
1029ec7b004SRick Macklem nfsrvd_mknod,
103af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
104af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
105af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
106af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
107af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
108af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
109af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
110af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
111af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
112af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
1139ec7b004SRick Macklem };
1149ec7b004SRick Macklem
1159ec7b004SRick Macklem int (*nfsrv3_procs2[NFS_V3NPROCS])(struct nfsrv_descript *,
116af444b18SEdward Tomasz Napierala int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *) = {
117af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
118af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
119af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
120af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
121af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
122af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
123af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
124af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
125af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
126af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
127af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
128af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
129af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
130af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
1319ec7b004SRick Macklem nfsrvd_rename,
1329ec7b004SRick Macklem nfsrvd_link,
133af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
134af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
135af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
136af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
137af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
138af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
1399ec7b004SRick Macklem };
1409ec7b004SRick Macklem
141c057a378SRick Macklem int (*nfsrv4_ops0[NFSV42_NOPS])(struct nfsrv_descript *,
142af444b18SEdward Tomasz Napierala int, vnode_t , struct nfsexstuff *) = {
143af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
144af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
145af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
1469ec7b004SRick Macklem nfsrvd_access,
1479ec7b004SRick Macklem nfsrvd_close,
1489ec7b004SRick Macklem nfsrvd_commit,
149af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
1509ec7b004SRick Macklem nfsrvd_delegpurge,
1519ec7b004SRick Macklem nfsrvd_delegreturn,
1529ec7b004SRick Macklem nfsrvd_getattr,
1539ec7b004SRick Macklem nfsrvd_getfh,
154af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
1559ec7b004SRick Macklem nfsrvd_lock,
1569ec7b004SRick Macklem nfsrvd_lockt,
1579ec7b004SRick Macklem nfsrvd_locku,
158af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
159af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
1609ec7b004SRick Macklem nfsrvd_verify,
161af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
162af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
1639ec7b004SRick Macklem nfsrvd_openconfirm,
1649ec7b004SRick Macklem nfsrvd_opendowngrade,
165af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
166af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
167af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
1689ec7b004SRick Macklem nfsrvd_read,
1699ec7b004SRick Macklem nfsrvd_readdirplus,
1709ec7b004SRick Macklem nfsrvd_readlink,
1719ec7b004SRick Macklem nfsrvd_remove,
172af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
1739ec7b004SRick Macklem nfsrvd_renew,
174af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
175af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
1769ec7b004SRick Macklem nfsrvd_secinfo,
1779ec7b004SRick Macklem nfsrvd_setattr,
1789ec7b004SRick Macklem nfsrvd_setclientid,
1799ec7b004SRick Macklem nfsrvd_setclientidcfrm,
1809ec7b004SRick Macklem nfsrvd_verify,
1819ec7b004SRick Macklem nfsrvd_write,
1829ec7b004SRick Macklem nfsrvd_releaselckown,
183c59e4cc3SRick Macklem nfsrvd_notsupp,
1849442a64eSRick Macklem nfsrvd_bindconnsess,
185c59e4cc3SRick Macklem nfsrvd_exchangeid,
186c59e4cc3SRick Macklem nfsrvd_createsession,
187c59e4cc3SRick Macklem nfsrvd_destroysession,
188c59e4cc3SRick Macklem nfsrvd_freestateid,
189c59e4cc3SRick Macklem nfsrvd_notsupp,
19090d2dfabSRick Macklem nfsrvd_getdevinfo,
191c59e4cc3SRick Macklem nfsrvd_notsupp,
19290d2dfabSRick Macklem nfsrvd_layoutcommit,
19390d2dfabSRick Macklem nfsrvd_layoutget,
19490d2dfabSRick Macklem nfsrvd_layoutreturn,
195947bd247SRick Macklem nfsrvd_secinfononame,
196c59e4cc3SRick Macklem nfsrvd_sequence,
197c59e4cc3SRick Macklem nfsrvd_notsupp,
1985d4835e4SRick Macklem nfsrvd_teststateid,
199c59e4cc3SRick Macklem nfsrvd_notsupp,
200c59e4cc3SRick Macklem nfsrvd_destroyclientid,
201c59e4cc3SRick Macklem nfsrvd_reclaimcomplete,
202c057a378SRick Macklem nfsrvd_allocate,
203c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
204c057a378SRick Macklem nfsrvd_notsupp,
205bb958dcfSRick Macklem nfsrvd_deallocate,
206c057a378SRick Macklem nfsrvd_ioadvise,
207c057a378SRick Macklem nfsrvd_layouterror,
208c057a378SRick Macklem nfsrvd_layoutstats,
209c057a378SRick Macklem nfsrvd_notsupp,
210c057a378SRick Macklem nfsrvd_notsupp,
211c057a378SRick Macklem nfsrvd_notsupp,
212c057a378SRick Macklem nfsrvd_seek,
213c057a378SRick Macklem nfsrvd_notsupp,
214c057a378SRick Macklem nfsrvd_notsupp,
215c057a378SRick Macklem nfsrvd_getxattr,
216c057a378SRick Macklem nfsrvd_setxattr,
217c057a378SRick Macklem nfsrvd_listxattr,
218c057a378SRick Macklem nfsrvd_rmxattr,
2199ec7b004SRick Macklem };
2209ec7b004SRick Macklem
221c057a378SRick Macklem int (*nfsrv4_ops1[NFSV42_NOPS])(struct nfsrv_descript *,
222af444b18SEdward Tomasz Napierala int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *) = {
223af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
224af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
225af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
226af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
227af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
228af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
2299ec7b004SRick Macklem nfsrvd_mknod,
230af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
231af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
232af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
233af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
234af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
235af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
236af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
237af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
2389ec7b004SRick Macklem nfsrvd_lookup,
2399ec7b004SRick Macklem nfsrvd_lookup,
240af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
2419ec7b004SRick Macklem nfsrvd_open,
2429ec7b004SRick Macklem nfsrvd_openattr,
243af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
244af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
245af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
246af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
247af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
248af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
249af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
250af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
251af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
252af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
253af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
254af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
255af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
256af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
257af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
258af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
259af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
260af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
261af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
262af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
263af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
264af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
265af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
266af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
267af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
268af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
269af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
270af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
271af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
272af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
273af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
274af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
275af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
276af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
277af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
278af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
279af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
280af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
281af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
282c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
283c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
284c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
285c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
286c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
287c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
288c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
289c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
290c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
291c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
292c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
293c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
294c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
295c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
296c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
297c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
298c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
2999ec7b004SRick Macklem };
3009ec7b004SRick Macklem
301c057a378SRick Macklem int (*nfsrv4_ops2[NFSV42_NOPS])(struct nfsrv_descript *,
302af444b18SEdward Tomasz Napierala int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *) = {
303af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
304af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
305af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
306af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
307af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
308af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
309af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
310af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
311af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
312af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
313af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
3149ec7b004SRick Macklem nfsrvd_link,
315af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
316af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
317af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
318af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
319af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
320af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
321af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
322af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
323af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
324af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
325af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
326af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
327af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
328af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
329af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
330af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
331af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
3329ec7b004SRick Macklem nfsrvd_rename,
333af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
334af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
335af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
336af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
337af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
338af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
339af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
340af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
341af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
342af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
343af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
344af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
345af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
346af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
347af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
348af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
349af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
350af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
351af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
352af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
353af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
354af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
355af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
356af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
357af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
358af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
359af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
360af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
361af444b18SEdward Tomasz Napierala (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
362c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
363c057a378SRick Macklem nfsrvd_copy_file_range,
364c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
365c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
366c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
367c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
368c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
369c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
370c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
371c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
372c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
373c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
374c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
375c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
376c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
377c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
378c057a378SRick Macklem (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
3799ec7b004SRick Macklem };
3809ec7b004SRick Macklem
3819ec7b004SRick Macklem /*
3829ec7b004SRick Macklem * Static array that defines which nfs rpc's are nonidempotent
3839ec7b004SRick Macklem */
3849ec7b004SRick Macklem static int nfsrv_nonidempotent[NFS_V3NPROCS] = {
3859ec7b004SRick Macklem FALSE,
3869ec7b004SRick Macklem FALSE,
3879ec7b004SRick Macklem TRUE,
3889ec7b004SRick Macklem FALSE,
3899ec7b004SRick Macklem FALSE,
3909ec7b004SRick Macklem FALSE,
3919ec7b004SRick Macklem FALSE,
3929ec7b004SRick Macklem TRUE,
3939ec7b004SRick Macklem TRUE,
3949ec7b004SRick Macklem TRUE,
3959ec7b004SRick Macklem TRUE,
3969ec7b004SRick Macklem TRUE,
3979ec7b004SRick Macklem TRUE,
3989ec7b004SRick Macklem TRUE,
3999ec7b004SRick Macklem TRUE,
4009ec7b004SRick Macklem TRUE,
4019ec7b004SRick Macklem FALSE,
4029ec7b004SRick Macklem FALSE,
4039ec7b004SRick Macklem FALSE,
4049ec7b004SRick Macklem FALSE,
4059ec7b004SRick Macklem FALSE,
4069ec7b004SRick Macklem FALSE,
4079ec7b004SRick Macklem };
4089ec7b004SRick Macklem
4099ec7b004SRick Macklem /*
4109ec7b004SRick Macklem * This static array indicates whether or not the RPC modifies the
4119ec7b004SRick Macklem * file system.
4129ec7b004SRick Macklem */
4133e5ba2e1SRick Macklem int nfsrv_writerpc[NFS_NPROCS] = { 0, 0, 1, 0, 0, 0, 0,
4149ec7b004SRick Macklem 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
4159ec7b004SRick Macklem 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
4169ec7b004SRick Macklem
417c057a378SRick Macklem SYSCTL_DECL(_vfs_nfsd);
418c057a378SRick Macklem static int nfs_minminorv4 = NFSV4_MINORVERSION;
419c057a378SRick Macklem SYSCTL_INT(_vfs_nfsd, OID_AUTO, server_min_minorversion4, CTLFLAG_RWTUN,
420c057a378SRick Macklem &nfs_minminorv4, 0,
421c057a378SRick Macklem "The lowest minor version of NFSv4 handled by the server");
422c057a378SRick Macklem
423c057a378SRick Macklem static int nfs_maxminorv4 = NFSV42_MINORVERSION;
424c057a378SRick Macklem SYSCTL_INT(_vfs_nfsd, OID_AUTO, server_max_minorversion4, CTLFLAG_RWTUN,
425c057a378SRick Macklem &nfs_maxminorv4, 0,
426c057a378SRick Macklem "The highest minor version of NFSv4 handled by the server");
427c057a378SRick Macklem
4289ec7b004SRick Macklem /* local functions */
4299ec7b004SRick Macklem static void nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
430113aa933SEdward Tomasz Napierala u_char *tag, int taglen, u_int32_t minorvers);
4319ec7b004SRick Macklem
4329ec7b004SRick Macklem /*
4339ec7b004SRick Macklem * This static array indicates which server procedures require the extra
4349ec7b004SRick Macklem * arguments to return the current file handle for V2, 3.
4359ec7b004SRick Macklem */
4369ec7b004SRick Macklem static int nfs_retfh[NFS_V3NPROCS] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1,
4379ec7b004SRick Macklem 1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0 };
4389ec7b004SRick Macklem
439c057a378SRick Macklem extern struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS];
4409ec7b004SRick Macklem
4419ec7b004SRick Macklem static int nfsv3to4op[NFS_V3NPROCS] = {
4429ec7b004SRick Macklem NFSPROC_NULL,
4439ec7b004SRick Macklem NFSV4OP_GETATTR,
4449ec7b004SRick Macklem NFSV4OP_SETATTR,
4459ec7b004SRick Macklem NFSV4OP_LOOKUP,
4469ec7b004SRick Macklem NFSV4OP_ACCESS,
4479ec7b004SRick Macklem NFSV4OP_READLINK,
4489ec7b004SRick Macklem NFSV4OP_READ,
4499ec7b004SRick Macklem NFSV4OP_WRITE,
4509ec7b004SRick Macklem NFSV4OP_V3CREATE,
4519ec7b004SRick Macklem NFSV4OP_MKDIR,
4529ec7b004SRick Macklem NFSV4OP_SYMLINK,
4539ec7b004SRick Macklem NFSV4OP_MKNOD,
4549ec7b004SRick Macklem NFSV4OP_REMOVE,
4559ec7b004SRick Macklem NFSV4OP_RMDIR,
4569ec7b004SRick Macklem NFSV4OP_RENAME,
4579ec7b004SRick Macklem NFSV4OP_LINK,
4589ec7b004SRick Macklem NFSV4OP_READDIR,
4599ec7b004SRick Macklem NFSV4OP_READDIRPLUS,
4609ec7b004SRick Macklem NFSV4OP_FSSTAT,
4619ec7b004SRick Macklem NFSV4OP_FSINFO,
4629ec7b004SRick Macklem NFSV4OP_PATHCONF,
4639ec7b004SRick Macklem NFSV4OP_COMMIT,
4649ec7b004SRick Macklem };
4659ec7b004SRick Macklem
4661b819cf2SRick Macklem static struct mtx nfsrvd_statmtx;
4671b819cf2SRick Macklem MTX_SYSINIT(nfsst, &nfsrvd_statmtx, "NFSstat", MTX_DEF);
4681b819cf2SRick Macklem
469ff2f1f69SRick Macklem static struct ucred *nfsrv_createrootcred(void);
470ff2f1f69SRick Macklem
4711b819cf2SRick Macklem static void
nfsrvd_statstart(int op,struct bintime * now)4721b819cf2SRick Macklem nfsrvd_statstart(int op, struct bintime *now)
4731b819cf2SRick Macklem {
4741b819cf2SRick Macklem if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
4751b819cf2SRick Macklem printf("%s: op %d invalid\n", __func__, op);
4761b819cf2SRick Macklem return;
4771b819cf2SRick Macklem }
4781b819cf2SRick Macklem
4791b819cf2SRick Macklem mtx_lock(&nfsrvd_statmtx);
480b039ca07SRick Macklem if (NFSD_VNET(nfsstatsv1_p)->srvstartcnt ==
481b039ca07SRick Macklem NFSD_VNET(nfsstatsv1_p)->srvdonecnt) {
4821b819cf2SRick Macklem if (now != NULL)
483b039ca07SRick Macklem NFSD_VNET(nfsstatsv1_p)->busyfrom = *now;
4841b819cf2SRick Macklem else
485b039ca07SRick Macklem binuptime(&NFSD_VNET(nfsstatsv1_p)->busyfrom);
4861b819cf2SRick Macklem
4871b819cf2SRick Macklem }
488b039ca07SRick Macklem NFSD_VNET(nfsstatsv1_p)->srvrpccnt[op]++;
489b039ca07SRick Macklem NFSD_VNET(nfsstatsv1_p)->srvstartcnt++;
4901b819cf2SRick Macklem mtx_unlock(&nfsrvd_statmtx);
4911b819cf2SRick Macklem
4921b819cf2SRick Macklem }
4931b819cf2SRick Macklem
4941b819cf2SRick Macklem static void
nfsrvd_statend(int op,uint64_t bytes,struct bintime * now,struct bintime * then)4951b819cf2SRick Macklem nfsrvd_statend(int op, uint64_t bytes, struct bintime *now,
4961b819cf2SRick Macklem struct bintime *then)
4971b819cf2SRick Macklem {
4981b819cf2SRick Macklem struct bintime dt, lnow;
4991b819cf2SRick Macklem
5001b819cf2SRick Macklem if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
5011b819cf2SRick Macklem printf("%s: op %d invalid\n", __func__, op);
5021b819cf2SRick Macklem return;
5031b819cf2SRick Macklem }
5041b819cf2SRick Macklem
5051b819cf2SRick Macklem if (now == NULL) {
5061b819cf2SRick Macklem now = &lnow;
5071b819cf2SRick Macklem binuptime(now);
5081b819cf2SRick Macklem }
5091b819cf2SRick Macklem
5101b819cf2SRick Macklem mtx_lock(&nfsrvd_statmtx);
5111b819cf2SRick Macklem
512b039ca07SRick Macklem NFSD_VNET(nfsstatsv1_p)->srvbytes[op] += bytes;
513b039ca07SRick Macklem NFSD_VNET(nfsstatsv1_p)->srvops[op]++;
5141b819cf2SRick Macklem
5151b819cf2SRick Macklem if (then != NULL) {
5161b819cf2SRick Macklem dt = *now;
5171b819cf2SRick Macklem bintime_sub(&dt, then);
518b039ca07SRick Macklem bintime_add(&NFSD_VNET(nfsstatsv1_p)->srvduration[op], &dt);
5191b819cf2SRick Macklem }
5201b819cf2SRick Macklem
5211b819cf2SRick Macklem dt = *now;
522b039ca07SRick Macklem bintime_sub(&dt, &NFSD_VNET(nfsstatsv1_p)->busyfrom);
523b039ca07SRick Macklem bintime_add(&NFSD_VNET(nfsstatsv1_p)->busytime, &dt);
524b039ca07SRick Macklem NFSD_VNET(nfsstatsv1_p)->busyfrom = *now;
5251b819cf2SRick Macklem
526b039ca07SRick Macklem NFSD_VNET(nfsstatsv1_p)->srvdonecnt++;
5271b819cf2SRick Macklem
5281b819cf2SRick Macklem mtx_unlock(&nfsrvd_statmtx);
5291b819cf2SRick Macklem }
5301b819cf2SRick Macklem
5319ec7b004SRick Macklem /*
5329ec7b004SRick Macklem * Do an RPC. Basically, get the file handles translated to vnode pointers
5339ec7b004SRick Macklem * and then call the appropriate server routine. The server routines are
5349ec7b004SRick Macklem * split into groups, based on whether they use a file handle or file
5359ec7b004SRick Macklem * handle plus name or ...
5369ec7b004SRick Macklem * The NFS V4 Compound RPC is performed separately by nfsrvd_compound().
5379ec7b004SRick Macklem */
538b9cc3262SRyan Moeller void
nfsrvd_dorpc(struct nfsrv_descript * nd,int isdgram,u_char * tag,int taglen,u_int32_t minorvers)539c59e4cc3SRick Macklem nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, u_char *tag, int taglen,
540113aa933SEdward Tomasz Napierala u_int32_t minorvers)
5419ec7b004SRick Macklem {
54217891d00SRick Macklem int error = 0, lktype;
5439ec7b004SRick Macklem vnode_t vp;
544774a3685SRick Macklem mount_t mp;
5459ec7b004SRick Macklem struct nfsrvfh fh;
5469ec7b004SRick Macklem struct nfsexstuff nes;
547774a3685SRick Macklem struct mbuf *md;
548774a3685SRick Macklem char *dpos;
549774a3685SRick Macklem
550774a3685SRick Macklem /*
551774a3685SRick Macklem * Save the current position in the request mbuf list so
552774a3685SRick Macklem * that a rollback to this location can be done upon an
553774a3685SRick Macklem * ERELOOKUP error return from an RPC function.
554774a3685SRick Macklem */
555774a3685SRick Macklem md = nd->nd_md;
556774a3685SRick Macklem dpos = nd->nd_dpos;
557774a3685SRick Macklem tryagain:
558774a3685SRick Macklem mp = NULL;
5599ec7b004SRick Macklem
5609ec7b004SRick Macklem /*
5619ec7b004SRick Macklem * Get a locked vnode for the first file handle
5629ec7b004SRick Macklem */
5639ec7b004SRick Macklem if (!(nd->nd_flag & ND_NFSV4)) {
564b38f7723SKonstantin Belousov KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc"));
5659ec7b004SRick Macklem /*
5669ec7b004SRick Macklem * For NFSv3, if the malloc/mget allocation is near limits,
5679ec7b004SRick Macklem * return NFSERR_DELAY.
5689ec7b004SRick Macklem */
5699ec7b004SRick Macklem if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) {
5709ec7b004SRick Macklem nd->nd_repstat = NFSERR_DELAY;
5719ec7b004SRick Macklem vp = NULL;
5729ec7b004SRick Macklem } else {
5739ec7b004SRick Macklem error = nfsrv_mtofh(nd, &fh);
5749ec7b004SRick Macklem if (error) {
5759ec7b004SRick Macklem if (error != EBADRPC)
5769ec7b004SRick Macklem printf("nfs dorpc err1=%d\n", error);
5779ec7b004SRick Macklem nd->nd_repstat = NFSERR_GARBAGE;
578a9285ae5SZack Kirsch goto out;
5799ec7b004SRick Macklem }
58017891d00SRick Macklem if (nd->nd_procnum == NFSPROC_READ ||
581d96b98a3SKenneth D. Merry nd->nd_procnum == NFSPROC_WRITE ||
58217891d00SRick Macklem nd->nd_procnum == NFSPROC_READDIR ||
5830c419e22SRick Macklem nd->nd_procnum == NFSPROC_READDIRPLUS ||
58417891d00SRick Macklem nd->nd_procnum == NFSPROC_READLINK ||
58517891d00SRick Macklem nd->nd_procnum == NFSPROC_GETATTR ||
5860c419e22SRick Macklem nd->nd_procnum == NFSPROC_ACCESS ||
5870c419e22SRick Macklem nd->nd_procnum == NFSPROC_FSSTAT ||
5880c419e22SRick Macklem nd->nd_procnum == NFSPROC_FSINFO)
58917891d00SRick Macklem lktype = LK_SHARED;
59017891d00SRick Macklem else
59117891d00SRick Macklem lktype = LK_EXCLUSIVE;
5929ec7b004SRick Macklem if (nd->nd_flag & ND_PUBLOOKUP)
59317891d00SRick Macklem nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes,
594a5df139eSRick Macklem &mp, nfsrv_writerpc[nd->nd_procnum], -1);
5959ec7b004SRick Macklem else
59617891d00SRick Macklem nfsd_fhtovp(nd, &fh, lktype, &vp, &nes,
597a5df139eSRick Macklem &mp, nfsrv_writerpc[nd->nd_procnum], -1);
5989ec7b004SRick Macklem if (nd->nd_repstat == NFSERR_PROGNOTV4)
599a9285ae5SZack Kirsch goto out;
6009ec7b004SRick Macklem }
6019ec7b004SRick Macklem }
6029ec7b004SRick Macklem
6039ec7b004SRick Macklem /*
6049ec7b004SRick Macklem * For V2 and 3, set the ND_SAVEREPLY flag for the recent request
6059ec7b004SRick Macklem * cache, as required.
6069ec7b004SRick Macklem * For V4, nfsrvd_compound() does this.
6079ec7b004SRick Macklem */
6089ec7b004SRick Macklem if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum])
6099ec7b004SRick Macklem nd->nd_flag |= ND_SAVEREPLY;
6109ec7b004SRick Macklem
6119ec7b004SRick Macklem nfsrvd_rephead(nd);
6129ec7b004SRick Macklem /*
6139ec7b004SRick Macklem * If nd_repstat is non-zero, just fill in the reply status
6149ec7b004SRick Macklem * to complete the RPC reply for V2. Otherwise, you must do
6159ec7b004SRick Macklem * the RPC.
6169ec7b004SRick Macklem */
6179ec7b004SRick Macklem if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) {
6189ec7b004SRick Macklem *nd->nd_errp = nfsd_errmap(nd);
6191b819cf2SRick Macklem nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], /*now*/ NULL);
6201b819cf2SRick Macklem nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
6211b819cf2SRick Macklem /*now*/ NULL, /*then*/ NULL);
6228974bc2fSRick Macklem vn_finished_write(mp);
623a9285ae5SZack Kirsch goto out;
6249ec7b004SRick Macklem }
6259ec7b004SRick Macklem
6269ec7b004SRick Macklem /*
6279ec7b004SRick Macklem * Now the procedure can be performed. For V4, nfsrvd_compound()
6289ec7b004SRick Macklem * works through the sub-rpcs, otherwise just call the procedure.
6299ec7b004SRick Macklem * The procedures are in three groups with different arguments.
6309ec7b004SRick Macklem * The group is indicated by the value in nfs_retfh[].
6319ec7b004SRick Macklem */
6329ec7b004SRick Macklem if (nd->nd_flag & ND_NFSV4) {
633113aa933SEdward Tomasz Napierala nfsrvd_compound(nd, isdgram, tag, taglen, minorvers);
6349ec7b004SRick Macklem } else {
6351b819cf2SRick Macklem struct bintime start_time;
6361b819cf2SRick Macklem
6371b819cf2SRick Macklem binuptime(&start_time);
6381b819cf2SRick Macklem nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], &start_time);
6391b819cf2SRick Macklem
6409ec7b004SRick Macklem if (nfs_retfh[nd->nd_procnum] == 1) {
6419ec7b004SRick Macklem if (vp)
642b249ce48SMateusz Guzik NFSVOPUNLOCK(vp);
6439ec7b004SRick Macklem error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram,
644af444b18SEdward Tomasz Napierala vp, NULL, (fhandle_t *)fh.nfsrvfh_data, &nes);
6459ec7b004SRick Macklem } else if (nfs_retfh[nd->nd_procnum] == 2) {
6469ec7b004SRick Macklem error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram,
647af444b18SEdward Tomasz Napierala vp, NULL, &nes, NULL);
6489ec7b004SRick Macklem } else {
6499ec7b004SRick Macklem error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
650af444b18SEdward Tomasz Napierala vp, &nes);
6519ec7b004SRick Macklem }
6528974bc2fSRick Macklem vn_finished_write(mp);
6531b819cf2SRick Macklem
654774a3685SRick Macklem if (error == 0 && nd->nd_repstat == ERELOOKUP) {
655774a3685SRick Macklem /*
656774a3685SRick Macklem * Roll back to the beginning of the RPC request
657774a3685SRick Macklem * arguments.
658774a3685SRick Macklem */
659774a3685SRick Macklem nd->nd_md = md;
660774a3685SRick Macklem nd->nd_dpos = dpos;
661774a3685SRick Macklem
662774a3685SRick Macklem /* Free the junk RPC reply and redo the RPC. */
663774a3685SRick Macklem m_freem(nd->nd_mreq);
664774a3685SRick Macklem nd->nd_mreq = nd->nd_mb = NULL;
665774a3685SRick Macklem nd->nd_repstat = 0;
666774a3685SRick Macklem goto tryagain;
667774a3685SRick Macklem }
668774a3685SRick Macklem
6691b819cf2SRick Macklem nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
6701b819cf2SRick Macklem /*now*/ NULL, /*then*/ &start_time);
6719ec7b004SRick Macklem }
6729ec7b004SRick Macklem if (error) {
6739ec7b004SRick Macklem if (error != EBADRPC)
6749ec7b004SRick Macklem printf("nfs dorpc err2=%d\n", error);
6759ec7b004SRick Macklem nd->nd_repstat = NFSERR_GARBAGE;
6769ec7b004SRick Macklem }
6779ec7b004SRick Macklem *nd->nd_errp = nfsd_errmap(nd);
6789ec7b004SRick Macklem
6799ec7b004SRick Macklem /*
6809ec7b004SRick Macklem * Don't cache certain reply status values.
6819ec7b004SRick Macklem */
6829ec7b004SRick Macklem if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) &&
6839ec7b004SRick Macklem (nd->nd_repstat == NFSERR_GARBAGE ||
6849ec7b004SRick Macklem nd->nd_repstat == NFSERR_BADXDR ||
6859ec7b004SRick Macklem nd->nd_repstat == NFSERR_MOVED ||
6869ec7b004SRick Macklem nd->nd_repstat == NFSERR_DELAY ||
6879ec7b004SRick Macklem nd->nd_repstat == NFSERR_BADSEQID ||
6889ec7b004SRick Macklem nd->nd_repstat == NFSERR_RESOURCE ||
6899ec7b004SRick Macklem nd->nd_repstat == NFSERR_SERVERFAULT ||
6909ec7b004SRick Macklem nd->nd_repstat == NFSERR_STALECLIENTID ||
6919ec7b004SRick Macklem nd->nd_repstat == NFSERR_STALESTATEID ||
6929ec7b004SRick Macklem nd->nd_repstat == NFSERR_OLDSTATEID ||
6939ec7b004SRick Macklem nd->nd_repstat == NFSERR_BADSTATEID ||
6949ec7b004SRick Macklem nd->nd_repstat == NFSERR_GRACE ||
6959ec7b004SRick Macklem nd->nd_repstat == NFSERR_NOGRACE))
6969ec7b004SRick Macklem nd->nd_flag &= ~ND_SAVEREPLY;
697a9285ae5SZack Kirsch
698a9285ae5SZack Kirsch out:
699a9285ae5SZack Kirsch NFSEXITCODE2(0, nd);
7009ec7b004SRick Macklem }
7019ec7b004SRick Macklem
7029ec7b004SRick Macklem /*
7039ec7b004SRick Macklem * Breaks down a compound RPC request and calls the server routines for
7049ec7b004SRick Macklem * the subprocedures.
7059ec7b004SRick Macklem * Some suboperations are performed directly here to simplify file handle<-->
7069ec7b004SRick Macklem * vnode pointer handling.
7079ec7b004SRick Macklem */
7089ec7b004SRick Macklem static void
nfsrvd_compound(struct nfsrv_descript * nd,int isdgram,u_char * tag,int taglen,u_int32_t minorvers)709c59e4cc3SRick Macklem nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,
710113aa933SEdward Tomasz Napierala int taglen, u_int32_t minorvers)
7119ec7b004SRick Macklem {
712a5df139eSRick Macklem int i, lktype, op, op0 = 0, rstat, statsinprog = 0;
7139ec7b004SRick Macklem u_int32_t *tl;
7149ec7b004SRick Macklem struct nfsclient *clp, *nclp;
715d224f05fSRick Macklem int error = 0, igotlock, nextop, numops, savefhcnt;
716c59e4cc3SRick Macklem u_int32_t retops = 0, *retopsp = NULL, *repp;
7179ec7b004SRick Macklem vnode_t vp, nvp, savevp;
7189ec7b004SRick Macklem struct nfsrvfh fh;
7198974bc2fSRick Macklem mount_t new_mp, temp_mp = NULL;
720ff2f1f69SRick Macklem struct ucred *credanon, *rootcred, *savecred;
7219ec7b004SRick Macklem struct nfsexstuff nes, vpnes, savevpnes;
7228974bc2fSRick Macklem fsid_t cur_fsid, save_fsid;
7239ec7b004SRick Macklem static u_int64_t compref = 0;
7241b819cf2SRick Macklem struct bintime start_time;
725113aa933SEdward Tomasz Napierala struct thread *p;
726774a3685SRick Macklem struct mbuf *mb, *md;
727774a3685SRick Macklem char *bpos, *dpos;
728774a3685SRick Macklem int bextpg, bextpgsiz;
729113aa933SEdward Tomasz Napierala
730113aa933SEdward Tomasz Napierala p = curthread;
731ff2f1f69SRick Macklem rootcred = savecred = NULL;
7329ec7b004SRick Macklem
733f8dc0630SRick Macklem /* Check for and optionally clear the no space flags for DSs. */
734f8dc0630SRick Macklem nfsrv_checknospc();
735f8dc0630SRick Macklem
7369ec7b004SRick Macklem NFSVNO_EXINIT(&vpnes);
7379ec7b004SRick Macklem NFSVNO_EXINIT(&savevpnes);
7389ec7b004SRick Macklem /*
7399ec7b004SRick Macklem * Put the seq# of the current compound RPC in nfsrv_descript.
7409ec7b004SRick Macklem * (This is used by nfsrv_checkgetattr(), to see if the write
7419ec7b004SRick Macklem * delegation was created by the same compound RPC as the one
7429ec7b004SRick Macklem * with that Getattr in it.)
7439ec7b004SRick Macklem * Don't worry about the 64bit number wrapping around. It ain't
7449ec7b004SRick Macklem * gonna happen before this server gets shut down/rebooted.
7459ec7b004SRick Macklem */
7469ec7b004SRick Macklem nd->nd_compref = compref++;
7479ec7b004SRick Macklem
7489ec7b004SRick Macklem /*
7499ec7b004SRick Macklem * Check for and optionally get a lock on the root. This lock means that
7509ec7b004SRick Macklem * no nfsd will be fiddling with the V4 file system and state stuff. It
7519ec7b004SRick Macklem * is required when the V4 root is being changed, the stable storage
7529ec7b004SRick Macklem * restart file is being updated, or callbacks are being done.
7539ec7b004SRick Macklem * When any of the nfsd are processing an NFSv4 compound RPC, they must
7549ec7b004SRick Macklem * either hold a reference count (nfs_usecnt) or the lock. When
7559ec7b004SRick Macklem * nfsrv_unlock() is called to release the lock, it can optionally
7569ec7b004SRick Macklem * also get a reference count, which saves the need for a call to
7579ec7b004SRick Macklem * nfsrv_getref() after nfsrv_unlock().
7589ec7b004SRick Macklem */
7599ec7b004SRick Macklem /*
7609ec7b004SRick Macklem * First, check to see if we need to wait for an update lock.
7619ec7b004SRick Macklem */
7629ec7b004SRick Macklem igotlock = 0;
7639ec7b004SRick Macklem NFSLOCKV4ROOTMUTEX();
7647e44856eSRick Macklem if (NFSD_VNET(nfsrv_stablefirst).nsf_flags & NFSNSF_NEEDLOCK)
7659ec7b004SRick Macklem igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
766ff29f3b2SRick Macklem NFSV4ROOTLOCKMUTEXPTR, NULL);
7679ec7b004SRick Macklem else
7689ec7b004SRick Macklem igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
769ff29f3b2SRick Macklem NFSV4ROOTLOCKMUTEXPTR, NULL);
7709ec7b004SRick Macklem NFSUNLOCKV4ROOTMUTEX();
7719ec7b004SRick Macklem if (igotlock) {
7729ec7b004SRick Macklem /*
7739ec7b004SRick Macklem * If I got the lock, I can update the stable storage file.
7749ec7b004SRick Macklem * Done when the grace period is over or a client has long
7759ec7b004SRick Macklem * since expired.
7769ec7b004SRick Macklem */
7777e44856eSRick Macklem NFSD_VNET(nfsrv_stablefirst).nsf_flags &= ~NFSNSF_NEEDLOCK;
7787e44856eSRick Macklem if ((NFSD_VNET(nfsrv_stablefirst).nsf_flags &
7799ec7b004SRick Macklem (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
7809ec7b004SRick Macklem nfsrv_updatestable(p);
7819ec7b004SRick Macklem
7829ec7b004SRick Macklem /*
7839ec7b004SRick Macklem * If at least one client has long since expired, search
7849ec7b004SRick Macklem * the client list for them, write a REVOKE record on the
7859ec7b004SRick Macklem * stable storage file and then remove them from the client
7869ec7b004SRick Macklem * list.
7879ec7b004SRick Macklem */
7887e44856eSRick Macklem if (NFSD_VNET(nfsrv_stablefirst).nsf_flags &
7897e44856eSRick Macklem NFSNSF_EXPIREDCLIENT) {
7907e44856eSRick Macklem NFSD_VNET(nfsrv_stablefirst).nsf_flags &=
7917e44856eSRick Macklem ~NFSNSF_EXPIREDCLIENT;
7921f54e596SRick Macklem for (i = 0; i < nfsrv_clienthashsize; i++) {
7937e44856eSRick Macklem LIST_FOREACH_SAFE(clp, &NFSD_VNET(nfsclienthash)[i],
7947e44856eSRick Macklem lc_hash, nclp) {
7959ec7b004SRick Macklem if (clp->lc_flags & LCL_EXPIREIT) {
7969ec7b004SRick Macklem if (!LIST_EMPTY(&clp->lc_open) ||
7979ec7b004SRick Macklem !LIST_EMPTY(&clp->lc_deleg))
7989ec7b004SRick Macklem nfsrv_writestable(clp->lc_id,
7999ec7b004SRick Macklem clp->lc_idlen, NFSNST_REVOKE, p);
8009ec7b004SRick Macklem nfsrv_cleanclient(clp, p);
8019ec7b004SRick Macklem nfsrv_freedeleglist(&clp->lc_deleg);
8029ec7b004SRick Macklem nfsrv_freedeleglist(&clp->lc_olddeleg);
8039ec7b004SRick Macklem LIST_REMOVE(clp, lc_hash);
8049ec7b004SRick Macklem nfsrv_zapclient(clp, p);
8059ec7b004SRick Macklem }
8069ec7b004SRick Macklem }
8079ec7b004SRick Macklem }
8089ec7b004SRick Macklem }
8099ec7b004SRick Macklem NFSLOCKV4ROOTMUTEX();
8109ec7b004SRick Macklem nfsv4_unlock(&nfsv4rootfs_lock, 1);
8119ec7b004SRick Macklem NFSUNLOCKV4ROOTMUTEX();
8129ec7b004SRick Macklem } else {
8139ec7b004SRick Macklem /*
8149ec7b004SRick Macklem * If we didn't get the lock, we need to get a refcnt,
8159ec7b004SRick Macklem * which also checks for and waits for the lock.
8169ec7b004SRick Macklem */
8179ec7b004SRick Macklem NFSLOCKV4ROOTMUTEX();
8189ec7b004SRick Macklem nfsv4_getref(&nfsv4rootfs_lock, NULL,
819ff29f3b2SRick Macklem NFSV4ROOTLOCKMUTEXPTR, NULL);
8209ec7b004SRick Macklem NFSUNLOCKV4ROOTMUTEX();
8219ec7b004SRick Macklem }
8229ec7b004SRick Macklem
8239ec7b004SRick Macklem /*
8249ec7b004SRick Macklem * If flagged, search for open owners that haven't had any opens
8259ec7b004SRick Macklem * for a long time.
8269ec7b004SRick Macklem */
8277e44856eSRick Macklem if (NFSD_VNET(nfsrv_stablefirst).nsf_flags & NFSNSF_NOOPENS) {
8289ec7b004SRick Macklem nfsrv_throwawayopens(p);
8299ec7b004SRick Macklem }
8309ec7b004SRick Macklem
83190d2dfabSRick Macklem /* Do a CBLAYOUTRECALL callback if over the high water mark. */
83290d2dfabSRick Macklem if (nfsrv_layoutcnt > nfsrv_layouthighwater)
83390d2dfabSRick Macklem nfsrv_recalloldlayout(p);
83490d2dfabSRick Macklem
8359ec7b004SRick Macklem savevp = vp = NULL;
8368974bc2fSRick Macklem save_fsid.val[0] = save_fsid.val[1] = 0;
8378974bc2fSRick Macklem cur_fsid.val[0] = cur_fsid.val[1] = 0;
838d224f05fSRick Macklem nextop = -1;
839d224f05fSRick Macklem savefhcnt = 0;
840c59e4cc3SRick Macklem
841c59e4cc3SRick Macklem /* If taglen < 0, there was a parsing error in nfsd_getminorvers(). */
8429ec7b004SRick Macklem if (taglen < 0) {
8439ec7b004SRick Macklem error = EBADRPC;
8449ec7b004SRick Macklem goto nfsmout;
8459ec7b004SRick Macklem }
846c59e4cc3SRick Macklem
8479ec7b004SRick Macklem (void) nfsm_strtom(nd, tag, taglen);
8489ec7b004SRick Macklem NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED);
849c59e4cc3SRick Macklem NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
850c057a378SRick Macklem if ((minorvers != NFSV4_MINORVERSION &&
851c057a378SRick Macklem minorvers != NFSV41_MINORVERSION &&
852c057a378SRick Macklem minorvers != NFSV42_MINORVERSION) ||
853c057a378SRick Macklem minorvers < nfs_minminorv4 || minorvers > nfs_maxminorv4)
8549ec7b004SRick Macklem nd->nd_repstat = NFSERR_MINORVERMISMATCH;
8559ec7b004SRick Macklem if (nd->nd_repstat)
8569ec7b004SRick Macklem numops = 0;
8579ec7b004SRick Macklem else
8589ec7b004SRick Macklem numops = fxdr_unsigned(int, *tl);
8599ec7b004SRick Macklem /*
8609ec7b004SRick Macklem * Loop around doing the sub ops.
8619ec7b004SRick Macklem * vp - is an unlocked vnode pointer for the CFH
8629ec7b004SRick Macklem * savevp - is an unlocked vnode pointer for the SAVEDFH
8639ec7b004SRick Macklem * (at some future date, it might turn out to be more appropriate
8649ec7b004SRick Macklem * to keep the file handles instead of vnode pointers?)
8659ec7b004SRick Macklem * savevpnes and vpnes - are the export flags for the above.
8669ec7b004SRick Macklem */
8679ec7b004SRick Macklem for (i = 0; i < numops; i++) {
8689ec7b004SRick Macklem NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED);
869d224f05fSRick Macklem if (savefhcnt > 0) {
870d224f05fSRick Macklem op = NFSV4OP_SAVEFH;
871d224f05fSRick Macklem *repp = txdr_unsigned(op);
872d224f05fSRick Macklem savefhcnt--;
873d224f05fSRick Macklem } else if (nextop == -1) {
874d224f05fSRick Macklem NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
8759183a2a3SRick Macklem *repp = *tl;
8769ec7b004SRick Macklem op = fxdr_unsigned(int, *tl);
877d224f05fSRick Macklem } else {
878d224f05fSRick Macklem op = nextop;
879d224f05fSRick Macklem *repp = txdr_unsigned(op);
880d224f05fSRick Macklem nextop = -1;
881d224f05fSRick Macklem }
882c59e4cc3SRick Macklem NFSD_DEBUG(4, "op=%d\n", op);
883c057a378SRick Macklem if (op < NFSV4OP_ACCESS || op >= NFSV42_NOPS ||
884c59e4cc3SRick Macklem (op >= NFSV4OP_NOPS && (nd->nd_flag & ND_NFSV41) == 0) ||
885c057a378SRick Macklem (op >= NFSV41_NOPS && (nd->nd_flag & ND_NFSV42) == 0)) {
8869ec7b004SRick Macklem nd->nd_repstat = NFSERR_OPILLEGAL;
8879183a2a3SRick Macklem *repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL);
8889ec7b004SRick Macklem *repp = nfsd_errmap(nd);
8899ec7b004SRick Macklem retops++;
8909ec7b004SRick Macklem break;
8919183a2a3SRick Macklem } else {
8929183a2a3SRick Macklem repp++;
8939ec7b004SRick Macklem }
8941d171e79SRick Macklem
8951d171e79SRick Macklem binuptime(&start_time);
8961d171e79SRick Macklem nfsrvd_statstart(op, &start_time);
8971d171e79SRick Macklem statsinprog = 1;
8981d171e79SRick Macklem
899c59e4cc3SRick Macklem if (i == 0)
900c59e4cc3SRick Macklem op0 = op;
901c59e4cc3SRick Macklem if (i == numops - 1)
902c59e4cc3SRick Macklem nd->nd_flag |= ND_LASTOP;
9039ec7b004SRick Macklem
9049ec7b004SRick Macklem /*
9059ec7b004SRick Macklem * Check for a referral on the current FH and, if so, return
9069ec7b004SRick Macklem * NFSERR_MOVED for all ops that allow it, except Getattr.
9079ec7b004SRick Macklem */
9089ec7b004SRick Macklem if (vp != NULL && op != NFSV4OP_GETATTR &&
9099ec7b004SRick Macklem nfsv4root_getreferral(vp, NULL, 0) != NULL &&
9109ec7b004SRick Macklem nfsrv_errmoved(op)) {
9119ec7b004SRick Macklem nd->nd_repstat = NFSERR_MOVED;
9129ec7b004SRick Macklem *repp = nfsd_errmap(nd);
9139ec7b004SRick Macklem retops++;
9149ec7b004SRick Macklem break;
9159ec7b004SRick Macklem }
9169ec7b004SRick Macklem
917c59e4cc3SRick Macklem /*
918c59e4cc3SRick Macklem * For NFSv4.1, check for a Sequence Operation being first
919c59e4cc3SRick Macklem * or one of the other allowed operations by itself.
920c59e4cc3SRick Macklem */
921c59e4cc3SRick Macklem if ((nd->nd_flag & ND_NFSV41) != 0) {
922c59e4cc3SRick Macklem if (i != 0 && op == NFSV4OP_SEQUENCE)
923c59e4cc3SRick Macklem nd->nd_repstat = NFSERR_SEQUENCEPOS;
924c59e4cc3SRick Macklem else if (i == 0 && op != NFSV4OP_SEQUENCE &&
925c59e4cc3SRick Macklem op != NFSV4OP_EXCHANGEID &&
926c59e4cc3SRick Macklem op != NFSV4OP_CREATESESSION &&
927c59e4cc3SRick Macklem op != NFSV4OP_BINDCONNTOSESS &&
928c59e4cc3SRick Macklem op != NFSV4OP_DESTROYCLIENTID &&
929c59e4cc3SRick Macklem op != NFSV4OP_DESTROYSESSION)
930c59e4cc3SRick Macklem nd->nd_repstat = NFSERR_OPNOTINSESS;
931c59e4cc3SRick Macklem else if (i != 0 && op0 != NFSV4OP_SEQUENCE)
932c59e4cc3SRick Macklem nd->nd_repstat = NFSERR_NOTONLYOP;
933c59e4cc3SRick Macklem if (nd->nd_repstat != 0) {
934c59e4cc3SRick Macklem *repp = nfsd_errmap(nd);
935c59e4cc3SRick Macklem retops++;
936c59e4cc3SRick Macklem break;
937c59e4cc3SRick Macklem }
938c59e4cc3SRick Macklem }
939c59e4cc3SRick Macklem
9409ec7b004SRick Macklem nd->nd_procnum = op;
9419ec7b004SRick Macklem /*
9429ec7b004SRick Macklem * If over flood level, reply NFSERR_RESOURCE, if at the first
9439ec7b004SRick Macklem * Op. (Since a client recovery from NFSERR_RESOURCE can get
9449ec7b004SRick Macklem * really nasty for certain Op sequences, I'll play it safe
9459ec7b004SRick Macklem * and only return the error at the beginning.) The cache
9469ec7b004SRick Macklem * will still function over flood level, but uses lots of
9479ec7b004SRick Macklem * mbufs.)
9489ec7b004SRick Macklem * If nfsrv_mallocmget_limit() returns True, the system is near
9499ec7b004SRick Macklem * to its limit for memory that malloc()/mget() can allocate.
9509ec7b004SRick Macklem */
951c59e4cc3SRick Macklem if (i == 0 && (nd->nd_rp == NULL ||
952c59e4cc3SRick Macklem nd->nd_rp->rc_refcnt == 0) &&
9539ec7b004SRick Macklem (nfsrv_mallocmget_limit() ||
9547e44856eSRick Macklem NFSD_VNET(nfsrc_tcpsavedreplies) >
9557e44856eSRick Macklem NFSD_VNET(nfsrc_floodlevel))) {
9567e44856eSRick Macklem if (NFSD_VNET(nfsrc_tcpsavedreplies) >
9577e44856eSRick Macklem NFSD_VNET(nfsrc_floodlevel))
95803738f60SRick Macklem printf("nfsd server cache flooded, try "
95903738f60SRick Macklem "increasing vfs.nfsd.tcphighwater\n");
9609ec7b004SRick Macklem nd->nd_repstat = NFSERR_RESOURCE;
9619ec7b004SRick Macklem *repp = nfsd_errmap(nd);
9629ec7b004SRick Macklem if (op == NFSV4OP_SETATTR) {
9639ec7b004SRick Macklem /*
9649ec7b004SRick Macklem * Setattr replies require a bitmap.
9659ec7b004SRick Macklem * even for errors like these.
9669ec7b004SRick Macklem */
9679ec7b004SRick Macklem NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
9689ec7b004SRick Macklem *tl = 0;
9699ec7b004SRick Macklem }
9709ec7b004SRick Macklem retops++;
9719ec7b004SRick Macklem break;
9729ec7b004SRick Macklem }
973ff2f1f69SRick Macklem
974ff2f1f69SRick Macklem /*
975ff2f1f69SRick Macklem * Check for the case of SP4_MACH_CRED and an operation in
976ff2f1f69SRick Macklem * the allow set. For these operations, replace nd_cred with
977ff2f1f69SRick Macklem * root credentials so that the operation will not fail due
978ff2f1f69SRick Macklem * to credentials.
979ff2f1f69SRick Macklem * NB: ND_MACHCRED is set by Sequence when the ClientID
980ff2f1f69SRick Macklem * specifies LCL_MACHCRED and the RPC is being performed
981ff2f1f69SRick Macklem * via krb5i or krb5p using the machine principal.
982ff2f1f69SRick Macklem */
983ff2f1f69SRick Macklem if ((nd->nd_flag & ND_MACHCRED) != 0) {
984ff2f1f69SRick Macklem if (NFSISSET_OPBIT(&nd->nd_allowops, op)) {
985ff2f1f69SRick Macklem /* Replace nd_cred with root creds. */
986ff2f1f69SRick Macklem if (rootcred == NULL)
987ff2f1f69SRick Macklem rootcred = nfsrv_createrootcred();
988ff2f1f69SRick Macklem if (savecred == NULL)
989ff2f1f69SRick Macklem savecred = nd->nd_cred;
990ff2f1f69SRick Macklem nd->nd_cred = rootcred;
991ff2f1f69SRick Macklem } else if (savecred != NULL) {
992ff2f1f69SRick Macklem nd->nd_cred = savecred;
993ff2f1f69SRick Macklem savecred = NULL;
994ff2f1f69SRick Macklem }
995ff2f1f69SRick Macklem }
996ff2f1f69SRick Macklem
9979ec7b004SRick Macklem if (nfsv4_opflag[op].savereply)
9989ec7b004SRick Macklem nd->nd_flag |= ND_SAVEREPLY;
9999ec7b004SRick Macklem switch (op) {
10009ec7b004SRick Macklem case NFSV4OP_PUTFH:
10019ec7b004SRick Macklem error = nfsrv_mtofh(nd, &fh);
10029ec7b004SRick Macklem if (error)
10039ec7b004SRick Macklem goto nfsmout;
1004d224f05fSRick Macklem if ((nd->nd_flag & ND_LASTOP) == 0) {
1005d224f05fSRick Macklem /*
1006d224f05fSRick Macklem * Pre-parse the next op#. If it is
1007d224f05fSRick Macklem * SaveFH, count it and skip to the
1008d224f05fSRick Macklem * next op#, if not the last op#.
1009d224f05fSRick Macklem * nextop is used to determine if
1010d224f05fSRick Macklem * NFSERR_WRONGSEC can be returned,
1011d224f05fSRick Macklem * per RFC5661 Sec. 2.6.
1012d224f05fSRick Macklem */
1013d224f05fSRick Macklem do {
1014d224f05fSRick Macklem NFSM_DISSECT(tl, uint32_t *,
1015d224f05fSRick Macklem NFSX_UNSIGNED);
1016d224f05fSRick Macklem nextop = fxdr_unsigned(int, *tl);
1017d224f05fSRick Macklem if (nextop == NFSV4OP_SAVEFH &&
1018d224f05fSRick Macklem i < numops - 1)
1019d224f05fSRick Macklem savefhcnt++;
1020d224f05fSRick Macklem } while (nextop == NFSV4OP_SAVEFH &&
1021d224f05fSRick Macklem i < numops - 1);
1022d224f05fSRick Macklem }
10238974bc2fSRick Macklem if (!nd->nd_repstat)
10248974bc2fSRick Macklem nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
1025a5df139eSRick Macklem NULL, 0, nextop);
10269ec7b004SRick Macklem /* For now, allow this for non-export FHs */
10279ec7b004SRick Macklem if (!nd->nd_repstat) {
10289ec7b004SRick Macklem if (vp)
10299ec7b004SRick Macklem vrele(vp);
10309ec7b004SRick Macklem vp = nvp;
10318974bc2fSRick Macklem cur_fsid = vp->v_mount->mnt_stat.f_fsid;
1032b249ce48SMateusz Guzik NFSVOPUNLOCK(vp);
10339ec7b004SRick Macklem vpnes = nes;
10349ec7b004SRick Macklem }
10359ec7b004SRick Macklem break;
10369ec7b004SRick Macklem case NFSV4OP_PUTPUBFH:
1037d224f05fSRick Macklem if (nfs_pubfhset) {
1038d224f05fSRick Macklem if ((nd->nd_flag & ND_LASTOP) == 0) {
1039d224f05fSRick Macklem /*
1040d224f05fSRick Macklem * Pre-parse the next op#. If it is
1041d224f05fSRick Macklem * SaveFH, count it and skip to the
1042d224f05fSRick Macklem * next op#, if not the last op#.
1043d224f05fSRick Macklem * nextop is used to determine if
1044d224f05fSRick Macklem * NFSERR_WRONGSEC can be returned,
1045d224f05fSRick Macklem * per RFC5661 Sec. 2.6.
1046d224f05fSRick Macklem */
1047d224f05fSRick Macklem do {
1048d224f05fSRick Macklem NFSM_DISSECT(tl, uint32_t *,
1049d224f05fSRick Macklem NFSX_UNSIGNED);
1050d224f05fSRick Macklem nextop = fxdr_unsigned(int,
1051d224f05fSRick Macklem *tl);
1052d224f05fSRick Macklem if (nextop == NFSV4OP_SAVEFH &&
1053d224f05fSRick Macklem i < numops - 1)
1054d224f05fSRick Macklem savefhcnt++;
1055d224f05fSRick Macklem } while (nextop == NFSV4OP_SAVEFH &&
1056d224f05fSRick Macklem i < numops - 1);
1057d224f05fSRick Macklem }
105817891d00SRick Macklem nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
1059a5df139eSRick Macklem &nes, NULL, 0, nextop);
1060d224f05fSRick Macklem } else
10619ec7b004SRick Macklem nd->nd_repstat = NFSERR_NOFILEHANDLE;
10629ec7b004SRick Macklem if (!nd->nd_repstat) {
10639ec7b004SRick Macklem if (vp)
10649ec7b004SRick Macklem vrele(vp);
10659ec7b004SRick Macklem vp = nvp;
10668974bc2fSRick Macklem cur_fsid = vp->v_mount->mnt_stat.f_fsid;
1067b249ce48SMateusz Guzik NFSVOPUNLOCK(vp);
10689ec7b004SRick Macklem vpnes = nes;
10699ec7b004SRick Macklem }
10709ec7b004SRick Macklem break;
10719ec7b004SRick Macklem case NFSV4OP_PUTROOTFH:
10727e44856eSRick Macklem if (NFSD_VNET(nfs_rootfhset)) {
1073d224f05fSRick Macklem if ((nd->nd_flag & ND_LASTOP) == 0) {
1074d224f05fSRick Macklem /*
1075d224f05fSRick Macklem * Pre-parse the next op#. If it is
1076d224f05fSRick Macklem * SaveFH, count it and skip to the
1077d224f05fSRick Macklem * next op#, if not the last op#.
1078d224f05fSRick Macklem * nextop is used to determine if
1079d224f05fSRick Macklem * NFSERR_WRONGSEC can be returned,
1080d224f05fSRick Macklem * per RFC5661 Sec. 2.6.
1081d224f05fSRick Macklem */
1082d224f05fSRick Macklem do {
1083d224f05fSRick Macklem NFSM_DISSECT(tl, uint32_t *,
1084d224f05fSRick Macklem NFSX_UNSIGNED);
1085d224f05fSRick Macklem nextop = fxdr_unsigned(int,
1086d224f05fSRick Macklem *tl);
1087d224f05fSRick Macklem if (nextop == NFSV4OP_SAVEFH &&
1088d224f05fSRick Macklem i < numops - 1)
1089d224f05fSRick Macklem savefhcnt++;
1090d224f05fSRick Macklem } while (nextop == NFSV4OP_SAVEFH &&
1091d224f05fSRick Macklem i < numops - 1);
1092d224f05fSRick Macklem }
10937e44856eSRick Macklem nfsd_fhtovp(nd, &NFSD_VNET(nfs_rootfh),
10947e44856eSRick Macklem LK_SHARED, &nvp, &nes, NULL, 0, nextop);
10959ec7b004SRick Macklem if (!nd->nd_repstat) {
10969ec7b004SRick Macklem if (vp)
10979ec7b004SRick Macklem vrele(vp);
10989ec7b004SRick Macklem vp = nvp;
10998974bc2fSRick Macklem cur_fsid = vp->v_mount->mnt_stat.f_fsid;
1100b249ce48SMateusz Guzik NFSVOPUNLOCK(vp);
11019ec7b004SRick Macklem vpnes = nes;
11029ec7b004SRick Macklem }
1103c9aad40fSRick Macklem } else
11049ec7b004SRick Macklem nd->nd_repstat = NFSERR_NOFILEHANDLE;
11059ec7b004SRick Macklem break;
11069ec7b004SRick Macklem case NFSV4OP_SAVEFH:
11079ec7b004SRick Macklem if (vp && NFSVNO_EXPORTED(&vpnes)) {
11089ec7b004SRick Macklem nd->nd_repstat = 0;
11099ec7b004SRick Macklem /* If vp == savevp, a no-op */
11109ec7b004SRick Macklem if (vp != savevp) {
11119ec7b004SRick Macklem if (savevp)
11129ec7b004SRick Macklem vrele(savevp);
11139ec7b004SRick Macklem VREF(vp);
11149ec7b004SRick Macklem savevp = vp;
11159ec7b004SRick Macklem savevpnes = vpnes;
11168974bc2fSRick Macklem save_fsid = cur_fsid;
11179ec7b004SRick Macklem }
111890d2dfabSRick Macklem if ((nd->nd_flag & ND_CURSTATEID) != 0) {
111990d2dfabSRick Macklem nd->nd_savedcurstateid =
112090d2dfabSRick Macklem nd->nd_curstateid;
112190d2dfabSRick Macklem nd->nd_flag |= ND_SAVEDCURSTATEID;
112290d2dfabSRick Macklem }
11239ec7b004SRick Macklem } else {
11249ec7b004SRick Macklem nd->nd_repstat = NFSERR_NOFILEHANDLE;
11259ec7b004SRick Macklem }
11269ec7b004SRick Macklem break;
11279ec7b004SRick Macklem case NFSV4OP_RESTOREFH:
11289ec7b004SRick Macklem if (savevp) {
1129d224f05fSRick Macklem if ((nd->nd_flag & ND_LASTOP) == 0) {
1130d224f05fSRick Macklem /*
1131d224f05fSRick Macklem * Pre-parse the next op#. If it is
1132d224f05fSRick Macklem * SaveFH, count it and skip to the
1133d224f05fSRick Macklem * next op#, if not the last op#.
1134d224f05fSRick Macklem * nextop is used to determine if
1135d224f05fSRick Macklem * NFSERR_WRONGSEC can be returned,
1136d224f05fSRick Macklem * per RFC5661 Sec. 2.6.
1137d224f05fSRick Macklem */
1138d224f05fSRick Macklem do {
1139d224f05fSRick Macklem NFSM_DISSECT(tl, uint32_t *,
1140d224f05fSRick Macklem NFSX_UNSIGNED);
1141d224f05fSRick Macklem nextop = fxdr_unsigned(int,
1142d224f05fSRick Macklem *tl);
1143d224f05fSRick Macklem if (nextop == NFSV4OP_SAVEFH &&
1144d224f05fSRick Macklem i < numops - 1)
1145d224f05fSRick Macklem savefhcnt++;
1146d224f05fSRick Macklem } while (nextop == NFSV4OP_SAVEFH &&
1147d224f05fSRick Macklem i < numops - 1);
1148d224f05fSRick Macklem }
11499ec7b004SRick Macklem nd->nd_repstat = 0;
11509ec7b004SRick Macklem /* If vp == savevp, a no-op */
11519ec7b004SRick Macklem if (vp != savevp) {
1152a5df139eSRick Macklem if (nfsrv_checkwrongsec(nd, nextop,
1153a5df139eSRick Macklem savevp->v_type))
1154a5df139eSRick Macklem nd->nd_repstat =
1155a5df139eSRick Macklem nfsvno_testexp(nd,
1156a5df139eSRick Macklem &savevpnes);
1157a5df139eSRick Macklem if (nd->nd_repstat == 0) {
11589ec7b004SRick Macklem VREF(savevp);
11599ec7b004SRick Macklem vrele(vp);
11609ec7b004SRick Macklem vp = savevp;
11619ec7b004SRick Macklem vpnes = savevpnes;
11628974bc2fSRick Macklem cur_fsid = save_fsid;
11639ec7b004SRick Macklem }
1164a5df139eSRick Macklem }
1165a5df139eSRick Macklem if (nd->nd_repstat == 0 &&
1166a5df139eSRick Macklem (nd->nd_flag & ND_SAVEDCURSTATEID) != 0) {
116790d2dfabSRick Macklem nd->nd_curstateid =
116890d2dfabSRick Macklem nd->nd_savedcurstateid;
116990d2dfabSRick Macklem nd->nd_flag |= ND_CURSTATEID;
117090d2dfabSRick Macklem }
11719ec7b004SRick Macklem } else {
11729ec7b004SRick Macklem nd->nd_repstat = NFSERR_RESTOREFH;
11739ec7b004SRick Macklem }
11749ec7b004SRick Macklem break;
11759ec7b004SRick Macklem default:
11769ec7b004SRick Macklem /*
11779ec7b004SRick Macklem * Allow a Lookup, Getattr, GetFH, Secinfo on an
11789ec7b004SRick Macklem * non-exported directory if
11799ec7b004SRick Macklem * nfs_rootfhset. Do I need to allow any other Ops?
11809ec7b004SRick Macklem * (You can only have a non-exported vpnes if
11819ec7b004SRick Macklem * nfs_rootfhset is true. See nfsd_fhtovp())
11829ec7b004SRick Macklem * Allow AUTH_SYS to be used for file systems
11839ec7b004SRick Macklem * exported GSS only for certain Ops, to allow
11849ec7b004SRick Macklem * clients to do mounts more easily.
11859ec7b004SRick Macklem */
11869ec7b004SRick Macklem if (nfsv4_opflag[op].needscfh && vp) {
11879ec7b004SRick Macklem if (!NFSVNO_EXPORTED(&vpnes) &&
11889ec7b004SRick Macklem op != NFSV4OP_LOOKUP &&
11899ec7b004SRick Macklem op != NFSV4OP_GETATTR &&
11909ec7b004SRick Macklem op != NFSV4OP_GETFH &&
11915a55e04fSRick Macklem op != NFSV4OP_ACCESS &&
11925a55e04fSRick Macklem op != NFSV4OP_READLINK &&
1193a5df139eSRick Macklem op != NFSV4OP_SECINFO &&
1194a5df139eSRick Macklem op != NFSV4OP_SECINFONONAME)
11959ec7b004SRick Macklem nd->nd_repstat = NFSERR_NOFILEHANDLE;
11969ec7b004SRick Macklem if (nd->nd_repstat) {
11979ec7b004SRick Macklem if (op == NFSV4OP_SETATTR) {
11989ec7b004SRick Macklem /*
11999ec7b004SRick Macklem * Setattr reply requires a bitmap
12009ec7b004SRick Macklem * even for errors like these.
12019ec7b004SRick Macklem */
12029ec7b004SRick Macklem NFSM_BUILD(tl, u_int32_t *,
12039ec7b004SRick Macklem NFSX_UNSIGNED);
12049ec7b004SRick Macklem *tl = 0;
12059ec7b004SRick Macklem }
12069ec7b004SRick Macklem break;
12079ec7b004SRick Macklem }
12089ec7b004SRick Macklem }
1209774a3685SRick Macklem
1210774a3685SRick Macklem /*
1211774a3685SRick Macklem * Save the current positions in the mbuf lists so
1212774a3685SRick Macklem * that a rollback to this location can be done upon a
1213774a3685SRick Macklem * redo due to a ERELOOKUP return for a operation.
1214774a3685SRick Macklem */
1215774a3685SRick Macklem mb = nd->nd_mb;
1216774a3685SRick Macklem bpos = nd->nd_bpos;
1217774a3685SRick Macklem bextpg = nd->nd_bextpg;
1218774a3685SRick Macklem bextpgsiz = nd->nd_bextpgsiz;
1219774a3685SRick Macklem md = nd->nd_md;
1220774a3685SRick Macklem dpos = nd->nd_dpos;
1221774a3685SRick Macklem tryagain:
1222774a3685SRick Macklem
12239ec7b004SRick Macklem if (nfsv4_opflag[op].retfh == 1) {
12249ec7b004SRick Macklem if (!vp) {
12259ec7b004SRick Macklem nd->nd_repstat = NFSERR_NOFILEHANDLE;
12269ec7b004SRick Macklem break;
12279ec7b004SRick Macklem }
1228a5df139eSRick Macklem if (NFSVNO_EXPORTED(&vpnes) && (op == NFSV4OP_LOOKUP ||
1229a5df139eSRick Macklem op == NFSV4OP_LOOKUPP || (op == NFSV4OP_OPEN &&
1230a5df139eSRick Macklem vp->v_type == VDIR))) {
1231a5df139eSRick Macklem /* Check for wrong security. */
1232a5df139eSRick Macklem rstat = nfsvno_testexp(nd, &vpnes);
1233a5df139eSRick Macklem if (rstat != 0) {
1234a5df139eSRick Macklem nd->nd_repstat = rstat;
1235a5df139eSRick Macklem break;
1236a5df139eSRick Macklem }
1237a5df139eSRick Macklem }
12389ec7b004SRick Macklem VREF(vp);
12399ec7b004SRick Macklem if (nfsv4_opflag[op].modifyfs)
1240785f073bSRick Macklem vn_start_write(vp, &temp_mp, V_WAIT);
12419ec7b004SRick Macklem error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
1242af444b18SEdward Tomasz Napierala &nvp, (fhandle_t *)fh.nfsrvfh_data, &vpnes);
12439ec7b004SRick Macklem if (!error && !nd->nd_repstat) {
12448974bc2fSRick Macklem if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) {
12458974bc2fSRick Macklem new_mp = nvp->v_mount;
1246245bfd34SRyan Moeller if (fsidcmp(&cur_fsid, &new_mp->mnt_stat.f_fsid) != 0) {
12478974bc2fSRick Macklem /* crossed a server mount point */
12488974bc2fSRick Macklem nd->nd_repstat = nfsvno_checkexp(new_mp,
12499ec7b004SRick Macklem nd->nd_nam, &nes, &credanon);
12509ec7b004SRick Macklem if (!nd->nd_repstat)
12519ec7b004SRick Macklem nd->nd_repstat = nfsd_excred(nd,
1252a5df139eSRick Macklem &nes, credanon, true);
12535679fe19SAlexander Kabaev if (credanon != NULL)
12545679fe19SAlexander Kabaev crfree(credanon);
12559ec7b004SRick Macklem if (!nd->nd_repstat) {
12569ec7b004SRick Macklem vpnes = nes;
12578974bc2fSRick Macklem cur_fsid = new_mp->mnt_stat.f_fsid;
12589ec7b004SRick Macklem }
12599ec7b004SRick Macklem }
126081f78d99SRick Macklem /* Lookup ops return a locked vnode */
1261b249ce48SMateusz Guzik NFSVOPUNLOCK(nvp);
12628974bc2fSRick Macklem }
12639ec7b004SRick Macklem if (!nd->nd_repstat) {
12649ec7b004SRick Macklem vrele(vp);
12659ec7b004SRick Macklem vp = nvp;
126681f78d99SRick Macklem } else
126781f78d99SRick Macklem vrele(nvp);
12689ec7b004SRick Macklem }
12699ec7b004SRick Macklem if (nfsv4_opflag[op].modifyfs)
1270785f073bSRick Macklem vn_finished_write(temp_mp);
12719ec7b004SRick Macklem } else if (nfsv4_opflag[op].retfh == 2) {
12729ec7b004SRick Macklem if (vp == NULL || savevp == NULL) {
12739ec7b004SRick Macklem nd->nd_repstat = NFSERR_NOFILEHANDLE;
12749ec7b004SRick Macklem break;
1275245bfd34SRyan Moeller } else if (fsidcmp(&cur_fsid, &save_fsid) != 0) {
12769ec7b004SRick Macklem nd->nd_repstat = NFSERR_XDEV;
12779ec7b004SRick Macklem break;
12789ec7b004SRick Macklem }
12799ec7b004SRick Macklem if (nfsv4_opflag[op].modifyfs)
1280785f073bSRick Macklem vn_start_write(savevp, &temp_mp, V_WAIT);
128198f234f3SZack Kirsch if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
1282629fa50eSRick Macklem VREF(vp);
1283629fa50eSRick Macklem VREF(savevp);
1284629fa50eSRick Macklem error = (*(nfsrv4_ops2[op]))(nd, isdgram,
1285af444b18SEdward Tomasz Napierala savevp, vp, &savevpnes, &vpnes);
1286629fa50eSRick Macklem } else
1287629fa50eSRick Macklem nd->nd_repstat = NFSERR_PERM;
12889ec7b004SRick Macklem if (nfsv4_opflag[op].modifyfs)
1289785f073bSRick Macklem vn_finished_write(temp_mp);
12909ec7b004SRick Macklem } else {
12919ec7b004SRick Macklem if (nfsv4_opflag[op].retfh != 0)
12929ec7b004SRick Macklem panic("nfsrvd_compound");
12939ec7b004SRick Macklem if (nfsv4_opflag[op].needscfh) {
129417891d00SRick Macklem if (vp != NULL) {
12950c419e22SRick Macklem lktype = nfsv4_opflag[op].lktype;
12960c419e22SRick Macklem if (nfsv4_opflag[op].modifyfs) {
1297785f073bSRick Macklem vn_start_write(vp, &temp_mp,
1298785f073bSRick Macklem V_WAIT);
12990c419e22SRick Macklem if (op == NFSV4OP_WRITE &&
13000c419e22SRick Macklem MNT_SHARED_WRITES(temp_mp))
13010c419e22SRick Macklem lktype = LK_SHARED;
13020c419e22SRick Macklem }
13030c419e22SRick Macklem if (NFSVOPLOCK(vp, lktype) == 0)
1304629fa50eSRick Macklem VREF(vp);
1305629fa50eSRick Macklem else
130617891d00SRick Macklem nd->nd_repstat = NFSERR_PERM;
1307629fa50eSRick Macklem } else {
13089ec7b004SRick Macklem nd->nd_repstat = NFSERR_NOFILEHANDLE;
13099ec7b004SRick Macklem if (op == NFSV4OP_SETATTR) {
13109ec7b004SRick Macklem /*
131117891d00SRick Macklem * Setattr reply requires a
131217891d00SRick Macklem * bitmap even for errors like
131317891d00SRick Macklem * these.
13149ec7b004SRick Macklem */
13159ec7b004SRick Macklem NFSM_BUILD(tl, u_int32_t *,
13169ec7b004SRick Macklem NFSX_UNSIGNED);
13179ec7b004SRick Macklem *tl = 0;
13189ec7b004SRick Macklem }
13199ec7b004SRick Macklem break;
13209ec7b004SRick Macklem }
1321947bd247SRick Macklem if (nd->nd_repstat == 0) {
1322629fa50eSRick Macklem error = (*(nfsrv4_ops0[op]))(nd,
1323af444b18SEdward Tomasz Napierala isdgram, vp, &vpnes);
1324947bd247SRick Macklem if ((op == NFSV4OP_SECINFO ||
1325947bd247SRick Macklem op == NFSV4OP_SECINFONONAME) &&
1326947bd247SRick Macklem error == 0 && nd->nd_repstat == 0) {
1327947bd247SRick Macklem /*
1328947bd247SRick Macklem * Secinfo and Secinfo_no_name
1329947bd247SRick Macklem * consume the current FH.
1330947bd247SRick Macklem */
1331947bd247SRick Macklem vrele(vp);
1332947bd247SRick Macklem vp = NULL;
1333947bd247SRick Macklem }
1334947bd247SRick Macklem }
13359ec7b004SRick Macklem if (nfsv4_opflag[op].modifyfs)
1336785f073bSRick Macklem vn_finished_write(temp_mp);
13379ec7b004SRick Macklem } else {
13389ec7b004SRick Macklem error = (*(nfsrv4_ops0[op]))(nd, isdgram,
1339af444b18SEdward Tomasz Napierala NULL, &vpnes);
13409ec7b004SRick Macklem }
13419ec7b004SRick Macklem }
134274b8d63dSPedro F. Giffuni }
13439ec7b004SRick Macklem if (error) {
13449ec7b004SRick Macklem if (error == EBADRPC || error == NFSERR_BADXDR) {
13459ec7b004SRick Macklem nd->nd_repstat = NFSERR_BADXDR;
13469ec7b004SRick Macklem } else {
13479ec7b004SRick Macklem nd->nd_repstat = error;
13489ec7b004SRick Macklem printf("nfsv4 comperr0=%d\n", error);
13499ec7b004SRick Macklem }
13509ec7b004SRick Macklem error = 0;
13519ec7b004SRick Macklem }
13521b819cf2SRick Macklem
1353774a3685SRick Macklem if (nd->nd_repstat == ERELOOKUP) {
1354774a3685SRick Macklem /*
1355774a3685SRick Macklem * Roll back to the beginning of the operation
1356774a3685SRick Macklem * arguments.
1357774a3685SRick Macklem */
1358774a3685SRick Macklem nd->nd_md = md;
1359774a3685SRick Macklem nd->nd_dpos = dpos;
1360774a3685SRick Macklem
1361774a3685SRick Macklem /*
1362774a3685SRick Macklem * Trim off the bogus reply for this operation
1363774a3685SRick Macklem * and redo the operation.
1364774a3685SRick Macklem */
1365774a3685SRick Macklem nfsm_trimtrailing(nd, mb, bpos, bextpg, bextpgsiz);
1366774a3685SRick Macklem nd->nd_repstat = 0;
1367dc78533aSRick Macklem nd->nd_flag |= ND_ERELOOKUP;
1368774a3685SRick Macklem goto tryagain;
1369774a3685SRick Macklem }
1370dc78533aSRick Macklem nd->nd_flag &= ~ND_ERELOOKUP;
1371774a3685SRick Macklem
13721b819cf2SRick Macklem if (statsinprog != 0) {
13731b819cf2SRick Macklem nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
13741b819cf2SRick Macklem /*then*/ &start_time);
13751b819cf2SRick Macklem statsinprog = 0;
13761b819cf2SRick Macklem }
13771b819cf2SRick Macklem
13789ec7b004SRick Macklem retops++;
13799ec7b004SRick Macklem if (nd->nd_repstat) {
13809ec7b004SRick Macklem *repp = nfsd_errmap(nd);
13819ec7b004SRick Macklem break;
13829ec7b004SRick Macklem } else {
13839ec7b004SRick Macklem *repp = 0; /* NFS4_OK */
13849ec7b004SRick Macklem }
13859ec7b004SRick Macklem }
13869ec7b004SRick Macklem nfsmout:
13871b819cf2SRick Macklem if (statsinprog != 0) {
13881b819cf2SRick Macklem nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
13891b819cf2SRick Macklem /*then*/ &start_time);
13901b819cf2SRick Macklem statsinprog = 0;
13911b819cf2SRick Macklem }
13929ec7b004SRick Macklem if (error) {
13939ec7b004SRick Macklem if (error == EBADRPC || error == NFSERR_BADXDR)
13949ec7b004SRick Macklem nd->nd_repstat = NFSERR_BADXDR;
13959ec7b004SRick Macklem else
13969ec7b004SRick Macklem printf("nfsv4 comperr1=%d\n", error);
13979ec7b004SRick Macklem }
13989ec7b004SRick Macklem if (taglen == -1) {
13999ec7b004SRick Macklem NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
14009ec7b004SRick Macklem *tl++ = 0;
14019ec7b004SRick Macklem *tl = 0;
14029ec7b004SRick Macklem } else {
14039ec7b004SRick Macklem *retopsp = txdr_unsigned(retops);
14049ec7b004SRick Macklem }
14059ec7b004SRick Macklem if (vp)
14069ec7b004SRick Macklem vrele(vp);
14079ec7b004SRick Macklem if (savevp)
14089ec7b004SRick Macklem vrele(savevp);
1409ff2f1f69SRick Macklem if (savecred != NULL)
1410ff2f1f69SRick Macklem nd->nd_cred = savecred;
1411ff2f1f69SRick Macklem if (rootcred != NULL)
1412ff2f1f69SRick Macklem crfree(rootcred);
14139ec7b004SRick Macklem NFSLOCKV4ROOTMUTEX();
14149ec7b004SRick Macklem nfsv4_relref(&nfsv4rootfs_lock);
14159ec7b004SRick Macklem NFSUNLOCKV4ROOTMUTEX();
1416a9285ae5SZack Kirsch
1417a9285ae5SZack Kirsch NFSEXITCODE2(0, nd);
14189ec7b004SRick Macklem }
1419ff2f1f69SRick Macklem
1420ff2f1f69SRick Macklem /* Create a credential for "root". */
1421ff2f1f69SRick Macklem static struct ucred *
nfsrv_createrootcred(void)1422ff2f1f69SRick Macklem nfsrv_createrootcred(void)
1423ff2f1f69SRick Macklem {
1424ff2f1f69SRick Macklem struct ucred *cr;
1425ff2f1f69SRick Macklem gid_t grp;
1426ff2f1f69SRick Macklem
1427ff2f1f69SRick Macklem cr = crget();
1428ff2f1f69SRick Macklem cr->cr_uid = cr->cr_ruid = cr->cr_svuid = UID_ROOT;
1429ff2f1f69SRick Macklem grp = GID_WHEEL;
1430ff2f1f69SRick Macklem crsetgroups(cr, 1, &grp);
1431ff2f1f69SRick Macklem cr->cr_rgid = cr->cr_svgid = cr->cr_groups[0];
1432ff2f1f69SRick Macklem cr->cr_prison = curthread->td_ucred->cr_prison;
1433ff2f1f69SRick Macklem prison_hold(cr->cr_prison);
1434ff2f1f69SRick Macklem #ifdef MAC
1435ff2f1f69SRick Macklem mac_cred_associate_nfsd(cr);
1436ff2f1f69SRick Macklem #endif
1437ff2f1f69SRick Macklem return (cr);
1438ff2f1f69SRick Macklem }
1439