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 #include <fs/nfs/nfsport.h>
42
43 extern struct nfsstatsv1 nfsstatsv1;
44 extern struct nfsrvfh nfs_pubfh, nfs_rootfh;
45 extern int nfs_pubfhset, nfs_rootfhset;
46 extern struct nfsv4lock nfsv4rootfs_lock;
47 extern struct nfsrv_stablefirst nfsrv_stablefirst;
48 extern struct nfsclienthashhead *nfsclienthash;
49 extern int nfsrv_clienthashsize;
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_bindconnsess,
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_teststateid,
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
326 /*
327 * Static array that defines which nfs rpc's are nonidempotent
328 */
329 static int nfsrv_nonidempotent[NFS_V3NPROCS] = {
330 FALSE,
331 FALSE,
332 TRUE,
333 FALSE,
334 FALSE,
335 FALSE,
336 FALSE,
337 TRUE,
338 TRUE,
339 TRUE,
340 TRUE,
341 TRUE,
342 TRUE,
343 TRUE,
344 TRUE,
345 TRUE,
346 FALSE,
347 FALSE,
348 FALSE,
349 FALSE,
350 FALSE,
351 FALSE,
352 };
353
354 /*
355 * This static array indicates whether or not the RPC modifies the
356 * file system.
357 */
358 static int nfs_writerpc[NFS_NPROCS] = { 0, 0, 1, 0, 0, 0, 0,
359 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
360 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
361
362 /* local functions */
363 static void nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
364 u_char *tag, int taglen, u_int32_t minorvers, NFSPROC_T *p);
365
366
367 /*
368 * This static array indicates which server procedures require the extra
369 * arguments to return the current file handle for V2, 3.
370 */
371 static int nfs_retfh[NFS_V3NPROCS] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1,
372 1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0 };
373
374 extern struct nfsv4_opflag nfsv4_opflag[NFSV41_NOPS];
375
376 static int nfsv3to4op[NFS_V3NPROCS] = {
377 NFSPROC_NULL,
378 NFSV4OP_GETATTR,
379 NFSV4OP_SETATTR,
380 NFSV4OP_LOOKUP,
381 NFSV4OP_ACCESS,
382 NFSV4OP_READLINK,
383 NFSV4OP_READ,
384 NFSV4OP_WRITE,
385 NFSV4OP_V3CREATE,
386 NFSV4OP_MKDIR,
387 NFSV4OP_SYMLINK,
388 NFSV4OP_MKNOD,
389 NFSV4OP_REMOVE,
390 NFSV4OP_RMDIR,
391 NFSV4OP_RENAME,
392 NFSV4OP_LINK,
393 NFSV4OP_READDIR,
394 NFSV4OP_READDIRPLUS,
395 NFSV4OP_FSSTAT,
396 NFSV4OP_FSINFO,
397 NFSV4OP_PATHCONF,
398 NFSV4OP_COMMIT,
399 };
400
401 static struct mtx nfsrvd_statmtx;
402 MTX_SYSINIT(nfsst, &nfsrvd_statmtx, "NFSstat", MTX_DEF);
403
404 static void
405 nfsrvd_statstart(int op, struct bintime *now)
406 {
407 if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
408 printf("%s: op %d invalid\n", __func__, op);
409 return;
410 }
411
412 mtx_lock(&nfsrvd_statmtx);
413 if (nfsstatsv1.srvstartcnt == nfsstatsv1.srvdonecnt) {
414 if (now != NULL)
415 nfsstatsv1.busyfrom = *now;
416 else
417 binuptime(&nfsstatsv1.busyfrom);
418
419 }
420 nfsstatsv1.srvrpccnt[op]++;
421 nfsstatsv1.srvstartcnt++;
422 mtx_unlock(&nfsrvd_statmtx);
423
424 }
425
426 static void
427 nfsrvd_statend(int op, uint64_t bytes, struct bintime *now,
428 struct bintime *then)
429 {
430 struct bintime dt, lnow;
431
432 if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
433 printf("%s: op %d invalid\n", __func__, op);
434 return;
435 }
436
437 if (now == NULL) {
438 now = &lnow;
439 binuptime(now);
440 }
441
442 mtx_lock(&nfsrvd_statmtx);
443
444 nfsstatsv1.srvbytes[op] += bytes;
445 nfsstatsv1.srvops[op]++;
446
447 if (then != NULL) {
448 dt = *now;
449 bintime_sub(&dt, then);
450 bintime_add(&nfsstatsv1.srvduration[op], &dt);
451 }
452
453 dt = *now;
454 bintime_sub(&dt, &nfsstatsv1.busyfrom);
455 bintime_add(&nfsstatsv1.busytime, &dt);
456 nfsstatsv1.busyfrom = *now;
457
458 nfsstatsv1.srvdonecnt++;
459
460 mtx_unlock(&nfsrvd_statmtx);
461 }
462
463 /*
464 * Do an RPC. Basically, get the file handles translated to vnode pointers
465 * and then call the appropriate server routine. The server routines are
466 * split into groups, based on whether they use a file handle or file
467 * handle plus name or ...
468 * The NFS V4 Compound RPC is performed separately by nfsrvd_compound().
469 */
470 void
471 nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, u_char *tag, int taglen,
472 u_int32_t minorvers, NFSPROC_T *p)
473 {
474 int error = 0, lktype;
475 vnode_t vp;
476 mount_t mp = NULL;
477 struct nfsrvfh fh;
478 struct nfsexstuff nes;
479
480 /*
481 * Get a locked vnode for the first file handle
482 */
483 if (!(nd->nd_flag & ND_NFSV4)) {
484 KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc"));
485 /*
486 * For NFSv3, if the malloc/mget allocation is near limits,
487 * return NFSERR_DELAY.
488 */
489 if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) {
490 nd->nd_repstat = NFSERR_DELAY;
491 vp = NULL;
492 } else {
493 error = nfsrv_mtofh(nd, &fh);
494 if (error) {
495 if (error != EBADRPC)
496 printf("nfs dorpc err1=%d\n", error);
497 nd->nd_repstat = NFSERR_GARBAGE;
498 goto out;
499 }
500 if (nd->nd_procnum == NFSPROC_READ ||
501 nd->nd_procnum == NFSPROC_WRITE ||
502 nd->nd_procnum == NFSPROC_READDIR ||
503 nd->nd_procnum == NFSPROC_READDIRPLUS ||
504 nd->nd_procnum == NFSPROC_READLINK ||
505 nd->nd_procnum == NFSPROC_GETATTR ||
506 nd->nd_procnum == NFSPROC_ACCESS ||
507 nd->nd_procnum == NFSPROC_FSSTAT ||
508 nd->nd_procnum == NFSPROC_FSINFO)
509 lktype = LK_SHARED;
510 else
511 lktype = LK_EXCLUSIVE;
512 if (nd->nd_flag & ND_PUBLOOKUP)
513 nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes,
514 &mp, nfs_writerpc[nd->nd_procnum], p);
515 else
516 nfsd_fhtovp(nd, &fh, lktype, &vp, &nes,
517 &mp, nfs_writerpc[nd->nd_procnum], p);
518 if (nd->nd_repstat == NFSERR_PROGNOTV4)
519 goto out;
520 }
521 }
522
523 /*
524 * For V2 and 3, set the ND_SAVEREPLY flag for the recent request
525 * cache, as required.
526 * For V4, nfsrvd_compound() does this.
527 */
528 if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum])
529 nd->nd_flag |= ND_SAVEREPLY;
530
531 nfsrvd_rephead(nd);
532 /*
533 * If nd_repstat is non-zero, just fill in the reply status
534 * to complete the RPC reply for V2. Otherwise, you must do
535 * the RPC.
536 */
537 if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) {
538 *nd->nd_errp = nfsd_errmap(nd);
539 nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], /*now*/ NULL);
540 nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
541 /*now*/ NULL, /*then*/ NULL);
542 if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0)
543 vn_finished_write(mp);
544 goto out;
545 }
546
547 /*
548 * Now the procedure can be performed. For V4, nfsrvd_compound()
549 * works through the sub-rpcs, otherwise just call the procedure.
550 * The procedures are in three groups with different arguments.
551 * The group is indicated by the value in nfs_retfh[].
552 */
553 if (nd->nd_flag & ND_NFSV4) {
554 nfsrvd_compound(nd, isdgram, tag, taglen, minorvers, p);
555 } else {
556 struct bintime start_time;
557
558 binuptime(&start_time);
559 nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], &start_time);
560
561 if (nfs_retfh[nd->nd_procnum] == 1) {
562 if (vp)
563 NFSVOPUNLOCK(vp, 0);
564 error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram,
565 vp, NULL, (fhandle_t *)fh.nfsrvfh_data, p, &nes);
566 } else if (nfs_retfh[nd->nd_procnum] == 2) {
567 error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram,
568 vp, NULL, p, &nes, NULL);
569 } else {
570 error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
571 vp, p, &nes);
572 }
573 if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0)
574 vn_finished_write(mp);
575
576 nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
577 /*now*/ NULL, /*then*/ &start_time);
578 }
579 if (error) {
580 if (error != EBADRPC)
581 printf("nfs dorpc err2=%d\n", error);
582 nd->nd_repstat = NFSERR_GARBAGE;
583 }
584 *nd->nd_errp = nfsd_errmap(nd);
585
586 /*
587 * Don't cache certain reply status values.
588 */
589 if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) &&
590 (nd->nd_repstat == NFSERR_GARBAGE ||
591 nd->nd_repstat == NFSERR_BADXDR ||
592 nd->nd_repstat == NFSERR_MOVED ||
593 nd->nd_repstat == NFSERR_DELAY ||
594 nd->nd_repstat == NFSERR_BADSEQID ||
595 nd->nd_repstat == NFSERR_RESOURCE ||
596 nd->nd_repstat == NFSERR_SERVERFAULT ||
597 nd->nd_repstat == NFSERR_STALECLIENTID ||
598 nd->nd_repstat == NFSERR_STALESTATEID ||
599 nd->nd_repstat == NFSERR_OLDSTATEID ||
600 nd->nd_repstat == NFSERR_BADSTATEID ||
601 nd->nd_repstat == NFSERR_GRACE ||
602 nd->nd_repstat == NFSERR_NOGRACE))
603 nd->nd_flag &= ~ND_SAVEREPLY;
604
605 out:
606 NFSEXITCODE2(0, nd);
607 }
608
609 /*
610 * Breaks down a compound RPC request and calls the server routines for
611 * the subprocedures.
612 * Some suboperations are performed directly here to simplify file handle<-->
613 * vnode pointer handling.
614 */
615 static void
616 nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,
617 int taglen, u_int32_t minorvers, NFSPROC_T *p)
618 {
619 int i, lktype, op, op0 = 0, statsinprog = 0;
620 u_int32_t *tl;
621 struct nfsclient *clp, *nclp;
622 int numops, error = 0, igotlock;
623 u_int32_t retops = 0, *retopsp = NULL, *repp;
624 vnode_t vp, nvp, savevp;
625 struct nfsrvfh fh;
626 mount_t new_mp, temp_mp = NULL;
627 struct ucred *credanon;
628 struct nfsexstuff nes, vpnes, savevpnes;
629 fsid_t cur_fsid, save_fsid;
630 static u_int64_t compref = 0;
631 struct bintime start_time;
632
633 NFSVNO_EXINIT(&vpnes);
634 NFSVNO_EXINIT(&savevpnes);
635 /*
636 * Put the seq# of the current compound RPC in nfsrv_descript.
637 * (This is used by nfsrv_checkgetattr(), to see if the write
638 * delegation was created by the same compound RPC as the one
639 * with that Getattr in it.)
640 * Don't worry about the 64bit number wrapping around. It ain't
641 * gonna happen before this server gets shut down/rebooted.
642 */
643 nd->nd_compref = compref++;
644
645 /*
646 * Check for and optionally get a lock on the root. This lock means that
647 * no nfsd will be fiddling with the V4 file system and state stuff. It
648 * is required when the V4 root is being changed, the stable storage
649 * restart file is being updated, or callbacks are being done.
650 * When any of the nfsd are processing an NFSv4 compound RPC, they must
651 * either hold a reference count (nfs_usecnt) or the lock. When
652 * nfsrv_unlock() is called to release the lock, it can optionally
653 * also get a reference count, which saves the need for a call to
654 * nfsrv_getref() after nfsrv_unlock().
655 */
656 /*
657 * First, check to see if we need to wait for an update lock.
658 */
659 igotlock = 0;
660 NFSLOCKV4ROOTMUTEX();
661 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK)
662 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
663 NFSV4ROOTLOCKMUTEXPTR, NULL);
664 else
665 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
666 NFSV4ROOTLOCKMUTEXPTR, NULL);
667 NFSUNLOCKV4ROOTMUTEX();
668 if (igotlock) {
669 /*
670 * If I got the lock, I can update the stable storage file.
671 * Done when the grace period is over or a client has long
672 * since expired.
673 */
674 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK;
675 if ((nfsrv_stablefirst.nsf_flags &
676 (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
677 nfsrv_updatestable(p);
678
679 /*
680 * If at least one client has long since expired, search
681 * the client list for them, write a REVOKE record on the
682 * stable storage file and then remove them from the client
683 * list.
684 */
685 if (nfsrv_stablefirst.nsf_flags & NFSNSF_EXPIREDCLIENT) {
686 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_EXPIREDCLIENT;
687 for (i = 0; i < nfsrv_clienthashsize; i++) {
688 LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash,
689 nclp) {
690 if (clp->lc_flags & LCL_EXPIREIT) {
691 if (!LIST_EMPTY(&clp->lc_open) ||
692 !LIST_EMPTY(&clp->lc_deleg))
693 nfsrv_writestable(clp->lc_id,
694 clp->lc_idlen, NFSNST_REVOKE, p);
695 nfsrv_cleanclient(clp, p);
696 nfsrv_freedeleglist(&clp->lc_deleg);
697 nfsrv_freedeleglist(&clp->lc_olddeleg);
698 LIST_REMOVE(clp, lc_hash);
699 nfsrv_zapclient(clp, p);
700 }
701 }
702 }
703 }
704 NFSLOCKV4ROOTMUTEX();
705 nfsv4_unlock(&nfsv4rootfs_lock, 1);
706 NFSUNLOCKV4ROOTMUTEX();
707 } else {
708 /*
709 * If we didn't get the lock, we need to get a refcnt,
710 * which also checks for and waits for the lock.
711 */
712 NFSLOCKV4ROOTMUTEX();
713 nfsv4_getref(&nfsv4rootfs_lock, NULL,
714 NFSV4ROOTLOCKMUTEXPTR, NULL);
715 NFSUNLOCKV4ROOTMUTEX();
716 }
717
718 /*
719 * If flagged, search for open owners that haven't had any opens
720 * for a long time.
721 */
722 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) {
723 nfsrv_throwawayopens(p);
724 }
725
726 savevp = vp = NULL;
727 save_fsid.val[0] = save_fsid.val[1] = 0;
728 cur_fsid.val[0] = cur_fsid.val[1] = 0;
729
730 /* If taglen < 0, there was a parsing error in nfsd_getminorvers(). */
731 if (taglen < 0) {
732 error = EBADRPC;
733 goto nfsmout;
734 }
735
736 (void) nfsm_strtom(nd, tag, taglen);
737 NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED);
738 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
739 if (minorvers != NFSV4_MINORVERSION && minorvers != NFSV41_MINORVERSION)
740 nd->nd_repstat = NFSERR_MINORVERMISMATCH;
741 if (nd->nd_repstat)
742 numops = 0;
743 else
744 numops = fxdr_unsigned(int, *tl);
745 /*
746 * Loop around doing the sub ops.
747 * vp - is an unlocked vnode pointer for the CFH
748 * savevp - is an unlocked vnode pointer for the SAVEDFH
749 * (at some future date, it might turn out to be more appropriate
750 * to keep the file handles instead of vnode pointers?)
751 * savevpnes and vpnes - are the export flags for the above.
752 */
753 for (i = 0; i < numops; i++) {
754 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
755 NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED);
756 *repp = *tl;
757 op = fxdr_unsigned(int, *tl);
758 NFSD_DEBUG(4, "op=%d\n", op);
759 if (op < NFSV4OP_ACCESS ||
760 (op >= NFSV4OP_NOPS && (nd->nd_flag & ND_NFSV41) == 0) ||
761 (op >= NFSV41_NOPS && (nd->nd_flag & ND_NFSV41) != 0)) {
762 nd->nd_repstat = NFSERR_OPILLEGAL;
763 *repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL);
764 *repp = nfsd_errmap(nd);
765 retops++;
766 break;
767 } else {
768 repp++;
769 }
770
771 binuptime(&start_time);
772 nfsrvd_statstart(op, &start_time);
773 statsinprog = 1;
774
775 if (i == 0)
776 op0 = op;
777 if (i == numops - 1)
778 nd->nd_flag |= ND_LASTOP;
779
780 /*
781 * Check for a referral on the current FH and, if so, return
782 * NFSERR_MOVED for all ops that allow it, except Getattr.
783 */
784 if (vp != NULL && op != NFSV4OP_GETATTR &&
785 nfsv4root_getreferral(vp, NULL, 0) != NULL &&
786 nfsrv_errmoved(op)) {
787 nd->nd_repstat = NFSERR_MOVED;
788 *repp = nfsd_errmap(nd);
789 retops++;
790 break;
791 }
792
793 /*
794 * For NFSv4.1, check for a Sequence Operation being first
795 * or one of the other allowed operations by itself.
796 */
797 if ((nd->nd_flag & ND_NFSV41) != 0) {
798 if (i != 0 && op == NFSV4OP_SEQUENCE)
799 nd->nd_repstat = NFSERR_SEQUENCEPOS;
800 else if (i == 0 && op != NFSV4OP_SEQUENCE &&
801 op != NFSV4OP_EXCHANGEID &&
802 op != NFSV4OP_CREATESESSION &&
803 op != NFSV4OP_BINDCONNTOSESS &&
804 op != NFSV4OP_DESTROYCLIENTID &&
805 op != NFSV4OP_DESTROYSESSION)
806 nd->nd_repstat = NFSERR_OPNOTINSESS;
807 else if (i != 0 && op0 != NFSV4OP_SEQUENCE)
808 nd->nd_repstat = NFSERR_NOTONLYOP;
809 if (nd->nd_repstat != 0) {
810 *repp = nfsd_errmap(nd);
811 retops++;
812 break;
813 }
814 }
815
816 nd->nd_procnum = op;
817 /*
818 * If over flood level, reply NFSERR_RESOURCE, if at the first
819 * Op. (Since a client recovery from NFSERR_RESOURCE can get
820 * really nasty for certain Op sequences, I'll play it safe
821 * and only return the error at the beginning.) The cache
822 * will still function over flood level, but uses lots of
823 * mbufs.)
824 * If nfsrv_mallocmget_limit() returns True, the system is near
825 * to its limit for memory that malloc()/mget() can allocate.
826 */
827 if (i == 0 && (nd->nd_rp == NULL ||
828 nd->nd_rp->rc_refcnt == 0) &&
829 (nfsrv_mallocmget_limit() ||
830 nfsrc_tcpsavedreplies > nfsrc_floodlevel)) {
831 if (nfsrc_tcpsavedreplies > nfsrc_floodlevel)
832 printf("nfsd server cache flooded, try "
833 "increasing vfs.nfsd.tcphighwater\n");
834 nd->nd_repstat = NFSERR_RESOURCE;
835 *repp = nfsd_errmap(nd);
836 if (op == NFSV4OP_SETATTR) {
837 /*
838 * Setattr replies require a bitmap.
839 * even for errors like these.
840 */
841 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
842 *tl = 0;
843 }
844 retops++;
845 break;
846 }
847 if (nfsv4_opflag[op].savereply)
848 nd->nd_flag |= ND_SAVEREPLY;
849 switch (op) {
850 case NFSV4OP_PUTFH:
851 error = nfsrv_mtofh(nd, &fh);
852 if (error)
853 goto nfsmout;
854 if (!nd->nd_repstat)
855 nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
856 NULL, 0, p);
857 /* For now, allow this for non-export FHs */
858 if (!nd->nd_repstat) {
859 if (vp)
860 vrele(vp);
861 vp = nvp;
862 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
863 NFSVOPUNLOCK(vp, 0);
864 vpnes = nes;
865 }
866 break;
867 case NFSV4OP_PUTPUBFH:
868 if (nfs_pubfhset)
869 nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
870 &nes, NULL, 0, p);
871 else
872 nd->nd_repstat = NFSERR_NOFILEHANDLE;
873 if (!nd->nd_repstat) {
874 if (vp)
875 vrele(vp);
876 vp = nvp;
877 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
878 NFSVOPUNLOCK(vp, 0);
879 vpnes = nes;
880 }
881 break;
882 case NFSV4OP_PUTROOTFH:
883 if (nfs_rootfhset) {
884 nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp,
885 &nes, NULL, 0, p);
886 if (!nd->nd_repstat) {
887 if (vp)
888 vrele(vp);
889 vp = nvp;
890 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
891 NFSVOPUNLOCK(vp, 0);
892 vpnes = nes;
893 }
894 } else
895 nd->nd_repstat = NFSERR_NOFILEHANDLE;
896 break;
897 case NFSV4OP_SAVEFH:
898 if (vp && NFSVNO_EXPORTED(&vpnes)) {
899 nd->nd_repstat = 0;
900 /* If vp == savevp, a no-op */
901 if (vp != savevp) {
902 if (savevp)
903 vrele(savevp);
904 VREF(vp);
905 savevp = vp;
906 savevpnes = vpnes;
907 save_fsid = cur_fsid;
908 }
909 } else {
910 nd->nd_repstat = NFSERR_NOFILEHANDLE;
911 }
912 break;
913 case NFSV4OP_RESTOREFH:
914 if (savevp) {
915 nd->nd_repstat = 0;
916 /* If vp == savevp, a no-op */
917 if (vp != savevp) {
918 VREF(savevp);
919 vrele(vp);
920 vp = savevp;
921 vpnes = savevpnes;
922 cur_fsid = save_fsid;
923 }
924 } else {
925 nd->nd_repstat = NFSERR_RESTOREFH;
926 }
927 break;
928 default:
929 /*
930 * Allow a Lookup, Getattr, GetFH, Secinfo on an
931 * non-exported directory if
932 * nfs_rootfhset. Do I need to allow any other Ops?
933 * (You can only have a non-exported vpnes if
934 * nfs_rootfhset is true. See nfsd_fhtovp())
935 * Allow AUTH_SYS to be used for file systems
936 * exported GSS only for certain Ops, to allow
937 * clients to do mounts more easily.
938 */
939 if (nfsv4_opflag[op].needscfh && vp) {
940 if (!NFSVNO_EXPORTED(&vpnes) &&
941 op != NFSV4OP_LOOKUP &&
942 op != NFSV4OP_GETATTR &&
943 op != NFSV4OP_GETFH &&
944 op != NFSV4OP_ACCESS &&
945 op != NFSV4OP_READLINK &&
946 op != NFSV4OP_SECINFO)
947 nd->nd_repstat = NFSERR_NOFILEHANDLE;
948 else if (nfsvno_testexp(nd, &vpnes) &&
949 op != NFSV4OP_LOOKUP &&
950 op != NFSV4OP_GETFH &&
951 op != NFSV4OP_GETATTR &&
952 op != NFSV4OP_SECINFO)
953 nd->nd_repstat = NFSERR_WRONGSEC;
954 if (nd->nd_repstat) {
955 if (op == NFSV4OP_SETATTR) {
956 /*
957 * Setattr reply requires a bitmap
958 * even for errors like these.
959 */
960 NFSM_BUILD(tl, u_int32_t *,
961 NFSX_UNSIGNED);
962 *tl = 0;
963 }
964 break;
965 }
966 }
967 if (nfsv4_opflag[op].retfh == 1) {
968 if (!vp) {
969 nd->nd_repstat = NFSERR_NOFILEHANDLE;
970 break;
971 }
972 VREF(vp);
973 if (nfsv4_opflag[op].modifyfs)
974 vn_start_write(vp, &temp_mp, V_WAIT);
975 error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
976 &nvp, (fhandle_t *)fh.nfsrvfh_data, p, &vpnes);
977 if (!error && !nd->nd_repstat) {
978 if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) {
979 new_mp = nvp->v_mount;
980 if (cur_fsid.val[0] !=
981 new_mp->mnt_stat.f_fsid.val[0] ||
982 cur_fsid.val[1] !=
983 new_mp->mnt_stat.f_fsid.val[1]) {
984 /* crossed a server mount point */
985 nd->nd_repstat = nfsvno_checkexp(new_mp,
986 nd->nd_nam, &nes, &credanon);
987 if (!nd->nd_repstat)
988 nd->nd_repstat = nfsd_excred(nd,
989 &nes, credanon);
990 if (credanon != NULL)
991 crfree(credanon);
992 if (!nd->nd_repstat) {
993 vpnes = nes;
994 cur_fsid = new_mp->mnt_stat.f_fsid;
995 }
996 }
997 /* Lookup ops return a locked vnode */
998 NFSVOPUNLOCK(nvp, 0);
999 }
1000 if (!nd->nd_repstat) {
1001 vrele(vp);
1002 vp = nvp;
1003 } else
1004 vrele(nvp);
1005 }
1006 if (nfsv4_opflag[op].modifyfs)
1007 vn_finished_write(temp_mp);
1008 } else if (nfsv4_opflag[op].retfh == 2) {
1009 if (vp == NULL || savevp == NULL) {
1010 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1011 break;
1012 } else if (cur_fsid.val[0] != save_fsid.val[0] ||
1013 cur_fsid.val[1] != save_fsid.val[1]) {
1014 nd->nd_repstat = NFSERR_XDEV;
1015 break;
1016 }
1017 if (nfsv4_opflag[op].modifyfs)
1018 vn_start_write(savevp, &temp_mp, V_WAIT);
1019 if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
1020 VREF(vp);
1021 VREF(savevp);
1022 error = (*(nfsrv4_ops2[op]))(nd, isdgram,
1023 savevp, vp, p, &savevpnes, &vpnes);
1024 } else
1025 nd->nd_repstat = NFSERR_PERM;
1026 if (nfsv4_opflag[op].modifyfs)
1027 vn_finished_write(temp_mp);
1028 } else {
1029 if (nfsv4_opflag[op].retfh != 0)
1030 panic("nfsrvd_compound");
1031 if (nfsv4_opflag[op].needscfh) {
1032 if (vp != NULL) {
1033 lktype = nfsv4_opflag[op].lktype;
1034 if (nfsv4_opflag[op].modifyfs) {
1035 vn_start_write(vp, &temp_mp,
1036 V_WAIT);
1037 if (op == NFSV4OP_WRITE &&
1038 MNT_SHARED_WRITES(temp_mp))
1039 lktype = LK_SHARED;
1040 }
1041 if (NFSVOPLOCK(vp, lktype) == 0)
1042 VREF(vp);
1043 else
1044 nd->nd_repstat = NFSERR_PERM;
1045 } else {
1046 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1047 if (op == NFSV4OP_SETATTR) {
1048 /*
1049 * Setattr reply requires a
1050 * bitmap even for errors like
1051 * these.
1052 */
1053 NFSM_BUILD(tl, u_int32_t *,
1054 NFSX_UNSIGNED);
1055 *tl = 0;
1056 }
1057 break;
1058 }
1059 if (nd->nd_repstat == 0)
1060 error = (*(nfsrv4_ops0[op]))(nd,
1061 isdgram, vp, p, &vpnes);
1062 if (nfsv4_opflag[op].modifyfs)
1063 vn_finished_write(temp_mp);
1064 } else {
1065 error = (*(nfsrv4_ops0[op]))(nd, isdgram,
1066 NULL, p, &vpnes);
1067 }
1068 }
1069 }
1070 if (error) {
1071 if (error == EBADRPC || error == NFSERR_BADXDR) {
1072 nd->nd_repstat = NFSERR_BADXDR;
1073 } else {
1074 nd->nd_repstat = error;
1075 printf("nfsv4 comperr0=%d\n", error);
1076 }
1077 error = 0;
1078 }
1079
1080 if (statsinprog != 0) {
1081 nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1082 /*then*/ &start_time);
1083 statsinprog = 0;
1084 }
1085
1086 retops++;
1087 if (nd->nd_repstat) {
1088 *repp = nfsd_errmap(nd);
1089 break;
1090 } else {
1091 *repp = 0; /* NFS4_OK */
1092 }
1093 }
1094 nfsmout:
1095 if (statsinprog != 0) {
1096 nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1097 /*then*/ &start_time);
1098 statsinprog = 0;
1099 }
1100 if (error) {
1101 if (error == EBADRPC || error == NFSERR_BADXDR)
1102 nd->nd_repstat = NFSERR_BADXDR;
1103 else
1104 printf("nfsv4 comperr1=%d\n", error);
1105 }
1106 if (taglen == -1) {
1107 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1108 *tl++ = 0;
1109 *tl = 0;
1110 } else {
1111 *retopsp = txdr_unsigned(retops);
1112 }
1113 if (vp)
1114 vrele(vp);
1115 if (savevp)
1116 vrele(savevp);
1117 NFSLOCKV4ROOTMUTEX();
1118 nfsv4_relref(&nfsv4rootfs_lock);
1119 NFSUNLOCKV4ROOTMUTEX();
1120
1121 NFSEXITCODE2(0, nd);
1122 }
Cache object: e6577649a03ac1e55f8b20172795fe2b
|