xref: /freebsd/sys/fs/nfsserver/nfs_nfsdsocket.c (revision 30d4d3db431a5df8084048c4d31e98e74d2f225a)
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