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