xref: /freebsd/sys/fs/nfsserver/nfs_nfsdsocket.c (revision 4543ef516683042d46f3bd3bb8a4f3f746e00499)
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 1989, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Rick Macklem at The University of Guelph.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  */
35 
36 #include <sys/cdefs.h>
37 /*
38  * Socket operations for use by the nfs server.
39  */
40 
41 #include <fs/nfs/nfsport.h>
42 
43 #include <security/mac/mac_framework.h>
44 
45 extern struct nfsrvfh nfs_pubfh;
46 extern int nfs_pubfhset;
47 extern struct nfsv4lock nfsv4rootfs_lock;
48 extern int nfsrv_clienthashsize;
49 extern int nfsd_debuglevel;
50 extern int nfsrv_layouthighwater;
51 extern volatile int nfsrv_layoutcnt;
52 NFSV4ROOTLOCKMUTEX;
53 NFSSTATESPINLOCK;
54 
55 NFSD_VNET_DECLARE(struct nfsrv_stablefirst, nfsrv_stablefirst);
56 NFSD_VNET_DECLARE(struct nfsclienthashhead *, nfsclienthash);
57 NFSD_VNET_DECLARE(int, nfsrc_floodlevel);
58 NFSD_VNET_DECLARE(int, nfsrc_tcpsavedreplies);
59 NFSD_VNET_DECLARE(struct nfsrvfh, nfs_rootfh);
60 NFSD_VNET_DECLARE(int, nfs_rootfhset);
61 NFSD_VNET_DECLARE(struct nfsstatsv1 *, nfsstatsv1_p);
62 
63 int (*nfsrv3_procs0[NFS_V3NPROCS])(struct nfsrv_descript *,
64     int, vnode_t , struct nfsexstuff *) = {
65 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
66 	nfsrvd_getattr,
67 	nfsrvd_setattr,
68 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
69 	nfsrvd_access,
70 	nfsrvd_readlink,
71 	nfsrvd_read,
72 	nfsrvd_write,
73 	nfsrvd_create,
74 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
75 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
76 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
77 	nfsrvd_remove,
78 	nfsrvd_remove,
79 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
80 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
81 	nfsrvd_readdir,
82 	nfsrvd_readdirplus,
83 	nfsrvd_statfs,
84 	nfsrvd_fsinfo,
85 	nfsrvd_pathconf,
86 	nfsrvd_commit,
87 };
88 
89 int (*nfsrv3_procs1[NFS_V3NPROCS])(struct nfsrv_descript *,
90     int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *) = {
91 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
92 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
93 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
94 	nfsrvd_lookup,
95 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
96 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
97 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
98 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
99 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
100 	nfsrvd_mkdir,
101 	nfsrvd_symlink,
102 	nfsrvd_mknod,
103 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
104 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
105 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
106 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
107 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
108 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
109 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
110 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
111 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
112 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
113 };
114 
115 int (*nfsrv3_procs2[NFS_V3NPROCS])(struct nfsrv_descript *,
116     int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *) = {
117 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
118 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
119 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
120 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
121 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
122 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
123 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
124 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
125 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
126 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
127 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
128 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
129 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
130 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
131 	nfsrvd_rename,
132 	nfsrvd_link,
133 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
134 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
135 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
136 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
137 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
138 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
139 };
140 
141 int (*nfsrv4_ops0[NFSV42_NOPS])(struct nfsrv_descript *,
142     int, vnode_t , struct nfsexstuff *) = {
143 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
144 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
145 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
146 	nfsrvd_access,
147 	nfsrvd_close,
148 	nfsrvd_commit,
149 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
150 	nfsrvd_delegpurge,
151 	nfsrvd_delegreturn,
152 	nfsrvd_getattr,
153 	nfsrvd_getfh,
154 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
155 	nfsrvd_lock,
156 	nfsrvd_lockt,
157 	nfsrvd_locku,
158 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
159 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
160 	nfsrvd_verify,
161 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
162 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
163 	nfsrvd_openconfirm,
164 	nfsrvd_opendowngrade,
165 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
166 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
167 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
168 	nfsrvd_read,
169 	nfsrvd_readdirplus,
170 	nfsrvd_readlink,
171 	nfsrvd_remove,
172 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
173 	nfsrvd_renew,
174 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
175 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
176 	nfsrvd_secinfo,
177 	nfsrvd_setattr,
178 	nfsrvd_setclientid,
179 	nfsrvd_setclientidcfrm,
180 	nfsrvd_verify,
181 	nfsrvd_write,
182 	nfsrvd_releaselckown,
183 	nfsrvd_notsupp,
184 	nfsrvd_bindconnsess,
185 	nfsrvd_exchangeid,
186 	nfsrvd_createsession,
187 	nfsrvd_destroysession,
188 	nfsrvd_freestateid,
189 	nfsrvd_notsupp,
190 	nfsrvd_getdevinfo,
191 	nfsrvd_notsupp,
192 	nfsrvd_layoutcommit,
193 	nfsrvd_layoutget,
194 	nfsrvd_layoutreturn,
195 	nfsrvd_secinfononame,
196 	nfsrvd_sequence,
197 	nfsrvd_notsupp,
198 	nfsrvd_teststateid,
199 	nfsrvd_notsupp,
200 	nfsrvd_destroyclientid,
201 	nfsrvd_reclaimcomplete,
202 	nfsrvd_allocate,
203 	(int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
204 	nfsrvd_notsupp,
205 	nfsrvd_deallocate,
206 	nfsrvd_ioadvise,
207 	nfsrvd_layouterror,
208 	nfsrvd_layoutstats,
209 	nfsrvd_notsupp,
210 	nfsrvd_notsupp,
211 	nfsrvd_notsupp,
212 	nfsrvd_seek,
213 	nfsrvd_notsupp,
214 	nfsrvd_notsupp,
215 	nfsrvd_getxattr,
216 	nfsrvd_setxattr,
217 	nfsrvd_listxattr,
218 	nfsrvd_rmxattr,
219 };
220 
221 int (*nfsrv4_ops1[NFSV42_NOPS])(struct nfsrv_descript *,
222     int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *) = {
223 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
224 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
225 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
226 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
227 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
228 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
229 	nfsrvd_mknod,
230 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
231 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
232 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
233 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
234 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
235 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
236 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
237 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
238 	nfsrvd_lookup,
239 	nfsrvd_lookup,
240 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
241 	nfsrvd_open,
242 	nfsrvd_openattr,
243 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
244 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
245 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
246 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
247 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
248 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
249 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
250 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
251 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
252 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
253 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
254 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
255 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
256 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
257 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
258 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
259 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
260 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
261 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
262 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
263 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
264 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
265 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
266 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
267 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
268 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
269 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
270 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
271 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
272 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
273 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
274 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
275 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
276 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
277 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
278 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
279 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
280 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
281 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
282 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
283 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
284 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
285 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
286 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
287 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
288 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
289 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
290 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
291 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
292 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
293 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
294 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
295 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
296 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
297 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
298 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
299 };
300 
301 int (*nfsrv4_ops2[NFSV42_NOPS])(struct nfsrv_descript *,
302     int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *) = {
303 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
304 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
305 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
306 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
307 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
308 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
309 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
310 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
311 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
312 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
313 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
314 	nfsrvd_link,
315 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
316 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
317 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
318 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
319 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
320 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
321 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
322 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
323 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
324 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
325 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
326 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
327 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
328 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
329 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
330 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
331 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
332 	nfsrvd_rename,
333 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
334 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
335 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
336 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
337 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
338 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
339 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
340 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
341 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
342 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
343 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
344 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
345 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
346 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
347 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
348 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
349 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
350 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
351 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
352 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
353 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
354 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
355 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
356 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
357 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
358 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
359 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
360 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
361 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
362 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
363 	nfsrvd_copy_file_range,
364 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
365 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
366 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
367 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
368 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
369 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
370 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
371 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
372 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
373 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
374 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
375 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
376 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
377 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
378 	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
379 };
380 
381 /*
382  * Static array that defines which nfs rpc's are nonidempotent
383  */
384 static int nfsrv_nonidempotent[NFS_V3NPROCS] = {
385 	FALSE,
386 	FALSE,
387 	TRUE,
388 	FALSE,
389 	FALSE,
390 	FALSE,
391 	FALSE,
392 	TRUE,
393 	TRUE,
394 	TRUE,
395 	TRUE,
396 	TRUE,
397 	TRUE,
398 	TRUE,
399 	TRUE,
400 	TRUE,
401 	FALSE,
402 	FALSE,
403 	FALSE,
404 	FALSE,
405 	FALSE,
406 	FALSE,
407 };
408 
409 /*
410  * This static array indicates whether or not the RPC modifies the
411  * file system.
412  */
413 int nfsrv_writerpc[NFS_NPROCS] = { 0, 0, 1, 0, 0, 0, 0,
414     1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
415     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
416 
417 SYSCTL_DECL(_vfs_nfsd);
418 static int	nfs_minminorv4 = NFSV4_MINORVERSION;
419 SYSCTL_INT(_vfs_nfsd, OID_AUTO, server_min_minorversion4, CTLFLAG_RWTUN,
420     &nfs_minminorv4, 0,
421     "The lowest minor version of NFSv4 handled by the server");
422 
423 static int	nfs_maxminorv4 = NFSV42_MINORVERSION;
424 SYSCTL_INT(_vfs_nfsd, OID_AUTO, server_max_minorversion4, CTLFLAG_RWTUN,
425     &nfs_maxminorv4, 0,
426     "The highest minor version of NFSv4 handled by the server");
427 
428 /* local functions */
429 static void nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
430     u_char *tag, int taglen, u_int32_t minorvers);
431 
432 /*
433  * This static array indicates which server procedures require the extra
434  * arguments to return the current file handle for V2, 3.
435  */
436 static int nfs_retfh[NFS_V3NPROCS] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1,
437 	1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0 };
438 
439 extern struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS];
440 
441 static int nfsv3to4op[NFS_V3NPROCS] = {
442 	NFSPROC_NULL,
443 	NFSV4OP_GETATTR,
444 	NFSV4OP_SETATTR,
445 	NFSV4OP_LOOKUP,
446 	NFSV4OP_ACCESS,
447 	NFSV4OP_READLINK,
448 	NFSV4OP_READ,
449 	NFSV4OP_WRITE,
450 	NFSV4OP_V3CREATE,
451 	NFSV4OP_MKDIR,
452 	NFSV4OP_SYMLINK,
453 	NFSV4OP_MKNOD,
454 	NFSV4OP_REMOVE,
455 	NFSV4OP_RMDIR,
456 	NFSV4OP_RENAME,
457 	NFSV4OP_LINK,
458 	NFSV4OP_READDIR,
459 	NFSV4OP_READDIRPLUS,
460 	NFSV4OP_FSSTAT,
461 	NFSV4OP_FSINFO,
462 	NFSV4OP_PATHCONF,
463 	NFSV4OP_COMMIT,
464 };
465 
466 static struct mtx nfsrvd_statmtx;
467 MTX_SYSINIT(nfsst, &nfsrvd_statmtx, "NFSstat", MTX_DEF);
468 
469 static struct ucred *nfsrv_createrootcred(void);
470 
471 static void
472 nfsrvd_statstart(int op, struct bintime *now)
473 {
474 	if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
475 		printf("%s: op %d invalid\n", __func__, op);
476 		return;
477 	}
478 
479 	mtx_lock(&nfsrvd_statmtx);
480 	if (NFSD_VNET(nfsstatsv1_p)->srvstartcnt ==
481 	    NFSD_VNET(nfsstatsv1_p)->srvdonecnt) {
482 		if (now != NULL)
483 			NFSD_VNET(nfsstatsv1_p)->busyfrom = *now;
484 		else
485 			binuptime(&NFSD_VNET(nfsstatsv1_p)->busyfrom);
486 
487 	}
488 	NFSD_VNET(nfsstatsv1_p)->srvrpccnt[op]++;
489 	NFSD_VNET(nfsstatsv1_p)->srvstartcnt++;
490 	mtx_unlock(&nfsrvd_statmtx);
491 
492 }
493 
494 static void
495 nfsrvd_statend(int op, uint64_t bytes, struct bintime *now,
496     struct bintime *then)
497 {
498 	struct bintime dt, lnow;
499 
500 	if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
501 		printf("%s: op %d invalid\n", __func__, op);
502 		return;
503 	}
504 
505 	if (now == NULL) {
506 		now = &lnow;
507 		binuptime(now);
508 	}
509 
510 	mtx_lock(&nfsrvd_statmtx);
511 
512 	NFSD_VNET(nfsstatsv1_p)->srvbytes[op] += bytes;
513 	NFSD_VNET(nfsstatsv1_p)->srvops[op]++;
514 
515 	if (then != NULL) {
516 		dt = *now;
517 		bintime_sub(&dt, then);
518 		bintime_add(&NFSD_VNET(nfsstatsv1_p)->srvduration[op], &dt);
519 	}
520 
521 	dt = *now;
522 	bintime_sub(&dt, &NFSD_VNET(nfsstatsv1_p)->busyfrom);
523 	bintime_add(&NFSD_VNET(nfsstatsv1_p)->busytime, &dt);
524 	NFSD_VNET(nfsstatsv1_p)->busyfrom = *now;
525 
526 	NFSD_VNET(nfsstatsv1_p)->srvdonecnt++;
527 
528 	mtx_unlock(&nfsrvd_statmtx);
529 }
530 
531 /*
532  * Do an RPC. Basically, get the file handles translated to vnode pointers
533  * and then call the appropriate server routine. The server routines are
534  * split into groups, based on whether they use a file handle or file
535  * handle plus name or ...
536  * The NFS V4 Compound RPC is performed separately by nfsrvd_compound().
537  */
538 void
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
709 nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,
710     int taglen, u_int32_t minorvers)
711 {
712 	int i, lktype, op, op0 = 0, rstat, statsinprog = 0;
713 	u_int32_t *tl;
714 	struct nfsclient *clp, *nclp;
715 	int error = 0, igotlock, nextop, numops, savefhcnt;
716 	u_int32_t retops = 0, *retopsp = NULL, *repp;
717 	vnode_t vp, nvp, savevp;
718 	struct nfsrvfh fh;
719 	mount_t new_mp, temp_mp = NULL;
720 	struct ucred *credanon, *rootcred, *savecred;
721 	struct nfsexstuff nes, vpnes, savevpnes;
722 	fsid_t cur_fsid, save_fsid;
723 	static u_int64_t compref = 0;
724 	struct bintime start_time;
725 	struct thread *p;
726 	struct mbuf *mb, *md;
727 	char *bpos, *dpos;
728 	int bextpg, bextpgsiz;
729 
730 	p = curthread;
731 	rootcred = savecred = NULL;
732 
733 	/* Check for and optionally clear the no space flags for DSs. */
734 	nfsrv_checknospc();
735 
736 	NFSVNO_EXINIT(&vpnes);
737 	NFSVNO_EXINIT(&savevpnes);
738 	/*
739 	 * Put the seq# of the current compound RPC in nfsrv_descript.
740 	 * (This is used by nfsrv_checkgetattr(), to see if the write
741 	 *  delegation was created by the same compound RPC as the one
742 	 *  with that Getattr in it.)
743 	 * Don't worry about the 64bit number wrapping around. It ain't
744 	 * gonna happen before this server gets shut down/rebooted.
745 	 */
746 	nd->nd_compref = compref++;
747 
748 	/*
749 	 * Check for and optionally get a lock on the root. This lock means that
750 	 * no nfsd will be fiddling with the V4 file system and state stuff. It
751 	 * is required when the V4 root is being changed, the stable storage
752 	 * restart file is being updated, or callbacks are being done.
753 	 * When any of the nfsd are processing an NFSv4 compound RPC, they must
754 	 * either hold a reference count (nfs_usecnt) or the lock. When
755 	 * nfsrv_unlock() is called to release the lock, it can optionally
756 	 * also get a reference count, which saves the need for a call to
757 	 * nfsrv_getref() after nfsrv_unlock().
758 	 */
759 	/*
760 	 * First, check to see if we need to wait for an update lock.
761 	 */
762 	igotlock = 0;
763 	NFSLOCKV4ROOTMUTEX();
764 	if (NFSD_VNET(nfsrv_stablefirst).nsf_flags & NFSNSF_NEEDLOCK)
765 		igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
766 		    NFSV4ROOTLOCKMUTEXPTR, NULL);
767 	else
768 		igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
769 		    NFSV4ROOTLOCKMUTEXPTR, NULL);
770 	NFSUNLOCKV4ROOTMUTEX();
771 	if (igotlock) {
772 		/*
773 		 * If I got the lock, I can update the stable storage file.
774 		 * Done when the grace period is over or a client has long
775 		 * since expired.
776 		 */
777 		NFSD_VNET(nfsrv_stablefirst).nsf_flags &= ~NFSNSF_NEEDLOCK;
778 		if ((NFSD_VNET(nfsrv_stablefirst).nsf_flags &
779 		    (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
780 			nfsrv_updatestable(p);
781 
782 		/*
783 		 * If at least one client has long since expired, search
784 		 * the client list for them, write a REVOKE record on the
785 		 * stable storage file and then remove them from the client
786 		 * list.
787 		 */
788 		if (NFSD_VNET(nfsrv_stablefirst).nsf_flags &
789 		    NFSNSF_EXPIREDCLIENT) {
790 			NFSD_VNET(nfsrv_stablefirst).nsf_flags &=
791 			    ~NFSNSF_EXPIREDCLIENT;
792 			for (i = 0; i < nfsrv_clienthashsize; i++) {
793 			    LIST_FOREACH_SAFE(clp, &NFSD_VNET(nfsclienthash)[i],
794 				lc_hash, nclp) {
795 				if (clp->lc_flags & LCL_EXPIREIT) {
796 				    if (!LIST_EMPTY(&clp->lc_open) ||
797 					!LIST_EMPTY(&clp->lc_deleg))
798 					nfsrv_writestable(clp->lc_id,
799 					    clp->lc_idlen, NFSNST_REVOKE, p);
800 				    nfsrv_cleanclient(clp, p);
801 				    nfsrv_freedeleglist(&clp->lc_deleg);
802 				    nfsrv_freedeleglist(&clp->lc_olddeleg);
803 				    LIST_REMOVE(clp, lc_hash);
804 				    nfsrv_zapclient(clp, p);
805 				}
806 			    }
807 			}
808 		}
809 		NFSLOCKV4ROOTMUTEX();
810 		nfsv4_unlock(&nfsv4rootfs_lock, 1);
811 		NFSUNLOCKV4ROOTMUTEX();
812 	} else {
813 		/*
814 		 * If we didn't get the lock, we need to get a refcnt,
815 		 * which also checks for and waits for the lock.
816 		 */
817 		NFSLOCKV4ROOTMUTEX();
818 		nfsv4_getref(&nfsv4rootfs_lock, NULL,
819 		    NFSV4ROOTLOCKMUTEXPTR, NULL);
820 		NFSUNLOCKV4ROOTMUTEX();
821 	}
822 
823 	/*
824 	 * If flagged, search for open owners that haven't had any opens
825 	 * for a long time.
826 	 */
827 	if (NFSD_VNET(nfsrv_stablefirst).nsf_flags & NFSNSF_NOOPENS) {
828 		nfsrv_throwawayopens(p);
829 	}
830 
831 	/* Do a CBLAYOUTRECALL callback if over the high water mark. */
832 	if (nfsrv_layoutcnt > nfsrv_layouthighwater)
833 		nfsrv_recalloldlayout(p);
834 
835 	savevp = vp = NULL;
836 	save_fsid.val[0] = save_fsid.val[1] = 0;
837 	cur_fsid.val[0] = cur_fsid.val[1] = 0;
838 	nextop = -1;
839 	savefhcnt = 0;
840 
841 	/* If taglen < 0, there was a parsing error in nfsd_getminorvers(). */
842 	if (taglen < 0) {
843 		error = EBADRPC;
844 		goto nfsmout;
845 	}
846 
847 	(void) nfsm_strtom(nd, tag, taglen);
848 	NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED);
849 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
850 	if ((minorvers != NFSV4_MINORVERSION &&
851 	    minorvers != NFSV41_MINORVERSION &&
852 	    minorvers != NFSV42_MINORVERSION) ||
853 	    minorvers < nfs_minminorv4 || minorvers > nfs_maxminorv4)
854 		nd->nd_repstat = NFSERR_MINORVERMISMATCH;
855 	if (nd->nd_repstat)
856 		numops = 0;
857 	else
858 		numops = fxdr_unsigned(int, *tl);
859 	/*
860 	 * Loop around doing the sub ops.
861 	 * vp - is an unlocked vnode pointer for the CFH
862 	 * savevp - is an unlocked vnode pointer for the SAVEDFH
863 	 * (at some future date, it might turn out to be more appropriate
864 	 *  to keep the file handles instead of vnode pointers?)
865 	 * savevpnes and vpnes - are the export flags for the above.
866 	 */
867 	for (i = 0; i < numops; i++) {
868 		NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED);
869 		if (savefhcnt > 0) {
870 			op = NFSV4OP_SAVEFH;
871 			*repp = txdr_unsigned(op);
872 			savefhcnt--;
873 		} else if (nextop == -1) {
874 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
875 			*repp = *tl;
876 			op = fxdr_unsigned(int, *tl);
877 		} else {
878 			op = nextop;
879 			*repp = txdr_unsigned(op);
880 			nextop = -1;
881 		}
882 		NFSD_DEBUG(4, "op=%d\n", op);
883 		if (op < NFSV4OP_ACCESS || op >= NFSV42_NOPS ||
884 		    (op >= NFSV4OP_NOPS && (nd->nd_flag & ND_NFSV41) == 0) ||
885 		    (op >= NFSV41_NOPS && (nd->nd_flag & ND_NFSV42) == 0)) {
886 			nd->nd_repstat = NFSERR_OPILLEGAL;
887 			*repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL);
888 			*repp = nfsd_errmap(nd);
889 			retops++;
890 			break;
891 		} else {
892 			repp++;
893 		}
894 
895 		binuptime(&start_time);
896 		nfsrvd_statstart(op, &start_time);
897 		statsinprog = 1;
898 
899 		if (i == 0)
900 			op0 = op;
901 		if (i == numops - 1)
902 			nd->nd_flag |= ND_LASTOP;
903 
904 		/*
905 		 * Check for a referral on the current FH and, if so, return
906 		 * NFSERR_MOVED for all ops that allow it, except Getattr.
907 		 */
908 		if (vp != NULL && op != NFSV4OP_GETATTR &&
909 		    nfsv4root_getreferral(vp, NULL, 0) != NULL &&
910 		    nfsrv_errmoved(op)) {
911 			nd->nd_repstat = NFSERR_MOVED;
912 			*repp = nfsd_errmap(nd);
913 			retops++;
914 			break;
915 		}
916 
917 		/*
918 		 * For NFSv4.1, check for a Sequence Operation being first
919 		 * or one of the other allowed operations by itself.
920 		 */
921 		if ((nd->nd_flag & ND_NFSV41) != 0) {
922 			if (i != 0 && op == NFSV4OP_SEQUENCE)
923 				nd->nd_repstat = NFSERR_SEQUENCEPOS;
924 			else if (i == 0 && op != NFSV4OP_SEQUENCE &&
925 			    op != NFSV4OP_EXCHANGEID &&
926 			    op != NFSV4OP_CREATESESSION &&
927 			    op != NFSV4OP_BINDCONNTOSESS &&
928 			    op != NFSV4OP_DESTROYCLIENTID &&
929 			    op != NFSV4OP_DESTROYSESSION)
930 				nd->nd_repstat = NFSERR_OPNOTINSESS;
931 			else if (i != 0 && op0 != NFSV4OP_SEQUENCE)
932 				nd->nd_repstat = NFSERR_NOTONLYOP;
933 			if (nd->nd_repstat != 0) {
934 				*repp = nfsd_errmap(nd);
935 				retops++;
936 				break;
937 			}
938 		}
939 
940 		nd->nd_procnum = op;
941 		/*
942 		 * If over flood level, reply NFSERR_RESOURCE, if at the first
943 		 * Op. (Since a client recovery from NFSERR_RESOURCE can get
944 		 * really nasty for certain Op sequences, I'll play it safe
945 		 * and only return the error at the beginning.) The cache
946 		 * will still function over flood level, but uses lots of
947 		 * mbufs.)
948 		 * If nfsrv_mallocmget_limit() returns True, the system is near
949 		 * to its limit for memory that malloc()/mget() can allocate.
950 		 */
951 		if (i == 0 && (nd->nd_rp == NULL ||
952 		    nd->nd_rp->rc_refcnt == 0) &&
953 		    (nfsrv_mallocmget_limit() ||
954 		     NFSD_VNET(nfsrc_tcpsavedreplies) >
955 		     NFSD_VNET(nfsrc_floodlevel))) {
956 			if (NFSD_VNET(nfsrc_tcpsavedreplies) >
957 			    NFSD_VNET(nfsrc_floodlevel))
958 				printf("nfsd server cache flooded, try "
959 				    "increasing vfs.nfsd.tcphighwater\n");
960 			nd->nd_repstat = NFSERR_RESOURCE;
961 			*repp = nfsd_errmap(nd);
962 			if (op == NFSV4OP_SETATTR) {
963 				/*
964 				 * Setattr replies require a bitmap.
965 				 * even for errors like these.
966 				 */
967 				NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
968 				*tl = 0;
969 			}
970 			retops++;
971 			break;
972 		}
973 
974 		/*
975 		 * Check for the case of SP4_MACH_CRED and an operation in
976 		 * the allow set.  For these operations, replace nd_cred with
977 		 * root credentials so that the operation will not fail due
978 		 * to credentials.
979 		 * NB: ND_MACHCRED is set by Sequence when the ClientID
980 		 * specifies LCL_MACHCRED and the RPC is being performed
981 		 * via krb5i or krb5p using the machine principal.
982 		 */
983 		if ((nd->nd_flag & ND_MACHCRED) != 0) {
984 			if (NFSISSET_OPBIT(&nd->nd_allowops, op)) {
985 				/* Replace nd_cred with root creds. */
986 				if (rootcred == NULL)
987 					rootcred = nfsrv_createrootcred();
988 				if (savecred == NULL)
989 					savecred = nd->nd_cred;
990 				nd->nd_cred = rootcred;
991 			} else if (savecred != NULL) {
992 				nd->nd_cred = savecred;
993 				savecred = NULL;
994 			}
995 		}
996 
997 		if (nfsv4_opflag[op].savereply)
998 			nd->nd_flag |= ND_SAVEREPLY;
999 		switch (op) {
1000 		case NFSV4OP_PUTFH:
1001 			error = nfsrv_mtofh(nd, &fh);
1002 			if (error)
1003 				goto nfsmout;
1004 			if ((nd->nd_flag & ND_LASTOP) == 0) {
1005 				/*
1006 				 * Pre-parse the next op#.  If it is
1007 				 * SaveFH, count it and skip to the
1008 				 * next op#, if not the last op#.
1009 				 * nextop is used to determine if
1010 				 * NFSERR_WRONGSEC can be returned,
1011 				 * per RFC5661 Sec. 2.6.
1012 				 */
1013 				do {
1014 					NFSM_DISSECT(tl, uint32_t *,
1015 					    NFSX_UNSIGNED);
1016 					nextop = fxdr_unsigned(int, *tl);
1017 					if (nextop == NFSV4OP_SAVEFH &&
1018 					    i < numops - 1)
1019 						savefhcnt++;
1020 				} while (nextop == NFSV4OP_SAVEFH &&
1021 				    i < numops - 1);
1022 			}
1023 			if (!nd->nd_repstat)
1024 				nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
1025 				    NULL, 0, nextop);
1026 			/* For now, allow this for non-export FHs */
1027 			if (!nd->nd_repstat) {
1028 				if (vp)
1029 					vrele(vp);
1030 				vp = nvp;
1031 				cur_fsid = vp->v_mount->mnt_stat.f_fsid;
1032 				NFSVOPUNLOCK(vp);
1033 				vpnes = nes;
1034 			}
1035 			break;
1036 		case NFSV4OP_PUTPUBFH:
1037 			if (nfs_pubfhset) {
1038 				if ((nd->nd_flag & ND_LASTOP) == 0) {
1039 					/*
1040 					 * Pre-parse the next op#.  If it is
1041 					 * SaveFH, count it and skip to the
1042 					 * next op#, if not the last op#.
1043 					 * nextop is used to determine if
1044 					 * NFSERR_WRONGSEC can be returned,
1045 					 * per RFC5661 Sec. 2.6.
1046 					 */
1047 					do {
1048 						NFSM_DISSECT(tl, uint32_t *,
1049 						    NFSX_UNSIGNED);
1050 						nextop = fxdr_unsigned(int,
1051 						    *tl);
1052 						if (nextop == NFSV4OP_SAVEFH &&
1053 						    i < numops - 1)
1054 							savefhcnt++;
1055 					} while (nextop == NFSV4OP_SAVEFH &&
1056 					    i < numops - 1);
1057 				}
1058 				nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
1059 				    &nes, NULL, 0, nextop);
1060 			} else
1061 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
1062 			if (!nd->nd_repstat) {
1063 				if (vp)
1064 					vrele(vp);
1065 				vp = nvp;
1066 				cur_fsid = vp->v_mount->mnt_stat.f_fsid;
1067 				NFSVOPUNLOCK(vp);
1068 				vpnes = nes;
1069 			}
1070 			break;
1071 		case NFSV4OP_PUTROOTFH:
1072 			if (NFSD_VNET(nfs_rootfhset)) {
1073 				if ((nd->nd_flag & ND_LASTOP) == 0) {
1074 					/*
1075 					 * Pre-parse the next op#.  If it is
1076 					 * SaveFH, count it and skip to the
1077 					 * next op#, if not the last op#.
1078 					 * nextop is used to determine if
1079 					 * NFSERR_WRONGSEC can be returned,
1080 					 * per RFC5661 Sec. 2.6.
1081 					 */
1082 					do {
1083 						NFSM_DISSECT(tl, uint32_t *,
1084 						    NFSX_UNSIGNED);
1085 						nextop = fxdr_unsigned(int,
1086 						    *tl);
1087 						if (nextop == NFSV4OP_SAVEFH &&
1088 						    i < numops - 1)
1089 							savefhcnt++;
1090 					} while (nextop == NFSV4OP_SAVEFH &&
1091 					    i < numops - 1);
1092 				}
1093 				nfsd_fhtovp(nd, &NFSD_VNET(nfs_rootfh),
1094 				    LK_SHARED, &nvp, &nes, NULL, 0, nextop);
1095 				if (!nd->nd_repstat) {
1096 					if (vp)
1097 						vrele(vp);
1098 					vp = nvp;
1099 					cur_fsid = vp->v_mount->mnt_stat.f_fsid;
1100 					NFSVOPUNLOCK(vp);
1101 					vpnes = nes;
1102 				}
1103 			} else
1104 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
1105 			break;
1106 		case NFSV4OP_SAVEFH:
1107 			if (vp && NFSVNO_EXPORTED(&vpnes)) {
1108 				nd->nd_repstat = 0;
1109 				/* If vp == savevp, a no-op */
1110 				if (vp != savevp) {
1111 					if (savevp)
1112 						vrele(savevp);
1113 					VREF(vp);
1114 					savevp = vp;
1115 					savevpnes = vpnes;
1116 					save_fsid = cur_fsid;
1117 				}
1118 				if ((nd->nd_flag & ND_CURSTATEID) != 0) {
1119 					nd->nd_savedcurstateid =
1120 					    nd->nd_curstateid;
1121 					nd->nd_flag |= ND_SAVEDCURSTATEID;
1122 				}
1123 			} else {
1124 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
1125 			}
1126 			break;
1127 		case NFSV4OP_RESTOREFH:
1128 			if (savevp) {
1129 				if ((nd->nd_flag & ND_LASTOP) == 0) {
1130 					/*
1131 					 * Pre-parse the next op#.  If it is
1132 					 * SaveFH, count it and skip to the
1133 					 * next op#, if not the last op#.
1134 					 * nextop is used to determine if
1135 					 * NFSERR_WRONGSEC can be returned,
1136 					 * per RFC5661 Sec. 2.6.
1137 					 */
1138 					do {
1139 						NFSM_DISSECT(tl, uint32_t *,
1140 						    NFSX_UNSIGNED);
1141 						nextop = fxdr_unsigned(int,
1142 						    *tl);
1143 						if (nextop == NFSV4OP_SAVEFH &&
1144 						    i < numops - 1)
1145 							savefhcnt++;
1146 					} while (nextop == NFSV4OP_SAVEFH &&
1147 					    i < numops - 1);
1148 				}
1149 				nd->nd_repstat = 0;
1150 				/* If vp == savevp, a no-op */
1151 				if (vp != savevp) {
1152 					if (nfsrv_checkwrongsec(nd, nextop,
1153 					    savevp->v_type))
1154 						nd->nd_repstat =
1155 						    nfsvno_testexp(nd,
1156 						    &savevpnes);
1157 					if (nd->nd_repstat == 0) {
1158 						VREF(savevp);
1159 						vrele(vp);
1160 						vp = savevp;
1161 						vpnes = savevpnes;
1162 						cur_fsid = save_fsid;
1163 					}
1164 				}
1165 				if (nd->nd_repstat == 0 &&
1166 				     (nd->nd_flag & ND_SAVEDCURSTATEID) != 0) {
1167 					nd->nd_curstateid =
1168 					    nd->nd_savedcurstateid;
1169 					nd->nd_flag |= ND_CURSTATEID;
1170 				}
1171 			} else {
1172 				nd->nd_repstat = NFSERR_RESTOREFH;
1173 			}
1174 			break;
1175 		default:
1176 		    /*
1177 		     * Allow a Lookup, Getattr, GetFH, Secinfo on an
1178 		     * non-exported directory if
1179 		     * nfs_rootfhset. Do I need to allow any other Ops?
1180 		     * (You can only have a non-exported vpnes if
1181 		     *  nfs_rootfhset is true. See nfsd_fhtovp())
1182 		     * Allow AUTH_SYS to be used for file systems
1183 		     * exported GSS only for certain Ops, to allow
1184 		     * clients to do mounts more easily.
1185 		     */
1186 		    if (nfsv4_opflag[op].needscfh && vp) {
1187 			if (!NFSVNO_EXPORTED(&vpnes) &&
1188 			    op != NFSV4OP_LOOKUP &&
1189 			    op != NFSV4OP_GETATTR &&
1190 			    op != NFSV4OP_GETFH &&
1191 			    op != NFSV4OP_ACCESS &&
1192 			    op != NFSV4OP_READLINK &&
1193 			    op != NFSV4OP_SECINFO &&
1194 			    op != NFSV4OP_SECINFONONAME)
1195 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
1196 			if (nd->nd_repstat) {
1197 				if (op == NFSV4OP_SETATTR) {
1198 				    /*
1199 				     * Setattr reply requires a bitmap
1200 				     * even for errors like these.
1201 				     */
1202 				    NFSM_BUILD(tl, u_int32_t *,
1203 					NFSX_UNSIGNED);
1204 				    *tl = 0;
1205 				}
1206 				break;
1207 			}
1208 		    }
1209 
1210 		    /*
1211 		     * Save the current positions in the mbuf lists so
1212 		     * that a rollback to this location can be done upon a
1213 		     * redo due to a ERELOOKUP return for a operation.
1214 		     */
1215 		    mb = nd->nd_mb;
1216 		    bpos = nd->nd_bpos;
1217 		    bextpg = nd->nd_bextpg;
1218 		    bextpgsiz = nd->nd_bextpgsiz;
1219 		    md = nd->nd_md;
1220 		    dpos = nd->nd_dpos;
1221 tryagain:
1222 
1223 		    if (nfsv4_opflag[op].retfh == 1) {
1224 			if (!vp) {
1225 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
1226 				break;
1227 			}
1228 			if (NFSVNO_EXPORTED(&vpnes) && (op == NFSV4OP_LOOKUP ||
1229 			    op == NFSV4OP_LOOKUPP || (op == NFSV4OP_OPEN &&
1230 			    vp->v_type == VDIR))) {
1231 				/* Check for wrong security. */
1232 				rstat = nfsvno_testexp(nd, &vpnes);
1233 				if (rstat != 0) {
1234 					nd->nd_repstat = rstat;
1235 					break;
1236 				}
1237 			}
1238 			VREF(vp);
1239 			if (nfsv4_opflag[op].modifyfs)
1240 				vn_start_write(vp, &temp_mp, V_WAIT);
1241 			error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
1242 			    &nvp, (fhandle_t *)fh.nfsrvfh_data, &vpnes);
1243 			if (!error && !nd->nd_repstat) {
1244 			    if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) {
1245 				new_mp = nvp->v_mount;
1246 				if (fsidcmp(&cur_fsid, &new_mp->mnt_stat.f_fsid) != 0) {
1247 				    /* crossed a server mount point */
1248 				    nd->nd_repstat = nfsvno_checkexp(new_mp,
1249 					nd->nd_nam, &nes, &credanon);
1250 				    if (!nd->nd_repstat)
1251 					nd->nd_repstat = nfsd_excred(nd,
1252 					    &nes, credanon, true);
1253 				    if (credanon != NULL)
1254 					crfree(credanon);
1255 				    if (!nd->nd_repstat) {
1256 					vpnes = nes;
1257 					cur_fsid = new_mp->mnt_stat.f_fsid;
1258 				    }
1259 				}
1260 				/* Lookup ops return a locked vnode */
1261 				NFSVOPUNLOCK(nvp);
1262 			    }
1263 			    if (!nd->nd_repstat) {
1264 				    vrele(vp);
1265 				    vp = nvp;
1266 			    } else
1267 				    vrele(nvp);
1268 			}
1269 			if (nfsv4_opflag[op].modifyfs)
1270 				vn_finished_write(temp_mp);
1271 		    } else if (nfsv4_opflag[op].retfh == 2) {
1272 			if (vp == NULL || savevp == NULL) {
1273 				nd->nd_repstat = NFSERR_NOFILEHANDLE;
1274 				break;
1275 			} else if (fsidcmp(&cur_fsid, &save_fsid) != 0) {
1276 				nd->nd_repstat = NFSERR_XDEV;
1277 				break;
1278 			}
1279 			if (nfsv4_opflag[op].modifyfs)
1280 				vn_start_write(savevp, &temp_mp, V_WAIT);
1281 			if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
1282 				VREF(vp);
1283 				VREF(savevp);
1284 				error = (*(nfsrv4_ops2[op]))(nd, isdgram,
1285 				    savevp, vp, &savevpnes, &vpnes);
1286 			} else
1287 				nd->nd_repstat = NFSERR_PERM;
1288 			if (nfsv4_opflag[op].modifyfs)
1289 				vn_finished_write(temp_mp);
1290 		    } else {
1291 			if (nfsv4_opflag[op].retfh != 0)
1292 				panic("nfsrvd_compound");
1293 			if (nfsv4_opflag[op].needscfh) {
1294 				if (vp != NULL) {
1295 					lktype = nfsv4_opflag[op].lktype;
1296 					if (nfsv4_opflag[op].modifyfs) {
1297 						vn_start_write(vp, &temp_mp,
1298 						    V_WAIT);
1299 						if (op == NFSV4OP_WRITE &&
1300 						    MNT_SHARED_WRITES(temp_mp))
1301 							lktype = LK_SHARED;
1302 					}
1303 					if (NFSVOPLOCK(vp, lktype) == 0)
1304 						VREF(vp);
1305 					else
1306 						nd->nd_repstat = NFSERR_PERM;
1307 				} else {
1308 					nd->nd_repstat = NFSERR_NOFILEHANDLE;
1309 					if (op == NFSV4OP_SETATTR) {
1310 						/*
1311 						 * Setattr reply requires a
1312 						 * bitmap even for errors like
1313 						 * these.
1314 						 */
1315 						NFSM_BUILD(tl, u_int32_t *,
1316 						    NFSX_UNSIGNED);
1317 						*tl = 0;
1318 					}
1319 					break;
1320 				}
1321 				if (nd->nd_repstat == 0) {
1322 					error = (*(nfsrv4_ops0[op]))(nd,
1323 					    isdgram, vp, &vpnes);
1324 					if ((op == NFSV4OP_SECINFO ||
1325 					     op == NFSV4OP_SECINFONONAME) &&
1326 					    error == 0 && nd->nd_repstat == 0) {
1327 						/*
1328 						 * Secinfo and Secinfo_no_name
1329 						 * consume the current FH.
1330 						 */
1331 						vrele(vp);
1332 						vp = NULL;
1333 					}
1334 				}
1335 				if (nfsv4_opflag[op].modifyfs)
1336 					vn_finished_write(temp_mp);
1337 			} else {
1338 				error = (*(nfsrv4_ops0[op]))(nd, isdgram,
1339 				    NULL, &vpnes);
1340 			}
1341 		    }
1342 		}
1343 		if (error) {
1344 			if (error == EBADRPC || error == NFSERR_BADXDR) {
1345 				nd->nd_repstat = NFSERR_BADXDR;
1346 			} else {
1347 				nd->nd_repstat = error;
1348 				printf("nfsv4 comperr0=%d\n", error);
1349 			}
1350 			error = 0;
1351 		}
1352 
1353 		if (nd->nd_repstat == ERELOOKUP) {
1354 			/*
1355 			 * Roll back to the beginning of the operation
1356 			 * arguments.
1357 			 */
1358 			nd->nd_md = md;
1359 			nd->nd_dpos = dpos;
1360 
1361 			/*
1362 			 * Trim off the bogus reply for this operation
1363 			 * and redo the operation.
1364 			 */
1365 			nfsm_trimtrailing(nd, mb, bpos, bextpg, bextpgsiz);
1366 			nd->nd_repstat = 0;
1367 			nd->nd_flag |= ND_ERELOOKUP;
1368 			goto tryagain;
1369 		}
1370 		nd->nd_flag &= ~ND_ERELOOKUP;
1371 
1372 		if (statsinprog != 0) {
1373 			nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1374 			    /*then*/ &start_time);
1375 			statsinprog = 0;
1376 		}
1377 
1378 		retops++;
1379 		if (nd->nd_repstat) {
1380 			*repp = nfsd_errmap(nd);
1381 			break;
1382 		} else {
1383 			*repp = 0;	/* NFS4_OK */
1384 		}
1385 	}
1386 nfsmout:
1387 	if (statsinprog != 0) {
1388 		nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1389 		    /*then*/ &start_time);
1390 		statsinprog = 0;
1391 	}
1392 	if (error) {
1393 		if (error == EBADRPC || error == NFSERR_BADXDR)
1394 			nd->nd_repstat = NFSERR_BADXDR;
1395 		else
1396 			printf("nfsv4 comperr1=%d\n", error);
1397 	}
1398 	if (taglen == -1) {
1399 		NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1400 		*tl++ = 0;
1401 		*tl = 0;
1402 	} else {
1403 		*retopsp = txdr_unsigned(retops);
1404 	}
1405 	if (vp)
1406 		vrele(vp);
1407 	if (savevp)
1408 		vrele(savevp);
1409 	if (savecred != NULL)
1410 		nd->nd_cred = savecred;
1411 	if (rootcred != NULL)
1412 		crfree(rootcred);
1413 	NFSLOCKV4ROOTMUTEX();
1414 	nfsv4_relref(&nfsv4rootfs_lock);
1415 	NFSUNLOCKV4ROOTMUTEX();
1416 
1417 	NFSEXITCODE2(0, nd);
1418 }
1419 
1420 /* Create a credential for "root". */
1421 static struct ucred *
1422 nfsrv_createrootcred(void)
1423 {
1424 	struct ucred *cr;
1425 	gid_t grp;
1426 
1427 	cr = crget();
1428 	cr->cr_uid = cr->cr_ruid = cr->cr_svuid = UID_ROOT;
1429 	grp = GID_WHEEL;
1430 	crsetgroups(cr, 1, &grp);
1431 	cr->cr_rgid = cr->cr_svgid = cr->cr_groups[0];
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