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[NFSCLIENTHASHSIZE];
50 extern int nfsrc_floodlevel, nfsrc_tcpsavedreplies;
51 extern int nfsd_debuglevel;
55 int (*nfsrv3_procs0[NFS_V3NPROCS])(struct nfsrv_descript *,
56 int, vnode_t , NFSPROC_T *, struct nfsexstuff *) = {
57 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
60 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
66 (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,
71 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
72 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
81 int (*nfsrv3_procs1[NFS_V3NPROCS])(struct nfsrv_descript *,
82 int, vnode_t , vnode_t *, fhandle_t *,
83 NFSPROC_T *, struct nfsexstuff *) = {
84 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
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,
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,
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,
96 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
97 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
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,
108 int (*nfsrv3_procs2[NFS_V3NPROCS])(struct nfsrv_descript *,
109 int, vnode_t , vnode_t , NFSPROC_T *,
110 struct nfsexstuff *, struct nfsexstuff *) = {
111 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
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,
127 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
128 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
129 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
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,
135 int (*nfsrv4_ops0[NFSV41_NOPS])(struct nfsrv_descript *,
136 int, vnode_t , NFSPROC_T *, struct nfsexstuff *) = {
137 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
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,
143 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
148 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
152 (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,
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 nfsrvd_opendowngrade,
159 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
160 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
161 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
166 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
168 (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,
173 nfsrvd_setclientidcfrm,
176 nfsrvd_releaselckown,
180 nfsrvd_createsession,
181 nfsrvd_destroysession,
194 nfsrvd_destroyclientid,
195 nfsrvd_reclaimcomplete,
198 int (*nfsrv4_ops1[NFSV41_NOPS])(struct nfsrv_descript *,
199 int, vnode_t , vnode_t *, fhandle_t *,
200 NFSPROC_T *, struct nfsexstuff *) = {
201 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
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,
208 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
209 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
210 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
211 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
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,
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,
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,
262 int (*nfsrv4_ops2[NFSV41_NOPS])(struct nfsrv_descript *,
263 int, vnode_t , vnode_t , NFSPROC_T *,
264 struct nfsexstuff *, struct nfsexstuff *) = {
265 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
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,
277 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
278 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
279 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
280 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
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,
295 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
296 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
297 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
298 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
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,
325 #endif /* !APPLEKEXT */
328 * Static array that defines which nfs rpc's are nonidempotent
330 static int nfsrv_nonidempotent[NFS_V3NPROCS] = {
356 * This static array indicates whether or not the RPC modifies the
359 static int nfs_writerpc[NFS_NPROCS] = { 0, 0, 1, 0, 0, 0, 0,
360 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
361 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
363 /* local functions */
364 static void nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
365 u_char *tag, int taglen, u_int32_t minorvers, NFSPROC_T *p);
369 * This static array indicates which server procedures require the extra
370 * arguments to return the current file handle for V2, 3.
372 static int nfs_retfh[NFS_V3NPROCS] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1,
373 1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0 };
375 extern struct nfsv4_opflag nfsv4_opflag[NFSV41_NOPS];
377 static int nfsv3to4op[NFS_V3NPROCS] = {
403 * Do an RPC. Basically, get the file handles translated to vnode pointers
404 * and then call the appropriate server routine. The server routines are
405 * split into groups, based on whether they use a file handle or file
406 * handle plus name or ...
407 * The NFS V4 Compound RPC is performed separately by nfsrvd_compound().
410 nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, u_char *tag, int taglen,
411 u_int32_t minorvers, NFSPROC_T *p)
413 int error = 0, lktype;
417 struct nfsexstuff nes;
420 * Get a locked vnode for the first file handle
422 if (!(nd->nd_flag & ND_NFSV4)) {
423 KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc"));
425 * For NFSv3, if the malloc/mget allocation is near limits,
426 * return NFSERR_DELAY.
428 if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) {
429 nd->nd_repstat = NFSERR_DELAY;
432 error = nfsrv_mtofh(nd, &fh);
434 if (error != EBADRPC)
435 printf("nfs dorpc err1=%d\n", error);
436 nd->nd_repstat = NFSERR_GARBAGE;
439 if (nd->nd_procnum == NFSPROC_READ ||
440 nd->nd_procnum == NFSPROC_WRITE ||
441 nd->nd_procnum == NFSPROC_READDIR ||
442 nd->nd_procnum == NFSPROC_READLINK ||
443 nd->nd_procnum == NFSPROC_GETATTR ||
444 nd->nd_procnum == NFSPROC_ACCESS)
447 lktype = LK_EXCLUSIVE;
448 if (nd->nd_flag & ND_PUBLOOKUP)
449 nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes,
450 &mp, nfs_writerpc[nd->nd_procnum], p);
452 nfsd_fhtovp(nd, &fh, lktype, &vp, &nes,
453 &mp, nfs_writerpc[nd->nd_procnum], p);
454 if (nd->nd_repstat == NFSERR_PROGNOTV4)
460 * For V2 and 3, set the ND_SAVEREPLY flag for the recent request
461 * cache, as required.
462 * For V4, nfsrvd_compound() does this.
464 if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum])
465 nd->nd_flag |= ND_SAVEREPLY;
469 * If nd_repstat is non-zero, just fill in the reply status
470 * to complete the RPC reply for V2. Otherwise, you must do
473 if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) {
474 *nd->nd_errp = nfsd_errmap(nd);
475 NFSINCRGLOBAL(newnfsstats.srvrpccnt[nfsv3to4op[nd->nd_procnum]]);
476 if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0)
477 vn_finished_write(mp);
482 * Now the procedure can be performed. For V4, nfsrvd_compound()
483 * works through the sub-rpcs, otherwise just call the procedure.
484 * The procedures are in three groups with different arguments.
485 * The group is indicated by the value in nfs_retfh[].
487 if (nd->nd_flag & ND_NFSV4) {
488 nfsrvd_compound(nd, isdgram, tag, taglen, minorvers, p);
490 if (nfs_retfh[nd->nd_procnum] == 1) {
493 error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram,
494 vp, NULL, (fhandle_t *)fh.nfsrvfh_data, p, &nes);
495 } else if (nfs_retfh[nd->nd_procnum] == 2) {
496 error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram,
497 vp, NULL, p, &nes, NULL);
499 error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
502 if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0)
503 vn_finished_write(mp);
504 NFSINCRGLOBAL(newnfsstats.srvrpccnt[nfsv3to4op[nd->nd_procnum]]);
507 if (error != EBADRPC)
508 printf("nfs dorpc err2=%d\n", error);
509 nd->nd_repstat = NFSERR_GARBAGE;
511 *nd->nd_errp = nfsd_errmap(nd);
514 * Don't cache certain reply status values.
516 if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) &&
517 (nd->nd_repstat == NFSERR_GARBAGE ||
518 nd->nd_repstat == NFSERR_BADXDR ||
519 nd->nd_repstat == NFSERR_MOVED ||
520 nd->nd_repstat == NFSERR_DELAY ||
521 nd->nd_repstat == NFSERR_BADSEQID ||
522 nd->nd_repstat == NFSERR_RESOURCE ||
523 nd->nd_repstat == NFSERR_SERVERFAULT ||
524 nd->nd_repstat == NFSERR_STALECLIENTID ||
525 nd->nd_repstat == NFSERR_STALESTATEID ||
526 nd->nd_repstat == NFSERR_OLDSTATEID ||
527 nd->nd_repstat == NFSERR_BADSTATEID ||
528 nd->nd_repstat == NFSERR_GRACE ||
529 nd->nd_repstat == NFSERR_NOGRACE))
530 nd->nd_flag &= ~ND_SAVEREPLY;
537 * Breaks down a compound RPC request and calls the server routines for
539 * Some suboperations are performed directly here to simplify file handle<-->
540 * vnode pointer handling.
543 nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,
544 int taglen, u_int32_t minorvers, NFSPROC_T *p)
548 struct nfsclient *clp, *nclp;
549 int numops, error = 0, igotlock;
550 u_int32_t retops = 0, *retopsp = NULL, *repp;
551 vnode_t vp, nvp, savevp;
553 mount_t new_mp, temp_mp = NULL;
554 struct ucred *credanon;
555 struct nfsexstuff nes, vpnes, savevpnes;
556 fsid_t cur_fsid, save_fsid;
557 static u_int64_t compref = 0;
559 NFSVNO_EXINIT(&vpnes);
560 NFSVNO_EXINIT(&savevpnes);
562 * Put the seq# of the current compound RPC in nfsrv_descript.
563 * (This is used by nfsrv_checkgetattr(), to see if the write
564 * delegation was created by the same compound RPC as the one
565 * with that Getattr in it.)
566 * Don't worry about the 64bit number wrapping around. It ain't
567 * gonna happen before this server gets shut down/rebooted.
569 nd->nd_compref = compref++;
572 * Check for and optionally get a lock on the root. This lock means that
573 * no nfsd will be fiddling with the V4 file system and state stuff. It
574 * is required when the V4 root is being changed, the stable storage
575 * restart file is being updated, or callbacks are being done.
576 * When any of the nfsd are processing an NFSv4 compound RPC, they must
577 * either hold a reference count (nfs_usecnt) or the lock. When
578 * nfsrv_unlock() is called to release the lock, it can optionally
579 * also get a reference count, which saves the need for a call to
580 * nfsrv_getref() after nfsrv_unlock().
583 * First, check to see if we need to wait for an update lock.
586 NFSLOCKV4ROOTMUTEX();
587 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK)
588 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
589 NFSV4ROOTLOCKMUTEXPTR, NULL);
591 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
592 NFSV4ROOTLOCKMUTEXPTR, NULL);
593 NFSUNLOCKV4ROOTMUTEX();
596 * If I got the lock, I can update the stable storage file.
597 * Done when the grace period is over or a client has long
600 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK;
601 if ((nfsrv_stablefirst.nsf_flags &
602 (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
603 nfsrv_updatestable(p);
606 * If at least one client has long since expired, search
607 * the client list for them, write a REVOKE record on the
608 * stable storage file and then remove them from the client
611 if (nfsrv_stablefirst.nsf_flags & NFSNSF_EXPIREDCLIENT) {
612 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_EXPIREDCLIENT;
613 for (i = 0; i < NFSCLIENTHASHSIZE; i++) {
614 LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash,
616 if (clp->lc_flags & LCL_EXPIREIT) {
617 if (!LIST_EMPTY(&clp->lc_open) ||
618 !LIST_EMPTY(&clp->lc_deleg))
619 nfsrv_writestable(clp->lc_id,
620 clp->lc_idlen, NFSNST_REVOKE, p);
621 nfsrv_cleanclient(clp, p);
622 nfsrv_freedeleglist(&clp->lc_deleg);
623 nfsrv_freedeleglist(&clp->lc_olddeleg);
624 LIST_REMOVE(clp, lc_hash);
625 nfsrv_zapclient(clp, p);
630 NFSLOCKV4ROOTMUTEX();
631 nfsv4_unlock(&nfsv4rootfs_lock, 1);
632 NFSUNLOCKV4ROOTMUTEX();
635 * If we didn't get the lock, we need to get a refcnt,
636 * which also checks for and waits for the lock.
638 NFSLOCKV4ROOTMUTEX();
639 nfsv4_getref(&nfsv4rootfs_lock, NULL,
640 NFSV4ROOTLOCKMUTEXPTR, NULL);
641 NFSUNLOCKV4ROOTMUTEX();
645 * If flagged, search for open owners that haven't had any opens
648 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) {
649 nfsrv_throwawayopens(p);
653 save_fsid.val[0] = save_fsid.val[1] = 0;
654 cur_fsid.val[0] = cur_fsid.val[1] = 0;
656 /* If taglen < 0, there was a parsing error in nfsd_getminorvers(). */
662 (void) nfsm_strtom(nd, tag, taglen);
663 NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED);
664 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
665 if (minorvers != NFSV4_MINORVERSION && minorvers != NFSV41_MINORVERSION)
666 nd->nd_repstat = NFSERR_MINORVERMISMATCH;
670 numops = fxdr_unsigned(int, *tl);
672 * Loop around doing the sub ops.
673 * vp - is an unlocked vnode pointer for the CFH
674 * savevp - is an unlocked vnode pointer for the SAVEDFH
675 * (at some future date, it might turn out to be more appropriate
676 * to keep the file handles instead of vnode pointers?)
677 * savevpnes and vpnes - are the export flags for the above.
679 for (i = 0; i < numops; i++) {
680 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
681 NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED);
683 op = fxdr_unsigned(int, *tl);
684 NFSD_DEBUG(4, "op=%d\n", op);
685 if (op < NFSV4OP_ACCESS ||
686 (op >= NFSV4OP_NOPS && (nd->nd_flag & ND_NFSV41) == 0) ||
687 (op >= NFSV41_NOPS && (nd->nd_flag & ND_NFSV41) != 0)) {
688 nd->nd_repstat = NFSERR_OPILLEGAL;
689 *repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL);
690 *repp = nfsd_errmap(nd);
699 nd->nd_flag |= ND_LASTOP;
702 * Check for a referral on the current FH and, if so, return
703 * NFSERR_MOVED for all ops that allow it, except Getattr.
705 if (vp != NULL && op != NFSV4OP_GETATTR &&
706 nfsv4root_getreferral(vp, NULL, 0) != NULL &&
707 nfsrv_errmoved(op)) {
708 nd->nd_repstat = NFSERR_MOVED;
709 *repp = nfsd_errmap(nd);
715 * For NFSv4.1, check for a Sequence Operation being first
716 * or one of the other allowed operations by itself.
718 if ((nd->nd_flag & ND_NFSV41) != 0) {
719 if (i != 0 && op == NFSV4OP_SEQUENCE)
720 nd->nd_repstat = NFSERR_SEQUENCEPOS;
721 else if (i == 0 && op != NFSV4OP_SEQUENCE &&
722 op != NFSV4OP_EXCHANGEID &&
723 op != NFSV4OP_CREATESESSION &&
724 op != NFSV4OP_BINDCONNTOSESS &&
725 op != NFSV4OP_DESTROYCLIENTID &&
726 op != NFSV4OP_DESTROYSESSION)
727 nd->nd_repstat = NFSERR_OPNOTINSESS;
728 else if (i != 0 && op0 != NFSV4OP_SEQUENCE)
729 nd->nd_repstat = NFSERR_NOTONLYOP;
730 if (nd->nd_repstat != 0) {
731 *repp = nfsd_errmap(nd);
739 * If over flood level, reply NFSERR_RESOURCE, if at the first
740 * Op. (Since a client recovery from NFSERR_RESOURCE can get
741 * really nasty for certain Op sequences, I'll play it safe
742 * and only return the error at the beginning.) The cache
743 * will still function over flood level, but uses lots of
745 * If nfsrv_mallocmget_limit() returns True, the system is near
746 * to its limit for memory that malloc()/mget() can allocate.
748 if (i == 0 && (nd->nd_rp == NULL ||
749 nd->nd_rp->rc_refcnt == 0) &&
750 (nfsrv_mallocmget_limit() ||
751 nfsrc_tcpsavedreplies > nfsrc_floodlevel)) {
752 if (nfsrc_tcpsavedreplies > nfsrc_floodlevel)
753 printf("nfsd server cache flooded, try "
754 "increasing vfs.nfsd.tcphighwater\n");
755 nd->nd_repstat = NFSERR_RESOURCE;
756 *repp = nfsd_errmap(nd);
757 if (op == NFSV4OP_SETATTR) {
759 * Setattr replies require a bitmap.
760 * even for errors like these.
762 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
768 if (nfsv4_opflag[op].savereply)
769 nd->nd_flag |= ND_SAVEREPLY;
770 NFSINCRGLOBAL(newnfsstats.srvrpccnt[nd->nd_procnum]);
773 error = nfsrv_mtofh(nd, &fh);
777 nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
779 /* For now, allow this for non-export FHs */
780 if (!nd->nd_repstat) {
784 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
789 case NFSV4OP_PUTPUBFH:
791 nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
794 nd->nd_repstat = NFSERR_NOFILEHANDLE;
795 if (!nd->nd_repstat) {
799 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
804 case NFSV4OP_PUTROOTFH:
806 nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp,
808 if (!nd->nd_repstat) {
812 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
817 nd->nd_repstat = NFSERR_NOFILEHANDLE;
820 if (vp && NFSVNO_EXPORTED(&vpnes)) {
822 /* If vp == savevp, a no-op */
829 save_fsid = cur_fsid;
832 nd->nd_repstat = NFSERR_NOFILEHANDLE;
835 case NFSV4OP_RESTOREFH:
838 /* If vp == savevp, a no-op */
844 cur_fsid = save_fsid;
847 nd->nd_repstat = NFSERR_RESTOREFH;
852 * Allow a Lookup, Getattr, GetFH, Secinfo on an
853 * non-exported directory if
854 * nfs_rootfhset. Do I need to allow any other Ops?
855 * (You can only have a non-exported vpnes if
856 * nfs_rootfhset is true. See nfsd_fhtovp())
857 * Allow AUTH_SYS to be used for file systems
858 * exported GSS only for certain Ops, to allow
859 * clients to do mounts more easily.
861 if (nfsv4_opflag[op].needscfh && vp) {
862 if (!NFSVNO_EXPORTED(&vpnes) &&
863 op != NFSV4OP_LOOKUP &&
864 op != NFSV4OP_GETATTR &&
865 op != NFSV4OP_GETFH &&
866 op != NFSV4OP_ACCESS &&
867 op != NFSV4OP_READLINK &&
868 op != NFSV4OP_SECINFO)
869 nd->nd_repstat = NFSERR_NOFILEHANDLE;
870 else if (nfsvno_testexp(nd, &vpnes) &&
871 op != NFSV4OP_LOOKUP &&
872 op != NFSV4OP_GETFH &&
873 op != NFSV4OP_GETATTR &&
874 op != NFSV4OP_SECINFO)
875 nd->nd_repstat = NFSERR_WRONGSEC;
876 if (nd->nd_repstat) {
877 if (op == NFSV4OP_SETATTR) {
879 * Setattr reply requires a bitmap
880 * even for errors like these.
882 NFSM_BUILD(tl, u_int32_t *,
889 if (nfsv4_opflag[op].retfh == 1) {
891 nd->nd_repstat = NFSERR_NOFILEHANDLE;
895 if (nfsv4_opflag[op].modifyfs)
896 vn_start_write(vp, &temp_mp, V_WAIT);
897 error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
898 &nvp, (fhandle_t *)fh.nfsrvfh_data, p, &vpnes);
899 if (!error && !nd->nd_repstat) {
900 if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) {
901 new_mp = nvp->v_mount;
902 if (cur_fsid.val[0] !=
903 new_mp->mnt_stat.f_fsid.val[0] ||
905 new_mp->mnt_stat.f_fsid.val[1]) {
906 /* crossed a server mount point */
907 nd->nd_repstat = nfsvno_checkexp(new_mp,
908 nd->nd_nam, &nes, &credanon);
910 nd->nd_repstat = nfsd_excred(nd,
912 if (credanon != NULL)
914 if (!nd->nd_repstat) {
916 cur_fsid = new_mp->mnt_stat.f_fsid;
919 /* Lookup ops return a locked vnode */
920 NFSVOPUNLOCK(nvp, 0);
922 if (!nd->nd_repstat) {
928 if (nfsv4_opflag[op].modifyfs)
929 vn_finished_write(temp_mp);
930 } else if (nfsv4_opflag[op].retfh == 2) {
931 if (vp == NULL || savevp == NULL) {
932 nd->nd_repstat = NFSERR_NOFILEHANDLE;
934 } else if (cur_fsid.val[0] != save_fsid.val[0] ||
935 cur_fsid.val[1] != save_fsid.val[1]) {
936 nd->nd_repstat = NFSERR_XDEV;
939 if (nfsv4_opflag[op].modifyfs)
940 vn_start_write(savevp, &temp_mp, V_WAIT);
941 if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
944 error = (*(nfsrv4_ops2[op]))(nd, isdgram,
945 savevp, vp, p, &savevpnes, &vpnes);
947 nd->nd_repstat = NFSERR_PERM;
948 if (nfsv4_opflag[op].modifyfs)
949 vn_finished_write(temp_mp);
951 if (nfsv4_opflag[op].retfh != 0)
952 panic("nfsrvd_compound");
953 if (nfsv4_opflag[op].needscfh) {
955 if (nfsv4_opflag[op].modifyfs)
956 vn_start_write(vp, &temp_mp,
958 if (NFSVOPLOCK(vp, nfsv4_opflag[op].lktype)
962 nd->nd_repstat = NFSERR_PERM;
964 nd->nd_repstat = NFSERR_NOFILEHANDLE;
965 if (op == NFSV4OP_SETATTR) {
967 * Setattr reply requires a
968 * bitmap even for errors like
971 NFSM_BUILD(tl, u_int32_t *,
977 if (nd->nd_repstat == 0)
978 error = (*(nfsrv4_ops0[op]))(nd,
979 isdgram, vp, p, &vpnes);
980 if (nfsv4_opflag[op].modifyfs)
981 vn_finished_write(temp_mp);
983 error = (*(nfsrv4_ops0[op]))(nd, isdgram,
989 if (error == EBADRPC || error == NFSERR_BADXDR) {
990 nd->nd_repstat = NFSERR_BADXDR;
992 nd->nd_repstat = error;
993 printf("nfsv4 comperr0=%d\n", error);
998 if (nd->nd_repstat) {
999 *repp = nfsd_errmap(nd);
1002 *repp = 0; /* NFS4_OK */
1007 if (error == EBADRPC || error == NFSERR_BADXDR)
1008 nd->nd_repstat = NFSERR_BADXDR;
1010 printf("nfsv4 comperr1=%d\n", error);
1013 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1017 *retopsp = txdr_unsigned(retops);
1023 NFSLOCKV4ROOTMUTEX();
1024 nfsv4_relref(&nfsv4rootfs_lock);
1025 NFSUNLOCKV4ROOTMUTEX();
1027 NFSEXITCODE2(0, nd);