2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Rick Macklem at The University of Guelph.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
38 * Socket operations for use by the nfs server.
42 #include <fs/nfs/nfsport.h>
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;
54 int (*nfsrv3_procs0[NFS_V3NPROCS])(struct nfsrv_descript *,
55 int, vnode_t , NFSPROC_T *, struct nfsexstuff *) = {
56 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
59 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
65 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
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,
70 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
71 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
80 int (*nfsrv3_procs1[NFS_V3NPROCS])(struct nfsrv_descript *,
81 int, vnode_t , vnode_t *, fhandle_t *,
82 NFSPROC_T *, struct nfsexstuff *) = {
83 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
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,
87 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
88 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
89 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
90 (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,
95 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
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,
107 int (*nfsrv3_procs2[NFS_V3NPROCS])(struct nfsrv_descript *,
108 int, vnode_t , vnode_t , NFSPROC_T *,
109 struct nfsexstuff *, struct nfsexstuff *) = {
110 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
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,
126 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
127 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
128 (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,
134 int (*nfsrv4_ops0[NFSV4OP_NOPS])(struct nfsrv_descript *,
135 int, vnode_t , NFSPROC_T *, struct nfsexstuff *) = {
136 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
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,
142 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
147 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
151 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
152 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
154 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
155 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
157 nfsrvd_opendowngrade,
158 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
159 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
160 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
165 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
167 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
168 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
172 nfsrvd_setclientidcfrm,
175 nfsrvd_releaselckown,
178 int (*nfsrv4_ops1[NFSV4OP_NOPS])(struct nfsrv_descript *,
179 int, vnode_t , vnode_t *, fhandle_t *,
180 NFSPROC_T *, struct nfsexstuff *) = {
181 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
182 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
183 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
184 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
185 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
186 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
188 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
189 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
190 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
191 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
192 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
193 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
194 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
195 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
198 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
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 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
208 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
209 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
210 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
211 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
212 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
213 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
214 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
215 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
216 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
217 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
218 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
219 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
220 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
223 int (*nfsrv4_ops2[NFSV4OP_NOPS])(struct nfsrv_descript *,
224 int, vnode_t , vnode_t , NFSPROC_T *,
225 struct nfsexstuff *, struct nfsexstuff *) = {
226 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
227 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
228 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
229 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
230 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
231 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
232 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
233 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
234 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
235 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
236 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
238 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
239 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
240 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
241 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
242 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
243 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
244 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
245 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
246 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
247 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
248 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
249 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
250 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
251 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
252 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
253 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
254 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
256 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
257 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
258 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
259 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
260 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
261 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
262 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
263 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
264 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
265 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , NFSPROC_T *, struct nfsexstuff *, struct nfsexstuff *))0,
267 #endif /* !APPLEKEXT */
270 * Static array that defines which nfs rpc's are nonidempotent
272 static int nfsrv_nonidempotent[NFS_V3NPROCS] = {
298 * This static array indicates whether or not the RPC modifies the
301 static int nfs_writerpc[NFS_NPROCS] = { 0, 0, 1, 0, 0, 0, 0,
302 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
303 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
305 /* local functions */
306 static void nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
311 * This static array indicates which server procedures require the extra
312 * arguments to return the current file handle for V2, 3.
314 static int nfs_retfh[NFS_V3NPROCS] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1,
315 1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0 };
317 extern struct nfsv4_opflag nfsv4_opflag[NFSV4OP_NOPS];
319 static int nfsv3to4op[NFS_V3NPROCS] = {
345 * Do an RPC. Basically, get the file handles translated to vnode pointers
346 * and then call the appropriate server routine. The server routines are
347 * split into groups, based on whether they use a file handle or file
348 * handle plus name or ...
349 * The NFS V4 Compound RPC is performed separately by nfsrvd_compound().
352 nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram,
355 int error = 0, lktype;
359 struct nfsexstuff nes;
362 * Get a locked vnode for the first file handle
364 if (!(nd->nd_flag & ND_NFSV4)) {
365 KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc"));
367 * For NFSv3, if the malloc/mget allocation is near limits,
368 * return NFSERR_DELAY.
370 if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) {
371 nd->nd_repstat = NFSERR_DELAY;
374 error = nfsrv_mtofh(nd, &fh);
376 if (error != EBADRPC)
377 printf("nfs dorpc err1=%d\n", error);
378 nd->nd_repstat = NFSERR_GARBAGE;
381 if (nd->nd_procnum == NFSPROC_READ ||
382 nd->nd_procnum == NFSPROC_READDIR ||
383 nd->nd_procnum == NFSPROC_READLINK ||
384 nd->nd_procnum == NFSPROC_GETATTR ||
385 nd->nd_procnum == NFSPROC_ACCESS)
388 lktype = LK_EXCLUSIVE;
389 if (nd->nd_flag & ND_PUBLOOKUP)
390 nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes,
391 &mp, nfs_writerpc[nd->nd_procnum], p);
393 nfsd_fhtovp(nd, &fh, lktype, &vp, &nes,
394 &mp, nfs_writerpc[nd->nd_procnum], p);
395 if (nd->nd_repstat == NFSERR_PROGNOTV4)
401 * For V2 and 3, set the ND_SAVEREPLY flag for the recent request
402 * cache, as required.
403 * For V4, nfsrvd_compound() does this.
405 if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum])
406 nd->nd_flag |= ND_SAVEREPLY;
410 * If nd_repstat is non-zero, just fill in the reply status
411 * to complete the RPC reply for V2. Otherwise, you must do
414 if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) {
415 *nd->nd_errp = nfsd_errmap(nd);
416 NFSINCRGLOBAL(newnfsstats.srvrpccnt[nfsv3to4op[nd->nd_procnum]]);
417 if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0)
418 vn_finished_write(mp);
423 * Now the procedure can be performed. For V4, nfsrvd_compound()
424 * works through the sub-rpcs, otherwise just call the procedure.
425 * The procedures are in three groups with different arguments.
426 * The group is indicated by the value in nfs_retfh[].
428 if (nd->nd_flag & ND_NFSV4) {
429 nfsrvd_compound(nd, isdgram, p);
431 if (nfs_retfh[nd->nd_procnum] == 1) {
434 error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram,
435 vp, NULL, (fhandle_t *)fh.nfsrvfh_data, p, &nes);
436 } else if (nfs_retfh[nd->nd_procnum] == 2) {
437 error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram,
438 vp, NULL, p, &nes, NULL);
440 error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
443 if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0)
444 vn_finished_write(mp);
445 NFSINCRGLOBAL(newnfsstats.srvrpccnt[nfsv3to4op[nd->nd_procnum]]);
448 if (error != EBADRPC)
449 printf("nfs dorpc err2=%d\n", error);
450 nd->nd_repstat = NFSERR_GARBAGE;
452 *nd->nd_errp = nfsd_errmap(nd);
455 * Don't cache certain reply status values.
457 if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) &&
458 (nd->nd_repstat == NFSERR_GARBAGE ||
459 nd->nd_repstat == NFSERR_BADXDR ||
460 nd->nd_repstat == NFSERR_MOVED ||
461 nd->nd_repstat == NFSERR_DELAY ||
462 nd->nd_repstat == NFSERR_BADSEQID ||
463 nd->nd_repstat == NFSERR_RESOURCE ||
464 nd->nd_repstat == NFSERR_SERVERFAULT ||
465 nd->nd_repstat == NFSERR_STALECLIENTID ||
466 nd->nd_repstat == NFSERR_STALESTATEID ||
467 nd->nd_repstat == NFSERR_OLDSTATEID ||
468 nd->nd_repstat == NFSERR_BADSTATEID ||
469 nd->nd_repstat == NFSERR_GRACE ||
470 nd->nd_repstat == NFSERR_NOGRACE))
471 nd->nd_flag &= ~ND_SAVEREPLY;
478 * Breaks down a compound RPC request and calls the server routines for
480 * Some suboperations are performed directly here to simplify file handle<-->
481 * vnode pointer handling.
484 nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
489 struct nfsclient *clp, *nclp;
490 int numops, taglen = -1, error = 0, igotlock;
491 u_int32_t minorvers, retops = 0, *retopsp = NULL, *repp;
492 u_char tag[NFSV4_SMALLSTR + 1], *tagstr;
493 vnode_t vp, nvp, savevp;
495 mount_t new_mp, temp_mp = NULL;
496 struct ucred *credanon;
497 struct nfsexstuff nes, vpnes, savevpnes;
498 fsid_t cur_fsid, save_fsid;
499 static u_int64_t compref = 0;
501 NFSVNO_EXINIT(&vpnes);
502 NFSVNO_EXINIT(&savevpnes);
504 * Put the seq# of the current compound RPC in nfsrv_descript.
505 * (This is used by nfsrv_checkgetattr(), to see if the write
506 * delegation was created by the same compound RPC as the one
507 * with that Getattr in it.)
508 * Don't worry about the 64bit number wrapping around. It ain't
509 * gonna happen before this server gets shut down/rebooted.
511 nd->nd_compref = compref++;
514 * Check for and optionally get a lock on the root. This lock means that
515 * no nfsd will be fiddling with the V4 file system and state stuff. It
516 * is required when the V4 root is being changed, the stable storage
517 * restart file is being updated, or callbacks are being done.
518 * When any of the nfsd are processing an NFSv4 compound RPC, they must
519 * either hold a reference count (nfs_usecnt) or the lock. When
520 * nfsrv_unlock() is called to release the lock, it can optionally
521 * also get a reference count, which saves the need for a call to
522 * nfsrv_getref() after nfsrv_unlock().
525 * First, check to see if we need to wait for an update lock.
528 NFSLOCKV4ROOTMUTEX();
529 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK)
530 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
531 NFSV4ROOTLOCKMUTEXPTR, NULL);
533 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
534 NFSV4ROOTLOCKMUTEXPTR, NULL);
535 NFSUNLOCKV4ROOTMUTEX();
538 * If I got the lock, I can update the stable storage file.
539 * Done when the grace period is over or a client has long
542 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK;
543 if ((nfsrv_stablefirst.nsf_flags &
544 (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
545 nfsrv_updatestable(p);
548 * If at least one client has long since expired, search
549 * the client list for them, write a REVOKE record on the
550 * stable storage file and then remove them from the client
553 if (nfsrv_stablefirst.nsf_flags & NFSNSF_EXPIREDCLIENT) {
554 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_EXPIREDCLIENT;
555 for (i = 0; i < NFSCLIENTHASHSIZE; i++) {
556 LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash,
558 if (clp->lc_flags & LCL_EXPIREIT) {
559 if (!LIST_EMPTY(&clp->lc_open) ||
560 !LIST_EMPTY(&clp->lc_deleg))
561 nfsrv_writestable(clp->lc_id,
562 clp->lc_idlen, NFSNST_REVOKE, p);
563 nfsrv_cleanclient(clp, p);
564 nfsrv_freedeleglist(&clp->lc_deleg);
565 nfsrv_freedeleglist(&clp->lc_olddeleg);
566 LIST_REMOVE(clp, lc_hash);
567 nfsrv_zapclient(clp, p);
572 NFSLOCKV4ROOTMUTEX();
573 nfsv4_unlock(&nfsv4rootfs_lock, 1);
574 NFSUNLOCKV4ROOTMUTEX();
577 * If we didn't get the lock, we need to get a refcnt,
578 * which also checks for and waits for the lock.
580 NFSLOCKV4ROOTMUTEX();
581 nfsv4_getref(&nfsv4rootfs_lock, NULL,
582 NFSV4ROOTLOCKMUTEXPTR, NULL);
583 NFSUNLOCKV4ROOTMUTEX();
587 * If flagged, search for open owners that haven't had any opens
590 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) {
591 nfsrv_throwawayopens(p);
595 save_fsid.val[0] = save_fsid.val[1] = 0;
596 cur_fsid.val[0] = cur_fsid.val[1] = 0;
597 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
598 taglen = fxdr_unsigned(int, *tl);
603 if (taglen <= NFSV4_SMALLSTR)
606 tagstr = malloc(taglen + 1, M_TEMP, M_WAITOK);
607 error = nfsrv_mtostr(nd, tagstr, taglen);
609 if (taglen > NFSV4_SMALLSTR)
610 free(tagstr, M_TEMP);
614 (void) nfsm_strtom(nd, tag, taglen);
615 if (taglen > NFSV4_SMALLSTR) {
616 free(tagstr, M_TEMP);
618 NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED);
619 NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
620 minorvers = fxdr_unsigned(u_int32_t, *tl++);
621 if (minorvers != NFSV4_MINORVERSION)
622 nd->nd_repstat = NFSERR_MINORVERMISMATCH;
626 numops = fxdr_unsigned(int, *tl);
628 * Loop around doing the sub ops.
629 * vp - is an unlocked vnode pointer for the CFH
630 * savevp - is an unlocked vnode pointer for the SAVEDFH
631 * (at some future date, it might turn out to be more appropriate
632 * to keep the file handles instead of vnode pointers?)
633 * savevpnes and vpnes - are the export flags for the above.
635 for (i = 0; i < numops; i++) {
636 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
637 NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED);
639 op = fxdr_unsigned(int, *tl);
640 if (op < NFSV4OP_ACCESS || op >= NFSV4OP_NOPS) {
641 nd->nd_repstat = NFSERR_OPILLEGAL;
642 *repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL);
643 *repp = nfsd_errmap(nd);
651 * Check for a referral on the current FH and, if so, return
652 * NFSERR_MOVED for all ops that allow it, except Getattr.
654 if (vp != NULL && op != NFSV4OP_GETATTR &&
655 nfsv4root_getreferral(vp, NULL, 0) != NULL &&
656 nfsrv_errmoved(op)) {
657 nd->nd_repstat = NFSERR_MOVED;
658 *repp = nfsd_errmap(nd);
665 * If over flood level, reply NFSERR_RESOURCE, if at the first
666 * Op. (Since a client recovery from NFSERR_RESOURCE can get
667 * really nasty for certain Op sequences, I'll play it safe
668 * and only return the error at the beginning.) The cache
669 * will still function over flood level, but uses lots of
671 * If nfsrv_mallocmget_limit() returns True, the system is near
672 * to its limit for memory that malloc()/mget() can allocate.
674 if (i == 0 && nd->nd_rp->rc_refcnt == 0 &&
675 (nfsrv_mallocmget_limit() ||
676 nfsrc_tcpsavedreplies > nfsrc_floodlevel)) {
677 if (nfsrc_tcpsavedreplies > nfsrc_floodlevel) {
678 printf("nfsd server cache flooded, try to");
679 printf(" increase nfsrc_floodlevel\n");
681 nd->nd_repstat = NFSERR_RESOURCE;
682 *repp = nfsd_errmap(nd);
683 if (op == NFSV4OP_SETATTR) {
685 * Setattr replies require a bitmap.
686 * even for errors like these.
688 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
694 if (nfsv4_opflag[op].savereply)
695 nd->nd_flag |= ND_SAVEREPLY;
696 NFSINCRGLOBAL(newnfsstats.srvrpccnt[nd->nd_procnum]);
699 error = nfsrv_mtofh(nd, &fh);
703 nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
705 /* For now, allow this for non-export FHs */
706 if (!nd->nd_repstat) {
710 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
715 case NFSV4OP_PUTPUBFH:
717 nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
720 nd->nd_repstat = NFSERR_NOFILEHANDLE;
721 if (!nd->nd_repstat) {
725 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
730 case NFSV4OP_PUTROOTFH:
732 nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp,
734 if (!nd->nd_repstat) {
738 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
743 nd->nd_repstat = NFSERR_NOFILEHANDLE;
746 if (vp && NFSVNO_EXPORTED(&vpnes)) {
748 /* If vp == savevp, a no-op */
755 save_fsid = cur_fsid;
758 nd->nd_repstat = NFSERR_NOFILEHANDLE;
761 case NFSV4OP_RESTOREFH:
764 /* If vp == savevp, a no-op */
770 cur_fsid = save_fsid;
773 nd->nd_repstat = NFSERR_RESTOREFH;
778 * Allow a Lookup, Getattr, GetFH, Secinfo on an
779 * non-exported directory if
780 * nfs_rootfhset. Do I need to allow any other Ops?
781 * (You can only have a non-exported vpnes if
782 * nfs_rootfhset is true. See nfsd_fhtovp())
783 * Allow AUTH_SYS to be used for file systems
784 * exported GSS only for certain Ops, to allow
785 * clients to do mounts more easily.
787 if (nfsv4_opflag[op].needscfh && vp) {
788 if (!NFSVNO_EXPORTED(&vpnes) &&
789 op != NFSV4OP_LOOKUP &&
790 op != NFSV4OP_GETATTR &&
791 op != NFSV4OP_GETFH &&
792 op != NFSV4OP_ACCESS &&
793 op != NFSV4OP_READLINK &&
794 op != NFSV4OP_SECINFO)
795 nd->nd_repstat = NFSERR_NOFILEHANDLE;
796 else if (nfsvno_testexp(nd, &vpnes) &&
797 op != NFSV4OP_LOOKUP &&
798 op != NFSV4OP_GETFH &&
799 op != NFSV4OP_GETATTR &&
800 op != NFSV4OP_SECINFO)
801 nd->nd_repstat = NFSERR_WRONGSEC;
802 if (nd->nd_repstat) {
803 if (op == NFSV4OP_SETATTR) {
805 * Setattr reply requires a bitmap
806 * even for errors like these.
808 NFSM_BUILD(tl, u_int32_t *,
815 if (nfsv4_opflag[op].retfh == 1) {
817 nd->nd_repstat = NFSERR_NOFILEHANDLE;
821 if (nfsv4_opflag[op].modifyfs)
822 vn_start_write(vp, &temp_mp, V_WAIT);
823 error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
824 &nvp, (fhandle_t *)fh.nfsrvfh_data, p, &vpnes);
825 if (!error && !nd->nd_repstat) {
826 if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) {
827 new_mp = nvp->v_mount;
828 if (cur_fsid.val[0] !=
829 new_mp->mnt_stat.f_fsid.val[0] ||
831 new_mp->mnt_stat.f_fsid.val[1]) {
832 /* crossed a server mount point */
833 nd->nd_repstat = nfsvno_checkexp(new_mp,
834 nd->nd_nam, &nes, &credanon);
836 nd->nd_repstat = nfsd_excred(nd,
838 if (credanon != NULL)
840 if (!nd->nd_repstat) {
842 cur_fsid = new_mp->mnt_stat.f_fsid;
845 /* Lookup ops return a locked vnode */
846 NFSVOPUNLOCK(nvp, 0);
848 if (!nd->nd_repstat) {
854 if (nfsv4_opflag[op].modifyfs)
855 vn_finished_write(temp_mp);
856 } else if (nfsv4_opflag[op].retfh == 2) {
857 if (vp == NULL || savevp == NULL) {
858 nd->nd_repstat = NFSERR_NOFILEHANDLE;
860 } else if (cur_fsid.val[0] != save_fsid.val[0] ||
861 cur_fsid.val[1] != save_fsid.val[1]) {
862 nd->nd_repstat = NFSERR_XDEV;
865 if (nfsv4_opflag[op].modifyfs)
866 vn_start_write(savevp, &temp_mp, V_WAIT);
867 if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
870 error = (*(nfsrv4_ops2[op]))(nd, isdgram,
871 savevp, vp, p, &savevpnes, &vpnes);
873 nd->nd_repstat = NFSERR_PERM;
874 if (nfsv4_opflag[op].modifyfs)
875 vn_finished_write(temp_mp);
877 if (nfsv4_opflag[op].retfh != 0)
878 panic("nfsrvd_compound");
879 if (nfsv4_opflag[op].needscfh) {
881 if (nfsv4_opflag[op].modifyfs)
882 vn_start_write(vp, &temp_mp,
884 if (NFSVOPLOCK(vp, nfsv4_opflag[op].lktype)
888 nd->nd_repstat = NFSERR_PERM;
890 nd->nd_repstat = NFSERR_NOFILEHANDLE;
891 if (op == NFSV4OP_SETATTR) {
893 * Setattr reply requires a
894 * bitmap even for errors like
897 NFSM_BUILD(tl, u_int32_t *,
903 if (nd->nd_repstat == 0)
904 error = (*(nfsrv4_ops0[op]))(nd,
905 isdgram, vp, p, &vpnes);
906 if (nfsv4_opflag[op].modifyfs)
907 vn_finished_write(temp_mp);
909 error = (*(nfsrv4_ops0[op]))(nd, isdgram,
915 if (error == EBADRPC || error == NFSERR_BADXDR) {
916 nd->nd_repstat = NFSERR_BADXDR;
918 nd->nd_repstat = error;
919 printf("nfsv4 comperr0=%d\n", error);
924 if (nd->nd_repstat) {
925 *repp = nfsd_errmap(nd);
928 *repp = 0; /* NFS4_OK */
933 if (error == EBADRPC || error == NFSERR_BADXDR)
934 nd->nd_repstat = NFSERR_BADXDR;
936 printf("nfsv4 comperr1=%d\n", error);
939 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
943 *retopsp = txdr_unsigned(retops);
949 NFSLOCKV4ROOTMUTEX();
950 nfsv4_relref(&nfsv4rootfs_lock);
951 NFSUNLOCKV4ROOTMUTEX();