1/*-
2 * Copyright (c) 1989, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Rick Macklem at The University of Guelph.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 4. Neither the name of the University nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 */
33
34#include <sys/cdefs.h>
35__FBSDID("$FreeBSD: stable/11/sys/fs/nfsserver/nfs_nfsdsocket.c 361236 2020-05-19 01:43:00Z freqlabs $");
36
37/*
38 * Socket operations for use by the nfs server.
39 */
40
41#include <fs/nfs/nfsport.h>
42
43extern struct nfsstatsv1 nfsstatsv1;
44extern struct nfsrvfh nfs_pubfh, nfs_rootfh;
45extern int nfs_pubfhset, nfs_rootfhset;
46extern struct nfsv4lock nfsv4rootfs_lock;
47extern struct nfsrv_stablefirst nfsrv_stablefirst;
48extern struct nfsclienthashhead *nfsclienthash;
49extern int nfsrv_clienthashsize;
50extern int nfsrc_floodlevel, nfsrc_tcpsavedreplies;
51extern int nfsd_debuglevel;
52NFSV4ROOTLOCKMUTEX;
53NFSSTATESPINLOCK;
54
55int (*nfsrv3_procs0[NFS_V3NPROCS])(struct nfsrv_descript *,
56    int, vnode_t , NFSPROC_T *, struct nfsexstuff *) = {
57	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
58	nfsrvd_getattr,
59	nfsrvd_setattr,
60	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
61	nfsrvd_access,
62	nfsrvd_readlink,
63	nfsrvd_read,
64	nfsrvd_write,
65	nfsrvd_create,
66	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
67	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
68	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
69	nfsrvd_remove,
70	nfsrvd_remove,
71	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
72	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
73	nfsrvd_readdir,
74	nfsrvd_readdirplus,
75	nfsrvd_statfs,
76	nfsrvd_fsinfo,
77	nfsrvd_pathconf,
78	nfsrvd_commit,
79};
80
81int (*nfsrv3_procs1[NFS_V3NPROCS])(struct nfsrv_descript *,
82    int, vnode_t , vnode_t *, fhandle_t *,
83    NFSPROC_T *, struct nfsexstuff *) = {
84	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
85	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
86	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
87	nfsrvd_lookup,
88	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
89	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
90	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
91	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
92	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
93	nfsrvd_mkdir,
94	nfsrvd_symlink,
95	nfsrvd_mknod,
96	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
97	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
98	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
99	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
100	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
101	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
102	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
103	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
104	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
105	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
106};
107
108int (*nfsrv3_procs2[NFS_V3NPROCS])(struct nfsrv_descript *,
109    int, vnode_t , vnode_t , NFSPROC_T *,
110    struct nfsexstuff *, struct nfsexstuff *) = {
111	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
112	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
113	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
114	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
115	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
116	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
117	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
118	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
119	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
120	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
121	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
122	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
123	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
124	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
125	nfsrvd_rename,
126	nfsrvd_link,
127	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
128	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
129	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
130	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
131	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
132	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
133};
134
135int (*nfsrv4_ops0[NFSV41_NOPS])(struct nfsrv_descript *,
136    int, vnode_t , NFSPROC_T *, struct nfsexstuff *) = {
137	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
138	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
139	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
140	nfsrvd_access,
141	nfsrvd_close,
142	nfsrvd_commit,
143	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
144	nfsrvd_delegpurge,
145	nfsrvd_delegreturn,
146	nfsrvd_getattr,
147	nfsrvd_getfh,
148	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
149	nfsrvd_lock,
150	nfsrvd_lockt,
151	nfsrvd_locku,
152	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
153	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
154	nfsrvd_verify,
155	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
156	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
157	nfsrvd_openconfirm,
158	nfsrvd_opendowngrade,
159	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
160	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
161	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
162	nfsrvd_read,
163	nfsrvd_readdirplus,
164	nfsrvd_readlink,
165	nfsrvd_remove,
166	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
167	nfsrvd_renew,
168	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
169	(int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
170	nfsrvd_secinfo,
171	nfsrvd_setattr,
172	nfsrvd_setclientid,
173	nfsrvd_setclientidcfrm,
174	nfsrvd_verify,
175	nfsrvd_write,
176	nfsrvd_releaselckown,
177	nfsrvd_notsupp,
178	nfsrvd_bindconnsess,
179	nfsrvd_exchangeid,
180	nfsrvd_createsession,
181	nfsrvd_destroysession,
182	nfsrvd_freestateid,
183	nfsrvd_notsupp,
184	nfsrvd_notsupp,
185	nfsrvd_notsupp,
186	nfsrvd_notsupp,
187	nfsrvd_notsupp,
188	nfsrvd_notsupp,
189	nfsrvd_notsupp,
190	nfsrvd_sequence,
191	nfsrvd_notsupp,
192	nfsrvd_teststateid,
193	nfsrvd_notsupp,
194	nfsrvd_destroyclientid,
195	nfsrvd_reclaimcomplete,
196};
197
198int (*nfsrv4_ops1[NFSV41_NOPS])(struct nfsrv_descript *,
199    int, vnode_t , vnode_t *, fhandle_t *,
200    NFSPROC_T *, struct nfsexstuff *) = {
201	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
202	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
203	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
204	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
205	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
206	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
207	nfsrvd_mknod,
208	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
209	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
210	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
211	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
212	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
213	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
214	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
215	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
216	nfsrvd_lookup,
217	nfsrvd_lookup,
218	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
219	nfsrvd_open,
220	nfsrvd_openattr,
221	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
222	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
223	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
224	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
225	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
226	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
227	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
228	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
229	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
230	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
231	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
232	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
233	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
234	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
235	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
236	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
237	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
238	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
239	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
240	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
241	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
242	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
243	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
244	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
245	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
246	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
247	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
248	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
249	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
250	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
251	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
252	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
253	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
254	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
255	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
256	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
257	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
258	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
259	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
260};
261
262int (*nfsrv4_ops2[NFSV41_NOPS])(struct nfsrv_descript *,
263    int, vnode_t , vnode_t , NFSPROC_T *,
264    struct nfsexstuff *, struct nfsexstuff *) = {
265	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
266	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
267	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
268	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
269	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
270	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
271	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
272	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
273	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
274	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
275	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
276	nfsrvd_link,
277	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
278	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
279	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
280	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
281	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
282	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
283	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
284	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
285	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
286	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
287	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
288	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
289	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
290	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
291	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
292	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
293	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
294	nfsrvd_rename,
295	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
296	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
297	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
298	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
299	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
300	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
301	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
302	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
303	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
304	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
305	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
306	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
307	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
308	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
309	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
310	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
311	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
312	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
313	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
314	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
315	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
316	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
317	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
318	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
319	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
320	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
321	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
322	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
323	(int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
324};
325
326/*
327 * Static array that defines which nfs rpc's are nonidempotent
328 */
329static int nfsrv_nonidempotent[NFS_V3NPROCS] = {
330	FALSE,
331	FALSE,
332	TRUE,
333	FALSE,
334	FALSE,
335	FALSE,
336	FALSE,
337	TRUE,
338	TRUE,
339	TRUE,
340	TRUE,
341	TRUE,
342	TRUE,
343	TRUE,
344	TRUE,
345	TRUE,
346	FALSE,
347	FALSE,
348	FALSE,
349	FALSE,
350	FALSE,
351	FALSE,
352};
353
354/*
355 * This static array indicates whether or not the RPC modifies the
356 * file system.
357 */
358static int nfs_writerpc[NFS_NPROCS] = { 0, 0, 1, 0, 0, 0, 0,
359    1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
360    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
361
362/* local functions */
363static void nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
364    u_char *tag, int taglen, u_int32_t minorvers, NFSPROC_T *p);
365
366
367/*
368 * This static array indicates which server procedures require the extra
369 * arguments to return the current file handle for V2, 3.
370 */
371static int nfs_retfh[NFS_V3NPROCS] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1,
372	1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0 };
373
374extern struct nfsv4_opflag nfsv4_opflag[NFSV41_NOPS];
375
376static int nfsv3to4op[NFS_V3NPROCS] = {
377	NFSPROC_NULL,
378	NFSV4OP_GETATTR,
379	NFSV4OP_SETATTR,
380	NFSV4OP_LOOKUP,
381	NFSV4OP_ACCESS,
382	NFSV4OP_READLINK,
383	NFSV4OP_READ,
384	NFSV4OP_WRITE,
385	NFSV4OP_V3CREATE,
386	NFSV4OP_MKDIR,
387	NFSV4OP_SYMLINK,
388	NFSV4OP_MKNOD,
389	NFSV4OP_REMOVE,
390	NFSV4OP_RMDIR,
391	NFSV4OP_RENAME,
392	NFSV4OP_LINK,
393	NFSV4OP_READDIR,
394	NFSV4OP_READDIRPLUS,
395	NFSV4OP_FSSTAT,
396	NFSV4OP_FSINFO,
397	NFSV4OP_PATHCONF,
398	NFSV4OP_COMMIT,
399};
400
401static struct mtx nfsrvd_statmtx;
402MTX_SYSINIT(nfsst, &nfsrvd_statmtx, "NFSstat", MTX_DEF);
403
404static void
405nfsrvd_statstart(int op, struct bintime *now)
406{
407	if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
408		printf("%s: op %d invalid\n", __func__, op);
409		return;
410	}
411
412	mtx_lock(&nfsrvd_statmtx);
413	if (nfsstatsv1.srvstartcnt == nfsstatsv1.srvdonecnt) {
414		if (now != NULL)
415			nfsstatsv1.busyfrom = *now;
416		else
417			binuptime(&nfsstatsv1.busyfrom);
418
419	}
420	nfsstatsv1.srvrpccnt[op]++;
421	nfsstatsv1.srvstartcnt++;
422	mtx_unlock(&nfsrvd_statmtx);
423
424}
425
426static void
427nfsrvd_statend(int op, uint64_t bytes, struct bintime *now,
428    struct bintime *then)
429{
430	struct bintime dt, lnow;
431
432	if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
433		printf("%s: op %d invalid\n", __func__, op);
434		return;
435	}
436
437	if (now == NULL) {
438		now = &lnow;
439		binuptime(now);
440	}
441
442	mtx_lock(&nfsrvd_statmtx);
443
444	nfsstatsv1.srvbytes[op] += bytes;
445	nfsstatsv1.srvops[op]++;
446
447	if (then != NULL) {
448		dt = *now;
449		bintime_sub(&dt, then);
450		bintime_add(&nfsstatsv1.srvduration[op], &dt);
451	}
452
453	dt = *now;
454	bintime_sub(&dt, &nfsstatsv1.busyfrom);
455	bintime_add(&nfsstatsv1.busytime, &dt);
456	nfsstatsv1.busyfrom = *now;
457
458	nfsstatsv1.srvdonecnt++;
459
460	mtx_unlock(&nfsrvd_statmtx);
461}
462
463/*
464 * Do an RPC. Basically, get the file handles translated to vnode pointers
465 * and then call the appropriate server routine. The server routines are
466 * split into groups, based on whether they use a file handle or file
467 * handle plus name or ...
468 * The NFS V4 Compound RPC is performed separately by nfsrvd_compound().
469 */
470void
471nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, u_char *tag, int taglen,
472    u_int32_t minorvers, NFSPROC_T *p)
473{
474	int error = 0, lktype;
475	vnode_t vp;
476	mount_t mp = NULL;
477	struct nfsrvfh fh;
478	struct nfsexstuff nes;
479
480	/*
481	 * Get a locked vnode for the first file handle
482	 */
483	if (!(nd->nd_flag & ND_NFSV4)) {
484		KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc"));
485		/*
486		 * For NFSv3, if the malloc/mget allocation is near limits,
487		 * return NFSERR_DELAY.
488		 */
489		if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) {
490			nd->nd_repstat = NFSERR_DELAY;
491			vp = NULL;
492		} else {
493			error = nfsrv_mtofh(nd, &fh);
494			if (error) {
495				if (error != EBADRPC)
496					printf("nfs dorpc err1=%d\n", error);
497				nd->nd_repstat = NFSERR_GARBAGE;
498				goto out;
499			}
500			if (nd->nd_procnum == NFSPROC_READ ||
501			    nd->nd_procnum == NFSPROC_WRITE ||
502			    nd->nd_procnum == NFSPROC_READDIR ||
503			    nd->nd_procnum == NFSPROC_READDIRPLUS ||
504			    nd->nd_procnum == NFSPROC_READLINK ||
505			    nd->nd_procnum == NFSPROC_GETATTR ||
506			    nd->nd_procnum == NFSPROC_ACCESS ||
507			    nd->nd_procnum == NFSPROC_FSSTAT ||
508			    nd->nd_procnum == NFSPROC_FSINFO)
509				lktype = LK_SHARED;
510			else
511				lktype = LK_EXCLUSIVE;
512			if (nd->nd_flag & ND_PUBLOOKUP)
513				nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes,
514				    &mp, nfs_writerpc[nd->nd_procnum], p);
515			else
516				nfsd_fhtovp(nd, &fh, lktype, &vp, &nes,
517				    &mp, nfs_writerpc[nd->nd_procnum], p);
518			if (nd->nd_repstat == NFSERR_PROGNOTV4)
519				goto out;
520		}
521	}
522
523	/*
524	 * For V2 and 3, set the ND_SAVEREPLY flag for the recent request
525	 * cache, as required.
526	 * For V4, nfsrvd_compound() does this.
527	 */
528	if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum])
529		nd->nd_flag |= ND_SAVEREPLY;
530
531	nfsrvd_rephead(nd);
532	/*
533	 * If nd_repstat is non-zero, just fill in the reply status
534	 * to complete the RPC reply for V2. Otherwise, you must do
535	 * the RPC.
536	 */
537	if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) {
538		*nd->nd_errp = nfsd_errmap(nd);
539		nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], /*now*/ NULL);
540		nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
541		   /*now*/ NULL, /*then*/ NULL);
542		if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0)
543			vn_finished_write(mp);
544		goto out;
545	}
546
547	/*
548	 * Now the procedure can be performed. For V4, nfsrvd_compound()
549	 * works through the sub-rpcs, otherwise just call the procedure.
550	 * The procedures are in three groups with different arguments.
551	 * The group is indicated by the value in nfs_retfh[].
552	 */
553	if (nd->nd_flag & ND_NFSV4) {
554		nfsrvd_compound(nd, isdgram, tag, taglen, minorvers, p);
555	} else {
556		struct bintime start_time;
557
558		binuptime(&start_time);
559		nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], &start_time);
560
561		if (nfs_retfh[nd->nd_procnum] == 1) {
562			if (vp)
563				NFSVOPUNLOCK(vp, 0);
564			error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram,
565			    vp, NULL, (fhandle_t *)fh.nfsrvfh_data, p, &nes);
566		} else if (nfs_retfh[nd->nd_procnum] == 2) {
567			error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram,
568			    vp, NULL, p, &nes, NULL);
569		} else {
570			error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
571			    vp, p, &nes);
572		}
573		if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0)
574			vn_finished_write(mp);
575
576		nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
577		    /*now*/ NULL, /*then*/ &start_time);
578	}
579	if (error) {
580		if (error != EBADRPC)
581			printf("nfs dorpc err2=%d\n", error);
582		nd->nd_repstat = NFSERR_GARBAGE;
583	}
584	*nd->nd_errp = nfsd_errmap(nd);
585
586	/*
587	 * Don't cache certain reply status values.
588	 */
589	if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) &&
590	    (nd->nd_repstat == NFSERR_GARBAGE ||
591	     nd->nd_repstat == NFSERR_BADXDR ||
592	     nd->nd_repstat == NFSERR_MOVED ||
593	     nd->nd_repstat == NFSERR_DELAY ||
594	     nd->nd_repstat == NFSERR_BADSEQID ||
595	     nd->nd_repstat == NFSERR_RESOURCE ||
596	     nd->nd_repstat == NFSERR_SERVERFAULT ||
597	     nd->nd_repstat == NFSERR_STALECLIENTID ||
598	     nd->nd_repstat == NFSERR_STALESTATEID ||
599	     nd->nd_repstat == NFSERR_OLDSTATEID ||
600	     nd->nd_repstat == NFSERR_BADSTATEID ||
601	     nd->nd_repstat == NFSERR_GRACE ||
602	     nd->nd_repstat == NFSERR_NOGRACE))
603		nd->nd_flag &= ~ND_SAVEREPLY;
604
605out:
606	NFSEXITCODE2(0, nd);
607}
608
609/*
610 * Breaks down a compound RPC request and calls the server routines for
611 * the subprocedures.
612 * Some suboperations are performed directly here to simplify file handle<-->
613 * vnode pointer handling.
614 */
615static void
616nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,
617    int taglen, u_int32_t minorvers, NFSPROC_T *p)
618{
619	int i, lktype, op, op0 = 0, statsinprog = 0;
620	u_int32_t *tl;
621	struct nfsclient *clp, *nclp;
622	int numops, error = 0, igotlock;
623	u_int32_t retops = 0, *retopsp = NULL, *repp;
624	vnode_t vp, nvp, savevp;
625	struct nfsrvfh fh;
626	mount_t new_mp, temp_mp = NULL;
627	struct ucred *credanon;
628	struct nfsexstuff nes, vpnes, savevpnes;
629	fsid_t cur_fsid, save_fsid;
630	static u_int64_t compref = 0;
631	struct bintime start_time;
632
633	NFSVNO_EXINIT(&vpnes);
634	NFSVNO_EXINIT(&savevpnes);
635	/*
636	 * Put the seq# of the current compound RPC in nfsrv_descript.
637	 * (This is used by nfsrv_checkgetattr(), to see if the write
638	 *  delegation was created by the same compound RPC as the one
639	 *  with that Getattr in it.)
640	 * Don't worry about the 64bit number wrapping around. It ain't
641	 * gonna happen before this server gets shut down/rebooted.
642	 */
643	nd->nd_compref = compref++;
644
645	/*
646	 * Check for and optionally get a lock on the root. This lock means that
647	 * no nfsd will be fiddling with the V4 file system and state stuff. It
648	 * is required when the V4 root is being changed, the stable storage
649	 * restart file is being updated, or callbacks are being done.
650	 * When any of the nfsd are processing an NFSv4 compound RPC, they must
651	 * either hold a reference count (nfs_usecnt) or the lock. When
652	 * nfsrv_unlock() is called to release the lock, it can optionally
653	 * also get a reference count, which saves the need for a call to
654	 * nfsrv_getref() after nfsrv_unlock().
655	 */
656	/*
657	 * First, check to see if we need to wait for an update lock.
658	 */
659	igotlock = 0;
660	NFSLOCKV4ROOTMUTEX();
661	if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK)
662		igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
663		    NFSV4ROOTLOCKMUTEXPTR, NULL);
664	else
665		igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
666		    NFSV4ROOTLOCKMUTEXPTR, NULL);
667	NFSUNLOCKV4ROOTMUTEX();
668	if (igotlock) {
669		/*
670		 * If I got the lock, I can update the stable storage file.
671		 * Done when the grace period is over or a client has long
672		 * since expired.
673		 */
674		nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK;
675		if ((nfsrv_stablefirst.nsf_flags &
676		    (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
677			nfsrv_updatestable(p);
678
679		/*
680		 * If at least one client has long since expired, search
681		 * the client list for them, write a REVOKE record on the
682		 * stable storage file and then remove them from the client
683		 * list.
684		 */
685		if (nfsrv_stablefirst.nsf_flags & NFSNSF_EXPIREDCLIENT) {
686			nfsrv_stablefirst.nsf_flags &= ~NFSNSF_EXPIREDCLIENT;
687			for (i = 0; i < nfsrv_clienthashsize; i++) {
688			    LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash,
689				nclp) {
690				if (clp->lc_flags & LCL_EXPIREIT) {
691				    if (!LIST_EMPTY(&clp->lc_open) ||
692					!LIST_EMPTY(&clp->lc_deleg))
693					nfsrv_writestable(clp->lc_id,
694					    clp->lc_idlen, NFSNST_REVOKE, p);
695				    nfsrv_cleanclient(clp, p);
696				    nfsrv_freedeleglist(&clp->lc_deleg);
697				    nfsrv_freedeleglist(&clp->lc_olddeleg);
698				    LIST_REMOVE(clp, lc_hash);
699				    nfsrv_zapclient(clp, p);
700				}
701			    }
702			}
703		}
704		NFSLOCKV4ROOTMUTEX();
705		nfsv4_unlock(&nfsv4rootfs_lock, 1);
706		NFSUNLOCKV4ROOTMUTEX();
707	} else {
708		/*
709		 * If we didn't get the lock, we need to get a refcnt,
710		 * which also checks for and waits for the lock.
711		 */
712		NFSLOCKV4ROOTMUTEX();
713		nfsv4_getref(&nfsv4rootfs_lock, NULL,
714		    NFSV4ROOTLOCKMUTEXPTR, NULL);
715		NFSUNLOCKV4ROOTMUTEX();
716	}
717
718	/*
719	 * If flagged, search for open owners that haven't had any opens
720	 * for a long time.
721	 */
722	if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) {
723		nfsrv_throwawayopens(p);
724	}
725
726	savevp = vp = NULL;
727	save_fsid.val[0] = save_fsid.val[1] = 0;
728	cur_fsid.val[0] = cur_fsid.val[1] = 0;
729
730	/* If taglen < 0, there was a parsing error in nfsd_getminorvers(). */
731	if (taglen < 0) {
732		error = EBADRPC;
733		goto nfsmout;
734	}
735
736	(void) nfsm_strtom(nd, tag, taglen);
737	NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED);
738	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
739	if (minorvers != NFSV4_MINORVERSION && minorvers != NFSV41_MINORVERSION)
740		nd->nd_repstat = NFSERR_MINORVERMISMATCH;
741	if (nd->nd_repstat)
742		numops = 0;
743	else
744		numops = fxdr_unsigned(int, *tl);
745	/*
746	 * Loop around doing the sub ops.
747	 * vp - is an unlocked vnode pointer for the CFH
748	 * savevp - is an unlocked vnode pointer for the SAVEDFH
749	 * (at some future date, it might turn out to be more appropriate
750	 *  to keep the file handles instead of vnode pointers?)
751	 * savevpnes and vpnes - are the export flags for the above.
752	 */
753	for (i = 0; i < numops; i++) {
754		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
755		NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED);
756		*repp = *tl;
757		op = fxdr_unsigned(int, *tl);
758		NFSD_DEBUG(4, "op=%d\n", op);
759		if (op < NFSV4OP_ACCESS ||
760		    (op >= NFSV4OP_NOPS && (nd->nd_flag & ND_NFSV41) == 0) ||
761		    (op >= NFSV41_NOPS && (nd->nd_flag & ND_NFSV41) != 0)) {
762			nd->nd_repstat = NFSERR_OPILLEGAL;
763			*repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL);
764			*repp = nfsd_errmap(nd);
765			retops++;
766			break;
767		} else {
768			repp++;
769		}
770
771		binuptime(&start_time);
772		nfsrvd_statstart(op, &start_time);
773		statsinprog = 1;
774
775		if (i == 0)
776			op0 = op;
777		if (i == numops - 1)
778			nd->nd_flag |= ND_LASTOP;
779
780		/*
781		 * Check for a referral on the current FH and, if so, return
782		 * NFSERR_MOVED for all ops that allow it, except Getattr.
783		 */
784		if (vp != NULL && op != NFSV4OP_GETATTR &&
785		    nfsv4root_getreferral(vp, NULL, 0) != NULL &&
786		    nfsrv_errmoved(op)) {
787			nd->nd_repstat = NFSERR_MOVED;
788			*repp = nfsd_errmap(nd);
789			retops++;
790			break;
791		}
792
793		/*
794		 * For NFSv4.1, check for a Sequence Operation being first
795		 * or one of the other allowed operations by itself.
796		 */
797		if ((nd->nd_flag & ND_NFSV41) != 0) {
798			if (i != 0 && op == NFSV4OP_SEQUENCE)
799				nd->nd_repstat = NFSERR_SEQUENCEPOS;
800			else if (i == 0 && op != NFSV4OP_SEQUENCE &&
801			    op != NFSV4OP_EXCHANGEID &&
802			    op != NFSV4OP_CREATESESSION &&
803			    op != NFSV4OP_BINDCONNTOSESS &&
804			    op != NFSV4OP_DESTROYCLIENTID &&
805			    op != NFSV4OP_DESTROYSESSION)
806				nd->nd_repstat = NFSERR_OPNOTINSESS;
807			else if (i != 0 && op0 != NFSV4OP_SEQUENCE)
808				nd->nd_repstat = NFSERR_NOTONLYOP;
809			if (nd->nd_repstat != 0) {
810				*repp = nfsd_errmap(nd);
811				retops++;
812				break;
813			}
814		}
815
816		nd->nd_procnum = op;
817		/*
818		 * If over flood level, reply NFSERR_RESOURCE, if at the first
819		 * Op. (Since a client recovery from NFSERR_RESOURCE can get
820		 * really nasty for certain Op sequences, I'll play it safe
821		 * and only return the error at the beginning.) The cache
822		 * will still function over flood level, but uses lots of
823		 * mbufs.)
824		 * If nfsrv_mallocmget_limit() returns True, the system is near
825		 * to its limit for memory that malloc()/mget() can allocate.
826		 */
827		if (i == 0 && (nd->nd_rp == NULL ||
828		    nd->nd_rp->rc_refcnt == 0) &&
829		    (nfsrv_mallocmget_limit() ||
830		     nfsrc_tcpsavedreplies > nfsrc_floodlevel)) {
831			if (nfsrc_tcpsavedreplies > nfsrc_floodlevel)
832				printf("nfsd server cache flooded, try "
833				    "increasing vfs.nfsd.tcphighwater\n");
834			nd->nd_repstat = NFSERR_RESOURCE;
835			*repp = nfsd_errmap(nd);
836			if (op == NFSV4OP_SETATTR) {
837				/*
838				 * Setattr replies require a bitmap.
839				 * even for errors like these.
840				 */
841				NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
842				*tl = 0;
843			}
844			retops++;
845			break;
846		}
847		if (nfsv4_opflag[op].savereply)
848			nd->nd_flag |= ND_SAVEREPLY;
849		switch (op) {
850		case NFSV4OP_PUTFH:
851			error = nfsrv_mtofh(nd, &fh);
852			if (error)
853				goto nfsmout;
854			if (!nd->nd_repstat)
855				nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
856				    NULL, 0, p);
857			/* For now, allow this for non-export FHs */
858			if (!nd->nd_repstat) {
859				if (vp)
860					vrele(vp);
861				vp = nvp;
862				cur_fsid = vp->v_mount->mnt_stat.f_fsid;
863				NFSVOPUNLOCK(vp, 0);
864				vpnes = nes;
865			}
866			break;
867		case NFSV4OP_PUTPUBFH:
868			if (nfs_pubfhset)
869			    nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
870				&nes, NULL, 0, p);
871			else
872			    nd->nd_repstat = NFSERR_NOFILEHANDLE;
873			if (!nd->nd_repstat) {
874				if (vp)
875					vrele(vp);
876				vp = nvp;
877				cur_fsid = vp->v_mount->mnt_stat.f_fsid;
878				NFSVOPUNLOCK(vp, 0);
879				vpnes = nes;
880			}
881			break;
882		case NFSV4OP_PUTROOTFH:
883			if (nfs_rootfhset) {
884				nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp,
885				    &nes, NULL, 0, p);
886				if (!nd->nd_repstat) {
887					if (vp)
888						vrele(vp);
889					vp = nvp;
890					cur_fsid = vp->v_mount->mnt_stat.f_fsid;
891					NFSVOPUNLOCK(vp, 0);
892					vpnes = nes;
893				}
894			} else
895				nd->nd_repstat = NFSERR_NOFILEHANDLE;
896			break;
897		case NFSV4OP_SAVEFH:
898			if (vp && NFSVNO_EXPORTED(&vpnes)) {
899				nd->nd_repstat = 0;
900				/* If vp == savevp, a no-op */
901				if (vp != savevp) {
902					if (savevp)
903						vrele(savevp);
904					VREF(vp);
905					savevp = vp;
906					savevpnes = vpnes;
907					save_fsid = cur_fsid;
908				}
909			} else {
910				nd->nd_repstat = NFSERR_NOFILEHANDLE;
911			}
912			break;
913		case NFSV4OP_RESTOREFH:
914			if (savevp) {
915				nd->nd_repstat = 0;
916				/* If vp == savevp, a no-op */
917				if (vp != savevp) {
918					VREF(savevp);
919					vrele(vp);
920					vp = savevp;
921					vpnes = savevpnes;
922					cur_fsid = save_fsid;
923				}
924			} else {
925				nd->nd_repstat = NFSERR_RESTOREFH;
926			}
927			break;
928		default:
929		    /*
930		     * Allow a Lookup, Getattr, GetFH, Secinfo on an
931		     * non-exported directory if
932		     * nfs_rootfhset. Do I need to allow any other Ops?
933		     * (You can only have a non-exported vpnes if
934		     *  nfs_rootfhset is true. See nfsd_fhtovp())
935		     * Allow AUTH_SYS to be used for file systems
936		     * exported GSS only for certain Ops, to allow
937		     * clients to do mounts more easily.
938		     */
939		    if (nfsv4_opflag[op].needscfh && vp) {
940			if (!NFSVNO_EXPORTED(&vpnes) &&
941			    op != NFSV4OP_LOOKUP &&
942			    op != NFSV4OP_GETATTR &&
943			    op != NFSV4OP_GETFH &&
944			    op != NFSV4OP_ACCESS &&
945			    op != NFSV4OP_READLINK &&
946			    op != NFSV4OP_SECINFO)
947				nd->nd_repstat = NFSERR_NOFILEHANDLE;
948			else if (nfsvno_testexp(nd, &vpnes) &&
949			    op != NFSV4OP_LOOKUP &&
950			    op != NFSV4OP_GETFH &&
951			    op != NFSV4OP_GETATTR &&
952			    op != NFSV4OP_SECINFO)
953				nd->nd_repstat = NFSERR_WRONGSEC;
954			if (nd->nd_repstat) {
955				if (op == NFSV4OP_SETATTR) {
956				    /*
957				     * Setattr reply requires a bitmap
958				     * even for errors like these.
959				     */
960				    NFSM_BUILD(tl, u_int32_t *,
961					NFSX_UNSIGNED);
962				    *tl = 0;
963				}
964				break;
965			}
966		    }
967		    if (nfsv4_opflag[op].retfh == 1) {
968			if (!vp) {
969				nd->nd_repstat = NFSERR_NOFILEHANDLE;
970				break;
971			}
972			VREF(vp);
973			if (nfsv4_opflag[op].modifyfs)
974				vn_start_write(vp, &temp_mp, V_WAIT);
975			error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
976			    &nvp, (fhandle_t *)fh.nfsrvfh_data, p, &vpnes);
977			if (!error && !nd->nd_repstat) {
978			    if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) {
979				new_mp = nvp->v_mount;
980				if (cur_fsid.val[0] !=
981				    new_mp->mnt_stat.f_fsid.val[0] ||
982				    cur_fsid.val[1] !=
983				    new_mp->mnt_stat.f_fsid.val[1]) {
984				    /* crossed a server mount point */
985				    nd->nd_repstat = nfsvno_checkexp(new_mp,
986					nd->nd_nam, &nes, &credanon);
987				    if (!nd->nd_repstat)
988					nd->nd_repstat = nfsd_excred(nd,
989					    &nes, credanon);
990				    if (credanon != NULL)
991					crfree(credanon);
992				    if (!nd->nd_repstat) {
993					vpnes = nes;
994					cur_fsid = new_mp->mnt_stat.f_fsid;
995				    }
996				}
997				/* Lookup ops return a locked vnode */
998				NFSVOPUNLOCK(nvp, 0);
999			    }
1000			    if (!nd->nd_repstat) {
1001				    vrele(vp);
1002				    vp = nvp;
1003			    } else
1004				    vrele(nvp);
1005			}
1006			if (nfsv4_opflag[op].modifyfs)
1007				vn_finished_write(temp_mp);
1008		    } else if (nfsv4_opflag[op].retfh == 2) {
1009			if (vp == NULL || savevp == NULL) {
1010				nd->nd_repstat = NFSERR_NOFILEHANDLE;
1011				break;
1012			} else if (cur_fsid.val[0] != save_fsid.val[0] ||
1013			    cur_fsid.val[1] != save_fsid.val[1]) {
1014				nd->nd_repstat = NFSERR_XDEV;
1015				break;
1016			}
1017			if (nfsv4_opflag[op].modifyfs)
1018				vn_start_write(savevp, &temp_mp, V_WAIT);
1019			if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
1020				VREF(vp);
1021				VREF(savevp);
1022				error = (*(nfsrv4_ops2[op]))(nd, isdgram,
1023				    savevp, vp, p, &savevpnes, &vpnes);
1024			} else
1025				nd->nd_repstat = NFSERR_PERM;
1026			if (nfsv4_opflag[op].modifyfs)
1027				vn_finished_write(temp_mp);
1028		    } else {
1029			if (nfsv4_opflag[op].retfh != 0)
1030				panic("nfsrvd_compound");
1031			if (nfsv4_opflag[op].needscfh) {
1032				if (vp != NULL) {
1033					lktype = nfsv4_opflag[op].lktype;
1034					if (nfsv4_opflag[op].modifyfs) {
1035						vn_start_write(vp, &temp_mp,
1036						    V_WAIT);
1037						if (op == NFSV4OP_WRITE &&
1038						    MNT_SHARED_WRITES(temp_mp))
1039							lktype = LK_SHARED;
1040					}
1041					if (NFSVOPLOCK(vp, lktype) == 0)
1042						VREF(vp);
1043					else
1044						nd->nd_repstat = NFSERR_PERM;
1045				} else {
1046					nd->nd_repstat = NFSERR_NOFILEHANDLE;
1047					if (op == NFSV4OP_SETATTR) {
1048						/*
1049						 * Setattr reply requires a
1050						 * bitmap even for errors like
1051						 * these.
1052						 */
1053						NFSM_BUILD(tl, u_int32_t *,
1054						    NFSX_UNSIGNED);
1055						*tl = 0;
1056					}
1057					break;
1058				}
1059				if (nd->nd_repstat == 0)
1060					error = (*(nfsrv4_ops0[op]))(nd,
1061					    isdgram, vp, p, &vpnes);
1062				if (nfsv4_opflag[op].modifyfs)
1063					vn_finished_write(temp_mp);
1064			} else {
1065				error = (*(nfsrv4_ops0[op]))(nd, isdgram,
1066				    NULL, p, &vpnes);
1067			}
1068		    }
1069		}
1070		if (error) {
1071			if (error == EBADRPC || error == NFSERR_BADXDR) {
1072				nd->nd_repstat = NFSERR_BADXDR;
1073			} else {
1074				nd->nd_repstat = error;
1075				printf("nfsv4 comperr0=%d\n", error);
1076			}
1077			error = 0;
1078		}
1079
1080		if (statsinprog != 0) {
1081			nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1082			    /*then*/ &start_time);
1083			statsinprog = 0;
1084		}
1085
1086		retops++;
1087		if (nd->nd_repstat) {
1088			*repp = nfsd_errmap(nd);
1089			break;
1090		} else {
1091			*repp = 0;	/* NFS4_OK */
1092		}
1093	}
1094nfsmout:
1095	if (statsinprog != 0) {
1096		nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1097		    /*then*/ &start_time);
1098		statsinprog = 0;
1099	}
1100	if (error) {
1101		if (error == EBADRPC || error == NFSERR_BADXDR)
1102			nd->nd_repstat = NFSERR_BADXDR;
1103		else
1104			printf("nfsv4 comperr1=%d\n", error);
1105	}
1106	if (taglen == -1) {
1107		NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1108		*tl++ = 0;
1109		*tl = 0;
1110	} else {
1111		*retopsp = txdr_unsigned(retops);
1112	}
1113	if (vp)
1114		vrele(vp);
1115	if (savevp)
1116		vrele(savevp);
1117	NFSLOCKV4ROOTMUTEX();
1118	nfsv4_relref(&nfsv4rootfs_lock);
1119	NFSUNLOCKV4ROOTMUTEX();
1120
1121	NFSEXITCODE2(0, nd);
1122}
1123