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;
53 vnode_t nfsv4root_vp = NULL;
54 int nfsv4root_set = 0;
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[NFSV4OP_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,
180 int (*nfsrv4_ops1[NFSV4OP_NOPS])(struct nfsrv_descript *,
181 int, vnode_t , vnode_t *, fhandle_t *,
182 NFSPROC_T *, struct nfsexstuff *) = {
183 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
184 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
185 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
186 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
187 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
188 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
190 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
191 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
192 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
193 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
194 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
195 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
196 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
197 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
200 (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,
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,
216 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
217 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
218 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
219 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
220 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
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,
225 int (*nfsrv4_ops2[NFSV4OP_NOPS])(struct nfsrv_descript *,
226 int, vnode_t , vnode_t , NFSPROC_T *,
227 struct nfsexstuff *, struct nfsexstuff *) = {
228 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
229 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
230 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
231 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
232 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
233 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
234 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
235 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
236 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
237 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
238 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
240 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
241 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
242 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
243 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
244 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
245 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
246 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
247 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
248 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
249 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
250 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
251 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
252 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
253 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
254 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
255 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
256 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
258 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
259 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
260 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
261 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
262 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
263 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
264 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
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,
269 #endif /* !APPLEKEXT */
272 * Static array that defines which nfs rpc's are nonidempotent
274 static int nfsrv_nonidempotent[NFS_V3NPROCS] = {
300 * This static array indicates whether or not the RPC modifies the
303 static int nfs_writerpc[NFS_NPROCS] = { 0, 0, 1, 0, 0, 0, 0,
304 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
305 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
307 /* local functions */
308 static void nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
313 * This static array indicates which server procedures require the extra
314 * arguments to return the current file handle for V2, 3.
316 static int nfs_retfh[NFS_V3NPROCS] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1,
317 1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0 };
319 extern struct nfsv4_opflag nfsv4_opflag[NFSV4OP_NOPS];
321 static int nfsv3to4op[NFS_V3NPROCS] = {
347 * Do an RPC. Basically, get the file handles translated to vnode pointers
348 * and then call the appropriate server routine. The server routines are
349 * split into groups, based on whether they use a file handle or file
350 * handle plus name or ...
351 * The NFS V4 Compound RPC is performed separately by nfsrvd_compound().
354 nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram,
361 struct nfsexstuff nes;
364 * Get a locked vnode for the first file handle
366 if (!(nd->nd_flag & ND_NFSV4)) {
367 KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc"));
369 * For NFSv3, if the malloc/mget allocation is near limits,
370 * return NFSERR_DELAY.
372 if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) {
373 nd->nd_repstat = NFSERR_DELAY;
376 error = nfsrv_mtofh(nd, &fh);
378 if (error != EBADRPC)
379 printf("nfs dorpc err1=%d\n", error);
380 nd->nd_repstat = NFSERR_GARBAGE;
383 nes.nes_vfslocked = 0;
384 if (nd->nd_flag & ND_PUBLOOKUP)
385 nfsd_fhtovp(nd, &nfs_pubfh, &vp, &nes,
386 &mp, nfs_writerpc[nd->nd_procnum], p);
388 nfsd_fhtovp(nd, &fh, &vp, &nes,
389 &mp, nfs_writerpc[nd->nd_procnum], p);
390 if (nd->nd_repstat == NFSERR_PROGNOTV4)
396 * For V2 and 3, set the ND_SAVEREPLY flag for the recent request
397 * cache, as required.
398 * For V4, nfsrvd_compound() does this.
400 if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum])
401 nd->nd_flag |= ND_SAVEREPLY;
405 * If nd_repstat is non-zero, just fill in the reply status
406 * to complete the RPC reply for V2. Otherwise, you must do
409 if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) {
410 *nd->nd_errp = nfsd_errmap(nd);
411 NFSINCRGLOBAL(newnfsstats.srvrpccnt[nfsv3to4op[nd->nd_procnum]]);
413 if (nfs_writerpc[nd->nd_procnum])
415 if (nes.nes_vfslocked)
416 nfsvno_unlockvfs(mp);
422 * Now the procedure can be performed. For V4, nfsrvd_compound()
423 * works through the sub-rpcs, otherwise just call the procedure.
424 * The procedures are in three groups with different arguments.
425 * The group is indicated by the value in nfs_retfh[].
427 if (nd->nd_flag & ND_NFSV4) {
428 nfsrvd_compound(nd, isdgram, p);
430 if (nfs_retfh[nd->nd_procnum] == 1) {
432 NFSVOPUNLOCK(vp, 0, p);
433 error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram,
434 vp, NULL, (fhandle_t *)fh.nfsrvfh_data, p, &nes);
435 } else if (nfs_retfh[nd->nd_procnum] == 2) {
436 error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram,
437 vp, NULL, p, &nes, NULL);
439 error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
443 if (nfs_writerpc[nd->nd_procnum])
445 if (nes.nes_vfslocked)
446 nfsvno_unlockvfs(mp);
448 NFSINCRGLOBAL(newnfsstats.srvrpccnt[nfsv3to4op[nd->nd_procnum]]);
451 if (error != EBADRPC)
452 printf("nfs dorpc err2=%d\n", error);
453 nd->nd_repstat = NFSERR_GARBAGE;
455 *nd->nd_errp = nfsd_errmap(nd);
458 * Don't cache certain reply status values.
460 if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) &&
461 (nd->nd_repstat == NFSERR_GARBAGE ||
462 nd->nd_repstat == NFSERR_BADXDR ||
463 nd->nd_repstat == NFSERR_MOVED ||
464 nd->nd_repstat == NFSERR_DELAY ||
465 nd->nd_repstat == NFSERR_BADSEQID ||
466 nd->nd_repstat == NFSERR_RESOURCE ||
467 nd->nd_repstat == NFSERR_SERVERFAULT ||
468 nd->nd_repstat == NFSERR_STALECLIENTID ||
469 nd->nd_repstat == NFSERR_STALESTATEID ||
470 nd->nd_repstat == NFSERR_OLDSTATEID ||
471 nd->nd_repstat == NFSERR_BADSTATEID ||
472 nd->nd_repstat == NFSERR_GRACE ||
473 nd->nd_repstat == NFSERR_NOGRACE))
474 nd->nd_flag &= ~ND_SAVEREPLY;
478 * Breaks down a compound RPC request and calls the server routines for
480 * Some suboperations are performed directly here to simplify file handle<-->
481 * vnode pointer handling.
484 nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
489 struct nfsclient *clp, *nclp;
490 int numops, taglen = -1, error = 0, igotlock;
491 u_int32_t minorvers, retops = 0, *retopsp = NULL, *repp;
492 u_char tag[NFSV4_SMALLSTR + 1], *tagstr;
493 vnode_t vp, nvp, savevp;
496 struct ucred *credanon;
497 struct nfsexstuff nes, vpnes, savevpnes;
498 static u_int64_t compref = 0;
500 NFSVNO_EXINIT(&vpnes);
501 NFSVNO_EXINIT(&savevpnes);
503 * Put the seq# of the current compound RPC in nfsrv_descript.
504 * (This is used by nfsrv_checkgetattr(), to see if the write
505 * delegation was created by the same compound RPC as the one
506 * with that Getattr in it.)
507 * Don't worry about the 64bit number wrapping around. It ain't
508 * gonna happen before this server gets shut down/rebooted.
510 nd->nd_compref = compref++;
513 * Check for and optionally get a lock on the root. This lock means that
514 * no nfsd will be fiddling with the V4 file system and state stuff. It
515 * is required when the V4 root is being changed, the stable storage
516 * restart file is being updated, or callbacks are being done.
517 * When any of the nfsd are processing an NFSv4 compound RPC, they must
518 * either hold a reference count (nfs_usecnt) or the lock. When
519 * nfsrv_unlock() is called to release the lock, it can optionally
520 * also get a reference count, which saves the need for a call to
521 * nfsrv_getref() after nfsrv_unlock().
524 * First, check to see if we need to wait for an update lock.
527 NFSLOCKV4ROOTMUTEX();
528 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK)
529 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
530 NFSV4ROOTLOCKMUTEXPTR);
532 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
533 NFSV4ROOTLOCKMUTEXPTR);
534 NFSUNLOCKV4ROOTMUTEX();
537 * If I got the lock, I can update the stable storage file.
538 * Done when the grace period is over or a client has long
541 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK;
542 if ((nfsrv_stablefirst.nsf_flags &
543 (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
544 nfsrv_updatestable(p);
547 * If at least one client has long since expired, search
548 * the client list for them, write a REVOKE record on the
549 * stable storage file and then remove them from the client
552 if (nfsrv_stablefirst.nsf_flags & NFSNSF_EXPIREDCLIENT) {
553 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_EXPIREDCLIENT;
554 for (i = 0; i < NFSCLIENTHASHSIZE; i++) {
555 LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash,
557 if (clp->lc_flags & LCL_EXPIREIT) {
558 if (!LIST_EMPTY(&clp->lc_open) ||
559 !LIST_EMPTY(&clp->lc_deleg))
560 nfsrv_writestable(clp->lc_id,
561 clp->lc_idlen, NFSNST_REVOKE, p);
562 nfsrv_cleanclient(clp, p);
563 nfsrv_freedeleglist(&clp->lc_deleg);
564 nfsrv_freedeleglist(&clp->lc_olddeleg);
565 LIST_REMOVE(clp, lc_hash);
566 nfsrv_zapclient(clp, p);
571 NFSLOCKV4ROOTMUTEX();
572 nfsv4_unlock(&nfsv4rootfs_lock, 1);
573 NFSUNLOCKV4ROOTMUTEX();
576 * If we didn't get the lock, we need to get a refcnt,
577 * which also checks for and waits for the lock.
579 NFSLOCKV4ROOTMUTEX();
580 nfsv4_getref(&nfsv4rootfs_lock, NULL,
581 NFSV4ROOTLOCKMUTEXPTR);
582 NFSUNLOCKV4ROOTMUTEX();
586 * If flagged, search for open owners that haven't had any opens
589 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) {
590 nfsrv_throwawayopens(p);
594 savevpnes.nes_vfslocked = vpnes.nes_vfslocked = 0;
596 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
597 taglen = fxdr_unsigned(int, *tl);
602 if (taglen <= NFSV4_SMALLSTR)
605 tagstr = malloc(taglen + 1, M_TEMP, M_WAITOK);
606 error = nfsrv_mtostr(nd, tagstr, taglen);
608 if (taglen > NFSV4_SMALLSTR)
609 free(tagstr, M_TEMP);
613 (void) nfsm_strtom(nd, tag, taglen);
614 if (taglen > NFSV4_SMALLSTR) {
615 free(tagstr, M_TEMP);
617 NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED);
618 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
619 minorvers = fxdr_unsigned(u_int32_t, *tl++);
620 if (minorvers != NFSV4_MINORVERSION)
621 nd->nd_repstat = NFSERR_MINORVERMISMATCH;
625 numops = fxdr_unsigned(int, *tl);
627 * Loop around doing the sub ops.
628 * vp - is an unlocked vnode pointer for the CFH
629 * savevp - is an unlocked vnode pointer for the SAVEDFH
630 * (at some future date, it might turn out to be more appropriate
631 * to keep the file handles instead of vnode pointers?)
632 * savevpnes and vpnes - are the export flags for the above.
634 for (i = 0; i < numops; i++) {
635 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
636 NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED);
638 op = fxdr_unsigned(int, *tl);
639 if (op < NFSV4OP_ACCESS || op >= NFSV4OP_NOPS) {
640 nd->nd_repstat = NFSERR_OPILLEGAL;
641 *repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL);
642 *repp = nfsd_errmap(nd);
650 * Check for a referral on the current FH and, if so, return
651 * NFSERR_MOVED for all ops that allow it, except Getattr.
653 if (vp != NULL && op != NFSV4OP_GETATTR &&
654 nfsv4root_getreferral(vp, NULL, 0) != NULL &&
655 nfsrv_errmoved(op)) {
656 nd->nd_repstat = NFSERR_MOVED;
657 *repp = nfsd_errmap(nd);
664 * If over flood level, reply NFSERR_RESOURCE, if at the first
665 * Op. (Since a client recovery from NFSERR_RESOURCE can get
666 * really nasty for certain Op sequences, I'll play it safe
667 * and only return the error at the beginning.) The cache
668 * will still function over flood level, but uses lots of
670 * If nfsrv_mallocmget_limit() returns True, the system is near
671 * to its limit for memory that malloc()/mget() can allocate.
673 if (i == 0 && nd->nd_rp->rc_refcnt == 0 &&
674 (nfsrv_mallocmget_limit() ||
675 nfsrc_tcpsavedreplies > nfsrc_floodlevel)) {
676 if (nfsrc_tcpsavedreplies > nfsrc_floodlevel) {
677 printf("nfsd server cache flooded, try to");
678 printf(" increase nfsrc_floodlevel\n");
680 nd->nd_repstat = NFSERR_RESOURCE;
681 *repp = nfsd_errmap(nd);
682 if (op == NFSV4OP_SETATTR) {
684 * Setattr replies require a bitmap.
685 * even for errors like these.
687 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
693 if (nfsv4_opflag[op].savereply)
694 nd->nd_flag |= ND_SAVEREPLY;
695 NFSINCRGLOBAL(newnfsstats.srvrpccnt[nd->nd_procnum]);
698 error = nfsrv_mtofh(nd, &fh);
701 if (!nd->nd_repstat) {
702 nes.nes_vfslocked = vpnes.nes_vfslocked;
703 nfsd_fhtovp(nd, &fh, &nvp, &nes, &mp,
706 /* For now, allow this for non-export FHs */
707 if (!nd->nd_repstat) {
711 NFSVOPUNLOCK(vp, 0, p);
715 case NFSV4OP_PUTPUBFH:
717 nes.nes_vfslocked = vpnes.nes_vfslocked;
718 nfsd_fhtovp(nd, &nfs_pubfh, &nvp,
721 nd->nd_repstat = NFSERR_NOFILEHANDLE;
723 if (!nd->nd_repstat) {
727 NFSVOPUNLOCK(vp, 0, p);
731 case NFSV4OP_PUTROOTFH:
733 nes.nes_vfslocked = vpnes.nes_vfslocked;
734 nfsd_fhtovp(nd, &nfs_rootfh, &nvp,
736 if (!nd->nd_repstat) {
740 NFSVOPUNLOCK(vp, 0, p);
743 } else if (nfsv4root_vp && nfsv4root_set) {
745 if (vpnes.nes_vfslocked)
746 nfsvno_unlockvfs(mp);
751 NFSVNO_SETEXRDONLY(&vpnes);
752 vpnes.nes_vfslocked = 0;
753 mp = vnode_mount(vp);
755 nd->nd_repstat = NFSERR_NOFILEHANDLE;
759 if (vp && NFSVNO_EXPORTED(&vpnes)) {
761 /* If vp == savevp, a no-op */
771 nd->nd_repstat = NFSERR_NOFILEHANDLE;
774 case NFSV4OP_RESTOREFH:
777 /* If vp == savevp, a no-op */
780 if (mp == NULL || savemp == NULL)
782 if (!savevpnes.nes_vfslocked &&
783 vpnes.nes_vfslocked) {
786 nfsvno_unlockvfs(mp);
787 } else if (savevpnes.nes_vfslocked &&
788 !vpnes.nes_vfslocked) {
791 savevpnes.nes_vfslocked = nfsvno_lockvfs(savemp);
799 nd->nd_repstat = NFSERR_RESTOREFH;
804 * Allow a Lookup, Getattr, GetFH, Secinfo on an
805 * non-exported directory if
806 * nfs_rootfhset. Do I need to allow any other Ops?
807 * (You can only have a non-exported vpnes if
808 * nfs_rootfhset is true. See nfsd_fhtovp())
809 * Allow AUTH_SYS to be used for file systems
810 * exported GSS only for certain Ops, to allow
811 * clients to do mounts more easily.
813 if (nfsv4_opflag[op].needscfh && vp) {
814 if (!NFSVNO_EXPORTED(&vpnes) &&
815 op != NFSV4OP_LOOKUP &&
816 op != NFSV4OP_GETATTR &&
817 op != NFSV4OP_GETFH &&
818 op != NFSV4OP_SECINFO)
819 nd->nd_repstat = NFSERR_NOFILEHANDLE;
820 else if (nfsvno_testexp(nd, &vpnes) &&
821 op != NFSV4OP_LOOKUP &&
822 op != NFSV4OP_GETFH &&
823 op != NFSV4OP_GETATTR &&
824 op != NFSV4OP_SECINFO)
825 nd->nd_repstat = NFSERR_WRONGSEC;
826 if (nd->nd_repstat) {
827 if (op == NFSV4OP_SETATTR) {
829 * Setattr reply requires a bitmap
830 * even for errors like these.
832 NFSM_BUILD(tl, u_int32_t *,
839 if (nfsv4_opflag[op].retfh == 1) {
841 nd->nd_repstat = NFSERR_NOFILEHANDLE;
845 if (nfsv4_opflag[op].modifyfs)
846 NFS_STARTWRITE(NULL, &mp);
847 error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
848 &nvp, (fhandle_t *)fh.nfsrvfh_data, p, &vpnes);
849 if (!error && !nd->nd_repstat) {
850 if (vfs_statfs(mp)->f_fsid.val[0] !=
851 vfs_statfs(vnode_mount(nvp))->f_fsid.val[0] ||
852 vfs_statfs(mp)->f_fsid.val[1] !=
853 vfs_statfs(vnode_mount(nvp))->f_fsid.val[1]) {
854 if (vfs_statfs(vnode_mount(nvp))->f_fsid.val[0] ==
856 vfs_statfs(vnode_mount(nvp))->f_fsid.val[1] ==
858 if (vpnes.nes_vfslocked) {
859 nfsvno_unlockvfs(mp);
860 vpnes.nes_vfslocked = 0;
862 NFSVNO_SETEXRDONLY(&vpnes);
863 mp = vnode_mount(nvp);
865 nd->nd_repstat = nfsvno_checkexp(vnode_mount(nvp),
866 nd->nd_nam, &nes, &credanon);
868 nd->nd_repstat = nfsd_excred(nd,
870 if (credanon != NULL)
872 if (!nd->nd_repstat) {
873 if (vpnes.nes_vfslocked)
874 nfsvno_unlockvfs(mp);
875 mp = vnode_mount(nvp);
877 vpnes.nes_vfslocked =
882 if (!nd->nd_repstat) {
887 if (nfsv4_opflag[op].modifyfs)
889 } else if (nfsv4_opflag[op].retfh == 2) {
890 if (vp == NULL || savevp == NULL) {
891 nd->nd_repstat = NFSERR_NOFILEHANDLE;
893 } else if (mp != savemp) {
894 nd->nd_repstat = NFSERR_XDEV;
899 if (nfsv4_opflag[op].modifyfs)
900 NFS_STARTWRITE(NULL, &mp);
901 NFSVOPLOCK(savevp, LK_EXCLUSIVE | LK_RETRY, p);
902 error = (*(nfsrv4_ops2[op]))(nd, isdgram, savevp,
903 vp, p, &savevpnes, &vpnes);
904 if (nfsv4_opflag[op].modifyfs)
907 if (nfsv4_opflag[op].retfh != 0)
908 panic("nfsrvd_compound");
909 if (nfsv4_opflag[op].needscfh) {
912 if (nfsv4_opflag[op].modifyfs)
913 NFS_STARTWRITE(NULL, &mp);
914 NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY, p);
916 nd->nd_repstat = NFSERR_NOFILEHANDLE;
917 if (op == NFSV4OP_SETATTR) {
919 * Setattr reply requires a bitmap
920 * even for errors like these.
922 NFSM_BUILD(tl, u_int32_t *,
928 error = (*(nfsrv4_ops0[op]))(nd, isdgram, vp,
930 if (nfsv4_opflag[op].modifyfs)
933 error = (*(nfsrv4_ops0[op]))(nd, isdgram,
939 if (error == EBADRPC || error == NFSERR_BADXDR) {
940 nd->nd_repstat = NFSERR_BADXDR;
942 nd->nd_repstat = error;
943 printf("nfsv4 comperr0=%d\n", error);
948 if (nd->nd_repstat) {
949 *repp = nfsd_errmap(nd);
952 *repp = 0; /* NFS4_OK */
957 if (error == EBADRPC || error == NFSERR_BADXDR)
958 nd->nd_repstat = NFSERR_BADXDR;
960 printf("nfsv4 comperr1=%d\n", error);
963 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
967 *retopsp = txdr_unsigned(retops);
969 if (mp && vpnes.nes_vfslocked)
970 nfsvno_unlockvfs(mp);
975 NFSLOCKV4ROOTMUTEX();
976 nfsv4_relref(&nfsv4rootfs_lock);
977 NFSUNLOCKV4ROOTMUTEX();