1 /*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Rick Macklem at The University of Guelph.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 */
35
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
38
39 /*
40 * Socket operations for use by the nfs server.
41 */
42
43 #include <fs/nfs/nfsport.h>
44
45 extern struct nfsstatsv1 nfsstatsv1;
46 extern struct nfsrvfh nfs_pubfh, nfs_rootfh;
47 extern int nfs_pubfhset, nfs_rootfhset;
48 extern struct nfsv4lock nfsv4rootfs_lock;
49 extern struct nfsrv_stablefirst nfsrv_stablefirst;
50 extern struct nfsclienthashhead *nfsclienthash;
51 extern int nfsrv_clienthashsize;
52 extern int nfsrc_floodlevel, nfsrc_tcpsavedreplies;
53 extern int nfsd_debuglevel;
54 extern int nfsrv_layouthighwater;
55 extern volatile int nfsrv_layoutcnt;
56 NFSV4ROOTLOCKMUTEX;
57 NFSSTATESPINLOCK;
58
59 int (*nfsrv3_procs0[NFS_V3NPROCS])(struct nfsrv_descript *,
60 int, vnode_t , struct nfsexstuff *) = {
61 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
62 nfsrvd_getattr,
63 nfsrvd_setattr,
64 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
65 nfsrvd_access,
66 nfsrvd_readlink,
67 nfsrvd_read,
68 nfsrvd_write,
69 nfsrvd_create,
70 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
71 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
72 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
73 nfsrvd_remove,
74 nfsrvd_remove,
75 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
76 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
77 nfsrvd_readdir,
78 nfsrvd_readdirplus,
79 nfsrvd_statfs,
80 nfsrvd_fsinfo,
81 nfsrvd_pathconf,
82 nfsrvd_commit,
83 };
84
85 int (*nfsrv3_procs1[NFS_V3NPROCS])(struct nfsrv_descript *,
86 int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *) = {
87 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
88 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
89 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
90 nfsrvd_lookup,
91 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
92 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
93 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
94 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
95 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
96 nfsrvd_mkdir,
97 nfsrvd_symlink,
98 nfsrvd_mknod,
99 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
100 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
101 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
102 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
103 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
104 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
105 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
106 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
107 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
108 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
109 };
110
111 int (*nfsrv3_procs2[NFS_V3NPROCS])(struct nfsrv_descript *,
112 int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *) = {
113 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
114 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
115 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
116 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
117 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
118 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
119 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
120 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
121 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
122 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
123 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
124 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
125 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
126 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
127 nfsrvd_rename,
128 nfsrvd_link,
129 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
130 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
131 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
132 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
133 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
134 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
135 };
136
137 int (*nfsrv4_ops0[NFSV42_NOPS])(struct nfsrv_descript *,
138 int, vnode_t , struct nfsexstuff *) = {
139 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
140 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
141 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
142 nfsrvd_access,
143 nfsrvd_close,
144 nfsrvd_commit,
145 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
146 nfsrvd_delegpurge,
147 nfsrvd_delegreturn,
148 nfsrvd_getattr,
149 nfsrvd_getfh,
150 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
151 nfsrvd_lock,
152 nfsrvd_lockt,
153 nfsrvd_locku,
154 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
155 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
156 nfsrvd_verify,
157 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
158 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
159 nfsrvd_openconfirm,
160 nfsrvd_opendowngrade,
161 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
162 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
163 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
164 nfsrvd_read,
165 nfsrvd_readdirplus,
166 nfsrvd_readlink,
167 nfsrvd_remove,
168 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
169 nfsrvd_renew,
170 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
171 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
172 nfsrvd_secinfo,
173 nfsrvd_setattr,
174 nfsrvd_setclientid,
175 nfsrvd_setclientidcfrm,
176 nfsrvd_verify,
177 nfsrvd_write,
178 nfsrvd_releaselckown,
179 nfsrvd_notsupp,
180 nfsrvd_bindconnsess,
181 nfsrvd_exchangeid,
182 nfsrvd_createsession,
183 nfsrvd_destroysession,
184 nfsrvd_freestateid,
185 nfsrvd_notsupp,
186 nfsrvd_getdevinfo,
187 nfsrvd_notsupp,
188 nfsrvd_layoutcommit,
189 nfsrvd_layoutget,
190 nfsrvd_layoutreturn,
191 nfsrvd_notsupp,
192 nfsrvd_sequence,
193 nfsrvd_notsupp,
194 nfsrvd_teststateid,
195 nfsrvd_notsupp,
196 nfsrvd_destroyclientid,
197 nfsrvd_reclaimcomplete,
198 nfsrvd_allocate,
199 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
200 nfsrvd_notsupp,
201 nfsrvd_notsupp,
202 nfsrvd_ioadvise,
203 nfsrvd_layouterror,
204 nfsrvd_layoutstats,
205 nfsrvd_notsupp,
206 nfsrvd_notsupp,
207 nfsrvd_notsupp,
208 nfsrvd_seek,
209 nfsrvd_notsupp,
210 nfsrvd_notsupp,
211 nfsrvd_getxattr,
212 nfsrvd_setxattr,
213 nfsrvd_listxattr,
214 nfsrvd_rmxattr,
215 };
216
217 int (*nfsrv4_ops1[NFSV42_NOPS])(struct nfsrv_descript *,
218 int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *) = {
219 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
220 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
221 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
222 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
223 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
224 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
225 nfsrvd_mknod,
226 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
227 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
228 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
229 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
230 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
231 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
232 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
233 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
234 nfsrvd_lookup,
235 nfsrvd_lookup,
236 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
237 nfsrvd_open,
238 nfsrvd_openattr,
239 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
240 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
241 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
242 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
243 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
244 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
245 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
246 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
247 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
248 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
249 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
250 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
251 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
252 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
253 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
254 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
255 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
256 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
257 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
258 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
259 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
260 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
261 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
262 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
263 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
264 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
265 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
266 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
267 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
268 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
269 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
270 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
271 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
272 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
273 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
274 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
275 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
276 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
277 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
278 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
279 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
280 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
281 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
282 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
283 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
284 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
285 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
286 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
287 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
288 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
289 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
290 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
291 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
292 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
293 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
294 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
295 };
296
297 int (*nfsrv4_ops2[NFSV42_NOPS])(struct nfsrv_descript *,
298 int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *) = {
299 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
300 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
301 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
302 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
303 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
304 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
305 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
306 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
307 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
308 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
309 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
310 nfsrvd_link,
311 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
312 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
313 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
314 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
315 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
316 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
317 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
318 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
319 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
320 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
321 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
322 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
323 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
324 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
325 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
326 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
327 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
328 nfsrvd_rename,
329 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
330 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
331 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
332 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
333 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
334 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
335 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
336 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
337 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
338 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
339 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
340 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
341 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
342 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
343 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
344 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
345 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
346 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
347 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
348 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
349 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
350 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
351 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
352 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
353 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
354 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
355 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
356 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
357 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
358 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
359 nfsrvd_copy_file_range,
360 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
361 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
362 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
363 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
364 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
365 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
366 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
367 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
368 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
369 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
370 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
371 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
372 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
373 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
374 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
375 };
376
377 /*
378 * Static array that defines which nfs rpc's are nonidempotent
379 */
380 static int nfsrv_nonidempotent[NFS_V3NPROCS] = {
381 FALSE,
382 FALSE,
383 TRUE,
384 FALSE,
385 FALSE,
386 FALSE,
387 FALSE,
388 TRUE,
389 TRUE,
390 TRUE,
391 TRUE,
392 TRUE,
393 TRUE,
394 TRUE,
395 TRUE,
396 TRUE,
397 FALSE,
398 FALSE,
399 FALSE,
400 FALSE,
401 FALSE,
402 FALSE,
403 };
404
405 /*
406 * This static array indicates whether or not the RPC modifies the
407 * file system.
408 */
409 int nfsrv_writerpc[NFS_NPROCS] = { 0, 0, 1, 0, 0, 0, 0,
410 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
411 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
412
413 SYSCTL_DECL(_vfs_nfsd);
414 static int nfs_minminorv4 = NFSV4_MINORVERSION;
415 SYSCTL_INT(_vfs_nfsd, OID_AUTO, server_min_minorversion4, CTLFLAG_RWTUN,
416 &nfs_minminorv4, 0,
417 "The lowest minor version of NFSv4 handled by the server");
418
419 static int nfs_maxminorv4 = NFSV42_MINORVERSION;
420 SYSCTL_INT(_vfs_nfsd, OID_AUTO, server_max_minorversion4, CTLFLAG_RWTUN,
421 &nfs_maxminorv4, 0,
422 "The highest minor version of NFSv4 handled by the server");
423
424 /* local functions */
425 static void nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
426 u_char *tag, int taglen, u_int32_t minorvers);
427
428 /*
429 * This static array indicates which server procedures require the extra
430 * arguments to return the current file handle for V2, 3.
431 */
432 static int nfs_retfh[NFS_V3NPROCS] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1,
433 1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0 };
434
435 extern struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS];
436
437 static int nfsv3to4op[NFS_V3NPROCS] = {
438 NFSPROC_NULL,
439 NFSV4OP_GETATTR,
440 NFSV4OP_SETATTR,
441 NFSV4OP_LOOKUP,
442 NFSV4OP_ACCESS,
443 NFSV4OP_READLINK,
444 NFSV4OP_READ,
445 NFSV4OP_WRITE,
446 NFSV4OP_V3CREATE,
447 NFSV4OP_MKDIR,
448 NFSV4OP_SYMLINK,
449 NFSV4OP_MKNOD,
450 NFSV4OP_REMOVE,
451 NFSV4OP_RMDIR,
452 NFSV4OP_RENAME,
453 NFSV4OP_LINK,
454 NFSV4OP_READDIR,
455 NFSV4OP_READDIRPLUS,
456 NFSV4OP_FSSTAT,
457 NFSV4OP_FSINFO,
458 NFSV4OP_PATHCONF,
459 NFSV4OP_COMMIT,
460 };
461
462 static struct mtx nfsrvd_statmtx;
463 MTX_SYSINIT(nfsst, &nfsrvd_statmtx, "NFSstat", MTX_DEF);
464
465 static void
466 nfsrvd_statstart(int op, struct bintime *now)
467 {
468 if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
469 printf("%s: op %d invalid\n", __func__, op);
470 return;
471 }
472
473 mtx_lock(&nfsrvd_statmtx);
474 if (nfsstatsv1.srvstartcnt == nfsstatsv1.srvdonecnt) {
475 if (now != NULL)
476 nfsstatsv1.busyfrom = *now;
477 else
478 binuptime(&nfsstatsv1.busyfrom);
479
480 }
481 nfsstatsv1.srvrpccnt[op]++;
482 nfsstatsv1.srvstartcnt++;
483 mtx_unlock(&nfsrvd_statmtx);
484
485 }
486
487 static void
488 nfsrvd_statend(int op, uint64_t bytes, struct bintime *now,
489 struct bintime *then)
490 {
491 struct bintime dt, lnow;
492
493 if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
494 printf("%s: op %d invalid\n", __func__, op);
495 return;
496 }
497
498 if (now == NULL) {
499 now = &lnow;
500 binuptime(now);
501 }
502
503 mtx_lock(&nfsrvd_statmtx);
504
505 nfsstatsv1.srvbytes[op] += bytes;
506 nfsstatsv1.srvops[op]++;
507
508 if (then != NULL) {
509 dt = *now;
510 bintime_sub(&dt, then);
511 bintime_add(&nfsstatsv1.srvduration[op], &dt);
512 }
513
514 dt = *now;
515 bintime_sub(&dt, &nfsstatsv1.busyfrom);
516 bintime_add(&nfsstatsv1.busytime, &dt);
517 nfsstatsv1.busyfrom = *now;
518
519 nfsstatsv1.srvdonecnt++;
520
521 mtx_unlock(&nfsrvd_statmtx);
522 }
523
524 /*
525 * Do an RPC. Basically, get the file handles translated to vnode pointers
526 * and then call the appropriate server routine. The server routines are
527 * split into groups, based on whether they use a file handle or file
528 * handle plus name or ...
529 * The NFS V4 Compound RPC is performed separately by nfsrvd_compound().
530 */
531 void
532 nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, u_char *tag, int taglen,
533 u_int32_t minorvers)
534 {
535 int error = 0, lktype;
536 vnode_t vp;
537 mount_t mp;
538 struct nfsrvfh fh;
539 struct nfsexstuff nes;
540 struct mbuf *md;
541 char *dpos;
542
543 /*
544 * Save the current position in the request mbuf list so
545 * that a rollback to this location can be done upon an
546 * ERELOOKUP error return from an RPC function.
547 */
548 md = nd->nd_md;
549 dpos = nd->nd_dpos;
550 tryagain:
551 mp = NULL;
552
553 /*
554 * Get a locked vnode for the first file handle
555 */
556 if (!(nd->nd_flag & ND_NFSV4)) {
557 KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc"));
558 /*
559 * For NFSv3, if the malloc/mget allocation is near limits,
560 * return NFSERR_DELAY.
561 */
562 if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) {
563 nd->nd_repstat = NFSERR_DELAY;
564 vp = NULL;
565 } else {
566 error = nfsrv_mtofh(nd, &fh);
567 if (error) {
568 if (error != EBADRPC)
569 printf("nfs dorpc err1=%d\n", error);
570 nd->nd_repstat = NFSERR_GARBAGE;
571 goto out;
572 }
573 if (nd->nd_procnum == NFSPROC_READ ||
574 nd->nd_procnum == NFSPROC_WRITE ||
575 nd->nd_procnum == NFSPROC_READDIR ||
576 nd->nd_procnum == NFSPROC_READDIRPLUS ||
577 nd->nd_procnum == NFSPROC_READLINK ||
578 nd->nd_procnum == NFSPROC_GETATTR ||
579 nd->nd_procnum == NFSPROC_ACCESS ||
580 nd->nd_procnum == NFSPROC_FSSTAT ||
581 nd->nd_procnum == NFSPROC_FSINFO)
582 lktype = LK_SHARED;
583 else
584 lktype = LK_EXCLUSIVE;
585 if (nd->nd_flag & ND_PUBLOOKUP)
586 nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes,
587 &mp, nfsrv_writerpc[nd->nd_procnum]);
588 else
589 nfsd_fhtovp(nd, &fh, lktype, &vp, &nes,
590 &mp, nfsrv_writerpc[nd->nd_procnum]);
591 if (nd->nd_repstat == NFSERR_PROGNOTV4)
592 goto out;
593 }
594 }
595
596 /*
597 * For V2 and 3, set the ND_SAVEREPLY flag for the recent request
598 * cache, as required.
599 * For V4, nfsrvd_compound() does this.
600 */
601 if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum])
602 nd->nd_flag |= ND_SAVEREPLY;
603
604 nfsrvd_rephead(nd);
605 /*
606 * If nd_repstat is non-zero, just fill in the reply status
607 * to complete the RPC reply for V2. Otherwise, you must do
608 * the RPC.
609 */
610 if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) {
611 *nd->nd_errp = nfsd_errmap(nd);
612 nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], /*now*/ NULL);
613 nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
614 /*now*/ NULL, /*then*/ NULL);
615 vn_finished_write(mp);
616 goto out;
617 }
618
619 /*
620 * Now the procedure can be performed. For V4, nfsrvd_compound()
621 * works through the sub-rpcs, otherwise just call the procedure.
622 * The procedures are in three groups with different arguments.
623 * The group is indicated by the value in nfs_retfh[].
624 */
625 if (nd->nd_flag & ND_NFSV4) {
626 nfsrvd_compound(nd, isdgram, tag, taglen, minorvers);
627 } else {
628 struct bintime start_time;
629
630 binuptime(&start_time);
631 nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], &start_time);
632
633 if (nfs_retfh[nd->nd_procnum] == 1) {
634 if (vp)
635 NFSVOPUNLOCK(vp);
636 error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram,
637 vp, NULL, (fhandle_t *)fh.nfsrvfh_data, &nes);
638 } else if (nfs_retfh[nd->nd_procnum] == 2) {
639 error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram,
640 vp, NULL, &nes, NULL);
641 } else {
642 error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
643 vp, &nes);
644 }
645 vn_finished_write(mp);
646
647 if (error == 0 && nd->nd_repstat == ERELOOKUP) {
648 /*
649 * Roll back to the beginning of the RPC request
650 * arguments.
651 */
652 nd->nd_md = md;
653 nd->nd_dpos = dpos;
654
655 /* Free the junk RPC reply and redo the RPC. */
656 m_freem(nd->nd_mreq);
657 nd->nd_mreq = nd->nd_mb = NULL;
658 nd->nd_repstat = 0;
659 goto tryagain;
660 }
661
662 nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
663 /*now*/ NULL, /*then*/ &start_time);
664 }
665 if (error) {
666 if (error != EBADRPC)
667 printf("nfs dorpc err2=%d\n", error);
668 nd->nd_repstat = NFSERR_GARBAGE;
669 }
670 *nd->nd_errp = nfsd_errmap(nd);
671
672 /*
673 * Don't cache certain reply status values.
674 */
675 if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) &&
676 (nd->nd_repstat == NFSERR_GARBAGE ||
677 nd->nd_repstat == NFSERR_BADXDR ||
678 nd->nd_repstat == NFSERR_MOVED ||
679 nd->nd_repstat == NFSERR_DELAY ||
680 nd->nd_repstat == NFSERR_BADSEQID ||
681 nd->nd_repstat == NFSERR_RESOURCE ||
682 nd->nd_repstat == NFSERR_SERVERFAULT ||
683 nd->nd_repstat == NFSERR_STALECLIENTID ||
684 nd->nd_repstat == NFSERR_STALESTATEID ||
685 nd->nd_repstat == NFSERR_OLDSTATEID ||
686 nd->nd_repstat == NFSERR_BADSTATEID ||
687 nd->nd_repstat == NFSERR_GRACE ||
688 nd->nd_repstat == NFSERR_NOGRACE))
689 nd->nd_flag &= ~ND_SAVEREPLY;
690
691 out:
692 NFSEXITCODE2(0, nd);
693 }
694
695 /*
696 * Breaks down a compound RPC request and calls the server routines for
697 * the subprocedures.
698 * Some suboperations are performed directly here to simplify file handle<-->
699 * vnode pointer handling.
700 */
701 static void
702 nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,
703 int taglen, u_int32_t minorvers)
704 {
705 int i, lktype, op, op0 = 0, statsinprog = 0;
706 u_int32_t *tl;
707 struct nfsclient *clp, *nclp;
708 int numops, error = 0, igotlock;
709 u_int32_t retops = 0, *retopsp = NULL, *repp;
710 vnode_t vp, nvp, savevp;
711 struct nfsrvfh fh;
712 mount_t new_mp, temp_mp = NULL;
713 struct ucred *credanon;
714 struct nfsexstuff nes, vpnes, savevpnes;
715 fsid_t cur_fsid, save_fsid;
716 static u_int64_t compref = 0;
717 struct bintime start_time;
718 struct thread *p;
719 struct mbuf *mb, *md;
720 char *bpos, *dpos;
721 int bextpg, bextpgsiz;
722
723 p = curthread;
724
725 NFSVNO_EXINIT(&vpnes);
726 NFSVNO_EXINIT(&savevpnes);
727 /*
728 * Put the seq# of the current compound RPC in nfsrv_descript.
729 * (This is used by nfsrv_checkgetattr(), to see if the write
730 * delegation was created by the same compound RPC as the one
731 * with that Getattr in it.)
732 * Don't worry about the 64bit number wrapping around. It ain't
733 * gonna happen before this server gets shut down/rebooted.
734 */
735 nd->nd_compref = compref++;
736
737 /*
738 * Check for and optionally get a lock on the root. This lock means that
739 * no nfsd will be fiddling with the V4 file system and state stuff. It
740 * is required when the V4 root is being changed, the stable storage
741 * restart file is being updated, or callbacks are being done.
742 * When any of the nfsd are processing an NFSv4 compound RPC, they must
743 * either hold a reference count (nfs_usecnt) or the lock. When
744 * nfsrv_unlock() is called to release the lock, it can optionally
745 * also get a reference count, which saves the need for a call to
746 * nfsrv_getref() after nfsrv_unlock().
747 */
748 /*
749 * First, check to see if we need to wait for an update lock.
750 */
751 igotlock = 0;
752 NFSLOCKV4ROOTMUTEX();
753 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK)
754 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
755 NFSV4ROOTLOCKMUTEXPTR, NULL);
756 else
757 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
758 NFSV4ROOTLOCKMUTEXPTR, NULL);
759 NFSUNLOCKV4ROOTMUTEX();
760 if (igotlock) {
761 /*
762 * If I got the lock, I can update the stable storage file.
763 * Done when the grace period is over or a client has long
764 * since expired.
765 */
766 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK;
767 if ((nfsrv_stablefirst.nsf_flags &
768 (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
769 nfsrv_updatestable(p);
770
771 /*
772 * If at least one client has long since expired, search
773 * the client list for them, write a REVOKE record on the
774 * stable storage file and then remove them from the client
775 * list.
776 */
777 if (nfsrv_stablefirst.nsf_flags & NFSNSF_EXPIREDCLIENT) {
778 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_EXPIREDCLIENT;
779 for (i = 0; i < nfsrv_clienthashsize; i++) {
780 LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash,
781 nclp) {
782 if (clp->lc_flags & LCL_EXPIREIT) {
783 if (!LIST_EMPTY(&clp->lc_open) ||
784 !LIST_EMPTY(&clp->lc_deleg))
785 nfsrv_writestable(clp->lc_id,
786 clp->lc_idlen, NFSNST_REVOKE, p);
787 nfsrv_cleanclient(clp, p);
788 nfsrv_freedeleglist(&clp->lc_deleg);
789 nfsrv_freedeleglist(&clp->lc_olddeleg);
790 LIST_REMOVE(clp, lc_hash);
791 nfsrv_zapclient(clp, p);
792 }
793 }
794 }
795 }
796 NFSLOCKV4ROOTMUTEX();
797 nfsv4_unlock(&nfsv4rootfs_lock, 1);
798 NFSUNLOCKV4ROOTMUTEX();
799 } else {
800 /*
801 * If we didn't get the lock, we need to get a refcnt,
802 * which also checks for and waits for the lock.
803 */
804 NFSLOCKV4ROOTMUTEX();
805 nfsv4_getref(&nfsv4rootfs_lock, NULL,
806 NFSV4ROOTLOCKMUTEXPTR, NULL);
807 NFSUNLOCKV4ROOTMUTEX();
808 }
809
810 /*
811 * If flagged, search for open owners that haven't had any opens
812 * for a long time.
813 */
814 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) {
815 nfsrv_throwawayopens(p);
816 }
817
818 /* Do a CBLAYOUTRECALL callback if over the high water mark. */
819 if (nfsrv_layoutcnt > nfsrv_layouthighwater)
820 nfsrv_recalloldlayout(p);
821
822 savevp = vp = NULL;
823 save_fsid.val[0] = save_fsid.val[1] = 0;
824 cur_fsid.val[0] = cur_fsid.val[1] = 0;
825
826 /* If taglen < 0, there was a parsing error in nfsd_getminorvers(). */
827 if (taglen < 0) {
828 error = EBADRPC;
829 goto nfsmout;
830 }
831
832 (void) nfsm_strtom(nd, tag, taglen);
833 NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED);
834 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
835 if ((minorvers != NFSV4_MINORVERSION &&
836 minorvers != NFSV41_MINORVERSION &&
837 minorvers != NFSV42_MINORVERSION) ||
838 minorvers < nfs_minminorv4 || minorvers > nfs_maxminorv4)
839 nd->nd_repstat = NFSERR_MINORVERMISMATCH;
840 if (nd->nd_repstat)
841 numops = 0;
842 else
843 numops = fxdr_unsigned(int, *tl);
844 /*
845 * Loop around doing the sub ops.
846 * vp - is an unlocked vnode pointer for the CFH
847 * savevp - is an unlocked vnode pointer for the SAVEDFH
848 * (at some future date, it might turn out to be more appropriate
849 * to keep the file handles instead of vnode pointers?)
850 * savevpnes and vpnes - are the export flags for the above.
851 */
852 for (i = 0; i < numops; i++) {
853 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
854 NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED);
855 *repp = *tl;
856 op = fxdr_unsigned(int, *tl);
857 NFSD_DEBUG(4, "op=%d\n", op);
858 if (op < NFSV4OP_ACCESS || op >= NFSV42_NOPS ||
859 (op >= NFSV4OP_NOPS && (nd->nd_flag & ND_NFSV41) == 0) ||
860 (op >= NFSV41_NOPS && (nd->nd_flag & ND_NFSV42) == 0)) {
861 nd->nd_repstat = NFSERR_OPILLEGAL;
862 *repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL);
863 *repp = nfsd_errmap(nd);
864 retops++;
865 break;
866 } else {
867 repp++;
868 }
869
870 binuptime(&start_time);
871 nfsrvd_statstart(op, &start_time);
872 statsinprog = 1;
873
874 if (i == 0)
875 op0 = op;
876 if (i == numops - 1)
877 nd->nd_flag |= ND_LASTOP;
878
879 /*
880 * Check for a referral on the current FH and, if so, return
881 * NFSERR_MOVED for all ops that allow it, except Getattr.
882 */
883 if (vp != NULL && op != NFSV4OP_GETATTR &&
884 nfsv4root_getreferral(vp, NULL, 0) != NULL &&
885 nfsrv_errmoved(op)) {
886 nd->nd_repstat = NFSERR_MOVED;
887 *repp = nfsd_errmap(nd);
888 retops++;
889 break;
890 }
891
892 /*
893 * For NFSv4.1, check for a Sequence Operation being first
894 * or one of the other allowed operations by itself.
895 */
896 if ((nd->nd_flag & ND_NFSV41) != 0) {
897 if (i != 0 && op == NFSV4OP_SEQUENCE)
898 nd->nd_repstat = NFSERR_SEQUENCEPOS;
899 else if (i == 0 && op != NFSV4OP_SEQUENCE &&
900 op != NFSV4OP_EXCHANGEID &&
901 op != NFSV4OP_CREATESESSION &&
902 op != NFSV4OP_BINDCONNTOSESS &&
903 op != NFSV4OP_DESTROYCLIENTID &&
904 op != NFSV4OP_DESTROYSESSION)
905 nd->nd_repstat = NFSERR_OPNOTINSESS;
906 else if (i != 0 && op0 != NFSV4OP_SEQUENCE)
907 nd->nd_repstat = NFSERR_NOTONLYOP;
908 if (nd->nd_repstat != 0) {
909 *repp = nfsd_errmap(nd);
910 retops++;
911 break;
912 }
913 }
914
915 nd->nd_procnum = op;
916 /*
917 * If over flood level, reply NFSERR_RESOURCE, if at the first
918 * Op. (Since a client recovery from NFSERR_RESOURCE can get
919 * really nasty for certain Op sequences, I'll play it safe
920 * and only return the error at the beginning.) The cache
921 * will still function over flood level, but uses lots of
922 * mbufs.)
923 * If nfsrv_mallocmget_limit() returns True, the system is near
924 * to its limit for memory that malloc()/mget() can allocate.
925 */
926 if (i == 0 && (nd->nd_rp == NULL ||
927 nd->nd_rp->rc_refcnt == 0) &&
928 (nfsrv_mallocmget_limit() ||
929 nfsrc_tcpsavedreplies > nfsrc_floodlevel)) {
930 if (nfsrc_tcpsavedreplies > nfsrc_floodlevel)
931 printf("nfsd server cache flooded, try "
932 "increasing vfs.nfsd.tcphighwater\n");
933 nd->nd_repstat = NFSERR_RESOURCE;
934 *repp = nfsd_errmap(nd);
935 if (op == NFSV4OP_SETATTR) {
936 /*
937 * Setattr replies require a bitmap.
938 * even for errors like these.
939 */
940 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
941 *tl = 0;
942 }
943 retops++;
944 break;
945 }
946 if (nfsv4_opflag[op].savereply)
947 nd->nd_flag |= ND_SAVEREPLY;
948 switch (op) {
949 case NFSV4OP_PUTFH:
950 error = nfsrv_mtofh(nd, &fh);
951 if (error)
952 goto nfsmout;
953 if (!nd->nd_repstat)
954 nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
955 NULL, 0);
956 /* For now, allow this for non-export FHs */
957 if (!nd->nd_repstat) {
958 if (vp)
959 vrele(vp);
960 vp = nvp;
961 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
962 NFSVOPUNLOCK(vp);
963 vpnes = nes;
964 }
965 break;
966 case NFSV4OP_PUTPUBFH:
967 if (nfs_pubfhset)
968 nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
969 &nes, NULL, 0);
970 else
971 nd->nd_repstat = NFSERR_NOFILEHANDLE;
972 if (!nd->nd_repstat) {
973 if (vp)
974 vrele(vp);
975 vp = nvp;
976 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
977 NFSVOPUNLOCK(vp);
978 vpnes = nes;
979 }
980 break;
981 case NFSV4OP_PUTROOTFH:
982 if (nfs_rootfhset) {
983 nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp,
984 &nes, NULL, 0);
985 if (!nd->nd_repstat) {
986 if (vp)
987 vrele(vp);
988 vp = nvp;
989 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
990 NFSVOPUNLOCK(vp);
991 vpnes = nes;
992 }
993 } else
994 nd->nd_repstat = NFSERR_NOFILEHANDLE;
995 break;
996 case NFSV4OP_SAVEFH:
997 if (vp && NFSVNO_EXPORTED(&vpnes)) {
998 nd->nd_repstat = 0;
999 /* If vp == savevp, a no-op */
1000 if (vp != savevp) {
1001 if (savevp)
1002 vrele(savevp);
1003 VREF(vp);
1004 savevp = vp;
1005 savevpnes = vpnes;
1006 save_fsid = cur_fsid;
1007 }
1008 if ((nd->nd_flag & ND_CURSTATEID) != 0) {
1009 nd->nd_savedcurstateid =
1010 nd->nd_curstateid;
1011 nd->nd_flag |= ND_SAVEDCURSTATEID;
1012 }
1013 } else {
1014 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1015 }
1016 break;
1017 case NFSV4OP_RESTOREFH:
1018 if (savevp) {
1019 nd->nd_repstat = 0;
1020 /* If vp == savevp, a no-op */
1021 if (vp != savevp) {
1022 VREF(savevp);
1023 vrele(vp);
1024 vp = savevp;
1025 vpnes = savevpnes;
1026 cur_fsid = save_fsid;
1027 }
1028 if ((nd->nd_flag & ND_SAVEDCURSTATEID) != 0) {
1029 nd->nd_curstateid =
1030 nd->nd_savedcurstateid;
1031 nd->nd_flag |= ND_CURSTATEID;
1032 }
1033 } else {
1034 nd->nd_repstat = NFSERR_RESTOREFH;
1035 }
1036 break;
1037 default:
1038 /*
1039 * Allow a Lookup, Getattr, GetFH, Secinfo on an
1040 * non-exported directory if
1041 * nfs_rootfhset. Do I need to allow any other Ops?
1042 * (You can only have a non-exported vpnes if
1043 * nfs_rootfhset is true. See nfsd_fhtovp())
1044 * Allow AUTH_SYS to be used for file systems
1045 * exported GSS only for certain Ops, to allow
1046 * clients to do mounts more easily.
1047 */
1048 if (nfsv4_opflag[op].needscfh && vp) {
1049 if (!NFSVNO_EXPORTED(&vpnes) &&
1050 op != NFSV4OP_LOOKUP &&
1051 op != NFSV4OP_GETATTR &&
1052 op != NFSV4OP_GETFH &&
1053 op != NFSV4OP_ACCESS &&
1054 op != NFSV4OP_READLINK &&
1055 op != NFSV4OP_SECINFO)
1056 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1057 else if (nfsvno_testexp(nd, &vpnes) &&
1058 op != NFSV4OP_LOOKUP &&
1059 op != NFSV4OP_GETFH &&
1060 op != NFSV4OP_GETATTR &&
1061 op != NFSV4OP_SECINFO)
1062 nd->nd_repstat = NFSERR_WRONGSEC;
1063 if (nd->nd_repstat) {
1064 if (op == NFSV4OP_SETATTR) {
1065 /*
1066 * Setattr reply requires a bitmap
1067 * even for errors like these.
1068 */
1069 NFSM_BUILD(tl, u_int32_t *,
1070 NFSX_UNSIGNED);
1071 *tl = 0;
1072 }
1073 break;
1074 }
1075 }
1076
1077 /*
1078 * Save the current positions in the mbuf lists so
1079 * that a rollback to this location can be done upon a
1080 * redo due to a ERELOOKUP return for a operation.
1081 */
1082 mb = nd->nd_mb;
1083 bpos = nd->nd_bpos;
1084 bextpg = nd->nd_bextpg;
1085 bextpgsiz = nd->nd_bextpgsiz;
1086 md = nd->nd_md;
1087 dpos = nd->nd_dpos;
1088 tryagain:
1089
1090 if (nfsv4_opflag[op].retfh == 1) {
1091 if (!vp) {
1092 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1093 break;
1094 }
1095 VREF(vp);
1096 if (nfsv4_opflag[op].modifyfs)
1097 vn_start_write(vp, &temp_mp, V_WAIT);
1098 error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
1099 &nvp, (fhandle_t *)fh.nfsrvfh_data, &vpnes);
1100 if (!error && !nd->nd_repstat) {
1101 if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) {
1102 new_mp = nvp->v_mount;
1103 if (fsidcmp(&cur_fsid, &new_mp->mnt_stat.f_fsid) != 0) {
1104 /* crossed a server mount point */
1105 nd->nd_repstat = nfsvno_checkexp(new_mp,
1106 nd->nd_nam, &nes, &credanon);
1107 if (!nd->nd_repstat)
1108 nd->nd_repstat = nfsd_excred(nd,
1109 &nes, credanon);
1110 if (credanon != NULL)
1111 crfree(credanon);
1112 if (!nd->nd_repstat) {
1113 vpnes = nes;
1114 cur_fsid = new_mp->mnt_stat.f_fsid;
1115 }
1116 }
1117 /* Lookup ops return a locked vnode */
1118 NFSVOPUNLOCK(nvp);
1119 }
1120 if (!nd->nd_repstat) {
1121 vrele(vp);
1122 vp = nvp;
1123 } else
1124 vrele(nvp);
1125 }
1126 if (nfsv4_opflag[op].modifyfs)
1127 vn_finished_write(temp_mp);
1128 } else if (nfsv4_opflag[op].retfh == 2) {
1129 if (vp == NULL || savevp == NULL) {
1130 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1131 break;
1132 } else if (fsidcmp(&cur_fsid, &save_fsid) != 0) {
1133 nd->nd_repstat = NFSERR_XDEV;
1134 break;
1135 }
1136 if (nfsv4_opflag[op].modifyfs)
1137 vn_start_write(savevp, &temp_mp, V_WAIT);
1138 if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
1139 VREF(vp);
1140 VREF(savevp);
1141 error = (*(nfsrv4_ops2[op]))(nd, isdgram,
1142 savevp, vp, &savevpnes, &vpnes);
1143 } else
1144 nd->nd_repstat = NFSERR_PERM;
1145 if (nfsv4_opflag[op].modifyfs)
1146 vn_finished_write(temp_mp);
1147 } else {
1148 if (nfsv4_opflag[op].retfh != 0)
1149 panic("nfsrvd_compound");
1150 if (nfsv4_opflag[op].needscfh) {
1151 if (vp != NULL) {
1152 lktype = nfsv4_opflag[op].lktype;
1153 if (nfsv4_opflag[op].modifyfs) {
1154 vn_start_write(vp, &temp_mp,
1155 V_WAIT);
1156 if (op == NFSV4OP_WRITE &&
1157 MNT_SHARED_WRITES(temp_mp))
1158 lktype = LK_SHARED;
1159 }
1160 if (NFSVOPLOCK(vp, lktype) == 0)
1161 VREF(vp);
1162 else
1163 nd->nd_repstat = NFSERR_PERM;
1164 } else {
1165 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1166 if (op == NFSV4OP_SETATTR) {
1167 /*
1168 * Setattr reply requires a
1169 * bitmap even for errors like
1170 * these.
1171 */
1172 NFSM_BUILD(tl, u_int32_t *,
1173 NFSX_UNSIGNED);
1174 *tl = 0;
1175 }
1176 break;
1177 }
1178 if (nd->nd_repstat == 0)
1179 error = (*(nfsrv4_ops0[op]))(nd,
1180 isdgram, vp, &vpnes);
1181 if (nfsv4_opflag[op].modifyfs)
1182 vn_finished_write(temp_mp);
1183 } else {
1184 error = (*(nfsrv4_ops0[op]))(nd, isdgram,
1185 NULL, &vpnes);
1186 }
1187 }
1188 }
1189 if (error) {
1190 if (error == EBADRPC || error == NFSERR_BADXDR) {
1191 nd->nd_repstat = NFSERR_BADXDR;
1192 } else {
1193 nd->nd_repstat = error;
1194 printf("nfsv4 comperr0=%d\n", error);
1195 }
1196 error = 0;
1197 }
1198
1199 if (nd->nd_repstat == ERELOOKUP) {
1200 /*
1201 * Roll back to the beginning of the operation
1202 * arguments.
1203 */
1204 nd->nd_md = md;
1205 nd->nd_dpos = dpos;
1206
1207 /*
1208 * Trim off the bogus reply for this operation
1209 * and redo the operation.
1210 */
1211 nfsm_trimtrailing(nd, mb, bpos, bextpg, bextpgsiz);
1212 nd->nd_repstat = 0;
1213 nd->nd_flag |= ND_ERELOOKUP;
1214 goto tryagain;
1215 }
1216 nd->nd_flag &= ~ND_ERELOOKUP;
1217
1218 if (statsinprog != 0) {
1219 nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1220 /*then*/ &start_time);
1221 statsinprog = 0;
1222 }
1223
1224 retops++;
1225 if (nd->nd_repstat) {
1226 *repp = nfsd_errmap(nd);
1227 break;
1228 } else {
1229 *repp = 0; /* NFS4_OK */
1230 }
1231 }
1232 nfsmout:
1233 if (statsinprog != 0) {
1234 nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1235 /*then*/ &start_time);
1236 statsinprog = 0;
1237 }
1238 if (error) {
1239 if (error == EBADRPC || error == NFSERR_BADXDR)
1240 nd->nd_repstat = NFSERR_BADXDR;
1241 else
1242 printf("nfsv4 comperr1=%d\n", error);
1243 }
1244 if (taglen == -1) {
1245 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1246 *tl++ = 0;
1247 *tl = 0;
1248 } else {
1249 *retopsp = txdr_unsigned(retops);
1250 }
1251 if (vp)
1252 vrele(vp);
1253 if (savevp)
1254 vrele(savevp);
1255 NFSLOCKV4ROOTMUTEX();
1256 nfsv4_relref(&nfsv4rootfs_lock);
1257 NFSUNLOCKV4ROOTMUTEX();
1258
1259 NFSEXITCODE2(0, nd);
1260 }
Cache object: e5c76d6231cd010c9c6e35b8c5a143d3
|