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)) {
369 panic("nfsrvd_dorpc");
372 * For NFSv3, if the malloc/mget allocation is near limits,
373 * return NFSERR_DELAY.
375 if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) {
376 nd->nd_repstat = NFSERR_DELAY;
379 error = nfsrv_mtofh(nd, &fh);
381 if (error != EBADRPC)
382 printf("nfs dorpc err1=%d\n", error);
383 nd->nd_repstat = NFSERR_GARBAGE;
386 nes.nes_vfslocked = 0;
387 if (nd->nd_flag & ND_PUBLOOKUP)
388 nfsd_fhtovp(nd, &nfs_pubfh, &vp, &nes,
389 &mp, nfs_writerpc[nd->nd_procnum], p);
391 nfsd_fhtovp(nd, &fh, &vp, &nes,
392 &mp, nfs_writerpc[nd->nd_procnum], p);
393 if (nd->nd_repstat == NFSERR_PROGNOTV4)
399 * For V2 and 3, set the ND_SAVEREPLY flag for the recent request
400 * cache, as required.
401 * For V4, nfsrvd_compound() does this.
403 if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum])
404 nd->nd_flag |= ND_SAVEREPLY;
408 * If nd_repstat is non-zero, just fill in the reply status
409 * to complete the RPC reply for V2. Otherwise, you must do
412 if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) {
413 *nd->nd_errp = nfsd_errmap(nd);
414 NFSINCRGLOBAL(newnfsstats.srvrpccnt[nfsv3to4op[nd->nd_procnum]]);
416 if (nfs_writerpc[nd->nd_procnum])
418 if (nes.nes_vfslocked)
419 nfsvno_unlockvfs(mp);
425 * Now the procedure can be performed. For V4, nfsrvd_compound()
426 * works through the sub-rpcs, otherwise just call the procedure.
427 * The procedures are in three groups with different arguments.
428 * The group is indicated by the value in nfs_retfh[].
430 if (nd->nd_flag & ND_NFSV4) {
431 nfsrvd_compound(nd, isdgram, p);
433 if (nfs_retfh[nd->nd_procnum] == 1) {
435 NFSVOPUNLOCK(vp, 0, p);
436 error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram,
437 vp, NULL, (fhandle_t *)fh.nfsrvfh_data, p, &nes);
438 } else if (nfs_retfh[nd->nd_procnum] == 2) {
439 error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram,
440 vp, NULL, p, &nes, NULL);
442 error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
446 if (nfs_writerpc[nd->nd_procnum])
448 if (nes.nes_vfslocked)
449 nfsvno_unlockvfs(mp);
451 NFSINCRGLOBAL(newnfsstats.srvrpccnt[nfsv3to4op[nd->nd_procnum]]);
454 if (error != EBADRPC)
455 printf("nfs dorpc err2=%d\n", error);
456 nd->nd_repstat = NFSERR_GARBAGE;
458 *nd->nd_errp = nfsd_errmap(nd);
461 * Don't cache certain reply status values.
463 if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) &&
464 (nd->nd_repstat == NFSERR_GARBAGE ||
465 nd->nd_repstat == NFSERR_BADXDR ||
466 nd->nd_repstat == NFSERR_MOVED ||
467 nd->nd_repstat == NFSERR_DELAY ||
468 nd->nd_repstat == NFSERR_BADSEQID ||
469 nd->nd_repstat == NFSERR_RESOURCE ||
470 nd->nd_repstat == NFSERR_SERVERFAULT ||
471 nd->nd_repstat == NFSERR_STALECLIENTID ||
472 nd->nd_repstat == NFSERR_STALESTATEID ||
473 nd->nd_repstat == NFSERR_OLDSTATEID ||
474 nd->nd_repstat == NFSERR_BADSTATEID ||
475 nd->nd_repstat == NFSERR_GRACE ||
476 nd->nd_repstat == NFSERR_NOGRACE))
477 nd->nd_flag &= ~ND_SAVEREPLY;
481 * Breaks down a compound RPC request and calls the server routines for
483 * Some suboperations are performed directly here to simplify file handle<-->
484 * vnode pointer handling.
487 nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
492 struct nfsclient *clp, *nclp;
493 int numops, taglen = -1, error = 0, igotlock;
494 u_int32_t minorvers, retops = 0, *retopsp = NULL, *repp;
495 u_char tag[NFSV4_SMALLSTR + 1], *tagstr;
496 vnode_t vp, nvp, savevp;
499 struct ucred *credanon;
500 struct nfsexstuff nes, vpnes, savevpnes;
501 static u_int64_t compref = 0;
503 NFSVNO_EXINIT(&vpnes);
504 NFSVNO_EXINIT(&savevpnes);
506 * Put the seq# of the current compound RPC in nfsrv_descript.
507 * (This is used by nfsrv_checkgetattr(), to see if the write
508 * delegation was created by the same compound RPC as the one
509 * with that Getattr in it.)
510 * Don't worry about the 64bit number wrapping around. It ain't
511 * gonna happen before this server gets shut down/rebooted.
513 nd->nd_compref = compref++;
516 * Check for and optionally get a lock on the root. This lock means that
517 * no nfsd will be fiddling with the V4 file system and state stuff. It
518 * is required when the V4 root is being changed, the stable storage
519 * restart file is being updated, or callbacks are being done.
520 * When any of the nfsd are processing an NFSv4 compound RPC, they must
521 * either hold a reference count (nfs_usecnt) or the lock. When
522 * nfsrv_unlock() is called to release the lock, it can optionally
523 * also get a reference count, which saves the need for a call to
524 * nfsrv_getref() after nfsrv_unlock().
527 * First, check to see if we need to wait for an update lock.
530 NFSLOCKV4ROOTMUTEX();
531 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK)
532 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
533 NFSV4ROOTLOCKMUTEXPTR);
535 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
536 NFSV4ROOTLOCKMUTEXPTR);
537 NFSUNLOCKV4ROOTMUTEX();
539 NFSLOCKSTATE(); /* to avoid a race with */
540 NFSUNLOCKSTATE(); /* nfsrv_servertimer() */
542 * If I got the lock, I can update the stable storage file.
543 * Done when the grace period is over or a client has long
546 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK;
547 if ((nfsrv_stablefirst.nsf_flags &
548 (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
549 nfsrv_updatestable(p);
552 * If at least one client has long since expired, search
553 * the client list for them, write a REVOKE record on the
554 * stable storage file and then remove them from the client
557 if (nfsrv_stablefirst.nsf_flags & NFSNSF_EXPIREDCLIENT) {
558 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_EXPIREDCLIENT;
559 for (i = 0; i < NFSCLIENTHASHSIZE; i++) {
560 LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash,
562 if (clp->lc_flags & LCL_EXPIREIT) {
563 if (!LIST_EMPTY(&clp->lc_open) ||
564 !LIST_EMPTY(&clp->lc_deleg))
565 nfsrv_writestable(clp->lc_id,
566 clp->lc_idlen, NFSNST_REVOKE, p);
567 nfsrv_cleanclient(clp, p);
568 nfsrv_freedeleglist(&clp->lc_deleg);
569 nfsrv_freedeleglist(&clp->lc_olddeleg);
570 LIST_REMOVE(clp, lc_hash);
571 nfsrv_zapclient(clp, p);
576 NFSLOCKV4ROOTMUTEX();
577 nfsv4_unlock(&nfsv4rootfs_lock, 1);
578 NFSUNLOCKV4ROOTMUTEX();
581 * If we didn't get the lock, we need to get a refcnt,
582 * which also checks for and waits for the lock.
584 NFSLOCKV4ROOTMUTEX();
585 nfsv4_getref(&nfsv4rootfs_lock, NULL,
586 NFSV4ROOTLOCKMUTEXPTR);
587 NFSUNLOCKV4ROOTMUTEX();
591 * If flagged, search for open owners that haven't had any opens
594 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) {
595 nfsrv_throwawayopens(p);
599 savevpnes.nes_vfslocked = vpnes.nes_vfslocked = 0;
601 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
602 taglen = fxdr_unsigned(int, *tl);
607 if (taglen <= NFSV4_SMALLSTR)
610 tagstr = malloc(taglen + 1, M_TEMP, M_WAITOK);
611 error = nfsrv_mtostr(nd, tagstr, taglen);
613 if (taglen > NFSV4_SMALLSTR)
614 free(tagstr, M_TEMP);
618 (void) nfsm_strtom(nd, tag, taglen);
619 if (taglen > NFSV4_SMALLSTR) {
620 free(tagstr, M_TEMP);
622 NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED);
623 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
624 minorvers = fxdr_unsigned(u_int32_t, *tl++);
625 if (minorvers != NFSV4_MINORVERSION)
626 nd->nd_repstat = NFSERR_MINORVERMISMATCH;
630 numops = fxdr_unsigned(int, *tl);
632 * Loop around doing the sub ops.
633 * vp - is an unlocked vnode pointer for the CFH
634 * savevp - is an unlocked vnode pointer for the SAVEDFH
635 * (at some future date, it might turn out to be more appropriate
636 * to keep the file handles instead of vnode pointers?)
637 * savevpnes and vpnes - are the export flags for the above.
639 for (i = 0; i < numops; i++) {
640 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
641 NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED);
643 op = fxdr_unsigned(int, *tl);
644 if (op < NFSV4OP_ACCESS || op >= NFSV4OP_NOPS) {
645 nd->nd_repstat = NFSERR_OPILLEGAL;
646 *repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL);
647 *repp = nfsd_errmap(nd);
655 * Check for a referral on the current FH and, if so, return
656 * NFSERR_MOVED for all ops that allow it, except Getattr.
658 if (vp != NULL && op != NFSV4OP_GETATTR &&
659 nfsv4root_getreferral(vp, NULL, 0) != NULL &&
660 nfsrv_errmoved(op)) {
661 nd->nd_repstat = NFSERR_MOVED;
662 *repp = nfsd_errmap(nd);
669 * If over flood level, reply NFSERR_RESOURCE, if at the first
670 * Op. (Since a client recovery from NFSERR_RESOURCE can get
671 * really nasty for certain Op sequences, I'll play it safe
672 * and only return the error at the beginning.) The cache
673 * will still function over flood level, but uses lots of
675 * If nfsrv_mallocmget_limit() returns True, the system is near
676 * to its limit for memory that malloc()/mget() can allocate.
678 if (i == 0 && nd->nd_rp->rc_refcnt == 0 &&
679 (nfsrv_mallocmget_limit() ||
680 nfsrc_tcpsavedreplies > nfsrc_floodlevel)) {
681 if (nfsrc_tcpsavedreplies > nfsrc_floodlevel) {
682 printf("nfsd server cache flooded, try to");
683 printf(" increase nfsrc_floodlevel\n");
685 nd->nd_repstat = NFSERR_RESOURCE;
686 *repp = nfsd_errmap(nd);
687 if (op == NFSV4OP_SETATTR) {
689 * Setattr replies require a bitmap.
690 * even for errors like these.
692 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
698 if (nfsv4_opflag[op].savereply)
699 nd->nd_flag |= ND_SAVEREPLY;
700 NFSINCRGLOBAL(newnfsstats.srvrpccnt[nd->nd_procnum]);
703 error = nfsrv_mtofh(nd, &fh);
706 if (!nd->nd_repstat) {
707 nes.nes_vfslocked = vpnes.nes_vfslocked;
708 nfsd_fhtovp(nd, &fh, &nvp, &nes, &mp,
711 /* For now, allow this for non-export FHs */
712 if (!nd->nd_repstat) {
716 NFSVOPUNLOCK(vp, 0, p);
720 case NFSV4OP_PUTPUBFH:
722 nes.nes_vfslocked = vpnes.nes_vfslocked;
723 nfsd_fhtovp(nd, &nfs_pubfh, &nvp,
726 nd->nd_repstat = NFSERR_NOFILEHANDLE;
728 if (!nd->nd_repstat) {
732 NFSVOPUNLOCK(vp, 0, p);
736 case NFSV4OP_PUTROOTFH:
738 nes.nes_vfslocked = vpnes.nes_vfslocked;
739 nfsd_fhtovp(nd, &nfs_rootfh, &nvp,
741 if (!nd->nd_repstat) {
745 NFSVOPUNLOCK(vp, 0, p);
748 } else if (nfsv4root_vp && nfsv4root_set) {
750 if (vpnes.nes_vfslocked)
751 nfsvno_unlockvfs(mp);
756 NFSVNO_SETEXRDONLY(&vpnes);
757 vpnes.nes_vfslocked = 0;
758 mp = vnode_mount(vp);
760 nd->nd_repstat = NFSERR_NOFILEHANDLE;
764 if (vp && NFSVNO_EXPORTED(&vpnes)) {
766 /* If vp == savevp, a no-op */
776 nd->nd_repstat = NFSERR_NOFILEHANDLE;
779 case NFSV4OP_RESTOREFH:
782 /* If vp == savevp, a no-op */
785 if (mp == NULL || savemp == NULL)
787 if (!savevpnes.nes_vfslocked &&
788 vpnes.nes_vfslocked) {
791 nfsvno_unlockvfs(mp);
792 } else if (savevpnes.nes_vfslocked &&
793 !vpnes.nes_vfslocked) {
796 savevpnes.nes_vfslocked = nfsvno_lockvfs(savemp);
804 nd->nd_repstat = NFSERR_RESTOREFH;
809 * Allow a Lookup, Getattr, GetFH, Secinfo on an
810 * non-exported directory if
811 * nfs_rootfhset. Do I need to allow any other Ops?
812 * (You can only have a non-exported vpnes if
813 * nfs_rootfhset is true. See nfsd_fhtovp())
814 * Allow AUTH_SYS to be used for file systems
815 * exported GSS only for certain Ops, to allow
816 * clients to do mounts more easily.
818 if (nfsv4_opflag[op].needscfh && vp) {
819 if (!NFSVNO_EXPORTED(&vpnes) &&
820 op != NFSV4OP_LOOKUP &&
821 op != NFSV4OP_GETATTR &&
822 op != NFSV4OP_GETFH &&
823 op != NFSV4OP_SECINFO)
824 nd->nd_repstat = NFSERR_NOFILEHANDLE;
825 else if (nfsvno_testexp(nd, &vpnes) &&
826 op != NFSV4OP_LOOKUP &&
827 op != NFSV4OP_GETFH &&
828 op != NFSV4OP_GETATTR &&
829 op != NFSV4OP_SECINFO)
830 nd->nd_repstat = NFSERR_WRONGSEC;
831 if (nd->nd_repstat) {
832 if (op == NFSV4OP_SETATTR) {
834 * Setattr reply requires a bitmap
835 * even for errors like these.
837 NFSM_BUILD(tl, u_int32_t *,
844 if (nfsv4_opflag[op].retfh == 1) {
846 nd->nd_repstat = NFSERR_NOFILEHANDLE;
850 if (nfsv4_opflag[op].modifyfs)
851 NFS_STARTWRITE(NULL, &mp);
852 error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
853 &nvp, (fhandle_t *)fh.nfsrvfh_data, p, &vpnes);
854 if (!error && !nd->nd_repstat) {
855 if (vfs_statfs(mp)->f_fsid.val[0] !=
856 vfs_statfs(vnode_mount(nvp))->f_fsid.val[0] ||
857 vfs_statfs(mp)->f_fsid.val[1] !=
858 vfs_statfs(vnode_mount(nvp))->f_fsid.val[1]) {
859 if (vfs_statfs(vnode_mount(nvp))->f_fsid.val[0] ==
861 vfs_statfs(vnode_mount(nvp))->f_fsid.val[1] ==
863 if (vpnes.nes_vfslocked) {
864 nfsvno_unlockvfs(mp);
865 vpnes.nes_vfslocked = 0;
867 NFSVNO_SETEXRDONLY(&vpnes);
868 mp = vnode_mount(nvp);
870 nd->nd_repstat = nfsvno_checkexp(vnode_mount(nvp),
871 nd->nd_nam, &nes, &credanon);
873 nd->nd_repstat = nfsd_excred(nd,
875 if (credanon != NULL)
877 if (!nd->nd_repstat) {
878 if (vpnes.nes_vfslocked)
879 nfsvno_unlockvfs(mp);
880 mp = vnode_mount(nvp);
882 vpnes.nes_vfslocked =
887 if (!nd->nd_repstat) {
892 if (nfsv4_opflag[op].modifyfs)
894 } else if (nfsv4_opflag[op].retfh == 2) {
895 if (vp == NULL || savevp == NULL) {
896 nd->nd_repstat = NFSERR_NOFILEHANDLE;
898 } else if (mp != savemp) {
899 nd->nd_repstat = NFSERR_XDEV;
904 if (nfsv4_opflag[op].modifyfs)
905 NFS_STARTWRITE(NULL, &mp);
906 NFSVOPLOCK(savevp, LK_EXCLUSIVE | LK_RETRY, p);
907 error = (*(nfsrv4_ops2[op]))(nd, isdgram, savevp,
908 vp, p, &savevpnes, &vpnes);
909 if (nfsv4_opflag[op].modifyfs)
912 if (nfsv4_opflag[op].retfh != 0)
913 panic("nfsrvd_compound");
914 if (nfsv4_opflag[op].needscfh) {
917 if (nfsv4_opflag[op].modifyfs)
918 NFS_STARTWRITE(NULL, &mp);
919 NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY, p);
921 nd->nd_repstat = NFSERR_NOFILEHANDLE;
922 if (op == NFSV4OP_SETATTR) {
924 * Setattr reply requires a bitmap
925 * even for errors like these.
927 NFSM_BUILD(tl, u_int32_t *,
933 error = (*(nfsrv4_ops0[op]))(nd, isdgram, vp,
935 if (nfsv4_opflag[op].modifyfs)
938 error = (*(nfsrv4_ops0[op]))(nd, isdgram,
944 if (error == EBADRPC || error == NFSERR_BADXDR) {
945 nd->nd_repstat = NFSERR_BADXDR;
947 nd->nd_repstat = error;
948 printf("nfsv4 comperr0=%d\n", error);
953 if (nd->nd_repstat) {
954 *repp = nfsd_errmap(nd);
957 *repp = 0; /* NFS4_OK */
962 if (error == EBADRPC || error == NFSERR_BADXDR)
963 nd->nd_repstat = NFSERR_BADXDR;
965 printf("nfsv4 comperr1=%d\n", error);
968 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
972 *retopsp = txdr_unsigned(retops);
974 if (mp && vpnes.nes_vfslocked)
975 nfsvno_unlockvfs(mp);
980 NFSLOCKV4ROOTMUTEX();
981 nfsv4_relref(&nfsv4rootfs_lock);
982 NFSUNLOCKV4ROOTMUTEX();