Print this page
NEX-16917 Need to reduce the impact of NFS per-share kstats on failover
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
NEX-16712 NFS dtrace providers do not support per-share filtering
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Yuri Pankon <yuri.pankov@nexenta.com>
NEX-15279 support NFS server in zone
NEX-15520 online NFS shares cause zoneadm halt to hang in nfs_export_zone_fini
Portions contributed by: Dan Kruchinin dan.kruchinin@nexenta.com
Portions contributed by: Stepan Zastupov stepan.zastupov@gmail.com
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
NEX-9275 Got "bad mutex" panic when run IO to nfs share from clients
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
NEX-14051 Be careful with RPC groups
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
8085 Handle RPC groups better
Reviewed by: "Joshua M. Clulow" <josh@sysmgr.org>
Reviewed by: Paul Dagnelie <pcd@delphix.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Approved by: Dan McDonald <danmcd@omniti.com>
NEX-7366 Getting panic in "module "nfssrv" due to a NULL pointer dereference" when updating NFS shares on a pool
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Steve Peng <steve.peng@nexenta.com>
NEX-6778 NFS kstats leak and cause system to hang
Revert "NEX-4261 Per-client NFS server IOPS, bandwidth, and latency kstats"
This reverts commit 586c3ab1927647487f01c337ddc011c642575a52.
Revert "NEX-5354 Aggregated IOPS, bandwidth, and latency kstats for NFS server"
This reverts commit c91d7614da8618ef48018102b077f60ecbbac8c2.
Revert "NEX-5667 nfssrv_stats_flags does not work for aggregated kstats"
This reverts commit 3dcf42618be7dd5f408c327f429c81e07ca08e74.
Revert "NEX-5750 Time values for aggregated NFS server kstats should be normalized"
This reverts commit 1f4d4f901153b0191027969fa4a8064f9d3b9ee1.
Revert "NEX-5942 Panic in rfs4_minorvers_mismatch() with NFSv4.1 client"
This reverts commit 40766417094a162f5e4cc8786c0fa0a7e5871cd9.
Revert "NEX-5752 NFS server: namespace collision in kstats"
This reverts commit ae81e668db86050da8e483264acb0cce0444a132.
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-4261 Per-client NFS server IOPS, bandwidth, and latency kstats
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-3097 IOPS, bandwidth, and latency kstats for NFS server
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
NEX-1974 Support for more than 16 groups with AUTH_SYS
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
NEX-1128 NFS server: Generic uid and gid remapping for AUTH_SYS
Reviewed by: Jan Kryl <jan.kryl@nexenta.com>
re #13613 rb4516 Tunables needs volatile keyword
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/fs/nfs/nfs_server.c
+++ new/usr/src/uts/common/fs/nfs/nfs_server.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
|
↓ open down ↓ |
10 lines elided |
↑ open up ↑ |
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 +
21 22 /*
22 23 * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
23 - * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
24 - * Copyright (c) 2013 by Delphix. All rights reserved.
25 - * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
26 - * Copyright (c) 2017 Joyent Inc
27 24 */
28 25
29 26 /*
30 27 * Copyright (c) 1983,1984,1985,1986,1987,1988,1989 AT&T.
31 28 * All rights reserved.
32 29 * Use is subject to license terms.
33 30 */
34 31
32 +/*
33 + * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
34 + * Copyright (c) 2013 by Delphix. All rights reserved.
35 + * Copyright 2018 Nexenta Systems, Inc.
36 + * Copyright (c) 2017 Joyent Inc
37 + */
38 +
35 39 #include <sys/param.h>
36 40 #include <sys/types.h>
37 41 #include <sys/systm.h>
38 42 #include <sys/cred.h>
39 43 #include <sys/proc.h>
40 44 #include <sys/user.h>
41 45 #include <sys/buf.h>
42 46 #include <sys/vfs.h>
43 47 #include <sys/vnode.h>
44 48 #include <sys/pathname.h>
45 49 #include <sys/uio.h>
46 50 #include <sys/file.h>
47 51 #include <sys/stat.h>
48 52 #include <sys/errno.h>
49 53 #include <sys/socket.h>
50 54 #include <sys/sysmacros.h>
51 55 #include <sys/siginfo.h>
52 56 #include <sys/tiuser.h>
53 57 #include <sys/statvfs.h>
54 58 #include <sys/stream.h>
55 59 #include <sys/strsun.h>
56 60 #include <sys/strsubr.h>
57 61 #include <sys/stropts.h>
58 62 #include <sys/timod.h>
59 63 #include <sys/t_kuser.h>
60 64 #include <sys/kmem.h>
61 65 #include <sys/kstat.h>
62 66 #include <sys/dirent.h>
63 67 #include <sys/cmn_err.h>
64 68 #include <sys/debug.h>
65 69 #include <sys/unistd.h>
66 70 #include <sys/vtrace.h>
67 71 #include <sys/mode.h>
68 72 #include <sys/acl.h>
69 73 #include <sys/sdt.h>
70 74 #include <sys/debug.h>
71 75
72 76 #include <rpc/types.h>
73 77 #include <rpc/auth.h>
74 78 #include <rpc/auth_unix.h>
75 79 #include <rpc/auth_des.h>
|
↓ open down ↓ |
31 lines elided |
↑ open up ↑ |
76 80 #include <rpc/svc.h>
77 81 #include <rpc/xdr.h>
78 82 #include <rpc/rpc_rdma.h>
79 83
80 84 #include <nfs/nfs.h>
81 85 #include <nfs/export.h>
82 86 #include <nfs/nfssys.h>
83 87 #include <nfs/nfs_clnt.h>
84 88 #include <nfs/nfs_acl.h>
85 89 #include <nfs/nfs_log.h>
86 -#include <nfs/nfs_cmd.h>
87 90 #include <nfs/lm.h>
88 91 #include <nfs/nfs_dispatch.h>
89 92 #include <nfs/nfs4_drc.h>
90 93
91 94 #include <sys/modctl.h>
92 95 #include <sys/cladm.h>
93 96 #include <sys/clconf.h>
94 97
95 98 #include <sys/tsol/label.h>
96 99
97 100 #define MAXHOST 32
98 101 const char *kinet_ntop6(uchar_t *, char *, size_t);
99 102
100 103 /*
101 104 * Module linkage information.
|
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
102 105 */
103 106
104 107 static struct modlmisc modlmisc = {
105 108 &mod_miscops, "NFS server module"
106 109 };
107 110
108 111 static struct modlinkage modlinkage = {
109 112 MODREV_1, (void *)&modlmisc, NULL
110 113 };
111 114
115 +zone_key_t nfssrv_zone_key;
112 116 kmem_cache_t *nfs_xuio_cache;
113 117 int nfs_loaned_buffers = 0;
114 118
115 119 int
116 120 _init(void)
117 121 {
118 122 int status;
119 123
120 - if ((status = nfs_srvinit()) != 0) {
121 - cmn_err(CE_WARN, "_init: nfs_srvinit failed");
122 - return (status);
123 - }
124 + nfs_srvinit();
124 125
125 126 status = mod_install((struct modlinkage *)&modlinkage);
126 127 if (status != 0) {
127 128 /*
128 129 * Could not load module, cleanup previous
129 130 * initialization work.
130 131 */
131 132 nfs_srvfini();
132 133
133 134 return (status);
134 135 }
135 136
136 137 /*
137 138 * Initialise some placeholders for nfssys() calls. These have
138 139 * to be declared by the nfs module, since that handles nfssys()
139 140 * calls - also used by NFS clients - but are provided by this
140 141 * nfssrv module. These also then serve as confirmation to the
141 142 * relevant code in nfs that nfssrv has been loaded, as they're
142 143 * initially NULL.
143 144 */
144 145 nfs_srv_quiesce_func = nfs_srv_quiesce_all;
145 146 nfs_srv_dss_func = rfs4_dss_setpaths;
146 147
147 148 /* setup DSS paths here; must be done before initial server startup */
148 149 rfs4_dss_paths = rfs4_dss_oldpaths = NULL;
149 150
150 151 /* initialize the copy reduction caches */
151 152
152 153 nfs_xuio_cache = kmem_cache_create("nfs_xuio_cache",
153 154 sizeof (nfs_xuio_t), 0, NULL, NULL, NULL, NULL, NULL, 0);
154 155
155 156 return (status);
156 157 }
157 158
158 159 int
159 160 _fini()
160 161 {
161 162 return (EBUSY);
162 163 }
163 164
164 165 int
165 166 _info(struct modinfo *modinfop)
166 167 {
167 168 return (mod_info(&modlinkage, modinfop));
168 169 }
169 170
|
↓ open down ↓ |
36 lines elided |
↑ open up ↑ |
170 171 /*
171 172 * PUBLICFH_CHECK() checks if the dispatch routine supports
172 173 * RPC_PUBLICFH_OK, if the filesystem is exported public, and if the
173 174 * incoming request is using the public filehandle. The check duplicates
174 175 * the exportmatch() call done in checkexport(), and we should consider
175 176 * modifying those routines to avoid the duplication. For now, we optimize
176 177 * by calling exportmatch() only after checking that the dispatch routine
177 178 * supports RPC_PUBLICFH_OK, and if the filesystem is explicitly exported
178 179 * public (i.e., not the placeholder).
179 180 */
180 -#define PUBLICFH_CHECK(disp, exi, fsid, xfid) \
181 +#define PUBLICFH_CHECK(ne, disp, exi, fsid, xfid) \
181 182 ((disp->dis_flags & RPC_PUBLICFH_OK) && \
182 183 ((exi->exi_export.ex_flags & EX_PUBLIC) || \
183 - (exi == exi_public && exportmatch(exi_root, \
184 + (exi == ne->exi_public && exportmatch(ne->exi_root, \
184 185 fsid, xfid))))
185 186
186 187 static void nfs_srv_shutdown_all(int);
187 -static void rfs4_server_start(int);
188 +static void rfs4_server_start(nfs_globals_t *, int);
188 189 static void nullfree(void);
189 190 static void rfs_dispatch(struct svc_req *, SVCXPRT *);
190 191 static void acl_dispatch(struct svc_req *, SVCXPRT *);
191 192 static void common_dispatch(struct svc_req *, SVCXPRT *,
192 193 rpcvers_t, rpcvers_t, char *,
193 194 struct rpc_disptable *);
194 -static void hanfsv4_failover(void);
195 195 static int checkauth(struct exportinfo *, struct svc_req *, cred_t *, int,
196 196 bool_t, bool_t *);
197 197 static char *client_name(struct svc_req *req);
198 198 static char *client_addr(struct svc_req *req, char *buf);
199 199 extern int sec_svc_getcred(struct svc_req *, cred_t *cr, char **, int *);
200 200 extern bool_t sec_svc_inrootlist(int, caddr_t, int, caddr_t *);
201 +static void *nfs_srv_zone_init(zoneid_t);
202 +static void nfs_srv_zone_fini(zoneid_t, void *);
201 203
202 204 #define NFSLOG_COPY_NETBUF(exi, xprt, nb) { \
203 205 (nb)->maxlen = (xprt)->xp_rtaddr.maxlen; \
204 206 (nb)->len = (xprt)->xp_rtaddr.len; \
205 207 (nb)->buf = kmem_alloc((nb)->len, KM_SLEEP); \
206 208 bcopy((xprt)->xp_rtaddr.buf, (nb)->buf, (nb)->len); \
207 209 }
208 210
209 211 /*
210 212 * Public Filehandle common nfs routines
211 213 */
212 214 static int MCLpath(char **);
213 215 static void URLparse(char *);
214 216
215 217 /*
216 218 * NFS callout table.
217 219 * This table is used by svc_getreq() to dispatch a request with
218 220 * a given prog/vers pair to an appropriate service provider
219 221 * dispatch routine.
220 222 *
221 223 * NOTE: ordering is relied upon below when resetting the version min/max
222 224 * for NFS_PROGRAM. Careful, if this is ever changed.
223 225 */
224 226 static SVC_CALLOUT __nfs_sc_clts[] = {
225 227 { NFS_PROGRAM, NFS_VERSMIN, NFS_VERSMAX, rfs_dispatch },
226 228 { NFS_ACL_PROGRAM, NFS_ACL_VERSMIN, NFS_ACL_VERSMAX, acl_dispatch }
227 229 };
228 230
229 231 static SVC_CALLOUT_TABLE nfs_sct_clts = {
230 232 sizeof (__nfs_sc_clts) / sizeof (__nfs_sc_clts[0]), FALSE,
231 233 __nfs_sc_clts
232 234 };
233 235
234 236 static SVC_CALLOUT __nfs_sc_cots[] = {
235 237 { NFS_PROGRAM, NFS_VERSMIN, NFS_VERSMAX, rfs_dispatch },
236 238 { NFS_ACL_PROGRAM, NFS_ACL_VERSMIN, NFS_ACL_VERSMAX, acl_dispatch }
237 239 };
238 240
239 241 static SVC_CALLOUT_TABLE nfs_sct_cots = {
240 242 sizeof (__nfs_sc_cots) / sizeof (__nfs_sc_cots[0]), FALSE, __nfs_sc_cots
|
↓ open down ↓ |
30 lines elided |
↑ open up ↑ |
241 243 };
242 244
243 245 static SVC_CALLOUT __nfs_sc_rdma[] = {
244 246 { NFS_PROGRAM, NFS_VERSMIN, NFS_VERSMAX, rfs_dispatch },
245 247 { NFS_ACL_PROGRAM, NFS_ACL_VERSMIN, NFS_ACL_VERSMAX, acl_dispatch }
246 248 };
247 249
248 250 static SVC_CALLOUT_TABLE nfs_sct_rdma = {
249 251 sizeof (__nfs_sc_rdma) / sizeof (__nfs_sc_rdma[0]), FALSE, __nfs_sc_rdma
250 252 };
251 -rpcvers_t nfs_versmin = NFS_VERSMIN_DEFAULT;
252 -rpcvers_t nfs_versmax = NFS_VERSMAX_DEFAULT;
253 253
254 254 /*
255 - * Used to track the state of the server so that initialization
256 - * can be done properly.
257 - */
258 -typedef enum {
259 - NFS_SERVER_STOPPED, /* server state destroyed */
260 - NFS_SERVER_STOPPING, /* server state being destroyed */
261 - NFS_SERVER_RUNNING,
262 - NFS_SERVER_QUIESCED, /* server state preserved */
263 - NFS_SERVER_OFFLINE /* server pool offline */
264 -} nfs_server_running_t;
265 -
266 -static nfs_server_running_t nfs_server_upordown;
267 -static kmutex_t nfs_server_upordown_lock;
268 -static kcondvar_t nfs_server_upordown_cv;
269 -
270 -/*
271 255 * DSS: distributed stable storage
272 256 * lists of all DSS paths: current, and before last warmstart
273 257 */
274 258 nvlist_t *rfs4_dss_paths, *rfs4_dss_oldpaths;
275 259
276 -int rfs4_dispatch(struct rpcdisp *, struct svc_req *, SVCXPRT *, char *);
260 +int rfs4_dispatch(struct rpcdisp *, struct svc_req *, SVCXPRT *, char *,
261 + size_t *);
277 262 bool_t rfs4_minorvers_mismatch(struct svc_req *, SVCXPRT *, void *);
278 263
279 264 /*
280 - * RDMA wait variables.
281 - */
282 -static kcondvar_t rdma_wait_cv;
283 -static kmutex_t rdma_wait_mutex;
284 -
285 -/*
286 265 * Will be called at the point the server pool is being unregistered
287 266 * from the pool list. From that point onwards, the pool is waiting
288 267 * to be drained and as such the server state is stale and pertains
289 268 * to the old instantiation of the NFS server pool.
290 269 */
291 270 void
292 271 nfs_srv_offline(void)
293 272 {
294 - mutex_enter(&nfs_server_upordown_lock);
295 - if (nfs_server_upordown == NFS_SERVER_RUNNING) {
296 - nfs_server_upordown = NFS_SERVER_OFFLINE;
273 + nfs_globals_t *ng;
274 +
275 + ng = zone_getspecific(nfssrv_zone_key, curzone);
276 +
277 + mutex_enter(&ng->nfs_server_upordown_lock);
278 + if (ng->nfs_server_upordown == NFS_SERVER_RUNNING) {
279 + ng->nfs_server_upordown = NFS_SERVER_OFFLINE;
297 280 }
298 - mutex_exit(&nfs_server_upordown_lock);
281 + mutex_exit(&ng->nfs_server_upordown_lock);
299 282 }
300 283
301 284 /*
302 285 * Will be called at the point the server pool is being destroyed so
303 286 * all transports have been closed and no service threads are in
304 287 * existence.
305 288 *
306 289 * If we quiesce the server, we're shutting it down without destroying the
307 290 * server state. This allows it to warm start subsequently.
308 291 */
309 292 void
310 293 nfs_srv_stop_all(void)
311 294 {
312 295 int quiesce = 0;
313 296 nfs_srv_shutdown_all(quiesce);
314 297 }
315 298
316 299 /*
|
↓ open down ↓ |
8 lines elided |
↑ open up ↑ |
317 300 * This alternative shutdown routine can be requested via nfssys()
318 301 */
319 302 void
320 303 nfs_srv_quiesce_all(void)
321 304 {
322 305 int quiesce = 1;
323 306 nfs_srv_shutdown_all(quiesce);
324 307 }
325 308
326 309 static void
327 -nfs_srv_shutdown_all(int quiesce) {
328 - mutex_enter(&nfs_server_upordown_lock);
310 +nfs_srv_shutdown_all(int quiesce)
311 +{
312 + nfs_globals_t *ng = zone_getspecific(nfssrv_zone_key, curzone);
313 +
314 + mutex_enter(&ng->nfs_server_upordown_lock);
329 315 if (quiesce) {
330 - if (nfs_server_upordown == NFS_SERVER_RUNNING ||
331 - nfs_server_upordown == NFS_SERVER_OFFLINE) {
332 - nfs_server_upordown = NFS_SERVER_QUIESCED;
333 - cv_signal(&nfs_server_upordown_cv);
316 + if (ng->nfs_server_upordown == NFS_SERVER_RUNNING ||
317 + ng->nfs_server_upordown == NFS_SERVER_OFFLINE) {
318 + ng->nfs_server_upordown = NFS_SERVER_QUIESCED;
319 + cv_signal(&ng->nfs_server_upordown_cv);
334 320
335 321 /* reset DSS state, for subsequent warm restart */
336 322 rfs4_dss_numnewpaths = 0;
337 323 rfs4_dss_newpaths = NULL;
338 324
339 325 cmn_err(CE_NOTE, "nfs_server: server is now quiesced; "
340 326 "NFSv4 state has been preserved");
341 327 }
342 328 } else {
343 - if (nfs_server_upordown == NFS_SERVER_OFFLINE) {
344 - nfs_server_upordown = NFS_SERVER_STOPPING;
345 - mutex_exit(&nfs_server_upordown_lock);
346 - rfs4_state_fini();
347 - rfs4_fini_drc(nfs4_drc);
348 - mutex_enter(&nfs_server_upordown_lock);
349 - nfs_server_upordown = NFS_SERVER_STOPPED;
350 - cv_signal(&nfs_server_upordown_cv);
329 + if (ng->nfs_server_upordown == NFS_SERVER_OFFLINE) {
330 + ng->nfs_server_upordown = NFS_SERVER_STOPPING;
331 + mutex_exit(&ng->nfs_server_upordown_lock);
332 + rfs4_state_zone_fini();
333 + rfs4_fini_drc();
334 + mutex_enter(&ng->nfs_server_upordown_lock);
335 + ng->nfs_server_upordown = NFS_SERVER_STOPPED;
336 + cv_signal(&ng->nfs_server_upordown_cv);
351 337 }
352 338 }
353 - mutex_exit(&nfs_server_upordown_lock);
339 + mutex_exit(&ng->nfs_server_upordown_lock);
354 340 }
355 341
356 342 static int
357 343 nfs_srv_set_sc_versions(struct file *fp, SVC_CALLOUT_TABLE **sctpp,
358 - rpcvers_t versmin, rpcvers_t versmax)
344 + rpcvers_t versmin, rpcvers_t versmax)
359 345 {
360 346 struct strioctl strioc;
361 347 struct T_info_ack tinfo;
362 348 int error, retval;
363 349
364 350 /*
365 351 * Find out what type of transport this is.
366 352 */
367 353 strioc.ic_cmd = TI_GETINFO;
368 354 strioc.ic_timout = -1;
369 355 strioc.ic_len = sizeof (tinfo);
370 356 strioc.ic_dp = (char *)&tinfo;
371 357 tinfo.PRIM_type = T_INFO_REQ;
372 358
373 359 error = strioctl(fp->f_vnode, I_STR, (intptr_t)&strioc, 0, K_TO_K,
374 360 CRED(), &retval);
375 361 if (error || retval)
376 362 return (error);
377 363
378 364 /*
379 365 * Based on our query of the transport type...
380 366 *
381 367 * Reset the min/max versions based on the caller's request
382 368 * NOTE: This assumes that NFS_PROGRAM is first in the array!!
383 369 * And the second entry is the NFS_ACL_PROGRAM.
384 370 */
385 371 switch (tinfo.SERV_type) {
386 372 case T_CLTS:
387 373 if (versmax == NFS_V4)
388 374 return (EINVAL);
389 375 __nfs_sc_clts[0].sc_versmin = versmin;
390 376 __nfs_sc_clts[0].sc_versmax = versmax;
391 377 __nfs_sc_clts[1].sc_versmin = versmin;
392 378 __nfs_sc_clts[1].sc_versmax = versmax;
393 379 *sctpp = &nfs_sct_clts;
394 380 break;
395 381 case T_COTS:
396 382 case T_COTS_ORD:
397 383 __nfs_sc_cots[0].sc_versmin = versmin;
398 384 __nfs_sc_cots[0].sc_versmax = versmax;
399 385 /* For the NFS_ACL program, check the max version */
400 386 if (versmax > NFS_ACL_VERSMAX)
401 387 versmax = NFS_ACL_VERSMAX;
402 388 __nfs_sc_cots[1].sc_versmin = versmin;
403 389 __nfs_sc_cots[1].sc_versmax = versmax;
404 390 *sctpp = &nfs_sct_cots;
405 391 break;
406 392 default:
407 393 error = EINVAL;
408 394 }
409 395
410 396 return (error);
|
↓ open down ↓ |
42 lines elided |
↑ open up ↑ |
411 397 }
412 398
413 399 /*
414 400 * NFS Server system call.
415 401 * Does all of the work of running a NFS server.
416 402 * uap->fd is the fd of an open transport provider
417 403 */
418 404 int
419 405 nfs_svc(struct nfs_svc_args *arg, model_t model)
420 406 {
407 + nfs_globals_t *ng;
421 408 file_t *fp;
422 409 SVCMASTERXPRT *xprt;
423 410 int error;
424 411 int readsize;
425 412 char buf[KNC_STRSIZE];
426 413 size_t len;
427 414 STRUCT_HANDLE(nfs_svc_args, uap);
428 415 struct netbuf addrmask;
429 416 SVC_CALLOUT_TABLE *sctp = NULL;
430 417
431 418 #ifdef lint
432 419 model = model; /* STRUCT macros don't always refer to it */
433 420 #endif
434 421
422 + ng = zone_getspecific(nfssrv_zone_key, curzone);
435 423 STRUCT_SET_HANDLE(uap, model, arg);
436 424
437 425 /* Check privileges in nfssys() */
438 426
439 427 if ((fp = getf(STRUCT_FGET(uap, fd))) == NULL)
440 428 return (EBADF);
441 429
442 430 /*
443 431 * Set read buffer size to rsize
444 432 * and add room for RPC headers.
445 433 */
446 434 readsize = nfs3tsize() + (RPC_MAXDATASIZE - NFS_MAXDATA);
447 435 if (readsize < RPC_MAXDATASIZE)
448 436 readsize = RPC_MAXDATASIZE;
449 437
450 438 error = copyinstr((const char *)STRUCT_FGETP(uap, netid), buf,
451 439 KNC_STRSIZE, &len);
452 440 if (error) {
453 441 releasef(STRUCT_FGET(uap, fd));
454 442 return (error);
455 443 }
456 444
457 445 addrmask.len = STRUCT_FGET(uap, addrmask.len);
|
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
458 446 addrmask.maxlen = STRUCT_FGET(uap, addrmask.maxlen);
459 447 addrmask.buf = kmem_alloc(addrmask.maxlen, KM_SLEEP);
460 448 error = copyin(STRUCT_FGETP(uap, addrmask.buf), addrmask.buf,
461 449 addrmask.len);
462 450 if (error) {
463 451 releasef(STRUCT_FGET(uap, fd));
464 452 kmem_free(addrmask.buf, addrmask.maxlen);
465 453 return (error);
466 454 }
467 455
468 - nfs_versmin = STRUCT_FGET(uap, versmin);
469 - nfs_versmax = STRUCT_FGET(uap, versmax);
456 + ng->nfs_versmin = STRUCT_FGET(uap, versmin);
457 + ng->nfs_versmax = STRUCT_FGET(uap, versmax);
470 458
471 459 /* Double check the vers min/max ranges */
472 - if ((nfs_versmin > nfs_versmax) ||
473 - (nfs_versmin < NFS_VERSMIN) ||
474 - (nfs_versmax > NFS_VERSMAX)) {
475 - nfs_versmin = NFS_VERSMIN_DEFAULT;
476 - nfs_versmax = NFS_VERSMAX_DEFAULT;
460 + if ((ng->nfs_versmin > ng->nfs_versmax) ||
461 + (ng->nfs_versmin < NFS_VERSMIN) ||
462 + (ng->nfs_versmax > NFS_VERSMAX)) {
463 + ng->nfs_versmin = NFS_VERSMIN_DEFAULT;
464 + ng->nfs_versmax = NFS_VERSMAX_DEFAULT;
477 465 }
478 466
479 - if (error =
480 - nfs_srv_set_sc_versions(fp, &sctp, nfs_versmin, nfs_versmax)) {
467 + if (error = nfs_srv_set_sc_versions(fp, &sctp, ng->nfs_versmin,
468 + ng->nfs_versmax)) {
481 469 releasef(STRUCT_FGET(uap, fd));
482 470 kmem_free(addrmask.buf, addrmask.maxlen);
483 471 return (error);
484 472 }
485 473
486 474 /* Initialize nfsv4 server */
487 - if (nfs_versmax == (rpcvers_t)NFS_V4)
488 - rfs4_server_start(STRUCT_FGET(uap, delegation));
475 + if (ng->nfs_versmax == (rpcvers_t)NFS_V4)
476 + rfs4_server_start(ng, STRUCT_FGET(uap, delegation));
489 477
490 478 /* Create a transport handle. */
491 479 error = svc_tli_kcreate(fp, readsize, buf, &addrmask, &xprt,
492 480 sctp, NULL, NFS_SVCPOOL_ID, TRUE);
493 481
494 482 if (error)
495 483 kmem_free(addrmask.buf, addrmask.maxlen);
496 484
497 485 releasef(STRUCT_FGET(uap, fd));
498 486
499 487 /* HA-NFSv4: save the cluster nodeid */
500 488 if (cluster_bootflags & CLUSTER_BOOTED)
501 489 lm_global_nlmid = clconf_get_nodeid();
502 490
503 491 return (error);
504 492 }
505 493
506 494 static void
507 -rfs4_server_start(int nfs4_srv_delegation)
495 +rfs4_server_start(nfs_globals_t *ng, int nfs4_srv_delegation)
508 496 {
509 497 /*
510 498 * Determine if the server has previously been "started" and
511 499 * if not, do the per instance initialization
512 500 */
513 - mutex_enter(&nfs_server_upordown_lock);
501 + mutex_enter(&ng->nfs_server_upordown_lock);
514 502
515 - if (nfs_server_upordown != NFS_SERVER_RUNNING) {
503 + if (ng->nfs_server_upordown != NFS_SERVER_RUNNING) {
516 504 /* Do we need to stop and wait on the previous server? */
517 - while (nfs_server_upordown == NFS_SERVER_STOPPING ||
518 - nfs_server_upordown == NFS_SERVER_OFFLINE)
519 - cv_wait(&nfs_server_upordown_cv,
520 - &nfs_server_upordown_lock);
505 + while (ng->nfs_server_upordown == NFS_SERVER_STOPPING ||
506 + ng->nfs_server_upordown == NFS_SERVER_OFFLINE)
507 + cv_wait(&ng->nfs_server_upordown_cv,
508 + &ng->nfs_server_upordown_lock);
521 509
522 - if (nfs_server_upordown != NFS_SERVER_RUNNING) {
510 + if (ng->nfs_server_upordown != NFS_SERVER_RUNNING) {
523 511 (void) svc_pool_control(NFS_SVCPOOL_ID,
524 512 SVCPSET_UNREGISTER_PROC, (void *)&nfs_srv_offline);
525 513 (void) svc_pool_control(NFS_SVCPOOL_ID,
526 514 SVCPSET_SHUTDOWN_PROC, (void *)&nfs_srv_stop_all);
527 515
528 - /* is this an nfsd warm start? */
529 - if (nfs_server_upordown == NFS_SERVER_QUIESCED) {
530 - cmn_err(CE_NOTE, "nfs_server: "
531 - "server was previously quiesced; "
532 - "existing NFSv4 state will be re-used");
516 + rfs4_do_server_start(ng->nfs_server_upordown,
517 + nfs4_srv_delegation,
518 + cluster_bootflags & CLUSTER_BOOTED);
533 519
534 - /*
535 - * HA-NFSv4: this is also the signal
536 - * that a Resource Group failover has
537 - * occurred.
538 - */
539 - if (cluster_bootflags & CLUSTER_BOOTED)
540 - hanfsv4_failover();
541 - } else {
542 - /* cold start */
543 - rfs4_state_init();
544 - nfs4_drc = rfs4_init_drc(nfs4_drc_max,
545 - nfs4_drc_hash);
546 - }
547 -
548 - /*
549 - * Check to see if delegation is to be
550 - * enabled at the server
551 - */
552 - if (nfs4_srv_delegation != FALSE)
553 - rfs4_set_deleg_policy(SRV_NORMAL_DELEGATE);
554 -
555 - nfs_server_upordown = NFS_SERVER_RUNNING;
520 + ng->nfs_server_upordown = NFS_SERVER_RUNNING;
556 521 }
557 - cv_signal(&nfs_server_upordown_cv);
522 + cv_signal(&ng->nfs_server_upordown_cv);
558 523 }
559 - mutex_exit(&nfs_server_upordown_lock);
524 + mutex_exit(&ng->nfs_server_upordown_lock);
560 525 }
561 526
562 527 /*
563 528 * If RDMA device available,
564 529 * start RDMA listener.
565 530 */
566 531 int
567 532 rdma_start(struct rdma_svc_args *rsa)
568 533 {
534 + nfs_globals_t *ng;
569 535 int error;
570 536 rdma_xprt_group_t started_rdma_xprts;
571 537 rdma_stat stat;
572 538 int svc_state = 0;
573 539
574 540 /* Double check the vers min/max ranges */
575 541 if ((rsa->nfs_versmin > rsa->nfs_versmax) ||
576 542 (rsa->nfs_versmin < NFS_VERSMIN) ||
577 543 (rsa->nfs_versmax > NFS_VERSMAX)) {
578 544 rsa->nfs_versmin = NFS_VERSMIN_DEFAULT;
579 545 rsa->nfs_versmax = NFS_VERSMAX_DEFAULT;
580 546 }
581 - nfs_versmin = rsa->nfs_versmin;
582 - nfs_versmax = rsa->nfs_versmax;
583 547
548 + ng = zone_getspecific(nfssrv_zone_key, curzone);
549 + ng->nfs_versmin = rsa->nfs_versmin;
550 + ng->nfs_versmax = rsa->nfs_versmax;
551 +
584 552 /* Set the versions in the callout table */
585 553 __nfs_sc_rdma[0].sc_versmin = rsa->nfs_versmin;
586 554 __nfs_sc_rdma[0].sc_versmax = rsa->nfs_versmax;
587 555 /* For the NFS_ACL program, check the max version */
588 556 __nfs_sc_rdma[1].sc_versmin = rsa->nfs_versmin;
589 557 if (rsa->nfs_versmax > NFS_ACL_VERSMAX)
590 558 __nfs_sc_rdma[1].sc_versmax = NFS_ACL_VERSMAX;
591 559 else
592 560 __nfs_sc_rdma[1].sc_versmax = rsa->nfs_versmax;
593 561
594 562 /* Initialize nfsv4 server */
595 563 if (rsa->nfs_versmax == (rpcvers_t)NFS_V4)
596 - rfs4_server_start(rsa->delegation);
564 + rfs4_server_start(ng, rsa->delegation);
597 565
598 566 started_rdma_xprts.rtg_count = 0;
599 567 started_rdma_xprts.rtg_listhead = NULL;
600 568 started_rdma_xprts.rtg_poolid = rsa->poolid;
601 569
602 570 restart:
603 571 error = svc_rdma_kcreate(rsa->netid, &nfs_sct_rdma, rsa->poolid,
604 572 &started_rdma_xprts);
605 573
606 574 svc_state = !error;
607 575
608 576 while (!error) {
609 577
610 578 /*
611 579 * wait till either interrupted by a signal on
612 580 * nfs service stop/restart or signalled by a
613 - * rdma plugin attach/detatch.
581 + * rdma attach/detatch.
614 582 */
615 583
616 584 stat = rdma_kwait();
617 585
618 586 /*
619 587 * stop services if running -- either on a HCA detach event
620 588 * or if the nfs service is stopped/restarted.
621 589 */
622 590
623 591 if ((stat == RDMA_HCA_DETACH || stat == RDMA_INTR) &&
624 592 svc_state) {
625 593 rdma_stop(&started_rdma_xprts);
626 594 svc_state = 0;
627 595 }
628 596
629 597 /*
630 598 * nfs service stop/restart, break out of the
631 599 * wait loop and return;
632 600 */
633 601 if (stat == RDMA_INTR)
634 602 return (0);
635 603
636 604 /*
637 605 * restart stopped services on a HCA attach event
638 606 * (if not already running)
639 607 */
640 608
641 609 if ((stat == RDMA_HCA_ATTACH) && (svc_state == 0))
642 610 goto restart;
643 611
644 612 /*
645 613 * loop until a nfs service stop/restart
646 614 */
647 615 }
648 616
649 617 return (error);
650 618 }
651 619
652 620 /* ARGSUSED */
653 621 void
|
↓ open down ↓ |
30 lines elided |
↑ open up ↑ |
654 622 rpc_null(caddr_t *argp, caddr_t *resp, struct exportinfo *exi,
655 623 struct svc_req *req, cred_t *cr, bool_t ro)
656 624 {
657 625 }
658 626
659 627 /* ARGSUSED */
660 628 void
661 629 rpc_null_v3(caddr_t *argp, caddr_t *resp, struct exportinfo *exi,
662 630 struct svc_req *req, cred_t *cr, bool_t ro)
663 631 {
664 - DTRACE_NFSV3_3(op__null__start, struct svc_req *, req,
665 - cred_t *, cr, vnode_t *, NULL);
666 - DTRACE_NFSV3_3(op__null__done, struct svc_req *, req,
667 - cred_t *, cr, vnode_t *, NULL);
632 + DTRACE_NFSV3_4(op__null__start, struct svc_req *, req,
633 + cred_t *, cr, vnode_t *, NULL, struct exportinfo *, exi);
634 + DTRACE_NFSV3_4(op__null__done, struct svc_req *, req,
635 + cred_t *, cr, vnode_t *, NULL, struct exportinfo *, exi);
668 636 }
669 637
670 638 /* ARGSUSED */
671 639 static void
672 640 rfs_error(caddr_t *argp, caddr_t *resp, struct exportinfo *exi,
673 641 struct svc_req *req, cred_t *cr, bool_t ro)
674 642 {
675 643 /* return (EOPNOTSUPP); */
676 644 }
677 645
678 646 static void
679 647 nullfree(void)
680 648 {
681 649 }
682 650
683 651 static char *rfscallnames_v2[] = {
684 652 "RFS2_NULL",
685 653 "RFS2_GETATTR",
686 654 "RFS2_SETATTR",
687 655 "RFS2_ROOT",
688 656 "RFS2_LOOKUP",
689 657 "RFS2_READLINK",
690 658 "RFS2_READ",
691 659 "RFS2_WRITECACHE",
692 660 "RFS2_WRITE",
693 661 "RFS2_CREATE",
694 662 "RFS2_REMOVE",
695 663 "RFS2_RENAME",
696 664 "RFS2_LINK",
697 665 "RFS2_SYMLINK",
698 666 "RFS2_MKDIR",
699 667 "RFS2_RMDIR",
700 668 "RFS2_READDIR",
701 669 "RFS2_STATFS"
702 670 };
703 671
704 672 static struct rpcdisp rfsdisptab_v2[] = {
705 673 /*
706 674 * NFS VERSION 2
707 675 */
708 676
709 677 /* RFS_NULL = 0 */
710 678 {rpc_null,
711 679 xdr_void, NULL_xdrproc_t, 0,
712 680 xdr_void, NULL_xdrproc_t, 0,
713 681 nullfree, RPC_IDEMPOTENT,
714 682 0},
715 683
716 684 /* RFS_GETATTR = 1 */
717 685 {rfs_getattr,
718 686 xdr_fhandle, xdr_fastfhandle, sizeof (fhandle_t),
719 687 xdr_attrstat, xdr_fastattrstat, sizeof (struct nfsattrstat),
720 688 nullfree, RPC_IDEMPOTENT|RPC_ALLOWANON|RPC_MAPRESP,
721 689 rfs_getattr_getfh},
722 690
723 691 /* RFS_SETATTR = 2 */
724 692 {rfs_setattr,
725 693 xdr_saargs, NULL_xdrproc_t, sizeof (struct nfssaargs),
726 694 xdr_attrstat, xdr_fastattrstat, sizeof (struct nfsattrstat),
727 695 nullfree, RPC_MAPRESP,
728 696 rfs_setattr_getfh},
729 697
730 698 /* RFS_ROOT = 3 *** NO LONGER SUPPORTED *** */
731 699 {rfs_error,
732 700 xdr_void, NULL_xdrproc_t, 0,
733 701 xdr_void, NULL_xdrproc_t, 0,
734 702 nullfree, RPC_IDEMPOTENT,
735 703 0},
736 704
737 705 /* RFS_LOOKUP = 4 */
738 706 {rfs_lookup,
739 707 xdr_diropargs, NULL_xdrproc_t, sizeof (struct nfsdiropargs),
740 708 xdr_diropres, xdr_fastdiropres, sizeof (struct nfsdiropres),
741 709 nullfree, RPC_IDEMPOTENT|RPC_MAPRESP|RPC_PUBLICFH_OK,
742 710 rfs_lookup_getfh},
743 711
744 712 /* RFS_READLINK = 5 */
745 713 {rfs_readlink,
746 714 xdr_fhandle, xdr_fastfhandle, sizeof (fhandle_t),
747 715 xdr_rdlnres, NULL_xdrproc_t, sizeof (struct nfsrdlnres),
748 716 rfs_rlfree, RPC_IDEMPOTENT,
749 717 rfs_readlink_getfh},
750 718
751 719 /* RFS_READ = 6 */
752 720 {rfs_read,
753 721 xdr_readargs, NULL_xdrproc_t, sizeof (struct nfsreadargs),
754 722 xdr_rdresult, NULL_xdrproc_t, sizeof (struct nfsrdresult),
755 723 rfs_rdfree, RPC_IDEMPOTENT,
756 724 rfs_read_getfh},
757 725
758 726 /* RFS_WRITECACHE = 7 *** NO LONGER SUPPORTED *** */
759 727 {rfs_error,
760 728 xdr_void, NULL_xdrproc_t, 0,
761 729 xdr_void, NULL_xdrproc_t, 0,
762 730 nullfree, RPC_IDEMPOTENT,
763 731 0},
764 732
765 733 /* RFS_WRITE = 8 */
766 734 {rfs_write,
767 735 xdr_writeargs, NULL_xdrproc_t, sizeof (struct nfswriteargs),
768 736 xdr_attrstat, xdr_fastattrstat, sizeof (struct nfsattrstat),
769 737 nullfree, RPC_MAPRESP,
770 738 rfs_write_getfh},
771 739
772 740 /* RFS_CREATE = 9 */
773 741 {rfs_create,
774 742 xdr_creatargs, NULL_xdrproc_t, sizeof (struct nfscreatargs),
775 743 xdr_diropres, xdr_fastdiropres, sizeof (struct nfsdiropres),
776 744 nullfree, RPC_MAPRESP,
777 745 rfs_create_getfh},
778 746
779 747 /* RFS_REMOVE = 10 */
780 748 {rfs_remove,
781 749 xdr_diropargs, NULL_xdrproc_t, sizeof (struct nfsdiropargs),
782 750 #ifdef _LITTLE_ENDIAN
783 751 xdr_enum, xdr_fastenum, sizeof (enum nfsstat),
784 752 #else
785 753 xdr_enum, NULL_xdrproc_t, sizeof (enum nfsstat),
786 754 #endif
787 755 nullfree, RPC_MAPRESP,
788 756 rfs_remove_getfh},
789 757
790 758 /* RFS_RENAME = 11 */
791 759 {rfs_rename,
792 760 xdr_rnmargs, NULL_xdrproc_t, sizeof (struct nfsrnmargs),
793 761 #ifdef _LITTLE_ENDIAN
794 762 xdr_enum, xdr_fastenum, sizeof (enum nfsstat),
795 763 #else
796 764 xdr_enum, NULL_xdrproc_t, sizeof (enum nfsstat),
797 765 #endif
798 766 nullfree, RPC_MAPRESP,
799 767 rfs_rename_getfh},
800 768
801 769 /* RFS_LINK = 12 */
802 770 {rfs_link,
803 771 xdr_linkargs, NULL_xdrproc_t, sizeof (struct nfslinkargs),
804 772 #ifdef _LITTLE_ENDIAN
805 773 xdr_enum, xdr_fastenum, sizeof (enum nfsstat),
806 774 #else
807 775 xdr_enum, NULL_xdrproc_t, sizeof (enum nfsstat),
808 776 #endif
809 777 nullfree, RPC_MAPRESP,
810 778 rfs_link_getfh},
811 779
812 780 /* RFS_SYMLINK = 13 */
813 781 {rfs_symlink,
814 782 xdr_slargs, NULL_xdrproc_t, sizeof (struct nfsslargs),
815 783 #ifdef _LITTLE_ENDIAN
816 784 xdr_enum, xdr_fastenum, sizeof (enum nfsstat),
817 785 #else
818 786 xdr_enum, NULL_xdrproc_t, sizeof (enum nfsstat),
819 787 #endif
820 788 nullfree, RPC_MAPRESP,
821 789 rfs_symlink_getfh},
822 790
823 791 /* RFS_MKDIR = 14 */
824 792 {rfs_mkdir,
825 793 xdr_creatargs, NULL_xdrproc_t, sizeof (struct nfscreatargs),
826 794 xdr_diropres, xdr_fastdiropres, sizeof (struct nfsdiropres),
827 795 nullfree, RPC_MAPRESP,
828 796 rfs_mkdir_getfh},
829 797
830 798 /* RFS_RMDIR = 15 */
831 799 {rfs_rmdir,
832 800 xdr_diropargs, NULL_xdrproc_t, sizeof (struct nfsdiropargs),
833 801 #ifdef _LITTLE_ENDIAN
834 802 xdr_enum, xdr_fastenum, sizeof (enum nfsstat),
835 803 #else
836 804 xdr_enum, NULL_xdrproc_t, sizeof (enum nfsstat),
837 805 #endif
838 806 nullfree, RPC_MAPRESP,
839 807 rfs_rmdir_getfh},
840 808
841 809 /* RFS_READDIR = 16 */
842 810 {rfs_readdir,
843 811 xdr_rddirargs, NULL_xdrproc_t, sizeof (struct nfsrddirargs),
844 812 xdr_putrddirres, NULL_xdrproc_t, sizeof (struct nfsrddirres),
845 813 rfs_rddirfree, RPC_IDEMPOTENT,
846 814 rfs_readdir_getfh},
847 815
848 816 /* RFS_STATFS = 17 */
849 817 {rfs_statfs,
850 818 xdr_fhandle, xdr_fastfhandle, sizeof (fhandle_t),
851 819 xdr_statfs, xdr_faststatfs, sizeof (struct nfsstatfs),
852 820 nullfree, RPC_IDEMPOTENT|RPC_ALLOWANON|RPC_MAPRESP,
853 821 rfs_statfs_getfh},
854 822 };
855 823
856 824 static char *rfscallnames_v3[] = {
857 825 "RFS3_NULL",
858 826 "RFS3_GETATTR",
859 827 "RFS3_SETATTR",
860 828 "RFS3_LOOKUP",
861 829 "RFS3_ACCESS",
862 830 "RFS3_READLINK",
863 831 "RFS3_READ",
864 832 "RFS3_WRITE",
865 833 "RFS3_CREATE",
866 834 "RFS3_MKDIR",
867 835 "RFS3_SYMLINK",
868 836 "RFS3_MKNOD",
869 837 "RFS3_REMOVE",
870 838 "RFS3_RMDIR",
871 839 "RFS3_RENAME",
872 840 "RFS3_LINK",
873 841 "RFS3_READDIR",
874 842 "RFS3_READDIRPLUS",
875 843 "RFS3_FSSTAT",
876 844 "RFS3_FSINFO",
877 845 "RFS3_PATHCONF",
878 846 "RFS3_COMMIT"
879 847 };
880 848
881 849 static struct rpcdisp rfsdisptab_v3[] = {
882 850 /*
883 851 * NFS VERSION 3
884 852 */
885 853
886 854 /* RFS_NULL = 0 */
887 855 {rpc_null_v3,
888 856 xdr_void, NULL_xdrproc_t, 0,
889 857 xdr_void, NULL_xdrproc_t, 0,
890 858 nullfree, RPC_IDEMPOTENT,
891 859 0},
892 860
893 861 /* RFS3_GETATTR = 1 */
894 862 {rfs3_getattr,
895 863 xdr_nfs_fh3_server, NULL_xdrproc_t, sizeof (GETATTR3args),
896 864 xdr_GETATTR3res, NULL_xdrproc_t, sizeof (GETATTR3res),
897 865 nullfree, (RPC_IDEMPOTENT | RPC_ALLOWANON),
898 866 rfs3_getattr_getfh},
899 867
900 868 /* RFS3_SETATTR = 2 */
901 869 {rfs3_setattr,
902 870 xdr_SETATTR3args, NULL_xdrproc_t, sizeof (SETATTR3args),
903 871 xdr_SETATTR3res, NULL_xdrproc_t, sizeof (SETATTR3res),
904 872 nullfree, 0,
905 873 rfs3_setattr_getfh},
906 874
907 875 /* RFS3_LOOKUP = 3 */
908 876 {rfs3_lookup,
909 877 xdr_diropargs3, NULL_xdrproc_t, sizeof (LOOKUP3args),
910 878 xdr_LOOKUP3res, NULL_xdrproc_t, sizeof (LOOKUP3res),
911 879 nullfree, (RPC_IDEMPOTENT | RPC_PUBLICFH_OK),
912 880 rfs3_lookup_getfh},
913 881
914 882 /* RFS3_ACCESS = 4 */
915 883 {rfs3_access,
916 884 xdr_ACCESS3args, NULL_xdrproc_t, sizeof (ACCESS3args),
917 885 xdr_ACCESS3res, NULL_xdrproc_t, sizeof (ACCESS3res),
918 886 nullfree, RPC_IDEMPOTENT,
919 887 rfs3_access_getfh},
920 888
921 889 /* RFS3_READLINK = 5 */
922 890 {rfs3_readlink,
923 891 xdr_nfs_fh3_server, NULL_xdrproc_t, sizeof (READLINK3args),
924 892 xdr_READLINK3res, NULL_xdrproc_t, sizeof (READLINK3res),
925 893 rfs3_readlink_free, RPC_IDEMPOTENT,
926 894 rfs3_readlink_getfh},
927 895
928 896 /* RFS3_READ = 6 */
929 897 {rfs3_read,
930 898 xdr_READ3args, NULL_xdrproc_t, sizeof (READ3args),
931 899 xdr_READ3res, NULL_xdrproc_t, sizeof (READ3res),
932 900 rfs3_read_free, RPC_IDEMPOTENT,
933 901 rfs3_read_getfh},
934 902
935 903 /* RFS3_WRITE = 7 */
936 904 {rfs3_write,
937 905 xdr_WRITE3args, NULL_xdrproc_t, sizeof (WRITE3args),
938 906 xdr_WRITE3res, NULL_xdrproc_t, sizeof (WRITE3res),
939 907 nullfree, 0,
940 908 rfs3_write_getfh},
941 909
942 910 /* RFS3_CREATE = 8 */
943 911 {rfs3_create,
944 912 xdr_CREATE3args, NULL_xdrproc_t, sizeof (CREATE3args),
945 913 xdr_CREATE3res, NULL_xdrproc_t, sizeof (CREATE3res),
946 914 nullfree, 0,
947 915 rfs3_create_getfh},
948 916
949 917 /* RFS3_MKDIR = 9 */
950 918 {rfs3_mkdir,
951 919 xdr_MKDIR3args, NULL_xdrproc_t, sizeof (MKDIR3args),
952 920 xdr_MKDIR3res, NULL_xdrproc_t, sizeof (MKDIR3res),
953 921 nullfree, 0,
954 922 rfs3_mkdir_getfh},
955 923
956 924 /* RFS3_SYMLINK = 10 */
957 925 {rfs3_symlink,
958 926 xdr_SYMLINK3args, NULL_xdrproc_t, sizeof (SYMLINK3args),
959 927 xdr_SYMLINK3res, NULL_xdrproc_t, sizeof (SYMLINK3res),
960 928 nullfree, 0,
961 929 rfs3_symlink_getfh},
962 930
963 931 /* RFS3_MKNOD = 11 */
964 932 {rfs3_mknod,
965 933 xdr_MKNOD3args, NULL_xdrproc_t, sizeof (MKNOD3args),
966 934 xdr_MKNOD3res, NULL_xdrproc_t, sizeof (MKNOD3res),
967 935 nullfree, 0,
968 936 rfs3_mknod_getfh},
969 937
970 938 /* RFS3_REMOVE = 12 */
971 939 {rfs3_remove,
972 940 xdr_diropargs3, NULL_xdrproc_t, sizeof (REMOVE3args),
973 941 xdr_REMOVE3res, NULL_xdrproc_t, sizeof (REMOVE3res),
974 942 nullfree, 0,
975 943 rfs3_remove_getfh},
976 944
977 945 /* RFS3_RMDIR = 13 */
978 946 {rfs3_rmdir,
979 947 xdr_diropargs3, NULL_xdrproc_t, sizeof (RMDIR3args),
980 948 xdr_RMDIR3res, NULL_xdrproc_t, sizeof (RMDIR3res),
981 949 nullfree, 0,
982 950 rfs3_rmdir_getfh},
983 951
984 952 /* RFS3_RENAME = 14 */
985 953 {rfs3_rename,
986 954 xdr_RENAME3args, NULL_xdrproc_t, sizeof (RENAME3args),
987 955 xdr_RENAME3res, NULL_xdrproc_t, sizeof (RENAME3res),
988 956 nullfree, 0,
989 957 rfs3_rename_getfh},
990 958
991 959 /* RFS3_LINK = 15 */
992 960 {rfs3_link,
993 961 xdr_LINK3args, NULL_xdrproc_t, sizeof (LINK3args),
994 962 xdr_LINK3res, NULL_xdrproc_t, sizeof (LINK3res),
995 963 nullfree, 0,
996 964 rfs3_link_getfh},
997 965
998 966 /* RFS3_READDIR = 16 */
999 967 {rfs3_readdir,
1000 968 xdr_READDIR3args, NULL_xdrproc_t, sizeof (READDIR3args),
1001 969 xdr_READDIR3res, NULL_xdrproc_t, sizeof (READDIR3res),
1002 970 rfs3_readdir_free, RPC_IDEMPOTENT,
1003 971 rfs3_readdir_getfh},
1004 972
1005 973 /* RFS3_READDIRPLUS = 17 */
1006 974 {rfs3_readdirplus,
1007 975 xdr_READDIRPLUS3args, NULL_xdrproc_t, sizeof (READDIRPLUS3args),
1008 976 xdr_READDIRPLUS3res, NULL_xdrproc_t, sizeof (READDIRPLUS3res),
1009 977 rfs3_readdirplus_free, RPC_AVOIDWORK,
1010 978 rfs3_readdirplus_getfh},
1011 979
1012 980 /* RFS3_FSSTAT = 18 */
1013 981 {rfs3_fsstat,
1014 982 xdr_nfs_fh3_server, NULL_xdrproc_t, sizeof (FSSTAT3args),
1015 983 xdr_FSSTAT3res, NULL_xdrproc_t, sizeof (FSSTAT3res),
1016 984 nullfree, RPC_IDEMPOTENT,
1017 985 rfs3_fsstat_getfh},
1018 986
1019 987 /* RFS3_FSINFO = 19 */
1020 988 {rfs3_fsinfo,
1021 989 xdr_nfs_fh3_server, NULL_xdrproc_t, sizeof (FSINFO3args),
1022 990 xdr_FSINFO3res, NULL_xdrproc_t, sizeof (FSINFO3res),
1023 991 nullfree, RPC_IDEMPOTENT|RPC_ALLOWANON,
1024 992 rfs3_fsinfo_getfh},
1025 993
1026 994 /* RFS3_PATHCONF = 20 */
1027 995 {rfs3_pathconf,
1028 996 xdr_nfs_fh3_server, NULL_xdrproc_t, sizeof (PATHCONF3args),
1029 997 xdr_PATHCONF3res, NULL_xdrproc_t, sizeof (PATHCONF3res),
1030 998 nullfree, RPC_IDEMPOTENT,
1031 999 rfs3_pathconf_getfh},
1032 1000
1033 1001 /* RFS3_COMMIT = 21 */
1034 1002 {rfs3_commit,
1035 1003 xdr_COMMIT3args, NULL_xdrproc_t, sizeof (COMMIT3args),
1036 1004 xdr_COMMIT3res, NULL_xdrproc_t, sizeof (COMMIT3res),
1037 1005 nullfree, RPC_IDEMPOTENT,
1038 1006 rfs3_commit_getfh},
1039 1007 };
1040 1008
1041 1009 static char *rfscallnames_v4[] = {
1042 1010 "RFS4_NULL",
1043 1011 "RFS4_COMPOUND",
1044 1012 "RFS4_NULL",
1045 1013 "RFS4_NULL",
1046 1014 "RFS4_NULL",
1047 1015 "RFS4_NULL",
1048 1016 "RFS4_NULL",
1049 1017 "RFS4_NULL",
1050 1018 "RFS4_CREATE"
1051 1019 };
1052 1020
1053 1021 static struct rpcdisp rfsdisptab_v4[] = {
1054 1022 /*
1055 1023 * NFS VERSION 4
1056 1024 */
1057 1025
1058 1026 /* RFS_NULL = 0 */
1059 1027 {rpc_null,
1060 1028 xdr_void, NULL_xdrproc_t, 0,
1061 1029 xdr_void, NULL_xdrproc_t, 0,
1062 1030 nullfree, RPC_IDEMPOTENT, 0},
1063 1031
1064 1032 /* RFS4_compound = 1 */
1065 1033 {rfs4_compound,
1066 1034 xdr_COMPOUND4args_srv, NULL_xdrproc_t, sizeof (COMPOUND4args),
1067 1035 xdr_COMPOUND4res_srv, NULL_xdrproc_t, sizeof (COMPOUND4res),
1068 1036 rfs4_compound_free, 0, 0},
1069 1037 };
1070 1038
1071 1039 union rfs_args {
1072 1040 /*
1073 1041 * NFS VERSION 2
1074 1042 */
1075 1043
1076 1044 /* RFS_NULL = 0 */
1077 1045
1078 1046 /* RFS_GETATTR = 1 */
1079 1047 fhandle_t nfs2_getattr_args;
1080 1048
1081 1049 /* RFS_SETATTR = 2 */
1082 1050 struct nfssaargs nfs2_setattr_args;
1083 1051
1084 1052 /* RFS_ROOT = 3 *** NO LONGER SUPPORTED *** */
1085 1053
1086 1054 /* RFS_LOOKUP = 4 */
1087 1055 struct nfsdiropargs nfs2_lookup_args;
1088 1056
1089 1057 /* RFS_READLINK = 5 */
1090 1058 fhandle_t nfs2_readlink_args;
1091 1059
1092 1060 /* RFS_READ = 6 */
1093 1061 struct nfsreadargs nfs2_read_args;
1094 1062
1095 1063 /* RFS_WRITECACHE = 7 *** NO LONGER SUPPORTED *** */
1096 1064
1097 1065 /* RFS_WRITE = 8 */
1098 1066 struct nfswriteargs nfs2_write_args;
1099 1067
1100 1068 /* RFS_CREATE = 9 */
1101 1069 struct nfscreatargs nfs2_create_args;
1102 1070
1103 1071 /* RFS_REMOVE = 10 */
1104 1072 struct nfsdiropargs nfs2_remove_args;
1105 1073
1106 1074 /* RFS_RENAME = 11 */
1107 1075 struct nfsrnmargs nfs2_rename_args;
1108 1076
1109 1077 /* RFS_LINK = 12 */
1110 1078 struct nfslinkargs nfs2_link_args;
1111 1079
1112 1080 /* RFS_SYMLINK = 13 */
1113 1081 struct nfsslargs nfs2_symlink_args;
1114 1082
1115 1083 /* RFS_MKDIR = 14 */
1116 1084 struct nfscreatargs nfs2_mkdir_args;
1117 1085
1118 1086 /* RFS_RMDIR = 15 */
1119 1087 struct nfsdiropargs nfs2_rmdir_args;
1120 1088
1121 1089 /* RFS_READDIR = 16 */
1122 1090 struct nfsrddirargs nfs2_readdir_args;
1123 1091
1124 1092 /* RFS_STATFS = 17 */
1125 1093 fhandle_t nfs2_statfs_args;
1126 1094
1127 1095 /*
1128 1096 * NFS VERSION 3
1129 1097 */
1130 1098
1131 1099 /* RFS_NULL = 0 */
1132 1100
1133 1101 /* RFS3_GETATTR = 1 */
1134 1102 GETATTR3args nfs3_getattr_args;
1135 1103
1136 1104 /* RFS3_SETATTR = 2 */
1137 1105 SETATTR3args nfs3_setattr_args;
1138 1106
1139 1107 /* RFS3_LOOKUP = 3 */
1140 1108 LOOKUP3args nfs3_lookup_args;
1141 1109
1142 1110 /* RFS3_ACCESS = 4 */
1143 1111 ACCESS3args nfs3_access_args;
1144 1112
1145 1113 /* RFS3_READLINK = 5 */
1146 1114 READLINK3args nfs3_readlink_args;
1147 1115
1148 1116 /* RFS3_READ = 6 */
1149 1117 READ3args nfs3_read_args;
1150 1118
1151 1119 /* RFS3_WRITE = 7 */
1152 1120 WRITE3args nfs3_write_args;
1153 1121
1154 1122 /* RFS3_CREATE = 8 */
1155 1123 CREATE3args nfs3_create_args;
1156 1124
1157 1125 /* RFS3_MKDIR = 9 */
1158 1126 MKDIR3args nfs3_mkdir_args;
1159 1127
1160 1128 /* RFS3_SYMLINK = 10 */
1161 1129 SYMLINK3args nfs3_symlink_args;
1162 1130
1163 1131 /* RFS3_MKNOD = 11 */
1164 1132 MKNOD3args nfs3_mknod_args;
1165 1133
1166 1134 /* RFS3_REMOVE = 12 */
1167 1135 REMOVE3args nfs3_remove_args;
1168 1136
1169 1137 /* RFS3_RMDIR = 13 */
1170 1138 RMDIR3args nfs3_rmdir_args;
1171 1139
1172 1140 /* RFS3_RENAME = 14 */
1173 1141 RENAME3args nfs3_rename_args;
1174 1142
1175 1143 /* RFS3_LINK = 15 */
1176 1144 LINK3args nfs3_link_args;
1177 1145
1178 1146 /* RFS3_READDIR = 16 */
1179 1147 READDIR3args nfs3_readdir_args;
1180 1148
1181 1149 /* RFS3_READDIRPLUS = 17 */
1182 1150 READDIRPLUS3args nfs3_readdirplus_args;
1183 1151
1184 1152 /* RFS3_FSSTAT = 18 */
1185 1153 FSSTAT3args nfs3_fsstat_args;
1186 1154
1187 1155 /* RFS3_FSINFO = 19 */
1188 1156 FSINFO3args nfs3_fsinfo_args;
1189 1157
1190 1158 /* RFS3_PATHCONF = 20 */
1191 1159 PATHCONF3args nfs3_pathconf_args;
1192 1160
1193 1161 /* RFS3_COMMIT = 21 */
1194 1162 COMMIT3args nfs3_commit_args;
1195 1163
1196 1164 /*
1197 1165 * NFS VERSION 4
1198 1166 */
1199 1167
1200 1168 /* RFS_NULL = 0 */
1201 1169
1202 1170 /* COMPUND = 1 */
1203 1171 COMPOUND4args nfs4_compound_args;
1204 1172 };
1205 1173
1206 1174 union rfs_res {
1207 1175 /*
1208 1176 * NFS VERSION 2
1209 1177 */
1210 1178
1211 1179 /* RFS_NULL = 0 */
1212 1180
1213 1181 /* RFS_GETATTR = 1 */
1214 1182 struct nfsattrstat nfs2_getattr_res;
1215 1183
1216 1184 /* RFS_SETATTR = 2 */
1217 1185 struct nfsattrstat nfs2_setattr_res;
1218 1186
1219 1187 /* RFS_ROOT = 3 *** NO LONGER SUPPORTED *** */
1220 1188
1221 1189 /* RFS_LOOKUP = 4 */
1222 1190 struct nfsdiropres nfs2_lookup_res;
1223 1191
1224 1192 /* RFS_READLINK = 5 */
1225 1193 struct nfsrdlnres nfs2_readlink_res;
1226 1194
1227 1195 /* RFS_READ = 6 */
1228 1196 struct nfsrdresult nfs2_read_res;
1229 1197
1230 1198 /* RFS_WRITECACHE = 7 *** NO LONGER SUPPORTED *** */
1231 1199
1232 1200 /* RFS_WRITE = 8 */
1233 1201 struct nfsattrstat nfs2_write_res;
1234 1202
1235 1203 /* RFS_CREATE = 9 */
1236 1204 struct nfsdiropres nfs2_create_res;
1237 1205
1238 1206 /* RFS_REMOVE = 10 */
1239 1207 enum nfsstat nfs2_remove_res;
1240 1208
1241 1209 /* RFS_RENAME = 11 */
1242 1210 enum nfsstat nfs2_rename_res;
1243 1211
1244 1212 /* RFS_LINK = 12 */
1245 1213 enum nfsstat nfs2_link_res;
1246 1214
1247 1215 /* RFS_SYMLINK = 13 */
1248 1216 enum nfsstat nfs2_symlink_res;
1249 1217
1250 1218 /* RFS_MKDIR = 14 */
1251 1219 struct nfsdiropres nfs2_mkdir_res;
1252 1220
1253 1221 /* RFS_RMDIR = 15 */
1254 1222 enum nfsstat nfs2_rmdir_res;
1255 1223
1256 1224 /* RFS_READDIR = 16 */
1257 1225 struct nfsrddirres nfs2_readdir_res;
1258 1226
1259 1227 /* RFS_STATFS = 17 */
1260 1228 struct nfsstatfs nfs2_statfs_res;
1261 1229
1262 1230 /*
1263 1231 * NFS VERSION 3
1264 1232 */
1265 1233
1266 1234 /* RFS_NULL = 0 */
1267 1235
1268 1236 /* RFS3_GETATTR = 1 */
1269 1237 GETATTR3res nfs3_getattr_res;
1270 1238
1271 1239 /* RFS3_SETATTR = 2 */
1272 1240 SETATTR3res nfs3_setattr_res;
1273 1241
1274 1242 /* RFS3_LOOKUP = 3 */
1275 1243 LOOKUP3res nfs3_lookup_res;
1276 1244
1277 1245 /* RFS3_ACCESS = 4 */
1278 1246 ACCESS3res nfs3_access_res;
1279 1247
1280 1248 /* RFS3_READLINK = 5 */
1281 1249 READLINK3res nfs3_readlink_res;
1282 1250
1283 1251 /* RFS3_READ = 6 */
1284 1252 READ3res nfs3_read_res;
1285 1253
1286 1254 /* RFS3_WRITE = 7 */
1287 1255 WRITE3res nfs3_write_res;
1288 1256
1289 1257 /* RFS3_CREATE = 8 */
1290 1258 CREATE3res nfs3_create_res;
1291 1259
1292 1260 /* RFS3_MKDIR = 9 */
1293 1261 MKDIR3res nfs3_mkdir_res;
1294 1262
1295 1263 /* RFS3_SYMLINK = 10 */
1296 1264 SYMLINK3res nfs3_symlink_res;
1297 1265
1298 1266 /* RFS3_MKNOD = 11 */
1299 1267 MKNOD3res nfs3_mknod_res;
1300 1268
1301 1269 /* RFS3_REMOVE = 12 */
1302 1270 REMOVE3res nfs3_remove_res;
1303 1271
1304 1272 /* RFS3_RMDIR = 13 */
1305 1273 RMDIR3res nfs3_rmdir_res;
1306 1274
1307 1275 /* RFS3_RENAME = 14 */
1308 1276 RENAME3res nfs3_rename_res;
1309 1277
1310 1278 /* RFS3_LINK = 15 */
1311 1279 LINK3res nfs3_link_res;
1312 1280
1313 1281 /* RFS3_READDIR = 16 */
1314 1282 READDIR3res nfs3_readdir_res;
1315 1283
1316 1284 /* RFS3_READDIRPLUS = 17 */
1317 1285 READDIRPLUS3res nfs3_readdirplus_res;
1318 1286
1319 1287 /* RFS3_FSSTAT = 18 */
1320 1288 FSSTAT3res nfs3_fsstat_res;
1321 1289
1322 1290 /* RFS3_FSINFO = 19 */
1323 1291 FSINFO3res nfs3_fsinfo_res;
1324 1292
1325 1293 /* RFS3_PATHCONF = 20 */
1326 1294 PATHCONF3res nfs3_pathconf_res;
1327 1295
1328 1296 /* RFS3_COMMIT = 21 */
1329 1297 COMMIT3res nfs3_commit_res;
1330 1298
1331 1299 /*
1332 1300 * NFS VERSION 4
1333 1301 */
1334 1302
|
↓ open down ↓ |
657 lines elided |
↑ open up ↑ |
1335 1303 /* RFS_NULL = 0 */
1336 1304
1337 1305 /* RFS4_COMPOUND = 1 */
1338 1306 COMPOUND4res nfs4_compound_res;
1339 1307
1340 1308 };
1341 1309
1342 1310 static struct rpc_disptable rfs_disptable[] = {
1343 1311 {sizeof (rfsdisptab_v2) / sizeof (rfsdisptab_v2[0]),
1344 1312 rfscallnames_v2,
1345 - &rfsproccnt_v2_ptr, rfsdisptab_v2},
1313 + &rfsproccnt_v2_ptr, &rfsprocio_v2_ptr, rfsdisptab_v2},
1346 1314 {sizeof (rfsdisptab_v3) / sizeof (rfsdisptab_v3[0]),
1347 1315 rfscallnames_v3,
1348 - &rfsproccnt_v3_ptr, rfsdisptab_v3},
1316 + &rfsproccnt_v3_ptr, &rfsprocio_v3_ptr, rfsdisptab_v3},
1349 1317 {sizeof (rfsdisptab_v4) / sizeof (rfsdisptab_v4[0]),
1350 1318 rfscallnames_v4,
1351 - &rfsproccnt_v4_ptr, rfsdisptab_v4},
1319 + &rfsproccnt_v4_ptr, &rfsprocio_v4_ptr, rfsdisptab_v4},
1352 1320 };
1353 1321
1354 1322 /*
1355 1323 * If nfs_portmon is set, then clients are required to use privileged
1356 1324 * ports (ports < IPPORT_RESERVED) in order to get NFS services.
1357 1325 *
1358 1326 * N.B.: this attempt to carry forward the already ill-conceived notion
1359 1327 * of privileged ports for TCP/UDP is really quite ineffectual. Not only
1360 1328 * is it transport-dependent, it's laughably easy to spoof. If you're
1361 1329 * really interested in security, you must start with secure RPC instead.
1362 1330 */
1363 -static int nfs_portmon = 0;
1331 +volatile int nfs_portmon = 0;
1364 1332
1365 1333 #ifdef DEBUG
1366 1334 static int cred_hits = 0;
1367 1335 static int cred_misses = 0;
1368 1336 #endif
1369 1337
1370 -
1371 1338 #ifdef DEBUG
1372 1339 /*
1373 1340 * Debug code to allow disabling of rfs_dispatch() use of
1374 1341 * fastxdrargs() and fastxdrres() calls for testing purposes.
1375 1342 */
1376 1343 static int rfs_no_fast_xdrargs = 0;
1377 1344 static int rfs_no_fast_xdrres = 0;
1378 1345 #endif
1379 1346
1380 1347 union acl_args {
1381 1348 /*
1382 1349 * ACL VERSION 2
1383 1350 */
1384 1351
1385 1352 /* ACL2_NULL = 0 */
1386 1353
1387 1354 /* ACL2_GETACL = 1 */
1388 1355 GETACL2args acl2_getacl_args;
1389 1356
1390 1357 /* ACL2_SETACL = 2 */
1391 1358 SETACL2args acl2_setacl_args;
1392 1359
1393 1360 /* ACL2_GETATTR = 3 */
1394 1361 GETATTR2args acl2_getattr_args;
1395 1362
1396 1363 /* ACL2_ACCESS = 4 */
1397 1364 ACCESS2args acl2_access_args;
1398 1365
1399 1366 /* ACL2_GETXATTRDIR = 5 */
1400 1367 GETXATTRDIR2args acl2_getxattrdir_args;
1401 1368
1402 1369 /*
1403 1370 * ACL VERSION 3
1404 1371 */
1405 1372
1406 1373 /* ACL3_NULL = 0 */
1407 1374
1408 1375 /* ACL3_GETACL = 1 */
1409 1376 GETACL3args acl3_getacl_args;
1410 1377
1411 1378 /* ACL3_SETACL = 2 */
1412 1379 SETACL3args acl3_setacl;
1413 1380
1414 1381 /* ACL3_GETXATTRDIR = 3 */
1415 1382 GETXATTRDIR3args acl3_getxattrdir_args;
1416 1383
1417 1384 };
1418 1385
1419 1386 union acl_res {
1420 1387 /*
1421 1388 * ACL VERSION 2
1422 1389 */
1423 1390
1424 1391 /* ACL2_NULL = 0 */
1425 1392
1426 1393 /* ACL2_GETACL = 1 */
1427 1394 GETACL2res acl2_getacl_res;
1428 1395
1429 1396 /* ACL2_SETACL = 2 */
1430 1397 SETACL2res acl2_setacl_res;
1431 1398
1432 1399 /* ACL2_GETATTR = 3 */
1433 1400 GETATTR2res acl2_getattr_res;
1434 1401
1435 1402 /* ACL2_ACCESS = 4 */
1436 1403 ACCESS2res acl2_access_res;
1437 1404
1438 1405 /* ACL2_GETXATTRDIR = 5 */
1439 1406 GETXATTRDIR2args acl2_getxattrdir_res;
1440 1407
1441 1408 /*
1442 1409 * ACL VERSION 3
1443 1410 */
1444 1411
1445 1412 /* ACL3_NULL = 0 */
1446 1413
1447 1414 /* ACL3_GETACL = 1 */
1448 1415 GETACL3res acl3_getacl_res;
1449 1416
1450 1417 /* ACL3_SETACL = 2 */
1451 1418 SETACL3res acl3_setacl_res;
1452 1419
1453 1420 /* ACL3_GETXATTRDIR = 3 */
1454 1421 GETXATTRDIR3res acl3_getxattrdir_res;
1455 1422
1456 1423 };
1457 1424
1458 1425 static bool_t
1459 1426 auth_tooweak(struct svc_req *req, char *res)
1460 1427 {
1461 1428
1462 1429 if (req->rq_vers == NFS_VERSION && req->rq_proc == RFS_LOOKUP) {
1463 1430 struct nfsdiropres *dr = (struct nfsdiropres *)res;
1464 1431 if ((enum wnfsstat)dr->dr_status == WNFSERR_CLNT_FLAVOR)
1465 1432 return (TRUE);
1466 1433 } else if (req->rq_vers == NFS_V3 && req->rq_proc == NFSPROC3_LOOKUP) {
|
↓ open down ↓ |
86 lines elided |
↑ open up ↑ |
1467 1434 LOOKUP3res *resp = (LOOKUP3res *)res;
1468 1435 if ((enum wnfsstat)resp->status == WNFSERR_CLNT_FLAVOR)
1469 1436 return (TRUE);
1470 1437 }
1471 1438 return (FALSE);
1472 1439 }
1473 1440
1474 1441
1475 1442 static void
1476 1443 common_dispatch(struct svc_req *req, SVCXPRT *xprt, rpcvers_t min_vers,
1477 - rpcvers_t max_vers, char *pgmname,
1478 - struct rpc_disptable *disptable)
1444 + rpcvers_t max_vers, char *pgmname, struct rpc_disptable *disptable)
1479 1445 {
1480 1446 int which;
1481 1447 rpcvers_t vers;
1482 1448 char *args;
1483 1449 union {
1484 1450 union rfs_args ra;
1485 1451 union acl_args aa;
1486 1452 } args_buf;
1487 1453 char *res;
1488 1454 union {
1489 1455 union rfs_res rr;
1490 1456 union acl_res ar;
1491 1457 } res_buf;
1492 1458 struct rpcdisp *disp = NULL;
1493 1459 int dis_flags = 0;
1494 1460 cred_t *cr;
1495 1461 int error = 0;
1496 1462 int anon_ok;
1497 1463 struct exportinfo *exi = NULL;
1498 1464 unsigned int nfslog_rec_id;
1499 1465 int dupstat;
1500 1466 struct dupreq *dr;
|
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
1501 1467 int authres;
1502 1468 bool_t publicfh_ok = FALSE;
1503 1469 enum_t auth_flavor;
1504 1470 bool_t dupcached = FALSE;
1505 1471 struct netbuf nb;
1506 1472 bool_t logging_enabled = FALSE;
1507 1473 struct exportinfo *nfslog_exi = NULL;
1508 1474 char **procnames;
1509 1475 char cbuf[INET6_ADDRSTRLEN]; /* to hold both IPv4 and IPv6 addr */
1510 1476 bool_t ro = FALSE;
1477 + kstat_t *ksp = NULL;
1478 + kstat_t *exi_ksp = NULL;
1479 + size_t pos; /* request size */
1480 + size_t rlen; /* reply size */
1481 + bool_t rsent = FALSE; /* reply was sent successfully */
1482 + nfs_export_t *ne = nfs_get_export();
1511 1483
1512 1484 vers = req->rq_vers;
1513 1485
1514 1486 if (vers < min_vers || vers > max_vers) {
1515 1487 svcerr_progvers(req->rq_xprt, min_vers, max_vers);
1516 1488 error++;
1517 1489 cmn_err(CE_NOTE, "%s: bad version number %u", pgmname, vers);
1518 1490 goto done;
1519 1491 }
1520 1492 vers -= min_vers;
1521 1493
1522 1494 which = req->rq_proc;
1523 1495 if (which < 0 || which >= disptable[(int)vers].dis_nprocs) {
1524 1496 svcerr_noproc(req->rq_xprt);
1525 1497 error++;
1526 1498 goto done;
1527 1499 }
1528 1500
1529 1501 (*(disptable[(int)vers].dis_proccntp))[which].value.ui64++;
1530 1502
1503 + ksp = (*(disptable[(int)vers].dis_prociop))[which];
1504 + if (ksp != NULL) {
1505 + mutex_enter(ksp->ks_lock);
1506 + kstat_runq_enter(KSTAT_IO_PTR(ksp));
1507 + mutex_exit(ksp->ks_lock);
1508 + }
1509 + pos = XDR_GETPOS(&xprt->xp_xdrin);
1510 +
1531 1511 disp = &disptable[(int)vers].dis_table[which];
1532 1512 procnames = disptable[(int)vers].dis_procnames;
1533 1513
1534 1514 auth_flavor = req->rq_cred.oa_flavor;
1535 1515
1536 1516 /*
1537 1517 * Deserialize into the args struct.
1538 1518 */
1539 1519 args = (char *)&args_buf;
1540 1520
1541 1521 #ifdef DEBUG
1542 1522 if (rfs_no_fast_xdrargs || (auth_flavor == RPCSEC_GSS) ||
1543 1523 disp->dis_fastxdrargs == NULL_xdrproc_t ||
1544 1524 !SVC_GETARGS(xprt, disp->dis_fastxdrargs, (char *)&args))
1545 1525 #else
1546 1526 if ((auth_flavor == RPCSEC_GSS) ||
1547 1527 disp->dis_fastxdrargs == NULL_xdrproc_t ||
1548 1528 !SVC_GETARGS(xprt, disp->dis_fastxdrargs, (char *)&args))
1549 1529 #endif
1550 1530 {
1551 1531 bzero(args, disp->dis_argsz);
1552 1532 if (!SVC_GETARGS(xprt, disp->dis_xdrargs, args)) {
1553 1533 error++;
1554 1534 /*
1555 1535 * Check if we are outside our capabilities.
1556 1536 */
1557 1537 if (rfs4_minorvers_mismatch(req, xprt, (void *)args))
1558 1538 goto done;
1559 1539
1560 1540 svcerr_decode(xprt);
1561 1541 cmn_err(CE_NOTE,
1562 1542 "Failed to decode arguments for %s version %u "
1563 1543 "procedure %s client %s%s",
|
↓ open down ↓ |
23 lines elided |
↑ open up ↑ |
1564 1544 pgmname, vers + min_vers, procnames[which],
1565 1545 client_name(req), client_addr(req, cbuf));
1566 1546 goto done;
1567 1547 }
1568 1548 }
1569 1549
1570 1550 /*
1571 1551 * If Version 4 use that specific dispatch function.
1572 1552 */
1573 1553 if (req->rq_vers == 4) {
1574 - error += rfs4_dispatch(disp, req, xprt, args);
1554 + error += rfs4_dispatch(disp, req, xprt, args, &rlen);
1555 + if (error == 0)
1556 + rsent = TRUE;
1575 1557 goto done;
1576 1558 }
1577 1559
1578 1560 dis_flags = disp->dis_flags;
1579 1561
1580 1562 /*
1581 1563 * Find export information and check authentication,
1582 1564 * setting the credential if everything is ok.
1583 1565 */
1584 1566 if (disp->dis_getfh != NULL) {
1585 1567 void *fh;
1586 1568 fsid_t *fsid;
1587 1569 fid_t *fid, *xfid;
1588 1570 fhandle_t *fh2;
1589 1571 nfs_fh3 *fh3;
1590 1572
1591 1573 fh = (*disp->dis_getfh)(args);
1592 1574 switch (req->rq_vers) {
1593 1575 case NFS_VERSION:
1594 1576 fh2 = (fhandle_t *)fh;
1595 1577 fsid = &fh2->fh_fsid;
1596 1578 fid = (fid_t *)&fh2->fh_len;
1597 1579 xfid = (fid_t *)&fh2->fh_xlen;
1598 1580 break;
1599 1581 case NFS_V3:
1600 1582 fh3 = (nfs_fh3 *)fh;
1601 1583 fsid = &fh3->fh3_fsid;
1602 1584 fid = FH3TOFIDP(fh3);
1603 1585 xfid = FH3TOXFIDP(fh3);
1604 1586 break;
1605 1587 }
1606 1588
1607 1589 /*
1608 1590 * Fix for bug 1038302 - corbin
1609 1591 * There is a problem here if anonymous access is
1610 1592 * disallowed. If the current request is part of the
1611 1593 * client's mount process for the requested filesystem,
1612 1594 * then it will carry root (uid 0) credentials on it, and
1613 1595 * will be denied by checkauth if that client does not
1614 1596 * have explicit root=0 permission. This will cause the
1615 1597 * client's mount operation to fail. As a work-around,
1616 1598 * we check here to see if the request is a getattr or
1617 1599 * statfs operation on the exported vnode itself, and
1618 1600 * pass a flag to checkauth with the result of this test.
1619 1601 *
1620 1602 * The filehandle refers to the mountpoint itself if
1621 1603 * the fh_data and fh_xdata portions of the filehandle
1622 1604 * are equal.
1623 1605 *
1624 1606 * Added anon_ok argument to checkauth().
|
↓ open down ↓ |
40 lines elided |
↑ open up ↑ |
1625 1607 */
1626 1608
1627 1609 if ((dis_flags & RPC_ALLOWANON) && EQFID(fid, xfid))
1628 1610 anon_ok = 1;
1629 1611 else
1630 1612 anon_ok = 0;
1631 1613
1632 1614 cr = xprt->xp_cred;
1633 1615 ASSERT(cr != NULL);
1634 1616 #ifdef DEBUG
1635 - if (crgetref(cr) != 1) {
1636 - crfree(cr);
1637 - cr = crget();
1638 - xprt->xp_cred = cr;
1639 - cred_misses++;
1640 - } else
1641 - cred_hits++;
1617 + {
1618 + if (crgetref(cr) != 1) {
1619 + crfree(cr);
1620 + cr = crget();
1621 + xprt->xp_cred = cr;
1622 + cred_misses++;
1623 + } else
1624 + cred_hits++;
1625 + }
1642 1626 #else
1643 1627 if (crgetref(cr) != 1) {
1644 1628 crfree(cr);
1645 1629 cr = crget();
1646 1630 xprt->xp_cred = cr;
1647 1631 }
1648 1632 #endif
1649 1633
1650 1634 exi = checkexport(fsid, xfid);
1651 1635
1652 1636 if (exi != NULL) {
1653 - publicfh_ok = PUBLICFH_CHECK(disp, exi, fsid, xfid);
1637 + rw_enter(&ne->exported_lock, RW_READER);
1638 + exi_ksp = NULL;
1654 1639
1640 + if (exi->exi_kstats != NULL) {
1641 + switch (req->rq_vers) {
1642 + case NFS_VERSION:
1643 + exi_ksp = exp_kstats_v2(exi->exi_kstats,
1644 + which);
1645 + break;
1646 + case NFS_V3:
1647 + exi_ksp = exp_kstats_v3(exi->exi_kstats,
1648 + which);
1649 + break;
1650 + default:
1651 + ASSERT(0);
1652 + break;
1653 + }
1654 + }
1655 +
1656 + if (exi_ksp != NULL) {
1657 + mutex_enter(exi_ksp->ks_lock);
1658 + kstat_runq_enter(KSTAT_IO_PTR(exi_ksp));
1659 + mutex_exit(exi_ksp->ks_lock);
1660 + } else {
1661 + rw_exit(&ne->exported_lock);
1662 + }
1663 +
1664 + publicfh_ok = PUBLICFH_CHECK(ne, disp, exi, fsid, xfid);
1655 1665 /*
1656 1666 * Don't allow non-V4 clients access
1657 1667 * to pseudo exports
1658 1668 */
1659 1669 if (PSEUDO(exi)) {
1660 1670 svcerr_weakauth(xprt);
1661 1671 error++;
1662 1672 goto done;
1663 1673 }
1664 1674
1665 1675 authres = checkauth(exi, req, cr, anon_ok, publicfh_ok,
1666 1676 &ro);
1667 1677 /*
1668 1678 * authres > 0: authentication OK - proceed
1669 1679 * authres == 0: authentication weak - return error
1670 1680 * authres < 0: authentication timeout - drop
1671 1681 */
1672 1682 if (authres <= 0) {
1673 1683 if (authres == 0) {
1674 1684 svcerr_weakauth(xprt);
1675 1685 error++;
1676 1686 }
1677 1687 goto done;
1678 1688 }
1679 1689 }
1680 1690 } else
1681 1691 cr = NULL;
1682 1692
1683 1693 if ((dis_flags & RPC_MAPRESP) && (auth_flavor != RPCSEC_GSS)) {
1684 1694 res = (char *)SVC_GETRES(xprt, disp->dis_ressz);
1685 1695 if (res == NULL)
1686 1696 res = (char *)&res_buf;
1687 1697 } else
1688 1698 res = (char *)&res_buf;
1689 1699
1690 1700 if (!(dis_flags & RPC_IDEMPOTENT)) {
1691 1701 dupstat = SVC_DUP_EXT(xprt, req, res, disp->dis_ressz, &dr,
1692 1702 &dupcached);
1693 1703
1694 1704 switch (dupstat) {
1695 1705 case DUP_ERROR:
1696 1706 svcerr_systemerr(xprt);
1697 1707 error++;
1698 1708 goto done;
1699 1709 /* NOTREACHED */
1700 1710 case DUP_INPROGRESS:
1701 1711 if (res != (char *)&res_buf)
1702 1712 SVC_FREERES(xprt);
1703 1713 error++;
1704 1714 goto done;
1705 1715 /* NOTREACHED */
1706 1716 case DUP_NEW:
1707 1717 case DUP_DROP:
1708 1718 curthread->t_flag |= T_DONTPEND;
1709 1719
1710 1720 (*disp->dis_proc)(args, res, exi, req, cr, ro);
1711 1721
1712 1722 curthread->t_flag &= ~T_DONTPEND;
1713 1723 if (curthread->t_flag & T_WOULDBLOCK) {
1714 1724 curthread->t_flag &= ~T_WOULDBLOCK;
1715 1725 SVC_DUPDONE_EXT(xprt, dr, res, NULL,
1716 1726 disp->dis_ressz, DUP_DROP);
1717 1727 if (res != (char *)&res_buf)
1718 1728 SVC_FREERES(xprt);
1719 1729 error++;
1720 1730 goto done;
1721 1731 }
1722 1732 if (dis_flags & RPC_AVOIDWORK) {
1723 1733 SVC_DUPDONE_EXT(xprt, dr, res, NULL,
1724 1734 disp->dis_ressz, DUP_DROP);
1725 1735 } else {
1726 1736 SVC_DUPDONE_EXT(xprt, dr, res,
1727 1737 disp->dis_resfree == nullfree ? NULL :
1728 1738 disp->dis_resfree,
1729 1739 disp->dis_ressz, DUP_DONE);
1730 1740 dupcached = TRUE;
1731 1741 }
1732 1742 break;
1733 1743 case DUP_DONE:
1734 1744 break;
1735 1745 }
1736 1746
1737 1747 } else {
1738 1748 curthread->t_flag |= T_DONTPEND;
1739 1749
1740 1750 (*disp->dis_proc)(args, res, exi, req, cr, ro);
1741 1751
1742 1752 curthread->t_flag &= ~T_DONTPEND;
1743 1753 if (curthread->t_flag & T_WOULDBLOCK) {
1744 1754 curthread->t_flag &= ~T_WOULDBLOCK;
1745 1755 if (res != (char *)&res_buf)
1746 1756 SVC_FREERES(xprt);
1747 1757 error++;
1748 1758 goto done;
1749 1759 }
1750 1760 }
1751 1761
1752 1762 if (auth_tooweak(req, res)) {
1753 1763 svcerr_weakauth(xprt);
1754 1764 error++;
1755 1765 goto done;
|
↓ open down ↓ |
91 lines elided |
↑ open up ↑ |
1756 1766 }
1757 1767
1758 1768 /*
1759 1769 * Check to see if logging has been enabled on the server.
1760 1770 * If so, then obtain the export info struct to be used for
1761 1771 * the later writing of the log record. This is done for
1762 1772 * the case that a lookup is done across a non-logged public
1763 1773 * file system.
1764 1774 */
1765 1775 if (nfslog_buffer_list != NULL) {
1766 - nfslog_exi = nfslog_get_exi(exi, req, res, &nfslog_rec_id);
1776 + nfslog_exi = nfslog_get_exi(ne, exi, req, res, &nfslog_rec_id);
1767 1777 /*
1768 1778 * Is logging enabled?
1769 1779 */
1770 1780 logging_enabled = (nfslog_exi != NULL);
1771 1781
1772 1782 /*
1773 1783 * Copy the netbuf for logging purposes, before it is
1774 1784 * freed by svc_sendreply().
1775 1785 */
1776 1786 if (logging_enabled) {
1777 1787 NFSLOG_COPY_NETBUF(nfslog_exi, xprt, &nb);
1778 1788 /*
1779 1789 * If RPC_MAPRESP flag set (i.e. in V2 ops) the
1780 1790 * res gets copied directly into the mbuf and
1781 1791 * may be freed soon after the sendreply. So we
1782 1792 * must copy it here to a safe place...
1783 1793 */
1784 1794 if (res != (char *)&res_buf) {
1785 1795 bcopy(res, (char *)&res_buf, disp->dis_ressz);
1786 1796 }
1787 1797 }
1788 1798 }
1789 1799
1790 1800 /*
1791 1801 * Serialize and send results struct
1792 1802 */
|
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
1793 1803 #ifdef DEBUG
1794 1804 if (rfs_no_fast_xdrres == 0 && res != (char *)&res_buf)
1795 1805 #else
1796 1806 if (res != (char *)&res_buf)
1797 1807 #endif
1798 1808 {
1799 1809 if (!svc_sendreply(xprt, disp->dis_fastxdrres, res)) {
1800 1810 cmn_err(CE_NOTE, "%s: bad sendreply", pgmname);
1801 1811 svcerr_systemerr(xprt);
1802 1812 error++;
1813 + } else {
1814 + rlen = xdr_sizeof(disp->dis_fastxdrres, res);
1815 + rsent = TRUE;
1803 1816 }
1804 1817 } else {
1805 1818 if (!svc_sendreply(xprt, disp->dis_xdrres, res)) {
1806 1819 cmn_err(CE_NOTE, "%s: bad sendreply", pgmname);
1807 1820 svcerr_systemerr(xprt);
1808 1821 error++;
1822 + } else {
1823 + rlen = xdr_sizeof(disp->dis_xdrres, res);
1824 + rsent = TRUE;
1809 1825 }
1810 1826 }
1811 1827
1812 1828 /*
1813 1829 * Log if needed
1814 1830 */
1815 1831 if (logging_enabled) {
1816 1832 nfslog_write_record(nfslog_exi, req, args, (char *)&res_buf,
1817 1833 cr, &nb, nfslog_rec_id, NFSLOG_ONE_BUFFER);
1818 - exi_rele(nfslog_exi);
1834 + exi_rele(&nfslog_exi);
1819 1835 kmem_free((&nb)->buf, (&nb)->len);
1820 1836 }
1821 1837
1822 1838 /*
1823 1839 * Free results struct. With the addition of NFS V4 we can
1824 1840 * have non-idempotent procedures with functions.
1825 1841 */
1826 1842 if (disp->dis_resfree != nullfree && dupcached == FALSE) {
1827 1843 (*disp->dis_resfree)(res);
1828 1844 }
1829 1845
1830 1846 done:
1847 + if (ksp != NULL || exi_ksp != NULL) {
1848 + pos = XDR_GETPOS(&xprt->xp_xdrin) - pos;
1849 + }
1850 +
1831 1851 /*
1832 1852 * Free arguments struct
1833 1853 */
1834 1854 if (disp) {
1835 1855 if (!SVC_FREEARGS(xprt, disp->dis_xdrargs, args)) {
1836 1856 cmn_err(CE_NOTE, "%s: bad freeargs", pgmname);
1837 1857 error++;
1838 1858 }
1839 1859 } else {
1840 1860 if (!SVC_FREEARGS(xprt, (xdrproc_t)0, (caddr_t)0)) {
1841 1861 cmn_err(CE_NOTE, "%s: bad freeargs", pgmname);
1842 1862 error++;
1843 1863 }
1844 1864 }
1845 1865
1866 + if (exi_ksp != NULL) {
1867 + mutex_enter(exi_ksp->ks_lock);
1868 + KSTAT_IO_PTR(exi_ksp)->nwritten += pos;
1869 + KSTAT_IO_PTR(exi_ksp)->writes++;
1870 + if (rsent) {
1871 + KSTAT_IO_PTR(exi_ksp)->nread += rlen;
1872 + KSTAT_IO_PTR(exi_ksp)->reads++;
1873 + }
1874 + kstat_runq_exit(KSTAT_IO_PTR(exi_ksp));
1875 + mutex_exit(exi_ksp->ks_lock);
1876 +
1877 + rw_exit(&ne->exported_lock);
1878 + }
1879 +
1846 1880 if (exi != NULL)
1847 - exi_rele(exi);
1881 + exi_rele(&exi);
1848 1882
1883 + if (ksp != NULL) {
1884 + mutex_enter(ksp->ks_lock);
1885 + KSTAT_IO_PTR(ksp)->nwritten += pos;
1886 + KSTAT_IO_PTR(ksp)->writes++;
1887 + if (rsent) {
1888 + KSTAT_IO_PTR(ksp)->nread += rlen;
1889 + KSTAT_IO_PTR(ksp)->reads++;
1890 + }
1891 + kstat_runq_exit(KSTAT_IO_PTR(ksp));
1892 + mutex_exit(ksp->ks_lock);
1893 + }
1894 +
1849 1895 global_svstat_ptr[req->rq_vers][NFS_BADCALLS].value.ui64 += error;
1850 1896
1851 1897 global_svstat_ptr[req->rq_vers][NFS_CALLS].value.ui64++;
1852 1898 }
1853 1899
1854 1900 static void
1855 1901 rfs_dispatch(struct svc_req *req, SVCXPRT *xprt)
1856 1902 {
1857 1903 common_dispatch(req, xprt, NFS_VERSMIN, NFS_VERSMAX,
1858 1904 "NFS", rfs_disptable);
1859 1905 }
1860 1906
1861 1907 static char *aclcallnames_v2[] = {
1862 1908 "ACL2_NULL",
1863 1909 "ACL2_GETACL",
1864 1910 "ACL2_SETACL",
1865 1911 "ACL2_GETATTR",
1866 1912 "ACL2_ACCESS",
1867 1913 "ACL2_GETXATTRDIR"
1868 1914 };
1869 1915
1870 1916 static struct rpcdisp acldisptab_v2[] = {
1871 1917 /*
1872 1918 * ACL VERSION 2
1873 1919 */
1874 1920
1875 1921 /* ACL2_NULL = 0 */
1876 1922 {rpc_null,
1877 1923 xdr_void, NULL_xdrproc_t, 0,
1878 1924 xdr_void, NULL_xdrproc_t, 0,
1879 1925 nullfree, RPC_IDEMPOTENT,
1880 1926 0},
1881 1927
1882 1928 /* ACL2_GETACL = 1 */
1883 1929 {acl2_getacl,
1884 1930 xdr_GETACL2args, xdr_fastGETACL2args, sizeof (GETACL2args),
1885 1931 xdr_GETACL2res, NULL_xdrproc_t, sizeof (GETACL2res),
1886 1932 acl2_getacl_free, RPC_IDEMPOTENT,
1887 1933 acl2_getacl_getfh},
1888 1934
1889 1935 /* ACL2_SETACL = 2 */
1890 1936 {acl2_setacl,
1891 1937 xdr_SETACL2args, NULL_xdrproc_t, sizeof (SETACL2args),
1892 1938 #ifdef _LITTLE_ENDIAN
1893 1939 xdr_SETACL2res, xdr_fastSETACL2res, sizeof (SETACL2res),
1894 1940 #else
1895 1941 xdr_SETACL2res, NULL_xdrproc_t, sizeof (SETACL2res),
1896 1942 #endif
1897 1943 nullfree, RPC_MAPRESP,
1898 1944 acl2_setacl_getfh},
1899 1945
1900 1946 /* ACL2_GETATTR = 3 */
1901 1947 {acl2_getattr,
1902 1948 xdr_GETATTR2args, xdr_fastGETATTR2args, sizeof (GETATTR2args),
1903 1949 #ifdef _LITTLE_ENDIAN
1904 1950 xdr_GETATTR2res, xdr_fastGETATTR2res, sizeof (GETATTR2res),
1905 1951 #else
1906 1952 xdr_GETATTR2res, NULL_xdrproc_t, sizeof (GETATTR2res),
1907 1953 #endif
1908 1954 nullfree, RPC_IDEMPOTENT|RPC_ALLOWANON|RPC_MAPRESP,
1909 1955 acl2_getattr_getfh},
1910 1956
1911 1957 /* ACL2_ACCESS = 4 */
1912 1958 {acl2_access,
1913 1959 xdr_ACCESS2args, xdr_fastACCESS2args, sizeof (ACCESS2args),
1914 1960 #ifdef _LITTLE_ENDIAN
1915 1961 xdr_ACCESS2res, xdr_fastACCESS2res, sizeof (ACCESS2res),
1916 1962 #else
1917 1963 xdr_ACCESS2res, NULL_xdrproc_t, sizeof (ACCESS2res),
1918 1964 #endif
1919 1965 nullfree, RPC_IDEMPOTENT|RPC_MAPRESP,
1920 1966 acl2_access_getfh},
1921 1967
1922 1968 /* ACL2_GETXATTRDIR = 5 */
1923 1969 {acl2_getxattrdir,
1924 1970 xdr_GETXATTRDIR2args, NULL_xdrproc_t, sizeof (GETXATTRDIR2args),
1925 1971 xdr_GETXATTRDIR2res, NULL_xdrproc_t, sizeof (GETXATTRDIR2res),
1926 1972 nullfree, RPC_IDEMPOTENT,
1927 1973 acl2_getxattrdir_getfh},
1928 1974 };
1929 1975
1930 1976 static char *aclcallnames_v3[] = {
1931 1977 "ACL3_NULL",
1932 1978 "ACL3_GETACL",
1933 1979 "ACL3_SETACL",
1934 1980 "ACL3_GETXATTRDIR"
1935 1981 };
1936 1982
1937 1983 static struct rpcdisp acldisptab_v3[] = {
1938 1984 /*
1939 1985 * ACL VERSION 3
1940 1986 */
1941 1987
1942 1988 /* ACL3_NULL = 0 */
1943 1989 {rpc_null,
1944 1990 xdr_void, NULL_xdrproc_t, 0,
1945 1991 xdr_void, NULL_xdrproc_t, 0,
1946 1992 nullfree, RPC_IDEMPOTENT,
1947 1993 0},
1948 1994
1949 1995 /* ACL3_GETACL = 1 */
1950 1996 {acl3_getacl,
1951 1997 xdr_GETACL3args, NULL_xdrproc_t, sizeof (GETACL3args),
1952 1998 xdr_GETACL3res, NULL_xdrproc_t, sizeof (GETACL3res),
1953 1999 acl3_getacl_free, RPC_IDEMPOTENT,
1954 2000 acl3_getacl_getfh},
1955 2001
1956 2002 /* ACL3_SETACL = 2 */
1957 2003 {acl3_setacl,
1958 2004 xdr_SETACL3args, NULL_xdrproc_t, sizeof (SETACL3args),
1959 2005 xdr_SETACL3res, NULL_xdrproc_t, sizeof (SETACL3res),
1960 2006 nullfree, 0,
1961 2007 acl3_setacl_getfh},
1962 2008
1963 2009 /* ACL3_GETXATTRDIR = 3 */
|
↓ open down ↓ |
105 lines elided |
↑ open up ↑ |
1964 2010 {acl3_getxattrdir,
1965 2011 xdr_GETXATTRDIR3args, NULL_xdrproc_t, sizeof (GETXATTRDIR3args),
1966 2012 xdr_GETXATTRDIR3res, NULL_xdrproc_t, sizeof (GETXATTRDIR3res),
1967 2013 nullfree, RPC_IDEMPOTENT,
1968 2014 acl3_getxattrdir_getfh},
1969 2015 };
1970 2016
1971 2017 static struct rpc_disptable acl_disptable[] = {
1972 2018 {sizeof (acldisptab_v2) / sizeof (acldisptab_v2[0]),
1973 2019 aclcallnames_v2,
1974 - &aclproccnt_v2_ptr, acldisptab_v2},
2020 + &aclproccnt_v2_ptr, &aclprocio_v2_ptr, acldisptab_v2},
1975 2021 {sizeof (acldisptab_v3) / sizeof (acldisptab_v3[0]),
1976 2022 aclcallnames_v3,
1977 - &aclproccnt_v3_ptr, acldisptab_v3},
2023 + &aclproccnt_v3_ptr, &aclprocio_v3_ptr, acldisptab_v3},
1978 2024 };
1979 2025
1980 2026 static void
1981 2027 acl_dispatch(struct svc_req *req, SVCXPRT *xprt)
1982 2028 {
1983 2029 common_dispatch(req, xprt, NFS_ACL_VERSMIN, NFS_ACL_VERSMAX,
1984 2030 "ACL", acl_disptable);
1985 2031 }
1986 2032
1987 2033 int
1988 2034 checkwin(int flavor, int window, struct svc_req *req)
1989 2035 {
1990 2036 struct authdes_cred *adc;
1991 2037
1992 2038 switch (flavor) {
1993 2039 case AUTH_DES:
1994 2040 adc = (struct authdes_cred *)req->rq_clntcred;
1995 2041 CTASSERT(sizeof (struct authdes_cred) <= RQCRED_SIZE);
1996 2042 if (adc->adc_fullname.window > window)
1997 2043 return (0);
1998 2044 break;
1999 2045
2000 2046 default:
2001 2047 break;
2002 2048 }
2003 2049 return (1);
2004 2050 }
2005 2051
2006 2052
2007 2053 /*
2008 2054 * checkauth() will check the access permission against the export
2009 2055 * information. Then map root uid/gid to appropriate uid/gid.
2010 2056 *
2011 2057 * This routine is used by NFS V3 and V2 code.
2012 2058 */
2013 2059 static int
2014 2060 checkauth(struct exportinfo *exi, struct svc_req *req, cred_t *cr, int anon_ok,
2015 2061 bool_t publicfh_ok, bool_t *ro)
2016 2062 {
2017 2063 int i, nfsflavor, rpcflavor, stat, access;
2018 2064 struct secinfo *secp;
2019 2065 caddr_t principal;
2020 2066 char buf[INET6_ADDRSTRLEN]; /* to hold both IPv4 and IPv6 addr */
2021 2067 int anon_res = 0;
2022 2068
2023 2069 uid_t uid;
2024 2070 gid_t gid;
2025 2071 uint_t ngids;
2026 2072 gid_t *gids;
2027 2073
2028 2074 /*
2029 2075 * Check for privileged port number
2030 2076 * N.B.: this assumes that we know the format of a netbuf.
2031 2077 */
2032 2078 if (nfs_portmon) {
2033 2079 struct sockaddr *ca;
2034 2080 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2035 2081
2036 2082 if (ca == NULL)
2037 2083 return (0);
2038 2084
2039 2085 if ((ca->sa_family == AF_INET &&
2040 2086 ntohs(((struct sockaddr_in *)ca)->sin_port) >=
2041 2087 IPPORT_RESERVED) ||
2042 2088 (ca->sa_family == AF_INET6 &&
2043 2089 ntohs(((struct sockaddr_in6 *)ca)->sin6_port) >=
2044 2090 IPPORT_RESERVED)) {
2045 2091 cmn_err(CE_NOTE,
2046 2092 "nfs_server: client %s%ssent NFS request from "
2047 2093 "unprivileged port",
2048 2094 client_name(req), client_addr(req, buf));
2049 2095 return (0);
2050 2096 }
2051 2097 }
2052 2098
2053 2099 /*
2054 2100 * return 1 on success or 0 on failure
2055 2101 */
2056 2102 stat = sec_svc_getcred(req, cr, &principal, &nfsflavor);
2057 2103
2058 2104 /*
2059 2105 * A failed AUTH_UNIX sec_svc_getcred() implies we couldn't set
2060 2106 * the credentials; below we map that to anonymous.
2061 2107 */
2062 2108 if (!stat && nfsflavor != AUTH_UNIX) {
2063 2109 cmn_err(CE_NOTE,
2064 2110 "nfs_server: couldn't get unix cred for %s",
2065 2111 client_name(req));
2066 2112 return (0);
2067 2113 }
2068 2114
2069 2115 /*
2070 2116 * Short circuit checkauth() on operations that support the
2071 2117 * public filehandle, and if the request for that operation
2072 2118 * is using the public filehandle. Note that we must call
2073 2119 * sec_svc_getcred() first so that xp_cookie is set to the
2074 2120 * right value. Normally xp_cookie is just the RPC flavor
2075 2121 * of the the request, but in the case of RPCSEC_GSS it
2076 2122 * could be a pseudo flavor.
2077 2123 */
2078 2124 if (publicfh_ok)
2079 2125 return (1);
2080 2126
2081 2127 rpcflavor = req->rq_cred.oa_flavor;
2082 2128 /*
2083 2129 * Check if the auth flavor is valid for this export
2084 2130 */
2085 2131 access = nfsauth_access(exi, req, cr, &uid, &gid, &ngids, &gids);
2086 2132 if (access & NFSAUTH_DROP)
2087 2133 return (-1); /* drop the request */
2088 2134
2089 2135 if (access & NFSAUTH_RO)
2090 2136 *ro = TRUE;
2091 2137
2092 2138 if (access & NFSAUTH_DENIED) {
2093 2139 /*
2094 2140 * If anon_ok == 1 and we got NFSAUTH_DENIED, it was
2095 2141 * probably due to the flavor not matching during
2096 2142 * the mount attempt. So map the flavor to AUTH_NONE
2097 2143 * so that the credentials get mapped to the anonymous
2098 2144 * user.
2099 2145 */
2100 2146 if (anon_ok == 1)
2101 2147 rpcflavor = AUTH_NONE;
2102 2148 else
2103 2149 return (0); /* deny access */
2104 2150
2105 2151 } else if (access & NFSAUTH_MAPNONE) {
2106 2152 /*
2107 2153 * Access was granted even though the flavor mismatched
2108 2154 * because AUTH_NONE was one of the exported flavors.
2109 2155 */
2110 2156 rpcflavor = AUTH_NONE;
2111 2157
2112 2158 } else if (access & NFSAUTH_WRONGSEC) {
2113 2159 /*
2114 2160 * NFSAUTH_WRONGSEC is used for NFSv4. If we get here,
2115 2161 * it means a client ignored the list of allowed flavors
2116 2162 * returned via the MOUNT protocol. So we just disallow it!
2117 2163 */
2118 2164 return (0);
2119 2165 }
2120 2166
2121 2167 if (rpcflavor != AUTH_SYS)
2122 2168 kmem_free(gids, ngids * sizeof (gid_t));
2123 2169
2124 2170 switch (rpcflavor) {
2125 2171 case AUTH_NONE:
2126 2172 anon_res = crsetugid(cr, exi->exi_export.ex_anon,
2127 2173 exi->exi_export.ex_anon);
2128 2174 (void) crsetgroups(cr, 0, NULL);
2129 2175 break;
2130 2176
2131 2177 case AUTH_UNIX:
2132 2178 if (!stat || crgetuid(cr) == 0 && !(access & NFSAUTH_UIDMAP)) {
2133 2179 anon_res = crsetugid(cr, exi->exi_export.ex_anon,
2134 2180 exi->exi_export.ex_anon);
2135 2181 (void) crsetgroups(cr, 0, NULL);
2136 2182 } else if (crgetuid(cr) == 0 && access & NFSAUTH_ROOT) {
2137 2183 /*
2138 2184 * It is root, so apply rootid to get real UID
2139 2185 * Find the secinfo structure. We should be able
2140 2186 * to find it by the time we reach here.
2141 2187 * nfsauth_access() has done the checking.
2142 2188 */
2143 2189 secp = NULL;
2144 2190 for (i = 0; i < exi->exi_export.ex_seccnt; i++) {
2145 2191 struct secinfo *sptr;
2146 2192 sptr = &exi->exi_export.ex_secinfo[i];
2147 2193 if (sptr->s_secinfo.sc_nfsnum == nfsflavor) {
2148 2194 secp = sptr;
2149 2195 break;
2150 2196 }
2151 2197 }
2152 2198 if (secp != NULL) {
2153 2199 (void) crsetugid(cr, secp->s_rootid,
2154 2200 secp->s_rootid);
2155 2201 (void) crsetgroups(cr, 0, NULL);
2156 2202 }
2157 2203 } else if (crgetuid(cr) != uid || crgetgid(cr) != gid) {
2158 2204 if (crsetugid(cr, uid, gid) != 0)
2159 2205 anon_res = crsetugid(cr,
2160 2206 exi->exi_export.ex_anon,
2161 2207 exi->exi_export.ex_anon);
2162 2208 (void) crsetgroups(cr, 0, NULL);
2163 2209 } else if (access & NFSAUTH_GROUPS) {
2164 2210 (void) crsetgroups(cr, ngids, gids);
2165 2211 }
2166 2212
2167 2213 kmem_free(gids, ngids * sizeof (gid_t));
2168 2214
2169 2215 break;
2170 2216
2171 2217 case AUTH_DES:
2172 2218 case RPCSEC_GSS:
2173 2219 /*
2174 2220 * Find the secinfo structure. We should be able
2175 2221 * to find it by the time we reach here.
2176 2222 * nfsauth_access() has done the checking.
2177 2223 */
2178 2224 secp = NULL;
2179 2225 for (i = 0; i < exi->exi_export.ex_seccnt; i++) {
2180 2226 if (exi->exi_export.ex_secinfo[i].s_secinfo.sc_nfsnum ==
2181 2227 nfsflavor) {
2182 2228 secp = &exi->exi_export.ex_secinfo[i];
2183 2229 break;
2184 2230 }
2185 2231 }
2186 2232
2187 2233 if (!secp) {
2188 2234 cmn_err(CE_NOTE, "nfs_server: client %s%shad "
2189 2235 "no secinfo data for flavor %d",
2190 2236 client_name(req), client_addr(req, buf),
2191 2237 nfsflavor);
2192 2238 return (0);
2193 2239 }
2194 2240
2195 2241 if (!checkwin(rpcflavor, secp->s_window, req)) {
2196 2242 cmn_err(CE_NOTE,
2197 2243 "nfs_server: client %s%sused invalid "
2198 2244 "auth window value",
2199 2245 client_name(req), client_addr(req, buf));
2200 2246 return (0);
2201 2247 }
2202 2248
2203 2249 /*
2204 2250 * Map root principals listed in the share's root= list to root,
2205 2251 * and map any others principals that were mapped to root by RPC
2206 2252 * to anon.
2207 2253 */
2208 2254 if (principal && sec_svc_inrootlist(rpcflavor, principal,
2209 2255 secp->s_rootcnt, secp->s_rootnames)) {
2210 2256 if (crgetuid(cr) == 0 && secp->s_rootid == 0)
2211 2257 return (1);
2212 2258
2213 2259
2214 2260 (void) crsetugid(cr, secp->s_rootid, secp->s_rootid);
2215 2261
2216 2262 /*
2217 2263 * NOTE: If and when kernel-land privilege tracing is
2218 2264 * added this may have to be replaced with code that
2219 2265 * retrieves root's supplementary groups (e.g., using
2220 2266 * kgss_get_group_info(). In the meantime principals
2221 2267 * mapped to uid 0 get all privileges, so setting cr's
2222 2268 * supplementary groups for them does nothing.
2223 2269 */
2224 2270 (void) crsetgroups(cr, 0, NULL);
2225 2271
2226 2272 return (1);
2227 2273 }
2228 2274
2229 2275 /*
2230 2276 * Not a root princ, or not in root list, map UID 0/nobody to
2231 2277 * the anon ID for the share. (RPC sets cr's UIDs and GIDs to
2232 2278 * UID_NOBODY and GID_NOBODY, respectively.)
2233 2279 */
2234 2280 if (crgetuid(cr) != 0 &&
2235 2281 (crgetuid(cr) != UID_NOBODY || crgetgid(cr) != GID_NOBODY))
2236 2282 return (1);
2237 2283
2238 2284 anon_res = crsetugid(cr, exi->exi_export.ex_anon,
2239 2285 exi->exi_export.ex_anon);
2240 2286 (void) crsetgroups(cr, 0, NULL);
2241 2287 break;
2242 2288 default:
2243 2289 return (0);
2244 2290 } /* switch on rpcflavor */
2245 2291
2246 2292 /*
2247 2293 * Even if anon access is disallowed via ex_anon == -1, we allow
2248 2294 * this access if anon_ok is set. So set creds to the default
2249 2295 * "nobody" id.
2250 2296 */
2251 2297 if (anon_res != 0) {
2252 2298 if (anon_ok == 0) {
2253 2299 cmn_err(CE_NOTE,
2254 2300 "nfs_server: client %s%ssent wrong "
2255 2301 "authentication for %s",
2256 2302 client_name(req), client_addr(req, buf),
2257 2303 exi->exi_export.ex_path ?
2258 2304 exi->exi_export.ex_path : "?");
2259 2305 return (0);
2260 2306 }
2261 2307
2262 2308 if (crsetugid(cr, UID_NOBODY, GID_NOBODY) != 0)
2263 2309 return (0);
2264 2310 }
2265 2311
2266 2312 return (1);
2267 2313 }
2268 2314
2269 2315 /*
2270 2316 * returns 0 on failure, -1 on a drop, -2 on wrong security flavor,
2271 2317 * and 1 on success
2272 2318 */
2273 2319 int
2274 2320 checkauth4(struct compound_state *cs, struct svc_req *req)
2275 2321 {
2276 2322 int i, rpcflavor, access;
2277 2323 struct secinfo *secp;
2278 2324 char buf[MAXHOST + 1];
2279 2325 int anon_res = 0, nfsflavor;
2280 2326 struct exportinfo *exi;
2281 2327 cred_t *cr;
2282 2328 caddr_t principal;
2283 2329
2284 2330 uid_t uid;
2285 2331 gid_t gid;
2286 2332 uint_t ngids;
2287 2333 gid_t *gids;
2288 2334
2289 2335 exi = cs->exi;
2290 2336 cr = cs->cr;
2291 2337 principal = cs->principal;
2292 2338 nfsflavor = cs->nfsflavor;
2293 2339
2294 2340 ASSERT(cr != NULL);
2295 2341
2296 2342 rpcflavor = req->rq_cred.oa_flavor;
2297 2343 cs->access &= ~CS_ACCESS_LIMITED;
2298 2344
2299 2345 /*
2300 2346 * Check for privileged port number
2301 2347 * N.B.: this assumes that we know the format of a netbuf.
2302 2348 */
2303 2349 if (nfs_portmon) {
2304 2350 struct sockaddr *ca;
2305 2351 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2306 2352
2307 2353 if (ca == NULL)
2308 2354 return (0);
2309 2355
2310 2356 if ((ca->sa_family == AF_INET &&
2311 2357 ntohs(((struct sockaddr_in *)ca)->sin_port) >=
2312 2358 IPPORT_RESERVED) ||
2313 2359 (ca->sa_family == AF_INET6 &&
2314 2360 ntohs(((struct sockaddr_in6 *)ca)->sin6_port) >=
2315 2361 IPPORT_RESERVED)) {
2316 2362 cmn_err(CE_NOTE,
2317 2363 "nfs_server: client %s%ssent NFSv4 request from "
2318 2364 "unprivileged port",
2319 2365 client_name(req), client_addr(req, buf));
2320 2366 return (0);
2321 2367 }
2322 2368 }
2323 2369
2324 2370 /*
2325 2371 * Check the access right per auth flavor on the vnode of
2326 2372 * this export for the given request.
2327 2373 */
2328 2374 access = nfsauth4_access(cs->exi, cs->vp, req, cr, &uid, &gid, &ngids,
2329 2375 &gids);
2330 2376
2331 2377 if (access & NFSAUTH_WRONGSEC)
2332 2378 return (-2); /* no access for this security flavor */
2333 2379
2334 2380 if (access & NFSAUTH_DROP)
2335 2381 return (-1); /* drop the request */
2336 2382
2337 2383 if (access & NFSAUTH_DENIED) {
2338 2384
2339 2385 if (exi->exi_export.ex_seccnt > 0)
2340 2386 return (0); /* deny access */
2341 2387
2342 2388 } else if (access & NFSAUTH_LIMITED) {
2343 2389
2344 2390 cs->access |= CS_ACCESS_LIMITED;
2345 2391
2346 2392 } else if (access & NFSAUTH_MAPNONE) {
2347 2393 /*
2348 2394 * Access was granted even though the flavor mismatched
2349 2395 * because AUTH_NONE was one of the exported flavors.
2350 2396 */
2351 2397 rpcflavor = AUTH_NONE;
2352 2398 }
2353 2399
2354 2400 /*
2355 2401 * XXX probably need to redo some of it for nfsv4?
2356 2402 * return 1 on success or 0 on failure
2357 2403 */
2358 2404
2359 2405 if (rpcflavor != AUTH_SYS)
2360 2406 kmem_free(gids, ngids * sizeof (gid_t));
2361 2407
2362 2408 switch (rpcflavor) {
2363 2409 case AUTH_NONE:
2364 2410 anon_res = crsetugid(cr, exi->exi_export.ex_anon,
2365 2411 exi->exi_export.ex_anon);
2366 2412 (void) crsetgroups(cr, 0, NULL);
2367 2413 break;
2368 2414
2369 2415 case AUTH_UNIX:
2370 2416 if (crgetuid(cr) == 0 && !(access & NFSAUTH_UIDMAP)) {
2371 2417 anon_res = crsetugid(cr, exi->exi_export.ex_anon,
2372 2418 exi->exi_export.ex_anon);
2373 2419 (void) crsetgroups(cr, 0, NULL);
2374 2420 } else if (crgetuid(cr) == 0 && access & NFSAUTH_ROOT) {
2375 2421 /*
2376 2422 * It is root, so apply rootid to get real UID
2377 2423 * Find the secinfo structure. We should be able
2378 2424 * to find it by the time we reach here.
2379 2425 * nfsauth_access() has done the checking.
2380 2426 */
2381 2427 secp = NULL;
2382 2428 for (i = 0; i < exi->exi_export.ex_seccnt; i++) {
2383 2429 struct secinfo *sptr;
2384 2430 sptr = &exi->exi_export.ex_secinfo[i];
2385 2431 if (sptr->s_secinfo.sc_nfsnum == nfsflavor) {
2386 2432 secp = &exi->exi_export.ex_secinfo[i];
2387 2433 break;
2388 2434 }
2389 2435 }
2390 2436 if (secp != NULL) {
2391 2437 (void) crsetugid(cr, secp->s_rootid,
2392 2438 secp->s_rootid);
2393 2439 (void) crsetgroups(cr, 0, NULL);
2394 2440 }
2395 2441 } else if (crgetuid(cr) != uid || crgetgid(cr) != gid) {
2396 2442 if (crsetugid(cr, uid, gid) != 0)
2397 2443 anon_res = crsetugid(cr,
2398 2444 exi->exi_export.ex_anon,
2399 2445 exi->exi_export.ex_anon);
2400 2446 (void) crsetgroups(cr, 0, NULL);
2401 2447 } if (access & NFSAUTH_GROUPS) {
2402 2448 (void) crsetgroups(cr, ngids, gids);
2403 2449 }
2404 2450
2405 2451 kmem_free(gids, ngids * sizeof (gid_t));
2406 2452
2407 2453 break;
2408 2454
2409 2455 default:
2410 2456 /*
2411 2457 * Find the secinfo structure. We should be able
2412 2458 * to find it by the time we reach here.
2413 2459 * nfsauth_access() has done the checking.
2414 2460 */
2415 2461 secp = NULL;
2416 2462 for (i = 0; i < exi->exi_export.ex_seccnt; i++) {
2417 2463 if (exi->exi_export.ex_secinfo[i].s_secinfo.sc_nfsnum ==
2418 2464 nfsflavor) {
2419 2465 secp = &exi->exi_export.ex_secinfo[i];
2420 2466 break;
2421 2467 }
2422 2468 }
2423 2469
2424 2470 if (!secp) {
2425 2471 cmn_err(CE_NOTE, "nfs_server: client %s%shad "
2426 2472 "no secinfo data for flavor %d",
2427 2473 client_name(req), client_addr(req, buf),
2428 2474 nfsflavor);
2429 2475 return (0);
2430 2476 }
2431 2477
2432 2478 if (!checkwin(rpcflavor, secp->s_window, req)) {
2433 2479 cmn_err(CE_NOTE,
2434 2480 "nfs_server: client %s%sused invalid "
2435 2481 "auth window value",
2436 2482 client_name(req), client_addr(req, buf));
2437 2483 return (0);
2438 2484 }
2439 2485
2440 2486 /*
2441 2487 * Map root principals listed in the share's root= list to root,
2442 2488 * and map any others principals that were mapped to root by RPC
2443 2489 * to anon. If not going to anon, set to rootid (root_mapping).
2444 2490 */
2445 2491 if (principal && sec_svc_inrootlist(rpcflavor, principal,
2446 2492 secp->s_rootcnt, secp->s_rootnames)) {
2447 2493 if (crgetuid(cr) == 0 && secp->s_rootid == 0)
2448 2494 return (1);
2449 2495
2450 2496 (void) crsetugid(cr, secp->s_rootid, secp->s_rootid);
2451 2497
2452 2498 /*
2453 2499 * NOTE: If and when kernel-land privilege tracing is
2454 2500 * added this may have to be replaced with code that
2455 2501 * retrieves root's supplementary groups (e.g., using
2456 2502 * kgss_get_group_info(). In the meantime principals
2457 2503 * mapped to uid 0 get all privileges, so setting cr's
2458 2504 * supplementary groups for them does nothing.
2459 2505 */
2460 2506 (void) crsetgroups(cr, 0, NULL);
2461 2507
2462 2508 return (1);
2463 2509 }
2464 2510
2465 2511 /*
2466 2512 * Not a root princ, or not in root list, map UID 0/nobody to
2467 2513 * the anon ID for the share. (RPC sets cr's UIDs and GIDs to
2468 2514 * UID_NOBODY and GID_NOBODY, respectively.)
2469 2515 */
2470 2516 if (crgetuid(cr) != 0 &&
2471 2517 (crgetuid(cr) != UID_NOBODY || crgetgid(cr) != GID_NOBODY))
2472 2518 return (1);
2473 2519
2474 2520 anon_res = crsetugid(cr, exi->exi_export.ex_anon,
2475 2521 exi->exi_export.ex_anon);
2476 2522 (void) crsetgroups(cr, 0, NULL);
2477 2523 break;
2478 2524 } /* switch on rpcflavor */
2479 2525
2480 2526 /*
2481 2527 * Even if anon access is disallowed via ex_anon == -1, we allow
2482 2528 * this access if anon_ok is set. So set creds to the default
2483 2529 * "nobody" id.
2484 2530 */
2485 2531
2486 2532 if (anon_res != 0) {
2487 2533 cmn_err(CE_NOTE,
2488 2534 "nfs_server: client %s%ssent wrong "
2489 2535 "authentication for %s",
2490 2536 client_name(req), client_addr(req, buf),
2491 2537 exi->exi_export.ex_path ?
2492 2538 exi->exi_export.ex_path : "?");
2493 2539 return (0);
2494 2540 }
2495 2541
2496 2542 return (1);
2497 2543 }
2498 2544
2499 2545
2500 2546 static char *
2501 2547 client_name(struct svc_req *req)
2502 2548 {
2503 2549 char *hostname = NULL;
2504 2550
2505 2551 /*
2506 2552 * If it's a Unix cred then use the
2507 2553 * hostname from the credential.
2508 2554 */
2509 2555 if (req->rq_cred.oa_flavor == AUTH_UNIX) {
2510 2556 hostname = ((struct authunix_parms *)
2511 2557 req->rq_clntcred)->aup_machname;
2512 2558 }
2513 2559 if (hostname == NULL)
2514 2560 hostname = "";
2515 2561
2516 2562 return (hostname);
2517 2563 }
2518 2564
2519 2565 static char *
2520 2566 client_addr(struct svc_req *req, char *buf)
2521 2567 {
2522 2568 struct sockaddr *ca;
2523 2569 uchar_t *b;
2524 2570 char *frontspace = "";
2525 2571
2526 2572 /*
2527 2573 * We assume we are called in tandem with client_name and the
2528 2574 * format string looks like "...client %s%sblah blah..."
2529 2575 *
2530 2576 * If it's a Unix cred then client_name returned
2531 2577 * a host name, so we need insert a space between host name
2532 2578 * and IP address.
2533 2579 */
2534 2580 if (req->rq_cred.oa_flavor == AUTH_UNIX)
2535 2581 frontspace = " ";
2536 2582
2537 2583 /*
2538 2584 * Convert the caller's IP address to a dotted string
2539 2585 */
2540 2586 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2541 2587
2542 2588 if (ca->sa_family == AF_INET) {
2543 2589 b = (uchar_t *)&((struct sockaddr_in *)ca)->sin_addr;
2544 2590 (void) sprintf(buf, "%s(%d.%d.%d.%d) ", frontspace,
2545 2591 b[0] & 0xFF, b[1] & 0xFF, b[2] & 0xFF, b[3] & 0xFF);
2546 2592 } else if (ca->sa_family == AF_INET6) {
2547 2593 struct sockaddr_in6 *sin6;
2548 2594 sin6 = (struct sockaddr_in6 *)ca;
2549 2595 (void) kinet_ntop6((uchar_t *)&sin6->sin6_addr,
2550 2596 buf, INET6_ADDRSTRLEN);
2551 2597
2552 2598 } else {
2553 2599
2554 2600 /*
2555 2601 * No IP address to print. If there was a host name
2556 2602 * printed, then we print a space.
2557 2603 */
2558 2604 (void) sprintf(buf, frontspace);
2559 2605 }
2560 2606
|
↓ open down ↓ |
573 lines elided |
↑ open up ↑ |
2561 2607 return (buf);
2562 2608 }
2563 2609
2564 2610 /*
2565 2611 * NFS Server initialization routine. This routine should only be called
2566 2612 * once. It performs the following tasks:
2567 2613 * - Call sub-initialization routines (localize access to variables)
2568 2614 * - Initialize all locks
2569 2615 * - initialize the version 3 write verifier
2570 2616 */
2571 -int
2617 +void
2572 2618 nfs_srvinit(void)
2573 2619 {
2574 - int error;
2620 + /* NFS server zone-specific global variables */
2621 + zone_key_create(&nfssrv_zone_key, nfs_srv_zone_init,
2622 + NULL, nfs_srv_zone_fini);
2575 2623
2576 - error = nfs_exportinit();
2577 - if (error != 0)
2578 - return (error);
2579 - error = rfs4_srvrinit();
2580 - if (error != 0) {
2581 - nfs_exportfini();
2582 - return (error);
2583 - }
2624 + nfs_exportinit();
2584 2625 rfs_srvrinit();
2585 2626 rfs3_srvrinit();
2627 + rfs4_srvrinit();
2586 2628 nfsauth_init();
2587 -
2588 - /* Init the stuff to control start/stop */
2589 - nfs_server_upordown = NFS_SERVER_STOPPED;
2590 - mutex_init(&nfs_server_upordown_lock, NULL, MUTEX_DEFAULT, NULL);
2591 - cv_init(&nfs_server_upordown_cv, NULL, CV_DEFAULT, NULL);
2592 - mutex_init(&rdma_wait_mutex, NULL, MUTEX_DEFAULT, NULL);
2593 - cv_init(&rdma_wait_cv, NULL, CV_DEFAULT, NULL);
2594 -
2595 - return (0);
2596 2629 }
2597 2630
2598 2631 /*
2599 2632 * NFS Server finalization routine. This routine is called to cleanup the
2600 2633 * initialization work previously performed if the NFS server module could
2601 2634 * not be loaded correctly.
2602 2635 */
2603 2636 void
2604 2637 nfs_srvfini(void)
2605 2638 {
2606 2639 nfsauth_fini();
2640 + rfs4_srvrfini();
2607 2641 rfs3_srvrfini();
2608 2642 rfs_srvrfini();
2609 2643 nfs_exportfini();
2610 2644
2611 - mutex_destroy(&nfs_server_upordown_lock);
2612 - cv_destroy(&nfs_server_upordown_cv);
2613 - mutex_destroy(&rdma_wait_mutex);
2614 - cv_destroy(&rdma_wait_cv);
2645 + (void) zone_key_delete(nfssrv_zone_key);
2615 2646 }
2616 2647
2648 +/* ARGSUSED */
2649 +static void *
2650 +nfs_srv_zone_init(zoneid_t zoneid)
2651 +{
2652 + nfs_globals_t *ng;
2653 +
2654 + ng = kmem_zalloc(sizeof (*ng), KM_SLEEP);
2655 +
2656 + ng->nfs_versmin = NFS_VERSMIN_DEFAULT;
2657 + ng->nfs_versmax = NFS_VERSMAX_DEFAULT;
2658 +
2659 + /* Init the stuff to control start/stop */
2660 + ng->nfs_server_upordown = NFS_SERVER_STOPPED;
2661 + mutex_init(&ng->nfs_server_upordown_lock, NULL, MUTEX_DEFAULT, NULL);
2662 + cv_init(&ng->nfs_server_upordown_cv, NULL, CV_DEFAULT, NULL);
2663 + mutex_init(&ng->rdma_wait_mutex, NULL, MUTEX_DEFAULT, NULL);
2664 + cv_init(&ng->rdma_wait_cv, NULL, CV_DEFAULT, NULL);
2665 +
2666 + return (ng);
2667 +}
2668 +
2669 +/* ARGSUSED */
2670 +static void
2671 +nfs_srv_zone_fini(zoneid_t zoneid, void *data)
2672 +{
2673 + nfs_globals_t *ng;
2674 +
2675 + ng = (nfs_globals_t *)data;
2676 + mutex_destroy(&ng->nfs_server_upordown_lock);
2677 + cv_destroy(&ng->nfs_server_upordown_cv);
2678 + mutex_destroy(&ng->rdma_wait_mutex);
2679 + cv_destroy(&ng->rdma_wait_cv);
2680 +
2681 + kmem_free(ng, sizeof (*ng));
2682 +}
2683 +
2617 2684 /*
2618 2685 * Set up an iovec array of up to cnt pointers.
2619 2686 */
2620 -
2621 2687 void
2622 2688 mblk_to_iov(mblk_t *m, int cnt, struct iovec *iovp)
2623 2689 {
2624 2690 while (m != NULL && cnt-- > 0) {
2625 2691 iovp->iov_base = (caddr_t)m->b_rptr;
2626 2692 iovp->iov_len = (m->b_wptr - m->b_rptr);
2627 2693 iovp++;
2628 2694 m = m->b_cont;
2629 2695 }
2630 2696 }
2631 2697
2632 2698 /*
2633 2699 * Common code between NFS Version 2 and NFS Version 3 for the public
2634 2700 * filehandle multicomponent lookups.
2635 2701 */
2636 2702
2637 2703 /*
2638 2704 * Public filehandle evaluation of a multi-component lookup, following
2639 2705 * symbolic links, if necessary. This may result in a vnode in another
2640 2706 * filesystem, which is OK as long as the other filesystem is exported.
2641 2707 *
2642 2708 * Note that the exi will be set either to NULL or a new reference to the
2643 2709 * exportinfo struct that corresponds to the vnode of the multi-component path.
2644 2710 * It is the callers responsibility to release this reference.
2645 2711 */
2646 2712 int
2647 2713 rfs_publicfh_mclookup(char *p, vnode_t *dvp, cred_t *cr, vnode_t **vpp,
2648 2714 struct exportinfo **exi, struct sec_ol *sec)
2649 2715 {
2650 2716 int pathflag;
2651 2717 vnode_t *mc_dvp = NULL;
2652 2718 vnode_t *realvp;
2653 2719 int error;
2654 2720
2655 2721 *exi = NULL;
2656 2722
2657 2723 /*
2658 2724 * check if the given path is a url or native path. Since p is
2659 2725 * modified by MCLpath(), it may be empty after returning from
2660 2726 * there, and should be checked.
2661 2727 */
2662 2728 if ((pathflag = MCLpath(&p)) == -1)
2663 2729 return (EIO);
2664 2730
2665 2731 /*
2666 2732 * If pathflag is SECURITY_QUERY, turn the SEC_QUERY bit
2667 2733 * on in sec->sec_flags. This bit will later serve as an
2668 2734 * indication in makefh_ol() or makefh3_ol() to overload the
2669 2735 * filehandle to contain the sec modes used by the server for
2670 2736 * the path.
2671 2737 */
2672 2738 if (pathflag == SECURITY_QUERY) {
2673 2739 if ((sec->sec_index = (uint_t)(*p)) > 0) {
2674 2740 sec->sec_flags |= SEC_QUERY;
2675 2741 p++;
2676 2742 if ((pathflag = MCLpath(&p)) == -1)
2677 2743 return (EIO);
2678 2744 } else {
2679 2745 cmn_err(CE_NOTE,
2680 2746 "nfs_server: invalid security index %d, "
2681 2747 "violating WebNFS SNEGO protocol.", sec->sec_index);
2682 2748 return (EIO);
2683 2749 }
2684 2750 }
2685 2751
2686 2752 if (p[0] == '\0') {
2687 2753 error = ENOENT;
2688 2754 goto publicfh_done;
2689 2755 }
2690 2756
2691 2757 error = rfs_pathname(p, &mc_dvp, vpp, dvp, cr, pathflag);
2692 2758
2693 2759 /*
2694 2760 * If name resolves to "/" we get EINVAL since we asked for
2695 2761 * the vnode of the directory that the file is in. Try again
2696 2762 * with NULL directory vnode.
2697 2763 */
2698 2764 if (error == EINVAL) {
2699 2765 error = rfs_pathname(p, NULL, vpp, dvp, cr, pathflag);
2700 2766 if (!error) {
2701 2767 ASSERT(*vpp != NULL);
2702 2768 if ((*vpp)->v_type == VDIR) {
2703 2769 VN_HOLD(*vpp);
2704 2770 mc_dvp = *vpp;
2705 2771 } else {
2706 2772 /*
2707 2773 * This should not happen, the filesystem is
2708 2774 * in an inconsistent state. Fail the lookup
2709 2775 * at this point.
2710 2776 */
2711 2777 VN_RELE(*vpp);
2712 2778 error = EINVAL;
2713 2779 }
2714 2780 }
2715 2781 }
2716 2782
2717 2783 if (error)
2718 2784 goto publicfh_done;
2719 2785
2720 2786 if (*vpp == NULL) {
2721 2787 error = ENOENT;
2722 2788 goto publicfh_done;
2723 2789 }
2724 2790
2725 2791 ASSERT(mc_dvp != NULL);
2726 2792 ASSERT(*vpp != NULL);
2727 2793
2728 2794 if ((*vpp)->v_type == VDIR) {
2729 2795 do {
2730 2796 /*
2731 2797 * *vpp may be an AutoFS node, so we perform
2732 2798 * a VOP_ACCESS() to trigger the mount of the intended
2733 2799 * filesystem, so we can perform the lookup in the
2734 2800 * intended filesystem.
2735 2801 */
2736 2802 (void) VOP_ACCESS(*vpp, 0, 0, cr, NULL);
2737 2803
2738 2804 /*
2739 2805 * If vnode is covered, get the
2740 2806 * the topmost vnode.
2741 2807 */
2742 2808 if (vn_mountedvfs(*vpp) != NULL) {
2743 2809 error = traverse(vpp);
2744 2810 if (error) {
2745 2811 VN_RELE(*vpp);
2746 2812 goto publicfh_done;
2747 2813 }
2748 2814 }
2749 2815
2750 2816 if (VOP_REALVP(*vpp, &realvp, NULL) == 0 &&
2751 2817 realvp != *vpp) {
2752 2818 /*
2753 2819 * If realvp is different from *vpp
2754 2820 * then release our reference on *vpp, so that
2755 2821 * the export access check be performed on the
2756 2822 * real filesystem instead.
2757 2823 */
2758 2824 VN_HOLD(realvp);
2759 2825 VN_RELE(*vpp);
2760 2826 *vpp = realvp;
2761 2827 } else {
2762 2828 break;
2763 2829 }
2764 2830 /* LINTED */
2765 2831 } while (TRUE);
2766 2832
2767 2833 /*
2768 2834 * Let nfs_vptexi() figure what the real parent is.
2769 2835 */
2770 2836 VN_RELE(mc_dvp);
2771 2837 mc_dvp = NULL;
2772 2838
2773 2839 } else {
2774 2840 /*
2775 2841 * If vnode is covered, get the
2776 2842 * the topmost vnode.
2777 2843 */
2778 2844 if (vn_mountedvfs(mc_dvp) != NULL) {
2779 2845 error = traverse(&mc_dvp);
2780 2846 if (error) {
2781 2847 VN_RELE(*vpp);
2782 2848 goto publicfh_done;
2783 2849 }
2784 2850 }
2785 2851
2786 2852 if (VOP_REALVP(mc_dvp, &realvp, NULL) == 0 &&
2787 2853 realvp != mc_dvp) {
2788 2854 /*
2789 2855 * *vpp is a file, obtain realvp of the parent
2790 2856 * directory vnode.
2791 2857 */
2792 2858 VN_HOLD(realvp);
2793 2859 VN_RELE(mc_dvp);
2794 2860 mc_dvp = realvp;
2795 2861 }
2796 2862 }
2797 2863
2798 2864 /*
2799 2865 * The pathname may take us from the public filesystem to another.
2800 2866 * If that's the case then just set the exportinfo to the new export
2801 2867 * and build filehandle for it. Thanks to per-access checking there's
2802 2868 * no security issues with doing this. If the client is not allowed
2803 2869 * access to this new export then it will get an access error when it
2804 2870 * tries to use the filehandle
2805 2871 */
2806 2872 if (error = nfs_check_vpexi(mc_dvp, *vpp, kcred, exi)) {
2807 2873 VN_RELE(*vpp);
2808 2874 goto publicfh_done;
2809 2875 }
2810 2876
2811 2877 /*
2812 2878 * Not allowed access to pseudo exports.
2813 2879 */
2814 2880 if (PSEUDO(*exi)) {
2815 2881 error = ENOENT;
2816 2882 VN_RELE(*vpp);
2817 2883 goto publicfh_done;
2818 2884 }
2819 2885
2820 2886 /*
2821 2887 * Do a lookup for the index file. We know the index option doesn't
2822 2888 * allow paths through handling in the share command, so mc_dvp will
2823 2889 * be the parent for the index file vnode, if its present. Use
2824 2890 * temporary pointers to preserve and reuse the vnode pointers of the
2825 2891 * original directory in case there's no index file. Note that the
2826 2892 * index file is a native path, and should not be interpreted by
2827 2893 * the URL parser in rfs_pathname()
2828 2894 */
2829 2895 if (((*exi)->exi_export.ex_flags & EX_INDEX) &&
2830 2896 ((*vpp)->v_type == VDIR) && (pathflag == URLPATH)) {
2831 2897 vnode_t *tvp, *tmc_dvp; /* temporary vnode pointers */
2832 2898
2833 2899 tmc_dvp = mc_dvp;
2834 2900 mc_dvp = tvp = *vpp;
2835 2901
2836 2902 error = rfs_pathname((*exi)->exi_export.ex_index, NULL, vpp,
2837 2903 mc_dvp, cr, NATIVEPATH);
2838 2904
2839 2905 if (error == ENOENT) {
2840 2906 *vpp = tvp;
2841 2907 mc_dvp = tmc_dvp;
2842 2908 error = 0;
2843 2909 } else { /* ok or error other than ENOENT */
2844 2910 if (tmc_dvp)
2845 2911 VN_RELE(tmc_dvp);
2846 2912 if (error)
|
↓ open down ↓ |
216 lines elided |
↑ open up ↑ |
2847 2913 goto publicfh_done;
2848 2914
2849 2915 /*
2850 2916 * Found a valid vp for index "filename". Sanity check
2851 2917 * for odd case where a directory is provided as index
2852 2918 * option argument and leads us to another filesystem
2853 2919 */
2854 2920
2855 2921 /* Release the reference on the old exi value */
2856 2922 ASSERT(*exi != NULL);
2857 - exi_rele(*exi);
2923 + exi_rele(exi);
2858 2924
2859 2925 if (error = nfs_check_vpexi(mc_dvp, *vpp, kcred, exi)) {
2860 2926 VN_RELE(*vpp);
2861 2927 goto publicfh_done;
2862 2928 }
2863 2929 }
2864 2930 }
2865 2931
2866 2932 publicfh_done:
2867 2933 if (mc_dvp)
2868 2934 VN_RELE(mc_dvp);
2869 2935
2870 2936 return (error);
2871 2937 }
2872 2938
2873 2939 /*
2874 2940 * Evaluate a multi-component path
2875 2941 */
2876 2942 int
2877 2943 rfs_pathname(
2878 2944 char *path, /* pathname to evaluate */
2879 2945 vnode_t **dirvpp, /* ret for ptr to parent dir vnode */
2880 2946 vnode_t **compvpp, /* ret for ptr to component vnode */
2881 2947 vnode_t *startdvp, /* starting vnode */
2882 2948 cred_t *cr, /* user's credential */
2883 2949 int pathflag) /* flag to identify path, e.g. URL */
2884 2950 {
2885 2951 char namebuf[TYPICALMAXPATHLEN];
|
↓ open down ↓ |
18 lines elided |
↑ open up ↑ |
2886 2952 struct pathname pn;
2887 2953 int error;
2888 2954
2889 2955 /*
2890 2956 * If pathname starts with '/', then set startdvp to root.
2891 2957 */
2892 2958 if (*path == '/') {
2893 2959 while (*path == '/')
2894 2960 path++;
2895 2961
2896 - startdvp = rootdir;
2962 + startdvp = ZONE_ROOTVP();
2897 2963 }
2898 2964
2899 2965 error = pn_get_buf(path, UIO_SYSSPACE, &pn, namebuf, sizeof (namebuf));
2900 2966 if (error == 0) {
2901 2967 /*
2902 2968 * Call the URL parser for URL paths to modify the original
2903 2969 * string to handle any '%' encoded characters that exist.
2904 2970 * Done here to avoid an extra bcopy in the lookup.
2905 2971 * We need to be careful about pathlen's. We know that
2906 2972 * rfs_pathname() is called with a non-empty path. However,
2907 2973 * it could be emptied due to the path simply being all /'s,
2908 2974 * which is valid to proceed with the lookup, or due to the
|
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
2909 2975 * URL parser finding an encoded null character at the
2910 2976 * beginning of path which should not proceed with the lookup.
2911 2977 */
2912 2978 if (pn.pn_pathlen != 0 && pathflag == URLPATH) {
2913 2979 URLparse(pn.pn_path);
2914 2980 if ((pn.pn_pathlen = strlen(pn.pn_path)) == 0)
2915 2981 return (ENOENT);
2916 2982 }
2917 2983 VN_HOLD(startdvp);
2918 2984 error = lookuppnvp(&pn, NULL, NO_FOLLOW, dirvpp, compvpp,
2919 - rootdir, startdvp, cr);
2985 + ZONE_ROOTVP(), startdvp, cr);
2920 2986 }
2921 2987 if (error == ENAMETOOLONG) {
2922 2988 /*
2923 2989 * This thread used a pathname > TYPICALMAXPATHLEN bytes long.
2924 2990 */
2925 2991 if (error = pn_get(path, UIO_SYSSPACE, &pn))
2926 2992 return (error);
2927 2993 if (pn.pn_pathlen != 0 && pathflag == URLPATH) {
2928 2994 URLparse(pn.pn_path);
2929 2995 if ((pn.pn_pathlen = strlen(pn.pn_path)) == 0) {
2930 2996 pn_free(&pn);
2931 2997 return (ENOENT);
2932 2998 }
2933 2999 }
2934 3000 VN_HOLD(startdvp);
2935 3001 error = lookuppnvp(&pn, NULL, NO_FOLLOW, dirvpp, compvpp,
2936 - rootdir, startdvp, cr);
3002 + ZONE_ROOTVP(), startdvp, cr);
2937 3003 pn_free(&pn);
2938 3004 }
2939 3005
2940 3006 return (error);
2941 3007 }
2942 3008
2943 3009 /*
2944 3010 * Adapt the multicomponent lookup path depending on the pathtype
2945 3011 */
2946 3012 static int
2947 3013 MCLpath(char **path)
2948 3014 {
2949 3015 unsigned char c = (unsigned char)**path;
2950 3016
2951 3017 /*
2952 3018 * If the MCL path is between 0x20 and 0x7E (graphic printable
2953 3019 * character of the US-ASCII coded character set), its a URL path,
2954 3020 * per RFC 1738.
2955 3021 */
2956 3022 if (c >= 0x20 && c <= 0x7E)
2957 3023 return (URLPATH);
2958 3024
2959 3025 /*
2960 3026 * If the first octet of the MCL path is not an ASCII character
2961 3027 * then it must be interpreted as a tag value that describes the
2962 3028 * format of the remaining octets of the MCL path.
2963 3029 *
2964 3030 * If the first octet of the MCL path is 0x81 it is a query
2965 3031 * for the security info.
2966 3032 */
2967 3033 switch (c) {
2968 3034 case 0x80: /* native path, i.e. MCL via mount protocol */
2969 3035 (*path)++;
2970 3036 return (NATIVEPATH);
2971 3037 case 0x81: /* security query */
2972 3038 (*path)++;
2973 3039 return (SECURITY_QUERY);
2974 3040 default:
2975 3041 return (-1);
2976 3042 }
2977 3043 }
2978 3044
2979 3045 #define fromhex(c) ((c >= '0' && c <= '9') ? (c - '0') : \
2980 3046 ((c >= 'A' && c <= 'F') ? (c - 'A' + 10) :\
2981 3047 ((c >= 'a' && c <= 'f') ? (c - 'a' + 10) : 0)))
2982 3048
2983 3049 /*
2984 3050 * The implementation of URLparse guarantees that the final string will
2985 3051 * fit in the original one. Replaces '%' occurrences followed by 2 characters
2986 3052 * with its corresponding hexadecimal character.
2987 3053 */
2988 3054 static void
2989 3055 URLparse(char *str)
2990 3056 {
2991 3057 char *p, *q;
2992 3058
2993 3059 p = q = str;
2994 3060 while (*p) {
2995 3061 *q = *p;
2996 3062 if (*p++ == '%') {
2997 3063 if (*p) {
2998 3064 *q = fromhex(*p) * 16;
2999 3065 p++;
3000 3066 if (*p) {
3001 3067 *q += fromhex(*p);
3002 3068 p++;
3003 3069 }
3004 3070 }
3005 3071 }
3006 3072 q++;
3007 3073 }
3008 3074 *q = '\0';
3009 3075 }
3010 3076
3011 3077
3012 3078 /*
3013 3079 * Get the export information for the lookup vnode, and verify its
3014 3080 * useable.
3015 3081 */
3016 3082 int
3017 3083 nfs_check_vpexi(vnode_t *mc_dvp, vnode_t *vp, cred_t *cr,
3018 3084 struct exportinfo **exi)
3019 3085 {
3020 3086 int walk;
3021 3087 int error = 0;
3022 3088
3023 3089 *exi = nfs_vptoexi(mc_dvp, vp, cr, &walk, NULL, FALSE);
3024 3090 if (*exi == NULL)
3025 3091 error = EACCES;
3026 3092 else {
3027 3093 /*
3028 3094 * If nosub is set for this export then
3029 3095 * a lookup relative to the public fh
|
↓ open down ↓ |
83 lines elided |
↑ open up ↑ |
3030 3096 * must not terminate below the
3031 3097 * exported directory.
3032 3098 */
3033 3099 if ((*exi)->exi_export.ex_flags & EX_NOSUB && walk > 0)
3034 3100 error = EACCES;
3035 3101 }
3036 3102
3037 3103 return (error);
3038 3104 }
3039 3105
3040 -/*
3041 - * Do the main work of handling HA-NFSv4 Resource Group failover on
3042 - * Sun Cluster.
3043 - * We need to detect whether any RG admin paths have been added or removed,
3044 - * and adjust resources accordingly.
3045 - * Currently we're using a very inefficient algorithm, ~ 2 * O(n**2). In
3046 - * order to scale, the list and array of paths need to be held in more
3047 - * suitable data structures.
3048 - */
3049 -static void
3050 -hanfsv4_failover(void)
3051 -{
3052 - int i, start_grace, numadded_paths = 0;
3053 - char **added_paths = NULL;
3054 - rfs4_dss_path_t *dss_path;
3055 -
3056 - /*
3057 - * Note: currently, rfs4_dss_pathlist cannot be NULL, since
3058 - * it will always include an entry for NFS4_DSS_VAR_DIR. If we
3059 - * make the latter dynamically specified too, the following will
3060 - * need to be adjusted.
3061 - */
3062 -
3063 - /*
3064 - * First, look for removed paths: RGs that have been failed-over
3065 - * away from this node.
3066 - * Walk the "currently-serving" rfs4_dss_pathlist and, for each
3067 - * path, check if it is on the "passed-in" rfs4_dss_newpaths array
3068 - * from nfsd. If not, that RG path has been removed.
3069 - *
3070 - * Note that nfsd has sorted rfs4_dss_newpaths for us, and removed
3071 - * any duplicates.
3072 - */
3073 - dss_path = rfs4_dss_pathlist;
3074 - do {
3075 - int found = 0;
3076 - char *path = dss_path->path;
3077 -
3078 - /* used only for non-HA so may not be removed */
3079 - if (strcmp(path, NFS4_DSS_VAR_DIR) == 0) {
3080 - dss_path = dss_path->next;
3081 - continue;
3082 - }
3083 -
3084 - for (i = 0; i < rfs4_dss_numnewpaths; i++) {
3085 - int cmpret;
3086 - char *newpath = rfs4_dss_newpaths[i];
3087 -
3088 - /*
3089 - * Since nfsd has sorted rfs4_dss_newpaths for us,
3090 - * once the return from strcmp is negative we know
3091 - * we've passed the point where "path" should be,
3092 - * and can stop searching: "path" has been removed.
3093 - */
3094 - cmpret = strcmp(path, newpath);
3095 - if (cmpret < 0)
3096 - break;
3097 - if (cmpret == 0) {
3098 - found = 1;
3099 - break;
3100 - }
3101 - }
3102 -
3103 - if (found == 0) {
3104 - unsigned index = dss_path->index;
3105 - rfs4_servinst_t *sip = dss_path->sip;
3106 - rfs4_dss_path_t *path_next = dss_path->next;
3107 -
3108 - /*
3109 - * This path has been removed.
3110 - * We must clear out the servinst reference to
3111 - * it, since it's now owned by another
3112 - * node: we should not attempt to touch it.
3113 - */
3114 - ASSERT(dss_path == sip->dss_paths[index]);
3115 - sip->dss_paths[index] = NULL;
3116 -
3117 - /* remove from "currently-serving" list, and destroy */
3118 - remque(dss_path);
3119 - /* allow for NUL */
3120 - kmem_free(dss_path->path, strlen(dss_path->path) + 1);
3121 - kmem_free(dss_path, sizeof (rfs4_dss_path_t));
3122 -
3123 - dss_path = path_next;
3124 - } else {
3125 - /* path was found; not removed */
3126 - dss_path = dss_path->next;
3127 - }
3128 - } while (dss_path != rfs4_dss_pathlist);
3129 -
3130 - /*
3131 - * Now, look for added paths: RGs that have been failed-over
3132 - * to this node.
3133 - * Walk the "passed-in" rfs4_dss_newpaths array from nfsd and,
3134 - * for each path, check if it is on the "currently-serving"
3135 - * rfs4_dss_pathlist. If not, that RG path has been added.
3136 - *
3137 - * Note: we don't do duplicate detection here; nfsd does that for us.
3138 - *
3139 - * Note: numadded_paths <= rfs4_dss_numnewpaths, which gives us
3140 - * an upper bound for the size needed for added_paths[numadded_paths].
3141 - */
3142 -
3143 - /* probably more space than we need, but guaranteed to be enough */
3144 - if (rfs4_dss_numnewpaths > 0) {
3145 - size_t sz = rfs4_dss_numnewpaths * sizeof (char *);
3146 - added_paths = kmem_zalloc(sz, KM_SLEEP);
3147 - }
3148 -
3149 - /* walk the "passed-in" rfs4_dss_newpaths array from nfsd */
3150 - for (i = 0; i < rfs4_dss_numnewpaths; i++) {
3151 - int found = 0;
3152 - char *newpath = rfs4_dss_newpaths[i];
3153 -
3154 - dss_path = rfs4_dss_pathlist;
3155 - do {
3156 - char *path = dss_path->path;
3157 -
3158 - /* used only for non-HA */
3159 - if (strcmp(path, NFS4_DSS_VAR_DIR) == 0) {
3160 - dss_path = dss_path->next;
3161 - continue;
3162 - }
3163 -
3164 - if (strncmp(path, newpath, strlen(path)) == 0) {
3165 - found = 1;
3166 - break;
3167 - }
3168 -
3169 - dss_path = dss_path->next;
3170 - } while (dss_path != rfs4_dss_pathlist);
3171 -
3172 - if (found == 0) {
3173 - added_paths[numadded_paths] = newpath;
3174 - numadded_paths++;
3175 - }
3176 - }
3177 -
3178 - /* did we find any added paths? */
3179 - if (numadded_paths > 0) {
3180 - /* create a new server instance, and start its grace period */
3181 - start_grace = 1;
3182 - rfs4_servinst_create(start_grace, numadded_paths, added_paths);
3183 -
3184 - /* read in the stable storage state from these paths */
3185 - rfs4_dss_readstate(numadded_paths, added_paths);
3186 -
3187 - /*
3188 - * Multiple failovers during a grace period will cause
3189 - * clients of the same resource group to be partitioned
3190 - * into different server instances, with different
3191 - * grace periods. Since clients of the same resource
3192 - * group must be subject to the same grace period,
3193 - * we need to reset all currently active grace periods.
3194 - */
3195 - rfs4_grace_reset_all();
3196 - }
3197 -
3198 - if (rfs4_dss_numnewpaths > 0)
3199 - kmem_free(added_paths, rfs4_dss_numnewpaths * sizeof (char *));
3200 -}
3201 -
3202 3106 /*
3203 3107 * Used by NFSv3 and NFSv4 server to query label of
3204 3108 * a pathname component during lookup/access ops.
3205 3109 */
3206 3110 ts_label_t *
3207 3111 nfs_getflabel(vnode_t *vp, struct exportinfo *exi)
3208 3112 {
3209 3113 zone_t *zone;
3210 3114 ts_label_t *zone_label;
3211 3115 char *path;
3212 3116
3213 3117 mutex_enter(&vp->v_lock);
3214 3118 if (vp->v_path != vn_vpath_empty) {
3215 3119 zone = zone_find_by_any_path(vp->v_path, B_FALSE);
3216 3120 mutex_exit(&vp->v_lock);
3217 3121 } else {
3218 3122 /*
3219 3123 * v_path not cached. Fall back on pathname of exported
3220 3124 * file system as we rely on pathname from which we can
3221 3125 * derive a label. The exported file system portion of
3222 3126 * path is sufficient to obtain a label.
3223 3127 */
3224 3128 path = exi->exi_export.ex_path;
3225 3129 if (path == NULL) {
3226 3130 mutex_exit(&vp->v_lock);
3227 3131 return (NULL);
3228 3132 }
3229 3133 zone = zone_find_by_any_path(path, B_FALSE);
3230 3134 mutex_exit(&vp->v_lock);
3231 3135 }
3232 3136 /*
3233 3137 * Caller has verified that the file is either
3234 3138 * exported or visible. So if the path falls in
3235 3139 * global zone, admin_low is returned; otherwise
3236 3140 * the zone's label is returned.
3237 3141 */
3238 3142 zone_label = zone->zone_slabel;
3239 3143 label_hold(zone_label);
3240 3144 zone_rele(zone);
3241 3145 return (zone_label);
3242 3146 }
3243 3147
3244 3148 /*
3245 3149 * TX NFS routine used by NFSv3 and NFSv4 to do label check
3246 3150 * on client label and server's file object lable.
3247 3151 */
3248 3152 boolean_t
3249 3153 do_rfs_label_check(bslabel_t *clabel, vnode_t *vp, int flag,
3250 3154 struct exportinfo *exi)
3251 3155 {
3252 3156 bslabel_t *slabel;
3253 3157 ts_label_t *tslabel;
3254 3158 boolean_t result;
3255 3159
3256 3160 if ((tslabel = nfs_getflabel(vp, exi)) == NULL) {
3257 3161 return (B_FALSE);
3258 3162 }
3259 3163 slabel = label2bslabel(tslabel);
3260 3164 DTRACE_PROBE4(tx__rfs__log__info__labelcheck, char *,
3261 3165 "comparing server's file label(1) with client label(2) (vp(3))",
3262 3166 bslabel_t *, slabel, bslabel_t *, clabel, vnode_t *, vp);
3263 3167
3264 3168 if (flag == EQUALITY_CHECK)
3265 3169 result = blequal(clabel, slabel);
3266 3170 else
3267 3171 result = bldominates(clabel, slabel);
3268 3172 label_rele(tslabel);
3269 3173 return (result);
3270 3174 }
3271 3175
3272 3176 /*
3273 3177 * Callback function to return the loaned buffers.
3274 3178 * Calls VOP_RETZCBUF() only after all uio_iov[]
3275 3179 * buffers are returned. nu_ref maintains the count.
3276 3180 */
3277 3181 void
3278 3182 rfs_free_xuio(void *free_arg)
3279 3183 {
3280 3184 uint_t ref;
3281 3185 nfs_xuio_t *nfsuiop = (nfs_xuio_t *)free_arg;
3282 3186
3283 3187 ref = atomic_dec_uint_nv(&nfsuiop->nu_ref);
3284 3188
3285 3189 /*
3286 3190 * Call VOP_RETZCBUF() only when all the iov buffers
3287 3191 * are sent OTW.
3288 3192 */
3289 3193 if (ref != 0)
3290 3194 return;
3291 3195
3292 3196 if (((uio_t *)nfsuiop)->uio_extflg & UIO_XUIO) {
3293 3197 (void) VOP_RETZCBUF(nfsuiop->nu_vp, (xuio_t *)free_arg, NULL,
3294 3198 NULL);
3295 3199 VN_RELE(nfsuiop->nu_vp);
3296 3200 }
3297 3201
3298 3202 kmem_cache_free(nfs_xuio_cache, free_arg);
3299 3203 }
3300 3204
3301 3205 xuio_t *
3302 3206 rfs_setup_xuio(vnode_t *vp)
3303 3207 {
3304 3208 nfs_xuio_t *nfsuiop;
3305 3209
3306 3210 nfsuiop = kmem_cache_alloc(nfs_xuio_cache, KM_SLEEP);
3307 3211
3308 3212 bzero(nfsuiop, sizeof (nfs_xuio_t));
3309 3213 nfsuiop->nu_vp = vp;
3310 3214
3311 3215 /*
3312 3216 * ref count set to 1. more may be added
3313 3217 * if multiple mblks refer to multiple iov's.
3314 3218 * This is done in uio_to_mblk().
3315 3219 */
3316 3220
3317 3221 nfsuiop->nu_ref = 1;
3318 3222
3319 3223 nfsuiop->nu_frtn.free_func = rfs_free_xuio;
3320 3224 nfsuiop->nu_frtn.free_arg = (char *)nfsuiop;
3321 3225
3322 3226 nfsuiop->nu_uio.xu_type = UIOTYPE_ZEROCOPY;
3323 3227
3324 3228 return (&nfsuiop->nu_uio);
3325 3229 }
3326 3230
3327 3231 mblk_t *
3328 3232 uio_to_mblk(uio_t *uiop)
3329 3233 {
3330 3234 struct iovec *iovp;
3331 3235 int i;
3332 3236 mblk_t *mp, *mp1;
3333 3237 nfs_xuio_t *nfsuiop = (nfs_xuio_t *)uiop;
3334 3238
3335 3239 if (uiop->uio_iovcnt == 0)
3336 3240 return (NULL);
3337 3241
3338 3242 iovp = uiop->uio_iov;
3339 3243 mp = mp1 = esballoca((uchar_t *)iovp->iov_base, iovp->iov_len,
3340 3244 BPRI_MED, &nfsuiop->nu_frtn);
3341 3245 ASSERT(mp != NULL);
3342 3246
3343 3247 mp->b_wptr += iovp->iov_len;
3344 3248 mp->b_datap->db_type = M_DATA;
3345 3249
3346 3250 for (i = 1; i < uiop->uio_iovcnt; i++) {
3347 3251 iovp = (uiop->uio_iov + i);
3348 3252
3349 3253 mp1->b_cont = esballoca(
3350 3254 (uchar_t *)iovp->iov_base, iovp->iov_len, BPRI_MED,
3351 3255 &nfsuiop->nu_frtn);
3352 3256
3353 3257 mp1 = mp1->b_cont;
3354 3258 ASSERT(mp1 != NULL);
3355 3259 mp1->b_wptr += iovp->iov_len;
3356 3260 mp1->b_datap->db_type = M_DATA;
3357 3261 }
3358 3262
3359 3263 nfsuiop->nu_ref = uiop->uio_iovcnt;
3360 3264
3361 3265 return (mp);
3362 3266 }
3363 3267
3364 3268 /*
3365 3269 * Allocate memory to hold data for a read request of len bytes.
3366 3270 *
3367 3271 * We don't allocate buffers greater than kmem_max_cached in size to avoid
3368 3272 * allocating memory from the kmem_oversized arena. If we allocate oversized
3369 3273 * buffers, we incur heavy cross-call activity when freeing these large buffers
3370 3274 * in the TCP receive path. Note that we can't set b_wptr here since the
3371 3275 * length of the data returned may differ from the length requested when
3372 3276 * reading the end of a file; we set b_wptr in rfs_rndup_mblks() once the
3373 3277 * length of the read is known.
3374 3278 */
3375 3279 mblk_t *
3376 3280 rfs_read_alloc(uint_t len, struct iovec **iov, int *iovcnt)
3377 3281 {
3378 3282 struct iovec *iovarr;
3379 3283 mblk_t *mp, **mpp = ∓
3380 3284 size_t mpsize;
3381 3285 uint_t remain = len;
3382 3286 int i, err = 0;
3383 3287
3384 3288 *iovcnt = howmany(len, kmem_max_cached);
3385 3289
3386 3290 iovarr = kmem_alloc(*iovcnt * sizeof (struct iovec), KM_SLEEP);
3387 3291 *iov = iovarr;
3388 3292
3389 3293 for (i = 0; i < *iovcnt; remain -= mpsize, i++) {
3390 3294 ASSERT(remain <= len);
3391 3295 /*
3392 3296 * We roundup the size we allocate to a multiple of
3393 3297 * BYTES_PER_XDR_UNIT (4 bytes) so that the call to
3394 3298 * xdrmblk_putmblk() never fails.
3395 3299 */
3396 3300 ASSERT(kmem_max_cached % BYTES_PER_XDR_UNIT == 0);
3397 3301 mpsize = MIN(kmem_max_cached, remain);
3398 3302 *mpp = allocb_wait(RNDUP(mpsize), BPRI_MED, STR_NOSIG, &err);
3399 3303 ASSERT(*mpp != NULL);
3400 3304 ASSERT(err == 0);
3401 3305
3402 3306 iovarr[i].iov_base = (caddr_t)(*mpp)->b_rptr;
3403 3307 iovarr[i].iov_len = mpsize;
3404 3308 mpp = &(*mpp)->b_cont;
3405 3309 }
3406 3310 return (mp);
3407 3311 }
3408 3312
3409 3313 void
3410 3314 rfs_rndup_mblks(mblk_t *mp, uint_t len, int buf_loaned)
3411 3315 {
3412 3316 int i;
3413 3317 int alloc_err = 0;
3414 3318 mblk_t *rmp;
3415 3319 uint_t mpsize, remainder;
3416 3320
3417 3321 remainder = P2NPHASE(len, BYTES_PER_XDR_UNIT);
3418 3322
3419 3323 /*
3420 3324 * Non copy-reduction case. This function assumes that blocks were
3421 3325 * allocated in multiples of BYTES_PER_XDR_UNIT bytes, which makes this
3422 3326 * padding safe without bounds checking.
3423 3327 */
3424 3328 if (!buf_loaned) {
3425 3329 /*
3426 3330 * Set the size of each mblk in the chain until we've consumed
3427 3331 * the specified length for all but the last one.
3428 3332 */
3429 3333 while ((mpsize = MBLKSIZE(mp)) < len) {
3430 3334 ASSERT(mpsize % BYTES_PER_XDR_UNIT == 0);
3431 3335 mp->b_wptr += mpsize;
3432 3336 len -= mpsize;
3433 3337 mp = mp->b_cont;
3434 3338 ASSERT(mp != NULL);
3435 3339 }
3436 3340
3437 3341 ASSERT(len + remainder <= mpsize);
3438 3342 mp->b_wptr += len;
3439 3343 for (i = 0; i < remainder; i++)
3440 3344 *mp->b_wptr++ = '\0';
3441 3345 return;
3442 3346 }
3443 3347
3444 3348 /*
3445 3349 * No remainder mblk required.
3446 3350 */
3447 3351 if (remainder == 0)
3448 3352 return;
3449 3353
3450 3354 /*
3451 3355 * Get to the last mblk in the chain.
3452 3356 */
3453 3357 while (mp->b_cont != NULL)
3454 3358 mp = mp->b_cont;
3455 3359
3456 3360 /*
3457 3361 * In case of copy-reduction mblks, the size of the mblks are fixed
3458 3362 * and are of the size of the loaned buffers. Allocate a remainder
3459 3363 * mblk and chain it to the data buffers. This is sub-optimal, but not
3460 3364 * expected to happen commonly.
3461 3365 */
3462 3366 rmp = allocb_wait(remainder, BPRI_MED, STR_NOSIG, &alloc_err);
3463 3367 ASSERT(rmp != NULL);
3464 3368 ASSERT(alloc_err == 0);
3465 3369
3466 3370 for (i = 0; i < remainder; i++)
3467 3371 *rmp->b_wptr++ = '\0';
3468 3372
3469 3373 rmp->b_datap->db_type = M_DATA;
3470 3374 mp->b_cont = rmp;
3471 3375 }
|
↓ open down ↓ |
260 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX