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