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 NFSV4ROOTLOCKMUTEX;
52 NFSSTATESPINLOCK;
53
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,
57 nfsrvd_getattr,
58 nfsrvd_setattr,
59 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
60 nfsrvd_access,
61 nfsrvd_readlink,
62 nfsrvd_read,
63 nfsrvd_write,
64 nfsrvd_create,
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,
68 nfsrvd_remove,
69 nfsrvd_remove,
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,
72 nfsrvd_readdir,
73 nfsrvd_readdirplus,
74 nfsrvd_statfs,
75 nfsrvd_fsinfo,
76 nfsrvd_pathconf,
77 nfsrvd_commit,
78 };
79
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,
86 nfsrvd_lookup,
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,
92 nfsrvd_mkdir,
93 nfsrvd_symlink,
94 nfsrvd_mknod,
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,
105 };
106
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,
124 nfsrvd_rename,
125 nfsrvd_link,
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,
132 };
133
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,
139 nfsrvd_access,
140 nfsrvd_close,
141 nfsrvd_commit,
142 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
143 nfsrvd_delegpurge,
144 nfsrvd_delegreturn,
145 nfsrvd_getattr,
146 nfsrvd_getfh,
147 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
148 nfsrvd_lock,
149 nfsrvd_lockt,
150 nfsrvd_locku,
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,
153 nfsrvd_verify,
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,
156 nfsrvd_openconfirm,
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,
161 nfsrvd_read,
162 nfsrvd_readdirplus,
163 nfsrvd_readlink,
164 nfsrvd_remove,
165 (int (*)(struct nfsrv_descript *, int, vnode_t , NFSPROC_T *, struct nfsexstuff *))0,
166 nfsrvd_renew,
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,
169 nfsrvd_secinfo,
170 nfsrvd_setattr,
171 nfsrvd_setclientid,
172 nfsrvd_setclientidcfrm,
173 nfsrvd_verify,
174 nfsrvd_write,
175 nfsrvd_releaselckown,
176 };
177
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,
187 nfsrvd_mknod,
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,
196 nfsrvd_lookup,
197 nfsrvd_lookup,
198 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, NFSPROC_T *, struct nfsexstuff *))0,
199 nfsrvd_open,
200 nfsrvd_openattr,
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,
221 };
222
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,
237 nfsrvd_link,
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,
255 nfsrvd_rename,
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,
266 };
267 #endif /* !APPLEKEXT */
268
269 /*
270 * Static array that defines which nfs rpc's are nonidempotent
271 */
272 static int nfsrv_nonidempotent[NFS_V3NPROCS] = {
273 FALSE,
274 FALSE,
275 TRUE,
276 FALSE,
277 FALSE,
278 FALSE,
279 FALSE,
280 TRUE,
281 TRUE,
282 TRUE,
283 TRUE,
284 TRUE,
285 TRUE,
286 TRUE,
287 TRUE,
288 TRUE,
289 FALSE,
290 FALSE,
291 FALSE,
292 FALSE,
293 FALSE,
294 FALSE,
295 };
296
297 /*
298 * This static array indicates whether or not the RPC modifies the
299 * file system.
300 */
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 };
304
305 /* local functions */
306 static void nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
307 NFSPROC_T *p);
308
309
310 /*
311 * This static array indicates which server procedures require the extra
312 * arguments to return the current file handle for V2, 3.
313 */
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 };
316
317 extern struct nfsv4_opflag nfsv4_opflag[NFSV4OP_NOPS];
318
319 static int nfsv3to4op[NFS_V3NPROCS] = {
320 NFSPROC_NULL,
321 NFSV4OP_GETATTR,
322 NFSV4OP_SETATTR,
323 NFSV4OP_LOOKUP,
324 NFSV4OP_ACCESS,
325 NFSV4OP_READLINK,
326 NFSV4OP_READ,
327 NFSV4OP_WRITE,
328 NFSV4OP_V3CREATE,
329 NFSV4OP_MKDIR,
330 NFSV4OP_SYMLINK,
331 NFSV4OP_MKNOD,
332 NFSV4OP_REMOVE,
333 NFSV4OP_RMDIR,
334 NFSV4OP_RENAME,
335 NFSV4OP_LINK,
336 NFSV4OP_READDIR,
337 NFSV4OP_READDIRPLUS,
338 NFSV4OP_FSSTAT,
339 NFSV4OP_FSINFO,
340 NFSV4OP_PATHCONF,
341 NFSV4OP_COMMIT,
342 };
343
344 /*
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().
350 */
351 APPLESTATIC void
352 nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram,
353 NFSPROC_T *p)
354 {
355 int error = 0, lktype;
356 vnode_t vp;
357 mount_t mp = NULL;
358 struct nfsrvfh fh;
359 struct nfsexstuff nes;
360
361 /*
362 * Get a locked vnode for the first file handle
363 */
364 if (!(nd->nd_flag & ND_NFSV4)) {
365 KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc"));
366 /*
367 * For NFSv3, if the malloc/mget allocation is near limits,
368 * return NFSERR_DELAY.
369 */
370 if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) {
371 nd->nd_repstat = NFSERR_DELAY;
372 vp = NULL;
373 } else {
374 error = nfsrv_mtofh(nd, &fh);
375 if (error) {
376 if (error != EBADRPC)
377 printf("nfs dorpc err1=%d\n", error);
378 nd->nd_repstat = NFSERR_GARBAGE;
379 goto out;
380 }
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)
386 lktype = LK_SHARED;
387 else
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);
392 else
393 nfsd_fhtovp(nd, &fh, lktype, &vp, &nes,
394 &mp, nfs_writerpc[nd->nd_procnum], p);
395 if (nd->nd_repstat == NFSERR_PROGNOTV4)
396 goto out;
397 }
398 }
399
400 /*
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.
404 */
405 if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum])
406 nd->nd_flag |= ND_SAVEREPLY;
407
408 nfsrvd_rephead(nd);
409 /*
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
412 * the RPC.
413 */
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);
419 goto out;
420 }
421
422 /*
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[].
427 */
428 if (nd->nd_flag & ND_NFSV4) {
429 nfsrvd_compound(nd, isdgram, p);
430 } else {
431 if (nfs_retfh[nd->nd_procnum] == 1) {
432 if (vp)
433 NFSVOPUNLOCK(vp, 0);
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);
439 } else {
440 error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
441 vp, p, &nes);
442 }
443 if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0)
444 vn_finished_write(mp);
445 NFSINCRGLOBAL(newnfsstats.srvrpccnt[nfsv3to4op[nd->nd_procnum]]);
446 }
447 if (error) {
448 if (error != EBADRPC)
449 printf("nfs dorpc err2=%d\n", error);
450 nd->nd_repstat = NFSERR_GARBAGE;
451 }
452 *nd->nd_errp = nfsd_errmap(nd);
453
454 /*
455 * Don't cache certain reply status values.
456 */
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;
472
473 out:
474 NFSEXITCODE2(0, nd);
475 }
476
477 /*
478 * Breaks down a compound RPC request and calls the server routines for
479 * the subprocedures.
480 * Some suboperations are performed directly here to simplify file handle<-->
481 * vnode pointer handling.
482 */
483 static void
484 nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
485 NFSPROC_T *p)
486 {
487 int i, op;
488 u_int32_t *tl;
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;
494 struct nfsrvfh fh;
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;
500
501 NFSVNO_EXINIT(&vpnes);
502 NFSVNO_EXINIT(&savevpnes);
503 /*
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.
510 */
511 nd->nd_compref = compref++;
512
513 /*
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().
523 */
524 /*
525 * First, check to see if we need to wait for an update lock.
526 */
527 igotlock = 0;
528 NFSLOCKV4ROOTMUTEX();
529 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK)
530 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
531 NFSV4ROOTLOCKMUTEXPTR, NULL);
532 else
533 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
534 NFSV4ROOTLOCKMUTEXPTR, NULL);
535 NFSUNLOCKV4ROOTMUTEX();
536 if (igotlock) {
537 /*
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
540 * since expired.
541 */
542 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK;
543 if ((nfsrv_stablefirst.nsf_flags &
544 (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
545 nfsrv_updatestable(p);
546
547 /*
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
551 * list.
552 */
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,
557 nclp) {
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);
568 }
569 }
570 }
571 }
572 NFSLOCKV4ROOTMUTEX();
573 nfsv4_unlock(&nfsv4rootfs_lock, 1);
574 NFSUNLOCKV4ROOTMUTEX();
575 } else {
576 /*
577 * If we didn't get the lock, we need to get a refcnt,
578 * which also checks for and waits for the lock.
579 */
580 NFSLOCKV4ROOTMUTEX();
581 nfsv4_getref(&nfsv4rootfs_lock, NULL,
582 NFSV4ROOTLOCKMUTEXPTR, NULL);
583 NFSUNLOCKV4ROOTMUTEX();
584 }
585
586 /*
587 * If flagged, search for open owners that haven't had any opens
588 * for a long time.
589 */
590 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) {
591 nfsrv_throwawayopens(p);
592 }
593
594 savevp = vp = NULL;
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);
599 if (taglen < 0) {
600 error = EBADRPC;
601 goto nfsmout;
602 }
603 if (taglen <= NFSV4_SMALLSTR)
604 tagstr = tag;
605 else
606 tagstr = malloc(taglen + 1, M_TEMP, M_WAITOK);
607 error = nfsrv_mtostr(nd, tagstr, taglen);
608 if (error) {
609 if (taglen > NFSV4_SMALLSTR)
610 free(tagstr, M_TEMP);
611 taglen = -1;
612 goto nfsmout;
613 }
614 (void) nfsm_strtom(nd, tag, taglen);
615 if (taglen > NFSV4_SMALLSTR) {
616 free(tagstr, M_TEMP);
617 }
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;
623 if (nd->nd_repstat)
624 numops = 0;
625 else
626 numops = fxdr_unsigned(int, *tl);
627 /*
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.
634 */
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);
638 *repp = *tl;
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);
644 retops++;
645 break;
646 } else {
647 repp++;
648 }
649
650 /*
651 * Check for a referral on the current FH and, if so, return
652 * NFSERR_MOVED for all ops that allow it, except Getattr.
653 */
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);
659 retops++;
660 break;
661 }
662
663 nd->nd_procnum = op;
664 /*
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
670 * mbufs.)
671 * If nfsrv_mallocmget_limit() returns True, the system is near
672 * to its limit for memory that malloc()/mget() can allocate.
673 */
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");
680 }
681 nd->nd_repstat = NFSERR_RESOURCE;
682 *repp = nfsd_errmap(nd);
683 if (op == NFSV4OP_SETATTR) {
684 /*
685 * Setattr replies require a bitmap.
686 * even for errors like these.
687 */
688 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
689 *tl = 0;
690 }
691 retops++;
692 break;
693 }
694 if (nfsv4_opflag[op].savereply)
695 nd->nd_flag |= ND_SAVEREPLY;
696 NFSINCRGLOBAL(newnfsstats.srvrpccnt[nd->nd_procnum]);
697 switch (op) {
698 case NFSV4OP_PUTFH:
699 error = nfsrv_mtofh(nd, &fh);
700 if (error)
701 goto nfsmout;
702 if (!nd->nd_repstat)
703 nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
704 NULL, 0, p);
705 /* For now, allow this for non-export FHs */
706 if (!nd->nd_repstat) {
707 if (vp)
708 vrele(vp);
709 vp = nvp;
710 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
711 NFSVOPUNLOCK(vp, 0);
712 vpnes = nes;
713 }
714 break;
715 case NFSV4OP_PUTPUBFH:
716 if (nfs_pubfhset)
717 nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
718 &nes, NULL, 0, p);
719 else
720 nd->nd_repstat = NFSERR_NOFILEHANDLE;
721 if (!nd->nd_repstat) {
722 if (vp)
723 vrele(vp);
724 vp = nvp;
725 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
726 NFSVOPUNLOCK(vp, 0);
727 vpnes = nes;
728 }
729 break;
730 case NFSV4OP_PUTROOTFH:
731 if (nfs_rootfhset) {
732 nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp,
733 &nes, NULL, 0, p);
734 if (!nd->nd_repstat) {
735 if (vp)
736 vrele(vp);
737 vp = nvp;
738 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
739 NFSVOPUNLOCK(vp, 0);
740 vpnes = nes;
741 }
742 } else
743 nd->nd_repstat = NFSERR_NOFILEHANDLE;
744 break;
745 case NFSV4OP_SAVEFH:
746 if (vp && NFSVNO_EXPORTED(&vpnes)) {
747 nd->nd_repstat = 0;
748 /* If vp == savevp, a no-op */
749 if (vp != savevp) {
750 if (savevp)
751 vrele(savevp);
752 VREF(vp);
753 savevp = vp;
754 savevpnes = vpnes;
755 save_fsid = cur_fsid;
756 }
757 } else {
758 nd->nd_repstat = NFSERR_NOFILEHANDLE;
759 }
760 break;
761 case NFSV4OP_RESTOREFH:
762 if (savevp) {
763 nd->nd_repstat = 0;
764 /* If vp == savevp, a no-op */
765 if (vp != savevp) {
766 VREF(savevp);
767 vrele(vp);
768 vp = savevp;
769 vpnes = savevpnes;
770 cur_fsid = save_fsid;
771 }
772 } else {
773 nd->nd_repstat = NFSERR_RESTOREFH;
774 }
775 break;
776 default:
777 /*
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.
786 */
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) {
804 /*
805 * Setattr reply requires a bitmap
806 * even for errors like these.
807 */
808 NFSM_BUILD(tl, u_int32_t *,
809 NFSX_UNSIGNED);
810 *tl = 0;
811 }
812 break;
813 }
814 }
815 if (nfsv4_opflag[op].retfh == 1) {
816 if (!vp) {
817 nd->nd_repstat = NFSERR_NOFILEHANDLE;
818 break;
819 }
820 VREF(vp);
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] ||
830 cur_fsid.val[1] !=
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);
835 if (!nd->nd_repstat)
836 nd->nd_repstat = nfsd_excred(nd,
837 &nes, credanon);
838 if (credanon != NULL)
839 crfree(credanon);
840 if (!nd->nd_repstat) {
841 vpnes = nes;
842 cur_fsid = new_mp->mnt_stat.f_fsid;
843 }
844 }
845 /* Lookup ops return a locked vnode */
846 NFSVOPUNLOCK(nvp, 0);
847 }
848 if (!nd->nd_repstat) {
849 vrele(vp);
850 vp = nvp;
851 } else
852 vrele(nvp);
853 }
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;
859 break;
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;
863 break;
864 }
865 if (nfsv4_opflag[op].modifyfs)
866 vn_start_write(savevp, &temp_mp, V_WAIT);
867 if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
868 VREF(vp);
869 VREF(savevp);
870 error = (*(nfsrv4_ops2[op]))(nd, isdgram,
871 savevp, vp, p, &savevpnes, &vpnes);
872 } else
873 nd->nd_repstat = NFSERR_PERM;
874 if (nfsv4_opflag[op].modifyfs)
875 vn_finished_write(temp_mp);
876 } else {
877 if (nfsv4_opflag[op].retfh != 0)
878 panic("nfsrvd_compound");
879 if (nfsv4_opflag[op].needscfh) {
880 if (vp != NULL) {
881 if (nfsv4_opflag[op].modifyfs)
882 vn_start_write(vp, &temp_mp,
883 V_WAIT);
884 if (NFSVOPLOCK(vp, nfsv4_opflag[op].lktype)
885 == 0)
886 VREF(vp);
887 else
888 nd->nd_repstat = NFSERR_PERM;
889 } else {
890 nd->nd_repstat = NFSERR_NOFILEHANDLE;
891 if (op == NFSV4OP_SETATTR) {
892 /*
893 * Setattr reply requires a
894 * bitmap even for errors like
895 * these.
896 */
897 NFSM_BUILD(tl, u_int32_t *,
898 NFSX_UNSIGNED);
899 *tl = 0;
900 }
901 break;
902 }
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);
908 } else {
909 error = (*(nfsrv4_ops0[op]))(nd, isdgram,
910 NULL, p, &vpnes);
911 }
912 }
913 };
914 if (error) {
915 if (error == EBADRPC || error == NFSERR_BADXDR) {
916 nd->nd_repstat = NFSERR_BADXDR;
917 } else {
918 nd->nd_repstat = error;
919 printf("nfsv4 comperr0=%d\n", error);
920 }
921 error = 0;
922 }
923 retops++;
924 if (nd->nd_repstat) {
925 *repp = nfsd_errmap(nd);
926 break;
927 } else {
928 *repp = 0; /* NFS4_OK */
929 }
930 }
931 nfsmout:
932 if (error) {
933 if (error == EBADRPC || error == NFSERR_BADXDR)
934 nd->nd_repstat = NFSERR_BADXDR;
935 else
936 printf("nfsv4 comperr1=%d\n", error);
937 }
938 if (taglen == -1) {
939 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
940 *tl++ = 0;
941 *tl = 0;
942 } else {
943 *retopsp = txdr_unsigned(retops);
944 }
945 if (vp)
946 vrele(vp);
947 if (savevp)
948 vrele(savevp);
949 NFSLOCKV4ROOTMUTEX();
950 nfsv4_relref(&nfsv4rootfs_lock);
951 NFSUNLOCKV4ROOTMUTEX();
952
953 NFSEXITCODE2(0, nd);
954 }
Cache object: 737a2f556a6f9b332201cce9e80677c2
|