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.
44 #include <fs/nfs/nfsport.h>
46 extern struct nfsstatsv1 nfsstatsv1;
47 extern struct nfsrvfh nfs_pubfh, nfs_rootfh;
48 extern int nfs_pubfhset, nfs_rootfhset;
49 extern struct nfsv4lock nfsv4rootfs_lock;
50 extern struct nfsrv_stablefirst nfsrv_stablefirst;
51 extern struct nfsclienthashhead *nfsclienthash;
52 extern int nfsrv_clienthashsize;
53 extern int nfsrc_floodlevel, nfsrc_tcpsavedreplies;
54 extern int nfsd_debuglevel;
55 extern int nfsrv_layouthighwater;
56 extern volatile int nfsrv_layoutcnt;
60 int (*nfsrv3_procs0[NFS_V3NPROCS])(struct nfsrv_descript *,
61 int, vnode_t , NFSPROC_T *, struct nfsexstuff *) = {
62 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
65 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
71 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
72 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
73 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
76 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
77 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
86 int (*nfsrv3_procs1[NFS_V3NPROCS])(struct nfsrv_descript *,
87 int, vnode_t , vnode_t *, fhandle_t *,
88 NFSPROC_T *, struct nfsexstuff *) = {
89 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
90 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
91 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
93 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
94 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
95 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
96 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
97 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
101 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
102 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
103 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
104 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
105 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
106 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
107 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
108 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
109 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
110 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
113 int (*nfsrv3_procs2[NFS_V3NPROCS])(struct nfsrv_descript *,
114 int, vnode_t , vnode_t , NFSPROC_T *,
115 struct nfsexstuff *, struct nfsexstuff *) = {
116 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
117 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
118 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
119 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
120 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
121 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
122 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
123 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
124 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
125 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
126 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
127 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
128 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
129 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
132 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
133 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
134 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
135 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
136 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
137 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
140 int (*nfsrv4_ops0[NFSV41_NOPS])(struct nfsrv_descript *,
141 int, vnode_t , NFSPROC_T *, struct nfsexstuff *) = {
142 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
143 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
144 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
148 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
153 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
157 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
158 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
160 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
161 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
163 nfsrvd_opendowngrade,
164 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
165 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
166 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
171 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
173 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
174 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
178 nfsrvd_setclientidcfrm,
181 nfsrvd_releaselckown,
185 nfsrvd_createsession,
186 nfsrvd_destroysession,
199 nfsrvd_destroyclientid,
200 nfsrvd_reclaimcomplete,
203 int (*nfsrv4_ops1[NFSV41_NOPS])(struct nfsrv_descript *,
204 int, vnode_t , vnode_t *, fhandle_t *,
205 NFSPROC_T *, struct nfsexstuff *) = {
206 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
207 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
208 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
209 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
210 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
211 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
213 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
214 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
215 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
216 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
217 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
218 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
219 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
220 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
223 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
226 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
227 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
228 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
229 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
230 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
231 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
232 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
233 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
234 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
235 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
236 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
237 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
238 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
239 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
240 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
241 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
242 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
243 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
244 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
245 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
246 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
247 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
248 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
249 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
250 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
251 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
252 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
253 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
254 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
255 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
256 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
257 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
258 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
259 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
260 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
261 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
262 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
263 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
264 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
267 int (*nfsrv4_ops2[NFSV41_NOPS])(struct nfsrv_descript *,
268 int, vnode_t , vnode_t , NFSPROC_T *,
269 struct nfsexstuff *, struct nfsexstuff *) = {
270 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
271 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
272 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
273 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
274 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
275 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
276 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
277 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
278 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
279 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
280 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
282 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
283 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
284 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
285 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
286 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
287 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
288 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
289 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
290 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
291 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
292 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
293 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
294 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
295 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
296 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
297 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
298 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
300 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
301 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
302 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
303 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
304 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
305 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
306 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
307 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
308 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
309 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
310 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
311 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
312 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
313 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
314 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
315 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
316 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
317 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
318 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
319 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
320 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
321 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
322 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
323 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
324 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
325 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
326 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
327 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
328 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
330 #endif /* !APPLEKEXT */
333 * Static array that defines which nfs rpc's are nonidempotent
335 static int nfsrv_nonidempotent[NFS_V3NPROCS] = {
361 * This static array indicates whether or not the RPC modifies the
364 int nfsrv_writerpc[NFS_NPROCS] = { 0, 0, 1, 0, 0, 0, 0,
365 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
366 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
368 /* local functions */
369 static void nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
370 u_char *tag, int taglen, u_int32_t minorvers, NFSPROC_T *p);
374 * This static array indicates which server procedures require the extra
375 * arguments to return the current file handle for V2, 3.
377 static int nfs_retfh[NFS_V3NPROCS] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1,
378 1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0 };
380 extern struct nfsv4_opflag nfsv4_opflag[NFSV41_NOPS];
382 static int nfsv3to4op[NFS_V3NPROCS] = {
407 static struct mtx nfsrvd_statmtx;
408 MTX_SYSINIT(nfsst, &nfsrvd_statmtx, "NFSstat", MTX_DEF);
411 nfsrvd_statstart(int op, struct bintime *now)
413 if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
414 printf("%s: op %d invalid\n", __func__, op);
418 mtx_lock(&nfsrvd_statmtx);
419 if (nfsstatsv1.srvstartcnt == nfsstatsv1.srvdonecnt) {
421 nfsstatsv1.busyfrom = *now;
423 binuptime(&nfsstatsv1.busyfrom);
426 nfsstatsv1.srvrpccnt[op]++;
427 nfsstatsv1.srvstartcnt++;
428 mtx_unlock(&nfsrvd_statmtx);
433 nfsrvd_statend(int op, uint64_t bytes, struct bintime *now,
434 struct bintime *then)
436 struct bintime dt, lnow;
438 if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
439 printf("%s: op %d invalid\n", __func__, op);
448 mtx_lock(&nfsrvd_statmtx);
450 nfsstatsv1.srvbytes[op] += bytes;
451 nfsstatsv1.srvops[op]++;
455 bintime_sub(&dt, then);
456 bintime_add(&nfsstatsv1.srvduration[op], &dt);
460 bintime_sub(&dt, &nfsstatsv1.busyfrom);
461 bintime_add(&nfsstatsv1.busytime, &dt);
462 nfsstatsv1.busyfrom = *now;
464 nfsstatsv1.srvdonecnt++;
466 mtx_unlock(&nfsrvd_statmtx);
470 * Do an RPC. Basically, get the file handles translated to vnode pointers
471 * and then call the appropriate server routine. The server routines are
472 * split into groups, based on whether they use a file handle or file
473 * handle plus name or ...
474 * The NFS V4 Compound RPC is performed separately by nfsrvd_compound().
477 nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, u_char *tag, int taglen,
478 u_int32_t minorvers, NFSPROC_T *p)
480 int error = 0, lktype;
484 struct nfsexstuff nes;
487 * Get a locked vnode for the first file handle
489 if (!(nd->nd_flag & ND_NFSV4)) {
490 KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc"));
492 * For NFSv3, if the malloc/mget allocation is near limits,
493 * return NFSERR_DELAY.
495 if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) {
496 nd->nd_repstat = NFSERR_DELAY;
499 error = nfsrv_mtofh(nd, &fh);
501 if (error != EBADRPC)
502 printf("nfs dorpc err1=%d\n", error);
503 nd->nd_repstat = NFSERR_GARBAGE;
506 if (nd->nd_procnum == NFSPROC_READ ||
507 nd->nd_procnum == NFSPROC_WRITE ||
508 nd->nd_procnum == NFSPROC_READDIR ||
509 nd->nd_procnum == NFSPROC_READDIRPLUS ||
510 nd->nd_procnum == NFSPROC_READLINK ||
511 nd->nd_procnum == NFSPROC_GETATTR ||
512 nd->nd_procnum == NFSPROC_ACCESS ||
513 nd->nd_procnum == NFSPROC_FSSTAT ||
514 nd->nd_procnum == NFSPROC_FSINFO)
517 lktype = LK_EXCLUSIVE;
518 if (nd->nd_flag & ND_PUBLOOKUP)
519 nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes,
520 &mp, nfsrv_writerpc[nd->nd_procnum], p);
522 nfsd_fhtovp(nd, &fh, lktype, &vp, &nes,
523 &mp, nfsrv_writerpc[nd->nd_procnum], p);
524 if (nd->nd_repstat == NFSERR_PROGNOTV4)
530 * For V2 and 3, set the ND_SAVEREPLY flag for the recent request
531 * cache, as required.
532 * For V4, nfsrvd_compound() does this.
534 if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum])
535 nd->nd_flag |= ND_SAVEREPLY;
539 * If nd_repstat is non-zero, just fill in the reply status
540 * to complete the RPC reply for V2. Otherwise, you must do
543 if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) {
544 *nd->nd_errp = nfsd_errmap(nd);
545 nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], /*now*/ NULL);
546 nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
547 /*now*/ NULL, /*then*/ NULL);
548 if (mp != NULL && nfsrv_writerpc[nd->nd_procnum] != 0)
549 vn_finished_write(mp);
554 * Now the procedure can be performed. For V4, nfsrvd_compound()
555 * works through the sub-rpcs, otherwise just call the procedure.
556 * The procedures are in three groups with different arguments.
557 * The group is indicated by the value in nfs_retfh[].
559 if (nd->nd_flag & ND_NFSV4) {
560 nfsrvd_compound(nd, isdgram, tag, taglen, minorvers, p);
562 struct bintime start_time;
564 binuptime(&start_time);
565 nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], &start_time);
567 if (nfs_retfh[nd->nd_procnum] == 1) {
570 error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram,
571 vp, NULL, (fhandle_t *)fh.nfsrvfh_data, p, &nes);
572 } else if (nfs_retfh[nd->nd_procnum] == 2) {
573 error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram,
574 vp, NULL, p, &nes, NULL);
576 error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
579 if (mp != NULL && nfsrv_writerpc[nd->nd_procnum] != 0)
580 vn_finished_write(mp);
582 nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
583 /*now*/ NULL, /*then*/ &start_time);
586 if (error != EBADRPC)
587 printf("nfs dorpc err2=%d\n", error);
588 nd->nd_repstat = NFSERR_GARBAGE;
590 *nd->nd_errp = nfsd_errmap(nd);
593 * Don't cache certain reply status values.
595 if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) &&
596 (nd->nd_repstat == NFSERR_GARBAGE ||
597 nd->nd_repstat == NFSERR_BADXDR ||
598 nd->nd_repstat == NFSERR_MOVED ||
599 nd->nd_repstat == NFSERR_DELAY ||
600 nd->nd_repstat == NFSERR_BADSEQID ||
601 nd->nd_repstat == NFSERR_RESOURCE ||
602 nd->nd_repstat == NFSERR_SERVERFAULT ||
603 nd->nd_repstat == NFSERR_STALECLIENTID ||
604 nd->nd_repstat == NFSERR_STALESTATEID ||
605 nd->nd_repstat == NFSERR_OLDSTATEID ||
606 nd->nd_repstat == NFSERR_BADSTATEID ||
607 nd->nd_repstat == NFSERR_GRACE ||
608 nd->nd_repstat == NFSERR_NOGRACE))
609 nd->nd_flag &= ~ND_SAVEREPLY;
616 * Breaks down a compound RPC request and calls the server routines for
618 * Some suboperations are performed directly here to simplify file handle<-->
619 * vnode pointer handling.
622 nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,
623 int taglen, u_int32_t minorvers, NFSPROC_T *p)
625 int i, lktype, op, op0 = 0, statsinprog = 0;
627 struct nfsclient *clp, *nclp;
628 int numops, error = 0, igotlock;
629 u_int32_t retops = 0, *retopsp = NULL, *repp;
630 vnode_t vp, nvp, savevp;
632 mount_t new_mp, temp_mp = NULL;
633 struct ucred *credanon;
634 struct nfsexstuff nes, vpnes, savevpnes;
635 fsid_t cur_fsid, save_fsid;
636 static u_int64_t compref = 0;
637 struct bintime start_time;
639 NFSVNO_EXINIT(&vpnes);
640 NFSVNO_EXINIT(&savevpnes);
642 * Put the seq# of the current compound RPC in nfsrv_descript.
643 * (This is used by nfsrv_checkgetattr(), to see if the write
644 * delegation was created by the same compound RPC as the one
645 * with that Getattr in it.)
646 * Don't worry about the 64bit number wrapping around. It ain't
647 * gonna happen before this server gets shut down/rebooted.
649 nd->nd_compref = compref++;
652 * Check for and optionally get a lock on the root. This lock means that
653 * no nfsd will be fiddling with the V4 file system and state stuff. It
654 * is required when the V4 root is being changed, the stable storage
655 * restart file is being updated, or callbacks are being done.
656 * When any of the nfsd are processing an NFSv4 compound RPC, they must
657 * either hold a reference count (nfs_usecnt) or the lock. When
658 * nfsrv_unlock() is called to release the lock, it can optionally
659 * also get a reference count, which saves the need for a call to
660 * nfsrv_getref() after nfsrv_unlock().
663 * First, check to see if we need to wait for an update lock.
666 NFSLOCKV4ROOTMUTEX();
667 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK)
668 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
669 NFSV4ROOTLOCKMUTEXPTR, NULL);
671 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
672 NFSV4ROOTLOCKMUTEXPTR, NULL);
673 NFSUNLOCKV4ROOTMUTEX();
676 * If I got the lock, I can update the stable storage file.
677 * Done when the grace period is over or a client has long
680 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK;
681 if ((nfsrv_stablefirst.nsf_flags &
682 (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
683 nfsrv_updatestable(p);
686 * If at least one client has long since expired, search
687 * the client list for them, write a REVOKE record on the
688 * stable storage file and then remove them from the client
691 if (nfsrv_stablefirst.nsf_flags & NFSNSF_EXPIREDCLIENT) {
692 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_EXPIREDCLIENT;
693 for (i = 0; i < nfsrv_clienthashsize; i++) {
694 LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash,
696 if (clp->lc_flags & LCL_EXPIREIT) {
697 if (!LIST_EMPTY(&clp->lc_open) ||
698 !LIST_EMPTY(&clp->lc_deleg))
699 nfsrv_writestable(clp->lc_id,
700 clp->lc_idlen, NFSNST_REVOKE, p);
701 nfsrv_cleanclient(clp, p);
702 nfsrv_freedeleglist(&clp->lc_deleg);
703 nfsrv_freedeleglist(&clp->lc_olddeleg);
704 LIST_REMOVE(clp, lc_hash);
705 nfsrv_zapclient(clp, p);
710 NFSLOCKV4ROOTMUTEX();
711 nfsv4_unlock(&nfsv4rootfs_lock, 1);
712 NFSUNLOCKV4ROOTMUTEX();
715 * If we didn't get the lock, we need to get a refcnt,
716 * which also checks for and waits for the lock.
718 NFSLOCKV4ROOTMUTEX();
719 nfsv4_getref(&nfsv4rootfs_lock, NULL,
720 NFSV4ROOTLOCKMUTEXPTR, NULL);
721 NFSUNLOCKV4ROOTMUTEX();
725 * If flagged, search for open owners that haven't had any opens
728 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) {
729 nfsrv_throwawayopens(p);
732 /* Do a CBLAYOUTRECALL callback if over the high water mark. */
733 if (nfsrv_layoutcnt > nfsrv_layouthighwater)
734 nfsrv_recalloldlayout(p);
737 save_fsid.val[0] = save_fsid.val[1] = 0;
738 cur_fsid.val[0] = cur_fsid.val[1] = 0;
740 /* If taglen < 0, there was a parsing error in nfsd_getminorvers(). */
746 (void) nfsm_strtom(nd, tag, taglen);
747 NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED);
748 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
749 if (minorvers != NFSV4_MINORVERSION && minorvers != NFSV41_MINORVERSION)
750 nd->nd_repstat = NFSERR_MINORVERMISMATCH;
754 numops = fxdr_unsigned(int, *tl);
756 * Loop around doing the sub ops.
757 * vp - is an unlocked vnode pointer for the CFH
758 * savevp - is an unlocked vnode pointer for the SAVEDFH
759 * (at some future date, it might turn out to be more appropriate
760 * to keep the file handles instead of vnode pointers?)
761 * savevpnes and vpnes - are the export flags for the above.
763 for (i = 0; i < numops; i++) {
764 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
765 NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED);
767 op = fxdr_unsigned(int, *tl);
768 NFSD_DEBUG(4, "op=%d\n", op);
770 binuptime(&start_time);
771 nfsrvd_statstart(op, &start_time);
774 if (op < NFSV4OP_ACCESS ||
775 (op >= NFSV4OP_NOPS && (nd->nd_flag & ND_NFSV41) == 0) ||
776 (op >= NFSV41_NOPS && (nd->nd_flag & ND_NFSV41) != 0)) {
777 nd->nd_repstat = NFSERR_OPILLEGAL;
778 *repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL);
779 *repp = nfsd_errmap(nd);
788 nd->nd_flag |= ND_LASTOP;
791 * Check for a referral on the current FH and, if so, return
792 * NFSERR_MOVED for all ops that allow it, except Getattr.
794 if (vp != NULL && op != NFSV4OP_GETATTR &&
795 nfsv4root_getreferral(vp, NULL, 0) != NULL &&
796 nfsrv_errmoved(op)) {
797 nd->nd_repstat = NFSERR_MOVED;
798 *repp = nfsd_errmap(nd);
804 * For NFSv4.1, check for a Sequence Operation being first
805 * or one of the other allowed operations by itself.
807 if ((nd->nd_flag & ND_NFSV41) != 0) {
808 if (i != 0 && op == NFSV4OP_SEQUENCE)
809 nd->nd_repstat = NFSERR_SEQUENCEPOS;
810 else if (i == 0 && op != NFSV4OP_SEQUENCE &&
811 op != NFSV4OP_EXCHANGEID &&
812 op != NFSV4OP_CREATESESSION &&
813 op != NFSV4OP_BINDCONNTOSESS &&
814 op != NFSV4OP_DESTROYCLIENTID &&
815 op != NFSV4OP_DESTROYSESSION)
816 nd->nd_repstat = NFSERR_OPNOTINSESS;
817 else if (i != 0 && op0 != NFSV4OP_SEQUENCE)
818 nd->nd_repstat = NFSERR_NOTONLYOP;
819 if (nd->nd_repstat != 0) {
820 *repp = nfsd_errmap(nd);
828 * If over flood level, reply NFSERR_RESOURCE, if at the first
829 * Op. (Since a client recovery from NFSERR_RESOURCE can get
830 * really nasty for certain Op sequences, I'll play it safe
831 * and only return the error at the beginning.) The cache
832 * will still function over flood level, but uses lots of
834 * If nfsrv_mallocmget_limit() returns True, the system is near
835 * to its limit for memory that malloc()/mget() can allocate.
837 if (i == 0 && (nd->nd_rp == NULL ||
838 nd->nd_rp->rc_refcnt == 0) &&
839 (nfsrv_mallocmget_limit() ||
840 nfsrc_tcpsavedreplies > nfsrc_floodlevel)) {
841 if (nfsrc_tcpsavedreplies > nfsrc_floodlevel)
842 printf("nfsd server cache flooded, try "
843 "increasing vfs.nfsd.tcphighwater\n");
844 nd->nd_repstat = NFSERR_RESOURCE;
845 *repp = nfsd_errmap(nd);
846 if (op == NFSV4OP_SETATTR) {
848 * Setattr replies require a bitmap.
849 * even for errors like these.
851 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
857 if (nfsv4_opflag[op].savereply)
858 nd->nd_flag |= ND_SAVEREPLY;
861 error = nfsrv_mtofh(nd, &fh);
865 nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
867 /* For now, allow this for non-export FHs */
868 if (!nd->nd_repstat) {
872 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
877 case NFSV4OP_PUTPUBFH:
879 nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
882 nd->nd_repstat = NFSERR_NOFILEHANDLE;
883 if (!nd->nd_repstat) {
887 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
892 case NFSV4OP_PUTROOTFH:
894 nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp,
896 if (!nd->nd_repstat) {
900 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
905 nd->nd_repstat = NFSERR_NOFILEHANDLE;
908 if (vp && NFSVNO_EXPORTED(&vpnes)) {
910 /* If vp == savevp, a no-op */
917 save_fsid = cur_fsid;
919 if ((nd->nd_flag & ND_CURSTATEID) != 0) {
920 nd->nd_savedcurstateid =
922 nd->nd_flag |= ND_SAVEDCURSTATEID;
925 nd->nd_repstat = NFSERR_NOFILEHANDLE;
928 case NFSV4OP_RESTOREFH:
931 /* If vp == savevp, a no-op */
937 cur_fsid = save_fsid;
939 if ((nd->nd_flag & ND_SAVEDCURSTATEID) != 0) {
941 nd->nd_savedcurstateid;
942 nd->nd_flag |= ND_CURSTATEID;
945 nd->nd_repstat = NFSERR_RESTOREFH;
950 * Allow a Lookup, Getattr, GetFH, Secinfo on an
951 * non-exported directory if
952 * nfs_rootfhset. Do I need to allow any other Ops?
953 * (You can only have a non-exported vpnes if
954 * nfs_rootfhset is true. See nfsd_fhtovp())
955 * Allow AUTH_SYS to be used for file systems
956 * exported GSS only for certain Ops, to allow
957 * clients to do mounts more easily.
959 if (nfsv4_opflag[op].needscfh && vp) {
960 if (!NFSVNO_EXPORTED(&vpnes) &&
961 op != NFSV4OP_LOOKUP &&
962 op != NFSV4OP_GETATTR &&
963 op != NFSV4OP_GETFH &&
964 op != NFSV4OP_ACCESS &&
965 op != NFSV4OP_READLINK &&
966 op != NFSV4OP_SECINFO)
967 nd->nd_repstat = NFSERR_NOFILEHANDLE;
968 else if (nfsvno_testexp(nd, &vpnes) &&
969 op != NFSV4OP_LOOKUP &&
970 op != NFSV4OP_GETFH &&
971 op != NFSV4OP_GETATTR &&
972 op != NFSV4OP_SECINFO)
973 nd->nd_repstat = NFSERR_WRONGSEC;
974 if (nd->nd_repstat) {
975 if (op == NFSV4OP_SETATTR) {
977 * Setattr reply requires a bitmap
978 * even for errors like these.
980 NFSM_BUILD(tl, u_int32_t *,
987 if (nfsv4_opflag[op].retfh == 1) {
989 nd->nd_repstat = NFSERR_NOFILEHANDLE;
993 if (nfsv4_opflag[op].modifyfs)
994 vn_start_write(vp, &temp_mp, V_WAIT);
995 error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
996 &nvp, (fhandle_t *)fh.nfsrvfh_data, p, &vpnes);
997 if (!error && !nd->nd_repstat) {
998 if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) {
999 new_mp = nvp->v_mount;
1000 if (cur_fsid.val[0] !=
1001 new_mp->mnt_stat.f_fsid.val[0] ||
1003 new_mp->mnt_stat.f_fsid.val[1]) {
1004 /* crossed a server mount point */
1005 nd->nd_repstat = nfsvno_checkexp(new_mp,
1006 nd->nd_nam, &nes, &credanon);
1007 if (!nd->nd_repstat)
1008 nd->nd_repstat = nfsd_excred(nd,
1010 if (credanon != NULL)
1012 if (!nd->nd_repstat) {
1014 cur_fsid = new_mp->mnt_stat.f_fsid;
1017 /* Lookup ops return a locked vnode */
1018 NFSVOPUNLOCK(nvp, 0);
1020 if (!nd->nd_repstat) {
1026 if (nfsv4_opflag[op].modifyfs)
1027 vn_finished_write(temp_mp);
1028 } else if (nfsv4_opflag[op].retfh == 2) {
1029 if (vp == NULL || savevp == NULL) {
1030 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1032 } else if (cur_fsid.val[0] != save_fsid.val[0] ||
1033 cur_fsid.val[1] != save_fsid.val[1]) {
1034 nd->nd_repstat = NFSERR_XDEV;
1037 if (nfsv4_opflag[op].modifyfs)
1038 vn_start_write(savevp, &temp_mp, V_WAIT);
1039 if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
1042 error = (*(nfsrv4_ops2[op]))(nd, isdgram,
1043 savevp, vp, p, &savevpnes, &vpnes);
1045 nd->nd_repstat = NFSERR_PERM;
1046 if (nfsv4_opflag[op].modifyfs)
1047 vn_finished_write(temp_mp);
1049 if (nfsv4_opflag[op].retfh != 0)
1050 panic("nfsrvd_compound");
1051 if (nfsv4_opflag[op].needscfh) {
1053 lktype = nfsv4_opflag[op].lktype;
1054 if (nfsv4_opflag[op].modifyfs) {
1055 vn_start_write(vp, &temp_mp,
1057 if (op == NFSV4OP_WRITE &&
1058 MNT_SHARED_WRITES(temp_mp))
1061 if (NFSVOPLOCK(vp, lktype) == 0)
1064 nd->nd_repstat = NFSERR_PERM;
1066 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1067 if (op == NFSV4OP_SETATTR) {
1069 * Setattr reply requires a
1070 * bitmap even for errors like
1073 NFSM_BUILD(tl, u_int32_t *,
1079 if (nd->nd_repstat == 0)
1080 error = (*(nfsrv4_ops0[op]))(nd,
1081 isdgram, vp, p, &vpnes);
1082 if (nfsv4_opflag[op].modifyfs)
1083 vn_finished_write(temp_mp);
1085 error = (*(nfsrv4_ops0[op]))(nd, isdgram,
1091 if (error == EBADRPC || error == NFSERR_BADXDR) {
1092 nd->nd_repstat = NFSERR_BADXDR;
1094 nd->nd_repstat = error;
1095 printf("nfsv4 comperr0=%d\n", error);
1100 if (statsinprog != 0) {
1101 nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1102 /*then*/ &start_time);
1107 if (nd->nd_repstat) {
1108 *repp = nfsd_errmap(nd);
1111 *repp = 0; /* NFS4_OK */
1115 if (statsinprog != 0) {
1116 nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1117 /*then*/ &start_time);
1121 if (error == EBADRPC || error == NFSERR_BADXDR)
1122 nd->nd_repstat = NFSERR_BADXDR;
1124 printf("nfsv4 comperr1=%d\n", error);
1127 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1131 *retopsp = txdr_unsigned(retops);
1137 NFSLOCKV4ROOTMUTEX();
1138 nfsv4_relref(&nfsv4rootfs_lock);
1139 NFSUNLOCKV4ROOTMUTEX();
1141 NFSEXITCODE2(0, nd);