]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/fs/nfsserver/nfs_nfsdsocket.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.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  * 4. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  */
33
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
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 nfsstats newnfsstats;
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 /*
404  * Do an RPC. Basically, get the file handles translated to vnode pointers
405  * and then call the appropriate server routine. The server routines are
406  * split into groups, based on whether they use a file handle or file
407  * handle plus name or ...
408  * The NFS V4 Compound RPC is performed separately by nfsrvd_compound().
409  */
410 APPLESTATIC void
411 nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, u_char *tag, int taglen,
412     u_int32_t minorvers, NFSPROC_T *p)
413 {
414         int error = 0, lktype;
415         vnode_t vp;
416         mount_t mp = NULL;
417         struct nfsrvfh fh;
418         struct nfsexstuff nes;
419
420         /*
421          * Get a locked vnode for the first file handle
422          */
423         if (!(nd->nd_flag & ND_NFSV4)) {
424                 KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc"));
425                 /*
426                  * For NFSv3, if the malloc/mget allocation is near limits,
427                  * return NFSERR_DELAY.
428                  */
429                 if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) {
430                         nd->nd_repstat = NFSERR_DELAY;
431                         vp = NULL;
432                 } else {
433                         error = nfsrv_mtofh(nd, &fh);
434                         if (error) {
435                                 if (error != EBADRPC)
436                                         printf("nfs dorpc err1=%d\n", error);
437                                 nd->nd_repstat = NFSERR_GARBAGE;
438                                 goto out;
439                         }
440                         if (nd->nd_procnum == NFSPROC_READ ||
441                             nd->nd_procnum == NFSPROC_WRITE ||
442                             nd->nd_procnum == NFSPROC_READDIR ||
443                             nd->nd_procnum == NFSPROC_READDIRPLUS ||
444                             nd->nd_procnum == NFSPROC_READLINK ||
445                             nd->nd_procnum == NFSPROC_GETATTR ||
446                             nd->nd_procnum == NFSPROC_ACCESS ||
447                             nd->nd_procnum == NFSPROC_FSSTAT ||
448                             nd->nd_procnum == NFSPROC_FSINFO)
449                                 lktype = LK_SHARED;
450                         else
451                                 lktype = LK_EXCLUSIVE;
452                         if (nd->nd_flag & ND_PUBLOOKUP)
453                                 nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes,
454                                     &mp, nfs_writerpc[nd->nd_procnum], p);
455                         else
456                                 nfsd_fhtovp(nd, &fh, lktype, &vp, &nes,
457                                     &mp, nfs_writerpc[nd->nd_procnum], p);
458                         if (nd->nd_repstat == NFSERR_PROGNOTV4)
459                                 goto out;
460                 }
461         }
462
463         /*
464          * For V2 and 3, set the ND_SAVEREPLY flag for the recent request
465          * cache, as required.
466          * For V4, nfsrvd_compound() does this.
467          */
468         if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum])
469                 nd->nd_flag |= ND_SAVEREPLY;
470
471         nfsrvd_rephead(nd);
472         /*
473          * If nd_repstat is non-zero, just fill in the reply status
474          * to complete the RPC reply for V2. Otherwise, you must do
475          * the RPC.
476          */
477         if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) {
478                 *nd->nd_errp = nfsd_errmap(nd);
479                 NFSINCRGLOBAL(newnfsstats.srvrpccnt[nfsv3to4op[nd->nd_procnum]]);
480                 if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0)
481                         vn_finished_write(mp);
482                 goto out;
483         }
484
485         /*
486          * Now the procedure can be performed. For V4, nfsrvd_compound()
487          * works through the sub-rpcs, otherwise just call the procedure.
488          * The procedures are in three groups with different arguments.
489          * The group is indicated by the value in nfs_retfh[].
490          */
491         if (nd->nd_flag & ND_NFSV4) {
492                 nfsrvd_compound(nd, isdgram, tag, taglen, minorvers, p);
493         } else {
494                 if (nfs_retfh[nd->nd_procnum] == 1) {
495                         if (vp)
496                                 NFSVOPUNLOCK(vp, 0);
497                         error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram,
498                             vp, NULL, (fhandle_t *)fh.nfsrvfh_data, p, &nes);
499                 } else if (nfs_retfh[nd->nd_procnum] == 2) {
500                         error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram,
501                             vp, NULL, p, &nes, NULL);
502                 } else {
503                         error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
504                             vp, p, &nes);
505                 }
506                 if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0)
507                         vn_finished_write(mp);
508                 NFSINCRGLOBAL(newnfsstats.srvrpccnt[nfsv3to4op[nd->nd_procnum]]);
509         }
510         if (error) {
511                 if (error != EBADRPC)
512                         printf("nfs dorpc err2=%d\n", error);
513                 nd->nd_repstat = NFSERR_GARBAGE;
514         }
515         *nd->nd_errp = nfsd_errmap(nd);
516
517         /*
518          * Don't cache certain reply status values.
519          */
520         if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) &&
521             (nd->nd_repstat == NFSERR_GARBAGE ||
522              nd->nd_repstat == NFSERR_BADXDR ||
523              nd->nd_repstat == NFSERR_MOVED ||
524              nd->nd_repstat == NFSERR_DELAY ||
525              nd->nd_repstat == NFSERR_BADSEQID ||
526              nd->nd_repstat == NFSERR_RESOURCE ||
527              nd->nd_repstat == NFSERR_SERVERFAULT ||
528              nd->nd_repstat == NFSERR_STALECLIENTID ||
529              nd->nd_repstat == NFSERR_STALESTATEID ||
530              nd->nd_repstat == NFSERR_OLDSTATEID ||
531              nd->nd_repstat == NFSERR_BADSTATEID ||
532              nd->nd_repstat == NFSERR_GRACE ||
533              nd->nd_repstat == NFSERR_NOGRACE))
534                 nd->nd_flag &= ~ND_SAVEREPLY;
535
536 out:
537         NFSEXITCODE2(0, nd);
538 }
539
540 /*
541  * Breaks down a compound RPC request and calls the server routines for
542  * the subprocedures.
543  * Some suboperations are performed directly here to simplify file handle<-->
544  * vnode pointer handling.
545  */
546 static void
547 nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,
548     int taglen, u_int32_t minorvers, NFSPROC_T *p)
549 {
550         int i, lktype, op, op0 = 0;
551         u_int32_t *tl;
552         struct nfsclient *clp, *nclp;
553         int numops, error = 0, igotlock;
554         u_int32_t retops = 0, *retopsp = NULL, *repp;
555         vnode_t vp, nvp, savevp;
556         struct nfsrvfh fh;
557         mount_t new_mp, temp_mp = NULL;
558         struct ucred *credanon;
559         struct nfsexstuff nes, vpnes, savevpnes;
560         fsid_t cur_fsid, save_fsid;
561         static u_int64_t compref = 0;
562
563         NFSVNO_EXINIT(&vpnes);
564         NFSVNO_EXINIT(&savevpnes);
565         /*
566          * Put the seq# of the current compound RPC in nfsrv_descript.
567          * (This is used by nfsrv_checkgetattr(), to see if the write
568          *  delegation was created by the same compound RPC as the one
569          *  with that Getattr in it.)
570          * Don't worry about the 64bit number wrapping around. It ain't
571          * gonna happen before this server gets shut down/rebooted.
572          */
573         nd->nd_compref = compref++;
574
575         /*
576          * Check for and optionally get a lock on the root. This lock means that
577          * no nfsd will be fiddling with the V4 file system and state stuff. It
578          * is required when the V4 root is being changed, the stable storage
579          * restart file is being updated, or callbacks are being done.
580          * When any of the nfsd are processing an NFSv4 compound RPC, they must
581          * either hold a reference count (nfs_usecnt) or the lock. When
582          * nfsrv_unlock() is called to release the lock, it can optionally
583          * also get a reference count, which saves the need for a call to
584          * nfsrv_getref() after nfsrv_unlock().
585          */
586         /*
587          * First, check to see if we need to wait for an update lock.
588          */
589         igotlock = 0;
590         NFSLOCKV4ROOTMUTEX();
591         if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK)
592                 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
593                     NFSV4ROOTLOCKMUTEXPTR, NULL);
594         else
595                 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
596                     NFSV4ROOTLOCKMUTEXPTR, NULL);
597         NFSUNLOCKV4ROOTMUTEX();
598         if (igotlock) {
599                 /*
600                  * If I got the lock, I can update the stable storage file.
601                  * Done when the grace period is over or a client has long
602                  * since expired.
603                  */
604                 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK;
605                 if ((nfsrv_stablefirst.nsf_flags &
606                     (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
607                         nfsrv_updatestable(p);
608
609                 /*
610                  * If at least one client has long since expired, search
611                  * the client list for them, write a REVOKE record on the
612                  * stable storage file and then remove them from the client
613                  * list.
614                  */
615                 if (nfsrv_stablefirst.nsf_flags & NFSNSF_EXPIREDCLIENT) {
616                         nfsrv_stablefirst.nsf_flags &= ~NFSNSF_EXPIREDCLIENT;
617                         for (i = 0; i < nfsrv_clienthashsize; i++) {
618                             LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash,
619                                 nclp) {
620                                 if (clp->lc_flags & LCL_EXPIREIT) {
621                                     if (!LIST_EMPTY(&clp->lc_open) ||
622                                         !LIST_EMPTY(&clp->lc_deleg))
623                                         nfsrv_writestable(clp->lc_id,
624                                             clp->lc_idlen, NFSNST_REVOKE, p);
625                                     nfsrv_cleanclient(clp, p);
626                                     nfsrv_freedeleglist(&clp->lc_deleg);
627                                     nfsrv_freedeleglist(&clp->lc_olddeleg);
628                                     LIST_REMOVE(clp, lc_hash);
629                                     nfsrv_zapclient(clp, p);
630                                 }
631                             }
632                         }
633                 }
634                 NFSLOCKV4ROOTMUTEX();
635                 nfsv4_unlock(&nfsv4rootfs_lock, 1);
636                 NFSUNLOCKV4ROOTMUTEX();
637         } else {
638                 /*
639                  * If we didn't get the lock, we need to get a refcnt,
640                  * which also checks for and waits for the lock.
641                  */
642                 NFSLOCKV4ROOTMUTEX();
643                 nfsv4_getref(&nfsv4rootfs_lock, NULL,
644                     NFSV4ROOTLOCKMUTEXPTR, NULL);
645                 NFSUNLOCKV4ROOTMUTEX();
646         }
647
648         /*
649          * If flagged, search for open owners that haven't had any opens
650          * for a long time.
651          */
652         if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) {
653                 nfsrv_throwawayopens(p);
654         }
655
656         savevp = vp = NULL;
657         save_fsid.val[0] = save_fsid.val[1] = 0;
658         cur_fsid.val[0] = cur_fsid.val[1] = 0;
659
660         /* If taglen < 0, there was a parsing error in nfsd_getminorvers(). */
661         if (taglen < 0) {
662                 error = EBADRPC;
663                 goto nfsmout;
664         }
665
666         (void) nfsm_strtom(nd, tag, taglen);
667         NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED);
668         NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
669         if (minorvers != NFSV4_MINORVERSION && minorvers != NFSV41_MINORVERSION)
670                 nd->nd_repstat = NFSERR_MINORVERMISMATCH;
671         if (nd->nd_repstat)
672                 numops = 0;
673         else
674                 numops = fxdr_unsigned(int, *tl);
675         /*
676          * Loop around doing the sub ops.
677          * vp - is an unlocked vnode pointer for the CFH
678          * savevp - is an unlocked vnode pointer for the SAVEDFH
679          * (at some future date, it might turn out to be more appropriate
680          *  to keep the file handles instead of vnode pointers?)
681          * savevpnes and vpnes - are the export flags for the above.
682          */
683         for (i = 0; i < numops; i++) {
684                 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
685                 NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED);
686                 *repp = *tl;
687                 op = fxdr_unsigned(int, *tl);
688                 NFSD_DEBUG(4, "op=%d\n", op);
689                 if (op < NFSV4OP_ACCESS ||
690                     (op >= NFSV4OP_NOPS && (nd->nd_flag & ND_NFSV41) == 0) ||
691                     (op >= NFSV41_NOPS && (nd->nd_flag & ND_NFSV41) != 0)) {
692                         nd->nd_repstat = NFSERR_OPILLEGAL;
693                         *repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL);
694                         *repp = nfsd_errmap(nd);
695                         retops++;
696                         break;
697                 } else {
698                         repp++;
699                 }
700                 if (i == 0)
701                         op0 = op;
702                 if (i == numops - 1)
703                         nd->nd_flag |= ND_LASTOP;
704
705                 /*
706                  * Check for a referral on the current FH and, if so, return
707                  * NFSERR_MOVED for all ops that allow it, except Getattr.
708                  */
709                 if (vp != NULL && op != NFSV4OP_GETATTR &&
710                     nfsv4root_getreferral(vp, NULL, 0) != NULL &&
711                     nfsrv_errmoved(op)) {
712                         nd->nd_repstat = NFSERR_MOVED;
713                         *repp = nfsd_errmap(nd);
714                         retops++;
715                         break;
716                 }
717
718                 /*
719                  * For NFSv4.1, check for a Sequence Operation being first
720                  * or one of the other allowed operations by itself.
721                  */
722                 if ((nd->nd_flag & ND_NFSV41) != 0) {
723                         if (i != 0 && op == NFSV4OP_SEQUENCE)
724                                 nd->nd_repstat = NFSERR_SEQUENCEPOS;
725                         else if (i == 0 && op != NFSV4OP_SEQUENCE &&
726                             op != NFSV4OP_EXCHANGEID &&
727                             op != NFSV4OP_CREATESESSION &&
728                             op != NFSV4OP_BINDCONNTOSESS &&
729                             op != NFSV4OP_DESTROYCLIENTID &&
730                             op != NFSV4OP_DESTROYSESSION)
731                                 nd->nd_repstat = NFSERR_OPNOTINSESS;
732                         else if (i != 0 && op0 != NFSV4OP_SEQUENCE)
733                                 nd->nd_repstat = NFSERR_NOTONLYOP;
734                         if (nd->nd_repstat != 0) {
735                                 *repp = nfsd_errmap(nd);
736                                 retops++;
737                                 break;
738                         }
739                 }
740
741                 nd->nd_procnum = op;
742                 /*
743                  * If over flood level, reply NFSERR_RESOURCE, if at the first
744                  * Op. (Since a client recovery from NFSERR_RESOURCE can get
745                  * really nasty for certain Op sequences, I'll play it safe
746                  * and only return the error at the beginning.) The cache
747                  * will still function over flood level, but uses lots of
748                  * mbufs.)
749                  * If nfsrv_mallocmget_limit() returns True, the system is near
750                  * to its limit for memory that malloc()/mget() can allocate.
751                  */
752                 if (i == 0 && (nd->nd_rp == NULL ||
753                     nd->nd_rp->rc_refcnt == 0) &&
754                     (nfsrv_mallocmget_limit() ||
755                      nfsrc_tcpsavedreplies > nfsrc_floodlevel)) {
756                         if (nfsrc_tcpsavedreplies > nfsrc_floodlevel)
757                                 printf("nfsd server cache flooded, try "
758                                     "increasing vfs.nfsd.tcphighwater\n");
759                         nd->nd_repstat = NFSERR_RESOURCE;
760                         *repp = nfsd_errmap(nd);
761                         if (op == NFSV4OP_SETATTR) {
762                                 /*
763                                  * Setattr replies require a bitmap.
764                                  * even for errors like these.
765                                  */
766                                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
767                                 *tl = 0;
768                         }
769                         retops++;
770                         break;
771                 }
772                 if (nfsv4_opflag[op].savereply)
773                         nd->nd_flag |= ND_SAVEREPLY;
774                 NFSINCRGLOBAL(newnfsstats.srvrpccnt[nd->nd_procnum]);
775                 switch (op) {
776                 case NFSV4OP_PUTFH:
777                         error = nfsrv_mtofh(nd, &fh);
778                         if (error)
779                                 goto nfsmout;
780                         if (!nd->nd_repstat)
781                                 nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
782                                     NULL, 0, p);
783                         /* For now, allow this for non-export FHs */
784                         if (!nd->nd_repstat) {
785                                 if (vp)
786                                         vrele(vp);
787                                 vp = nvp;
788                                 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
789                                 NFSVOPUNLOCK(vp, 0);
790                                 vpnes = nes;
791                         }
792                         break;
793                 case NFSV4OP_PUTPUBFH:
794                         if (nfs_pubfhset)
795                             nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
796                                 &nes, NULL, 0, p);
797                         else
798                             nd->nd_repstat = NFSERR_NOFILEHANDLE;
799                         if (!nd->nd_repstat) {
800                                 if (vp)
801                                         vrele(vp);
802                                 vp = nvp;
803                                 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
804                                 NFSVOPUNLOCK(vp, 0);
805                                 vpnes = nes;
806                         }
807                         break;
808                 case NFSV4OP_PUTROOTFH:
809                         if (nfs_rootfhset) {
810                                 nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp,
811                                     &nes, NULL, 0, p);
812                                 if (!nd->nd_repstat) {
813                                         if (vp)
814                                                 vrele(vp);
815                                         vp = nvp;
816                                         cur_fsid = vp->v_mount->mnt_stat.f_fsid;
817                                         NFSVOPUNLOCK(vp, 0);
818                                         vpnes = nes;
819                                 }
820                         } else
821                                 nd->nd_repstat = NFSERR_NOFILEHANDLE;
822                         break;
823                 case NFSV4OP_SAVEFH:
824                         if (vp && NFSVNO_EXPORTED(&vpnes)) {
825                                 nd->nd_repstat = 0;
826                                 /* If vp == savevp, a no-op */
827                                 if (vp != savevp) {
828                                         if (savevp)
829                                                 vrele(savevp);
830                                         VREF(vp);
831                                         savevp = vp;
832                                         savevpnes = vpnes;
833                                         save_fsid = cur_fsid;
834                                 }
835                         } else {
836                                 nd->nd_repstat = NFSERR_NOFILEHANDLE;
837                         }
838                         break;
839                 case NFSV4OP_RESTOREFH:
840                         if (savevp) {
841                                 nd->nd_repstat = 0;
842                                 /* If vp == savevp, a no-op */
843                                 if (vp != savevp) {
844                                         VREF(savevp);
845                                         vrele(vp);
846                                         vp = savevp;
847                                         vpnes = savevpnes;
848                                         cur_fsid = save_fsid;
849                                 }
850                         } else {
851                                 nd->nd_repstat = NFSERR_RESTOREFH;
852                         }
853                         break;
854                 default:
855                     /*
856                      * Allow a Lookup, Getattr, GetFH, Secinfo on an
857                      * non-exported directory if
858                      * nfs_rootfhset. Do I need to allow any other Ops?
859                      * (You can only have a non-exported vpnes if
860                      *  nfs_rootfhset is true. See nfsd_fhtovp())
861                      * Allow AUTH_SYS to be used for file systems
862                      * exported GSS only for certain Ops, to allow
863                      * clients to do mounts more easily.
864                      */
865                     if (nfsv4_opflag[op].needscfh && vp) {
866                         if (!NFSVNO_EXPORTED(&vpnes) &&
867                             op != NFSV4OP_LOOKUP &&
868                             op != NFSV4OP_GETATTR &&
869                             op != NFSV4OP_GETFH &&
870                             op != NFSV4OP_ACCESS &&
871                             op != NFSV4OP_READLINK &&
872                             op != NFSV4OP_SECINFO)
873                                 nd->nd_repstat = NFSERR_NOFILEHANDLE;
874                         else if (nfsvno_testexp(nd, &vpnes) &&
875                             op != NFSV4OP_LOOKUP &&
876                             op != NFSV4OP_GETFH &&
877                             op != NFSV4OP_GETATTR &&
878                             op != NFSV4OP_SECINFO)
879                                 nd->nd_repstat = NFSERR_WRONGSEC;
880                         if (nd->nd_repstat) {
881                                 if (op == NFSV4OP_SETATTR) {
882                                     /*
883                                      * Setattr reply requires a bitmap
884                                      * even for errors like these.
885                                      */
886                                     NFSM_BUILD(tl, u_int32_t *,
887                                         NFSX_UNSIGNED);
888                                     *tl = 0;
889                                 }
890                                 break;
891                         }
892                     }
893                     if (nfsv4_opflag[op].retfh == 1) {
894                         if (!vp) {
895                                 nd->nd_repstat = NFSERR_NOFILEHANDLE;
896                                 break;
897                         }
898                         VREF(vp);
899                         if (nfsv4_opflag[op].modifyfs)
900                                 vn_start_write(vp, &temp_mp, V_WAIT);
901                         error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
902                             &nvp, (fhandle_t *)fh.nfsrvfh_data, p, &vpnes);
903                         if (!error && !nd->nd_repstat) {
904                             if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) {
905                                 new_mp = nvp->v_mount;
906                                 if (cur_fsid.val[0] !=
907                                     new_mp->mnt_stat.f_fsid.val[0] ||
908                                     cur_fsid.val[1] !=
909                                     new_mp->mnt_stat.f_fsid.val[1]) {
910                                     /* crossed a server mount point */
911                                     nd->nd_repstat = nfsvno_checkexp(new_mp,
912                                         nd->nd_nam, &nes, &credanon);
913                                     if (!nd->nd_repstat)
914                                         nd->nd_repstat = nfsd_excred(nd,
915                                             &nes, credanon);
916                                     if (credanon != NULL)
917                                         crfree(credanon);
918                                     if (!nd->nd_repstat) {
919                                         vpnes = nes;
920                                         cur_fsid = new_mp->mnt_stat.f_fsid;
921                                     }
922                                 }
923                                 /* Lookup ops return a locked vnode */
924                                 NFSVOPUNLOCK(nvp, 0);
925                             }
926                             if (!nd->nd_repstat) {
927                                     vrele(vp);
928                                     vp = nvp;
929                             } else
930                                     vrele(nvp);
931                         }
932                         if (nfsv4_opflag[op].modifyfs)
933                                 vn_finished_write(temp_mp);
934                     } else if (nfsv4_opflag[op].retfh == 2) {
935                         if (vp == NULL || savevp == NULL) {
936                                 nd->nd_repstat = NFSERR_NOFILEHANDLE;
937                                 break;
938                         } else if (cur_fsid.val[0] != save_fsid.val[0] ||
939                             cur_fsid.val[1] != save_fsid.val[1]) {
940                                 nd->nd_repstat = NFSERR_XDEV;
941                                 break;
942                         }
943                         if (nfsv4_opflag[op].modifyfs)
944                                 vn_start_write(savevp, &temp_mp, V_WAIT);
945                         if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
946                                 VREF(vp);
947                                 VREF(savevp);
948                                 error = (*(nfsrv4_ops2[op]))(nd, isdgram,
949                                     savevp, vp, p, &savevpnes, &vpnes);
950                         } else
951                                 nd->nd_repstat = NFSERR_PERM;
952                         if (nfsv4_opflag[op].modifyfs)
953                                 vn_finished_write(temp_mp);
954                     } else {
955                         if (nfsv4_opflag[op].retfh != 0)
956                                 panic("nfsrvd_compound");
957                         if (nfsv4_opflag[op].needscfh) {
958                                 if (vp != NULL) {
959                                         lktype = nfsv4_opflag[op].lktype;
960                                         if (nfsv4_opflag[op].modifyfs) {
961                                                 vn_start_write(vp, &temp_mp,
962                                                     V_WAIT);
963                                                 if (op == NFSV4OP_WRITE &&
964                                                     MNT_SHARED_WRITES(temp_mp))
965                                                         lktype = LK_SHARED;
966                                         }
967                                         if (NFSVOPLOCK(vp, lktype) == 0)
968                                                 VREF(vp);
969                                         else
970                                                 nd->nd_repstat = NFSERR_PERM;
971                                 } else {
972                                         nd->nd_repstat = NFSERR_NOFILEHANDLE;
973                                         if (op == NFSV4OP_SETATTR) {
974                                                 /*
975                                                  * Setattr reply requires a
976                                                  * bitmap even for errors like
977                                                  * these.
978                                                  */
979                                                 NFSM_BUILD(tl, u_int32_t *,
980                                                     NFSX_UNSIGNED);
981                                                 *tl = 0;
982                                         }
983                                         break;
984                                 }
985                                 if (nd->nd_repstat == 0)
986                                         error = (*(nfsrv4_ops0[op]))(nd,
987                                             isdgram, vp, p, &vpnes);
988                                 if (nfsv4_opflag[op].modifyfs)
989                                         vn_finished_write(temp_mp);
990                         } else {
991                                 error = (*(nfsrv4_ops0[op]))(nd, isdgram,
992                                     NULL, p, &vpnes);
993                         }
994                     }
995                 };
996                 if (error) {
997                         if (error == EBADRPC || error == NFSERR_BADXDR) {
998                                 nd->nd_repstat = NFSERR_BADXDR;
999                         } else {
1000                                 nd->nd_repstat = error;
1001                                 printf("nfsv4 comperr0=%d\n", error);
1002                         }
1003                         error = 0;
1004                 }
1005                 retops++;
1006                 if (nd->nd_repstat) {
1007                         *repp = nfsd_errmap(nd);
1008                         break;
1009                 } else {
1010                         *repp = 0;      /* NFS4_OK */
1011                 }
1012         }
1013 nfsmout:
1014         if (error) {
1015                 if (error == EBADRPC || error == NFSERR_BADXDR)
1016                         nd->nd_repstat = NFSERR_BADXDR;
1017                 else
1018                         printf("nfsv4 comperr1=%d\n", error);
1019         }
1020         if (taglen == -1) {
1021                 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1022                 *tl++ = 0;
1023                 *tl = 0;
1024         } else {
1025                 *retopsp = txdr_unsigned(retops);
1026         }
1027         if (vp)
1028                 vrele(vp);
1029         if (savevp)
1030                 vrele(savevp);
1031         NFSLOCKV4ROOTMUTEX();
1032         nfsv4_relref(&nfsv4rootfs_lock);
1033         NFSUNLOCKV4ROOTMUTEX();
1034
1035         NFSEXITCODE2(0, nd);
1036 }