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;
58 int (*nfsrv3_procs0[NFS_V3NPROCS])(struct nfsrv_descript *,
59 int, vnode_t , NFSPROC_T *, struct nfsexstuff *) = {
60 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
63 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
69 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
70 (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,
74 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
75 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
84 int (*nfsrv3_procs1[NFS_V3NPROCS])(struct nfsrv_descript *,
85 int, vnode_t , vnode_t *, fhandle_t *,
86 NFSPROC_T *, struct nfsexstuff *) = {
87 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
88 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
89 (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,
92 (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,
99 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
100 (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,
111 int (*nfsrv3_procs2[NFS_V3NPROCS])(struct nfsrv_descript *,
112 int, vnode_t , vnode_t , NFSPROC_T *,
113 struct nfsexstuff *, struct nfsexstuff *) = {
114 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
115 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
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,
130 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
131 (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,
138 int (*nfsrv4_ops0[NFSV41_NOPS])(struct nfsrv_descript *,
139 int, vnode_t , NFSPROC_T *, struct nfsexstuff *) = {
140 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
141 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
142 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
146 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
151 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
155 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
156 (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,
159 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
161 nfsrvd_opendowngrade,
162 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
163 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
164 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
169 (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,
172 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
176 nfsrvd_setclientidcfrm,
179 nfsrvd_releaselckown,
183 nfsrvd_createsession,
184 nfsrvd_destroysession,
197 nfsrvd_destroyclientid,
198 nfsrvd_reclaimcomplete,
201 int (*nfsrv4_ops1[NFSV41_NOPS])(struct nfsrv_descript *,
202 int, vnode_t , vnode_t *, fhandle_t *,
203 NFSPROC_T *, struct nfsexstuff *) = {
204 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
205 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
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,
211 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
212 (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,
221 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
224 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
225 (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,
265 int (*nfsrv4_ops2[NFSV41_NOPS])(struct nfsrv_descript *,
266 int, vnode_t , vnode_t , NFSPROC_T *,
267 struct nfsexstuff *, struct nfsexstuff *) = {
268 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
269 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
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,
280 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
281 (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,
298 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
299 (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,
328 #endif /* !APPLEKEXT */
331 * Static array that defines which nfs rpc's are nonidempotent
333 static int nfsrv_nonidempotent[NFS_V3NPROCS] = {
359 * This static array indicates whether or not the RPC modifies the
362 static int nfs_writerpc[NFS_NPROCS] = { 0, 0, 1, 0, 0, 0, 0,
363 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
364 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
366 /* local functions */
367 static void nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
368 u_char *tag, int taglen, u_int32_t minorvers, NFSPROC_T *p);
372 * This static array indicates which server procedures require the extra
373 * arguments to return the current file handle for V2, 3.
375 static int nfs_retfh[NFS_V3NPROCS] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1,
376 1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0 };
378 extern struct nfsv4_opflag nfsv4_opflag[NFSV41_NOPS];
380 static int nfsv3to4op[NFS_V3NPROCS] = {
405 static struct mtx nfsrvd_statmtx;
406 MTX_SYSINIT(nfsst, &nfsrvd_statmtx, "NFSstat", MTX_DEF);
409 nfsrvd_statstart(int op, struct bintime *now)
411 if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
412 printf("%s: op %d invalid\n", __func__, op);
416 mtx_lock(&nfsrvd_statmtx);
417 if (nfsstatsv1.srvstartcnt == nfsstatsv1.srvdonecnt) {
419 nfsstatsv1.busyfrom = *now;
421 binuptime(&nfsstatsv1.busyfrom);
424 nfsstatsv1.srvrpccnt[op]++;
425 nfsstatsv1.srvstartcnt++;
426 mtx_unlock(&nfsrvd_statmtx);
431 nfsrvd_statend(int op, uint64_t bytes, struct bintime *now,
432 struct bintime *then)
434 struct bintime dt, lnow;
436 if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
437 printf("%s: op %d invalid\n", __func__, op);
446 mtx_lock(&nfsrvd_statmtx);
448 nfsstatsv1.srvbytes[op] += bytes;
449 nfsstatsv1.srvops[op]++;
453 bintime_sub(&dt, then);
454 bintime_add(&nfsstatsv1.srvduration[op], &dt);
458 bintime_sub(&dt, &nfsstatsv1.busyfrom);
459 bintime_add(&nfsstatsv1.busytime, &dt);
460 nfsstatsv1.busyfrom = *now;
462 nfsstatsv1.srvdonecnt++;
464 mtx_unlock(&nfsrvd_statmtx);
468 * Do an RPC. Basically, get the file handles translated to vnode pointers
469 * and then call the appropriate server routine. The server routines are
470 * split into groups, based on whether they use a file handle or file
471 * handle plus name or ...
472 * The NFS V4 Compound RPC is performed separately by nfsrvd_compound().
475 nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, u_char *tag, int taglen,
476 u_int32_t minorvers, NFSPROC_T *p)
478 int error = 0, lktype;
482 struct nfsexstuff nes;
485 * Get a locked vnode for the first file handle
487 if (!(nd->nd_flag & ND_NFSV4)) {
488 KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc"));
490 * For NFSv3, if the malloc/mget allocation is near limits,
491 * return NFSERR_DELAY.
493 if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) {
494 nd->nd_repstat = NFSERR_DELAY;
497 error = nfsrv_mtofh(nd, &fh);
499 if (error != EBADRPC)
500 printf("nfs dorpc err1=%d\n", error);
501 nd->nd_repstat = NFSERR_GARBAGE;
504 if (nd->nd_procnum == NFSPROC_READ ||
505 nd->nd_procnum == NFSPROC_WRITE ||
506 nd->nd_procnum == NFSPROC_READDIR ||
507 nd->nd_procnum == NFSPROC_READDIRPLUS ||
508 nd->nd_procnum == NFSPROC_READLINK ||
509 nd->nd_procnum == NFSPROC_GETATTR ||
510 nd->nd_procnum == NFSPROC_ACCESS ||
511 nd->nd_procnum == NFSPROC_FSSTAT ||
512 nd->nd_procnum == NFSPROC_FSINFO)
515 lktype = LK_EXCLUSIVE;
516 if (nd->nd_flag & ND_PUBLOOKUP)
517 nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes,
518 &mp, nfs_writerpc[nd->nd_procnum], p);
520 nfsd_fhtovp(nd, &fh, lktype, &vp, &nes,
521 &mp, nfs_writerpc[nd->nd_procnum], p);
522 if (nd->nd_repstat == NFSERR_PROGNOTV4)
528 * For V2 and 3, set the ND_SAVEREPLY flag for the recent request
529 * cache, as required.
530 * For V4, nfsrvd_compound() does this.
532 if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum])
533 nd->nd_flag |= ND_SAVEREPLY;
537 * If nd_repstat is non-zero, just fill in the reply status
538 * to complete the RPC reply for V2. Otherwise, you must do
541 if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) {
542 *nd->nd_errp = nfsd_errmap(nd);
543 nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], /*now*/ NULL);
544 nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
545 /*now*/ NULL, /*then*/ NULL);
546 if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0)
547 vn_finished_write(mp);
552 * Now the procedure can be performed. For V4, nfsrvd_compound()
553 * works through the sub-rpcs, otherwise just call the procedure.
554 * The procedures are in three groups with different arguments.
555 * The group is indicated by the value in nfs_retfh[].
557 if (nd->nd_flag & ND_NFSV4) {
558 nfsrvd_compound(nd, isdgram, tag, taglen, minorvers, p);
560 struct bintime start_time;
562 binuptime(&start_time);
563 nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], &start_time);
565 if (nfs_retfh[nd->nd_procnum] == 1) {
568 error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram,
569 vp, NULL, (fhandle_t *)fh.nfsrvfh_data, p, &nes);
570 } else if (nfs_retfh[nd->nd_procnum] == 2) {
571 error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram,
572 vp, NULL, p, &nes, NULL);
574 error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
577 if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0)
578 vn_finished_write(mp);
580 nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
581 /*now*/ NULL, /*then*/ &start_time);
584 if (error != EBADRPC)
585 printf("nfs dorpc err2=%d\n", error);
586 nd->nd_repstat = NFSERR_GARBAGE;
588 *nd->nd_errp = nfsd_errmap(nd);
591 * Don't cache certain reply status values.
593 if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) &&
594 (nd->nd_repstat == NFSERR_GARBAGE ||
595 nd->nd_repstat == NFSERR_BADXDR ||
596 nd->nd_repstat == NFSERR_MOVED ||
597 nd->nd_repstat == NFSERR_DELAY ||
598 nd->nd_repstat == NFSERR_BADSEQID ||
599 nd->nd_repstat == NFSERR_RESOURCE ||
600 nd->nd_repstat == NFSERR_SERVERFAULT ||
601 nd->nd_repstat == NFSERR_STALECLIENTID ||
602 nd->nd_repstat == NFSERR_STALESTATEID ||
603 nd->nd_repstat == NFSERR_OLDSTATEID ||
604 nd->nd_repstat == NFSERR_BADSTATEID ||
605 nd->nd_repstat == NFSERR_GRACE ||
606 nd->nd_repstat == NFSERR_NOGRACE))
607 nd->nd_flag &= ~ND_SAVEREPLY;
614 * Breaks down a compound RPC request and calls the server routines for
616 * Some suboperations are performed directly here to simplify file handle<-->
617 * vnode pointer handling.
620 nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,
621 int taglen, u_int32_t minorvers, NFSPROC_T *p)
623 int i, lktype, op, op0 = 0, statsinprog = 0;
625 struct nfsclient *clp, *nclp;
626 int numops, error = 0, igotlock;
627 u_int32_t retops = 0, *retopsp = NULL, *repp;
628 vnode_t vp, nvp, savevp;
630 mount_t new_mp, temp_mp = NULL;
631 struct ucred *credanon;
632 struct nfsexstuff nes, vpnes, savevpnes;
633 fsid_t cur_fsid, save_fsid;
634 static u_int64_t compref = 0;
635 struct bintime start_time;
637 NFSVNO_EXINIT(&vpnes);
638 NFSVNO_EXINIT(&savevpnes);
640 * Put the seq# of the current compound RPC in nfsrv_descript.
641 * (This is used by nfsrv_checkgetattr(), to see if the write
642 * delegation was created by the same compound RPC as the one
643 * with that Getattr in it.)
644 * Don't worry about the 64bit number wrapping around. It ain't
645 * gonna happen before this server gets shut down/rebooted.
647 nd->nd_compref = compref++;
650 * Check for and optionally get a lock on the root. This lock means that
651 * no nfsd will be fiddling with the V4 file system and state stuff. It
652 * is required when the V4 root is being changed, the stable storage
653 * restart file is being updated, or callbacks are being done.
654 * When any of the nfsd are processing an NFSv4 compound RPC, they must
655 * either hold a reference count (nfs_usecnt) or the lock. When
656 * nfsrv_unlock() is called to release the lock, it can optionally
657 * also get a reference count, which saves the need for a call to
658 * nfsrv_getref() after nfsrv_unlock().
661 * First, check to see if we need to wait for an update lock.
664 NFSLOCKV4ROOTMUTEX();
665 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK)
666 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
667 NFSV4ROOTLOCKMUTEXPTR, NULL);
669 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
670 NFSV4ROOTLOCKMUTEXPTR, NULL);
671 NFSUNLOCKV4ROOTMUTEX();
674 * If I got the lock, I can update the stable storage file.
675 * Done when the grace period is over or a client has long
678 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK;
679 if ((nfsrv_stablefirst.nsf_flags &
680 (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
681 nfsrv_updatestable(p);
684 * If at least one client has long since expired, search
685 * the client list for them, write a REVOKE record on the
686 * stable storage file and then remove them from the client
689 if (nfsrv_stablefirst.nsf_flags & NFSNSF_EXPIREDCLIENT) {
690 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_EXPIREDCLIENT;
691 for (i = 0; i < nfsrv_clienthashsize; i++) {
692 LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash,
694 if (clp->lc_flags & LCL_EXPIREIT) {
695 if (!LIST_EMPTY(&clp->lc_open) ||
696 !LIST_EMPTY(&clp->lc_deleg))
697 nfsrv_writestable(clp->lc_id,
698 clp->lc_idlen, NFSNST_REVOKE, p);
699 nfsrv_cleanclient(clp, p);
700 nfsrv_freedeleglist(&clp->lc_deleg);
701 nfsrv_freedeleglist(&clp->lc_olddeleg);
702 LIST_REMOVE(clp, lc_hash);
703 nfsrv_zapclient(clp, p);
708 NFSLOCKV4ROOTMUTEX();
709 nfsv4_unlock(&nfsv4rootfs_lock, 1);
710 NFSUNLOCKV4ROOTMUTEX();
713 * If we didn't get the lock, we need to get a refcnt,
714 * which also checks for and waits for the lock.
716 NFSLOCKV4ROOTMUTEX();
717 nfsv4_getref(&nfsv4rootfs_lock, NULL,
718 NFSV4ROOTLOCKMUTEXPTR, NULL);
719 NFSUNLOCKV4ROOTMUTEX();
723 * If flagged, search for open owners that haven't had any opens
726 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) {
727 nfsrv_throwawayopens(p);
731 save_fsid.val[0] = save_fsid.val[1] = 0;
732 cur_fsid.val[0] = cur_fsid.val[1] = 0;
734 /* If taglen < 0, there was a parsing error in nfsd_getminorvers(). */
740 (void) nfsm_strtom(nd, tag, taglen);
741 NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED);
742 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
743 if (minorvers != NFSV4_MINORVERSION && minorvers != NFSV41_MINORVERSION)
744 nd->nd_repstat = NFSERR_MINORVERMISMATCH;
748 numops = fxdr_unsigned(int, *tl);
750 * Loop around doing the sub ops.
751 * vp - is an unlocked vnode pointer for the CFH
752 * savevp - is an unlocked vnode pointer for the SAVEDFH
753 * (at some future date, it might turn out to be more appropriate
754 * to keep the file handles instead of vnode pointers?)
755 * savevpnes and vpnes - are the export flags for the above.
757 for (i = 0; i < numops; i++) {
758 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
759 NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED);
761 op = fxdr_unsigned(int, *tl);
762 NFSD_DEBUG(4, "op=%d\n", op);
764 binuptime(&start_time);
765 nfsrvd_statstart(op, &start_time);
768 if (op < NFSV4OP_ACCESS ||
769 (op >= NFSV4OP_NOPS && (nd->nd_flag & ND_NFSV41) == 0) ||
770 (op >= NFSV41_NOPS && (nd->nd_flag & ND_NFSV41) != 0)) {
771 nd->nd_repstat = NFSERR_OPILLEGAL;
772 *repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL);
773 *repp = nfsd_errmap(nd);
782 nd->nd_flag |= ND_LASTOP;
785 * Check for a referral on the current FH and, if so, return
786 * NFSERR_MOVED for all ops that allow it, except Getattr.
788 if (vp != NULL && op != NFSV4OP_GETATTR &&
789 nfsv4root_getreferral(vp, NULL, 0) != NULL &&
790 nfsrv_errmoved(op)) {
791 nd->nd_repstat = NFSERR_MOVED;
792 *repp = nfsd_errmap(nd);
798 * For NFSv4.1, check for a Sequence Operation being first
799 * or one of the other allowed operations by itself.
801 if ((nd->nd_flag & ND_NFSV41) != 0) {
802 if (i != 0 && op == NFSV4OP_SEQUENCE)
803 nd->nd_repstat = NFSERR_SEQUENCEPOS;
804 else if (i == 0 && op != NFSV4OP_SEQUENCE &&
805 op != NFSV4OP_EXCHANGEID &&
806 op != NFSV4OP_CREATESESSION &&
807 op != NFSV4OP_BINDCONNTOSESS &&
808 op != NFSV4OP_DESTROYCLIENTID &&
809 op != NFSV4OP_DESTROYSESSION)
810 nd->nd_repstat = NFSERR_OPNOTINSESS;
811 else if (i != 0 && op0 != NFSV4OP_SEQUENCE)
812 nd->nd_repstat = NFSERR_NOTONLYOP;
813 if (nd->nd_repstat != 0) {
814 *repp = nfsd_errmap(nd);
822 * If over flood level, reply NFSERR_RESOURCE, if at the first
823 * Op. (Since a client recovery from NFSERR_RESOURCE can get
824 * really nasty for certain Op sequences, I'll play it safe
825 * and only return the error at the beginning.) The cache
826 * will still function over flood level, but uses lots of
828 * If nfsrv_mallocmget_limit() returns True, the system is near
829 * to its limit for memory that malloc()/mget() can allocate.
831 if (i == 0 && (nd->nd_rp == NULL ||
832 nd->nd_rp->rc_refcnt == 0) &&
833 (nfsrv_mallocmget_limit() ||
834 nfsrc_tcpsavedreplies > nfsrc_floodlevel)) {
835 if (nfsrc_tcpsavedreplies > nfsrc_floodlevel)
836 printf("nfsd server cache flooded, try "
837 "increasing vfs.nfsd.tcphighwater\n");
838 nd->nd_repstat = NFSERR_RESOURCE;
839 *repp = nfsd_errmap(nd);
840 if (op == NFSV4OP_SETATTR) {
842 * Setattr replies require a bitmap.
843 * even for errors like these.
845 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
851 if (nfsv4_opflag[op].savereply)
852 nd->nd_flag |= ND_SAVEREPLY;
855 error = nfsrv_mtofh(nd, &fh);
859 nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
861 /* For now, allow this for non-export FHs */
862 if (!nd->nd_repstat) {
866 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
871 case NFSV4OP_PUTPUBFH:
873 nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
876 nd->nd_repstat = NFSERR_NOFILEHANDLE;
877 if (!nd->nd_repstat) {
881 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
886 case NFSV4OP_PUTROOTFH:
888 nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp,
890 if (!nd->nd_repstat) {
894 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
899 nd->nd_repstat = NFSERR_NOFILEHANDLE;
902 if (vp && NFSVNO_EXPORTED(&vpnes)) {
904 /* If vp == savevp, a no-op */
911 save_fsid = cur_fsid;
914 nd->nd_repstat = NFSERR_NOFILEHANDLE;
917 case NFSV4OP_RESTOREFH:
920 /* If vp == savevp, a no-op */
926 cur_fsid = save_fsid;
929 nd->nd_repstat = NFSERR_RESTOREFH;
934 * Allow a Lookup, Getattr, GetFH, Secinfo on an
935 * non-exported directory if
936 * nfs_rootfhset. Do I need to allow any other Ops?
937 * (You can only have a non-exported vpnes if
938 * nfs_rootfhset is true. See nfsd_fhtovp())
939 * Allow AUTH_SYS to be used for file systems
940 * exported GSS only for certain Ops, to allow
941 * clients to do mounts more easily.
943 if (nfsv4_opflag[op].needscfh && vp) {
944 if (!NFSVNO_EXPORTED(&vpnes) &&
945 op != NFSV4OP_LOOKUP &&
946 op != NFSV4OP_GETATTR &&
947 op != NFSV4OP_GETFH &&
948 op != NFSV4OP_ACCESS &&
949 op != NFSV4OP_READLINK &&
950 op != NFSV4OP_SECINFO)
951 nd->nd_repstat = NFSERR_NOFILEHANDLE;
952 else if (nfsvno_testexp(nd, &vpnes) &&
953 op != NFSV4OP_LOOKUP &&
954 op != NFSV4OP_GETFH &&
955 op != NFSV4OP_GETATTR &&
956 op != NFSV4OP_SECINFO)
957 nd->nd_repstat = NFSERR_WRONGSEC;
958 if (nd->nd_repstat) {
959 if (op == NFSV4OP_SETATTR) {
961 * Setattr reply requires a bitmap
962 * even for errors like these.
964 NFSM_BUILD(tl, u_int32_t *,
971 if (nfsv4_opflag[op].retfh == 1) {
973 nd->nd_repstat = NFSERR_NOFILEHANDLE;
977 if (nfsv4_opflag[op].modifyfs)
978 vn_start_write(vp, &temp_mp, V_WAIT);
979 error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
980 &nvp, (fhandle_t *)fh.nfsrvfh_data, p, &vpnes);
981 if (!error && !nd->nd_repstat) {
982 if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) {
983 new_mp = nvp->v_mount;
984 if (cur_fsid.val[0] !=
985 new_mp->mnt_stat.f_fsid.val[0] ||
987 new_mp->mnt_stat.f_fsid.val[1]) {
988 /* crossed a server mount point */
989 nd->nd_repstat = nfsvno_checkexp(new_mp,
990 nd->nd_nam, &nes, &credanon);
992 nd->nd_repstat = nfsd_excred(nd,
994 if (credanon != NULL)
996 if (!nd->nd_repstat) {
998 cur_fsid = new_mp->mnt_stat.f_fsid;
1001 /* Lookup ops return a locked vnode */
1002 NFSVOPUNLOCK(nvp, 0);
1004 if (!nd->nd_repstat) {
1010 if (nfsv4_opflag[op].modifyfs)
1011 vn_finished_write(temp_mp);
1012 } else if (nfsv4_opflag[op].retfh == 2) {
1013 if (vp == NULL || savevp == NULL) {
1014 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1016 } else if (cur_fsid.val[0] != save_fsid.val[0] ||
1017 cur_fsid.val[1] != save_fsid.val[1]) {
1018 nd->nd_repstat = NFSERR_XDEV;
1021 if (nfsv4_opflag[op].modifyfs)
1022 vn_start_write(savevp, &temp_mp, V_WAIT);
1023 if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
1026 error = (*(nfsrv4_ops2[op]))(nd, isdgram,
1027 savevp, vp, p, &savevpnes, &vpnes);
1029 nd->nd_repstat = NFSERR_PERM;
1030 if (nfsv4_opflag[op].modifyfs)
1031 vn_finished_write(temp_mp);
1033 if (nfsv4_opflag[op].retfh != 0)
1034 panic("nfsrvd_compound");
1035 if (nfsv4_opflag[op].needscfh) {
1037 lktype = nfsv4_opflag[op].lktype;
1038 if (nfsv4_opflag[op].modifyfs) {
1039 vn_start_write(vp, &temp_mp,
1041 if (op == NFSV4OP_WRITE &&
1042 MNT_SHARED_WRITES(temp_mp))
1045 if (NFSVOPLOCK(vp, lktype) == 0)
1048 nd->nd_repstat = NFSERR_PERM;
1050 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1051 if (op == NFSV4OP_SETATTR) {
1053 * Setattr reply requires a
1054 * bitmap even for errors like
1057 NFSM_BUILD(tl, u_int32_t *,
1063 if (nd->nd_repstat == 0)
1064 error = (*(nfsrv4_ops0[op]))(nd,
1065 isdgram, vp, p, &vpnes);
1066 if (nfsv4_opflag[op].modifyfs)
1067 vn_finished_write(temp_mp);
1069 error = (*(nfsrv4_ops0[op]))(nd, isdgram,
1075 if (error == EBADRPC || error == NFSERR_BADXDR) {
1076 nd->nd_repstat = NFSERR_BADXDR;
1078 nd->nd_repstat = error;
1079 printf("nfsv4 comperr0=%d\n", error);
1084 if (statsinprog != 0) {
1085 nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1086 /*then*/ &start_time);
1091 if (nd->nd_repstat) {
1092 *repp = nfsd_errmap(nd);
1095 *repp = 0; /* NFS4_OK */
1099 if (statsinprog != 0) {
1100 nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1101 /*then*/ &start_time);
1105 if (error == EBADRPC || error == NFSERR_BADXDR)
1106 nd->nd_repstat = NFSERR_BADXDR;
1108 printf("nfsv4 comperr1=%d\n", error);
1111 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1115 *retopsp = txdr_unsigned(retops);
1121 NFSLOCKV4ROOTMUTEX();
1122 nfsv4_relref(&nfsv4rootfs_lock);
1123 NFSUNLOCKV4ROOTMUTEX();
1125 NFSEXITCODE2(0, nd);