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