2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Rick Macklem at The University of Guelph.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
38 * Socket operations for use by the nfs server.
42 #include <fs/nfs/nfsport.h>
44 extern struct nfsstatsv1 nfsstatsv1;
45 extern struct nfsrvfh nfs_pubfh, nfs_rootfh;
46 extern int nfs_pubfhset, nfs_rootfhset;
47 extern struct nfsv4lock nfsv4rootfs_lock;
48 extern struct nfsrv_stablefirst nfsrv_stablefirst;
49 extern struct nfsclienthashhead *nfsclienthash;
50 extern int nfsrv_clienthashsize;
51 extern int nfsrc_floodlevel, nfsrc_tcpsavedreplies;
52 extern int nfsd_debuglevel;
56 int (*nfsrv3_procs0[NFS_V3NPROCS])(struct nfsrv_descript *,
57 int, vnode_t , NFSPROC_T *, struct nfsexstuff *) = {
58 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
61 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
67 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
68 (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,
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,
82 int (*nfsrv3_procs1[NFS_V3NPROCS])(struct nfsrv_descript *,
83 int, vnode_t , vnode_t *, fhandle_t *,
84 NFSPROC_T *, struct nfsexstuff *) = {
85 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
86 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
87 (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,
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,
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,
97 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
98 (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,
109 int (*nfsrv3_procs2[NFS_V3NPROCS])(struct nfsrv_descript *,
110 int, vnode_t , vnode_t , NFSPROC_T *,
111 struct nfsexstuff *, struct nfsexstuff *) = {
112 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
113 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
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,
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,
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,
136 int (*nfsrv4_ops0[NFSV41_NOPS])(struct nfsrv_descript *,
137 int, vnode_t , NFSPROC_T *, struct nfsexstuff *) = {
138 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
139 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
140 (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,
149 (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,
154 (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,
157 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
159 nfsrvd_opendowngrade,
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,
162 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
167 (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,
170 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
174 nfsrvd_setclientidcfrm,
177 nfsrvd_releaselckown,
181 nfsrvd_createsession,
182 nfsrvd_destroysession,
195 nfsrvd_destroyclientid,
196 nfsrvd_reclaimcomplete,
199 int (*nfsrv4_ops1[NFSV41_NOPS])(struct nfsrv_descript *,
200 int, vnode_t , vnode_t *, fhandle_t *,
201 NFSPROC_T *, struct nfsexstuff *) = {
202 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
203 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
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,
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,
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,
219 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
222 (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,
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,
263 int (*nfsrv4_ops2[NFSV41_NOPS])(struct nfsrv_descript *,
264 int, vnode_t , vnode_t , NFSPROC_T *,
265 struct nfsexstuff *, struct nfsexstuff *) = {
266 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
267 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
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,
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,
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,
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,
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,
326 #endif /* !APPLEKEXT */
329 * Static array that defines which nfs rpc's are nonidempotent
331 static int nfsrv_nonidempotent[NFS_V3NPROCS] = {
357 * This static array indicates whether or not the RPC modifies the
360 static int nfs_writerpc[NFS_NPROCS] = { 0, 0, 1, 0, 0, 0, 0,
361 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
362 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
364 /* local functions */
365 static void nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
366 u_char *tag, int taglen, u_int32_t minorvers, NFSPROC_T *p);
370 * This static array indicates which server procedures require the extra
371 * arguments to return the current file handle for V2, 3.
373 static int nfs_retfh[NFS_V3NPROCS] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1,
374 1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0 };
376 extern struct nfsv4_opflag nfsv4_opflag[NFSV41_NOPS];
378 static int nfsv3to4op[NFS_V3NPROCS] = {
403 static struct mtx nfsrvd_statmtx;
404 MTX_SYSINIT(nfsst, &nfsrvd_statmtx, "NFSstat", MTX_DEF);
407 nfsrvd_statstart(int op, struct bintime *now)
409 if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
410 printf("%s: op %d invalid\n", __func__, op);
414 mtx_lock(&nfsrvd_statmtx);
415 if (nfsstatsv1.srvstartcnt == nfsstatsv1.srvdonecnt) {
417 nfsstatsv1.busyfrom = *now;
419 binuptime(&nfsstatsv1.busyfrom);
422 nfsstatsv1.srvrpccnt[op]++;
423 nfsstatsv1.srvstartcnt++;
424 mtx_unlock(&nfsrvd_statmtx);
429 nfsrvd_statend(int op, uint64_t bytes, struct bintime *now,
430 struct bintime *then)
432 struct bintime dt, lnow;
434 if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
435 printf("%s: op %d invalid\n", __func__, op);
444 mtx_lock(&nfsrvd_statmtx);
446 nfsstatsv1.srvbytes[op] += bytes;
447 nfsstatsv1.srvops[op]++;
451 bintime_sub(&dt, then);
452 bintime_add(&nfsstatsv1.srvduration[op], &dt);
456 bintime_sub(&dt, &nfsstatsv1.busyfrom);
457 bintime_add(&nfsstatsv1.busytime, &dt);
458 nfsstatsv1.busyfrom = *now;
460 nfsstatsv1.srvdonecnt++;
462 mtx_unlock(&nfsrvd_statmtx);
466 * Do an RPC. Basically, get the file handles translated to vnode pointers
467 * and then call the appropriate server routine. The server routines are
468 * split into groups, based on whether they use a file handle or file
469 * handle plus name or ...
470 * The NFS V4 Compound RPC is performed separately by nfsrvd_compound().
473 nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, u_char *tag, int taglen,
474 u_int32_t minorvers, NFSPROC_T *p)
476 int error = 0, lktype;
480 struct nfsexstuff nes;
483 * Get a locked vnode for the first file handle
485 if (!(nd->nd_flag & ND_NFSV4)) {
486 KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc"));
488 * For NFSv3, if the malloc/mget allocation is near limits,
489 * return NFSERR_DELAY.
491 if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) {
492 nd->nd_repstat = NFSERR_DELAY;
495 error = nfsrv_mtofh(nd, &fh);
497 if (error != EBADRPC)
498 printf("nfs dorpc err1=%d\n", error);
499 nd->nd_repstat = NFSERR_GARBAGE;
502 if (nd->nd_procnum == NFSPROC_READ ||
503 nd->nd_procnum == NFSPROC_WRITE ||
504 nd->nd_procnum == NFSPROC_READDIR ||
505 nd->nd_procnum == NFSPROC_READDIRPLUS ||
506 nd->nd_procnum == NFSPROC_READLINK ||
507 nd->nd_procnum == NFSPROC_GETATTR ||
508 nd->nd_procnum == NFSPROC_ACCESS ||
509 nd->nd_procnum == NFSPROC_FSSTAT ||
510 nd->nd_procnum == NFSPROC_FSINFO)
513 lktype = LK_EXCLUSIVE;
514 if (nd->nd_flag & ND_PUBLOOKUP)
515 nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes,
516 &mp, nfs_writerpc[nd->nd_procnum], p);
518 nfsd_fhtovp(nd, &fh, lktype, &vp, &nes,
519 &mp, nfs_writerpc[nd->nd_procnum], p);
520 if (nd->nd_repstat == NFSERR_PROGNOTV4)
526 * For V2 and 3, set the ND_SAVEREPLY flag for the recent request
527 * cache, as required.
528 * For V4, nfsrvd_compound() does this.
530 if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum])
531 nd->nd_flag |= ND_SAVEREPLY;
535 * If nd_repstat is non-zero, just fill in the reply status
536 * to complete the RPC reply for V2. Otherwise, you must do
539 if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) {
540 *nd->nd_errp = nfsd_errmap(nd);
541 nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], /*now*/ NULL);
542 nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
543 /*now*/ NULL, /*then*/ NULL);
544 if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0)
545 vn_finished_write(mp);
550 * Now the procedure can be performed. For V4, nfsrvd_compound()
551 * works through the sub-rpcs, otherwise just call the procedure.
552 * The procedures are in three groups with different arguments.
553 * The group is indicated by the value in nfs_retfh[].
555 if (nd->nd_flag & ND_NFSV4) {
556 nfsrvd_compound(nd, isdgram, tag, taglen, minorvers, p);
558 struct bintime start_time;
560 binuptime(&start_time);
561 nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], &start_time);
563 if (nfs_retfh[nd->nd_procnum] == 1) {
566 error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram,
567 vp, NULL, (fhandle_t *)fh.nfsrvfh_data, p, &nes);
568 } else if (nfs_retfh[nd->nd_procnum] == 2) {
569 error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram,
570 vp, NULL, p, &nes, NULL);
572 error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
575 if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0)
576 vn_finished_write(mp);
578 nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
579 /*now*/ NULL, /*then*/ &start_time);
582 if (error != EBADRPC)
583 printf("nfs dorpc err2=%d\n", error);
584 nd->nd_repstat = NFSERR_GARBAGE;
586 *nd->nd_errp = nfsd_errmap(nd);
589 * Don't cache certain reply status values.
591 if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) &&
592 (nd->nd_repstat == NFSERR_GARBAGE ||
593 nd->nd_repstat == NFSERR_BADXDR ||
594 nd->nd_repstat == NFSERR_MOVED ||
595 nd->nd_repstat == NFSERR_DELAY ||
596 nd->nd_repstat == NFSERR_BADSEQID ||
597 nd->nd_repstat == NFSERR_RESOURCE ||
598 nd->nd_repstat == NFSERR_SERVERFAULT ||
599 nd->nd_repstat == NFSERR_STALECLIENTID ||
600 nd->nd_repstat == NFSERR_STALESTATEID ||
601 nd->nd_repstat == NFSERR_OLDSTATEID ||
602 nd->nd_repstat == NFSERR_BADSTATEID ||
603 nd->nd_repstat == NFSERR_GRACE ||
604 nd->nd_repstat == NFSERR_NOGRACE))
605 nd->nd_flag &= ~ND_SAVEREPLY;
612 * Breaks down a compound RPC request and calls the server routines for
614 * Some suboperations are performed directly here to simplify file handle<-->
615 * vnode pointer handling.
618 nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,
619 int taglen, u_int32_t minorvers, NFSPROC_T *p)
621 int i, lktype, op, op0 = 0, statsinprog = 0;
623 struct nfsclient *clp, *nclp;
624 int numops, error = 0, igotlock;
625 u_int32_t retops = 0, *retopsp = NULL, *repp;
626 vnode_t vp, nvp, savevp;
628 mount_t new_mp, temp_mp = NULL;
629 struct ucred *credanon;
630 struct nfsexstuff nes, vpnes, savevpnes;
631 fsid_t cur_fsid, save_fsid;
632 static u_int64_t compref = 0;
633 struct bintime start_time;
635 NFSVNO_EXINIT(&vpnes);
636 NFSVNO_EXINIT(&savevpnes);
638 * Put the seq# of the current compound RPC in nfsrv_descript.
639 * (This is used by nfsrv_checkgetattr(), to see if the write
640 * delegation was created by the same compound RPC as the one
641 * with that Getattr in it.)
642 * Don't worry about the 64bit number wrapping around. It ain't
643 * gonna happen before this server gets shut down/rebooted.
645 nd->nd_compref = compref++;
648 * Check for and optionally get a lock on the root. This lock means that
649 * no nfsd will be fiddling with the V4 file system and state stuff. It
650 * is required when the V4 root is being changed, the stable storage
651 * restart file is being updated, or callbacks are being done.
652 * When any of the nfsd are processing an NFSv4 compound RPC, they must
653 * either hold a reference count (nfs_usecnt) or the lock. When
654 * nfsrv_unlock() is called to release the lock, it can optionally
655 * also get a reference count, which saves the need for a call to
656 * nfsrv_getref() after nfsrv_unlock().
659 * First, check to see if we need to wait for an update lock.
662 NFSLOCKV4ROOTMUTEX();
663 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK)
664 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
665 NFSV4ROOTLOCKMUTEXPTR, NULL);
667 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
668 NFSV4ROOTLOCKMUTEXPTR, NULL);
669 NFSUNLOCKV4ROOTMUTEX();
672 * If I got the lock, I can update the stable storage file.
673 * Done when the grace period is over or a client has long
676 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK;
677 if ((nfsrv_stablefirst.nsf_flags &
678 (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
679 nfsrv_updatestable(p);
682 * If at least one client has long since expired, search
683 * the client list for them, write a REVOKE record on the
684 * stable storage file and then remove them from the client
687 if (nfsrv_stablefirst.nsf_flags & NFSNSF_EXPIREDCLIENT) {
688 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_EXPIREDCLIENT;
689 for (i = 0; i < nfsrv_clienthashsize; i++) {
690 LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash,
692 if (clp->lc_flags & LCL_EXPIREIT) {
693 if (!LIST_EMPTY(&clp->lc_open) ||
694 !LIST_EMPTY(&clp->lc_deleg))
695 nfsrv_writestable(clp->lc_id,
696 clp->lc_idlen, NFSNST_REVOKE, p);
697 nfsrv_cleanclient(clp, p);
698 nfsrv_freedeleglist(&clp->lc_deleg);
699 nfsrv_freedeleglist(&clp->lc_olddeleg);
700 LIST_REMOVE(clp, lc_hash);
701 nfsrv_zapclient(clp, p);
706 NFSLOCKV4ROOTMUTEX();
707 nfsv4_unlock(&nfsv4rootfs_lock, 1);
708 NFSUNLOCKV4ROOTMUTEX();
711 * If we didn't get the lock, we need to get a refcnt,
712 * which also checks for and waits for the lock.
714 NFSLOCKV4ROOTMUTEX();
715 nfsv4_getref(&nfsv4rootfs_lock, NULL,
716 NFSV4ROOTLOCKMUTEXPTR, NULL);
717 NFSUNLOCKV4ROOTMUTEX();
721 * If flagged, search for open owners that haven't had any opens
724 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) {
725 nfsrv_throwawayopens(p);
729 save_fsid.val[0] = save_fsid.val[1] = 0;
730 cur_fsid.val[0] = cur_fsid.val[1] = 0;
732 /* If taglen < 0, there was a parsing error in nfsd_getminorvers(). */
738 (void) nfsm_strtom(nd, tag, taglen);
739 NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED);
740 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
741 if (minorvers != NFSV4_MINORVERSION && minorvers != NFSV41_MINORVERSION)
742 nd->nd_repstat = NFSERR_MINORVERMISMATCH;
746 numops = fxdr_unsigned(int, *tl);
748 * Loop around doing the sub ops.
749 * vp - is an unlocked vnode pointer for the CFH
750 * savevp - is an unlocked vnode pointer for the SAVEDFH
751 * (at some future date, it might turn out to be more appropriate
752 * to keep the file handles instead of vnode pointers?)
753 * savevpnes and vpnes - are the export flags for the above.
755 for (i = 0; i < numops; i++) {
756 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
757 NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED);
759 op = fxdr_unsigned(int, *tl);
760 NFSD_DEBUG(4, "op=%d\n", op);
762 binuptime(&start_time);
763 nfsrvd_statstart(op, &start_time);
766 if (op < NFSV4OP_ACCESS ||
767 (op >= NFSV4OP_NOPS && (nd->nd_flag & ND_NFSV41) == 0) ||
768 (op >= NFSV41_NOPS && (nd->nd_flag & ND_NFSV41) != 0)) {
769 nd->nd_repstat = NFSERR_OPILLEGAL;
770 *repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL);
771 *repp = nfsd_errmap(nd);
780 nd->nd_flag |= ND_LASTOP;
783 * Check for a referral on the current FH and, if so, return
784 * NFSERR_MOVED for all ops that allow it, except Getattr.
786 if (vp != NULL && op != NFSV4OP_GETATTR &&
787 nfsv4root_getreferral(vp, NULL, 0) != NULL &&
788 nfsrv_errmoved(op)) {
789 nd->nd_repstat = NFSERR_MOVED;
790 *repp = nfsd_errmap(nd);
796 * For NFSv4.1, check for a Sequence Operation being first
797 * or one of the other allowed operations by itself.
799 if ((nd->nd_flag & ND_NFSV41) != 0) {
800 if (i != 0 && op == NFSV4OP_SEQUENCE)
801 nd->nd_repstat = NFSERR_SEQUENCEPOS;
802 else if (i == 0 && op != NFSV4OP_SEQUENCE &&
803 op != NFSV4OP_EXCHANGEID &&
804 op != NFSV4OP_CREATESESSION &&
805 op != NFSV4OP_BINDCONNTOSESS &&
806 op != NFSV4OP_DESTROYCLIENTID &&
807 op != NFSV4OP_DESTROYSESSION)
808 nd->nd_repstat = NFSERR_OPNOTINSESS;
809 else if (i != 0 && op0 != NFSV4OP_SEQUENCE)
810 nd->nd_repstat = NFSERR_NOTONLYOP;
811 if (nd->nd_repstat != 0) {
812 *repp = nfsd_errmap(nd);
820 * If over flood level, reply NFSERR_RESOURCE, if at the first
821 * Op. (Since a client recovery from NFSERR_RESOURCE can get
822 * really nasty for certain Op sequences, I'll play it safe
823 * and only return the error at the beginning.) The cache
824 * will still function over flood level, but uses lots of
826 * If nfsrv_mallocmget_limit() returns True, the system is near
827 * to its limit for memory that malloc()/mget() can allocate.
829 if (i == 0 && (nd->nd_rp == NULL ||
830 nd->nd_rp->rc_refcnt == 0) &&
831 (nfsrv_mallocmget_limit() ||
832 nfsrc_tcpsavedreplies > nfsrc_floodlevel)) {
833 if (nfsrc_tcpsavedreplies > nfsrc_floodlevel)
834 printf("nfsd server cache flooded, try "
835 "increasing vfs.nfsd.tcphighwater\n");
836 nd->nd_repstat = NFSERR_RESOURCE;
837 *repp = nfsd_errmap(nd);
838 if (op == NFSV4OP_SETATTR) {
840 * Setattr replies require a bitmap.
841 * even for errors like these.
843 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
849 if (nfsv4_opflag[op].savereply)
850 nd->nd_flag |= ND_SAVEREPLY;
853 error = nfsrv_mtofh(nd, &fh);
857 nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
859 /* For now, allow this for non-export FHs */
860 if (!nd->nd_repstat) {
864 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
869 case NFSV4OP_PUTPUBFH:
871 nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
874 nd->nd_repstat = NFSERR_NOFILEHANDLE;
875 if (!nd->nd_repstat) {
879 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
884 case NFSV4OP_PUTROOTFH:
886 nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp,
888 if (!nd->nd_repstat) {
892 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
897 nd->nd_repstat = NFSERR_NOFILEHANDLE;
900 if (vp && NFSVNO_EXPORTED(&vpnes)) {
902 /* If vp == savevp, a no-op */
909 save_fsid = cur_fsid;
912 nd->nd_repstat = NFSERR_NOFILEHANDLE;
915 case NFSV4OP_RESTOREFH:
918 /* If vp == savevp, a no-op */
924 cur_fsid = save_fsid;
927 nd->nd_repstat = NFSERR_RESTOREFH;
932 * Allow a Lookup, Getattr, GetFH, Secinfo on an
933 * non-exported directory if
934 * nfs_rootfhset. Do I need to allow any other Ops?
935 * (You can only have a non-exported vpnes if
936 * nfs_rootfhset is true. See nfsd_fhtovp())
937 * Allow AUTH_SYS to be used for file systems
938 * exported GSS only for certain Ops, to allow
939 * clients to do mounts more easily.
941 if (nfsv4_opflag[op].needscfh && vp) {
942 if (!NFSVNO_EXPORTED(&vpnes) &&
943 op != NFSV4OP_LOOKUP &&
944 op != NFSV4OP_GETATTR &&
945 op != NFSV4OP_GETFH &&
946 op != NFSV4OP_ACCESS &&
947 op != NFSV4OP_READLINK &&
948 op != NFSV4OP_SECINFO)
949 nd->nd_repstat = NFSERR_NOFILEHANDLE;
950 else if (nfsvno_testexp(nd, &vpnes) &&
951 op != NFSV4OP_LOOKUP &&
952 op != NFSV4OP_GETFH &&
953 op != NFSV4OP_GETATTR &&
954 op != NFSV4OP_SECINFO)
955 nd->nd_repstat = NFSERR_WRONGSEC;
956 if (nd->nd_repstat) {
957 if (op == NFSV4OP_SETATTR) {
959 * Setattr reply requires a bitmap
960 * even for errors like these.
962 NFSM_BUILD(tl, u_int32_t *,
969 if (nfsv4_opflag[op].retfh == 1) {
971 nd->nd_repstat = NFSERR_NOFILEHANDLE;
975 if (nfsv4_opflag[op].modifyfs)
976 vn_start_write(vp, &temp_mp, V_WAIT);
977 error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
978 &nvp, (fhandle_t *)fh.nfsrvfh_data, p, &vpnes);
979 if (!error && !nd->nd_repstat) {
980 if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) {
981 new_mp = nvp->v_mount;
982 if (cur_fsid.val[0] !=
983 new_mp->mnt_stat.f_fsid.val[0] ||
985 new_mp->mnt_stat.f_fsid.val[1]) {
986 /* crossed a server mount point */
987 nd->nd_repstat = nfsvno_checkexp(new_mp,
988 nd->nd_nam, &nes, &credanon);
990 nd->nd_repstat = nfsd_excred(nd,
992 if (credanon != NULL)
994 if (!nd->nd_repstat) {
996 cur_fsid = new_mp->mnt_stat.f_fsid;
999 /* Lookup ops return a locked vnode */
1000 NFSVOPUNLOCK(nvp, 0);
1002 if (!nd->nd_repstat) {
1008 if (nfsv4_opflag[op].modifyfs)
1009 vn_finished_write(temp_mp);
1010 } else if (nfsv4_opflag[op].retfh == 2) {
1011 if (vp == NULL || savevp == NULL) {
1012 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1014 } else if (cur_fsid.val[0] != save_fsid.val[0] ||
1015 cur_fsid.val[1] != save_fsid.val[1]) {
1016 nd->nd_repstat = NFSERR_XDEV;
1019 if (nfsv4_opflag[op].modifyfs)
1020 vn_start_write(savevp, &temp_mp, V_WAIT);
1021 if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
1024 error = (*(nfsrv4_ops2[op]))(nd, isdgram,
1025 savevp, vp, p, &savevpnes, &vpnes);
1027 nd->nd_repstat = NFSERR_PERM;
1028 if (nfsv4_opflag[op].modifyfs)
1029 vn_finished_write(temp_mp);
1031 if (nfsv4_opflag[op].retfh != 0)
1032 panic("nfsrvd_compound");
1033 if (nfsv4_opflag[op].needscfh) {
1035 lktype = nfsv4_opflag[op].lktype;
1036 if (nfsv4_opflag[op].modifyfs) {
1037 vn_start_write(vp, &temp_mp,
1039 if (op == NFSV4OP_WRITE &&
1040 MNT_SHARED_WRITES(temp_mp))
1043 if (NFSVOPLOCK(vp, lktype) == 0)
1046 nd->nd_repstat = NFSERR_PERM;
1048 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1049 if (op == NFSV4OP_SETATTR) {
1051 * Setattr reply requires a
1052 * bitmap even for errors like
1055 NFSM_BUILD(tl, u_int32_t *,
1061 if (nd->nd_repstat == 0)
1062 error = (*(nfsrv4_ops0[op]))(nd,
1063 isdgram, vp, p, &vpnes);
1064 if (nfsv4_opflag[op].modifyfs)
1065 vn_finished_write(temp_mp);
1067 error = (*(nfsrv4_ops0[op]))(nd, isdgram,
1073 if (error == EBADRPC || error == NFSERR_BADXDR) {
1074 nd->nd_repstat = NFSERR_BADXDR;
1076 nd->nd_repstat = error;
1077 printf("nfsv4 comperr0=%d\n", error);
1082 if (statsinprog != 0) {
1083 nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1084 /*then*/ &start_time);
1089 if (nd->nd_repstat) {
1090 *repp = nfsd_errmap(nd);
1093 *repp = 0; /* NFS4_OK */
1097 if (statsinprog != 0) {
1098 nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1099 /*then*/ &start_time);
1103 if (error == EBADRPC || error == NFSERR_BADXDR)
1104 nd->nd_repstat = NFSERR_BADXDR;
1106 printf("nfsv4 comperr1=%d\n", error);
1109 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1113 *retopsp = txdr_unsigned(retops);
1119 NFSLOCKV4ROOTMUTEX();
1120 nfsv4_relref(&nfsv4rootfs_lock);
1121 NFSUNLOCKV4ROOTMUTEX();
1123 NFSEXITCODE2(0, nd);