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 /*
38 * Socket operations for use by the nfs server.
39 */
40
41 #include <fs/nfs/nfsport.h>
42
43 #include <security/mac/mac_framework.h>
44
45 extern struct nfsrvfh nfs_pubfh;
46 extern int nfs_pubfhset;
47 extern struct nfsv4lock nfsv4rootfs_lock;
48 extern int nfsrv_clienthashsize;
49 extern int nfsd_debuglevel;
50 extern int nfsrv_layouthighwater;
51 extern volatile int nfsrv_layoutcnt;
52 NFSV4ROOTLOCKMUTEX;
53 NFSSTATESPINLOCK;
54
55 VNET_DECLARE(struct nfsrv_stablefirst, nfsrv_stablefirst);
56 VNET_DECLARE(struct nfsclienthashhead *, nfsclienthash);
57 VNET_DECLARE(int, nfsrc_floodlevel);
58 VNET_DECLARE(int, nfsrc_tcpsavedreplies);
59 VNET_DECLARE(struct nfsrvfh, nfs_rootfh);
60 VNET_DECLARE(int, nfs_rootfhset);
61 VNET_DECLARE(struct nfsstatsv1 *, nfsstatsv1_p);
62
63 int (*nfsrv3_procs0[NFS_V3NPROCS])(struct nfsrv_descript *,
64 int, vnode_t , struct nfsexstuff *) = {
65 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
66 nfsrvd_getattr,
67 nfsrvd_setattr,
68 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
69 nfsrvd_access,
70 nfsrvd_readlink,
71 nfsrvd_read,
72 nfsrvd_write,
73 nfsrvd_create,
74 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
75 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
76 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
77 nfsrvd_remove,
78 nfsrvd_remove,
79 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
80 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
81 nfsrvd_readdir,
82 nfsrvd_readdirplus,
83 nfsrvd_statfs,
84 nfsrvd_fsinfo,
85 nfsrvd_pathconf,
86 nfsrvd_commit,
87 };
88
89 int (*nfsrv3_procs1[NFS_V3NPROCS])(struct nfsrv_descript *,
90 int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *) = {
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 nfsrvd_lookup,
95 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
96 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
97 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
98 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
99 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
100 nfsrvd_mkdir,
101 nfsrvd_symlink,
102 nfsrvd_mknod,
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 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
110 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
111 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
112 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
113 };
114
115 int (*nfsrv3_procs2[NFS_V3NPROCS])(struct nfsrv_descript *,
116 int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *) = {
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 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
128 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
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 nfsrvd_rename,
132 nfsrvd_link,
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 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
136 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
137 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
138 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
139 };
140
141 int (*nfsrv4_ops0[NFSV42_NOPS])(struct nfsrv_descript *,
142 int, vnode_t , struct nfsexstuff *) = {
143 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
144 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
145 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
146 nfsrvd_access,
147 nfsrvd_close,
148 nfsrvd_commit,
149 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
150 nfsrvd_delegpurge,
151 nfsrvd_delegreturn,
152 nfsrvd_getattr,
153 nfsrvd_getfh,
154 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
155 nfsrvd_lock,
156 nfsrvd_lockt,
157 nfsrvd_locku,
158 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
159 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
160 nfsrvd_verify,
161 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
162 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
163 nfsrvd_openconfirm,
164 nfsrvd_opendowngrade,
165 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
166 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
167 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
168 nfsrvd_read,
169 nfsrvd_readdirplus,
170 nfsrvd_readlink,
171 nfsrvd_remove,
172 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
173 nfsrvd_renew,
174 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
175 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
176 nfsrvd_secinfo,
177 nfsrvd_setattr,
178 nfsrvd_setclientid,
179 nfsrvd_setclientidcfrm,
180 nfsrvd_verify,
181 nfsrvd_write,
182 nfsrvd_releaselckown,
183 nfsrvd_notsupp,
184 nfsrvd_bindconnsess,
185 nfsrvd_exchangeid,
186 nfsrvd_createsession,
187 nfsrvd_destroysession,
188 nfsrvd_freestateid,
189 nfsrvd_notsupp,
190 nfsrvd_getdevinfo,
191 nfsrvd_notsupp,
192 nfsrvd_layoutcommit,
193 nfsrvd_layoutget,
194 nfsrvd_layoutreturn,
195 nfsrvd_secinfononame,
196 nfsrvd_sequence,
197 nfsrvd_notsupp,
198 nfsrvd_teststateid,
199 nfsrvd_notsupp,
200 nfsrvd_destroyclientid,
201 nfsrvd_reclaimcomplete,
202 nfsrvd_allocate,
203 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
204 nfsrvd_notsupp,
205 nfsrvd_deallocate,
206 nfsrvd_ioadvise,
207 nfsrvd_layouterror,
208 nfsrvd_layoutstats,
209 nfsrvd_notsupp,
210 nfsrvd_notsupp,
211 nfsrvd_notsupp,
212 nfsrvd_seek,
213 nfsrvd_notsupp,
214 nfsrvd_notsupp,
215 nfsrvd_getxattr,
216 nfsrvd_setxattr,
217 nfsrvd_listxattr,
218 nfsrvd_rmxattr,
219 };
220
221 int (*nfsrv4_ops1[NFSV42_NOPS])(struct nfsrv_descript *,
222 int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *) = {
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 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
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 nfsrvd_mknod,
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 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
235 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
236 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
237 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
238 nfsrvd_lookup,
239 nfsrvd_lookup,
240 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
241 nfsrvd_open,
242 nfsrvd_openattr,
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 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
296 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
297 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
298 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
299 };
300
301 int (*nfsrv4_ops2[NFSV42_NOPS])(struct nfsrv_descript *,
302 int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *) = {
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 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
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 nfsrvd_link,
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 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
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 nfsrvd_rename,
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 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
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 nfsrvd_copy_file_range,
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 nfsrvd_clone,
375 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
376 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
377 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
378 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
379 };
380
381 /*
382 * Static array that defines which nfs rpc's are nonidempotent
383 */
384 static int nfsrv_nonidempotent[NFS_V3NPROCS] = {
385 FALSE,
386 FALSE,
387 TRUE,
388 FALSE,
389 FALSE,
390 FALSE,
391 FALSE,
392 TRUE,
393 TRUE,
394 TRUE,
395 TRUE,
396 TRUE,
397 TRUE,
398 TRUE,
399 TRUE,
400 TRUE,
401 FALSE,
402 FALSE,
403 FALSE,
404 FALSE,
405 FALSE,
406 FALSE,
407 };
408
409 /*
410 * This static array indicates whether or not the RPC modifies the
411 * file system.
412 */
413 int nfsrv_writerpc[NFS_NPROCS] = { 0, 0, 1, 0, 0, 0, 0,
414 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
415 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
416
417 SYSCTL_DECL(_vfs_nfsd);
418 static int nfs_minminorv4 = NFSV4_MINORVERSION;
419 SYSCTL_INT(_vfs_nfsd, OID_AUTO, server_min_minorversion4, CTLFLAG_RWTUN,
420 &nfs_minminorv4, 0,
421 "The lowest minor version of NFSv4 handled by the server");
422
423 static int nfs_maxminorv4 = NFSV42_MINORVERSION;
424 SYSCTL_INT(_vfs_nfsd, OID_AUTO, server_max_minorversion4, CTLFLAG_RWTUN,
425 &nfs_maxminorv4, 0,
426 "The highest minor version of NFSv4 handled by the server");
427
428 /* local functions */
429 static void nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
430 u_char *tag, int taglen, u_int32_t minorvers);
431
432 /*
433 * This static array indicates which server procedures require the extra
434 * arguments to return the current file handle for V2, 3.
435 */
436 static int nfs_retfh[NFS_V3NPROCS] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1,
437 1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0 };
438
439 extern struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS];
440
441 static int nfsv3to4op[NFS_V3NPROCS] = {
442 NFSPROC_NULL,
443 NFSV4OP_GETATTR,
444 NFSV4OP_SETATTR,
445 NFSV4OP_LOOKUP,
446 NFSV4OP_ACCESS,
447 NFSV4OP_READLINK,
448 NFSV4OP_READ,
449 NFSV4OP_WRITE,
450 NFSV4OP_V3CREATE,
451 NFSV4OP_MKDIR,
452 NFSV4OP_SYMLINK,
453 NFSV4OP_MKNOD,
454 NFSV4OP_REMOVE,
455 NFSV4OP_RMDIR,
456 NFSV4OP_RENAME,
457 NFSV4OP_LINK,
458 NFSV4OP_READDIR,
459 NFSV4OP_READDIRPLUS,
460 NFSV4OP_FSSTAT,
461 NFSV4OP_FSINFO,
462 NFSV4OP_PATHCONF,
463 NFSV4OP_COMMIT,
464 };
465
466 static struct mtx nfsrvd_statmtx;
467 MTX_SYSINIT(nfsst, &nfsrvd_statmtx, "NFSstat", MTX_DEF);
468
469 static struct ucred *nfsrv_createrootcred(void);
470
471 static void
nfsrvd_statstart(int op,struct bintime * now)472 nfsrvd_statstart(int op, struct bintime *now)
473 {
474 if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
475 printf("%s: op %d invalid\n", __func__, op);
476 return;
477 }
478
479 mtx_lock(&nfsrvd_statmtx);
480 if (VNET(nfsstatsv1_p)->srvstartcnt ==
481 VNET(nfsstatsv1_p)->srvdonecnt) {
482 if (now != NULL)
483 VNET(nfsstatsv1_p)->busyfrom = *now;
484 else
485 binuptime(&VNET(nfsstatsv1_p)->busyfrom);
486
487 }
488 VNET(nfsstatsv1_p)->srvrpccnt[op]++;
489 VNET(nfsstatsv1_p)->srvstartcnt++;
490 mtx_unlock(&nfsrvd_statmtx);
491
492 }
493
494 static void
nfsrvd_statend(int op,uint64_t bytes,struct bintime * now,struct bintime * then)495 nfsrvd_statend(int op, uint64_t bytes, struct bintime *now,
496 struct bintime *then)
497 {
498 struct bintime dt, lnow;
499
500 if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
501 printf("%s: op %d invalid\n", __func__, op);
502 return;
503 }
504
505 if (now == NULL) {
506 now = &lnow;
507 binuptime(now);
508 }
509
510 mtx_lock(&nfsrvd_statmtx);
511
512 VNET(nfsstatsv1_p)->srvbytes[op] += bytes;
513 VNET(nfsstatsv1_p)->srvops[op]++;
514
515 if (then != NULL) {
516 dt = *now;
517 bintime_sub(&dt, then);
518 bintime_add(&VNET(nfsstatsv1_p)->srvduration[op], &dt);
519 }
520
521 dt = *now;
522 bintime_sub(&dt, &VNET(nfsstatsv1_p)->busyfrom);
523 bintime_add(&VNET(nfsstatsv1_p)->busytime, &dt);
524 VNET(nfsstatsv1_p)->busyfrom = *now;
525
526 VNET(nfsstatsv1_p)->srvdonecnt++;
527
528 mtx_unlock(&nfsrvd_statmtx);
529 }
530
531 /*
532 * Do an RPC. Basically, get the file handles translated to vnode pointers
533 * and then call the appropriate server routine. The server routines are
534 * split into groups, based on whether they use a file handle or file
535 * handle plus name or ...
536 * The NFS V4 Compound RPC is performed separately by nfsrvd_compound().
537 */
538 void
nfsrvd_dorpc(struct nfsrv_descript * nd,int isdgram,u_char * tag,int taglen,u_int32_t minorvers)539 nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, u_char *tag, int taglen,
540 u_int32_t minorvers)
541 {
542 int error = 0, lktype;
543 vnode_t vp;
544 mount_t mp;
545 struct nfsrvfh fh;
546 struct nfsexstuff nes;
547 struct mbuf *md;
548 char *dpos;
549
550 /*
551 * Save the current position in the request mbuf list so
552 * that a rollback to this location can be done upon an
553 * ERELOOKUP error return from an RPC function.
554 */
555 md = nd->nd_md;
556 dpos = nd->nd_dpos;
557 tryagain:
558 mp = NULL;
559
560 /*
561 * Get a locked vnode for the first file handle
562 */
563 if (!(nd->nd_flag & ND_NFSV4)) {
564 KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc"));
565 /*
566 * For NFSv3, if the malloc/mget allocation is near limits,
567 * return NFSERR_DELAY.
568 */
569 if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) {
570 nd->nd_repstat = NFSERR_DELAY;
571 vp = NULL;
572 } else {
573 error = nfsrv_mtofh(nd, &fh);
574 if (error) {
575 if (error != EBADRPC)
576 printf("nfs dorpc err1=%d\n", error);
577 nd->nd_repstat = NFSERR_GARBAGE;
578 goto out;
579 }
580 if (nd->nd_procnum == NFSPROC_READ ||
581 nd->nd_procnum == NFSPROC_WRITE ||
582 nd->nd_procnum == NFSPROC_READDIR ||
583 nd->nd_procnum == NFSPROC_READDIRPLUS ||
584 nd->nd_procnum == NFSPROC_READLINK ||
585 nd->nd_procnum == NFSPROC_GETATTR ||
586 nd->nd_procnum == NFSPROC_ACCESS ||
587 nd->nd_procnum == NFSPROC_FSSTAT ||
588 nd->nd_procnum == NFSPROC_FSINFO)
589 lktype = LK_SHARED;
590 else
591 lktype = LK_EXCLUSIVE;
592 if (nd->nd_flag & ND_PUBLOOKUP)
593 nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes,
594 &mp, nfsrv_writerpc[nd->nd_procnum], -1);
595 else
596 nfsd_fhtovp(nd, &fh, lktype, &vp, &nes,
597 &mp, nfsrv_writerpc[nd->nd_procnum], -1);
598 if (nd->nd_repstat == NFSERR_PROGNOTV4)
599 goto out;
600 }
601 }
602
603 /*
604 * For V2 and 3, set the ND_SAVEREPLY flag for the recent request
605 * cache, as required.
606 * For V4, nfsrvd_compound() does this.
607 */
608 if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum])
609 nd->nd_flag |= ND_SAVEREPLY;
610
611 nfsrvd_rephead(nd);
612 /*
613 * If nd_repstat is non-zero, just fill in the reply status
614 * to complete the RPC reply for V2. Otherwise, you must do
615 * the RPC.
616 */
617 if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) {
618 *nd->nd_errp = nfsd_errmap(nd);
619 nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], /*now*/ NULL);
620 nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
621 /*now*/ NULL, /*then*/ NULL);
622 vn_finished_write(mp);
623 goto out;
624 }
625
626 /*
627 * Now the procedure can be performed. For V4, nfsrvd_compound()
628 * works through the sub-rpcs, otherwise just call the procedure.
629 * The procedures are in three groups with different arguments.
630 * The group is indicated by the value in nfs_retfh[].
631 */
632 if (nd->nd_flag & ND_NFSV4) {
633 nfsrvd_compound(nd, isdgram, tag, taglen, minorvers);
634 } else {
635 struct bintime start_time;
636
637 binuptime(&start_time);
638 nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], &start_time);
639
640 if (nfs_retfh[nd->nd_procnum] == 1) {
641 if (vp)
642 NFSVOPUNLOCK(vp);
643 error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram,
644 vp, NULL, (fhandle_t *)fh.nfsrvfh_data, &nes);
645 } else if (nfs_retfh[nd->nd_procnum] == 2) {
646 error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram,
647 vp, NULL, &nes, NULL);
648 } else {
649 error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
650 vp, &nes);
651 }
652 vn_finished_write(mp);
653
654 if (error == 0 && nd->nd_repstat == ERELOOKUP) {
655 /*
656 * Roll back to the beginning of the RPC request
657 * arguments.
658 */
659 nd->nd_md = md;
660 nd->nd_dpos = dpos;
661
662 /* Free the junk RPC reply and redo the RPC. */
663 m_freem(nd->nd_mreq);
664 nd->nd_mreq = nd->nd_mb = NULL;
665 nd->nd_repstat = 0;
666 goto tryagain;
667 }
668
669 nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
670 /*now*/ NULL, /*then*/ &start_time);
671 }
672 if (error) {
673 if (error != EBADRPC)
674 printf("nfs dorpc err2=%d\n", error);
675 nd->nd_repstat = NFSERR_GARBAGE;
676 }
677 *nd->nd_errp = nfsd_errmap(nd);
678
679 /*
680 * Don't cache certain reply status values.
681 */
682 if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) &&
683 (nd->nd_repstat == NFSERR_GARBAGE ||
684 nd->nd_repstat == NFSERR_BADXDR ||
685 nd->nd_repstat == NFSERR_MOVED ||
686 nd->nd_repstat == NFSERR_DELAY ||
687 nd->nd_repstat == NFSERR_BADSEQID ||
688 nd->nd_repstat == NFSERR_RESOURCE ||
689 nd->nd_repstat == NFSERR_SERVERFAULT ||
690 nd->nd_repstat == NFSERR_STALECLIENTID ||
691 nd->nd_repstat == NFSERR_STALESTATEID ||
692 nd->nd_repstat == NFSERR_OLDSTATEID ||
693 nd->nd_repstat == NFSERR_BADSTATEID ||
694 nd->nd_repstat == NFSERR_GRACE ||
695 nd->nd_repstat == NFSERR_NOGRACE))
696 nd->nd_flag &= ~ND_SAVEREPLY;
697
698 out:
699 NFSEXITCODE2(0, nd);
700 }
701
702 /*
703 * Breaks down a compound RPC request and calls the server routines for
704 * the subprocedures.
705 * Some suboperations are performed directly here to simplify file handle<-->
706 * vnode pointer handling.
707 */
708 static void
nfsrvd_compound(struct nfsrv_descript * nd,int isdgram,u_char * tag,int taglen,u_int32_t minorvers)709 nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,
710 int taglen, u_int32_t minorvers)
711 {
712 int i, lktype, op, op0 = 0, rstat, statsinprog = 0;
713 u_int32_t *tl;
714 struct nfsclient *clp, *nclp;
715 int error = 0, igotlock, nextop, numops, savefhcnt;
716 u_int32_t retops = 0, *retopsp = NULL, *repp;
717 vnode_t vp, nvp, savevp;
718 struct nfsrvfh fh;
719 mount_t new_mp, temp_mp = NULL;
720 struct ucred *credanon, *rootcred, *savecred;
721 struct nfsexstuff nes, vpnes, savevpnes;
722 fsid_t cur_fsid, save_fsid;
723 static u_int64_t compref = 0;
724 struct bintime start_time;
725 struct thread *p;
726 struct mbuf *mb, *md;
727 char *bpos, *dpos;
728 int bextpg, bextpgsiz;
729
730 p = curthread;
731 rootcred = savecred = NULL;
732
733 /* Check for and optionally clear the no space flags for DSs. */
734 nfsrv_checknospc();
735
736 NFSVNO_EXINIT(&vpnes);
737 NFSVNO_EXINIT(&savevpnes);
738 /*
739 * Put the seq# of the current compound RPC in nfsrv_descript.
740 * (This is used by nfsrv_checkgetattr(), to see if the write
741 * delegation was created by the same compound RPC as the one
742 * with that Getattr in it.)
743 * Don't worry about the 64bit number wrapping around. It ain't
744 * gonna happen before this server gets shut down/rebooted.
745 */
746 nd->nd_compref = compref++;
747
748 /*
749 * Check for and optionally get a lock on the root. This lock means that
750 * no nfsd will be fiddling with the V4 file system and state stuff. It
751 * is required when the V4 root is being changed, the stable storage
752 * restart file is being updated, or callbacks are being done.
753 * When any of the nfsd are processing an NFSv4 compound RPC, they must
754 * either hold a reference count (nfs_usecnt) or the lock. When
755 * nfsrv_unlock() is called to release the lock, it can optionally
756 * also get a reference count, which saves the need for a call to
757 * nfsrv_getref() after nfsrv_unlock().
758 */
759 /*
760 * First, check to see if we need to wait for an update lock.
761 */
762 igotlock = 0;
763 NFSLOCKV4ROOTMUTEX();
764 if (VNET(nfsrv_stablefirst).nsf_flags & NFSNSF_NEEDLOCK)
765 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
766 NFSV4ROOTLOCKMUTEXPTR, NULL);
767 else
768 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
769 NFSV4ROOTLOCKMUTEXPTR, NULL);
770 NFSUNLOCKV4ROOTMUTEX();
771 if (igotlock) {
772 /*
773 * If I got the lock, I can update the stable storage file.
774 * Done when the grace period is over or a client has long
775 * since expired.
776 */
777 VNET(nfsrv_stablefirst).nsf_flags &= ~NFSNSF_NEEDLOCK;
778 if ((VNET(nfsrv_stablefirst).nsf_flags &
779 (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
780 nfsrv_updatestable(p);
781
782 /*
783 * If at least one client has long since expired, search
784 * the client list for them, write a REVOKE record on the
785 * stable storage file and then remove them from the client
786 * list.
787 */
788 if (VNET(nfsrv_stablefirst).nsf_flags &
789 NFSNSF_EXPIREDCLIENT) {
790 VNET(nfsrv_stablefirst).nsf_flags &=
791 ~NFSNSF_EXPIREDCLIENT;
792 for (i = 0; i < nfsrv_clienthashsize; i++) {
793 LIST_FOREACH_SAFE(clp, &VNET(nfsclienthash)[i],
794 lc_hash, nclp) {
795 if (clp->lc_flags & LCL_EXPIREIT) {
796 if (!LIST_EMPTY(&clp->lc_open) ||
797 !LIST_EMPTY(&clp->lc_deleg))
798 nfsrv_writestable(clp->lc_id,
799 clp->lc_idlen, NFSNST_REVOKE, p);
800 nfsrv_cleanclient(clp, p, false, NULL);
801 nfsrv_freedeleglist(&clp->lc_deleg);
802 nfsrv_freedeleglist(&clp->lc_olddeleg);
803 LIST_REMOVE(clp, lc_hash);
804 nfsrv_zapclient(clp, p);
805 }
806 }
807 }
808 }
809 NFSLOCKV4ROOTMUTEX();
810 nfsv4_unlock(&nfsv4rootfs_lock, 1);
811 NFSUNLOCKV4ROOTMUTEX();
812 } else {
813 /*
814 * If we didn't get the lock, we need to get a refcnt,
815 * which also checks for and waits for the lock.
816 */
817 NFSLOCKV4ROOTMUTEX();
818 nfsv4_getref(&nfsv4rootfs_lock, NULL,
819 NFSV4ROOTLOCKMUTEXPTR, NULL);
820 NFSUNLOCKV4ROOTMUTEX();
821 }
822
823 /*
824 * If flagged, search for open owners that haven't had any opens
825 * for a long time.
826 */
827 if (VNET(nfsrv_stablefirst).nsf_flags & NFSNSF_NOOPENS) {
828 nfsrv_throwawayopens(p);
829 }
830
831 /* Do a CBLAYOUTRECALL callback if over the high water mark. */
832 if (nfsrv_layoutcnt > nfsrv_layouthighwater)
833 nfsrv_recalloldlayout(p);
834
835 savevp = vp = NULL;
836 save_fsid.val[0] = save_fsid.val[1] = 0;
837 cur_fsid.val[0] = cur_fsid.val[1] = 0;
838 nextop = -1;
839 savefhcnt = 0;
840
841 /* If taglen < 0, there was a parsing error in nfsd_getminorvers(). */
842 if (taglen < 0) {
843 error = EBADRPC;
844 goto nfsmout;
845 }
846
847 (void) nfsm_strtom(nd, tag, taglen);
848 NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED);
849 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
850 if ((minorvers != NFSV4_MINORVERSION &&
851 minorvers != NFSV41_MINORVERSION &&
852 minorvers != NFSV42_MINORVERSION) ||
853 minorvers < nfs_minminorv4 || minorvers > nfs_maxminorv4)
854 nd->nd_repstat = NFSERR_MINORVERMISMATCH;
855 if (nd->nd_repstat)
856 numops = 0;
857 else
858 numops = fxdr_unsigned(int, *tl);
859 /*
860 * Loop around doing the sub ops.
861 * vp - is an unlocked vnode pointer for the CFH
862 * savevp - is an unlocked vnode pointer for the SAVEDFH
863 * (at some future date, it might turn out to be more appropriate
864 * to keep the file handles instead of vnode pointers?)
865 * savevpnes and vpnes - are the export flags for the above.
866 */
867 for (i = 0; i < numops; i++) {
868 NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED);
869 if (savefhcnt > 0) {
870 op = NFSV4OP_SAVEFH;
871 *repp = txdr_unsigned(op);
872 savefhcnt--;
873 } else if (nextop == -1) {
874 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
875 *repp = *tl;
876 op = fxdr_unsigned(int, *tl);
877 } else {
878 op = nextop;
879 *repp = txdr_unsigned(op);
880 nextop = -1;
881 }
882 NFSD_DEBUG(4, "op=%d\n", op);
883 if (op < NFSV4OP_ACCESS || op >= NFSV42_NOPS ||
884 (op >= NFSV4OP_NOPS && (nd->nd_flag & ND_NFSV41) == 0) ||
885 (op >= NFSV41_NOPS && (nd->nd_flag & ND_NFSV42) == 0)) {
886 nd->nd_repstat = NFSERR_OPILLEGAL;
887 *repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL);
888 *repp = nfsd_errmap(nd);
889 retops++;
890 break;
891 } else {
892 repp++;
893 }
894
895 binuptime(&start_time);
896 nfsrvd_statstart(op, &start_time);
897 statsinprog = 1;
898
899 if (i == 0)
900 op0 = op;
901 if (i == numops - 1)
902 nd->nd_flag |= ND_LASTOP;
903
904 /*
905 * Check for a referral on the current FH and, if so, return
906 * NFSERR_MOVED for all ops that allow it, except Getattr.
907 */
908 if (vp != NULL && op != NFSV4OP_GETATTR &&
909 nfsv4root_getreferral(vp, NULL, 0) != NULL &&
910 nfsrv_errmoved(op)) {
911 nd->nd_repstat = NFSERR_MOVED;
912 *repp = nfsd_errmap(nd);
913 retops++;
914 break;
915 }
916
917 /*
918 * For NFSv4.1, check for a Sequence Operation being first
919 * or one of the other allowed operations by itself.
920 */
921 if ((nd->nd_flag & ND_NFSV41) != 0) {
922 if (i != 0 && op == NFSV4OP_SEQUENCE)
923 nd->nd_repstat = NFSERR_SEQUENCEPOS;
924 else if (i == 0 && op != NFSV4OP_SEQUENCE &&
925 op != NFSV4OP_EXCHANGEID &&
926 op != NFSV4OP_CREATESESSION &&
927 op != NFSV4OP_BINDCONNTOSESS &&
928 op != NFSV4OP_DESTROYCLIENTID &&
929 op != NFSV4OP_DESTROYSESSION)
930 nd->nd_repstat = NFSERR_OPNOTINSESS;
931 else if (i != 0 && op0 != NFSV4OP_SEQUENCE)
932 nd->nd_repstat = NFSERR_NOTONLYOP;
933 if (nd->nd_repstat != 0) {
934 *repp = nfsd_errmap(nd);
935 retops++;
936 break;
937 }
938 }
939
940 nd->nd_procnum = op;
941 /*
942 * If over flood level, reply NFSERR_RESOURCE, if at the first
943 * Op. (Since a client recovery from NFSERR_RESOURCE can get
944 * really nasty for certain Op sequences, I'll play it safe
945 * and only return the error at the beginning.) The cache
946 * will still function over flood level, but uses lots of
947 * mbufs.)
948 * If nfsrv_mallocmget_limit() returns True, the system is near
949 * to its limit for memory that malloc()/mget() can allocate.
950 */
951 if (i == 0 && (nd->nd_rp == NULL ||
952 nd->nd_rp->rc_refcnt == 0) &&
953 (nfsrv_mallocmget_limit() ||
954 VNET(nfsrc_tcpsavedreplies) >
955 VNET(nfsrc_floodlevel))) {
956 if (VNET(nfsrc_tcpsavedreplies) >
957 VNET(nfsrc_floodlevel))
958 printf("nfsd server cache flooded, try "
959 "increasing vfs.nfsd.tcphighwater\n");
960 nd->nd_repstat = NFSERR_RESOURCE;
961 *repp = nfsd_errmap(nd);
962 if (op == NFSV4OP_SETATTR) {
963 /*
964 * Setattr replies require a bitmap.
965 * even for errors like these.
966 */
967 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
968 *tl = 0;
969 }
970 retops++;
971 break;
972 }
973
974 /*
975 * Check for the case of SP4_MACH_CRED and an operation in
976 * the allow set. For these operations, replace nd_cred with
977 * root credentials so that the operation will not fail due
978 * to credentials.
979 * NB: ND_MACHCRED is set by Sequence when the ClientID
980 * specifies LCL_MACHCRED and the RPC is being performed
981 * via krb5i or krb5p using the machine principal.
982 */
983 if ((nd->nd_flag & ND_MACHCRED) != 0) {
984 if (NFSISSET_OPBIT(&nd->nd_allowops, op)) {
985 /* Replace nd_cred with root creds. */
986 if (rootcred == NULL)
987 rootcred = nfsrv_createrootcred();
988 if (savecred == NULL)
989 savecred = nd->nd_cred;
990 nd->nd_cred = rootcred;
991 } else if (savecred != NULL) {
992 nd->nd_cred = savecred;
993 savecred = NULL;
994 }
995 }
996
997 if (nfsv4_opflag[op].savereply)
998 nd->nd_flag |= ND_SAVEREPLY;
999 switch (op) {
1000 case NFSV4OP_PUTFH:
1001 error = nfsrv_mtofh(nd, &fh);
1002 if (error)
1003 goto nfsmout;
1004 if ((nd->nd_flag & ND_LASTOP) == 0) {
1005 /*
1006 * Pre-parse the next op#. If it is
1007 * SaveFH, count it and skip to the
1008 * next op#, if not the last op#.
1009 * nextop is used to determine if
1010 * NFSERR_WRONGSEC can be returned,
1011 * per RFC5661 Sec. 2.6.
1012 */
1013 do {
1014 NFSM_DISSECT(tl, uint32_t *,
1015 NFSX_UNSIGNED);
1016 nextop = fxdr_unsigned(int, *tl);
1017 if (nextop == NFSV4OP_SAVEFH &&
1018 i < numops - 1)
1019 savefhcnt++;
1020 } while (nextop == NFSV4OP_SAVEFH &&
1021 i < numops - 1);
1022 }
1023 if (!nd->nd_repstat)
1024 nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
1025 NULL, 0, nextop);
1026 /* For now, allow this for non-export FHs */
1027 if (!nd->nd_repstat) {
1028 if (vp)
1029 vrele(vp);
1030 vp = nvp;
1031 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
1032 NFSVOPUNLOCK(vp);
1033 vpnes = nes;
1034 } else if (nd->nd_repstat == ESTALE)
1035 nfsrv_freestrandedstate(&fh);
1036 break;
1037 case NFSV4OP_PUTPUBFH:
1038 if (nfs_pubfhset) {
1039 if ((nd->nd_flag & ND_LASTOP) == 0) {
1040 /*
1041 * Pre-parse the next op#. If it is
1042 * SaveFH, count it and skip to the
1043 * next op#, if not the last op#.
1044 * nextop is used to determine if
1045 * NFSERR_WRONGSEC can be returned,
1046 * per RFC5661 Sec. 2.6.
1047 */
1048 do {
1049 NFSM_DISSECT(tl, uint32_t *,
1050 NFSX_UNSIGNED);
1051 nextop = fxdr_unsigned(int,
1052 *tl);
1053 if (nextop == NFSV4OP_SAVEFH &&
1054 i < numops - 1)
1055 savefhcnt++;
1056 } while (nextop == NFSV4OP_SAVEFH &&
1057 i < numops - 1);
1058 }
1059 nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
1060 &nes, NULL, 0, nextop);
1061 } else
1062 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1063 if (!nd->nd_repstat) {
1064 if (vp)
1065 vrele(vp);
1066 vp = nvp;
1067 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
1068 NFSVOPUNLOCK(vp);
1069 vpnes = nes;
1070 }
1071 break;
1072 case NFSV4OP_PUTROOTFH:
1073 if (VNET(nfs_rootfhset)) {
1074 if ((nd->nd_flag & ND_LASTOP) == 0) {
1075 /*
1076 * Pre-parse the next op#. If it is
1077 * SaveFH, count it and skip to the
1078 * next op#, if not the last op#.
1079 * nextop is used to determine if
1080 * NFSERR_WRONGSEC can be returned,
1081 * per RFC5661 Sec. 2.6.
1082 */
1083 do {
1084 NFSM_DISSECT(tl, uint32_t *,
1085 NFSX_UNSIGNED);
1086 nextop = fxdr_unsigned(int,
1087 *tl);
1088 if (nextop == NFSV4OP_SAVEFH &&
1089 i < numops - 1)
1090 savefhcnt++;
1091 } while (nextop == NFSV4OP_SAVEFH &&
1092 i < numops - 1);
1093 }
1094 nfsd_fhtovp(nd, &VNET(nfs_rootfh),
1095 LK_SHARED, &nvp, &nes, NULL, 0, nextop);
1096 if (!nd->nd_repstat) {
1097 if (vp)
1098 vrele(vp);
1099 vp = nvp;
1100 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
1101 NFSVOPUNLOCK(vp);
1102 vpnes = nes;
1103 }
1104 } else
1105 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1106 break;
1107 case NFSV4OP_SAVEFH:
1108 if (vp && NFSVNO_EXPORTED(&vpnes)) {
1109 nd->nd_repstat = 0;
1110 /* If vp == savevp, a no-op */
1111 if (vp != savevp) {
1112 if (savevp)
1113 vrele(savevp);
1114 vref(vp);
1115 savevp = vp;
1116 savevpnes = vpnes;
1117 save_fsid = cur_fsid;
1118 }
1119 if ((nd->nd_flag & ND_CURSTATEID) != 0) {
1120 nd->nd_savedcurstateid =
1121 nd->nd_curstateid;
1122 nd->nd_flag |= ND_SAVEDCURSTATEID;
1123 }
1124 } else {
1125 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1126 }
1127 break;
1128 case NFSV4OP_RESTOREFH:
1129 if (savevp) {
1130 if ((nd->nd_flag & ND_LASTOP) == 0) {
1131 /*
1132 * Pre-parse the next op#. If it is
1133 * SaveFH, count it and skip to the
1134 * next op#, if not the last op#.
1135 * nextop is used to determine if
1136 * NFSERR_WRONGSEC can be returned,
1137 * per RFC5661 Sec. 2.6.
1138 */
1139 do {
1140 NFSM_DISSECT(tl, uint32_t *,
1141 NFSX_UNSIGNED);
1142 nextop = fxdr_unsigned(int,
1143 *tl);
1144 if (nextop == NFSV4OP_SAVEFH &&
1145 i < numops - 1)
1146 savefhcnt++;
1147 } while (nextop == NFSV4OP_SAVEFH &&
1148 i < numops - 1);
1149 }
1150 nd->nd_repstat = 0;
1151 /* If vp == savevp, a no-op */
1152 if (vp != savevp) {
1153 if (nfsrv_checkwrongsec(nd, nextop,
1154 savevp->v_type))
1155 nd->nd_repstat =
1156 nfsvno_testexp(nd,
1157 &savevpnes);
1158 if (nd->nd_repstat == 0) {
1159 vref(savevp);
1160 vrele(vp);
1161 vp = savevp;
1162 vpnes = savevpnes;
1163 cur_fsid = save_fsid;
1164 }
1165 }
1166 if (nd->nd_repstat == 0 &&
1167 (nd->nd_flag & ND_SAVEDCURSTATEID) != 0) {
1168 nd->nd_curstateid =
1169 nd->nd_savedcurstateid;
1170 nd->nd_flag |= ND_CURSTATEID;
1171 }
1172 } else {
1173 nd->nd_repstat = NFSERR_RESTOREFH;
1174 }
1175 break;
1176 default:
1177 /*
1178 * Allow a Lookup, Getattr, GetFH, Secinfo on an
1179 * non-exported directory if
1180 * nfs_rootfhset. Do I need to allow any other Ops?
1181 * (You can only have a non-exported vpnes if
1182 * nfs_rootfhset is true. See nfsd_fhtovp())
1183 * Allow AUTH_SYS to be used for file systems
1184 * exported GSS only for certain Ops, to allow
1185 * clients to do mounts more easily.
1186 */
1187 if (nfsv4_opflag[op].needscfh && vp) {
1188 if (!NFSVNO_EXPORTED(&vpnes) &&
1189 op != NFSV4OP_LOOKUP &&
1190 op != NFSV4OP_GETATTR &&
1191 op != NFSV4OP_GETFH &&
1192 op != NFSV4OP_ACCESS &&
1193 op != NFSV4OP_READLINK &&
1194 op != NFSV4OP_SECINFO &&
1195 op != NFSV4OP_SECINFONONAME)
1196 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1197 if (nd->nd_repstat) {
1198 if (op == NFSV4OP_SETATTR) {
1199 /*
1200 * Setattr reply requires a bitmap
1201 * even for errors like these.
1202 */
1203 NFSM_BUILD(tl, u_int32_t *,
1204 NFSX_UNSIGNED);
1205 *tl = 0;
1206 }
1207 break;
1208 }
1209 }
1210
1211 /*
1212 * Save the current positions in the mbuf lists so
1213 * that a rollback to this location can be done upon a
1214 * redo due to a ERELOOKUP return for a operation.
1215 */
1216 mb = nd->nd_mb;
1217 bpos = nd->nd_bpos;
1218 bextpg = nd->nd_bextpg;
1219 bextpgsiz = nd->nd_bextpgsiz;
1220 md = nd->nd_md;
1221 dpos = nd->nd_dpos;
1222 tryagain:
1223
1224 if (nfsv4_opflag[op].retfh == 1) {
1225 if (!vp) {
1226 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1227 break;
1228 }
1229 if (NFSVNO_EXPORTED(&vpnes) && (op == NFSV4OP_LOOKUP ||
1230 op == NFSV4OP_LOOKUPP || (op == NFSV4OP_OPEN &&
1231 vp->v_type == VDIR))) {
1232 /* Check for wrong security. */
1233 rstat = nfsvno_testexp(nd, &vpnes);
1234 if (rstat != 0) {
1235 nd->nd_repstat = rstat;
1236 break;
1237 }
1238 }
1239 vref(vp);
1240 if (nfsv4_opflag[op].modifyfs)
1241 vn_start_write(vp, &temp_mp, V_WAIT);
1242 error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
1243 &nvp, (fhandle_t *)fh.nfsrvfh_data, &vpnes);
1244 if (!error && !nd->nd_repstat) {
1245 if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) {
1246 new_mp = nvp->v_mount;
1247 if (fsidcmp(&cur_fsid, &new_mp->mnt_stat.f_fsid) != 0) {
1248 /* crossed a server mount point */
1249 nd->nd_repstat = nfsvno_checkexp(new_mp,
1250 nd->nd_nam, &nes, &credanon);
1251 if (!nd->nd_repstat)
1252 nd->nd_repstat = nfsd_excred(nd,
1253 &nes, credanon, true);
1254 if (credanon != NULL)
1255 crfree(credanon);
1256 if (!nd->nd_repstat) {
1257 vpnes = nes;
1258 cur_fsid = new_mp->mnt_stat.f_fsid;
1259 }
1260 }
1261 /* Lookup ops return a locked vnode */
1262 NFSVOPUNLOCK(nvp);
1263 }
1264 if (!nd->nd_repstat) {
1265 vrele(vp);
1266 vp = nvp;
1267 } else
1268 vrele(nvp);
1269 }
1270 if (nfsv4_opflag[op].modifyfs)
1271 vn_finished_write(temp_mp);
1272 } else if (nfsv4_opflag[op].retfh == 2) {
1273 if (vp == NULL || savevp == NULL) {
1274 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1275 break;
1276 } else if (fsidcmp(&cur_fsid, &save_fsid) != 0 &&
1277 op != NFSV4OP_COPY && op != NFSV4OP_CLONE) {
1278 nd->nd_repstat = NFSERR_XDEV;
1279 break;
1280 }
1281 if (nfsv4_opflag[op].modifyfs)
1282 vn_start_write(savevp, &temp_mp, V_WAIT);
1283 if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
1284 vref(vp);
1285 vref(savevp);
1286 error = (*(nfsrv4_ops2[op]))(nd, isdgram,
1287 savevp, vp, &savevpnes, &vpnes);
1288 } else
1289 nd->nd_repstat = NFSERR_PERM;
1290 if (nfsv4_opflag[op].modifyfs)
1291 vn_finished_write(temp_mp);
1292 } else {
1293 if (nfsv4_opflag[op].retfh != 0)
1294 panic("nfsrvd_compound");
1295 if (nfsv4_opflag[op].needscfh) {
1296 if (vp != NULL) {
1297 lktype = nfsv4_opflag[op].lktype;
1298 if (nfsv4_opflag[op].modifyfs) {
1299 vn_start_write(vp, &temp_mp,
1300 V_WAIT);
1301 if (op == NFSV4OP_WRITE &&
1302 MNT_SHARED_WRITES(temp_mp))
1303 lktype = LK_SHARED;
1304 }
1305 if (NFSVOPLOCK(vp, lktype) == 0)
1306 vref(vp);
1307 else
1308 nd->nd_repstat = NFSERR_PERM;
1309 } else {
1310 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1311 if (op == NFSV4OP_SETATTR) {
1312 /*
1313 * Setattr reply requires a
1314 * bitmap even for errors like
1315 * these.
1316 */
1317 NFSM_BUILD(tl, u_int32_t *,
1318 NFSX_UNSIGNED);
1319 *tl = 0;
1320 }
1321 break;
1322 }
1323 if (nd->nd_repstat == 0) {
1324 error = (*(nfsrv4_ops0[op]))(nd,
1325 isdgram, vp, &vpnes);
1326 if ((op == NFSV4OP_SECINFO ||
1327 op == NFSV4OP_SECINFONONAME) &&
1328 error == 0 && nd->nd_repstat == 0) {
1329 /*
1330 * Secinfo and Secinfo_no_name
1331 * consume the current FH.
1332 */
1333 vrele(vp);
1334 vp = NULL;
1335 }
1336 }
1337 if (nfsv4_opflag[op].modifyfs)
1338 vn_finished_write(temp_mp);
1339 } else {
1340 error = (*(nfsrv4_ops0[op]))(nd, isdgram,
1341 NULL, &vpnes);
1342 }
1343 }
1344 }
1345 if (error) {
1346 if (error == EBADRPC || error == NFSERR_BADXDR) {
1347 nd->nd_repstat = NFSERR_BADXDR;
1348 } else {
1349 nd->nd_repstat = error;
1350 printf("nfsv4 comperr0=%d\n", error);
1351 }
1352 error = 0;
1353 }
1354
1355 if (nd->nd_repstat == ERELOOKUP) {
1356 /*
1357 * Roll back to the beginning of the operation
1358 * arguments.
1359 */
1360 nd->nd_md = md;
1361 nd->nd_dpos = dpos;
1362
1363 /*
1364 * Trim off the bogus reply for this operation
1365 * and redo the operation.
1366 */
1367 nfsm_trimtrailing(nd, mb, bpos, bextpg, bextpgsiz);
1368 nd->nd_repstat = 0;
1369 nd->nd_flag |= ND_ERELOOKUP;
1370 goto tryagain;
1371 }
1372 nd->nd_flag &= ~ND_ERELOOKUP;
1373
1374 if (statsinprog != 0) {
1375 nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1376 /*then*/ &start_time);
1377 statsinprog = 0;
1378 }
1379
1380 retops++;
1381 if (nd->nd_repstat) {
1382 *repp = nfsd_errmap(nd);
1383 break;
1384 } else {
1385 *repp = 0; /* NFS4_OK */
1386 }
1387 }
1388 nfsmout:
1389 if (statsinprog != 0) {
1390 nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1391 /*then*/ &start_time);
1392 statsinprog = 0;
1393 }
1394 if (error) {
1395 if (error == EBADRPC || error == NFSERR_BADXDR)
1396 nd->nd_repstat = NFSERR_BADXDR;
1397 else
1398 printf("nfsv4 comperr1=%d\n", error);
1399 }
1400 if (taglen == -1) {
1401 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1402 *tl++ = 0;
1403 *tl = 0;
1404 } else {
1405 *retopsp = txdr_unsigned(retops);
1406 }
1407 if (vp)
1408 vrele(vp);
1409 if (savevp)
1410 vrele(savevp);
1411 if (savecred != NULL)
1412 nd->nd_cred = savecred;
1413 if (rootcred != NULL)
1414 crfree(rootcred);
1415 NFSLOCKV4ROOTMUTEX();
1416 nfsv4_relref(&nfsv4rootfs_lock);
1417 NFSUNLOCKV4ROOTMUTEX();
1418
1419 NFSEXITCODE2(0, nd);
1420 }
1421
1422 /* Create a credential for "root". */
1423 static struct ucred *
nfsrv_createrootcred(void)1424 nfsrv_createrootcred(void)
1425 {
1426 struct ucred *cr;
1427
1428 cr = crget();
1429 cr->cr_uid = cr->cr_ruid = cr->cr_svuid = UID_ROOT;
1430 crsetgroups_and_egid(cr, 0, NULL, GID_WHEEL);
1431 cr->cr_rgid = cr->cr_svgid = cr->cr_gid;
1432 cr->cr_prison = curthread->td_ucred->cr_prison;
1433 prison_hold(cr->cr_prison);
1434 #ifdef MAC
1435 mac_cred_associate_nfsd(cr);
1436 #endif
1437 return (cr);
1438 }
1439