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