]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/fs/nfsserver/nfs_nfsdsocket.c
zfs: merge openzfs/zfs@d96e29576
[FreeBSD/FreeBSD.git] / sys / fs / nfsserver / nfs_nfsdsocket.c
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 1989, 1993
5  *      The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Rick Macklem at The University of Guelph.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  */
35
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
38
39 /*
40  * Socket operations for use by the nfs server.
41  */
42
43 #include <fs/nfs/nfsport.h>
44
45 #include <security/mac/mac_framework.h>
46
47 extern struct nfsrvfh nfs_pubfh;
48 extern int nfs_pubfhset;
49 extern struct nfsv4lock nfsv4rootfs_lock;
50 extern int nfsrv_clienthashsize;
51 extern int nfsd_debuglevel;
52 extern int nfsrv_layouthighwater;
53 extern volatile int nfsrv_layoutcnt;
54 NFSV4ROOTLOCKMUTEX;
55 NFSSTATESPINLOCK;
56
57 NFSD_VNET_DECLARE(struct nfsrv_stablefirst, nfsrv_stablefirst);
58 NFSD_VNET_DECLARE(struct nfsclienthashhead *, nfsclienthash);
59 NFSD_VNET_DECLARE(int, nfsrc_floodlevel);
60 NFSD_VNET_DECLARE(int, nfsrc_tcpsavedreplies);
61 NFSD_VNET_DECLARE(struct nfsrvfh, nfs_rootfh);
62 NFSD_VNET_DECLARE(int, nfs_rootfhset);
63 NFSD_VNET_DECLARE(struct nfsstatsv1 *, nfsstatsv1_p);
64
65 int (*nfsrv3_procs0[NFS_V3NPROCS])(struct nfsrv_descript *,
66     int, vnode_t , struct nfsexstuff *) = {
67         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
68         nfsrvd_getattr,
69         nfsrvd_setattr,
70         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
71         nfsrvd_access,
72         nfsrvd_readlink,
73         nfsrvd_read,
74         nfsrvd_write,
75         nfsrvd_create,
76         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
77         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
78         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
79         nfsrvd_remove,
80         nfsrvd_remove,
81         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
82         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
83         nfsrvd_readdir,
84         nfsrvd_readdirplus,
85         nfsrvd_statfs,
86         nfsrvd_fsinfo,
87         nfsrvd_pathconf,
88         nfsrvd_commit,
89 };
90
91 int (*nfsrv3_procs1[NFS_V3NPROCS])(struct nfsrv_descript *,
92     int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *) = {
93         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
94         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
95         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
96         nfsrvd_lookup,
97         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
98         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
99         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
100         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
101         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
102         nfsrvd_mkdir,
103         nfsrvd_symlink,
104         nfsrvd_mknod,
105         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
106         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
107         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
108         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
109         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
110         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
111         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
112         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
113         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
114         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
115 };
116
117 int (*nfsrv3_procs2[NFS_V3NPROCS])(struct nfsrv_descript *,
118     int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *) = {
119         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
120         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
121         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
122         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
123         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
124         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
125         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
126         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
127         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
128         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
129         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
130         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
131         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
132         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
133         nfsrvd_rename,
134         nfsrvd_link,
135         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
136         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
137         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
138         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
139         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
140         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
141 };
142
143 int (*nfsrv4_ops0[NFSV42_NOPS])(struct nfsrv_descript *,
144     int, vnode_t , struct nfsexstuff *) = {
145         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
146         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
147         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
148         nfsrvd_access,
149         nfsrvd_close,
150         nfsrvd_commit,
151         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
152         nfsrvd_delegpurge,
153         nfsrvd_delegreturn,
154         nfsrvd_getattr,
155         nfsrvd_getfh,
156         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
157         nfsrvd_lock,
158         nfsrvd_lockt,
159         nfsrvd_locku,
160         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
161         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
162         nfsrvd_verify,
163         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
164         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
165         nfsrvd_openconfirm,
166         nfsrvd_opendowngrade,
167         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
168         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
169         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
170         nfsrvd_read,
171         nfsrvd_readdirplus,
172         nfsrvd_readlink,
173         nfsrvd_remove,
174         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
175         nfsrvd_renew,
176         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
177         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
178         nfsrvd_secinfo,
179         nfsrvd_setattr,
180         nfsrvd_setclientid,
181         nfsrvd_setclientidcfrm,
182         nfsrvd_verify,
183         nfsrvd_write,
184         nfsrvd_releaselckown,
185         nfsrvd_notsupp,
186         nfsrvd_bindconnsess,
187         nfsrvd_exchangeid,
188         nfsrvd_createsession,
189         nfsrvd_destroysession,
190         nfsrvd_freestateid,
191         nfsrvd_notsupp,
192         nfsrvd_getdevinfo,
193         nfsrvd_notsupp,
194         nfsrvd_layoutcommit,
195         nfsrvd_layoutget,
196         nfsrvd_layoutreturn,
197         nfsrvd_secinfononame,
198         nfsrvd_sequence,
199         nfsrvd_notsupp,
200         nfsrvd_teststateid,
201         nfsrvd_notsupp,
202         nfsrvd_destroyclientid,
203         nfsrvd_reclaimcomplete,
204         nfsrvd_allocate,
205         (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
206         nfsrvd_notsupp,
207         nfsrvd_deallocate,
208         nfsrvd_ioadvise,
209         nfsrvd_layouterror,
210         nfsrvd_layoutstats,
211         nfsrvd_notsupp,
212         nfsrvd_notsupp,
213         nfsrvd_notsupp,
214         nfsrvd_seek,
215         nfsrvd_notsupp,
216         nfsrvd_notsupp,
217         nfsrvd_getxattr,
218         nfsrvd_setxattr,
219         nfsrvd_listxattr,
220         nfsrvd_rmxattr,
221 };
222
223 int (*nfsrv4_ops1[NFSV42_NOPS])(struct nfsrv_descript *,
224     int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *) = {
225         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
226         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
227         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
228         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
229         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
230         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
231         nfsrvd_mknod,
232         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
233         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
234         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
235         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
236         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
237         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
238         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
239         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
240         nfsrvd_lookup,
241         nfsrvd_lookup,
242         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
243         nfsrvd_open,
244         nfsrvd_openattr,
245         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
246         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
247         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
248         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
249         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
250         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
251         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
252         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
253         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
254         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
255         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
256         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
257         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
258         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
259         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
260         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
261         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
262         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
263         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
264         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
265         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
266         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
267         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
268         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
269         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
270         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
271         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
272         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
273         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
274         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
275         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
276         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
277         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
278         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
279         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
280         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
281         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
282         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
283         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
284         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
285         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
286         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
287         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
288         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
289         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
290         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
291         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
292         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
293         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
294         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
295         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
296         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
297         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
298         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
299         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
300         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
301 };
302
303 int (*nfsrv4_ops2[NFSV42_NOPS])(struct nfsrv_descript *,
304     int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *) = {
305         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
306         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
307         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
308         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
309         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
310         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
311         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
312         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
313         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
314         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
315         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
316         nfsrvd_link,
317         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
318         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
319         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
320         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
321         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
322         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
323         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
324         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
325         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
326         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
327         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
328         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
329         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
330         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
331         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
332         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
333         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
334         nfsrvd_rename,
335         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
336         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
337         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
338         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
339         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
340         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
341         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
342         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
343         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
344         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
345         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
346         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
347         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
348         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
349         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
350         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
351         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
352         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
353         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
354         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
355         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
356         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
357         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
358         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
359         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
360         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
361         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
362         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
363         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
364         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
365         nfsrvd_copy_file_range,
366         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
367         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
368         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
369         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
370         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
371         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
372         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
373         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
374         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
375         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
376         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
377         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
378         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
379         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
380         (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
381 };
382
383 /*
384  * Static array that defines which nfs rpc's are nonidempotent
385  */
386 static int nfsrv_nonidempotent[NFS_V3NPROCS] = {
387         FALSE,
388         FALSE,
389         TRUE,
390         FALSE,
391         FALSE,
392         FALSE,
393         FALSE,
394         TRUE,
395         TRUE,
396         TRUE,
397         TRUE,
398         TRUE,
399         TRUE,
400         TRUE,
401         TRUE,
402         TRUE,
403         FALSE,
404         FALSE,
405         FALSE,
406         FALSE,
407         FALSE,
408         FALSE,
409 };
410
411 /*
412  * This static array indicates whether or not the RPC modifies the
413  * file system.
414  */
415 int nfsrv_writerpc[NFS_NPROCS] = { 0, 0, 1, 0, 0, 0, 0,
416     1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
417     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
418
419 SYSCTL_DECL(_vfs_nfsd);
420 static int      nfs_minminorv4 = NFSV4_MINORVERSION;
421 SYSCTL_INT(_vfs_nfsd, OID_AUTO, server_min_minorversion4, CTLFLAG_RWTUN,
422     &nfs_minminorv4, 0,
423     "The lowest minor version of NFSv4 handled by the server");
424
425 static int      nfs_maxminorv4 = NFSV42_MINORVERSION;
426 SYSCTL_INT(_vfs_nfsd, OID_AUTO, server_max_minorversion4, CTLFLAG_RWTUN,
427     &nfs_maxminorv4, 0,
428     "The highest minor version of NFSv4 handled by the server");
429
430 /* local functions */
431 static void nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
432     u_char *tag, int taglen, u_int32_t minorvers);
433
434 /*
435  * This static array indicates which server procedures require the extra
436  * arguments to return the current file handle for V2, 3.
437  */
438 static int nfs_retfh[NFS_V3NPROCS] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1,
439         1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0 };
440
441 extern struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS];
442
443 static int nfsv3to4op[NFS_V3NPROCS] = {
444         NFSPROC_NULL,
445         NFSV4OP_GETATTR,
446         NFSV4OP_SETATTR,
447         NFSV4OP_LOOKUP,
448         NFSV4OP_ACCESS,
449         NFSV4OP_READLINK,
450         NFSV4OP_READ,
451         NFSV4OP_WRITE,
452         NFSV4OP_V3CREATE,
453         NFSV4OP_MKDIR,
454         NFSV4OP_SYMLINK,
455         NFSV4OP_MKNOD,
456         NFSV4OP_REMOVE,
457         NFSV4OP_RMDIR,
458         NFSV4OP_RENAME,
459         NFSV4OP_LINK,
460         NFSV4OP_READDIR,
461         NFSV4OP_READDIRPLUS,
462         NFSV4OP_FSSTAT,
463         NFSV4OP_FSINFO,
464         NFSV4OP_PATHCONF,
465         NFSV4OP_COMMIT,
466 };
467
468 static struct mtx nfsrvd_statmtx;
469 MTX_SYSINIT(nfsst, &nfsrvd_statmtx, "NFSstat", MTX_DEF);
470
471 static struct ucred *nfsrv_createrootcred(void);
472
473 static void
474 nfsrvd_statstart(int op, struct bintime *now)
475 {
476         if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
477                 printf("%s: op %d invalid\n", __func__, op);
478                 return;
479         }
480
481         mtx_lock(&nfsrvd_statmtx);
482         if (NFSD_VNET(nfsstatsv1_p)->srvstartcnt ==
483             NFSD_VNET(nfsstatsv1_p)->srvdonecnt) {
484                 if (now != NULL)
485                         NFSD_VNET(nfsstatsv1_p)->busyfrom = *now;
486                 else
487                         binuptime(&NFSD_VNET(nfsstatsv1_p)->busyfrom);
488                 
489         }
490         NFSD_VNET(nfsstatsv1_p)->srvrpccnt[op]++;
491         NFSD_VNET(nfsstatsv1_p)->srvstartcnt++;
492         mtx_unlock(&nfsrvd_statmtx);
493
494 }
495
496 static void
497 nfsrvd_statend(int op, uint64_t bytes, struct bintime *now,
498     struct bintime *then)
499 {
500         struct bintime dt, lnow;
501
502         if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
503                 printf("%s: op %d invalid\n", __func__, op);
504                 return;
505         }
506
507         if (now == NULL) {
508                 now = &lnow;
509                 binuptime(now);
510         }
511
512         mtx_lock(&nfsrvd_statmtx);
513
514         NFSD_VNET(nfsstatsv1_p)->srvbytes[op] += bytes;
515         NFSD_VNET(nfsstatsv1_p)->srvops[op]++;
516
517         if (then != NULL) {
518                 dt = *now;
519                 bintime_sub(&dt, then);
520                 bintime_add(&NFSD_VNET(nfsstatsv1_p)->srvduration[op], &dt);
521         }
522
523         dt = *now;
524         bintime_sub(&dt, &NFSD_VNET(nfsstatsv1_p)->busyfrom);
525         bintime_add(&NFSD_VNET(nfsstatsv1_p)->busytime, &dt);
526         NFSD_VNET(nfsstatsv1_p)->busyfrom = *now;
527
528         NFSD_VNET(nfsstatsv1_p)->srvdonecnt++;
529
530         mtx_unlock(&nfsrvd_statmtx);
531 }
532
533 /*
534  * Do an RPC. Basically, get the file handles translated to vnode pointers
535  * and then call the appropriate server routine. The server routines are
536  * split into groups, based on whether they use a file handle or file
537  * handle plus name or ...
538  * The NFS V4 Compound RPC is performed separately by nfsrvd_compound().
539  */
540 void
541 nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, u_char *tag, int taglen,
542     u_int32_t minorvers)
543 {
544         int error = 0, lktype;
545         vnode_t vp;
546         mount_t mp;
547         struct nfsrvfh fh;
548         struct nfsexstuff nes;
549         struct mbuf *md;
550         char *dpos;
551
552         /*
553          * Save the current position in the request mbuf list so
554          * that a rollback to this location can be done upon an
555          * ERELOOKUP error return from an RPC function.
556          */
557         md = nd->nd_md;
558         dpos = nd->nd_dpos;
559 tryagain:
560         mp = NULL;
561
562         /*
563          * Get a locked vnode for the first file handle
564          */
565         if (!(nd->nd_flag & ND_NFSV4)) {
566                 KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc"));
567                 /*
568                  * For NFSv3, if the malloc/mget allocation is near limits,
569                  * return NFSERR_DELAY.
570                  */
571                 if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) {
572                         nd->nd_repstat = NFSERR_DELAY;
573                         vp = NULL;
574                 } else {
575                         error = nfsrv_mtofh(nd, &fh);
576                         if (error) {
577                                 if (error != EBADRPC)
578                                         printf("nfs dorpc err1=%d\n", error);
579                                 nd->nd_repstat = NFSERR_GARBAGE;
580                                 goto out;
581                         }
582                         if (nd->nd_procnum == NFSPROC_READ ||
583                             nd->nd_procnum == NFSPROC_WRITE ||
584                             nd->nd_procnum == NFSPROC_READDIR ||
585                             nd->nd_procnum == NFSPROC_READDIRPLUS ||
586                             nd->nd_procnum == NFSPROC_READLINK ||
587                             nd->nd_procnum == NFSPROC_GETATTR ||
588                             nd->nd_procnum == NFSPROC_ACCESS ||
589                             nd->nd_procnum == NFSPROC_FSSTAT ||
590                             nd->nd_procnum == NFSPROC_FSINFO)
591                                 lktype = LK_SHARED;
592                         else
593                                 lktype = LK_EXCLUSIVE;
594                         if (nd->nd_flag & ND_PUBLOOKUP)
595                                 nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes,
596                                     &mp, nfsrv_writerpc[nd->nd_procnum], -1);
597                         else
598                                 nfsd_fhtovp(nd, &fh, lktype, &vp, &nes,
599                                     &mp, nfsrv_writerpc[nd->nd_procnum], -1);
600                         if (nd->nd_repstat == NFSERR_PROGNOTV4)
601                                 goto out;
602                 }
603         }
604
605         /*
606          * For V2 and 3, set the ND_SAVEREPLY flag for the recent request
607          * cache, as required.
608          * For V4, nfsrvd_compound() does this.
609          */
610         if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum])
611                 nd->nd_flag |= ND_SAVEREPLY;
612
613         nfsrvd_rephead(nd);
614         /*
615          * If nd_repstat is non-zero, just fill in the reply status
616          * to complete the RPC reply for V2. Otherwise, you must do
617          * the RPC.
618          */
619         if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) {
620                 *nd->nd_errp = nfsd_errmap(nd);
621                 nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], /*now*/ NULL);
622                 nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
623                    /*now*/ NULL, /*then*/ NULL);
624                 vn_finished_write(mp);
625                 goto out;
626         }
627
628         /*
629          * Now the procedure can be performed. For V4, nfsrvd_compound()
630          * works through the sub-rpcs, otherwise just call the procedure.
631          * The procedures are in three groups with different arguments.
632          * The group is indicated by the value in nfs_retfh[].
633          */
634         if (nd->nd_flag & ND_NFSV4) {
635                 nfsrvd_compound(nd, isdgram, tag, taglen, minorvers);
636         } else {
637                 struct bintime start_time;
638
639                 binuptime(&start_time);
640                 nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], &start_time);
641
642                 if (nfs_retfh[nd->nd_procnum] == 1) {
643                         if (vp)
644                                 NFSVOPUNLOCK(vp);
645                         error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram,
646                             vp, NULL, (fhandle_t *)fh.nfsrvfh_data, &nes);
647                 } else if (nfs_retfh[nd->nd_procnum] == 2) {
648                         error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram,
649                             vp, NULL, &nes, NULL);
650                 } else {
651                         error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
652                             vp, &nes);
653                 }
654                 vn_finished_write(mp);
655
656                 if (error == 0 && nd->nd_repstat == ERELOOKUP) {
657                         /*
658                          * Roll back to the beginning of the RPC request
659                          * arguments.
660                          */
661                         nd->nd_md = md;
662                         nd->nd_dpos = dpos;
663
664                         /* Free the junk RPC reply and redo the RPC. */
665                         m_freem(nd->nd_mreq);
666                         nd->nd_mreq = nd->nd_mb = NULL;
667                         nd->nd_repstat = 0;
668                         goto tryagain;
669                 }
670
671                 nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
672                     /*now*/ NULL, /*then*/ &start_time);
673         }
674         if (error) {
675                 if (error != EBADRPC)
676                         printf("nfs dorpc err2=%d\n", error);
677                 nd->nd_repstat = NFSERR_GARBAGE;
678         }
679         *nd->nd_errp = nfsd_errmap(nd);
680
681         /*
682          * Don't cache certain reply status values.
683          */
684         if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) &&
685             (nd->nd_repstat == NFSERR_GARBAGE ||
686              nd->nd_repstat == NFSERR_BADXDR ||
687              nd->nd_repstat == NFSERR_MOVED ||
688              nd->nd_repstat == NFSERR_DELAY ||
689              nd->nd_repstat == NFSERR_BADSEQID ||
690              nd->nd_repstat == NFSERR_RESOURCE ||
691              nd->nd_repstat == NFSERR_SERVERFAULT ||
692              nd->nd_repstat == NFSERR_STALECLIENTID ||
693              nd->nd_repstat == NFSERR_STALESTATEID ||
694              nd->nd_repstat == NFSERR_OLDSTATEID ||
695              nd->nd_repstat == NFSERR_BADSTATEID ||
696              nd->nd_repstat == NFSERR_GRACE ||
697              nd->nd_repstat == NFSERR_NOGRACE))
698                 nd->nd_flag &= ~ND_SAVEREPLY;
699
700 out:
701         NFSEXITCODE2(0, nd);
702 }
703
704 /*
705  * Breaks down a compound RPC request and calls the server routines for
706  * the subprocedures.
707  * Some suboperations are performed directly here to simplify file handle<-->
708  * vnode pointer handling.
709  */
710 static void
711 nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,
712     int taglen, u_int32_t minorvers)
713 {
714         int i, lktype, op, op0 = 0, rstat, statsinprog = 0;
715         u_int32_t *tl;
716         struct nfsclient *clp, *nclp;
717         int error = 0, igotlock, nextop, numops, savefhcnt;
718         u_int32_t retops = 0, *retopsp = NULL, *repp;
719         vnode_t vp, nvp, savevp;
720         struct nfsrvfh fh;
721         mount_t new_mp, temp_mp = NULL;
722         struct ucred *credanon, *rootcred, *savecred;
723         struct nfsexstuff nes, vpnes, savevpnes;
724         fsid_t cur_fsid, save_fsid;
725         static u_int64_t compref = 0;
726         struct bintime start_time;
727         struct thread *p;
728         struct mbuf *mb, *md;
729         char *bpos, *dpos;
730         int bextpg, bextpgsiz;
731
732         p = curthread;
733         rootcred = savecred = NULL;
734
735         /* Check for and optionally clear the no space flags for DSs. */
736         nfsrv_checknospc();
737
738         NFSVNO_EXINIT(&vpnes);
739         NFSVNO_EXINIT(&savevpnes);
740         /*
741          * Put the seq# of the current compound RPC in nfsrv_descript.
742          * (This is used by nfsrv_checkgetattr(), to see if the write
743          *  delegation was created by the same compound RPC as the one
744          *  with that Getattr in it.)
745          * Don't worry about the 64bit number wrapping around. It ain't
746          * gonna happen before this server gets shut down/rebooted.
747          */
748         nd->nd_compref = compref++;
749
750         /*
751          * Check for and optionally get a lock on the root. This lock means that
752          * no nfsd will be fiddling with the V4 file system and state stuff. It
753          * is required when the V4 root is being changed, the stable storage
754          * restart file is being updated, or callbacks are being done.
755          * When any of the nfsd are processing an NFSv4 compound RPC, they must
756          * either hold a reference count (nfs_usecnt) or the lock. When
757          * nfsrv_unlock() is called to release the lock, it can optionally
758          * also get a reference count, which saves the need for a call to
759          * nfsrv_getref() after nfsrv_unlock().
760          */
761         /*
762          * First, check to see if we need to wait for an update lock.
763          */
764         igotlock = 0;
765         NFSLOCKV4ROOTMUTEX();
766         if (NFSD_VNET(nfsrv_stablefirst).nsf_flags & NFSNSF_NEEDLOCK)
767                 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
768                     NFSV4ROOTLOCKMUTEXPTR, NULL);
769         else
770                 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
771                     NFSV4ROOTLOCKMUTEXPTR, NULL);
772         NFSUNLOCKV4ROOTMUTEX();
773         if (igotlock) {
774                 /*
775                  * If I got the lock, I can update the stable storage file.
776                  * Done when the grace period is over or a client has long
777                  * since expired.
778                  */
779                 NFSD_VNET(nfsrv_stablefirst).nsf_flags &= ~NFSNSF_NEEDLOCK;
780                 if ((NFSD_VNET(nfsrv_stablefirst).nsf_flags &
781                     (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
782                         nfsrv_updatestable(p);
783
784                 /*
785                  * If at least one client has long since expired, search
786                  * the client list for them, write a REVOKE record on the
787                  * stable storage file and then remove them from the client
788                  * list.
789                  */
790                 if (NFSD_VNET(nfsrv_stablefirst).nsf_flags &
791                     NFSNSF_EXPIREDCLIENT) {
792                         NFSD_VNET(nfsrv_stablefirst).nsf_flags &=
793                             ~NFSNSF_EXPIREDCLIENT;
794                         for (i = 0; i < nfsrv_clienthashsize; i++) {
795                             LIST_FOREACH_SAFE(clp, &NFSD_VNET(nfsclienthash)[i],
796                                 lc_hash, nclp) {
797                                 if (clp->lc_flags & LCL_EXPIREIT) {
798                                     if (!LIST_EMPTY(&clp->lc_open) ||
799                                         !LIST_EMPTY(&clp->lc_deleg))
800                                         nfsrv_writestable(clp->lc_id,
801                                             clp->lc_idlen, NFSNST_REVOKE, p);
802                                     nfsrv_cleanclient(clp, p);
803                                     nfsrv_freedeleglist(&clp->lc_deleg);
804                                     nfsrv_freedeleglist(&clp->lc_olddeleg);
805                                     LIST_REMOVE(clp, lc_hash);
806                                     nfsrv_zapclient(clp, p);
807                                 }
808                             }
809                         }
810                 }
811                 NFSLOCKV4ROOTMUTEX();
812                 nfsv4_unlock(&nfsv4rootfs_lock, 1);
813                 NFSUNLOCKV4ROOTMUTEX();
814         } else {
815                 /*
816                  * If we didn't get the lock, we need to get a refcnt,
817                  * which also checks for and waits for the lock.
818                  */
819                 NFSLOCKV4ROOTMUTEX();
820                 nfsv4_getref(&nfsv4rootfs_lock, NULL,
821                     NFSV4ROOTLOCKMUTEXPTR, NULL);
822                 NFSUNLOCKV4ROOTMUTEX();
823         }
824
825         /*
826          * If flagged, search for open owners that haven't had any opens
827          * for a long time.
828          */
829         if (NFSD_VNET(nfsrv_stablefirst).nsf_flags & NFSNSF_NOOPENS) {
830                 nfsrv_throwawayopens(p);
831         }
832
833         /* Do a CBLAYOUTRECALL callback if over the high water mark. */
834         if (nfsrv_layoutcnt > nfsrv_layouthighwater)
835                 nfsrv_recalloldlayout(p);
836
837         savevp = vp = NULL;
838         save_fsid.val[0] = save_fsid.val[1] = 0;
839         cur_fsid.val[0] = cur_fsid.val[1] = 0;
840         nextop = -1;
841         savefhcnt = 0;
842
843         /* If taglen < 0, there was a parsing error in nfsd_getminorvers(). */
844         if (taglen < 0) {
845                 error = EBADRPC;
846                 goto nfsmout;
847         }
848
849         (void) nfsm_strtom(nd, tag, taglen);
850         NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED);
851         NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
852         if ((minorvers != NFSV4_MINORVERSION &&
853             minorvers != NFSV41_MINORVERSION &&
854             minorvers != NFSV42_MINORVERSION) ||
855             minorvers < nfs_minminorv4 || minorvers > nfs_maxminorv4)
856                 nd->nd_repstat = NFSERR_MINORVERMISMATCH;
857         if (nd->nd_repstat)
858                 numops = 0;
859         else
860                 numops = fxdr_unsigned(int, *tl);
861         /*
862          * Loop around doing the sub ops.
863          * vp - is an unlocked vnode pointer for the CFH
864          * savevp - is an unlocked vnode pointer for the SAVEDFH
865          * (at some future date, it might turn out to be more appropriate
866          *  to keep the file handles instead of vnode pointers?)
867          * savevpnes and vpnes - are the export flags for the above.
868          */
869         for (i = 0; i < numops; i++) {
870                 NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED);
871                 if (savefhcnt > 0) {
872                         op = NFSV4OP_SAVEFH;
873                         *repp = txdr_unsigned(op);
874                         savefhcnt--;
875                 } else if (nextop == -1) {
876                         NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
877                         *repp = *tl;
878                         op = fxdr_unsigned(int, *tl);
879                 } else {
880                         op = nextop;
881                         *repp = txdr_unsigned(op);
882                         nextop = -1;
883                 }
884                 NFSD_DEBUG(4, "op=%d\n", op);
885                 if (op < NFSV4OP_ACCESS || op >= NFSV42_NOPS ||
886                     (op >= NFSV4OP_NOPS && (nd->nd_flag & ND_NFSV41) == 0) ||
887                     (op >= NFSV41_NOPS && (nd->nd_flag & ND_NFSV42) == 0)) {
888                         nd->nd_repstat = NFSERR_OPILLEGAL;
889                         *repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL);
890                         *repp = nfsd_errmap(nd);
891                         retops++;
892                         break;
893                 } else {
894                         repp++;
895                 }
896
897                 binuptime(&start_time);
898                 nfsrvd_statstart(op, &start_time);
899                 statsinprog = 1;
900
901                 if (i == 0)
902                         op0 = op;
903                 if (i == numops - 1)
904                         nd->nd_flag |= ND_LASTOP;
905
906                 /*
907                  * Check for a referral on the current FH and, if so, return
908                  * NFSERR_MOVED for all ops that allow it, except Getattr.
909                  */
910                 if (vp != NULL && op != NFSV4OP_GETATTR &&
911                     nfsv4root_getreferral(vp, NULL, 0) != NULL &&
912                     nfsrv_errmoved(op)) {
913                         nd->nd_repstat = NFSERR_MOVED;
914                         *repp = nfsd_errmap(nd);
915                         retops++;
916                         break;
917                 }
918
919                 /*
920                  * For NFSv4.1, check for a Sequence Operation being first
921                  * or one of the other allowed operations by itself.
922                  */
923                 if ((nd->nd_flag & ND_NFSV41) != 0) {
924                         if (i != 0 && op == NFSV4OP_SEQUENCE)
925                                 nd->nd_repstat = NFSERR_SEQUENCEPOS;
926                         else if (i == 0 && op != NFSV4OP_SEQUENCE &&
927                             op != NFSV4OP_EXCHANGEID &&
928                             op != NFSV4OP_CREATESESSION &&
929                             op != NFSV4OP_BINDCONNTOSESS &&
930                             op != NFSV4OP_DESTROYCLIENTID &&
931                             op != NFSV4OP_DESTROYSESSION)
932                                 nd->nd_repstat = NFSERR_OPNOTINSESS;
933                         else if (i != 0 && op0 != NFSV4OP_SEQUENCE)
934                                 nd->nd_repstat = NFSERR_NOTONLYOP;
935                         if (nd->nd_repstat != 0) {
936                                 *repp = nfsd_errmap(nd);
937                                 retops++;
938                                 break;
939                         }
940                 }
941
942                 nd->nd_procnum = op;
943                 /*
944                  * If over flood level, reply NFSERR_RESOURCE, if at the first
945                  * Op. (Since a client recovery from NFSERR_RESOURCE can get
946                  * really nasty for certain Op sequences, I'll play it safe
947                  * and only return the error at the beginning.) The cache
948                  * will still function over flood level, but uses lots of
949                  * mbufs.)
950                  * If nfsrv_mallocmget_limit() returns True, the system is near
951                  * to its limit for memory that malloc()/mget() can allocate.
952                  */
953                 if (i == 0 && (nd->nd_rp == NULL ||
954                     nd->nd_rp->rc_refcnt == 0) &&
955                     (nfsrv_mallocmget_limit() ||
956                      NFSD_VNET(nfsrc_tcpsavedreplies) >
957                      NFSD_VNET(nfsrc_floodlevel))) {
958                         if (NFSD_VNET(nfsrc_tcpsavedreplies) >
959                             NFSD_VNET(nfsrc_floodlevel))
960                                 printf("nfsd server cache flooded, try "
961                                     "increasing vfs.nfsd.tcphighwater\n");
962                         nd->nd_repstat = NFSERR_RESOURCE;
963                         *repp = nfsd_errmap(nd);
964                         if (op == NFSV4OP_SETATTR) {
965                                 /*
966                                  * Setattr replies require a bitmap.
967                                  * even for errors like these.
968                                  */
969                                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
970                                 *tl = 0;
971                         }
972                         retops++;
973                         break;
974                 }
975
976                 /*
977                  * Check for the case of SP4_MACH_CRED and an operation in
978                  * the allow set.  For these operations, replace nd_cred with
979                  * root credentials so that the operation will not fail due
980                  * to credentials.
981                  * NB: ND_MACHCRED is set by Sequence when the ClientID
982                  * specifies LCL_MACHCRED and the RPC is being performed
983                  * via krb5i or krb5p using the machine principal.
984                  */
985                 if ((nd->nd_flag & ND_MACHCRED) != 0) {
986                         if (NFSISSET_OPBIT(&nd->nd_allowops, op)) {
987                                 /* Replace nd_cred with root creds. */
988                                 if (rootcred == NULL)
989                                         rootcred = nfsrv_createrootcred();
990                                 if (savecred == NULL)
991                                         savecred = nd->nd_cred;
992                                 nd->nd_cred = rootcred;
993                         } else if (savecred != NULL) {
994                                 nd->nd_cred = savecred;
995                                 savecred = NULL;
996                         }
997                 }
998
999                 if (nfsv4_opflag[op].savereply)
1000                         nd->nd_flag |= ND_SAVEREPLY;
1001                 switch (op) {
1002                 case NFSV4OP_PUTFH:
1003                         error = nfsrv_mtofh(nd, &fh);
1004                         if (error)
1005                                 goto nfsmout;
1006                         if ((nd->nd_flag & ND_LASTOP) == 0) {
1007                                 /*
1008                                  * Pre-parse the next op#.  If it is
1009                                  * SaveFH, count it and skip to the
1010                                  * next op#, if not the last op#.
1011                                  * nextop is used to determine if
1012                                  * NFSERR_WRONGSEC can be returned,
1013                                  * per RFC5661 Sec. 2.6.
1014                                  */
1015                                 do {
1016                                         NFSM_DISSECT(tl, uint32_t *,
1017                                             NFSX_UNSIGNED);
1018                                         nextop = fxdr_unsigned(int, *tl);
1019                                         if (nextop == NFSV4OP_SAVEFH &&
1020                                             i < numops - 1)
1021                                                 savefhcnt++;
1022                                 } while (nextop == NFSV4OP_SAVEFH &&
1023                                     i < numops - 1);
1024                         }
1025                         if (!nd->nd_repstat)
1026                                 nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
1027                                     NULL, 0, nextop);
1028                         /* For now, allow this for non-export FHs */
1029                         if (!nd->nd_repstat) {
1030                                 if (vp)
1031                                         vrele(vp);
1032                                 vp = nvp;
1033                                 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
1034                                 NFSVOPUNLOCK(vp);
1035                                 vpnes = nes;
1036                         }
1037                         break;
1038                 case NFSV4OP_PUTPUBFH:
1039                         if (nfs_pubfhset) {
1040                                 if ((nd->nd_flag & ND_LASTOP) == 0) {
1041                                         /*
1042                                          * Pre-parse the next op#.  If it is
1043                                          * SaveFH, count it and skip to the
1044                                          * next op#, if not the last op#.
1045                                          * nextop is used to determine if
1046                                          * NFSERR_WRONGSEC can be returned,
1047                                          * per RFC5661 Sec. 2.6.
1048                                          */
1049                                         do {
1050                                                 NFSM_DISSECT(tl, uint32_t *,
1051                                                     NFSX_UNSIGNED);
1052                                                 nextop = fxdr_unsigned(int,
1053                                                     *tl);
1054                                                 if (nextop == NFSV4OP_SAVEFH &&
1055                                                     i < numops - 1)
1056                                                         savefhcnt++;
1057                                         } while (nextop == NFSV4OP_SAVEFH &&
1058                                             i < numops - 1);
1059                                 }
1060                                 nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
1061                                     &nes, NULL, 0, nextop);
1062                         } else
1063                                 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1064                         if (!nd->nd_repstat) {
1065                                 if (vp)
1066                                         vrele(vp);
1067                                 vp = nvp;
1068                                 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
1069                                 NFSVOPUNLOCK(vp);
1070                                 vpnes = nes;
1071                         }
1072                         break;
1073                 case NFSV4OP_PUTROOTFH:
1074                         if (NFSD_VNET(nfs_rootfhset)) {
1075                                 if ((nd->nd_flag & ND_LASTOP) == 0) {
1076                                         /*
1077                                          * Pre-parse the next op#.  If it is
1078                                          * SaveFH, count it and skip to the
1079                                          * next op#, if not the last op#.
1080                                          * nextop is used to determine if
1081                                          * NFSERR_WRONGSEC can be returned,
1082                                          * per RFC5661 Sec. 2.6.
1083                                          */
1084                                         do {
1085                                                 NFSM_DISSECT(tl, uint32_t *,
1086                                                     NFSX_UNSIGNED);
1087                                                 nextop = fxdr_unsigned(int,
1088                                                     *tl);
1089                                                 if (nextop == NFSV4OP_SAVEFH &&
1090                                                     i < numops - 1)
1091                                                         savefhcnt++;
1092                                         } while (nextop == NFSV4OP_SAVEFH &&
1093                                             i < numops - 1);
1094                                 }
1095                                 nfsd_fhtovp(nd, &NFSD_VNET(nfs_rootfh),
1096                                     LK_SHARED, &nvp, &nes, NULL, 0, nextop);
1097                                 if (!nd->nd_repstat) {
1098                                         if (vp)
1099                                                 vrele(vp);
1100                                         vp = nvp;
1101                                         cur_fsid = vp->v_mount->mnt_stat.f_fsid;
1102                                         NFSVOPUNLOCK(vp);
1103                                         vpnes = nes;
1104                                 }
1105                         } else
1106                                 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1107                         break;
1108                 case NFSV4OP_SAVEFH:
1109                         if (vp && NFSVNO_EXPORTED(&vpnes)) {
1110                                 nd->nd_repstat = 0;
1111                                 /* If vp == savevp, a no-op */
1112                                 if (vp != savevp) {
1113                                         if (savevp)
1114                                                 vrele(savevp);
1115                                         VREF(vp);
1116                                         savevp = vp;
1117                                         savevpnes = vpnes;
1118                                         save_fsid = cur_fsid;
1119                                 }
1120                                 if ((nd->nd_flag & ND_CURSTATEID) != 0) {
1121                                         nd->nd_savedcurstateid =
1122                                             nd->nd_curstateid;
1123                                         nd->nd_flag |= ND_SAVEDCURSTATEID;
1124                                 }
1125                         } else {
1126                                 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1127                         }
1128                         break;
1129                 case NFSV4OP_RESTOREFH:
1130                         if (savevp) {
1131                                 if ((nd->nd_flag & ND_LASTOP) == 0) {
1132                                         /*
1133                                          * Pre-parse the next op#.  If it is
1134                                          * SaveFH, count it and skip to the
1135                                          * next op#, if not the last op#.
1136                                          * nextop is used to determine if
1137                                          * NFSERR_WRONGSEC can be returned,
1138                                          * per RFC5661 Sec. 2.6.
1139                                          */
1140                                         do {
1141                                                 NFSM_DISSECT(tl, uint32_t *,
1142                                                     NFSX_UNSIGNED);
1143                                                 nextop = fxdr_unsigned(int,
1144                                                     *tl);
1145                                                 if (nextop == NFSV4OP_SAVEFH &&
1146                                                     i < numops - 1)
1147                                                         savefhcnt++;
1148                                         } while (nextop == NFSV4OP_SAVEFH &&
1149                                             i < numops - 1);
1150                                 }
1151                                 nd->nd_repstat = 0;
1152                                 /* If vp == savevp, a no-op */
1153                                 if (vp != savevp) {
1154                                         if (nfsrv_checkwrongsec(nd, nextop,
1155                                             savevp->v_type))
1156                                                 nd->nd_repstat =
1157                                                     nfsvno_testexp(nd,
1158                                                     &savevpnes);
1159                                         if (nd->nd_repstat == 0) {
1160                                                 VREF(savevp);
1161                                                 vrele(vp);
1162                                                 vp = savevp;
1163                                                 vpnes = savevpnes;
1164                                                 cur_fsid = save_fsid;
1165                                         }
1166                                 }
1167                                 if (nd->nd_repstat == 0 &&
1168                                      (nd->nd_flag & ND_SAVEDCURSTATEID) != 0) {
1169                                         nd->nd_curstateid =
1170                                             nd->nd_savedcurstateid;
1171                                         nd->nd_flag |= ND_CURSTATEID;
1172                                 }
1173                         } else {
1174                                 nd->nd_repstat = NFSERR_RESTOREFH;
1175                         }
1176                         break;
1177                 default:
1178                     /*
1179                      * Allow a Lookup, Getattr, GetFH, Secinfo on an
1180                      * non-exported directory if
1181                      * nfs_rootfhset. Do I need to allow any other Ops?
1182                      * (You can only have a non-exported vpnes if
1183                      *  nfs_rootfhset is true. See nfsd_fhtovp())
1184                      * Allow AUTH_SYS to be used for file systems
1185                      * exported GSS only for certain Ops, to allow
1186                      * clients to do mounts more easily.
1187                      */
1188                     if (nfsv4_opflag[op].needscfh && vp) {
1189                         if (!NFSVNO_EXPORTED(&vpnes) &&
1190                             op != NFSV4OP_LOOKUP &&
1191                             op != NFSV4OP_GETATTR &&
1192                             op != NFSV4OP_GETFH &&
1193                             op != NFSV4OP_ACCESS &&
1194                             op != NFSV4OP_READLINK &&
1195                             op != NFSV4OP_SECINFO &&
1196                             op != NFSV4OP_SECINFONONAME)
1197                                 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1198                         if (nd->nd_repstat) {
1199                                 if (op == NFSV4OP_SETATTR) {
1200                                     /*
1201                                      * Setattr reply requires a bitmap
1202                                      * even for errors like these.
1203                                      */
1204                                     NFSM_BUILD(tl, u_int32_t *,
1205                                         NFSX_UNSIGNED);
1206                                     *tl = 0;
1207                                 }
1208                                 break;
1209                         }
1210                     }
1211
1212                     /*
1213                      * Save the current positions in the mbuf lists so
1214                      * that a rollback to this location can be done upon a
1215                      * redo due to a ERELOOKUP return for a operation.
1216                      */
1217                     mb = nd->nd_mb;
1218                     bpos = nd->nd_bpos;
1219                     bextpg = nd->nd_bextpg;
1220                     bextpgsiz = nd->nd_bextpgsiz;
1221                     md = nd->nd_md;
1222                     dpos = nd->nd_dpos;
1223 tryagain:
1224
1225                     if (nfsv4_opflag[op].retfh == 1) {
1226                         if (!vp) {
1227                                 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1228                                 break;
1229                         }
1230                         if (NFSVNO_EXPORTED(&vpnes) && (op == NFSV4OP_LOOKUP ||
1231                             op == NFSV4OP_LOOKUPP || (op == NFSV4OP_OPEN &&
1232                             vp->v_type == VDIR))) {
1233                                 /* Check for wrong security. */
1234                                 rstat = nfsvno_testexp(nd, &vpnes);
1235                                 if (rstat != 0) {
1236                                         nd->nd_repstat = rstat;
1237                                         break;
1238                                 }
1239                         }
1240                         VREF(vp);
1241                         if (nfsv4_opflag[op].modifyfs)
1242                                 vn_start_write(vp, &temp_mp, V_WAIT);
1243                         error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
1244                             &nvp, (fhandle_t *)fh.nfsrvfh_data, &vpnes);
1245                         if (!error && !nd->nd_repstat) {
1246                             if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) {
1247                                 new_mp = nvp->v_mount;
1248                                 if (fsidcmp(&cur_fsid, &new_mp->mnt_stat.f_fsid) != 0) {
1249                                     /* crossed a server mount point */
1250                                     nd->nd_repstat = nfsvno_checkexp(new_mp,
1251                                         nd->nd_nam, &nes, &credanon);
1252                                     if (!nd->nd_repstat)
1253                                         nd->nd_repstat = nfsd_excred(nd,
1254                                             &nes, credanon, true);
1255                                     if (credanon != NULL)
1256                                         crfree(credanon);
1257                                     if (!nd->nd_repstat) {
1258                                         vpnes = nes;
1259                                         cur_fsid = new_mp->mnt_stat.f_fsid;
1260                                     }
1261                                 }
1262                                 /* Lookup ops return a locked vnode */
1263                                 NFSVOPUNLOCK(nvp);
1264                             }
1265                             if (!nd->nd_repstat) {
1266                                     vrele(vp);
1267                                     vp = nvp;
1268                             } else
1269                                     vrele(nvp);
1270                         }
1271                         if (nfsv4_opflag[op].modifyfs)
1272                                 vn_finished_write(temp_mp);
1273                     } else if (nfsv4_opflag[op].retfh == 2) {
1274                         if (vp == NULL || savevp == NULL) {
1275                                 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1276                                 break;
1277                         } else if (fsidcmp(&cur_fsid, &save_fsid) != 0) {
1278                                 nd->nd_repstat = NFSERR_XDEV;
1279                                 break;
1280                         }
1281                         if (nfsv4_opflag[op].modifyfs)
1282                                 vn_start_write(savevp, &temp_mp, V_WAIT);
1283                         if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
1284                                 VREF(vp);
1285                                 VREF(savevp);
1286                                 error = (*(nfsrv4_ops2[op]))(nd, isdgram,
1287                                     savevp, vp, &savevpnes, &vpnes);
1288                         } else
1289                                 nd->nd_repstat = NFSERR_PERM;
1290                         if (nfsv4_opflag[op].modifyfs)
1291                                 vn_finished_write(temp_mp);
1292                     } else {
1293                         if (nfsv4_opflag[op].retfh != 0)
1294                                 panic("nfsrvd_compound");
1295                         if (nfsv4_opflag[op].needscfh) {
1296                                 if (vp != NULL) {
1297                                         lktype = nfsv4_opflag[op].lktype;
1298                                         if (nfsv4_opflag[op].modifyfs) {
1299                                                 vn_start_write(vp, &temp_mp,
1300                                                     V_WAIT);
1301                                                 if (op == NFSV4OP_WRITE &&
1302                                                     MNT_SHARED_WRITES(temp_mp))
1303                                                         lktype = LK_SHARED;
1304                                         }
1305                                         if (NFSVOPLOCK(vp, lktype) == 0)
1306                                                 VREF(vp);
1307                                         else
1308                                                 nd->nd_repstat = NFSERR_PERM;
1309                                 } else {
1310                                         nd->nd_repstat = NFSERR_NOFILEHANDLE;
1311                                         if (op == NFSV4OP_SETATTR) {
1312                                                 /*
1313                                                  * Setattr reply requires a
1314                                                  * bitmap even for errors like
1315                                                  * these.
1316                                                  */
1317                                                 NFSM_BUILD(tl, u_int32_t *,
1318                                                     NFSX_UNSIGNED);
1319                                                 *tl = 0;
1320                                         }
1321                                         break;
1322                                 }
1323                                 if (nd->nd_repstat == 0) {
1324                                         error = (*(nfsrv4_ops0[op]))(nd,
1325                                             isdgram, vp, &vpnes);
1326                                         if ((op == NFSV4OP_SECINFO ||
1327                                              op == NFSV4OP_SECINFONONAME) &&
1328                                             error == 0 && nd->nd_repstat == 0) {
1329                                                 /*
1330                                                  * Secinfo and Secinfo_no_name
1331                                                  * consume the current FH.
1332                                                  */
1333                                                 vrele(vp);
1334                                                 vp = NULL;
1335                                         }
1336                                 }
1337                                 if (nfsv4_opflag[op].modifyfs)
1338                                         vn_finished_write(temp_mp);
1339                         } else {
1340                                 error = (*(nfsrv4_ops0[op]))(nd, isdgram,
1341                                     NULL, &vpnes);
1342                         }
1343                     }
1344                 }
1345                 if (error) {
1346                         if (error == EBADRPC || error == NFSERR_BADXDR) {
1347                                 nd->nd_repstat = NFSERR_BADXDR;
1348                         } else {
1349                                 nd->nd_repstat = error;
1350                                 printf("nfsv4 comperr0=%d\n", error);
1351                         }
1352                         error = 0;
1353                 }
1354
1355                 if (nd->nd_repstat == ERELOOKUP) {
1356                         /*
1357                          * Roll back to the beginning of the operation
1358                          * arguments.
1359                          */
1360                         nd->nd_md = md;
1361                         nd->nd_dpos = dpos;
1362
1363                         /*
1364                          * Trim off the bogus reply for this operation
1365                          * and redo the operation.
1366                          */
1367                         nfsm_trimtrailing(nd, mb, bpos, bextpg, bextpgsiz);
1368                         nd->nd_repstat = 0;
1369                         nd->nd_flag |= ND_ERELOOKUP;
1370                         goto tryagain;
1371                 }
1372                 nd->nd_flag &= ~ND_ERELOOKUP;
1373
1374                 if (statsinprog != 0) {
1375                         nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1376                             /*then*/ &start_time);
1377                         statsinprog = 0;
1378                 }
1379
1380                 retops++;
1381                 if (nd->nd_repstat) {
1382                         *repp = nfsd_errmap(nd);
1383                         break;
1384                 } else {
1385                         *repp = 0;      /* NFS4_OK */
1386                 }
1387         }
1388 nfsmout:
1389         if (statsinprog != 0) {
1390                 nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1391                     /*then*/ &start_time);
1392                 statsinprog = 0;
1393         }
1394         if (error) {
1395                 if (error == EBADRPC || error == NFSERR_BADXDR)
1396                         nd->nd_repstat = NFSERR_BADXDR;
1397                 else
1398                         printf("nfsv4 comperr1=%d\n", error);
1399         }
1400         if (taglen == -1) {
1401                 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1402                 *tl++ = 0;
1403                 *tl = 0;
1404         } else {
1405                 *retopsp = txdr_unsigned(retops);
1406         }
1407         if (vp)
1408                 vrele(vp);
1409         if (savevp)
1410                 vrele(savevp);
1411         if (savecred != NULL)
1412                 nd->nd_cred = savecred;
1413         if (rootcred != NULL)
1414                 crfree(rootcred);
1415         NFSLOCKV4ROOTMUTEX();
1416         nfsv4_relref(&nfsv4rootfs_lock);
1417         NFSUNLOCKV4ROOTMUTEX();
1418
1419         NFSEXITCODE2(0, nd);
1420 }
1421
1422 /* Create a credential for "root". */
1423 static struct ucred *
1424 nfsrv_createrootcred(void)
1425 {
1426         struct ucred *cr;
1427         gid_t grp;
1428
1429         cr = crget();
1430         cr->cr_uid = cr->cr_ruid = cr->cr_svuid = UID_ROOT;
1431         grp = GID_WHEEL;
1432         crsetgroups(cr, 1, &grp);
1433         cr->cr_rgid = cr->cr_svgid = cr->cr_groups[0];
1434         cr->cr_prison = curthread->td_ucred->cr_prison;
1435         prison_hold(cr->cr_prison);
1436 #ifdef MAC
1437         mac_cred_associate_nfsd(cr);
1438 #endif
1439         return (cr);
1440 }