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 NFSD_VNET_DECLARE(struct nfsrv_stablefirst, nfsrv_stablefirst);
56 NFSD_VNET_DECLARE(struct nfsclienthashhead *, nfsclienthash);
57 NFSD_VNET_DECLARE(int, nfsrc_floodlevel);
58 NFSD_VNET_DECLARE(int, nfsrc_tcpsavedreplies);
59 NFSD_VNET_DECLARE(struct nfsrvfh, nfs_rootfh);
60 NFSD_VNET_DECLARE(int, nfs_rootfhset);
61 NFSD_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 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
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 (NFSD_VNET(nfsstatsv1_p)->srvstartcnt ==
481 NFSD_VNET(nfsstatsv1_p)->srvdonecnt) {
482 if (now != NULL)
483 NFSD_VNET(nfsstatsv1_p)->busyfrom = *now;
484 else
485 binuptime(&NFSD_VNET(nfsstatsv1_p)->busyfrom);
486
487 }
488 NFSD_VNET(nfsstatsv1_p)->srvrpccnt[op]++;
489 NFSD_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 NFSD_VNET(nfsstatsv1_p)->srvbytes[op] += bytes;
513 NFSD_VNET(nfsstatsv1_p)->srvops[op]++;
514
515 if (then != NULL) {
516 dt = *now;
517 bintime_sub(&dt, then);
518 bintime_add(&NFSD_VNET(nfsstatsv1_p)->srvduration[op], &dt);
519 }
520
521 dt = *now;
522 bintime_sub(&dt, &NFSD_VNET(nfsstatsv1_p)->busyfrom);
523 bintime_add(&NFSD_VNET(nfsstatsv1_p)->busytime, &dt);
524 NFSD_VNET(nfsstatsv1_p)->busyfrom = *now;
525
526 NFSD_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 (NFSD_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 NFSD_VNET(nfsrv_stablefirst).nsf_flags &= ~NFSNSF_NEEDLOCK;
778 if ((NFSD_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 (NFSD_VNET(nfsrv_stablefirst).nsf_flags &
789 NFSNSF_EXPIREDCLIENT) {
790 NFSD_VNET(nfsrv_stablefirst).nsf_flags &=
791 ~NFSNSF_EXPIREDCLIENT;
792 for (i = 0; i < nfsrv_clienthashsize; i++) {
793 LIST_FOREACH_SAFE(clp, &NFSD_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 (NFSD_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 NFSD_VNET(nfsrc_tcpsavedreplies) >
955 NFSD_VNET(nfsrc_floodlevel))) {
956 if (NFSD_VNET(nfsrc_tcpsavedreplies) >
957 NFSD_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 }
1035 break;
1036 case NFSV4OP_PUTPUBFH:
1037 if (nfs_pubfhset) {
1038 if ((nd->nd_flag & ND_LASTOP) == 0) {
1039 /*
1040 * Pre-parse the next op#. If it is
1041 * SaveFH, count it and skip to the
1042 * next op#, if not the last op#.
1043 * nextop is used to determine if
1044 * NFSERR_WRONGSEC can be returned,
1045 * per RFC5661 Sec. 2.6.
1046 */
1047 do {
1048 NFSM_DISSECT(tl, uint32_t *,
1049 NFSX_UNSIGNED);
1050 nextop = fxdr_unsigned(int,
1051 *tl);
1052 if (nextop == NFSV4OP_SAVEFH &&
1053 i < numops - 1)
1054 savefhcnt++;
1055 } while (nextop == NFSV4OP_SAVEFH &&
1056 i < numops - 1);
1057 }
1058 nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
1059 &nes, NULL, 0, nextop);
1060 } else
1061 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1062 if (!nd->nd_repstat) {
1063 if (vp)
1064 vrele(vp);
1065 vp = nvp;
1066 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
1067 NFSVOPUNLOCK(vp);
1068 vpnes = nes;
1069 }
1070 break;
1071 case NFSV4OP_PUTROOTFH:
1072 if (NFSD_VNET(nfs_rootfhset)) {
1073 if ((nd->nd_flag & ND_LASTOP) == 0) {
1074 /*
1075 * Pre-parse the next op#. If it is
1076 * SaveFH, count it and skip to the
1077 * next op#, if not the last op#.
1078 * nextop is used to determine if
1079 * NFSERR_WRONGSEC can be returned,
1080 * per RFC5661 Sec. 2.6.
1081 */
1082 do {
1083 NFSM_DISSECT(tl, uint32_t *,
1084 NFSX_UNSIGNED);
1085 nextop = fxdr_unsigned(int,
1086 *tl);
1087 if (nextop == NFSV4OP_SAVEFH &&
1088 i < numops - 1)
1089 savefhcnt++;
1090 } while (nextop == NFSV4OP_SAVEFH &&
1091 i < numops - 1);
1092 }
1093 nfsd_fhtovp(nd, &NFSD_VNET(nfs_rootfh),
1094 LK_SHARED, &nvp, &nes, NULL, 0, nextop);
1095 if (!nd->nd_repstat) {
1096 if (vp)
1097 vrele(vp);
1098 vp = nvp;
1099 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
1100 NFSVOPUNLOCK(vp);
1101 vpnes = nes;
1102 }
1103 } else
1104 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1105 break;
1106 case NFSV4OP_SAVEFH:
1107 if (vp && NFSVNO_EXPORTED(&vpnes)) {
1108 nd->nd_repstat = 0;
1109 /* If vp == savevp, a no-op */
1110 if (vp != savevp) {
1111 if (savevp)
1112 vrele(savevp);
1113 VREF(vp);
1114 savevp = vp;
1115 savevpnes = vpnes;
1116 save_fsid = cur_fsid;
1117 }
1118 if ((nd->nd_flag & ND_CURSTATEID) != 0) {
1119 nd->nd_savedcurstateid =
1120 nd->nd_curstateid;
1121 nd->nd_flag |= ND_SAVEDCURSTATEID;
1122 }
1123 } else {
1124 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1125 }
1126 break;
1127 case NFSV4OP_RESTOREFH:
1128 if (savevp) {
1129 if ((nd->nd_flag & ND_LASTOP) == 0) {
1130 /*
1131 * Pre-parse the next op#. If it is
1132 * SaveFH, count it and skip to the
1133 * next op#, if not the last op#.
1134 * nextop is used to determine if
1135 * NFSERR_WRONGSEC can be returned,
1136 * per RFC5661 Sec. 2.6.
1137 */
1138 do {
1139 NFSM_DISSECT(tl, uint32_t *,
1140 NFSX_UNSIGNED);
1141 nextop = fxdr_unsigned(int,
1142 *tl);
1143 if (nextop == NFSV4OP_SAVEFH &&
1144 i < numops - 1)
1145 savefhcnt++;
1146 } while (nextop == NFSV4OP_SAVEFH &&
1147 i < numops - 1);
1148 }
1149 nd->nd_repstat = 0;
1150 /* If vp == savevp, a no-op */
1151 if (vp != savevp) {
1152 if (nfsrv_checkwrongsec(nd, nextop,
1153 savevp->v_type))
1154 nd->nd_repstat =
1155 nfsvno_testexp(nd,
1156 &savevpnes);
1157 if (nd->nd_repstat == 0) {
1158 VREF(savevp);
1159 vrele(vp);
1160 vp = savevp;
1161 vpnes = savevpnes;
1162 cur_fsid = save_fsid;
1163 }
1164 }
1165 if (nd->nd_repstat == 0 &&
1166 (nd->nd_flag & ND_SAVEDCURSTATEID) != 0) {
1167 nd->nd_curstateid =
1168 nd->nd_savedcurstateid;
1169 nd->nd_flag |= ND_CURSTATEID;
1170 }
1171 } else {
1172 nd->nd_repstat = NFSERR_RESTOREFH;
1173 }
1174 break;
1175 default:
1176 /*
1177 * Allow a Lookup, Getattr, GetFH, Secinfo on an
1178 * non-exported directory if
1179 * nfs_rootfhset. Do I need to allow any other Ops?
1180 * (You can only have a non-exported vpnes if
1181 * nfs_rootfhset is true. See nfsd_fhtovp())
1182 * Allow AUTH_SYS to be used for file systems
1183 * exported GSS only for certain Ops, to allow
1184 * clients to do mounts more easily.
1185 */
1186 if (nfsv4_opflag[op].needscfh && vp) {
1187 if (!NFSVNO_EXPORTED(&vpnes) &&
1188 op != NFSV4OP_LOOKUP &&
1189 op != NFSV4OP_GETATTR &&
1190 op != NFSV4OP_GETFH &&
1191 op != NFSV4OP_ACCESS &&
1192 op != NFSV4OP_READLINK &&
1193 op != NFSV4OP_SECINFO &&
1194 op != NFSV4OP_SECINFONONAME)
1195 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1196 if (nd->nd_repstat) {
1197 if (op == NFSV4OP_SETATTR) {
1198 /*
1199 * Setattr reply requires a bitmap
1200 * even for errors like these.
1201 */
1202 NFSM_BUILD(tl, u_int32_t *,
1203 NFSX_UNSIGNED);
1204 *tl = 0;
1205 }
1206 break;
1207 }
1208 }
1209
1210 /*
1211 * Save the current positions in the mbuf lists so
1212 * that a rollback to this location can be done upon a
1213 * redo due to a ERELOOKUP return for a operation.
1214 */
1215 mb = nd->nd_mb;
1216 bpos = nd->nd_bpos;
1217 bextpg = nd->nd_bextpg;
1218 bextpgsiz = nd->nd_bextpgsiz;
1219 md = nd->nd_md;
1220 dpos = nd->nd_dpos;
1221 tryagain:
1222
1223 if (nfsv4_opflag[op].retfh == 1) {
1224 if (!vp) {
1225 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1226 break;
1227 }
1228 if (NFSVNO_EXPORTED(&vpnes) && (op == NFSV4OP_LOOKUP ||
1229 op == NFSV4OP_LOOKUPP || (op == NFSV4OP_OPEN &&
1230 vp->v_type == VDIR))) {
1231 /* Check for wrong security. */
1232 rstat = nfsvno_testexp(nd, &vpnes);
1233 if (rstat != 0) {
1234 nd->nd_repstat = rstat;
1235 break;
1236 }
1237 }
1238 VREF(vp);
1239 if (nfsv4_opflag[op].modifyfs)
1240 vn_start_write(vp, &temp_mp, V_WAIT);
1241 error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
1242 &nvp, (fhandle_t *)fh.nfsrvfh_data, &vpnes);
1243 if (!error && !nd->nd_repstat) {
1244 if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) {
1245 new_mp = nvp->v_mount;
1246 if (fsidcmp(&cur_fsid, &new_mp->mnt_stat.f_fsid) != 0) {
1247 /* crossed a server mount point */
1248 nd->nd_repstat = nfsvno_checkexp(new_mp,
1249 nd->nd_nam, &nes, &credanon);
1250 if (!nd->nd_repstat)
1251 nd->nd_repstat = nfsd_excred(nd,
1252 &nes, credanon, true);
1253 if (credanon != NULL)
1254 crfree(credanon);
1255 if (!nd->nd_repstat) {
1256 vpnes = nes;
1257 cur_fsid = new_mp->mnt_stat.f_fsid;
1258 }
1259 }
1260 /* Lookup ops return a locked vnode */
1261 NFSVOPUNLOCK(nvp);
1262 }
1263 if (!nd->nd_repstat) {
1264 vrele(vp);
1265 vp = nvp;
1266 } else
1267 vrele(nvp);
1268 }
1269 if (nfsv4_opflag[op].modifyfs)
1270 vn_finished_write(temp_mp);
1271 } else if (nfsv4_opflag[op].retfh == 2) {
1272 if (vp == NULL || savevp == NULL) {
1273 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1274 break;
1275 } else if (fsidcmp(&cur_fsid, &save_fsid) != 0) {
1276 nd->nd_repstat = NFSERR_XDEV;
1277 break;
1278 }
1279 if (nfsv4_opflag[op].modifyfs)
1280 vn_start_write(savevp, &temp_mp, V_WAIT);
1281 if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
1282 VREF(vp);
1283 VREF(savevp);
1284 error = (*(nfsrv4_ops2[op]))(nd, isdgram,
1285 savevp, vp, &savevpnes, &vpnes);
1286 } else
1287 nd->nd_repstat = NFSERR_PERM;
1288 if (nfsv4_opflag[op].modifyfs)
1289 vn_finished_write(temp_mp);
1290 } else {
1291 if (nfsv4_opflag[op].retfh != 0)
1292 panic("nfsrvd_compound");
1293 if (nfsv4_opflag[op].needscfh) {
1294 if (vp != NULL) {
1295 lktype = nfsv4_opflag[op].lktype;
1296 if (nfsv4_opflag[op].modifyfs) {
1297 vn_start_write(vp, &temp_mp,
1298 V_WAIT);
1299 if (op == NFSV4OP_WRITE &&
1300 MNT_SHARED_WRITES(temp_mp))
1301 lktype = LK_SHARED;
1302 }
1303 if (NFSVOPLOCK(vp, lktype) == 0)
1304 VREF(vp);
1305 else
1306 nd->nd_repstat = NFSERR_PERM;
1307 } else {
1308 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1309 if (op == NFSV4OP_SETATTR) {
1310 /*
1311 * Setattr reply requires a
1312 * bitmap even for errors like
1313 * these.
1314 */
1315 NFSM_BUILD(tl, u_int32_t *,
1316 NFSX_UNSIGNED);
1317 *tl = 0;
1318 }
1319 break;
1320 }
1321 if (nd->nd_repstat == 0) {
1322 error = (*(nfsrv4_ops0[op]))(nd,
1323 isdgram, vp, &vpnes);
1324 if ((op == NFSV4OP_SECINFO ||
1325 op == NFSV4OP_SECINFONONAME) &&
1326 error == 0 && nd->nd_repstat == 0) {
1327 /*
1328 * Secinfo and Secinfo_no_name
1329 * consume the current FH.
1330 */
1331 vrele(vp);
1332 vp = NULL;
1333 }
1334 }
1335 if (nfsv4_opflag[op].modifyfs)
1336 vn_finished_write(temp_mp);
1337 } else {
1338 error = (*(nfsrv4_ops0[op]))(nd, isdgram,
1339 NULL, &vpnes);
1340 }
1341 }
1342 }
1343 if (error) {
1344 if (error == EBADRPC || error == NFSERR_BADXDR) {
1345 nd->nd_repstat = NFSERR_BADXDR;
1346 } else {
1347 nd->nd_repstat = error;
1348 printf("nfsv4 comperr0=%d\n", error);
1349 }
1350 error = 0;
1351 }
1352
1353 if (nd->nd_repstat == ERELOOKUP) {
1354 /*
1355 * Roll back to the beginning of the operation
1356 * arguments.
1357 */
1358 nd->nd_md = md;
1359 nd->nd_dpos = dpos;
1360
1361 /*
1362 * Trim off the bogus reply for this operation
1363 * and redo the operation.
1364 */
1365 nfsm_trimtrailing(nd, mb, bpos, bextpg, bextpgsiz);
1366 nd->nd_repstat = 0;
1367 nd->nd_flag |= ND_ERELOOKUP;
1368 goto tryagain;
1369 }
1370 nd->nd_flag &= ~ND_ERELOOKUP;
1371
1372 if (statsinprog != 0) {
1373 nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1374 /*then*/ &start_time);
1375 statsinprog = 0;
1376 }
1377
1378 retops++;
1379 if (nd->nd_repstat) {
1380 *repp = nfsd_errmap(nd);
1381 break;
1382 } else {
1383 *repp = 0; /* NFS4_OK */
1384 }
1385 }
1386 nfsmout:
1387 if (statsinprog != 0) {
1388 nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1389 /*then*/ &start_time);
1390 statsinprog = 0;
1391 }
1392 if (error) {
1393 if (error == EBADRPC || error == NFSERR_BADXDR)
1394 nd->nd_repstat = NFSERR_BADXDR;
1395 else
1396 printf("nfsv4 comperr1=%d\n", error);
1397 }
1398 if (taglen == -1) {
1399 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1400 *tl++ = 0;
1401 *tl = 0;
1402 } else {
1403 *retopsp = txdr_unsigned(retops);
1404 }
1405 if (vp)
1406 vrele(vp);
1407 if (savevp)
1408 vrele(savevp);
1409 if (savecred != NULL)
1410 nd->nd_cred = savecred;
1411 if (rootcred != NULL)
1412 crfree(rootcred);
1413 NFSLOCKV4ROOTMUTEX();
1414 nfsv4_relref(&nfsv4rootfs_lock);
1415 NFSUNLOCKV4ROOTMUTEX();
1416
1417 NFSEXITCODE2(0, nd);
1418 }
1419
1420 /* Create a credential for "root". */
1421 static struct ucred *
nfsrv_createrootcred(void)1422 nfsrv_createrootcred(void)
1423 {
1424 struct ucred *cr;
1425
1426 cr = crget();
1427 cr->cr_uid = cr->cr_ruid = cr->cr_svuid = UID_ROOT;
1428 crsetgroups_fallback(cr, 0, NULL, GID_WHEEL);
1429 cr->cr_rgid = cr->cr_svgid = cr->cr_gid;
1430 cr->cr_prison = curthread->td_ucred->cr_prison;
1431 prison_hold(cr->cr_prison);
1432 #ifdef MAC
1433 mac_cred_associate_nfsd(cr);
1434 #endif
1435 return (cr);
1436 }
1437