2 * SPDX-License-Identifier: BSD-3-Clause
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * Rick Macklem at The University of Guelph.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
40 * Socket operations for use by the nfs server.
43 #include <fs/nfs/nfsport.h>
45 extern struct nfsrvfh nfs_pubfh;
46 extern int nfs_pubfhset;
47 extern struct nfsv4lock nfsv4rootfs_lock;
48 extern int nfsrv_clienthashsize;
49 extern int nfsd_debuglevel;
50 extern int nfsrv_layouthighwater;
51 extern volatile int nfsrv_layoutcnt;
55 NFSD_VNET_DECLARE(struct nfsrv_stablefirst, nfsrv_stablefirst);
56 NFSD_VNET_DECLARE(struct nfsclienthashhead *, nfsclienthash);
57 NFSD_VNET_DECLARE(int, nfsrc_floodlevel);
58 NFSD_VNET_DECLARE(int, nfsrc_tcpsavedreplies);
59 NFSD_VNET_DECLARE(struct nfsrvfh, nfs_rootfh);
60 NFSD_VNET_DECLARE(int, nfs_rootfhset);
61 NFSD_VNET_DECLARE(struct nfsstatsv1 *, nfsstatsv1_p);
63 int (*nfsrv3_procs0[NFS_V3NPROCS])(struct nfsrv_descript *,
64 int, vnode_t , struct nfsexstuff *) = {
65 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
68 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
74 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
75 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
76 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
79 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
80 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
89 int (*nfsrv3_procs1[NFS_V3NPROCS])(struct nfsrv_descript *,
90 int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *) = {
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,
95 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
96 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
97 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
98 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
99 (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 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
110 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
111 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
112 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
115 int (*nfsrv3_procs2[NFS_V3NPROCS])(struct nfsrv_descript *,
116 int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *) = {
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 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
128 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
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,
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 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
136 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
137 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
138 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
141 int (*nfsrv4_ops0[NFSV42_NOPS])(struct nfsrv_descript *,
142 int, vnode_t , struct nfsexstuff *) = {
143 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
144 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
145 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
149 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
154 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
158 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
159 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
161 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
162 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
164 nfsrvd_opendowngrade,
165 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
166 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
167 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
172 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
174 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
175 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
179 nfsrvd_setclientidcfrm,
182 nfsrvd_releaselckown,
186 nfsrvd_createsession,
187 nfsrvd_destroysession,
195 nfsrvd_secinfononame,
200 nfsrvd_destroyclientid,
201 nfsrvd_reclaimcomplete,
203 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
221 int (*nfsrv4_ops1[NFSV42_NOPS])(struct nfsrv_descript *,
222 int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *) = {
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 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
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,
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 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
235 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
236 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
237 (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,
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 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
296 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
297 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
298 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
301 int (*nfsrv4_ops2[NFSV42_NOPS])(struct nfsrv_descript *,
302 int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *) = {
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 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
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,
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 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
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,
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 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
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 nfsrvd_copy_file_range,
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 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
376 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
377 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
378 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
382 * Static array that defines which nfs rpc's are nonidempotent
384 static int nfsrv_nonidempotent[NFS_V3NPROCS] = {
410 * This static array indicates whether or not the RPC modifies the
413 int nfsrv_writerpc[NFS_NPROCS] = { 0, 0, 1, 0, 0, 0, 0,
414 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
415 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
417 SYSCTL_DECL(_vfs_nfsd);
418 static int nfs_minminorv4 = NFSV4_MINORVERSION;
419 SYSCTL_INT(_vfs_nfsd, OID_AUTO, server_min_minorversion4, CTLFLAG_RWTUN,
421 "The lowest minor version of NFSv4 handled by the server");
423 static int nfs_maxminorv4 = NFSV42_MINORVERSION;
424 SYSCTL_INT(_vfs_nfsd, OID_AUTO, server_max_minorversion4, CTLFLAG_RWTUN,
426 "The highest minor version of NFSv4 handled by the server");
428 /* local functions */
429 static void nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
430 u_char *tag, int taglen, u_int32_t minorvers);
433 * This static array indicates which server procedures require the extra
434 * arguments to return the current file handle for V2, 3.
436 static int nfs_retfh[NFS_V3NPROCS] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1,
437 1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0 };
439 extern struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS];
441 static int nfsv3to4op[NFS_V3NPROCS] = {
466 static struct mtx nfsrvd_statmtx;
467 MTX_SYSINIT(nfsst, &nfsrvd_statmtx, "NFSstat", MTX_DEF);
470 nfsrvd_statstart(int op, struct bintime *now)
472 if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
473 printf("%s: op %d invalid\n", __func__, op);
477 mtx_lock(&nfsrvd_statmtx);
478 if (NFSD_VNET(nfsstatsv1_p)->srvstartcnt ==
479 NFSD_VNET(nfsstatsv1_p)->srvdonecnt) {
481 NFSD_VNET(nfsstatsv1_p)->busyfrom = *now;
483 binuptime(&NFSD_VNET(nfsstatsv1_p)->busyfrom);
486 NFSD_VNET(nfsstatsv1_p)->srvrpccnt[op]++;
487 NFSD_VNET(nfsstatsv1_p)->srvstartcnt++;
488 mtx_unlock(&nfsrvd_statmtx);
493 nfsrvd_statend(int op, uint64_t bytes, struct bintime *now,
494 struct bintime *then)
496 struct bintime dt, lnow;
498 if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
499 printf("%s: op %d invalid\n", __func__, op);
508 mtx_lock(&nfsrvd_statmtx);
510 NFSD_VNET(nfsstatsv1_p)->srvbytes[op] += bytes;
511 NFSD_VNET(nfsstatsv1_p)->srvops[op]++;
515 bintime_sub(&dt, then);
516 bintime_add(&NFSD_VNET(nfsstatsv1_p)->srvduration[op], &dt);
520 bintime_sub(&dt, &NFSD_VNET(nfsstatsv1_p)->busyfrom);
521 bintime_add(&NFSD_VNET(nfsstatsv1_p)->busytime, &dt);
522 NFSD_VNET(nfsstatsv1_p)->busyfrom = *now;
524 NFSD_VNET(nfsstatsv1_p)->srvdonecnt++;
526 mtx_unlock(&nfsrvd_statmtx);
530 * Do an RPC. Basically, get the file handles translated to vnode pointers
531 * and then call the appropriate server routine. The server routines are
532 * split into groups, based on whether they use a file handle or file
533 * handle plus name or ...
534 * The NFS V4 Compound RPC is performed separately by nfsrvd_compound().
537 nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, u_char *tag, int taglen,
540 int error = 0, lktype;
544 struct nfsexstuff nes;
549 * Save the current position in the request mbuf list so
550 * that a rollback to this location can be done upon an
551 * ERELOOKUP error return from an RPC function.
559 * Get a locked vnode for the first file handle
561 if (!(nd->nd_flag & ND_NFSV4)) {
562 KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc"));
564 * For NFSv3, if the malloc/mget allocation is near limits,
565 * return NFSERR_DELAY.
567 if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) {
568 nd->nd_repstat = NFSERR_DELAY;
571 error = nfsrv_mtofh(nd, &fh);
573 if (error != EBADRPC)
574 printf("nfs dorpc err1=%d\n", error);
575 nd->nd_repstat = NFSERR_GARBAGE;
578 if (nd->nd_procnum == NFSPROC_READ ||
579 nd->nd_procnum == NFSPROC_WRITE ||
580 nd->nd_procnum == NFSPROC_READDIR ||
581 nd->nd_procnum == NFSPROC_READDIRPLUS ||
582 nd->nd_procnum == NFSPROC_READLINK ||
583 nd->nd_procnum == NFSPROC_GETATTR ||
584 nd->nd_procnum == NFSPROC_ACCESS ||
585 nd->nd_procnum == NFSPROC_FSSTAT ||
586 nd->nd_procnum == NFSPROC_FSINFO)
589 lktype = LK_EXCLUSIVE;
590 if (nd->nd_flag & ND_PUBLOOKUP)
591 nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes,
592 &mp, nfsrv_writerpc[nd->nd_procnum], -1);
594 nfsd_fhtovp(nd, &fh, lktype, &vp, &nes,
595 &mp, nfsrv_writerpc[nd->nd_procnum], -1);
596 if (nd->nd_repstat == NFSERR_PROGNOTV4)
602 * For V2 and 3, set the ND_SAVEREPLY flag for the recent request
603 * cache, as required.
604 * For V4, nfsrvd_compound() does this.
606 if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum])
607 nd->nd_flag |= ND_SAVEREPLY;
611 * If nd_repstat is non-zero, just fill in the reply status
612 * to complete the RPC reply for V2. Otherwise, you must do
615 if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) {
616 *nd->nd_errp = nfsd_errmap(nd);
617 nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], /*now*/ NULL);
618 nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
619 /*now*/ NULL, /*then*/ NULL);
620 vn_finished_write(mp);
625 * Now the procedure can be performed. For V4, nfsrvd_compound()
626 * works through the sub-rpcs, otherwise just call the procedure.
627 * The procedures are in three groups with different arguments.
628 * The group is indicated by the value in nfs_retfh[].
630 if (nd->nd_flag & ND_NFSV4) {
631 nfsrvd_compound(nd, isdgram, tag, taglen, minorvers);
633 struct bintime start_time;
635 binuptime(&start_time);
636 nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], &start_time);
638 if (nfs_retfh[nd->nd_procnum] == 1) {
641 error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram,
642 vp, NULL, (fhandle_t *)fh.nfsrvfh_data, &nes);
643 } else if (nfs_retfh[nd->nd_procnum] == 2) {
644 error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram,
645 vp, NULL, &nes, NULL);
647 error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
650 vn_finished_write(mp);
652 if (error == 0 && nd->nd_repstat == ERELOOKUP) {
654 * Roll back to the beginning of the RPC request
660 /* Free the junk RPC reply and redo the RPC. */
661 m_freem(nd->nd_mreq);
662 nd->nd_mreq = nd->nd_mb = NULL;
667 nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
668 /*now*/ NULL, /*then*/ &start_time);
671 if (error != EBADRPC)
672 printf("nfs dorpc err2=%d\n", error);
673 nd->nd_repstat = NFSERR_GARBAGE;
675 *nd->nd_errp = nfsd_errmap(nd);
678 * Don't cache certain reply status values.
680 if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) &&
681 (nd->nd_repstat == NFSERR_GARBAGE ||
682 nd->nd_repstat == NFSERR_BADXDR ||
683 nd->nd_repstat == NFSERR_MOVED ||
684 nd->nd_repstat == NFSERR_DELAY ||
685 nd->nd_repstat == NFSERR_BADSEQID ||
686 nd->nd_repstat == NFSERR_RESOURCE ||
687 nd->nd_repstat == NFSERR_SERVERFAULT ||
688 nd->nd_repstat == NFSERR_STALECLIENTID ||
689 nd->nd_repstat == NFSERR_STALESTATEID ||
690 nd->nd_repstat == NFSERR_OLDSTATEID ||
691 nd->nd_repstat == NFSERR_BADSTATEID ||
692 nd->nd_repstat == NFSERR_GRACE ||
693 nd->nd_repstat == NFSERR_NOGRACE))
694 nd->nd_flag &= ~ND_SAVEREPLY;
701 * Breaks down a compound RPC request and calls the server routines for
703 * Some suboperations are performed directly here to simplify file handle<-->
704 * vnode pointer handling.
707 nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,
708 int taglen, u_int32_t minorvers)
710 int i, lktype, op, op0 = 0, rstat, statsinprog = 0;
712 struct nfsclient *clp, *nclp;
713 int error = 0, igotlock, nextop, numops, savefhcnt;
714 u_int32_t retops = 0, *retopsp = NULL, *repp;
715 vnode_t vp, nvp, savevp;
717 mount_t new_mp, temp_mp = NULL;
718 struct ucred *credanon;
719 struct nfsexstuff nes, vpnes, savevpnes;
720 fsid_t cur_fsid, save_fsid;
721 static u_int64_t compref = 0;
722 struct bintime start_time;
724 struct mbuf *mb, *md;
726 int bextpg, bextpgsiz;
730 /* Check for and optionally clear the no space flags for DSs. */
733 NFSVNO_EXINIT(&vpnes);
734 NFSVNO_EXINIT(&savevpnes);
736 * Put the seq# of the current compound RPC in nfsrv_descript.
737 * (This is used by nfsrv_checkgetattr(), to see if the write
738 * delegation was created by the same compound RPC as the one
739 * with that Getattr in it.)
740 * Don't worry about the 64bit number wrapping around. It ain't
741 * gonna happen before this server gets shut down/rebooted.
743 nd->nd_compref = compref++;
746 * Check for and optionally get a lock on the root. This lock means that
747 * no nfsd will be fiddling with the V4 file system and state stuff. It
748 * is required when the V4 root is being changed, the stable storage
749 * restart file is being updated, or callbacks are being done.
750 * When any of the nfsd are processing an NFSv4 compound RPC, they must
751 * either hold a reference count (nfs_usecnt) or the lock. When
752 * nfsrv_unlock() is called to release the lock, it can optionally
753 * also get a reference count, which saves the need for a call to
754 * nfsrv_getref() after nfsrv_unlock().
757 * First, check to see if we need to wait for an update lock.
760 NFSLOCKV4ROOTMUTEX();
761 if (NFSD_VNET(nfsrv_stablefirst).nsf_flags & NFSNSF_NEEDLOCK)
762 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
763 NFSV4ROOTLOCKMUTEXPTR, NULL);
765 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
766 NFSV4ROOTLOCKMUTEXPTR, NULL);
767 NFSUNLOCKV4ROOTMUTEX();
770 * If I got the lock, I can update the stable storage file.
771 * Done when the grace period is over or a client has long
774 NFSD_VNET(nfsrv_stablefirst).nsf_flags &= ~NFSNSF_NEEDLOCK;
775 if ((NFSD_VNET(nfsrv_stablefirst).nsf_flags &
776 (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
777 nfsrv_updatestable(p);
780 * If at least one client has long since expired, search
781 * the client list for them, write a REVOKE record on the
782 * stable storage file and then remove them from the client
785 if (NFSD_VNET(nfsrv_stablefirst).nsf_flags &
786 NFSNSF_EXPIREDCLIENT) {
787 NFSD_VNET(nfsrv_stablefirst).nsf_flags &=
788 ~NFSNSF_EXPIREDCLIENT;
789 for (i = 0; i < nfsrv_clienthashsize; i++) {
790 LIST_FOREACH_SAFE(clp, &NFSD_VNET(nfsclienthash)[i],
792 if (clp->lc_flags & LCL_EXPIREIT) {
793 if (!LIST_EMPTY(&clp->lc_open) ||
794 !LIST_EMPTY(&clp->lc_deleg))
795 nfsrv_writestable(clp->lc_id,
796 clp->lc_idlen, NFSNST_REVOKE, p);
797 nfsrv_cleanclient(clp, p);
798 nfsrv_freedeleglist(&clp->lc_deleg);
799 nfsrv_freedeleglist(&clp->lc_olddeleg);
800 LIST_REMOVE(clp, lc_hash);
801 nfsrv_zapclient(clp, p);
806 NFSLOCKV4ROOTMUTEX();
807 nfsv4_unlock(&nfsv4rootfs_lock, 1);
808 NFSUNLOCKV4ROOTMUTEX();
811 * If we didn't get the lock, we need to get a refcnt,
812 * which also checks for and waits for the lock.
814 NFSLOCKV4ROOTMUTEX();
815 nfsv4_getref(&nfsv4rootfs_lock, NULL,
816 NFSV4ROOTLOCKMUTEXPTR, NULL);
817 NFSUNLOCKV4ROOTMUTEX();
821 * If flagged, search for open owners that haven't had any opens
824 if (NFSD_VNET(nfsrv_stablefirst).nsf_flags & NFSNSF_NOOPENS) {
825 nfsrv_throwawayopens(p);
828 /* Do a CBLAYOUTRECALL callback if over the high water mark. */
829 if (nfsrv_layoutcnt > nfsrv_layouthighwater)
830 nfsrv_recalloldlayout(p);
833 save_fsid.val[0] = save_fsid.val[1] = 0;
834 cur_fsid.val[0] = cur_fsid.val[1] = 0;
838 /* If taglen < 0, there was a parsing error in nfsd_getminorvers(). */
844 (void) nfsm_strtom(nd, tag, taglen);
845 NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED);
846 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
847 if ((minorvers != NFSV4_MINORVERSION &&
848 minorvers != NFSV41_MINORVERSION &&
849 minorvers != NFSV42_MINORVERSION) ||
850 minorvers < nfs_minminorv4 || minorvers > nfs_maxminorv4)
851 nd->nd_repstat = NFSERR_MINORVERMISMATCH;
855 numops = fxdr_unsigned(int, *tl);
857 * Loop around doing the sub ops.
858 * vp - is an unlocked vnode pointer for the CFH
859 * savevp - is an unlocked vnode pointer for the SAVEDFH
860 * (at some future date, it might turn out to be more appropriate
861 * to keep the file handles instead of vnode pointers?)
862 * savevpnes and vpnes - are the export flags for the above.
864 for (i = 0; i < numops; i++) {
865 NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED);
868 *repp = txdr_unsigned(op);
870 } else if (nextop == -1) {
871 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
873 op = fxdr_unsigned(int, *tl);
876 *repp = txdr_unsigned(op);
879 NFSD_DEBUG(4, "op=%d\n", op);
880 if (op < NFSV4OP_ACCESS || op >= NFSV42_NOPS ||
881 (op >= NFSV4OP_NOPS && (nd->nd_flag & ND_NFSV41) == 0) ||
882 (op >= NFSV41_NOPS && (nd->nd_flag & ND_NFSV42) == 0)) {
883 nd->nd_repstat = NFSERR_OPILLEGAL;
884 *repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL);
885 *repp = nfsd_errmap(nd);
892 binuptime(&start_time);
893 nfsrvd_statstart(op, &start_time);
899 nd->nd_flag |= ND_LASTOP;
902 * Check for a referral on the current FH and, if so, return
903 * NFSERR_MOVED for all ops that allow it, except Getattr.
905 if (vp != NULL && op != NFSV4OP_GETATTR &&
906 nfsv4root_getreferral(vp, NULL, 0) != NULL &&
907 nfsrv_errmoved(op)) {
908 nd->nd_repstat = NFSERR_MOVED;
909 *repp = nfsd_errmap(nd);
915 * For NFSv4.1, check for a Sequence Operation being first
916 * or one of the other allowed operations by itself.
918 if ((nd->nd_flag & ND_NFSV41) != 0) {
919 if (i != 0 && op == NFSV4OP_SEQUENCE)
920 nd->nd_repstat = NFSERR_SEQUENCEPOS;
921 else if (i == 0 && op != NFSV4OP_SEQUENCE &&
922 op != NFSV4OP_EXCHANGEID &&
923 op != NFSV4OP_CREATESESSION &&
924 op != NFSV4OP_BINDCONNTOSESS &&
925 op != NFSV4OP_DESTROYCLIENTID &&
926 op != NFSV4OP_DESTROYSESSION)
927 nd->nd_repstat = NFSERR_OPNOTINSESS;
928 else if (i != 0 && op0 != NFSV4OP_SEQUENCE)
929 nd->nd_repstat = NFSERR_NOTONLYOP;
930 if (nd->nd_repstat != 0) {
931 *repp = nfsd_errmap(nd);
939 * If over flood level, reply NFSERR_RESOURCE, if at the first
940 * Op. (Since a client recovery from NFSERR_RESOURCE can get
941 * really nasty for certain Op sequences, I'll play it safe
942 * and only return the error at the beginning.) The cache
943 * will still function over flood level, but uses lots of
945 * If nfsrv_mallocmget_limit() returns True, the system is near
946 * to its limit for memory that malloc()/mget() can allocate.
948 if (i == 0 && (nd->nd_rp == NULL ||
949 nd->nd_rp->rc_refcnt == 0) &&
950 (nfsrv_mallocmget_limit() ||
951 NFSD_VNET(nfsrc_tcpsavedreplies) >
952 NFSD_VNET(nfsrc_floodlevel))) {
953 if (NFSD_VNET(nfsrc_tcpsavedreplies) >
954 NFSD_VNET(nfsrc_floodlevel))
955 printf("nfsd server cache flooded, try "
956 "increasing vfs.nfsd.tcphighwater\n");
957 nd->nd_repstat = NFSERR_RESOURCE;
958 *repp = nfsd_errmap(nd);
959 if (op == NFSV4OP_SETATTR) {
961 * Setattr replies require a bitmap.
962 * even for errors like these.
964 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
970 if (nfsv4_opflag[op].savereply)
971 nd->nd_flag |= ND_SAVEREPLY;
974 error = nfsrv_mtofh(nd, &fh);
977 if ((nd->nd_flag & ND_LASTOP) == 0) {
979 * Pre-parse the next op#. If it is
980 * SaveFH, count it and skip to the
981 * next op#, if not the last op#.
982 * nextop is used to determine if
983 * NFSERR_WRONGSEC can be returned,
984 * per RFC5661 Sec. 2.6.
987 NFSM_DISSECT(tl, uint32_t *,
989 nextop = fxdr_unsigned(int, *tl);
990 if (nextop == NFSV4OP_SAVEFH &&
993 } while (nextop == NFSV4OP_SAVEFH &&
997 nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
999 /* For now, allow this for non-export FHs */
1000 if (!nd->nd_repstat) {
1004 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
1009 case NFSV4OP_PUTPUBFH:
1011 if ((nd->nd_flag & ND_LASTOP) == 0) {
1013 * Pre-parse the next op#. If it is
1014 * SaveFH, count it and skip to the
1015 * next op#, if not the last op#.
1016 * nextop is used to determine if
1017 * NFSERR_WRONGSEC can be returned,
1018 * per RFC5661 Sec. 2.6.
1021 NFSM_DISSECT(tl, uint32_t *,
1023 nextop = fxdr_unsigned(int,
1025 if (nextop == NFSV4OP_SAVEFH &&
1028 } while (nextop == NFSV4OP_SAVEFH &&
1031 nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
1032 &nes, NULL, 0, nextop);
1034 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1035 if (!nd->nd_repstat) {
1039 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
1044 case NFSV4OP_PUTROOTFH:
1045 if (NFSD_VNET(nfs_rootfhset)) {
1046 if ((nd->nd_flag & ND_LASTOP) == 0) {
1048 * Pre-parse the next op#. If it is
1049 * SaveFH, count it and skip to the
1050 * next op#, if not the last op#.
1051 * nextop is used to determine if
1052 * NFSERR_WRONGSEC can be returned,
1053 * per RFC5661 Sec. 2.6.
1056 NFSM_DISSECT(tl, uint32_t *,
1058 nextop = fxdr_unsigned(int,
1060 if (nextop == NFSV4OP_SAVEFH &&
1063 } while (nextop == NFSV4OP_SAVEFH &&
1066 nfsd_fhtovp(nd, &NFSD_VNET(nfs_rootfh),
1067 LK_SHARED, &nvp, &nes, NULL, 0, nextop);
1068 if (!nd->nd_repstat) {
1072 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
1077 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1079 case NFSV4OP_SAVEFH:
1080 if (vp && NFSVNO_EXPORTED(&vpnes)) {
1082 /* If vp == savevp, a no-op */
1089 save_fsid = cur_fsid;
1091 if ((nd->nd_flag & ND_CURSTATEID) != 0) {
1092 nd->nd_savedcurstateid =
1094 nd->nd_flag |= ND_SAVEDCURSTATEID;
1097 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1100 case NFSV4OP_RESTOREFH:
1102 if ((nd->nd_flag & ND_LASTOP) == 0) {
1104 * Pre-parse the next op#. If it is
1105 * SaveFH, count it and skip to the
1106 * next op#, if not the last op#.
1107 * nextop is used to determine if
1108 * NFSERR_WRONGSEC can be returned,
1109 * per RFC5661 Sec. 2.6.
1112 NFSM_DISSECT(tl, uint32_t *,
1114 nextop = fxdr_unsigned(int,
1116 if (nextop == NFSV4OP_SAVEFH &&
1119 } while (nextop == NFSV4OP_SAVEFH &&
1123 /* If vp == savevp, a no-op */
1125 if (nfsrv_checkwrongsec(nd, nextop,
1130 if (nd->nd_repstat == 0) {
1135 cur_fsid = save_fsid;
1138 if (nd->nd_repstat == 0 &&
1139 (nd->nd_flag & ND_SAVEDCURSTATEID) != 0) {
1141 nd->nd_savedcurstateid;
1142 nd->nd_flag |= ND_CURSTATEID;
1145 nd->nd_repstat = NFSERR_RESTOREFH;
1150 * Allow a Lookup, Getattr, GetFH, Secinfo on an
1151 * non-exported directory if
1152 * nfs_rootfhset. Do I need to allow any other Ops?
1153 * (You can only have a non-exported vpnes if
1154 * nfs_rootfhset is true. See nfsd_fhtovp())
1155 * Allow AUTH_SYS to be used for file systems
1156 * exported GSS only for certain Ops, to allow
1157 * clients to do mounts more easily.
1159 if (nfsv4_opflag[op].needscfh && vp) {
1160 if (!NFSVNO_EXPORTED(&vpnes) &&
1161 op != NFSV4OP_LOOKUP &&
1162 op != NFSV4OP_GETATTR &&
1163 op != NFSV4OP_GETFH &&
1164 op != NFSV4OP_ACCESS &&
1165 op != NFSV4OP_READLINK &&
1166 op != NFSV4OP_SECINFO &&
1167 op != NFSV4OP_SECINFONONAME)
1168 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1169 if (nd->nd_repstat) {
1170 if (op == NFSV4OP_SETATTR) {
1172 * Setattr reply requires a bitmap
1173 * even for errors like these.
1175 NFSM_BUILD(tl, u_int32_t *,
1184 * Save the current positions in the mbuf lists so
1185 * that a rollback to this location can be done upon a
1186 * redo due to a ERELOOKUP return for a operation.
1190 bextpg = nd->nd_bextpg;
1191 bextpgsiz = nd->nd_bextpgsiz;
1196 if (nfsv4_opflag[op].retfh == 1) {
1198 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1201 if (NFSVNO_EXPORTED(&vpnes) && (op == NFSV4OP_LOOKUP ||
1202 op == NFSV4OP_LOOKUPP || (op == NFSV4OP_OPEN &&
1203 vp->v_type == VDIR))) {
1204 /* Check for wrong security. */
1205 rstat = nfsvno_testexp(nd, &vpnes);
1207 nd->nd_repstat = rstat;
1212 if (nfsv4_opflag[op].modifyfs)
1213 vn_start_write(vp, &temp_mp, V_WAIT);
1214 error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
1215 &nvp, (fhandle_t *)fh.nfsrvfh_data, &vpnes);
1216 if (!error && !nd->nd_repstat) {
1217 if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) {
1218 new_mp = nvp->v_mount;
1219 if (fsidcmp(&cur_fsid, &new_mp->mnt_stat.f_fsid) != 0) {
1220 /* crossed a server mount point */
1221 nd->nd_repstat = nfsvno_checkexp(new_mp,
1222 nd->nd_nam, &nes, &credanon);
1223 if (!nd->nd_repstat)
1224 nd->nd_repstat = nfsd_excred(nd,
1225 &nes, credanon, true);
1226 if (credanon != NULL)
1228 if (!nd->nd_repstat) {
1230 cur_fsid = new_mp->mnt_stat.f_fsid;
1233 /* Lookup ops return a locked vnode */
1236 if (!nd->nd_repstat) {
1242 if (nfsv4_opflag[op].modifyfs)
1243 vn_finished_write(temp_mp);
1244 } else if (nfsv4_opflag[op].retfh == 2) {
1245 if (vp == NULL || savevp == NULL) {
1246 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1248 } else if (fsidcmp(&cur_fsid, &save_fsid) != 0) {
1249 nd->nd_repstat = NFSERR_XDEV;
1252 if (nfsv4_opflag[op].modifyfs)
1253 vn_start_write(savevp, &temp_mp, V_WAIT);
1254 if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
1257 error = (*(nfsrv4_ops2[op]))(nd, isdgram,
1258 savevp, vp, &savevpnes, &vpnes);
1260 nd->nd_repstat = NFSERR_PERM;
1261 if (nfsv4_opflag[op].modifyfs)
1262 vn_finished_write(temp_mp);
1264 if (nfsv4_opflag[op].retfh != 0)
1265 panic("nfsrvd_compound");
1266 if (nfsv4_opflag[op].needscfh) {
1268 lktype = nfsv4_opflag[op].lktype;
1269 if (nfsv4_opflag[op].modifyfs) {
1270 vn_start_write(vp, &temp_mp,
1272 if (op == NFSV4OP_WRITE &&
1273 MNT_SHARED_WRITES(temp_mp))
1276 if (NFSVOPLOCK(vp, lktype) == 0)
1279 nd->nd_repstat = NFSERR_PERM;
1281 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1282 if (op == NFSV4OP_SETATTR) {
1284 * Setattr reply requires a
1285 * bitmap even for errors like
1288 NFSM_BUILD(tl, u_int32_t *,
1294 if (nd->nd_repstat == 0) {
1295 error = (*(nfsrv4_ops0[op]))(nd,
1296 isdgram, vp, &vpnes);
1297 if ((op == NFSV4OP_SECINFO ||
1298 op == NFSV4OP_SECINFONONAME) &&
1299 error == 0 && nd->nd_repstat == 0) {
1301 * Secinfo and Secinfo_no_name
1302 * consume the current FH.
1308 if (nfsv4_opflag[op].modifyfs)
1309 vn_finished_write(temp_mp);
1311 error = (*(nfsrv4_ops0[op]))(nd, isdgram,
1317 if (error == EBADRPC || error == NFSERR_BADXDR) {
1318 nd->nd_repstat = NFSERR_BADXDR;
1320 nd->nd_repstat = error;
1321 printf("nfsv4 comperr0=%d\n", error);
1326 if (nd->nd_repstat == ERELOOKUP) {
1328 * Roll back to the beginning of the operation
1335 * Trim off the bogus reply for this operation
1336 * and redo the operation.
1338 nfsm_trimtrailing(nd, mb, bpos, bextpg, bextpgsiz);
1340 nd->nd_flag |= ND_ERELOOKUP;
1343 nd->nd_flag &= ~ND_ERELOOKUP;
1345 if (statsinprog != 0) {
1346 nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1347 /*then*/ &start_time);
1352 if (nd->nd_repstat) {
1353 *repp = nfsd_errmap(nd);
1356 *repp = 0; /* NFS4_OK */
1360 if (statsinprog != 0) {
1361 nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1362 /*then*/ &start_time);
1366 if (error == EBADRPC || error == NFSERR_BADXDR)
1367 nd->nd_repstat = NFSERR_BADXDR;
1369 printf("nfsv4 comperr1=%d\n", error);
1372 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1376 *retopsp = txdr_unsigned(retops);
1382 NFSLOCKV4ROOTMUTEX();
1383 nfsv4_relref(&nfsv4rootfs_lock);
1384 NFSUNLOCKV4ROOTMUTEX();
1386 NFSEXITCODE2(0, nd);