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