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);
430 * This static array indicates which server procedures require the extra
431 * arguments to return the current file handle for V2, 3.
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 };
436 extern struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS];
438 static int nfsv3to4op[NFS_V3NPROCS] = {
463 static struct mtx nfsrvd_statmtx;
464 MTX_SYSINIT(nfsst, &nfsrvd_statmtx, "NFSstat", MTX_DEF);
467 nfsrvd_statstart(int op, struct bintime *now)
469 if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
470 printf("%s: op %d invalid\n", __func__, op);
474 mtx_lock(&nfsrvd_statmtx);
475 if (nfsstatsv1.srvstartcnt == nfsstatsv1.srvdonecnt) {
477 nfsstatsv1.busyfrom = *now;
479 binuptime(&nfsstatsv1.busyfrom);
482 nfsstatsv1.srvrpccnt[op]++;
483 nfsstatsv1.srvstartcnt++;
484 mtx_unlock(&nfsrvd_statmtx);
489 nfsrvd_statend(int op, uint64_t bytes, struct bintime *now,
490 struct bintime *then)
492 struct bintime dt, lnow;
494 if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
495 printf("%s: op %d invalid\n", __func__, op);
504 mtx_lock(&nfsrvd_statmtx);
506 nfsstatsv1.srvbytes[op] += bytes;
507 nfsstatsv1.srvops[op]++;
511 bintime_sub(&dt, then);
512 bintime_add(&nfsstatsv1.srvduration[op], &dt);
516 bintime_sub(&dt, &nfsstatsv1.busyfrom);
517 bintime_add(&nfsstatsv1.busytime, &dt);
518 nfsstatsv1.busyfrom = *now;
520 nfsstatsv1.srvdonecnt++;
522 mtx_unlock(&nfsrvd_statmtx);
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().
533 nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, u_char *tag, int taglen,
536 int error = 0, lktype;
540 struct nfsexstuff nes;
543 * Get a locked vnode for the first file handle
545 if (!(nd->nd_flag & ND_NFSV4)) {
546 KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc"));
548 * For NFSv3, if the malloc/mget allocation is near limits,
549 * return NFSERR_DELAY.
551 if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) {
552 nd->nd_repstat = NFSERR_DELAY;
555 error = nfsrv_mtofh(nd, &fh);
557 if (error != EBADRPC)
558 printf("nfs dorpc err1=%d\n", error);
559 nd->nd_repstat = NFSERR_GARBAGE;
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)
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]);
578 nfsd_fhtovp(nd, &fh, lktype, &vp, &nes,
579 &mp, nfsrv_writerpc[nd->nd_procnum]);
580 if (nd->nd_repstat == NFSERR_PROGNOTV4)
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.
590 if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum])
591 nd->nd_flag |= ND_SAVEREPLY;
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
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);
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[].
615 if (nd->nd_flag & ND_NFSV4) {
616 nfsrvd_compound(nd, isdgram, tag, taglen, minorvers);
618 struct bintime start_time;
620 binuptime(&start_time);
621 nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], &start_time);
623 if (nfs_retfh[nd->nd_procnum] == 1) {
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);
632 error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
635 if (mp != NULL && nfsrv_writerpc[nd->nd_procnum] != 0)
636 vn_finished_write(mp);
638 nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
639 /*now*/ NULL, /*then*/ &start_time);
642 if (error != EBADRPC)
643 printf("nfs dorpc err2=%d\n", error);
644 nd->nd_repstat = NFSERR_GARBAGE;
646 *nd->nd_errp = nfsd_errmap(nd);
649 * Don't cache certain reply status values.
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;
672 * Breaks down a compound RPC request and calls the server routines for
674 * Some suboperations are performed directly here to simplify file handle<-->
675 * vnode pointer handling.
678 nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,
679 int taglen, u_int32_t minorvers)
681 int i, lktype, op, op0 = 0, statsinprog = 0;
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;
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;
698 NFSVNO_EXINIT(&vpnes);
699 NFSVNO_EXINIT(&savevpnes);
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.
708 nd->nd_compref = compref++;
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().
722 * First, check to see if we need to wait for an update lock.
725 NFSLOCKV4ROOTMUTEX();
726 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK)
727 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
728 NFSV4ROOTLOCKMUTEXPTR, NULL);
730 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
731 NFSV4ROOTLOCKMUTEXPTR, NULL);
732 NFSUNLOCKV4ROOTMUTEX();
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
739 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK;
740 if ((nfsrv_stablefirst.nsf_flags &
741 (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
742 nfsrv_updatestable(p);
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
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,
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);
769 NFSLOCKV4ROOTMUTEX();
770 nfsv4_unlock(&nfsv4rootfs_lock, 1);
771 NFSUNLOCKV4ROOTMUTEX();
774 * If we didn't get the lock, we need to get a refcnt,
775 * which also checks for and waits for the lock.
777 NFSLOCKV4ROOTMUTEX();
778 nfsv4_getref(&nfsv4rootfs_lock, NULL,
779 NFSV4ROOTLOCKMUTEXPTR, NULL);
780 NFSUNLOCKV4ROOTMUTEX();
784 * If flagged, search for open owners that haven't had any opens
787 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) {
788 nfsrv_throwawayopens(p);
791 /* Do a CBLAYOUTRECALL callback if over the high water mark. */
792 if (nfsrv_layoutcnt > nfsrv_layouthighwater)
793 nfsrv_recalloldlayout(p);
796 save_fsid.val[0] = save_fsid.val[1] = 0;
797 cur_fsid.val[0] = cur_fsid.val[1] = 0;
799 /* If taglen < 0, there was a parsing error in nfsd_getminorvers(). */
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;
816 numops = fxdr_unsigned(int, *tl);
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.
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);
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);
843 binuptime(&start_time);
844 nfsrvd_statstart(op, &start_time);
850 nd->nd_flag |= ND_LASTOP;
853 * Check for a referral on the current FH and, if so, return
854 * NFSERR_MOVED for all ops that allow it, except Getattr.
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);
866 * For NFSv4.1, check for a Sequence Operation being first
867 * or one of the other allowed operations by itself.
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);
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
896 * If nfsrv_mallocmget_limit() returns True, the system is near
897 * to its limit for memory that malloc()/mget() can allocate.
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) {
910 * Setattr replies require a bitmap.
911 * even for errors like these.
913 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
919 if (nfsv4_opflag[op].savereply)
920 nd->nd_flag |= ND_SAVEREPLY;
923 error = nfsrv_mtofh(nd, &fh);
927 nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
929 /* For now, allow this for non-export FHs */
930 if (!nd->nd_repstat) {
934 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
939 case NFSV4OP_PUTPUBFH:
941 nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
944 nd->nd_repstat = NFSERR_NOFILEHANDLE;
945 if (!nd->nd_repstat) {
949 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
954 case NFSV4OP_PUTROOTFH:
956 nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp,
958 if (!nd->nd_repstat) {
962 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
967 nd->nd_repstat = NFSERR_NOFILEHANDLE;
970 if (vp && NFSVNO_EXPORTED(&vpnes)) {
972 /* If vp == savevp, a no-op */
979 save_fsid = cur_fsid;
981 if ((nd->nd_flag & ND_CURSTATEID) != 0) {
982 nd->nd_savedcurstateid =
984 nd->nd_flag |= ND_SAVEDCURSTATEID;
987 nd->nd_repstat = NFSERR_NOFILEHANDLE;
990 case NFSV4OP_RESTOREFH:
993 /* If vp == savevp, a no-op */
999 cur_fsid = save_fsid;
1001 if ((nd->nd_flag & ND_SAVEDCURSTATEID) != 0) {
1003 nd->nd_savedcurstateid;
1004 nd->nd_flag |= ND_CURSTATEID;
1007 nd->nd_repstat = NFSERR_RESTOREFH;
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.
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) {
1039 * Setattr reply requires a bitmap
1040 * even for errors like these.
1042 NFSM_BUILD(tl, u_int32_t *,
1049 if (nfsv4_opflag[op].retfh == 1) {
1051 nd->nd_repstat = NFSERR_NOFILEHANDLE;
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,
1069 if (credanon != NULL)
1071 if (!nd->nd_repstat) {
1073 cur_fsid = new_mp->mnt_stat.f_fsid;
1076 /* Lookup ops return a locked vnode */
1079 if (!nd->nd_repstat) {
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;
1091 } else if (fsidcmp(&cur_fsid, &save_fsid) != 0) {
1092 nd->nd_repstat = NFSERR_XDEV;
1095 if (nfsv4_opflag[op].modifyfs)
1096 vn_start_write(savevp, &temp_mp, V_WAIT);
1097 if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
1100 error = (*(nfsrv4_ops2[op]))(nd, isdgram,
1101 savevp, vp, &savevpnes, &vpnes);
1103 nd->nd_repstat = NFSERR_PERM;
1104 if (nfsv4_opflag[op].modifyfs)
1105 vn_finished_write(temp_mp);
1107 if (nfsv4_opflag[op].retfh != 0)
1108 panic("nfsrvd_compound");
1109 if (nfsv4_opflag[op].needscfh) {
1111 lktype = nfsv4_opflag[op].lktype;
1112 if (nfsv4_opflag[op].modifyfs) {
1113 vn_start_write(vp, &temp_mp,
1115 if (op == NFSV4OP_WRITE &&
1116 MNT_SHARED_WRITES(temp_mp))
1119 if (NFSVOPLOCK(vp, lktype) == 0)
1122 nd->nd_repstat = NFSERR_PERM;
1124 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1125 if (op == NFSV4OP_SETATTR) {
1127 * Setattr reply requires a
1128 * bitmap even for errors like
1131 NFSM_BUILD(tl, u_int32_t *,
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);
1143 error = (*(nfsrv4_ops0[op]))(nd, isdgram,
1149 if (error == EBADRPC || error == NFSERR_BADXDR) {
1150 nd->nd_repstat = NFSERR_BADXDR;
1152 nd->nd_repstat = error;
1153 printf("nfsv4 comperr0=%d\n", error);
1158 if (statsinprog != 0) {
1159 nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1160 /*then*/ &start_time);
1165 if (nd->nd_repstat) {
1166 *repp = nfsd_errmap(nd);
1169 *repp = 0; /* NFS4_OK */
1173 if (statsinprog != 0) {
1174 nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1175 /*then*/ &start_time);
1179 if (error == EBADRPC || error == NFSERR_BADXDR)
1180 nd->nd_repstat = NFSERR_BADXDR;
1182 printf("nfsv4 comperr1=%d\n", error);
1185 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1189 *retopsp = txdr_unsigned(retops);
1195 NFSLOCKV4ROOTMUTEX();
1196 nfsv4_relref(&nfsv4rootfs_lock);
1197 NFSUNLOCKV4ROOTMUTEX();
1199 NFSEXITCODE2(0, nd);