xref: /freebsd/sys/fs/nfsserver/nfs_nfsdsocket.c (revision 3d265fce43746c293ae826e9603adbfe09f93cf6)
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 1989, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Rick Macklem at The University of Guelph.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  */
35 
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
38 
39 /*
40  * Socket operations for use by the nfs server.
41  */
42 
43 #include <fs/nfs/nfsport.h>
44 
45 extern struct nfsstatsv1 nfsstatsv1;
46 extern struct nfsrvfh nfs_pubfh, nfs_rootfh;
47 extern int nfs_pubfhset, nfs_rootfhset;
48 extern struct nfsv4lock nfsv4rootfs_lock;
49 extern struct nfsrv_stablefirst nfsrv_stablefirst;
50 extern struct nfsclienthashhead *nfsclienthash;
51 extern int nfsrv_clienthashsize;
52 extern int nfsrc_floodlevel, nfsrc_tcpsavedreplies;
53 extern int nfsd_debuglevel;
54 extern int nfsrv_layouthighwater;
55 extern volatile int nfsrv_layoutcnt;
56 NFSV4ROOTLOCKMUTEX;
57 NFSSTATESPINLOCK;
58 
59 int (*nfsrv3_procs0[NFS_V3NPROCS])(struct nfsrv_descript *,
60     int, vnode_t , struct nfsexstuff *) = {
61 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
62 	nfsrvd_getattr,
63 	nfsrvd_setattr,
64 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
65 	nfsrvd_access,
66 	nfsrvd_readlink,
67 	nfsrvd_read,
68 	nfsrvd_write,
69 	nfsrvd_create,
70 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
71 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
72 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
73 	nfsrvd_remove,
74 	nfsrvd_remove,
75 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
76 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
77 	nfsrvd_readdir,
78 	nfsrvd_readdirplus,
79 	nfsrvd_statfs,
80 	nfsrvd_fsinfo,
81 	nfsrvd_pathconf,
82 	nfsrvd_commit,
83 };
84 
85 int (*nfsrv3_procs1[NFS_V3NPROCS])(struct nfsrv_descript *,
86     int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *) = {
87 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
88 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
89 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
90 	nfsrvd_lookup,
91 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
92 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
93 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
94 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
95 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
96 	nfsrvd_mkdir,
97 	nfsrvd_symlink,
98 	nfsrvd_mknod,
99 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
100 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
101 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
102 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
103 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
104 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
105 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
106 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
107 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
108 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
109 };
110 
111 int (*nfsrv3_procs2[NFS_V3NPROCS])(struct nfsrv_descript *,
112     int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *) = {
113 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
114 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
115 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
116 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
117 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
118 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
119 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
120 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
121 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
122 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
123 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
124 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
125 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
126 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
127 	nfsrvd_rename,
128 	nfsrvd_link,
129 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
130 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
131 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
132 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
133 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
134 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
135 };
136 
137 int (*nfsrv4_ops0[NFSV42_NOPS])(struct nfsrv_descript *,
138     int, vnode_t , struct nfsexstuff *) = {
139 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
140 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
141 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
142 	nfsrvd_access,
143 	nfsrvd_close,
144 	nfsrvd_commit,
145 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
146 	nfsrvd_delegpurge,
147 	nfsrvd_delegreturn,
148 	nfsrvd_getattr,
149 	nfsrvd_getfh,
150 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
151 	nfsrvd_lock,
152 	nfsrvd_lockt,
153 	nfsrvd_locku,
154 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
155 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
156 	nfsrvd_verify,
157 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
158 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
159 	nfsrvd_openconfirm,
160 	nfsrvd_opendowngrade,
161 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
162 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
163 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
164 	nfsrvd_read,
165 	nfsrvd_readdirplus,
166 	nfsrvd_readlink,
167 	nfsrvd_remove,
168 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
169 	nfsrvd_renew,
170 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
171 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
172 	nfsrvd_secinfo,
173 	nfsrvd_setattr,
174 	nfsrvd_setclientid,
175 	nfsrvd_setclientidcfrm,
176 	nfsrvd_verify,
177 	nfsrvd_write,
178 	nfsrvd_releaselckown,
179 	nfsrvd_notsupp,
180 	nfsrvd_bindconnsess,
181 	nfsrvd_exchangeid,
182 	nfsrvd_createsession,
183 	nfsrvd_destroysession,
184 	nfsrvd_freestateid,
185 	nfsrvd_notsupp,
186 	nfsrvd_getdevinfo,
187 	nfsrvd_notsupp,
188 	nfsrvd_layoutcommit,
189 	nfsrvd_layoutget,
190 	nfsrvd_layoutreturn,
191 	nfsrvd_notsupp,
192 	nfsrvd_sequence,
193 	nfsrvd_notsupp,
194 	nfsrvd_teststateid,
195 	nfsrvd_notsupp,
196 	nfsrvd_destroyclientid,
197 	nfsrvd_reclaimcomplete,
198 	nfsrvd_allocate,
199 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
200 	nfsrvd_notsupp,
201 	nfsrvd_notsupp,
202 	nfsrvd_ioadvise,
203 	nfsrvd_layouterror,
204 	nfsrvd_layoutstats,
205 	nfsrvd_notsupp,
206 	nfsrvd_notsupp,
207 	nfsrvd_notsupp,
208 	nfsrvd_seek,
209 	nfsrvd_notsupp,
210 	nfsrvd_notsupp,
211 	nfsrvd_getxattr,
212 	nfsrvd_setxattr,
213 	nfsrvd_listxattr,
214 	nfsrvd_rmxattr,
215 };
216 
217 int (*nfsrv4_ops1[NFSV42_NOPS])(struct nfsrv_descript *,
218     int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *) = {
219 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
220 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
221 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
222 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
223 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
224 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
225 	nfsrvd_mknod,
226 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
227 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
228 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
229 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
230 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
231 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
232 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
233 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
234 	nfsrvd_lookup,
235 	nfsrvd_lookup,
236 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
237 	nfsrvd_open,
238 	nfsrvd_openattr,
239 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
240 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
241 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
242 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
243 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
244 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
245 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
246 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
247 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
248 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
249 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
250 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
251 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
252 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
253 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
254 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
255 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
256 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
257 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
258 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
259 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
260 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
261 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
262 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
263 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
264 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
265 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
266 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
267 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
268 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
269 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
270 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
271 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
272 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
273 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
274 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
275 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
276 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
277 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
278 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
279 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
280 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
281 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
282 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
283 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
284 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
285 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
286 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
287 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
288 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
289 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
290 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
291 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
292 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
293 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
294 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
295 };
296 
297 int (*nfsrv4_ops2[NFSV42_NOPS])(struct nfsrv_descript *,
298     int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *) = {
299 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
300 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
301 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
302 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
303 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
304 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
305 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
306 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
307 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
308 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
309 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
310 	nfsrvd_link,
311 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
312 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
313 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
314 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
315 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
316 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
317 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
318 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
319 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
320 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
321 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
322 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
323 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
324 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
325 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
326 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
327 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
328 	nfsrvd_rename,
329 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
330 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
331 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
332 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
333 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
334 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
335 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
336 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
337 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
338 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
339 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
340 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
341 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
342 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
343 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
344 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
345 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
346 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
347 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
348 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
349 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
350 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
351 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
352 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
353 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
354 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
355 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
356 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
357 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
358 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
359 	nfsrvd_copy_file_range,
360 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
361 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
362 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
363 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
364 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
365 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
366 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
367 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
368 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
369 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
370 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
371 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
372 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
373 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
374 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
375 };
376 
377 /*
378  * Static array that defines which nfs rpc's are nonidempotent
379  */
380 static int nfsrv_nonidempotent[NFS_V3NPROCS] = {
381 	FALSE,
382 	FALSE,
383 	TRUE,
384 	FALSE,
385 	FALSE,
386 	FALSE,
387 	FALSE,
388 	TRUE,
389 	TRUE,
390 	TRUE,
391 	TRUE,
392 	TRUE,
393 	TRUE,
394 	TRUE,
395 	TRUE,
396 	TRUE,
397 	FALSE,
398 	FALSE,
399 	FALSE,
400 	FALSE,
401 	FALSE,
402 	FALSE,
403 };
404 
405 /*
406  * This static array indicates whether or not the RPC modifies the
407  * file system.
408  */
409 int nfsrv_writerpc[NFS_NPROCS] = { 0, 0, 1, 0, 0, 0, 0,
410     1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
411     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
412 
413 SYSCTL_DECL(_vfs_nfsd);
414 static int	nfs_minminorv4 = NFSV4_MINORVERSION;
415 SYSCTL_INT(_vfs_nfsd, OID_AUTO, server_min_minorversion4, CTLFLAG_RWTUN,
416     &nfs_minminorv4, 0,
417     "The lowest minor version of NFSv4 handled by the server");
418 
419 static int	nfs_maxminorv4 = NFSV42_MINORVERSION;
420 SYSCTL_INT(_vfs_nfsd, OID_AUTO, server_max_minorversion4, CTLFLAG_RWTUN,
421     &nfs_maxminorv4, 0,
422     "The highest minor version of NFSv4 handled by the server");
423 
424 /* local functions */
425 static void nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
426     u_char *tag, int taglen, u_int32_t minorvers);
427 
428 /*
429  * This static array indicates which server procedures require the extra
430  * arguments to return the current file handle for V2, 3.
431  */
432 static int nfs_retfh[NFS_V3NPROCS] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1,
433 	1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0 };
434 
435 extern struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS];
436 
437 static int nfsv3to4op[NFS_V3NPROCS] = {
438 	NFSPROC_NULL,
439 	NFSV4OP_GETATTR,
440 	NFSV4OP_SETATTR,
441 	NFSV4OP_LOOKUP,
442 	NFSV4OP_ACCESS,
443 	NFSV4OP_READLINK,
444 	NFSV4OP_READ,
445 	NFSV4OP_WRITE,
446 	NFSV4OP_V3CREATE,
447 	NFSV4OP_MKDIR,
448 	NFSV4OP_SYMLINK,
449 	NFSV4OP_MKNOD,
450 	NFSV4OP_REMOVE,
451 	NFSV4OP_RMDIR,
452 	NFSV4OP_RENAME,
453 	NFSV4OP_LINK,
454 	NFSV4OP_READDIR,
455 	NFSV4OP_READDIRPLUS,
456 	NFSV4OP_FSSTAT,
457 	NFSV4OP_FSINFO,
458 	NFSV4OP_PATHCONF,
459 	NFSV4OP_COMMIT,
460 };
461 
462 static struct mtx nfsrvd_statmtx;
463 MTX_SYSINIT(nfsst, &nfsrvd_statmtx, "NFSstat", MTX_DEF);
464 
465 static void
466 nfsrvd_statstart(int op, struct bintime *now)
467 {
468 	if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
469 		printf("%s: op %d invalid\n", __func__, op);
470 		return;
471 	}
472 
473 	mtx_lock(&nfsrvd_statmtx);
474 	if (nfsstatsv1.srvstartcnt == nfsstatsv1.srvdonecnt) {
475 		if (now != NULL)
476 			nfsstatsv1.busyfrom = *now;
477 		else
478 			binuptime(&nfsstatsv1.busyfrom);
479 
480 	}
481 	nfsstatsv1.srvrpccnt[op]++;
482 	nfsstatsv1.srvstartcnt++;
483 	mtx_unlock(&nfsrvd_statmtx);
484 
485 }
486 
487 static void
488 nfsrvd_statend(int op, uint64_t bytes, struct bintime *now,
489     struct bintime *then)
490 {
491 	struct bintime dt, lnow;
492 
493 	if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
494 		printf("%s: op %d invalid\n", __func__, op);
495 		return;
496 	}
497 
498 	if (now == NULL) {
499 		now = &lnow;
500 		binuptime(now);
501 	}
502 
503 	mtx_lock(&nfsrvd_statmtx);
504 
505 	nfsstatsv1.srvbytes[op] += bytes;
506 	nfsstatsv1.srvops[op]++;
507 
508 	if (then != NULL) {
509 		dt = *now;
510 		bintime_sub(&dt, then);
511 		bintime_add(&nfsstatsv1.srvduration[op], &dt);
512 	}
513 
514 	dt = *now;
515 	bintime_sub(&dt, &nfsstatsv1.busyfrom);
516 	bintime_add(&nfsstatsv1.busytime, &dt);
517 	nfsstatsv1.busyfrom = *now;
518 
519 	nfsstatsv1.srvdonecnt++;
520 
521 	mtx_unlock(&nfsrvd_statmtx);
522 }
523 
524 /*
525  * Do an RPC. Basically, get the file handles translated to vnode pointers
526  * and then call the appropriate server routine. The server routines are
527  * split into groups, based on whether they use a file handle or file
528  * handle plus name or ...
529  * The NFS V4 Compound RPC is performed separately by nfsrvd_compound().
530  */
531 void
532 nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, u_char *tag, int taglen,
533     u_int32_t minorvers)
534 {
535 	int error = 0, lktype;
536 	vnode_t vp;
537 	mount_t mp = NULL;
538 	struct nfsrvfh fh;
539 	struct nfsexstuff nes;
540 
541 	/*
542 	 * Get a locked vnode for the first file handle
543 	 */
544 	if (!(nd->nd_flag & ND_NFSV4)) {
545 		KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc"));
546 		/*
547 		 * For NFSv3, if the malloc/mget allocation is near limits,
548 		 * return NFSERR_DELAY.
549 		 */
550 		if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) {
551 			nd->nd_repstat = NFSERR_DELAY;
552 			vp = NULL;
553 		} else {
554 			error = nfsrv_mtofh(nd, &fh);
555 			if (error) {
556 				if (error != EBADRPC)
557 					printf("nfs dorpc err1=%d\n", error);
558 				nd->nd_repstat = NFSERR_GARBAGE;
559 				goto out;
560 			}
561 			if (nd->nd_procnum == NFSPROC_READ ||
562 			    nd->nd_procnum == NFSPROC_WRITE ||
563 			    nd->nd_procnum == NFSPROC_READDIR ||
564 			    nd->nd_procnum == NFSPROC_READDIRPLUS ||
565 			    nd->nd_procnum == NFSPROC_READLINK ||
566 			    nd->nd_procnum == NFSPROC_GETATTR ||
567 			    nd->nd_procnum == NFSPROC_ACCESS ||
568 			    nd->nd_procnum == NFSPROC_FSSTAT ||
569 			    nd->nd_procnum == NFSPROC_FSINFO)
570 				lktype = LK_SHARED;
571 			else
572 				lktype = LK_EXCLUSIVE;
573 			if (nd->nd_flag & ND_PUBLOOKUP)
574 				nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes,
575 				    &mp, nfsrv_writerpc[nd->nd_procnum]);
576 			else
577 				nfsd_fhtovp(nd, &fh, lktype, &vp, &nes,
578 				    &mp, nfsrv_writerpc[nd->nd_procnum]);
579 			if (nd->nd_repstat == NFSERR_PROGNOTV4)
580 				goto out;
581 		}
582 	}
583 
584 	/*
585 	 * For V2 and 3, set the ND_SAVEREPLY flag for the recent request
586 	 * cache, as required.
587 	 * For V4, nfsrvd_compound() does this.
588 	 */
589 	if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum])
590 		nd->nd_flag |= ND_SAVEREPLY;
591 
592 	nfsrvd_rephead(nd);
593 	/*
594 	 * If nd_repstat is non-zero, just fill in the reply status
595 	 * to complete the RPC reply for V2. Otherwise, you must do
596 	 * the RPC.
597 	 */
598 	if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) {
599 		*nd->nd_errp = nfsd_errmap(nd);
600 		nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], /*now*/ NULL);
601 		nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
602 		   /*now*/ NULL, /*then*/ NULL);
603 		if (mp != NULL && nfsrv_writerpc[nd->nd_procnum] != 0)
604 			vn_finished_write(mp);
605 		goto out;
606 	}
607 
608 	/*
609 	 * Now the procedure can be performed. For V4, nfsrvd_compound()
610 	 * works through the sub-rpcs, otherwise just call the procedure.
611 	 * The procedures are in three groups with different arguments.
612 	 * The group is indicated by the value in nfs_retfh[].
613 	 */
614 	if (nd->nd_flag & ND_NFSV4) {
615 		nfsrvd_compound(nd, isdgram, tag, taglen, minorvers);
616 	} else {
617 		struct bintime start_time;
618 
619 		binuptime(&start_time);
620 		nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], &start_time);
621 
622 		if (nfs_retfh[nd->nd_procnum] == 1) {
623 			if (vp)
624 				NFSVOPUNLOCK(vp);
625 			error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram,
626 			    vp, NULL, (fhandle_t *)fh.nfsrvfh_data, &nes);
627 		} else if (nfs_retfh[nd->nd_procnum] == 2) {
628 			error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram,
629 			    vp, NULL, &nes, NULL);
630 		} else {
631 			error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
632 			    vp, &nes);
633 		}
634 		if (mp != NULL && nfsrv_writerpc[nd->nd_procnum] != 0)
635 			vn_finished_write(mp);
636 
637 		nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
638 		    /*now*/ NULL, /*then*/ &start_time);
639 	}
640 	if (error) {
641 		if (error != EBADRPC)
642 			printf("nfs dorpc err2=%d\n", error);
643 		nd->nd_repstat = NFSERR_GARBAGE;
644 	}
645 	*nd->nd_errp = nfsd_errmap(nd);
646 
647 	/*
648 	 * Don't cache certain reply status values.
649 	 */
650 	if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) &&
651 	    (nd->nd_repstat == NFSERR_GARBAGE ||
652 	     nd->nd_repstat == NFSERR_BADXDR ||
653 	     nd->nd_repstat == NFSERR_MOVED ||
654 	     nd->nd_repstat == NFSERR_DELAY ||
655 	     nd->nd_repstat == NFSERR_BADSEQID ||
656 	     nd->nd_repstat == NFSERR_RESOURCE ||
657 	     nd->nd_repstat == NFSERR_SERVERFAULT ||
658 	     nd->nd_repstat == NFSERR_STALECLIENTID ||
659 	     nd->nd_repstat == NFSERR_STALESTATEID ||
660 	     nd->nd_repstat == NFSERR_OLDSTATEID ||
661 	     nd->nd_repstat == NFSERR_BADSTATEID ||
662 	     nd->nd_repstat == NFSERR_GRACE ||
663 	     nd->nd_repstat == NFSERR_NOGRACE))
664 		nd->nd_flag &= ~ND_SAVEREPLY;
665 
666 out:
667 	NFSEXITCODE2(0, nd);
668 }
669 
670 /*
671  * Breaks down a compound RPC request and calls the server routines for
672  * the subprocedures.
673  * Some suboperations are performed directly here to simplify file handle<-->
674  * vnode pointer handling.
675  */
676 static void
677 nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,
678     int taglen, u_int32_t minorvers)
679 {
680 	int i, lktype, op, op0 = 0, statsinprog = 0;
681 	u_int32_t *tl;
682 	struct nfsclient *clp, *nclp;
683 	int numops, error = 0, igotlock;
684 	u_int32_t retops = 0, *retopsp = NULL, *repp;
685 	vnode_t vp, nvp, savevp;
686 	struct nfsrvfh fh;
687 	mount_t new_mp, temp_mp = NULL;
688 	struct ucred *credanon;
689 	struct nfsexstuff nes, vpnes, savevpnes;
690 	fsid_t cur_fsid, save_fsid;
691 	static u_int64_t compref = 0;
692 	struct bintime start_time;
693 	struct thread *p;
694 
695 	p = curthread;
696 
697 	NFSVNO_EXINIT(&vpnes);
698 	NFSVNO_EXINIT(&savevpnes);
699 	/*
700 	 * Put the seq# of the current compound RPC in nfsrv_descript.
701 	 * (This is used by nfsrv_checkgetattr(), to see if the write
702 	 *  delegation was created by the same compound RPC as the one
703 	 *  with that Getattr in it.)
704 	 * Don't worry about the 64bit number wrapping around. It ain't
705 	 * gonna happen before this server gets shut down/rebooted.
706 	 */
707 	nd->nd_compref = compref++;
708 
709 	/*
710 	 * Check for and optionally get a lock on the root. This lock means that
711 	 * no nfsd will be fiddling with the V4 file system and state stuff. It
712 	 * is required when the V4 root is being changed, the stable storage
713 	 * restart file is being updated, or callbacks are being done.
714 	 * When any of the nfsd are processing an NFSv4 compound RPC, they must
715 	 * either hold a reference count (nfs_usecnt) or the lock. When
716 	 * nfsrv_unlock() is called to release the lock, it can optionally
717 	 * also get a reference count, which saves the need for a call to
718 	 * nfsrv_getref() after nfsrv_unlock().
719 	 */
720 	/*
721 	 * First, check to see if we need to wait for an update lock.
722 	 */
723 	igotlock = 0;
724 	NFSLOCKV4ROOTMUTEX();
725 	if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK)
726 		igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
727 		    NFSV4ROOTLOCKMUTEXPTR, NULL);
728 	else
729 		igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
730 		    NFSV4ROOTLOCKMUTEXPTR, NULL);
731 	NFSUNLOCKV4ROOTMUTEX();
732 	if (igotlock) {
733 		/*
734 		 * If I got the lock, I can update the stable storage file.
735 		 * Done when the grace period is over or a client has long
736 		 * since expired.
737 		 */
738 		nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK;
739 		if ((nfsrv_stablefirst.nsf_flags &
740 		    (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
741 			nfsrv_updatestable(p);
742 
743 		/*
744 		 * If at least one client has long since expired, search
745 		 * the client list for them, write a REVOKE record on the
746 		 * stable storage file and then remove them from the client
747 		 * list.
748 		 */
749 		if (nfsrv_stablefirst.nsf_flags & NFSNSF_EXPIREDCLIENT) {
750 			nfsrv_stablefirst.nsf_flags &= ~NFSNSF_EXPIREDCLIENT;
751 			for (i = 0; i < nfsrv_clienthashsize; i++) {
752 			    LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash,
753 				nclp) {
754 				if (clp->lc_flags & LCL_EXPIREIT) {
755 				    if (!LIST_EMPTY(&clp->lc_open) ||
756 					!LIST_EMPTY(&clp->lc_deleg))
757 					nfsrv_writestable(clp->lc_id,
758 					    clp->lc_idlen, NFSNST_REVOKE, p);
759 				    nfsrv_cleanclient(clp, p);
760 				    nfsrv_freedeleglist(&clp->lc_deleg);
761 				    nfsrv_freedeleglist(&clp->lc_olddeleg);
762 				    LIST_REMOVE(clp, lc_hash);
763 				    nfsrv_zapclient(clp, p);
764 				}
765 			    }
766 			}
767 		}
768 		NFSLOCKV4ROOTMUTEX();
769 		nfsv4_unlock(&nfsv4rootfs_lock, 1);
770 		NFSUNLOCKV4ROOTMUTEX();
771 	} else {
772 		/*
773 		 * If we didn't get the lock, we need to get a refcnt,
774 		 * which also checks for and waits for the lock.
775 		 */
776 		NFSLOCKV4ROOTMUTEX();
777 		nfsv4_getref(&nfsv4rootfs_lock, NULL,
778 		    NFSV4ROOTLOCKMUTEXPTR, NULL);
779 		NFSUNLOCKV4ROOTMUTEX();
780 	}
781 
782 	/*
783 	 * If flagged, search for open owners that haven't had any opens
784 	 * for a long time.
785 	 */
786 	if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) {
787 		nfsrv_throwawayopens(p);
788 	}
789 
790 	/* Do a CBLAYOUTRECALL callback if over the high water mark. */
791 	if (nfsrv_layoutcnt > nfsrv_layouthighwater)
792 		nfsrv_recalloldlayout(p);
793 
794 	savevp = vp = NULL;
795 	save_fsid.val[0] = save_fsid.val[1] = 0;
796 	cur_fsid.val[0] = cur_fsid.val[1] = 0;
797 
798 	/* If taglen < 0, there was a parsing error in nfsd_getminorvers(). */
799 	if (taglen < 0) {
800 		error = EBADRPC;
801 		goto nfsmout;
802 	}
803 
804 	(void) nfsm_strtom(nd, tag, taglen);
805 	NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED);
806 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
807 	if ((minorvers != NFSV4_MINORVERSION &&
808 	    minorvers != NFSV41_MINORVERSION &&
809 	    minorvers != NFSV42_MINORVERSION) ||
810 	    minorvers < nfs_minminorv4 || minorvers > nfs_maxminorv4)
811 		nd->nd_repstat = NFSERR_MINORVERMISMATCH;
812 	if (nd->nd_repstat)
813 		numops = 0;
814 	else
815 		numops = fxdr_unsigned(int, *tl);
816 	/*
817 	 * Loop around doing the sub ops.
818 	 * vp - is an unlocked vnode pointer for the CFH
819 	 * savevp - is an unlocked vnode pointer for the SAVEDFH
820 	 * (at some future date, it might turn out to be more appropriate
821 	 *  to keep the file handles instead of vnode pointers?)
822 	 * savevpnes and vpnes - are the export flags for the above.
823 	 */
824 	for (i = 0; i < numops; i++) {
825 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
826 		NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED);
827 		*repp = *tl;
828 		op = fxdr_unsigned(int, *tl);
829 		NFSD_DEBUG(4, "op=%d\n", op);
830 		if (op < NFSV4OP_ACCESS || op >= NFSV42_NOPS ||
831 		    (op >= NFSV4OP_NOPS && (nd->nd_flag & ND_NFSV41) == 0) ||
832 		    (op >= NFSV41_NOPS && (nd->nd_flag & ND_NFSV42) == 0)) {
833 			nd->nd_repstat = NFSERR_OPILLEGAL;
834 			*repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL);
835 			*repp = nfsd_errmap(nd);
836 			retops++;
837 			break;
838 		} else {
839 			repp++;
840 		}
841 
842 		binuptime(&start_time);
843 		nfsrvd_statstart(op, &start_time);
844 		statsinprog = 1;
845 
846 		if (i == 0)
847 			op0 = op;
848 		if (i == numops - 1)
849 			nd->nd_flag |= ND_LASTOP;
850 
851 		/*
852 		 * Check for a referral on the current FH and, if so, return
853 		 * NFSERR_MOVED for all ops that allow it, except Getattr.
854 		 */
855 		if (vp != NULL && op != NFSV4OP_GETATTR &&
856 		    nfsv4root_getreferral(vp, NULL, 0) != NULL &&
857 		    nfsrv_errmoved(op)) {
858 			nd->nd_repstat = NFSERR_MOVED;
859 			*repp = nfsd_errmap(nd);
860 			retops++;
861 			break;
862 		}
863 
864 		/*
865 		 * For NFSv4.1, check for a Sequence Operation being first
866 		 * or one of the other allowed operations by itself.
867 		 */
868 		if ((nd->nd_flag & ND_NFSV41) != 0) {
869 			if (i != 0 && op == NFSV4OP_SEQUENCE)
870 				nd->nd_repstat = NFSERR_SEQUENCEPOS;
871 			else if (i == 0 && op != NFSV4OP_SEQUENCE &&
872 			    op != NFSV4OP_EXCHANGEID &&
873 			    op != NFSV4OP_CREATESESSION &&
874 			    op != NFSV4OP_BINDCONNTOSESS &&
875 			    op != NFSV4OP_DESTROYCLIENTID &&
876 			    op != NFSV4OP_DESTROYSESSION)
877 				nd->nd_repstat = NFSERR_OPNOTINSESS;
878 			else if (i != 0 && op0 != NFSV4OP_SEQUENCE)
879 				nd->nd_repstat = NFSERR_NOTONLYOP;
880 			if (nd->nd_repstat != 0) {
881 				*repp = nfsd_errmap(nd);
882 				retops++;
883 				break;
884 			}
885 		}
886 
887 		nd->nd_procnum = op;
888 		/*
889 		 * If over flood level, reply NFSERR_RESOURCE, if at the first
890 		 * Op. (Since a client recovery from NFSERR_RESOURCE can get
891 		 * really nasty for certain Op sequences, I'll play it safe
892 		 * and only return the error at the beginning.) The cache
893 		 * will still function over flood level, but uses lots of
894 		 * mbufs.)
895 		 * If nfsrv_mallocmget_limit() returns True, the system is near
896 		 * to its limit for memory that malloc()/mget() can allocate.
897 		 */
898 		if (i == 0 && (nd->nd_rp == NULL ||
899 		    nd->nd_rp->rc_refcnt == 0) &&
900 		    (nfsrv_mallocmget_limit() ||
901 		     nfsrc_tcpsavedreplies > nfsrc_floodlevel)) {
902 			if (nfsrc_tcpsavedreplies > nfsrc_floodlevel)
903 				printf("nfsd server cache flooded, try "
904 				    "increasing vfs.nfsd.tcphighwater\n");
905 			nd->nd_repstat = NFSERR_RESOURCE;
906 			*repp = nfsd_errmap(nd);
907 			if (op == NFSV4OP_SETATTR) {
908 				/*
909 				 * Setattr replies require a bitmap.
910 				 * even for errors like these.
911 				 */
912 				NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
913 				*tl = 0;
914 			}
915 			retops++;
916 			break;
917 		}
918 		if (nfsv4_opflag[op].savereply)
919 			nd->nd_flag |= ND_SAVEREPLY;
920 		switch (op) {
921 		case NFSV4OP_PUTFH:
922 			error = nfsrv_mtofh(nd, &fh);
923 			if (error)
924 				goto nfsmout;
925 			if (!nd->nd_repstat)
926 				nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
927 				    NULL, 0);
928 			/* For now, allow this for non-export FHs */
929 			if (!nd->nd_repstat) {
930 				if (vp)
931 					vrele(vp);
932 				vp = nvp;
933 				cur_fsid = vp->v_mount->mnt_stat.f_fsid;
934 				NFSVOPUNLOCK(vp);
935 				vpnes = nes;
936 			}
937 			break;
938 		case NFSV4OP_PUTPUBFH:
939 			if (nfs_pubfhset)
940 			    nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
941 				&nes, NULL, 0);
942 			else
943 			    nd->nd_repstat = NFSERR_NOFILEHANDLE;
944 			if (!nd->nd_repstat) {
945 				if (vp)
946 					vrele(vp);
947 				vp = nvp;
948 				cur_fsid = vp->v_mount->mnt_stat.f_fsid;
949 				NFSVOPUNLOCK(vp);
950 				vpnes = nes;
951 			}
952 			break;
953 		case NFSV4OP_PUTROOTFH:
954 			if (nfs_rootfhset) {
955 				nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp,
956 				    &nes, NULL, 0);
957 				if (!nd->nd_repstat) {
958 					if (vp)
959 						vrele(vp);
960 					vp = nvp;
961 					cur_fsid = vp->v_mount->mnt_stat.f_fsid;
962 					NFSVOPUNLOCK(vp);
963 					vpnes = nes;
964 				}
965 			} else
966 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
967 			break;
968 		case NFSV4OP_SAVEFH:
969 			if (vp && NFSVNO_EXPORTED(&vpnes)) {
970 				nd->nd_repstat = 0;
971 				/* If vp == savevp, a no-op */
972 				if (vp != savevp) {
973 					if (savevp)
974 						vrele(savevp);
975 					VREF(vp);
976 					savevp = vp;
977 					savevpnes = vpnes;
978 					save_fsid = cur_fsid;
979 				}
980 				if ((nd->nd_flag & ND_CURSTATEID) != 0) {
981 					nd->nd_savedcurstateid =
982 					    nd->nd_curstateid;
983 					nd->nd_flag |= ND_SAVEDCURSTATEID;
984 				}
985 			} else {
986 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
987 			}
988 			break;
989 		case NFSV4OP_RESTOREFH:
990 			if (savevp) {
991 				nd->nd_repstat = 0;
992 				/* If vp == savevp, a no-op */
993 				if (vp != savevp) {
994 					VREF(savevp);
995 					vrele(vp);
996 					vp = savevp;
997 					vpnes = savevpnes;
998 					cur_fsid = save_fsid;
999 				}
1000 				if ((nd->nd_flag & ND_SAVEDCURSTATEID) != 0) {
1001 					nd->nd_curstateid =
1002 					    nd->nd_savedcurstateid;
1003 					nd->nd_flag |= ND_CURSTATEID;
1004 				}
1005 			} else {
1006 				nd->nd_repstat = NFSERR_RESTOREFH;
1007 			}
1008 			break;
1009 		default:
1010 		    /*
1011 		     * Allow a Lookup, Getattr, GetFH, Secinfo on an
1012 		     * non-exported directory if
1013 		     * nfs_rootfhset. Do I need to allow any other Ops?
1014 		     * (You can only have a non-exported vpnes if
1015 		     *  nfs_rootfhset is true. See nfsd_fhtovp())
1016 		     * Allow AUTH_SYS to be used for file systems
1017 		     * exported GSS only for certain Ops, to allow
1018 		     * clients to do mounts more easily.
1019 		     */
1020 		    if (nfsv4_opflag[op].needscfh && vp) {
1021 			if (!NFSVNO_EXPORTED(&vpnes) &&
1022 			    op != NFSV4OP_LOOKUP &&
1023 			    op != NFSV4OP_GETATTR &&
1024 			    op != NFSV4OP_GETFH &&
1025 			    op != NFSV4OP_ACCESS &&
1026 			    op != NFSV4OP_READLINK &&
1027 			    op != NFSV4OP_SECINFO)
1028 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
1029 			else if (nfsvno_testexp(nd, &vpnes) &&
1030 			    op != NFSV4OP_LOOKUP &&
1031 			    op != NFSV4OP_GETFH &&
1032 			    op != NFSV4OP_GETATTR &&
1033 			    op != NFSV4OP_SECINFO)
1034 				nd->nd_repstat = NFSERR_WRONGSEC;
1035 			if (nd->nd_repstat) {
1036 				if (op == NFSV4OP_SETATTR) {
1037 				    /*
1038 				     * Setattr reply requires a bitmap
1039 				     * even for errors like these.
1040 				     */
1041 				    NFSM_BUILD(tl, u_int32_t *,
1042 					NFSX_UNSIGNED);
1043 				    *tl = 0;
1044 				}
1045 				break;
1046 			}
1047 		    }
1048 		    if (nfsv4_opflag[op].retfh == 1) {
1049 			if (!vp) {
1050 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
1051 				break;
1052 			}
1053 			VREF(vp);
1054 			if (nfsv4_opflag[op].modifyfs)
1055 				vn_start_write(vp, &temp_mp, V_WAIT);
1056 			error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
1057 			    &nvp, (fhandle_t *)fh.nfsrvfh_data, &vpnes);
1058 			if (!error && !nd->nd_repstat) {
1059 			    if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) {
1060 				new_mp = nvp->v_mount;
1061 				if (fsidcmp(&cur_fsid, &new_mp->mnt_stat.f_fsid) != 0) {
1062 				    /* crossed a server mount point */
1063 				    nd->nd_repstat = nfsvno_checkexp(new_mp,
1064 					nd->nd_nam, &nes, &credanon);
1065 				    if (!nd->nd_repstat)
1066 					nd->nd_repstat = nfsd_excred(nd,
1067 					    &nes, credanon);
1068 				    if (credanon != NULL)
1069 					crfree(credanon);
1070 				    if (!nd->nd_repstat) {
1071 					vpnes = nes;
1072 					cur_fsid = new_mp->mnt_stat.f_fsid;
1073 				    }
1074 				}
1075 				/* Lookup ops return a locked vnode */
1076 				NFSVOPUNLOCK(nvp);
1077 			    }
1078 			    if (!nd->nd_repstat) {
1079 				    vrele(vp);
1080 				    vp = nvp;
1081 			    } else
1082 				    vrele(nvp);
1083 			}
1084 			if (nfsv4_opflag[op].modifyfs)
1085 				vn_finished_write(temp_mp);
1086 		    } else if (nfsv4_opflag[op].retfh == 2) {
1087 			if (vp == NULL || savevp == NULL) {
1088 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
1089 				break;
1090 			} else if (fsidcmp(&cur_fsid, &save_fsid) != 0) {
1091 				nd->nd_repstat = NFSERR_XDEV;
1092 				break;
1093 			}
1094 			if (nfsv4_opflag[op].modifyfs)
1095 				vn_start_write(savevp, &temp_mp, V_WAIT);
1096 			if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
1097 				VREF(vp);
1098 				VREF(savevp);
1099 				error = (*(nfsrv4_ops2[op]))(nd, isdgram,
1100 				    savevp, vp, &savevpnes, &vpnes);
1101 			} else
1102 				nd->nd_repstat = NFSERR_PERM;
1103 			if (nfsv4_opflag[op].modifyfs)
1104 				vn_finished_write(temp_mp);
1105 		    } else {
1106 			if (nfsv4_opflag[op].retfh != 0)
1107 				panic("nfsrvd_compound");
1108 			if (nfsv4_opflag[op].needscfh) {
1109 				if (vp != NULL) {
1110 					lktype = nfsv4_opflag[op].lktype;
1111 					if (nfsv4_opflag[op].modifyfs) {
1112 						vn_start_write(vp, &temp_mp,
1113 						    V_WAIT);
1114 						if (op == NFSV4OP_WRITE &&
1115 						    MNT_SHARED_WRITES(temp_mp))
1116 							lktype = LK_SHARED;
1117 					}
1118 					if (NFSVOPLOCK(vp, lktype) == 0)
1119 						VREF(vp);
1120 					else
1121 						nd->nd_repstat = NFSERR_PERM;
1122 				} else {
1123 					nd->nd_repstat = NFSERR_NOFILEHANDLE;
1124 					if (op == NFSV4OP_SETATTR) {
1125 						/*
1126 						 * Setattr reply requires a
1127 						 * bitmap even for errors like
1128 						 * these.
1129 						 */
1130 						NFSM_BUILD(tl, u_int32_t *,
1131 						    NFSX_UNSIGNED);
1132 						*tl = 0;
1133 					}
1134 					break;
1135 				}
1136 				if (nd->nd_repstat == 0)
1137 					error = (*(nfsrv4_ops0[op]))(nd,
1138 					    isdgram, vp, &vpnes);
1139 				if (nfsv4_opflag[op].modifyfs)
1140 					vn_finished_write(temp_mp);
1141 			} else {
1142 				error = (*(nfsrv4_ops0[op]))(nd, isdgram,
1143 				    NULL, &vpnes);
1144 			}
1145 		    }
1146 		}
1147 		if (error) {
1148 			if (error == EBADRPC || error == NFSERR_BADXDR) {
1149 				nd->nd_repstat = NFSERR_BADXDR;
1150 			} else {
1151 				nd->nd_repstat = error;
1152 				printf("nfsv4 comperr0=%d\n", error);
1153 			}
1154 			error = 0;
1155 		}
1156 
1157 		if (statsinprog != 0) {
1158 			nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1159 			    /*then*/ &start_time);
1160 			statsinprog = 0;
1161 		}
1162 
1163 		retops++;
1164 		if (nd->nd_repstat) {
1165 			*repp = nfsd_errmap(nd);
1166 			break;
1167 		} else {
1168 			*repp = 0;	/* NFS4_OK */
1169 		}
1170 	}
1171 nfsmout:
1172 	if (statsinprog != 0) {
1173 		nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1174 		    /*then*/ &start_time);
1175 		statsinprog = 0;
1176 	}
1177 	if (error) {
1178 		if (error == EBADRPC || error == NFSERR_BADXDR)
1179 			nd->nd_repstat = NFSERR_BADXDR;
1180 		else
1181 			printf("nfsv4 comperr1=%d\n", error);
1182 	}
1183 	if (taglen == -1) {
1184 		NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1185 		*tl++ = 0;
1186 		*tl = 0;
1187 	} else {
1188 		*retopsp = txdr_unsigned(retops);
1189 	}
1190 	if (vp)
1191 		vrele(vp);
1192 	if (savevp)
1193 		vrele(savevp);
1194 	NFSLOCKV4ROOTMUTEX();
1195 	nfsv4_relref(&nfsv4rootfs_lock);
1196 	NFSUNLOCKV4ROOTMUTEX();
1197 
1198 	NFSEXITCODE2(0, nd);
1199 }
1200