xref: /freebsd/sys/fs/nfsserver/nfs_nfsdsocket.c (revision 32100375a661c1e16588ddfa7b90ca8d26cb9786)
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 /*
430  * This static array indicates which server procedures require the extra
431  * arguments to return the current file handle for V2, 3.
432  */
433 static int nfs_retfh[NFS_V3NPROCS] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1,
434 	1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0 };
435 
436 extern struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS];
437 
438 static int nfsv3to4op[NFS_V3NPROCS] = {
439 	NFSPROC_NULL,
440 	NFSV4OP_GETATTR,
441 	NFSV4OP_SETATTR,
442 	NFSV4OP_LOOKUP,
443 	NFSV4OP_ACCESS,
444 	NFSV4OP_READLINK,
445 	NFSV4OP_READ,
446 	NFSV4OP_WRITE,
447 	NFSV4OP_V3CREATE,
448 	NFSV4OP_MKDIR,
449 	NFSV4OP_SYMLINK,
450 	NFSV4OP_MKNOD,
451 	NFSV4OP_REMOVE,
452 	NFSV4OP_RMDIR,
453 	NFSV4OP_RENAME,
454 	NFSV4OP_LINK,
455 	NFSV4OP_READDIR,
456 	NFSV4OP_READDIRPLUS,
457 	NFSV4OP_FSSTAT,
458 	NFSV4OP_FSINFO,
459 	NFSV4OP_PATHCONF,
460 	NFSV4OP_COMMIT,
461 };
462 
463 static struct mtx nfsrvd_statmtx;
464 MTX_SYSINIT(nfsst, &nfsrvd_statmtx, "NFSstat", MTX_DEF);
465 
466 static void
467 nfsrvd_statstart(int op, struct bintime *now)
468 {
469 	if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
470 		printf("%s: op %d invalid\n", __func__, op);
471 		return;
472 	}
473 
474 	mtx_lock(&nfsrvd_statmtx);
475 	if (nfsstatsv1.srvstartcnt == nfsstatsv1.srvdonecnt) {
476 		if (now != NULL)
477 			nfsstatsv1.busyfrom = *now;
478 		else
479 			binuptime(&nfsstatsv1.busyfrom);
480 
481 	}
482 	nfsstatsv1.srvrpccnt[op]++;
483 	nfsstatsv1.srvstartcnt++;
484 	mtx_unlock(&nfsrvd_statmtx);
485 
486 }
487 
488 static void
489 nfsrvd_statend(int op, uint64_t bytes, struct bintime *now,
490     struct bintime *then)
491 {
492 	struct bintime dt, lnow;
493 
494 	if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
495 		printf("%s: op %d invalid\n", __func__, op);
496 		return;
497 	}
498 
499 	if (now == NULL) {
500 		now = &lnow;
501 		binuptime(now);
502 	}
503 
504 	mtx_lock(&nfsrvd_statmtx);
505 
506 	nfsstatsv1.srvbytes[op] += bytes;
507 	nfsstatsv1.srvops[op]++;
508 
509 	if (then != NULL) {
510 		dt = *now;
511 		bintime_sub(&dt, then);
512 		bintime_add(&nfsstatsv1.srvduration[op], &dt);
513 	}
514 
515 	dt = *now;
516 	bintime_sub(&dt, &nfsstatsv1.busyfrom);
517 	bintime_add(&nfsstatsv1.busytime, &dt);
518 	nfsstatsv1.busyfrom = *now;
519 
520 	nfsstatsv1.srvdonecnt++;
521 
522 	mtx_unlock(&nfsrvd_statmtx);
523 }
524 
525 /*
526  * Do an RPC. Basically, get the file handles translated to vnode pointers
527  * and then call the appropriate server routine. The server routines are
528  * split into groups, based on whether they use a file handle or file
529  * handle plus name or ...
530  * The NFS V4 Compound RPC is performed separately by nfsrvd_compound().
531  */
532 void
533 nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, u_char *tag, int taglen,
534     u_int32_t minorvers)
535 {
536 	int error = 0, lktype;
537 	vnode_t vp;
538 	mount_t mp = NULL;
539 	struct nfsrvfh fh;
540 	struct nfsexstuff nes;
541 
542 	/*
543 	 * Get a locked vnode for the first file handle
544 	 */
545 	if (!(nd->nd_flag & ND_NFSV4)) {
546 		KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc"));
547 		/*
548 		 * For NFSv3, if the malloc/mget allocation is near limits,
549 		 * return NFSERR_DELAY.
550 		 */
551 		if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) {
552 			nd->nd_repstat = NFSERR_DELAY;
553 			vp = NULL;
554 		} else {
555 			error = nfsrv_mtofh(nd, &fh);
556 			if (error) {
557 				if (error != EBADRPC)
558 					printf("nfs dorpc err1=%d\n", error);
559 				nd->nd_repstat = NFSERR_GARBAGE;
560 				goto out;
561 			}
562 			if (nd->nd_procnum == NFSPROC_READ ||
563 			    nd->nd_procnum == NFSPROC_WRITE ||
564 			    nd->nd_procnum == NFSPROC_READDIR ||
565 			    nd->nd_procnum == NFSPROC_READDIRPLUS ||
566 			    nd->nd_procnum == NFSPROC_READLINK ||
567 			    nd->nd_procnum == NFSPROC_GETATTR ||
568 			    nd->nd_procnum == NFSPROC_ACCESS ||
569 			    nd->nd_procnum == NFSPROC_FSSTAT ||
570 			    nd->nd_procnum == NFSPROC_FSINFO)
571 				lktype = LK_SHARED;
572 			else
573 				lktype = LK_EXCLUSIVE;
574 			if (nd->nd_flag & ND_PUBLOOKUP)
575 				nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes,
576 				    &mp, nfsrv_writerpc[nd->nd_procnum]);
577 			else
578 				nfsd_fhtovp(nd, &fh, lktype, &vp, &nes,
579 				    &mp, nfsrv_writerpc[nd->nd_procnum]);
580 			if (nd->nd_repstat == NFSERR_PROGNOTV4)
581 				goto out;
582 		}
583 	}
584 
585 	/*
586 	 * For V2 and 3, set the ND_SAVEREPLY flag for the recent request
587 	 * cache, as required.
588 	 * For V4, nfsrvd_compound() does this.
589 	 */
590 	if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum])
591 		nd->nd_flag |= ND_SAVEREPLY;
592 
593 	nfsrvd_rephead(nd);
594 	/*
595 	 * If nd_repstat is non-zero, just fill in the reply status
596 	 * to complete the RPC reply for V2. Otherwise, you must do
597 	 * the RPC.
598 	 */
599 	if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) {
600 		*nd->nd_errp = nfsd_errmap(nd);
601 		nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], /*now*/ NULL);
602 		nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
603 		   /*now*/ NULL, /*then*/ NULL);
604 		if (mp != NULL && nfsrv_writerpc[nd->nd_procnum] != 0)
605 			vn_finished_write(mp);
606 		goto out;
607 	}
608 
609 	/*
610 	 * Now the procedure can be performed. For V4, nfsrvd_compound()
611 	 * works through the sub-rpcs, otherwise just call the procedure.
612 	 * The procedures are in three groups with different arguments.
613 	 * The group is indicated by the value in nfs_retfh[].
614 	 */
615 	if (nd->nd_flag & ND_NFSV4) {
616 		nfsrvd_compound(nd, isdgram, tag, taglen, minorvers);
617 	} else {
618 		struct bintime start_time;
619 
620 		binuptime(&start_time);
621 		nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], &start_time);
622 
623 		if (nfs_retfh[nd->nd_procnum] == 1) {
624 			if (vp)
625 				NFSVOPUNLOCK(vp);
626 			error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram,
627 			    vp, NULL, (fhandle_t *)fh.nfsrvfh_data, &nes);
628 		} else if (nfs_retfh[nd->nd_procnum] == 2) {
629 			error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram,
630 			    vp, NULL, &nes, NULL);
631 		} else {
632 			error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
633 			    vp, &nes);
634 		}
635 		if (mp != NULL && nfsrv_writerpc[nd->nd_procnum] != 0)
636 			vn_finished_write(mp);
637 
638 		nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
639 		    /*now*/ NULL, /*then*/ &start_time);
640 	}
641 	if (error) {
642 		if (error != EBADRPC)
643 			printf("nfs dorpc err2=%d\n", error);
644 		nd->nd_repstat = NFSERR_GARBAGE;
645 	}
646 	*nd->nd_errp = nfsd_errmap(nd);
647 
648 	/*
649 	 * Don't cache certain reply status values.
650 	 */
651 	if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) &&
652 	    (nd->nd_repstat == NFSERR_GARBAGE ||
653 	     nd->nd_repstat == NFSERR_BADXDR ||
654 	     nd->nd_repstat == NFSERR_MOVED ||
655 	     nd->nd_repstat == NFSERR_DELAY ||
656 	     nd->nd_repstat == NFSERR_BADSEQID ||
657 	     nd->nd_repstat == NFSERR_RESOURCE ||
658 	     nd->nd_repstat == NFSERR_SERVERFAULT ||
659 	     nd->nd_repstat == NFSERR_STALECLIENTID ||
660 	     nd->nd_repstat == NFSERR_STALESTATEID ||
661 	     nd->nd_repstat == NFSERR_OLDSTATEID ||
662 	     nd->nd_repstat == NFSERR_BADSTATEID ||
663 	     nd->nd_repstat == NFSERR_GRACE ||
664 	     nd->nd_repstat == NFSERR_NOGRACE))
665 		nd->nd_flag &= ~ND_SAVEREPLY;
666 
667 out:
668 	NFSEXITCODE2(0, nd);
669 }
670 
671 /*
672  * Breaks down a compound RPC request and calls the server routines for
673  * the subprocedures.
674  * Some suboperations are performed directly here to simplify file handle<-->
675  * vnode pointer handling.
676  */
677 static void
678 nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,
679     int taglen, u_int32_t minorvers)
680 {
681 	int i, lktype, op, op0 = 0, statsinprog = 0;
682 	u_int32_t *tl;
683 	struct nfsclient *clp, *nclp;
684 	int numops, error = 0, igotlock;
685 	u_int32_t retops = 0, *retopsp = NULL, *repp;
686 	vnode_t vp, nvp, savevp;
687 	struct nfsrvfh fh;
688 	mount_t new_mp, temp_mp = NULL;
689 	struct ucred *credanon;
690 	struct nfsexstuff nes, vpnes, savevpnes;
691 	fsid_t cur_fsid, save_fsid;
692 	static u_int64_t compref = 0;
693 	struct bintime start_time;
694 	struct thread *p;
695 
696 	p = curthread;
697 
698 	NFSVNO_EXINIT(&vpnes);
699 	NFSVNO_EXINIT(&savevpnes);
700 	/*
701 	 * Put the seq# of the current compound RPC in nfsrv_descript.
702 	 * (This is used by nfsrv_checkgetattr(), to see if the write
703 	 *  delegation was created by the same compound RPC as the one
704 	 *  with that Getattr in it.)
705 	 * Don't worry about the 64bit number wrapping around. It ain't
706 	 * gonna happen before this server gets shut down/rebooted.
707 	 */
708 	nd->nd_compref = compref++;
709 
710 	/*
711 	 * Check for and optionally get a lock on the root. This lock means that
712 	 * no nfsd will be fiddling with the V4 file system and state stuff. It
713 	 * is required when the V4 root is being changed, the stable storage
714 	 * restart file is being updated, or callbacks are being done.
715 	 * When any of the nfsd are processing an NFSv4 compound RPC, they must
716 	 * either hold a reference count (nfs_usecnt) or the lock. When
717 	 * nfsrv_unlock() is called to release the lock, it can optionally
718 	 * also get a reference count, which saves the need for a call to
719 	 * nfsrv_getref() after nfsrv_unlock().
720 	 */
721 	/*
722 	 * First, check to see if we need to wait for an update lock.
723 	 */
724 	igotlock = 0;
725 	NFSLOCKV4ROOTMUTEX();
726 	if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK)
727 		igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
728 		    NFSV4ROOTLOCKMUTEXPTR, NULL);
729 	else
730 		igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
731 		    NFSV4ROOTLOCKMUTEXPTR, NULL);
732 	NFSUNLOCKV4ROOTMUTEX();
733 	if (igotlock) {
734 		/*
735 		 * If I got the lock, I can update the stable storage file.
736 		 * Done when the grace period is over or a client has long
737 		 * since expired.
738 		 */
739 		nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK;
740 		if ((nfsrv_stablefirst.nsf_flags &
741 		    (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
742 			nfsrv_updatestable(p);
743 
744 		/*
745 		 * If at least one client has long since expired, search
746 		 * the client list for them, write a REVOKE record on the
747 		 * stable storage file and then remove them from the client
748 		 * list.
749 		 */
750 		if (nfsrv_stablefirst.nsf_flags & NFSNSF_EXPIREDCLIENT) {
751 			nfsrv_stablefirst.nsf_flags &= ~NFSNSF_EXPIREDCLIENT;
752 			for (i = 0; i < nfsrv_clienthashsize; i++) {
753 			    LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash,
754 				nclp) {
755 				if (clp->lc_flags & LCL_EXPIREIT) {
756 				    if (!LIST_EMPTY(&clp->lc_open) ||
757 					!LIST_EMPTY(&clp->lc_deleg))
758 					nfsrv_writestable(clp->lc_id,
759 					    clp->lc_idlen, NFSNST_REVOKE, p);
760 				    nfsrv_cleanclient(clp, p);
761 				    nfsrv_freedeleglist(&clp->lc_deleg);
762 				    nfsrv_freedeleglist(&clp->lc_olddeleg);
763 				    LIST_REMOVE(clp, lc_hash);
764 				    nfsrv_zapclient(clp, p);
765 				}
766 			    }
767 			}
768 		}
769 		NFSLOCKV4ROOTMUTEX();
770 		nfsv4_unlock(&nfsv4rootfs_lock, 1);
771 		NFSUNLOCKV4ROOTMUTEX();
772 	} else {
773 		/*
774 		 * If we didn't get the lock, we need to get a refcnt,
775 		 * which also checks for and waits for the lock.
776 		 */
777 		NFSLOCKV4ROOTMUTEX();
778 		nfsv4_getref(&nfsv4rootfs_lock, NULL,
779 		    NFSV4ROOTLOCKMUTEXPTR, NULL);
780 		NFSUNLOCKV4ROOTMUTEX();
781 	}
782 
783 	/*
784 	 * If flagged, search for open owners that haven't had any opens
785 	 * for a long time.
786 	 */
787 	if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) {
788 		nfsrv_throwawayopens(p);
789 	}
790 
791 	/* Do a CBLAYOUTRECALL callback if over the high water mark. */
792 	if (nfsrv_layoutcnt > nfsrv_layouthighwater)
793 		nfsrv_recalloldlayout(p);
794 
795 	savevp = vp = NULL;
796 	save_fsid.val[0] = save_fsid.val[1] = 0;
797 	cur_fsid.val[0] = cur_fsid.val[1] = 0;
798 
799 	/* If taglen < 0, there was a parsing error in nfsd_getminorvers(). */
800 	if (taglen < 0) {
801 		error = EBADRPC;
802 		goto nfsmout;
803 	}
804 
805 	(void) nfsm_strtom(nd, tag, taglen);
806 	NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED);
807 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
808 	if ((minorvers != NFSV4_MINORVERSION &&
809 	    minorvers != NFSV41_MINORVERSION &&
810 	    minorvers != NFSV42_MINORVERSION) ||
811 	    minorvers < nfs_minminorv4 || minorvers > nfs_maxminorv4)
812 		nd->nd_repstat = NFSERR_MINORVERMISMATCH;
813 	if (nd->nd_repstat)
814 		numops = 0;
815 	else
816 		numops = fxdr_unsigned(int, *tl);
817 	/*
818 	 * Loop around doing the sub ops.
819 	 * vp - is an unlocked vnode pointer for the CFH
820 	 * savevp - is an unlocked vnode pointer for the SAVEDFH
821 	 * (at some future date, it might turn out to be more appropriate
822 	 *  to keep the file handles instead of vnode pointers?)
823 	 * savevpnes and vpnes - are the export flags for the above.
824 	 */
825 	for (i = 0; i < numops; i++) {
826 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
827 		NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED);
828 		*repp = *tl;
829 		op = fxdr_unsigned(int, *tl);
830 		NFSD_DEBUG(4, "op=%d\n", op);
831 		if (op < NFSV4OP_ACCESS || op >= NFSV42_NOPS ||
832 		    (op >= NFSV4OP_NOPS && (nd->nd_flag & ND_NFSV41) == 0) ||
833 		    (op >= NFSV41_NOPS && (nd->nd_flag & ND_NFSV42) == 0)) {
834 			nd->nd_repstat = NFSERR_OPILLEGAL;
835 			*repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL);
836 			*repp = nfsd_errmap(nd);
837 			retops++;
838 			break;
839 		} else {
840 			repp++;
841 		}
842 
843 		binuptime(&start_time);
844 		nfsrvd_statstart(op, &start_time);
845 		statsinprog = 1;
846 
847 		if (i == 0)
848 			op0 = op;
849 		if (i == numops - 1)
850 			nd->nd_flag |= ND_LASTOP;
851 
852 		/*
853 		 * Check for a referral on the current FH and, if so, return
854 		 * NFSERR_MOVED for all ops that allow it, except Getattr.
855 		 */
856 		if (vp != NULL && op != NFSV4OP_GETATTR &&
857 		    nfsv4root_getreferral(vp, NULL, 0) != NULL &&
858 		    nfsrv_errmoved(op)) {
859 			nd->nd_repstat = NFSERR_MOVED;
860 			*repp = nfsd_errmap(nd);
861 			retops++;
862 			break;
863 		}
864 
865 		/*
866 		 * For NFSv4.1, check for a Sequence Operation being first
867 		 * or one of the other allowed operations by itself.
868 		 */
869 		if ((nd->nd_flag & ND_NFSV41) != 0) {
870 			if (i != 0 && op == NFSV4OP_SEQUENCE)
871 				nd->nd_repstat = NFSERR_SEQUENCEPOS;
872 			else if (i == 0 && op != NFSV4OP_SEQUENCE &&
873 			    op != NFSV4OP_EXCHANGEID &&
874 			    op != NFSV4OP_CREATESESSION &&
875 			    op != NFSV4OP_BINDCONNTOSESS &&
876 			    op != NFSV4OP_DESTROYCLIENTID &&
877 			    op != NFSV4OP_DESTROYSESSION)
878 				nd->nd_repstat = NFSERR_OPNOTINSESS;
879 			else if (i != 0 && op0 != NFSV4OP_SEQUENCE)
880 				nd->nd_repstat = NFSERR_NOTONLYOP;
881 			if (nd->nd_repstat != 0) {
882 				*repp = nfsd_errmap(nd);
883 				retops++;
884 				break;
885 			}
886 		}
887 
888 		nd->nd_procnum = op;
889 		/*
890 		 * If over flood level, reply NFSERR_RESOURCE, if at the first
891 		 * Op. (Since a client recovery from NFSERR_RESOURCE can get
892 		 * really nasty for certain Op sequences, I'll play it safe
893 		 * and only return the error at the beginning.) The cache
894 		 * will still function over flood level, but uses lots of
895 		 * mbufs.)
896 		 * If nfsrv_mallocmget_limit() returns True, the system is near
897 		 * to its limit for memory that malloc()/mget() can allocate.
898 		 */
899 		if (i == 0 && (nd->nd_rp == NULL ||
900 		    nd->nd_rp->rc_refcnt == 0) &&
901 		    (nfsrv_mallocmget_limit() ||
902 		     nfsrc_tcpsavedreplies > nfsrc_floodlevel)) {
903 			if (nfsrc_tcpsavedreplies > nfsrc_floodlevel)
904 				printf("nfsd server cache flooded, try "
905 				    "increasing vfs.nfsd.tcphighwater\n");
906 			nd->nd_repstat = NFSERR_RESOURCE;
907 			*repp = nfsd_errmap(nd);
908 			if (op == NFSV4OP_SETATTR) {
909 				/*
910 				 * Setattr replies require a bitmap.
911 				 * even for errors like these.
912 				 */
913 				NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
914 				*tl = 0;
915 			}
916 			retops++;
917 			break;
918 		}
919 		if (nfsv4_opflag[op].savereply)
920 			nd->nd_flag |= ND_SAVEREPLY;
921 		switch (op) {
922 		case NFSV4OP_PUTFH:
923 			error = nfsrv_mtofh(nd, &fh);
924 			if (error)
925 				goto nfsmout;
926 			if (!nd->nd_repstat)
927 				nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
928 				    NULL, 0);
929 			/* For now, allow this for non-export FHs */
930 			if (!nd->nd_repstat) {
931 				if (vp)
932 					vrele(vp);
933 				vp = nvp;
934 				cur_fsid = vp->v_mount->mnt_stat.f_fsid;
935 				NFSVOPUNLOCK(vp);
936 				vpnes = nes;
937 			}
938 			break;
939 		case NFSV4OP_PUTPUBFH:
940 			if (nfs_pubfhset)
941 			    nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
942 				&nes, NULL, 0);
943 			else
944 			    nd->nd_repstat = NFSERR_NOFILEHANDLE;
945 			if (!nd->nd_repstat) {
946 				if (vp)
947 					vrele(vp);
948 				vp = nvp;
949 				cur_fsid = vp->v_mount->mnt_stat.f_fsid;
950 				NFSVOPUNLOCK(vp);
951 				vpnes = nes;
952 			}
953 			break;
954 		case NFSV4OP_PUTROOTFH:
955 			if (nfs_rootfhset) {
956 				nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp,
957 				    &nes, NULL, 0);
958 				if (!nd->nd_repstat) {
959 					if (vp)
960 						vrele(vp);
961 					vp = nvp;
962 					cur_fsid = vp->v_mount->mnt_stat.f_fsid;
963 					NFSVOPUNLOCK(vp);
964 					vpnes = nes;
965 				}
966 			} else
967 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
968 			break;
969 		case NFSV4OP_SAVEFH:
970 			if (vp && NFSVNO_EXPORTED(&vpnes)) {
971 				nd->nd_repstat = 0;
972 				/* If vp == savevp, a no-op */
973 				if (vp != savevp) {
974 					if (savevp)
975 						vrele(savevp);
976 					VREF(vp);
977 					savevp = vp;
978 					savevpnes = vpnes;
979 					save_fsid = cur_fsid;
980 				}
981 				if ((nd->nd_flag & ND_CURSTATEID) != 0) {
982 					nd->nd_savedcurstateid =
983 					    nd->nd_curstateid;
984 					nd->nd_flag |= ND_SAVEDCURSTATEID;
985 				}
986 			} else {
987 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
988 			}
989 			break;
990 		case NFSV4OP_RESTOREFH:
991 			if (savevp) {
992 				nd->nd_repstat = 0;
993 				/* If vp == savevp, a no-op */
994 				if (vp != savevp) {
995 					VREF(savevp);
996 					vrele(vp);
997 					vp = savevp;
998 					vpnes = savevpnes;
999 					cur_fsid = save_fsid;
1000 				}
1001 				if ((nd->nd_flag & ND_SAVEDCURSTATEID) != 0) {
1002 					nd->nd_curstateid =
1003 					    nd->nd_savedcurstateid;
1004 					nd->nd_flag |= ND_CURSTATEID;
1005 				}
1006 			} else {
1007 				nd->nd_repstat = NFSERR_RESTOREFH;
1008 			}
1009 			break;
1010 		default:
1011 		    /*
1012 		     * Allow a Lookup, Getattr, GetFH, Secinfo on an
1013 		     * non-exported directory if
1014 		     * nfs_rootfhset. Do I need to allow any other Ops?
1015 		     * (You can only have a non-exported vpnes if
1016 		     *  nfs_rootfhset is true. See nfsd_fhtovp())
1017 		     * Allow AUTH_SYS to be used for file systems
1018 		     * exported GSS only for certain Ops, to allow
1019 		     * clients to do mounts more easily.
1020 		     */
1021 		    if (nfsv4_opflag[op].needscfh && vp) {
1022 			if (!NFSVNO_EXPORTED(&vpnes) &&
1023 			    op != NFSV4OP_LOOKUP &&
1024 			    op != NFSV4OP_GETATTR &&
1025 			    op != NFSV4OP_GETFH &&
1026 			    op != NFSV4OP_ACCESS &&
1027 			    op != NFSV4OP_READLINK &&
1028 			    op != NFSV4OP_SECINFO)
1029 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
1030 			else if (nfsvno_testexp(nd, &vpnes) &&
1031 			    op != NFSV4OP_LOOKUP &&
1032 			    op != NFSV4OP_GETFH &&
1033 			    op != NFSV4OP_GETATTR &&
1034 			    op != NFSV4OP_SECINFO)
1035 				nd->nd_repstat = NFSERR_WRONGSEC;
1036 			if (nd->nd_repstat) {
1037 				if (op == NFSV4OP_SETATTR) {
1038 				    /*
1039 				     * Setattr reply requires a bitmap
1040 				     * even for errors like these.
1041 				     */
1042 				    NFSM_BUILD(tl, u_int32_t *,
1043 					NFSX_UNSIGNED);
1044 				    *tl = 0;
1045 				}
1046 				break;
1047 			}
1048 		    }
1049 		    if (nfsv4_opflag[op].retfh == 1) {
1050 			if (!vp) {
1051 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
1052 				break;
1053 			}
1054 			VREF(vp);
1055 			if (nfsv4_opflag[op].modifyfs)
1056 				vn_start_write(vp, &temp_mp, V_WAIT);
1057 			error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
1058 			    &nvp, (fhandle_t *)fh.nfsrvfh_data, &vpnes);
1059 			if (!error && !nd->nd_repstat) {
1060 			    if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) {
1061 				new_mp = nvp->v_mount;
1062 				if (fsidcmp(&cur_fsid, &new_mp->mnt_stat.f_fsid) != 0) {
1063 				    /* crossed a server mount point */
1064 				    nd->nd_repstat = nfsvno_checkexp(new_mp,
1065 					nd->nd_nam, &nes, &credanon);
1066 				    if (!nd->nd_repstat)
1067 					nd->nd_repstat = nfsd_excred(nd,
1068 					    &nes, credanon);
1069 				    if (credanon != NULL)
1070 					crfree(credanon);
1071 				    if (!nd->nd_repstat) {
1072 					vpnes = nes;
1073 					cur_fsid = new_mp->mnt_stat.f_fsid;
1074 				    }
1075 				}
1076 				/* Lookup ops return a locked vnode */
1077 				NFSVOPUNLOCK(nvp);
1078 			    }
1079 			    if (!nd->nd_repstat) {
1080 				    vrele(vp);
1081 				    vp = nvp;
1082 			    } else
1083 				    vrele(nvp);
1084 			}
1085 			if (nfsv4_opflag[op].modifyfs)
1086 				vn_finished_write(temp_mp);
1087 		    } else if (nfsv4_opflag[op].retfh == 2) {
1088 			if (vp == NULL || savevp == NULL) {
1089 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
1090 				break;
1091 			} else if (fsidcmp(&cur_fsid, &save_fsid) != 0) {
1092 				nd->nd_repstat = NFSERR_XDEV;
1093 				break;
1094 			}
1095 			if (nfsv4_opflag[op].modifyfs)
1096 				vn_start_write(savevp, &temp_mp, V_WAIT);
1097 			if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
1098 				VREF(vp);
1099 				VREF(savevp);
1100 				error = (*(nfsrv4_ops2[op]))(nd, isdgram,
1101 				    savevp, vp, &savevpnes, &vpnes);
1102 			} else
1103 				nd->nd_repstat = NFSERR_PERM;
1104 			if (nfsv4_opflag[op].modifyfs)
1105 				vn_finished_write(temp_mp);
1106 		    } else {
1107 			if (nfsv4_opflag[op].retfh != 0)
1108 				panic("nfsrvd_compound");
1109 			if (nfsv4_opflag[op].needscfh) {
1110 				if (vp != NULL) {
1111 					lktype = nfsv4_opflag[op].lktype;
1112 					if (nfsv4_opflag[op].modifyfs) {
1113 						vn_start_write(vp, &temp_mp,
1114 						    V_WAIT);
1115 						if (op == NFSV4OP_WRITE &&
1116 						    MNT_SHARED_WRITES(temp_mp))
1117 							lktype = LK_SHARED;
1118 					}
1119 					if (NFSVOPLOCK(vp, lktype) == 0)
1120 						VREF(vp);
1121 					else
1122 						nd->nd_repstat = NFSERR_PERM;
1123 				} else {
1124 					nd->nd_repstat = NFSERR_NOFILEHANDLE;
1125 					if (op == NFSV4OP_SETATTR) {
1126 						/*
1127 						 * Setattr reply requires a
1128 						 * bitmap even for errors like
1129 						 * these.
1130 						 */
1131 						NFSM_BUILD(tl, u_int32_t *,
1132 						    NFSX_UNSIGNED);
1133 						*tl = 0;
1134 					}
1135 					break;
1136 				}
1137 				if (nd->nd_repstat == 0)
1138 					error = (*(nfsrv4_ops0[op]))(nd,
1139 					    isdgram, vp, &vpnes);
1140 				if (nfsv4_opflag[op].modifyfs)
1141 					vn_finished_write(temp_mp);
1142 			} else {
1143 				error = (*(nfsrv4_ops0[op]))(nd, isdgram,
1144 				    NULL, &vpnes);
1145 			}
1146 		    }
1147 		}
1148 		if (error) {
1149 			if (error == EBADRPC || error == NFSERR_BADXDR) {
1150 				nd->nd_repstat = NFSERR_BADXDR;
1151 			} else {
1152 				nd->nd_repstat = error;
1153 				printf("nfsv4 comperr0=%d\n", error);
1154 			}
1155 			error = 0;
1156 		}
1157 
1158 		if (statsinprog != 0) {
1159 			nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1160 			    /*then*/ &start_time);
1161 			statsinprog = 0;
1162 		}
1163 
1164 		retops++;
1165 		if (nd->nd_repstat) {
1166 			*repp = nfsd_errmap(nd);
1167 			break;
1168 		} else {
1169 			*repp = 0;	/* NFS4_OK */
1170 		}
1171 	}
1172 nfsmout:
1173 	if (statsinprog != 0) {
1174 		nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1175 		    /*then*/ &start_time);
1176 		statsinprog = 0;
1177 	}
1178 	if (error) {
1179 		if (error == EBADRPC || error == NFSERR_BADXDR)
1180 			nd->nd_repstat = NFSERR_BADXDR;
1181 		else
1182 			printf("nfsv4 comperr1=%d\n", error);
1183 	}
1184 	if (taglen == -1) {
1185 		NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1186 		*tl++ = 0;
1187 		*tl = 0;
1188 	} else {
1189 		*retopsp = txdr_unsigned(retops);
1190 	}
1191 	if (vp)
1192 		vrele(vp);
1193 	if (savevp)
1194 		vrele(savevp);
1195 	NFSLOCKV4ROOTMUTEX();
1196 	nfsv4_relref(&nfsv4rootfs_lock);
1197 	NFSUNLOCKV4ROOTMUTEX();
1198 
1199 	NFSEXITCODE2(0, nd);
1200 }
1201