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
45extern struct nfsrvfh nfs_pubfh;
46extern int nfs_pubfhset;
47extern struct nfsv4lock nfsv4rootfs_lock;
48extern int nfsrv_clienthashsize;
49extern int nfsd_debuglevel;
50extern int nfsrv_layouthighwater;
51extern volatile int nfsrv_layoutcnt;
52NFSV4ROOTLOCKMUTEX;
53NFSSTATESPINLOCK;
54
55NFSD_VNET_DECLARE(struct nfsrv_stablefirst, nfsrv_stablefirst);
56NFSD_VNET_DECLARE(struct nfsclienthashhead *, nfsclienthash);
57NFSD_VNET_DECLARE(int, nfsrc_floodlevel);
58NFSD_VNET_DECLARE(int, nfsrc_tcpsavedreplies);
59NFSD_VNET_DECLARE(struct nfsrvfh, nfs_rootfh);
60NFSD_VNET_DECLARE(int, nfs_rootfhset);
61NFSD_VNET_DECLARE(struct nfsstatsv1 *, nfsstatsv1_p);
62
63int (*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
89int (*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
115int (*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
141int (*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
221int (*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
301int (*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 */
384static 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 */
413int 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
417SYSCTL_DECL(_vfs_nfsd);
418static int	nfs_minminorv4 = NFSV4_MINORVERSION;
419SYSCTL_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
423static int	nfs_maxminorv4 = NFSV42_MINORVERSION;
424SYSCTL_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 */
429static 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 */
436static 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
439extern struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS];
440
441static 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
466static struct mtx nfsrvd_statmtx;
467MTX_SYSINIT(nfsst, &nfsrvd_statmtx, "NFSstat", MTX_DEF);
468
469static struct ucred *nfsrv_createrootcred(void);
470
471static void
472nfsrvd_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
494static void
495nfsrvd_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 */
538void
539nfsrvd_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;
557tryagain:
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
698out:
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 */
708static void
709nfsrvd_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;
1221tryagain:
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	}
1386nfsmout:
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". */
1421static struct ucred *
1422nfsrv_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