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 #include <security/mac/mac_framework.h>
47 extern struct nfsrvfh nfs_pubfh;
48 extern int nfs_pubfhset;
49 extern struct nfsv4lock nfsv4rootfs_lock;
50 extern int nfsrv_clienthashsize;
51 extern int nfsd_debuglevel;
52 extern int nfsrv_layouthighwater;
53 extern volatile int nfsrv_layoutcnt;
57 NFSD_VNET_DECLARE(struct nfsrv_stablefirst, nfsrv_stablefirst);
58 NFSD_VNET_DECLARE(struct nfsclienthashhead *, nfsclienthash);
59 NFSD_VNET_DECLARE(int, nfsrc_floodlevel);
60 NFSD_VNET_DECLARE(int, nfsrc_tcpsavedreplies);
61 NFSD_VNET_DECLARE(struct nfsrvfh, nfs_rootfh);
62 NFSD_VNET_DECLARE(int, nfs_rootfhset);
63 NFSD_VNET_DECLARE(struct nfsstatsv1 *, nfsstatsv1_p);
65 int (*nfsrv3_procs0[NFS_V3NPROCS])(struct nfsrv_descript *,
66 int, vnode_t , struct nfsexstuff *) = {
67 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
70 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
76 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
77 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
78 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
81 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
82 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
91 int (*nfsrv3_procs1[NFS_V3NPROCS])(struct nfsrv_descript *,
92 int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *) = {
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,
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,
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,
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,
113 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
114 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
117 int (*nfsrv3_procs2[NFS_V3NPROCS])(struct nfsrv_descript *,
118 int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *) = {
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,
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,
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,
139 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
140 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
143 int (*nfsrv4_ops0[NFSV42_NOPS])(struct nfsrv_descript *,
144 int, vnode_t , struct nfsexstuff *) = {
145 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
146 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
147 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
151 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
156 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
160 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
161 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
163 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
164 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
166 nfsrvd_opendowngrade,
167 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
168 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
169 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
174 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
176 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
177 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
181 nfsrvd_setclientidcfrm,
184 nfsrvd_releaselckown,
188 nfsrvd_createsession,
189 nfsrvd_destroysession,
197 nfsrvd_secinfononame,
202 nfsrvd_destroyclientid,
203 nfsrvd_reclaimcomplete,
205 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
223 int (*nfsrv4_ops1[NFSV42_NOPS])(struct nfsrv_descript *,
224 int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *) = {
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,
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,
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,
238 (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,
242 (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,
299 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
300 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
303 int (*nfsrv4_ops2[NFSV42_NOPS])(struct nfsrv_descript *,
304 int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *) = {
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,
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,
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,
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,
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 (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 nfsrvd_copy_file_range,
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,
379 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
380 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
384 * Static array that defines which nfs rpc's are nonidempotent
386 static int nfsrv_nonidempotent[NFS_V3NPROCS] = {
412 * This static array indicates whether or not the RPC modifies the
415 int nfsrv_writerpc[NFS_NPROCS] = { 0, 0, 1, 0, 0, 0, 0,
416 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
417 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
419 SYSCTL_DECL(_vfs_nfsd);
420 static int nfs_minminorv4 = NFSV4_MINORVERSION;
421 SYSCTL_INT(_vfs_nfsd, OID_AUTO, server_min_minorversion4, CTLFLAG_RWTUN,
423 "The lowest minor version of NFSv4 handled by the server");
425 static int nfs_maxminorv4 = NFSV42_MINORVERSION;
426 SYSCTL_INT(_vfs_nfsd, OID_AUTO, server_max_minorversion4, CTLFLAG_RWTUN,
428 "The highest minor version of NFSv4 handled by the server");
430 /* local functions */
431 static void nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
432 u_char *tag, int taglen, u_int32_t minorvers);
435 * This static array indicates which server procedures require the extra
436 * arguments to return the current file handle for V2, 3.
438 static int nfs_retfh[NFS_V3NPROCS] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1,
439 1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0 };
441 extern struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS];
443 static int nfsv3to4op[NFS_V3NPROCS] = {
468 static struct mtx nfsrvd_statmtx;
469 MTX_SYSINIT(nfsst, &nfsrvd_statmtx, "NFSstat", MTX_DEF);
471 static struct ucred *nfsrv_createrootcred(void);
474 nfsrvd_statstart(int op, struct bintime *now)
476 if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
477 printf("%s: op %d invalid\n", __func__, op);
481 mtx_lock(&nfsrvd_statmtx);
482 if (NFSD_VNET(nfsstatsv1_p)->srvstartcnt ==
483 NFSD_VNET(nfsstatsv1_p)->srvdonecnt) {
485 NFSD_VNET(nfsstatsv1_p)->busyfrom = *now;
487 binuptime(&NFSD_VNET(nfsstatsv1_p)->busyfrom);
490 NFSD_VNET(nfsstatsv1_p)->srvrpccnt[op]++;
491 NFSD_VNET(nfsstatsv1_p)->srvstartcnt++;
492 mtx_unlock(&nfsrvd_statmtx);
497 nfsrvd_statend(int op, uint64_t bytes, struct bintime *now,
498 struct bintime *then)
500 struct bintime dt, lnow;
502 if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
503 printf("%s: op %d invalid\n", __func__, op);
512 mtx_lock(&nfsrvd_statmtx);
514 NFSD_VNET(nfsstatsv1_p)->srvbytes[op] += bytes;
515 NFSD_VNET(nfsstatsv1_p)->srvops[op]++;
519 bintime_sub(&dt, then);
520 bintime_add(&NFSD_VNET(nfsstatsv1_p)->srvduration[op], &dt);
524 bintime_sub(&dt, &NFSD_VNET(nfsstatsv1_p)->busyfrom);
525 bintime_add(&NFSD_VNET(nfsstatsv1_p)->busytime, &dt);
526 NFSD_VNET(nfsstatsv1_p)->busyfrom = *now;
528 NFSD_VNET(nfsstatsv1_p)->srvdonecnt++;
530 mtx_unlock(&nfsrvd_statmtx);
534 * Do an RPC. Basically, get the file handles translated to vnode pointers
535 * and then call the appropriate server routine. The server routines are
536 * split into groups, based on whether they use a file handle or file
537 * handle plus name or ...
538 * The NFS V4 Compound RPC is performed separately by nfsrvd_compound().
541 nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, u_char *tag, int taglen,
544 int error = 0, lktype;
548 struct nfsexstuff nes;
553 * Save the current position in the request mbuf list so
554 * that a rollback to this location can be done upon an
555 * ERELOOKUP error return from an RPC function.
563 * Get a locked vnode for the first file handle
565 if (!(nd->nd_flag & ND_NFSV4)) {
566 KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc"));
568 * For NFSv3, if the malloc/mget allocation is near limits,
569 * return NFSERR_DELAY.
571 if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) {
572 nd->nd_repstat = NFSERR_DELAY;
575 error = nfsrv_mtofh(nd, &fh);
577 if (error != EBADRPC)
578 printf("nfs dorpc err1=%d\n", error);
579 nd->nd_repstat = NFSERR_GARBAGE;
582 if (nd->nd_procnum == NFSPROC_READ ||
583 nd->nd_procnum == NFSPROC_WRITE ||
584 nd->nd_procnum == NFSPROC_READDIR ||
585 nd->nd_procnum == NFSPROC_READDIRPLUS ||
586 nd->nd_procnum == NFSPROC_READLINK ||
587 nd->nd_procnum == NFSPROC_GETATTR ||
588 nd->nd_procnum == NFSPROC_ACCESS ||
589 nd->nd_procnum == NFSPROC_FSSTAT ||
590 nd->nd_procnum == NFSPROC_FSINFO)
593 lktype = LK_EXCLUSIVE;
594 if (nd->nd_flag & ND_PUBLOOKUP)
595 nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes,
596 &mp, nfsrv_writerpc[nd->nd_procnum], -1);
598 nfsd_fhtovp(nd, &fh, lktype, &vp, &nes,
599 &mp, nfsrv_writerpc[nd->nd_procnum], -1);
600 if (nd->nd_repstat == NFSERR_PROGNOTV4)
606 * For V2 and 3, set the ND_SAVEREPLY flag for the recent request
607 * cache, as required.
608 * For V4, nfsrvd_compound() does this.
610 if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum])
611 nd->nd_flag |= ND_SAVEREPLY;
615 * If nd_repstat is non-zero, just fill in the reply status
616 * to complete the RPC reply for V2. Otherwise, you must do
619 if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) {
620 *nd->nd_errp = nfsd_errmap(nd);
621 nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], /*now*/ NULL);
622 nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
623 /*now*/ NULL, /*then*/ NULL);
624 vn_finished_write(mp);
629 * Now the procedure can be performed. For V4, nfsrvd_compound()
630 * works through the sub-rpcs, otherwise just call the procedure.
631 * The procedures are in three groups with different arguments.
632 * The group is indicated by the value in nfs_retfh[].
634 if (nd->nd_flag & ND_NFSV4) {
635 nfsrvd_compound(nd, isdgram, tag, taglen, minorvers);
637 struct bintime start_time;
639 binuptime(&start_time);
640 nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], &start_time);
642 if (nfs_retfh[nd->nd_procnum] == 1) {
645 error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram,
646 vp, NULL, (fhandle_t *)fh.nfsrvfh_data, &nes);
647 } else if (nfs_retfh[nd->nd_procnum] == 2) {
648 error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram,
649 vp, NULL, &nes, NULL);
651 error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
654 vn_finished_write(mp);
656 if (error == 0 && nd->nd_repstat == ERELOOKUP) {
658 * Roll back to the beginning of the RPC request
664 /* Free the junk RPC reply and redo the RPC. */
665 m_freem(nd->nd_mreq);
666 nd->nd_mreq = nd->nd_mb = NULL;
671 nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
672 /*now*/ NULL, /*then*/ &start_time);
675 if (error != EBADRPC)
676 printf("nfs dorpc err2=%d\n", error);
677 nd->nd_repstat = NFSERR_GARBAGE;
679 *nd->nd_errp = nfsd_errmap(nd);
682 * Don't cache certain reply status values.
684 if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) &&
685 (nd->nd_repstat == NFSERR_GARBAGE ||
686 nd->nd_repstat == NFSERR_BADXDR ||
687 nd->nd_repstat == NFSERR_MOVED ||
688 nd->nd_repstat == NFSERR_DELAY ||
689 nd->nd_repstat == NFSERR_BADSEQID ||
690 nd->nd_repstat == NFSERR_RESOURCE ||
691 nd->nd_repstat == NFSERR_SERVERFAULT ||
692 nd->nd_repstat == NFSERR_STALECLIENTID ||
693 nd->nd_repstat == NFSERR_STALESTATEID ||
694 nd->nd_repstat == NFSERR_OLDSTATEID ||
695 nd->nd_repstat == NFSERR_BADSTATEID ||
696 nd->nd_repstat == NFSERR_GRACE ||
697 nd->nd_repstat == NFSERR_NOGRACE))
698 nd->nd_flag &= ~ND_SAVEREPLY;
705 * Breaks down a compound RPC request and calls the server routines for
707 * Some suboperations are performed directly here to simplify file handle<-->
708 * vnode pointer handling.
711 nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,
712 int taglen, u_int32_t minorvers)
714 int i, lktype, op, op0 = 0, rstat, statsinprog = 0;
716 struct nfsclient *clp, *nclp;
717 int error = 0, igotlock, nextop, numops, savefhcnt;
718 u_int32_t retops = 0, *retopsp = NULL, *repp;
719 vnode_t vp, nvp, savevp;
721 mount_t new_mp, temp_mp = NULL;
722 struct ucred *credanon, *rootcred, *savecred;
723 struct nfsexstuff nes, vpnes, savevpnes;
724 fsid_t cur_fsid, save_fsid;
725 static u_int64_t compref = 0;
726 struct bintime start_time;
728 struct mbuf *mb, *md;
730 int bextpg, bextpgsiz;
733 rootcred = savecred = NULL;
735 /* Check for and optionally clear the no space flags for DSs. */
738 NFSVNO_EXINIT(&vpnes);
739 NFSVNO_EXINIT(&savevpnes);
741 * Put the seq# of the current compound RPC in nfsrv_descript.
742 * (This is used by nfsrv_checkgetattr(), to see if the write
743 * delegation was created by the same compound RPC as the one
744 * with that Getattr in it.)
745 * Don't worry about the 64bit number wrapping around. It ain't
746 * gonna happen before this server gets shut down/rebooted.
748 nd->nd_compref = compref++;
751 * Check for and optionally get a lock on the root. This lock means that
752 * no nfsd will be fiddling with the V4 file system and state stuff. It
753 * is required when the V4 root is being changed, the stable storage
754 * restart file is being updated, or callbacks are being done.
755 * When any of the nfsd are processing an NFSv4 compound RPC, they must
756 * either hold a reference count (nfs_usecnt) or the lock. When
757 * nfsrv_unlock() is called to release the lock, it can optionally
758 * also get a reference count, which saves the need for a call to
759 * nfsrv_getref() after nfsrv_unlock().
762 * First, check to see if we need to wait for an update lock.
765 NFSLOCKV4ROOTMUTEX();
766 if (NFSD_VNET(nfsrv_stablefirst).nsf_flags & NFSNSF_NEEDLOCK)
767 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
768 NFSV4ROOTLOCKMUTEXPTR, NULL);
770 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
771 NFSV4ROOTLOCKMUTEXPTR, NULL);
772 NFSUNLOCKV4ROOTMUTEX();
775 * If I got the lock, I can update the stable storage file.
776 * Done when the grace period is over or a client has long
779 NFSD_VNET(nfsrv_stablefirst).nsf_flags &= ~NFSNSF_NEEDLOCK;
780 if ((NFSD_VNET(nfsrv_stablefirst).nsf_flags &
781 (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
782 nfsrv_updatestable(p);
785 * If at least one client has long since expired, search
786 * the client list for them, write a REVOKE record on the
787 * stable storage file and then remove them from the client
790 if (NFSD_VNET(nfsrv_stablefirst).nsf_flags &
791 NFSNSF_EXPIREDCLIENT) {
792 NFSD_VNET(nfsrv_stablefirst).nsf_flags &=
793 ~NFSNSF_EXPIREDCLIENT;
794 for (i = 0; i < nfsrv_clienthashsize; i++) {
795 LIST_FOREACH_SAFE(clp, &NFSD_VNET(nfsclienthash)[i],
797 if (clp->lc_flags & LCL_EXPIREIT) {
798 if (!LIST_EMPTY(&clp->lc_open) ||
799 !LIST_EMPTY(&clp->lc_deleg))
800 nfsrv_writestable(clp->lc_id,
801 clp->lc_idlen, NFSNST_REVOKE, p);
802 nfsrv_cleanclient(clp, p);
803 nfsrv_freedeleglist(&clp->lc_deleg);
804 nfsrv_freedeleglist(&clp->lc_olddeleg);
805 LIST_REMOVE(clp, lc_hash);
806 nfsrv_zapclient(clp, p);
811 NFSLOCKV4ROOTMUTEX();
812 nfsv4_unlock(&nfsv4rootfs_lock, 1);
813 NFSUNLOCKV4ROOTMUTEX();
816 * If we didn't get the lock, we need to get a refcnt,
817 * which also checks for and waits for the lock.
819 NFSLOCKV4ROOTMUTEX();
820 nfsv4_getref(&nfsv4rootfs_lock, NULL,
821 NFSV4ROOTLOCKMUTEXPTR, NULL);
822 NFSUNLOCKV4ROOTMUTEX();
826 * If flagged, search for open owners that haven't had any opens
829 if (NFSD_VNET(nfsrv_stablefirst).nsf_flags & NFSNSF_NOOPENS) {
830 nfsrv_throwawayopens(p);
833 /* Do a CBLAYOUTRECALL callback if over the high water mark. */
834 if (nfsrv_layoutcnt > nfsrv_layouthighwater)
835 nfsrv_recalloldlayout(p);
838 save_fsid.val[0] = save_fsid.val[1] = 0;
839 cur_fsid.val[0] = cur_fsid.val[1] = 0;
843 /* If taglen < 0, there was a parsing error in nfsd_getminorvers(). */
849 (void) nfsm_strtom(nd, tag, taglen);
850 NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED);
851 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
852 if ((minorvers != NFSV4_MINORVERSION &&
853 minorvers != NFSV41_MINORVERSION &&
854 minorvers != NFSV42_MINORVERSION) ||
855 minorvers < nfs_minminorv4 || minorvers > nfs_maxminorv4)
856 nd->nd_repstat = NFSERR_MINORVERMISMATCH;
860 numops = fxdr_unsigned(int, *tl);
862 * Loop around doing the sub ops.
863 * vp - is an unlocked vnode pointer for the CFH
864 * savevp - is an unlocked vnode pointer for the SAVEDFH
865 * (at some future date, it might turn out to be more appropriate
866 * to keep the file handles instead of vnode pointers?)
867 * savevpnes and vpnes - are the export flags for the above.
869 for (i = 0; i < numops; i++) {
870 NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED);
873 *repp = txdr_unsigned(op);
875 } else if (nextop == -1) {
876 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
878 op = fxdr_unsigned(int, *tl);
881 *repp = txdr_unsigned(op);
884 NFSD_DEBUG(4, "op=%d\n", op);
885 if (op < NFSV4OP_ACCESS || op >= NFSV42_NOPS ||
886 (op >= NFSV4OP_NOPS && (nd->nd_flag & ND_NFSV41) == 0) ||
887 (op >= NFSV41_NOPS && (nd->nd_flag & ND_NFSV42) == 0)) {
888 nd->nd_repstat = NFSERR_OPILLEGAL;
889 *repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL);
890 *repp = nfsd_errmap(nd);
897 binuptime(&start_time);
898 nfsrvd_statstart(op, &start_time);
904 nd->nd_flag |= ND_LASTOP;
907 * Check for a referral on the current FH and, if so, return
908 * NFSERR_MOVED for all ops that allow it, except Getattr.
910 if (vp != NULL && op != NFSV4OP_GETATTR &&
911 nfsv4root_getreferral(vp, NULL, 0) != NULL &&
912 nfsrv_errmoved(op)) {
913 nd->nd_repstat = NFSERR_MOVED;
914 *repp = nfsd_errmap(nd);
920 * For NFSv4.1, check for a Sequence Operation being first
921 * or one of the other allowed operations by itself.
923 if ((nd->nd_flag & ND_NFSV41) != 0) {
924 if (i != 0 && op == NFSV4OP_SEQUENCE)
925 nd->nd_repstat = NFSERR_SEQUENCEPOS;
926 else if (i == 0 && op != NFSV4OP_SEQUENCE &&
927 op != NFSV4OP_EXCHANGEID &&
928 op != NFSV4OP_CREATESESSION &&
929 op != NFSV4OP_BINDCONNTOSESS &&
930 op != NFSV4OP_DESTROYCLIENTID &&
931 op != NFSV4OP_DESTROYSESSION)
932 nd->nd_repstat = NFSERR_OPNOTINSESS;
933 else if (i != 0 && op0 != NFSV4OP_SEQUENCE)
934 nd->nd_repstat = NFSERR_NOTONLYOP;
935 if (nd->nd_repstat != 0) {
936 *repp = nfsd_errmap(nd);
944 * If over flood level, reply NFSERR_RESOURCE, if at the first
945 * Op. (Since a client recovery from NFSERR_RESOURCE can get
946 * really nasty for certain Op sequences, I'll play it safe
947 * and only return the error at the beginning.) The cache
948 * will still function over flood level, but uses lots of
950 * If nfsrv_mallocmget_limit() returns True, the system is near
951 * to its limit for memory that malloc()/mget() can allocate.
953 if (i == 0 && (nd->nd_rp == NULL ||
954 nd->nd_rp->rc_refcnt == 0) &&
955 (nfsrv_mallocmget_limit() ||
956 NFSD_VNET(nfsrc_tcpsavedreplies) >
957 NFSD_VNET(nfsrc_floodlevel))) {
958 if (NFSD_VNET(nfsrc_tcpsavedreplies) >
959 NFSD_VNET(nfsrc_floodlevel))
960 printf("nfsd server cache flooded, try "
961 "increasing vfs.nfsd.tcphighwater\n");
962 nd->nd_repstat = NFSERR_RESOURCE;
963 *repp = nfsd_errmap(nd);
964 if (op == NFSV4OP_SETATTR) {
966 * Setattr replies require a bitmap.
967 * even for errors like these.
969 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
977 * Check for the case of SP4_MACH_CRED and an operation in
978 * the allow set. For these operations, replace nd_cred with
979 * root credentials so that the operation will not fail due
981 * NB: ND_MACHCRED is set by Sequence when the ClientID
982 * specifies LCL_MACHCRED and the RPC is being performed
983 * via krb5i or krb5p using the machine principal.
985 if ((nd->nd_flag & ND_MACHCRED) != 0) {
986 if (NFSISSET_OPBIT(&nd->nd_allowops, op)) {
987 /* Replace nd_cred with root creds. */
988 if (rootcred == NULL)
989 rootcred = nfsrv_createrootcred();
990 if (savecred == NULL)
991 savecred = nd->nd_cred;
992 nd->nd_cred = rootcred;
993 } else if (savecred != NULL) {
994 nd->nd_cred = savecred;
999 if (nfsv4_opflag[op].savereply)
1000 nd->nd_flag |= ND_SAVEREPLY;
1003 error = nfsrv_mtofh(nd, &fh);
1006 if ((nd->nd_flag & ND_LASTOP) == 0) {
1008 * Pre-parse the next op#. If it is
1009 * SaveFH, count it and skip to the
1010 * next op#, if not the last op#.
1011 * nextop is used to determine if
1012 * NFSERR_WRONGSEC can be returned,
1013 * per RFC5661 Sec. 2.6.
1016 NFSM_DISSECT(tl, uint32_t *,
1018 nextop = fxdr_unsigned(int, *tl);
1019 if (nextop == NFSV4OP_SAVEFH &&
1022 } while (nextop == NFSV4OP_SAVEFH &&
1025 if (!nd->nd_repstat)
1026 nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
1028 /* For now, allow this for non-export FHs */
1029 if (!nd->nd_repstat) {
1033 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
1038 case NFSV4OP_PUTPUBFH:
1040 if ((nd->nd_flag & ND_LASTOP) == 0) {
1042 * Pre-parse the next op#. If it is
1043 * SaveFH, count it and skip to the
1044 * next op#, if not the last op#.
1045 * nextop is used to determine if
1046 * NFSERR_WRONGSEC can be returned,
1047 * per RFC5661 Sec. 2.6.
1050 NFSM_DISSECT(tl, uint32_t *,
1052 nextop = fxdr_unsigned(int,
1054 if (nextop == NFSV4OP_SAVEFH &&
1057 } while (nextop == NFSV4OP_SAVEFH &&
1060 nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
1061 &nes, NULL, 0, nextop);
1063 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1064 if (!nd->nd_repstat) {
1068 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
1073 case NFSV4OP_PUTROOTFH:
1074 if (NFSD_VNET(nfs_rootfhset)) {
1075 if ((nd->nd_flag & ND_LASTOP) == 0) {
1077 * Pre-parse the next op#. If it is
1078 * SaveFH, count it and skip to the
1079 * next op#, if not the last op#.
1080 * nextop is used to determine if
1081 * NFSERR_WRONGSEC can be returned,
1082 * per RFC5661 Sec. 2.6.
1085 NFSM_DISSECT(tl, uint32_t *,
1087 nextop = fxdr_unsigned(int,
1089 if (nextop == NFSV4OP_SAVEFH &&
1092 } while (nextop == NFSV4OP_SAVEFH &&
1095 nfsd_fhtovp(nd, &NFSD_VNET(nfs_rootfh),
1096 LK_SHARED, &nvp, &nes, NULL, 0, nextop);
1097 if (!nd->nd_repstat) {
1101 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
1106 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1108 case NFSV4OP_SAVEFH:
1109 if (vp && NFSVNO_EXPORTED(&vpnes)) {
1111 /* If vp == savevp, a no-op */
1118 save_fsid = cur_fsid;
1120 if ((nd->nd_flag & ND_CURSTATEID) != 0) {
1121 nd->nd_savedcurstateid =
1123 nd->nd_flag |= ND_SAVEDCURSTATEID;
1126 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1129 case NFSV4OP_RESTOREFH:
1131 if ((nd->nd_flag & ND_LASTOP) == 0) {
1133 * Pre-parse the next op#. If it is
1134 * SaveFH, count it and skip to the
1135 * next op#, if not the last op#.
1136 * nextop is used to determine if
1137 * NFSERR_WRONGSEC can be returned,
1138 * per RFC5661 Sec. 2.6.
1141 NFSM_DISSECT(tl, uint32_t *,
1143 nextop = fxdr_unsigned(int,
1145 if (nextop == NFSV4OP_SAVEFH &&
1148 } while (nextop == NFSV4OP_SAVEFH &&
1152 /* If vp == savevp, a no-op */
1154 if (nfsrv_checkwrongsec(nd, nextop,
1159 if (nd->nd_repstat == 0) {
1164 cur_fsid = save_fsid;
1167 if (nd->nd_repstat == 0 &&
1168 (nd->nd_flag & ND_SAVEDCURSTATEID) != 0) {
1170 nd->nd_savedcurstateid;
1171 nd->nd_flag |= ND_CURSTATEID;
1174 nd->nd_repstat = NFSERR_RESTOREFH;
1179 * Allow a Lookup, Getattr, GetFH, Secinfo on an
1180 * non-exported directory if
1181 * nfs_rootfhset. Do I need to allow any other Ops?
1182 * (You can only have a non-exported vpnes if
1183 * nfs_rootfhset is true. See nfsd_fhtovp())
1184 * Allow AUTH_SYS to be used for file systems
1185 * exported GSS only for certain Ops, to allow
1186 * clients to do mounts more easily.
1188 if (nfsv4_opflag[op].needscfh && vp) {
1189 if (!NFSVNO_EXPORTED(&vpnes) &&
1190 op != NFSV4OP_LOOKUP &&
1191 op != NFSV4OP_GETATTR &&
1192 op != NFSV4OP_GETFH &&
1193 op != NFSV4OP_ACCESS &&
1194 op != NFSV4OP_READLINK &&
1195 op != NFSV4OP_SECINFO &&
1196 op != NFSV4OP_SECINFONONAME)
1197 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1198 if (nd->nd_repstat) {
1199 if (op == NFSV4OP_SETATTR) {
1201 * Setattr reply requires a bitmap
1202 * even for errors like these.
1204 NFSM_BUILD(tl, u_int32_t *,
1213 * Save the current positions in the mbuf lists so
1214 * that a rollback to this location can be done upon a
1215 * redo due to a ERELOOKUP return for a operation.
1219 bextpg = nd->nd_bextpg;
1220 bextpgsiz = nd->nd_bextpgsiz;
1225 if (nfsv4_opflag[op].retfh == 1) {
1227 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1230 if (NFSVNO_EXPORTED(&vpnes) && (op == NFSV4OP_LOOKUP ||
1231 op == NFSV4OP_LOOKUPP || (op == NFSV4OP_OPEN &&
1232 vp->v_type == VDIR))) {
1233 /* Check for wrong security. */
1234 rstat = nfsvno_testexp(nd, &vpnes);
1236 nd->nd_repstat = rstat;
1241 if (nfsv4_opflag[op].modifyfs)
1242 vn_start_write(vp, &temp_mp, V_WAIT);
1243 error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
1244 &nvp, (fhandle_t *)fh.nfsrvfh_data, &vpnes);
1245 if (!error && !nd->nd_repstat) {
1246 if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) {
1247 new_mp = nvp->v_mount;
1248 if (fsidcmp(&cur_fsid, &new_mp->mnt_stat.f_fsid) != 0) {
1249 /* crossed a server mount point */
1250 nd->nd_repstat = nfsvno_checkexp(new_mp,
1251 nd->nd_nam, &nes, &credanon);
1252 if (!nd->nd_repstat)
1253 nd->nd_repstat = nfsd_excred(nd,
1254 &nes, credanon, true);
1255 if (credanon != NULL)
1257 if (!nd->nd_repstat) {
1259 cur_fsid = new_mp->mnt_stat.f_fsid;
1262 /* Lookup ops return a locked vnode */
1265 if (!nd->nd_repstat) {
1271 if (nfsv4_opflag[op].modifyfs)
1272 vn_finished_write(temp_mp);
1273 } else if (nfsv4_opflag[op].retfh == 2) {
1274 if (vp == NULL || savevp == NULL) {
1275 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1277 } else if (fsidcmp(&cur_fsid, &save_fsid) != 0) {
1278 nd->nd_repstat = NFSERR_XDEV;
1281 if (nfsv4_opflag[op].modifyfs)
1282 vn_start_write(savevp, &temp_mp, V_WAIT);
1283 if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
1286 error = (*(nfsrv4_ops2[op]))(nd, isdgram,
1287 savevp, vp, &savevpnes, &vpnes);
1289 nd->nd_repstat = NFSERR_PERM;
1290 if (nfsv4_opflag[op].modifyfs)
1291 vn_finished_write(temp_mp);
1293 if (nfsv4_opflag[op].retfh != 0)
1294 panic("nfsrvd_compound");
1295 if (nfsv4_opflag[op].needscfh) {
1297 lktype = nfsv4_opflag[op].lktype;
1298 if (nfsv4_opflag[op].modifyfs) {
1299 vn_start_write(vp, &temp_mp,
1301 if (op == NFSV4OP_WRITE &&
1302 MNT_SHARED_WRITES(temp_mp))
1305 if (NFSVOPLOCK(vp, lktype) == 0)
1308 nd->nd_repstat = NFSERR_PERM;
1310 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1311 if (op == NFSV4OP_SETATTR) {
1313 * Setattr reply requires a
1314 * bitmap even for errors like
1317 NFSM_BUILD(tl, u_int32_t *,
1323 if (nd->nd_repstat == 0) {
1324 error = (*(nfsrv4_ops0[op]))(nd,
1325 isdgram, vp, &vpnes);
1326 if ((op == NFSV4OP_SECINFO ||
1327 op == NFSV4OP_SECINFONONAME) &&
1328 error == 0 && nd->nd_repstat == 0) {
1330 * Secinfo and Secinfo_no_name
1331 * consume the current FH.
1337 if (nfsv4_opflag[op].modifyfs)
1338 vn_finished_write(temp_mp);
1340 error = (*(nfsrv4_ops0[op]))(nd, isdgram,
1346 if (error == EBADRPC || error == NFSERR_BADXDR) {
1347 nd->nd_repstat = NFSERR_BADXDR;
1349 nd->nd_repstat = error;
1350 printf("nfsv4 comperr0=%d\n", error);
1355 if (nd->nd_repstat == ERELOOKUP) {
1357 * Roll back to the beginning of the operation
1364 * Trim off the bogus reply for this operation
1365 * and redo the operation.
1367 nfsm_trimtrailing(nd, mb, bpos, bextpg, bextpgsiz);
1369 nd->nd_flag |= ND_ERELOOKUP;
1372 nd->nd_flag &= ~ND_ERELOOKUP;
1374 if (statsinprog != 0) {
1375 nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1376 /*then*/ &start_time);
1381 if (nd->nd_repstat) {
1382 *repp = nfsd_errmap(nd);
1385 *repp = 0; /* NFS4_OK */
1389 if (statsinprog != 0) {
1390 nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1391 /*then*/ &start_time);
1395 if (error == EBADRPC || error == NFSERR_BADXDR)
1396 nd->nd_repstat = NFSERR_BADXDR;
1398 printf("nfsv4 comperr1=%d\n", error);
1401 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1405 *retopsp = txdr_unsigned(retops);
1411 if (savecred != NULL)
1412 nd->nd_cred = savecred;
1413 if (rootcred != NULL)
1415 NFSLOCKV4ROOTMUTEX();
1416 nfsv4_relref(&nfsv4rootfs_lock);
1417 NFSUNLOCKV4ROOTMUTEX();
1419 NFSEXITCODE2(0, nd);
1422 /* Create a credential for "root". */
1423 static struct ucred *
1424 nfsrv_createrootcred(void)
1430 cr->cr_uid = cr->cr_ruid = cr->cr_svuid = UID_ROOT;
1432 crsetgroups(cr, 1, &grp);
1433 cr->cr_rgid = cr->cr_svgid = cr->cr_groups[0];
1434 cr->cr_prison = curthread->td_ucred->cr_prison;
1435 prison_hold(cr->cr_prison);
1437 mac_cred_associate_nfsd(cr);