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