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 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;
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,
64 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
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,
75 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
76 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
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,
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,
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,
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,
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,
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,
145 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
150 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
154 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
155 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
157 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
158 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
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,
168 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
170 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
171 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
175 nfsrvd_setclientidcfrm,
178 nfsrvd_releaselckown,
182 nfsrvd_createsession,
183 nfsrvd_destroysession,
196 nfsrvd_destroyclientid,
197 nfsrvd_reclaimcomplete,
199 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
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,
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,
236 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
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,
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,
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,
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,
378 * Static array that defines which nfs rpc's are nonidempotent
380 static int nfsrv_nonidempotent[NFS_V3NPROCS] = {
406 * This static array indicates whether or not the RPC modifies the
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 };
413 SYSCTL_DECL(_vfs_nfsd);
414 static int nfs_minminorv4 = NFSV4_MINORVERSION;
415 SYSCTL_INT(_vfs_nfsd, OID_AUTO, server_min_minorversion4, CTLFLAG_RWTUN,
417 "The lowest minor version of NFSv4 handled by the server");
419 static int nfs_maxminorv4 = NFSV42_MINORVERSION;
420 SYSCTL_INT(_vfs_nfsd, OID_AUTO, server_max_minorversion4, CTLFLAG_RWTUN,
422 "The highest minor version of NFSv4 handled by the server");
424 /* local functions */
425 static void nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
426 u_char *tag, int taglen, u_int32_t minorvers);
429 * This static array indicates which server procedures require the extra
430 * arguments to return the current file handle for V2, 3.
432 static int nfs_retfh[NFS_V3NPROCS] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1,
433 1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0 };
435 extern struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS];
437 static int nfsv3to4op[NFS_V3NPROCS] = {
462 static struct mtx nfsrvd_statmtx;
463 MTX_SYSINIT(nfsst, &nfsrvd_statmtx, "NFSstat", MTX_DEF);
466 nfsrvd_statstart(int op, struct bintime *now)
468 if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
469 printf("%s: op %d invalid\n", __func__, op);
473 mtx_lock(&nfsrvd_statmtx);
474 if (nfsstatsv1.srvstartcnt == nfsstatsv1.srvdonecnt) {
476 nfsstatsv1.busyfrom = *now;
478 binuptime(&nfsstatsv1.busyfrom);
481 nfsstatsv1.srvrpccnt[op]++;
482 nfsstatsv1.srvstartcnt++;
483 mtx_unlock(&nfsrvd_statmtx);
488 nfsrvd_statend(int op, uint64_t bytes, struct bintime *now,
489 struct bintime *then)
491 struct bintime dt, lnow;
493 if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
494 printf("%s: op %d invalid\n", __func__, op);
503 mtx_lock(&nfsrvd_statmtx);
505 nfsstatsv1.srvbytes[op] += bytes;
506 nfsstatsv1.srvops[op]++;
510 bintime_sub(&dt, then);
511 bintime_add(&nfsstatsv1.srvduration[op], &dt);
515 bintime_sub(&dt, &nfsstatsv1.busyfrom);
516 bintime_add(&nfsstatsv1.busytime, &dt);
517 nfsstatsv1.busyfrom = *now;
519 nfsstatsv1.srvdonecnt++;
521 mtx_unlock(&nfsrvd_statmtx);
525 * Do an RPC. Basically, get the file handles translated to vnode pointers
526 * and then call the appropriate server routine. The server routines are
527 * split into groups, based on whether they use a file handle or file
528 * handle plus name or ...
529 * The NFS V4 Compound RPC is performed separately by nfsrvd_compound().
532 nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, u_char *tag, int taglen,
535 int error = 0, lktype;
539 struct nfsexstuff nes;
542 * Get a locked vnode for the first file handle
544 if (!(nd->nd_flag & ND_NFSV4)) {
545 KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc"));
547 * For NFSv3, if the malloc/mget allocation is near limits,
548 * return NFSERR_DELAY.
550 if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) {
551 nd->nd_repstat = NFSERR_DELAY;
554 error = nfsrv_mtofh(nd, &fh);
556 if (error != EBADRPC)
557 printf("nfs dorpc err1=%d\n", error);
558 nd->nd_repstat = NFSERR_GARBAGE;
561 if (nd->nd_procnum == NFSPROC_READ ||
562 nd->nd_procnum == NFSPROC_WRITE ||
563 nd->nd_procnum == NFSPROC_READDIR ||
564 nd->nd_procnum == NFSPROC_READDIRPLUS ||
565 nd->nd_procnum == NFSPROC_READLINK ||
566 nd->nd_procnum == NFSPROC_GETATTR ||
567 nd->nd_procnum == NFSPROC_ACCESS ||
568 nd->nd_procnum == NFSPROC_FSSTAT ||
569 nd->nd_procnum == NFSPROC_FSINFO)
572 lktype = LK_EXCLUSIVE;
573 if (nd->nd_flag & ND_PUBLOOKUP)
574 nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes,
575 &mp, nfsrv_writerpc[nd->nd_procnum]);
577 nfsd_fhtovp(nd, &fh, lktype, &vp, &nes,
578 &mp, nfsrv_writerpc[nd->nd_procnum]);
579 if (nd->nd_repstat == NFSERR_PROGNOTV4)
585 * For V2 and 3, set the ND_SAVEREPLY flag for the recent request
586 * cache, as required.
587 * For V4, nfsrvd_compound() does this.
589 if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum])
590 nd->nd_flag |= ND_SAVEREPLY;
594 * If nd_repstat is non-zero, just fill in the reply status
595 * to complete the RPC reply for V2. Otherwise, you must do
598 if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) {
599 *nd->nd_errp = nfsd_errmap(nd);
600 nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], /*now*/ NULL);
601 nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
602 /*now*/ NULL, /*then*/ NULL);
603 if (mp != NULL && nfsrv_writerpc[nd->nd_procnum] != 0)
604 vn_finished_write(mp);
609 * Now the procedure can be performed. For V4, nfsrvd_compound()
610 * works through the sub-rpcs, otherwise just call the procedure.
611 * The procedures are in three groups with different arguments.
612 * The group is indicated by the value in nfs_retfh[].
614 if (nd->nd_flag & ND_NFSV4) {
615 nfsrvd_compound(nd, isdgram, tag, taglen, minorvers);
617 struct bintime start_time;
619 binuptime(&start_time);
620 nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], &start_time);
622 if (nfs_retfh[nd->nd_procnum] == 1) {
625 error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram,
626 vp, NULL, (fhandle_t *)fh.nfsrvfh_data, &nes);
627 } else if (nfs_retfh[nd->nd_procnum] == 2) {
628 error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram,
629 vp, NULL, &nes, NULL);
631 error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
634 if (mp != NULL && nfsrv_writerpc[nd->nd_procnum] != 0)
635 vn_finished_write(mp);
637 nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
638 /*now*/ NULL, /*then*/ &start_time);
641 if (error != EBADRPC)
642 printf("nfs dorpc err2=%d\n", error);
643 nd->nd_repstat = NFSERR_GARBAGE;
645 *nd->nd_errp = nfsd_errmap(nd);
648 * Don't cache certain reply status values.
650 if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) &&
651 (nd->nd_repstat == NFSERR_GARBAGE ||
652 nd->nd_repstat == NFSERR_BADXDR ||
653 nd->nd_repstat == NFSERR_MOVED ||
654 nd->nd_repstat == NFSERR_DELAY ||
655 nd->nd_repstat == NFSERR_BADSEQID ||
656 nd->nd_repstat == NFSERR_RESOURCE ||
657 nd->nd_repstat == NFSERR_SERVERFAULT ||
658 nd->nd_repstat == NFSERR_STALECLIENTID ||
659 nd->nd_repstat == NFSERR_STALESTATEID ||
660 nd->nd_repstat == NFSERR_OLDSTATEID ||
661 nd->nd_repstat == NFSERR_BADSTATEID ||
662 nd->nd_repstat == NFSERR_GRACE ||
663 nd->nd_repstat == NFSERR_NOGRACE))
664 nd->nd_flag &= ~ND_SAVEREPLY;
671 * Breaks down a compound RPC request and calls the server routines for
673 * Some suboperations are performed directly here to simplify file handle<-->
674 * vnode pointer handling.
677 nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,
678 int taglen, u_int32_t minorvers)
680 int i, lktype, op, op0 = 0, statsinprog = 0;
682 struct nfsclient *clp, *nclp;
683 int numops, error = 0, igotlock;
684 u_int32_t retops = 0, *retopsp = NULL, *repp;
685 vnode_t vp, nvp, savevp;
687 mount_t new_mp, temp_mp = NULL;
688 struct ucred *credanon;
689 struct nfsexstuff nes, vpnes, savevpnes;
690 fsid_t cur_fsid, save_fsid;
691 static u_int64_t compref = 0;
692 struct bintime start_time;
697 NFSVNO_EXINIT(&vpnes);
698 NFSVNO_EXINIT(&savevpnes);
700 * Put the seq# of the current compound RPC in nfsrv_descript.
701 * (This is used by nfsrv_checkgetattr(), to see if the write
702 * delegation was created by the same compound RPC as the one
703 * with that Getattr in it.)
704 * Don't worry about the 64bit number wrapping around. It ain't
705 * gonna happen before this server gets shut down/rebooted.
707 nd->nd_compref = compref++;
710 * Check for and optionally get a lock on the root. This lock means that
711 * no nfsd will be fiddling with the V4 file system and state stuff. It
712 * is required when the V4 root is being changed, the stable storage
713 * restart file is being updated, or callbacks are being done.
714 * When any of the nfsd are processing an NFSv4 compound RPC, they must
715 * either hold a reference count (nfs_usecnt) or the lock. When
716 * nfsrv_unlock() is called to release the lock, it can optionally
717 * also get a reference count, which saves the need for a call to
718 * nfsrv_getref() after nfsrv_unlock().
721 * First, check to see if we need to wait for an update lock.
724 NFSLOCKV4ROOTMUTEX();
725 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK)
726 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
727 NFSV4ROOTLOCKMUTEXPTR, NULL);
729 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
730 NFSV4ROOTLOCKMUTEXPTR, NULL);
731 NFSUNLOCKV4ROOTMUTEX();
734 * If I got the lock, I can update the stable storage file.
735 * Done when the grace period is over or a client has long
738 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK;
739 if ((nfsrv_stablefirst.nsf_flags &
740 (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
741 nfsrv_updatestable(p);
744 * If at least one client has long since expired, search
745 * the client list for them, write a REVOKE record on the
746 * stable storage file and then remove them from the client
749 if (nfsrv_stablefirst.nsf_flags & NFSNSF_EXPIREDCLIENT) {
750 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_EXPIREDCLIENT;
751 for (i = 0; i < nfsrv_clienthashsize; i++) {
752 LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash,
754 if (clp->lc_flags & LCL_EXPIREIT) {
755 if (!LIST_EMPTY(&clp->lc_open) ||
756 !LIST_EMPTY(&clp->lc_deleg))
757 nfsrv_writestable(clp->lc_id,
758 clp->lc_idlen, NFSNST_REVOKE, p);
759 nfsrv_cleanclient(clp, p);
760 nfsrv_freedeleglist(&clp->lc_deleg);
761 nfsrv_freedeleglist(&clp->lc_olddeleg);
762 LIST_REMOVE(clp, lc_hash);
763 nfsrv_zapclient(clp, p);
768 NFSLOCKV4ROOTMUTEX();
769 nfsv4_unlock(&nfsv4rootfs_lock, 1);
770 NFSUNLOCKV4ROOTMUTEX();
773 * If we didn't get the lock, we need to get a refcnt,
774 * which also checks for and waits for the lock.
776 NFSLOCKV4ROOTMUTEX();
777 nfsv4_getref(&nfsv4rootfs_lock, NULL,
778 NFSV4ROOTLOCKMUTEXPTR, NULL);
779 NFSUNLOCKV4ROOTMUTEX();
783 * If flagged, search for open owners that haven't had any opens
786 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) {
787 nfsrv_throwawayopens(p);
790 /* Do a CBLAYOUTRECALL callback if over the high water mark. */
791 if (nfsrv_layoutcnt > nfsrv_layouthighwater)
792 nfsrv_recalloldlayout(p);
795 save_fsid.val[0] = save_fsid.val[1] = 0;
796 cur_fsid.val[0] = cur_fsid.val[1] = 0;
798 /* If taglen < 0, there was a parsing error in nfsd_getminorvers(). */
804 (void) nfsm_strtom(nd, tag, taglen);
805 NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED);
806 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
807 if ((minorvers != NFSV4_MINORVERSION &&
808 minorvers != NFSV41_MINORVERSION &&
809 minorvers != NFSV42_MINORVERSION) ||
810 minorvers < nfs_minminorv4 || minorvers > nfs_maxminorv4)
811 nd->nd_repstat = NFSERR_MINORVERMISMATCH;
815 numops = fxdr_unsigned(int, *tl);
817 * Loop around doing the sub ops.
818 * vp - is an unlocked vnode pointer for the CFH
819 * savevp - is an unlocked vnode pointer for the SAVEDFH
820 * (at some future date, it might turn out to be more appropriate
821 * to keep the file handles instead of vnode pointers?)
822 * savevpnes and vpnes - are the export flags for the above.
824 for (i = 0; i < numops; i++) {
825 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
826 NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED);
828 op = fxdr_unsigned(int, *tl);
829 NFSD_DEBUG(4, "op=%d\n", op);
830 if (op < NFSV4OP_ACCESS || op >= NFSV42_NOPS ||
831 (op >= NFSV4OP_NOPS && (nd->nd_flag & ND_NFSV41) == 0) ||
832 (op >= NFSV41_NOPS && (nd->nd_flag & ND_NFSV42) == 0)) {
833 nd->nd_repstat = NFSERR_OPILLEGAL;
834 *repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL);
835 *repp = nfsd_errmap(nd);
842 binuptime(&start_time);
843 nfsrvd_statstart(op, &start_time);
849 nd->nd_flag |= ND_LASTOP;
852 * Check for a referral on the current FH and, if so, return
853 * NFSERR_MOVED for all ops that allow it, except Getattr.
855 if (vp != NULL && op != NFSV4OP_GETATTR &&
856 nfsv4root_getreferral(vp, NULL, 0) != NULL &&
857 nfsrv_errmoved(op)) {
858 nd->nd_repstat = NFSERR_MOVED;
859 *repp = nfsd_errmap(nd);
865 * For NFSv4.1, check for a Sequence Operation being first
866 * or one of the other allowed operations by itself.
868 if ((nd->nd_flag & ND_NFSV41) != 0) {
869 if (i != 0 && op == NFSV4OP_SEQUENCE)
870 nd->nd_repstat = NFSERR_SEQUENCEPOS;
871 else if (i == 0 && op != NFSV4OP_SEQUENCE &&
872 op != NFSV4OP_EXCHANGEID &&
873 op != NFSV4OP_CREATESESSION &&
874 op != NFSV4OP_BINDCONNTOSESS &&
875 op != NFSV4OP_DESTROYCLIENTID &&
876 op != NFSV4OP_DESTROYSESSION)
877 nd->nd_repstat = NFSERR_OPNOTINSESS;
878 else if (i != 0 && op0 != NFSV4OP_SEQUENCE)
879 nd->nd_repstat = NFSERR_NOTONLYOP;
880 if (nd->nd_repstat != 0) {
881 *repp = nfsd_errmap(nd);
889 * If over flood level, reply NFSERR_RESOURCE, if at the first
890 * Op. (Since a client recovery from NFSERR_RESOURCE can get
891 * really nasty for certain Op sequences, I'll play it safe
892 * and only return the error at the beginning.) The cache
893 * will still function over flood level, but uses lots of
895 * If nfsrv_mallocmget_limit() returns True, the system is near
896 * to its limit for memory that malloc()/mget() can allocate.
898 if (i == 0 && (nd->nd_rp == NULL ||
899 nd->nd_rp->rc_refcnt == 0) &&
900 (nfsrv_mallocmget_limit() ||
901 nfsrc_tcpsavedreplies > nfsrc_floodlevel)) {
902 if (nfsrc_tcpsavedreplies > nfsrc_floodlevel)
903 printf("nfsd server cache flooded, try "
904 "increasing vfs.nfsd.tcphighwater\n");
905 nd->nd_repstat = NFSERR_RESOURCE;
906 *repp = nfsd_errmap(nd);
907 if (op == NFSV4OP_SETATTR) {
909 * Setattr replies require a bitmap.
910 * even for errors like these.
912 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
918 if (nfsv4_opflag[op].savereply)
919 nd->nd_flag |= ND_SAVEREPLY;
922 error = nfsrv_mtofh(nd, &fh);
926 nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
928 /* For now, allow this for non-export FHs */
929 if (!nd->nd_repstat) {
933 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
938 case NFSV4OP_PUTPUBFH:
940 nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
943 nd->nd_repstat = NFSERR_NOFILEHANDLE;
944 if (!nd->nd_repstat) {
948 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
953 case NFSV4OP_PUTROOTFH:
955 nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp,
957 if (!nd->nd_repstat) {
961 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
966 nd->nd_repstat = NFSERR_NOFILEHANDLE;
969 if (vp && NFSVNO_EXPORTED(&vpnes)) {
971 /* If vp == savevp, a no-op */
978 save_fsid = cur_fsid;
980 if ((nd->nd_flag & ND_CURSTATEID) != 0) {
981 nd->nd_savedcurstateid =
983 nd->nd_flag |= ND_SAVEDCURSTATEID;
986 nd->nd_repstat = NFSERR_NOFILEHANDLE;
989 case NFSV4OP_RESTOREFH:
992 /* If vp == savevp, a no-op */
998 cur_fsid = save_fsid;
1000 if ((nd->nd_flag & ND_SAVEDCURSTATEID) != 0) {
1002 nd->nd_savedcurstateid;
1003 nd->nd_flag |= ND_CURSTATEID;
1006 nd->nd_repstat = NFSERR_RESTOREFH;
1011 * Allow a Lookup, Getattr, GetFH, Secinfo on an
1012 * non-exported directory if
1013 * nfs_rootfhset. Do I need to allow any other Ops?
1014 * (You can only have a non-exported vpnes if
1015 * nfs_rootfhset is true. See nfsd_fhtovp())
1016 * Allow AUTH_SYS to be used for file systems
1017 * exported GSS only for certain Ops, to allow
1018 * clients to do mounts more easily.
1020 if (nfsv4_opflag[op].needscfh && vp) {
1021 if (!NFSVNO_EXPORTED(&vpnes) &&
1022 op != NFSV4OP_LOOKUP &&
1023 op != NFSV4OP_GETATTR &&
1024 op != NFSV4OP_GETFH &&
1025 op != NFSV4OP_ACCESS &&
1026 op != NFSV4OP_READLINK &&
1027 op != NFSV4OP_SECINFO)
1028 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1029 else if (nfsvno_testexp(nd, &vpnes) &&
1030 op != NFSV4OP_LOOKUP &&
1031 op != NFSV4OP_GETFH &&
1032 op != NFSV4OP_GETATTR &&
1033 op != NFSV4OP_SECINFO)
1034 nd->nd_repstat = NFSERR_WRONGSEC;
1035 if (nd->nd_repstat) {
1036 if (op == NFSV4OP_SETATTR) {
1038 * Setattr reply requires a bitmap
1039 * even for errors like these.
1041 NFSM_BUILD(tl, u_int32_t *,
1048 if (nfsv4_opflag[op].retfh == 1) {
1050 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1054 if (nfsv4_opflag[op].modifyfs)
1055 vn_start_write(vp, &temp_mp, V_WAIT);
1056 error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
1057 &nvp, (fhandle_t *)fh.nfsrvfh_data, &vpnes);
1058 if (!error && !nd->nd_repstat) {
1059 if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) {
1060 new_mp = nvp->v_mount;
1061 if (fsidcmp(&cur_fsid, &new_mp->mnt_stat.f_fsid) != 0) {
1062 /* crossed a server mount point */
1063 nd->nd_repstat = nfsvno_checkexp(new_mp,
1064 nd->nd_nam, &nes, &credanon);
1065 if (!nd->nd_repstat)
1066 nd->nd_repstat = nfsd_excred(nd,
1068 if (credanon != NULL)
1070 if (!nd->nd_repstat) {
1072 cur_fsid = new_mp->mnt_stat.f_fsid;
1075 /* Lookup ops return a locked vnode */
1078 if (!nd->nd_repstat) {
1084 if (nfsv4_opflag[op].modifyfs)
1085 vn_finished_write(temp_mp);
1086 } else if (nfsv4_opflag[op].retfh == 2) {
1087 if (vp == NULL || savevp == NULL) {
1088 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1090 } else if (fsidcmp(&cur_fsid, &save_fsid) != 0) {
1091 nd->nd_repstat = NFSERR_XDEV;
1094 if (nfsv4_opflag[op].modifyfs)
1095 vn_start_write(savevp, &temp_mp, V_WAIT);
1096 if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
1099 error = (*(nfsrv4_ops2[op]))(nd, isdgram,
1100 savevp, vp, &savevpnes, &vpnes);
1102 nd->nd_repstat = NFSERR_PERM;
1103 if (nfsv4_opflag[op].modifyfs)
1104 vn_finished_write(temp_mp);
1106 if (nfsv4_opflag[op].retfh != 0)
1107 panic("nfsrvd_compound");
1108 if (nfsv4_opflag[op].needscfh) {
1110 lktype = nfsv4_opflag[op].lktype;
1111 if (nfsv4_opflag[op].modifyfs) {
1112 vn_start_write(vp, &temp_mp,
1114 if (op == NFSV4OP_WRITE &&
1115 MNT_SHARED_WRITES(temp_mp))
1118 if (NFSVOPLOCK(vp, lktype) == 0)
1121 nd->nd_repstat = NFSERR_PERM;
1123 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1124 if (op == NFSV4OP_SETATTR) {
1126 * Setattr reply requires a
1127 * bitmap even for errors like
1130 NFSM_BUILD(tl, u_int32_t *,
1136 if (nd->nd_repstat == 0)
1137 error = (*(nfsrv4_ops0[op]))(nd,
1138 isdgram, vp, &vpnes);
1139 if (nfsv4_opflag[op].modifyfs)
1140 vn_finished_write(temp_mp);
1142 error = (*(nfsrv4_ops0[op]))(nd, isdgram,
1148 if (error == EBADRPC || error == NFSERR_BADXDR) {
1149 nd->nd_repstat = NFSERR_BADXDR;
1151 nd->nd_repstat = error;
1152 printf("nfsv4 comperr0=%d\n", error);
1157 if (statsinprog != 0) {
1158 nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1159 /*then*/ &start_time);
1164 if (nd->nd_repstat) {
1165 *repp = nfsd_errmap(nd);
1168 *repp = 0; /* NFS4_OK */
1172 if (statsinprog != 0) {
1173 nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1174 /*then*/ &start_time);
1178 if (error == EBADRPC || error == NFSERR_BADXDR)
1179 nd->nd_repstat = NFSERR_BADXDR;
1181 printf("nfsv4 comperr1=%d\n", error);
1184 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1188 *retopsp = txdr_unsigned(retops);
1194 NFSLOCKV4ROOTMUTEX();
1195 nfsv4_relref(&nfsv4rootfs_lock);
1196 NFSUNLOCKV4ROOTMUTEX();
1198 NFSEXITCODE2(0, nd);