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 * 4. 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 nfsstats newnfsstats;
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] = {
404 * Do an RPC. Basically, get the file handles translated to vnode pointers
405 * and then call the appropriate server routine. The server routines are
406 * split into groups, based on whether they use a file handle or file
407 * handle plus name or ...
408 * The NFS V4 Compound RPC is performed separately by nfsrvd_compound().
411 nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, u_char *tag, int taglen,
412 u_int32_t minorvers, NFSPROC_T *p)
414 int error = 0, lktype;
418 struct nfsexstuff nes;
421 * Get a locked vnode for the first file handle
423 if (!(nd->nd_flag & ND_NFSV4)) {
424 KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc"));
426 * For NFSv3, if the malloc/mget allocation is near limits,
427 * return NFSERR_DELAY.
429 if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) {
430 nd->nd_repstat = NFSERR_DELAY;
433 error = nfsrv_mtofh(nd, &fh);
435 if (error != EBADRPC)
436 printf("nfs dorpc err1=%d\n", error);
437 nd->nd_repstat = NFSERR_GARBAGE;
440 if (nd->nd_procnum == NFSPROC_READ ||
441 nd->nd_procnum == NFSPROC_WRITE ||
442 nd->nd_procnum == NFSPROC_READDIR ||
443 nd->nd_procnum == NFSPROC_READDIRPLUS ||
444 nd->nd_procnum == NFSPROC_READLINK ||
445 nd->nd_procnum == NFSPROC_GETATTR ||
446 nd->nd_procnum == NFSPROC_ACCESS ||
447 nd->nd_procnum == NFSPROC_FSSTAT ||
448 nd->nd_procnum == NFSPROC_FSINFO)
451 lktype = LK_EXCLUSIVE;
452 if (nd->nd_flag & ND_PUBLOOKUP)
453 nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes,
454 &mp, nfs_writerpc[nd->nd_procnum], p);
456 nfsd_fhtovp(nd, &fh, lktype, &vp, &nes,
457 &mp, nfs_writerpc[nd->nd_procnum], p);
458 if (nd->nd_repstat == NFSERR_PROGNOTV4)
464 * For V2 and 3, set the ND_SAVEREPLY flag for the recent request
465 * cache, as required.
466 * For V4, nfsrvd_compound() does this.
468 if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum])
469 nd->nd_flag |= ND_SAVEREPLY;
473 * If nd_repstat is non-zero, just fill in the reply status
474 * to complete the RPC reply for V2. Otherwise, you must do
477 if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) {
478 *nd->nd_errp = nfsd_errmap(nd);
479 NFSINCRGLOBAL(newnfsstats.srvrpccnt[nfsv3to4op[nd->nd_procnum]]);
480 if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0)
481 vn_finished_write(mp);
486 * Now the procedure can be performed. For V4, nfsrvd_compound()
487 * works through the sub-rpcs, otherwise just call the procedure.
488 * The procedures are in three groups with different arguments.
489 * The group is indicated by the value in nfs_retfh[].
491 if (nd->nd_flag & ND_NFSV4) {
492 nfsrvd_compound(nd, isdgram, tag, taglen, minorvers, p);
494 if (nfs_retfh[nd->nd_procnum] == 1) {
497 error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram,
498 vp, NULL, (fhandle_t *)fh.nfsrvfh_data, p, &nes);
499 } else if (nfs_retfh[nd->nd_procnum] == 2) {
500 error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram,
501 vp, NULL, p, &nes, NULL);
503 error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
506 if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0)
507 vn_finished_write(mp);
508 NFSINCRGLOBAL(newnfsstats.srvrpccnt[nfsv3to4op[nd->nd_procnum]]);
511 if (error != EBADRPC)
512 printf("nfs dorpc err2=%d\n", error);
513 nd->nd_repstat = NFSERR_GARBAGE;
515 *nd->nd_errp = nfsd_errmap(nd);
518 * Don't cache certain reply status values.
520 if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) &&
521 (nd->nd_repstat == NFSERR_GARBAGE ||
522 nd->nd_repstat == NFSERR_BADXDR ||
523 nd->nd_repstat == NFSERR_MOVED ||
524 nd->nd_repstat == NFSERR_DELAY ||
525 nd->nd_repstat == NFSERR_BADSEQID ||
526 nd->nd_repstat == NFSERR_RESOURCE ||
527 nd->nd_repstat == NFSERR_SERVERFAULT ||
528 nd->nd_repstat == NFSERR_STALECLIENTID ||
529 nd->nd_repstat == NFSERR_STALESTATEID ||
530 nd->nd_repstat == NFSERR_OLDSTATEID ||
531 nd->nd_repstat == NFSERR_BADSTATEID ||
532 nd->nd_repstat == NFSERR_GRACE ||
533 nd->nd_repstat == NFSERR_NOGRACE))
534 nd->nd_flag &= ~ND_SAVEREPLY;
541 * Breaks down a compound RPC request and calls the server routines for
543 * Some suboperations are performed directly here to simplify file handle<-->
544 * vnode pointer handling.
547 nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,
548 int taglen, u_int32_t minorvers, NFSPROC_T *p)
550 int i, lktype, op, op0 = 0;
552 struct nfsclient *clp, *nclp;
553 int numops, error = 0, igotlock;
554 u_int32_t retops = 0, *retopsp = NULL, *repp;
555 vnode_t vp, nvp, savevp;
557 mount_t new_mp, temp_mp = NULL;
558 struct ucred *credanon;
559 struct nfsexstuff nes, vpnes, savevpnes;
560 fsid_t cur_fsid, save_fsid;
561 static u_int64_t compref = 0;
563 NFSVNO_EXINIT(&vpnes);
564 NFSVNO_EXINIT(&savevpnes);
566 * Put the seq# of the current compound RPC in nfsrv_descript.
567 * (This is used by nfsrv_checkgetattr(), to see if the write
568 * delegation was created by the same compound RPC as the one
569 * with that Getattr in it.)
570 * Don't worry about the 64bit number wrapping around. It ain't
571 * gonna happen before this server gets shut down/rebooted.
573 nd->nd_compref = compref++;
576 * Check for and optionally get a lock on the root. This lock means that
577 * no nfsd will be fiddling with the V4 file system and state stuff. It
578 * is required when the V4 root is being changed, the stable storage
579 * restart file is being updated, or callbacks are being done.
580 * When any of the nfsd are processing an NFSv4 compound RPC, they must
581 * either hold a reference count (nfs_usecnt) or the lock. When
582 * nfsrv_unlock() is called to release the lock, it can optionally
583 * also get a reference count, which saves the need for a call to
584 * nfsrv_getref() after nfsrv_unlock().
587 * First, check to see if we need to wait for an update lock.
590 NFSLOCKV4ROOTMUTEX();
591 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK)
592 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
593 NFSV4ROOTLOCKMUTEXPTR, NULL);
595 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
596 NFSV4ROOTLOCKMUTEXPTR, NULL);
597 NFSUNLOCKV4ROOTMUTEX();
600 * If I got the lock, I can update the stable storage file.
601 * Done when the grace period is over or a client has long
604 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK;
605 if ((nfsrv_stablefirst.nsf_flags &
606 (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
607 nfsrv_updatestable(p);
610 * If at least one client has long since expired, search
611 * the client list for them, write a REVOKE record on the
612 * stable storage file and then remove them from the client
615 if (nfsrv_stablefirst.nsf_flags & NFSNSF_EXPIREDCLIENT) {
616 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_EXPIREDCLIENT;
617 for (i = 0; i < nfsrv_clienthashsize; i++) {
618 LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash,
620 if (clp->lc_flags & LCL_EXPIREIT) {
621 if (!LIST_EMPTY(&clp->lc_open) ||
622 !LIST_EMPTY(&clp->lc_deleg))
623 nfsrv_writestable(clp->lc_id,
624 clp->lc_idlen, NFSNST_REVOKE, p);
625 nfsrv_cleanclient(clp, p);
626 nfsrv_freedeleglist(&clp->lc_deleg);
627 nfsrv_freedeleglist(&clp->lc_olddeleg);
628 LIST_REMOVE(clp, lc_hash);
629 nfsrv_zapclient(clp, p);
634 NFSLOCKV4ROOTMUTEX();
635 nfsv4_unlock(&nfsv4rootfs_lock, 1);
636 NFSUNLOCKV4ROOTMUTEX();
639 * If we didn't get the lock, we need to get a refcnt,
640 * which also checks for and waits for the lock.
642 NFSLOCKV4ROOTMUTEX();
643 nfsv4_getref(&nfsv4rootfs_lock, NULL,
644 NFSV4ROOTLOCKMUTEXPTR, NULL);
645 NFSUNLOCKV4ROOTMUTEX();
649 * If flagged, search for open owners that haven't had any opens
652 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) {
653 nfsrv_throwawayopens(p);
657 save_fsid.val[0] = save_fsid.val[1] = 0;
658 cur_fsid.val[0] = cur_fsid.val[1] = 0;
660 /* If taglen < 0, there was a parsing error in nfsd_getminorvers(). */
666 (void) nfsm_strtom(nd, tag, taglen);
667 NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED);
668 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
669 if (minorvers != NFSV4_MINORVERSION && minorvers != NFSV41_MINORVERSION)
670 nd->nd_repstat = NFSERR_MINORVERMISMATCH;
674 numops = fxdr_unsigned(int, *tl);
676 * Loop around doing the sub ops.
677 * vp - is an unlocked vnode pointer for the CFH
678 * savevp - is an unlocked vnode pointer for the SAVEDFH
679 * (at some future date, it might turn out to be more appropriate
680 * to keep the file handles instead of vnode pointers?)
681 * savevpnes and vpnes - are the export flags for the above.
683 for (i = 0; i < numops; i++) {
684 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
685 NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED);
687 op = fxdr_unsigned(int, *tl);
688 NFSD_DEBUG(4, "op=%d\n", op);
689 if (op < NFSV4OP_ACCESS ||
690 (op >= NFSV4OP_NOPS && (nd->nd_flag & ND_NFSV41) == 0) ||
691 (op >= NFSV41_NOPS && (nd->nd_flag & ND_NFSV41) != 0)) {
692 nd->nd_repstat = NFSERR_OPILLEGAL;
693 *repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL);
694 *repp = nfsd_errmap(nd);
703 nd->nd_flag |= ND_LASTOP;
706 * Check for a referral on the current FH and, if so, return
707 * NFSERR_MOVED for all ops that allow it, except Getattr.
709 if (vp != NULL && op != NFSV4OP_GETATTR &&
710 nfsv4root_getreferral(vp, NULL, 0) != NULL &&
711 nfsrv_errmoved(op)) {
712 nd->nd_repstat = NFSERR_MOVED;
713 *repp = nfsd_errmap(nd);
719 * For NFSv4.1, check for a Sequence Operation being first
720 * or one of the other allowed operations by itself.
722 if ((nd->nd_flag & ND_NFSV41) != 0) {
723 if (i != 0 && op == NFSV4OP_SEQUENCE)
724 nd->nd_repstat = NFSERR_SEQUENCEPOS;
725 else if (i == 0 && op != NFSV4OP_SEQUENCE &&
726 op != NFSV4OP_EXCHANGEID &&
727 op != NFSV4OP_CREATESESSION &&
728 op != NFSV4OP_BINDCONNTOSESS &&
729 op != NFSV4OP_DESTROYCLIENTID &&
730 op != NFSV4OP_DESTROYSESSION)
731 nd->nd_repstat = NFSERR_OPNOTINSESS;
732 else if (i != 0 && op0 != NFSV4OP_SEQUENCE)
733 nd->nd_repstat = NFSERR_NOTONLYOP;
734 if (nd->nd_repstat != 0) {
735 *repp = nfsd_errmap(nd);
743 * If over flood level, reply NFSERR_RESOURCE, if at the first
744 * Op. (Since a client recovery from NFSERR_RESOURCE can get
745 * really nasty for certain Op sequences, I'll play it safe
746 * and only return the error at the beginning.) The cache
747 * will still function over flood level, but uses lots of
749 * If nfsrv_mallocmget_limit() returns True, the system is near
750 * to its limit for memory that malloc()/mget() can allocate.
752 if (i == 0 && (nd->nd_rp == NULL ||
753 nd->nd_rp->rc_refcnt == 0) &&
754 (nfsrv_mallocmget_limit() ||
755 nfsrc_tcpsavedreplies > nfsrc_floodlevel)) {
756 if (nfsrc_tcpsavedreplies > nfsrc_floodlevel)
757 printf("nfsd server cache flooded, try "
758 "increasing vfs.nfsd.tcphighwater\n");
759 nd->nd_repstat = NFSERR_RESOURCE;
760 *repp = nfsd_errmap(nd);
761 if (op == NFSV4OP_SETATTR) {
763 * Setattr replies require a bitmap.
764 * even for errors like these.
766 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
772 if (nfsv4_opflag[op].savereply)
773 nd->nd_flag |= ND_SAVEREPLY;
774 NFSINCRGLOBAL(newnfsstats.srvrpccnt[nd->nd_procnum]);
777 error = nfsrv_mtofh(nd, &fh);
781 nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
783 /* For now, allow this for non-export FHs */
784 if (!nd->nd_repstat) {
788 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
793 case NFSV4OP_PUTPUBFH:
795 nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
798 nd->nd_repstat = NFSERR_NOFILEHANDLE;
799 if (!nd->nd_repstat) {
803 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
808 case NFSV4OP_PUTROOTFH:
810 nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp,
812 if (!nd->nd_repstat) {
816 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
821 nd->nd_repstat = NFSERR_NOFILEHANDLE;
824 if (vp && NFSVNO_EXPORTED(&vpnes)) {
826 /* If vp == savevp, a no-op */
833 save_fsid = cur_fsid;
836 nd->nd_repstat = NFSERR_NOFILEHANDLE;
839 case NFSV4OP_RESTOREFH:
842 /* If vp == savevp, a no-op */
848 cur_fsid = save_fsid;
851 nd->nd_repstat = NFSERR_RESTOREFH;
856 * Allow a Lookup, Getattr, GetFH, Secinfo on an
857 * non-exported directory if
858 * nfs_rootfhset. Do I need to allow any other Ops?
859 * (You can only have a non-exported vpnes if
860 * nfs_rootfhset is true. See nfsd_fhtovp())
861 * Allow AUTH_SYS to be used for file systems
862 * exported GSS only for certain Ops, to allow
863 * clients to do mounts more easily.
865 if (nfsv4_opflag[op].needscfh && vp) {
866 if (!NFSVNO_EXPORTED(&vpnes) &&
867 op != NFSV4OP_LOOKUP &&
868 op != NFSV4OP_GETATTR &&
869 op != NFSV4OP_GETFH &&
870 op != NFSV4OP_ACCESS &&
871 op != NFSV4OP_READLINK &&
872 op != NFSV4OP_SECINFO)
873 nd->nd_repstat = NFSERR_NOFILEHANDLE;
874 else if (nfsvno_testexp(nd, &vpnes) &&
875 op != NFSV4OP_LOOKUP &&
876 op != NFSV4OP_GETFH &&
877 op != NFSV4OP_GETATTR &&
878 op != NFSV4OP_SECINFO)
879 nd->nd_repstat = NFSERR_WRONGSEC;
880 if (nd->nd_repstat) {
881 if (op == NFSV4OP_SETATTR) {
883 * Setattr reply requires a bitmap
884 * even for errors like these.
886 NFSM_BUILD(tl, u_int32_t *,
893 if (nfsv4_opflag[op].retfh == 1) {
895 nd->nd_repstat = NFSERR_NOFILEHANDLE;
899 if (nfsv4_opflag[op].modifyfs)
900 vn_start_write(vp, &temp_mp, V_WAIT);
901 error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
902 &nvp, (fhandle_t *)fh.nfsrvfh_data, p, &vpnes);
903 if (!error && !nd->nd_repstat) {
904 if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) {
905 new_mp = nvp->v_mount;
906 if (cur_fsid.val[0] !=
907 new_mp->mnt_stat.f_fsid.val[0] ||
909 new_mp->mnt_stat.f_fsid.val[1]) {
910 /* crossed a server mount point */
911 nd->nd_repstat = nfsvno_checkexp(new_mp,
912 nd->nd_nam, &nes, &credanon);
914 nd->nd_repstat = nfsd_excred(nd,
916 if (credanon != NULL)
918 if (!nd->nd_repstat) {
920 cur_fsid = new_mp->mnt_stat.f_fsid;
923 /* Lookup ops return a locked vnode */
924 NFSVOPUNLOCK(nvp, 0);
926 if (!nd->nd_repstat) {
932 if (nfsv4_opflag[op].modifyfs)
933 vn_finished_write(temp_mp);
934 } else if (nfsv4_opflag[op].retfh == 2) {
935 if (vp == NULL || savevp == NULL) {
936 nd->nd_repstat = NFSERR_NOFILEHANDLE;
938 } else if (cur_fsid.val[0] != save_fsid.val[0] ||
939 cur_fsid.val[1] != save_fsid.val[1]) {
940 nd->nd_repstat = NFSERR_XDEV;
943 if (nfsv4_opflag[op].modifyfs)
944 vn_start_write(savevp, &temp_mp, V_WAIT);
945 if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
948 error = (*(nfsrv4_ops2[op]))(nd, isdgram,
949 savevp, vp, p, &savevpnes, &vpnes);
951 nd->nd_repstat = NFSERR_PERM;
952 if (nfsv4_opflag[op].modifyfs)
953 vn_finished_write(temp_mp);
955 if (nfsv4_opflag[op].retfh != 0)
956 panic("nfsrvd_compound");
957 if (nfsv4_opflag[op].needscfh) {
959 lktype = nfsv4_opflag[op].lktype;
960 if (nfsv4_opflag[op].modifyfs) {
961 vn_start_write(vp, &temp_mp,
963 if (op == NFSV4OP_WRITE &&
964 MNT_SHARED_WRITES(temp_mp))
967 if (NFSVOPLOCK(vp, lktype) == 0)
970 nd->nd_repstat = NFSERR_PERM;
972 nd->nd_repstat = NFSERR_NOFILEHANDLE;
973 if (op == NFSV4OP_SETATTR) {
975 * Setattr reply requires a
976 * bitmap even for errors like
979 NFSM_BUILD(tl, u_int32_t *,
985 if (nd->nd_repstat == 0)
986 error = (*(nfsrv4_ops0[op]))(nd,
987 isdgram, vp, p, &vpnes);
988 if (nfsv4_opflag[op].modifyfs)
989 vn_finished_write(temp_mp);
991 error = (*(nfsrv4_ops0[op]))(nd, isdgram,
997 if (error == EBADRPC || error == NFSERR_BADXDR) {
998 nd->nd_repstat = NFSERR_BADXDR;
1000 nd->nd_repstat = error;
1001 printf("nfsv4 comperr0=%d\n", error);
1006 if (nd->nd_repstat) {
1007 *repp = nfsd_errmap(nd);
1010 *repp = 0; /* NFS4_OK */
1015 if (error == EBADRPC || error == NFSERR_BADXDR)
1016 nd->nd_repstat = NFSERR_BADXDR;
1018 printf("nfsv4 comperr1=%d\n", error);
1021 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1025 *retopsp = txdr_unsigned(retops);
1031 NFSLOCKV4ROOTMUTEX();
1032 nfsv4_relref(&nfsv4rootfs_lock);
1033 NFSUNLOCKV4ROOTMUTEX();
1035 NFSEXITCODE2(0, nd);