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