]> git.saurik.com Git - apple/xnu.git/blob - bsd/nfs/nfs_vfsops.c
ad7d5a2714ea3e5da2b95cbd8b0de4ae5f5a066d
[apple/xnu.git] / bsd / nfs / nfs_vfsops.c
1 /*
2 * Copyright (c) 2000-2014 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
29 /*
30 * Copyright (c) 1989, 1993, 1995
31 * The Regents of the University of California. All rights reserved.
32 *
33 * This code is derived from software contributed to Berkeley by
34 * Rick Macklem at The University of Guelph.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. All advertising materials mentioning features or use of this software
45 * must display the following acknowledgement:
46 * This product includes software developed by the University of
47 * California, Berkeley and its contributors.
48 * 4. Neither the name of the University nor the names of its contributors
49 * may be used to endorse or promote products derived from this software
50 * without specific prior written permission.
51 *
52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * SUCH DAMAGE.
63 *
64 * @(#)nfs_vfsops.c 8.12 (Berkeley) 5/20/95
65 * FreeBSD-Id: nfs_vfsops.c,v 1.52 1997/11/12 05:42:21 julian Exp $
66 */
67 /*
68 * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce
69 * support for mandatory and extensible security protections. This notice
70 * is included in support of clause 2.2 (b) of the Apple Public License,
71 * Version 2.0.
72 */
73
74 #include <sys/param.h>
75 #include <sys/systm.h>
76 #include <sys/conf.h>
77 #include <sys/ioctl.h>
78 #include <sys/signal.h>
79 #include <sys/proc_internal.h> /* for fs rooting to update rootdir in fdp */
80 #include <sys/kauth.h>
81 #include <sys/vnode_internal.h>
82 #include <sys/malloc.h>
83 #include <sys/kernel.h>
84 #include <sys/sysctl.h>
85 #include <sys/mount_internal.h>
86 #include <sys/kpi_mbuf.h>
87 #include <sys/socket.h>
88 #include <sys/socketvar.h>
89 #include <sys/fcntl.h>
90 #include <sys/quota.h>
91 #include <sys/priv.h>
92 #include <libkern/OSAtomic.h>
93
94 #include <sys/vm.h>
95 #include <sys/vmparam.h>
96
97 #if !defined(NO_MOUNT_PRIVATE)
98 #include <sys/filedesc.h>
99 #endif /* NO_MOUNT_PRIVATE */
100
101 #include <net/if.h>
102 #include <net/route.h>
103 #include <netinet/in.h>
104
105 #include <nfs/rpcv2.h>
106 #include <nfs/krpc.h>
107 #include <nfs/nfsproto.h>
108 #include <nfs/nfs.h>
109 #include <nfs/nfsnode.h>
110 #include <nfs/nfs_gss.h>
111 #include <nfs/nfsmount.h>
112 #include <nfs/xdr_subs.h>
113 #include <nfs/nfsm_subs.h>
114 #include <nfs/nfsdiskless.h>
115 #include <nfs/nfs_lock.h>
116 #if CONFIG_MACF
117 #include <security/mac_framework.h>
118 #endif
119
120 #include <pexpert/pexpert.h>
121
122 #define NFS_VFS_DBG(...) NFS_DBG(NFS_FAC_VFS, 7, ## __VA_ARGS__)
123
124 /*
125 * NFS client globals
126 */
127
128 int nfs_ticks;
129 static lck_grp_t *nfs_global_grp, *nfs_mount_grp;
130 lck_mtx_t *nfs_global_mutex;
131 uint32_t nfs_fs_attr_bitmap[NFS_ATTR_BITMAP_LEN];
132 uint32_t nfs_object_attr_bitmap[NFS_ATTR_BITMAP_LEN];
133 uint32_t nfs_getattr_bitmap[NFS_ATTR_BITMAP_LEN];
134 struct nfsclientidlist nfsclientids;
135
136 /* NFS requests */
137 struct nfs_reqqhead nfs_reqq;
138 lck_grp_t *nfs_request_grp;
139 lck_mtx_t *nfs_request_mutex;
140 thread_call_t nfs_request_timer_call;
141 int nfs_request_timer_on;
142 u_int32_t nfs_xid = 0;
143 u_int32_t nfs_xidwrap = 0; /* to build a (non-wrapping) 64 bit xid */
144
145 thread_call_t nfs_buf_timer_call;
146
147 /* NFSv4 */
148 lck_grp_t *nfs_open_grp;
149 uint32_t nfs_open_owner_seqnum = 0;
150 uint32_t nfs_lock_owner_seqnum = 0;
151 thread_call_t nfs4_callback_timer_call;
152 int nfs4_callback_timer_on = 0;
153
154 /* nfsiod */
155 lck_grp_t *nfsiod_lck_grp;
156 lck_mtx_t *nfsiod_mutex;
157 struct nfsiodlist nfsiodfree, nfsiodwork;
158 struct nfsiodmountlist nfsiodmounts;
159 int nfsiod_thread_count = 0;
160 int nfsiod_thread_max = NFS_DEFASYNCTHREAD;
161 int nfs_max_async_writes = NFS_DEFMAXASYNCWRITES;
162
163 int nfs_iosize = NFS_IOSIZE;
164 int nfs_access_cache_timeout = NFS_MAXATTRTIMO;
165 int nfs_access_delete = 1; /* too many servers get this wrong - workaround on by default */
166 int nfs_access_dotzfs = 1;
167 int nfs_access_for_getattr = 0;
168 int nfs_allow_async = 0;
169 int nfs_statfs_rate_limit = NFS_DEFSTATFSRATELIMIT;
170 int nfs_lockd_mounts = 0;
171 int nfs_lockd_request_sent = 0;
172 int nfs_idmap_ctrl = NFS_IDMAP_CTRL_USE_IDMAP_SERVICE;
173 int nfs_callback_port = 0;
174
175 int nfs_tprintf_initial_delay = NFS_TPRINTF_INITIAL_DELAY;
176 int nfs_tprintf_delay = NFS_TPRINTF_DELAY;
177
178
179 int mountnfs(char *, mount_t, vfs_context_t, vnode_t *);
180 static int nfs_mount_diskless(struct nfs_dlmount *, const char *, int, vnode_t *, mount_t *, vfs_context_t);
181 #if !defined(NO_MOUNT_PRIVATE)
182 static int nfs_mount_diskless_private(struct nfs_dlmount *, const char *, int, vnode_t *, mount_t *, vfs_context_t);
183 #endif /* NO_MOUNT_PRIVATE */
184 int nfs_mount_connect(struct nfsmount *);
185 void nfs_mount_drain_and_cleanup(struct nfsmount *);
186 void nfs_mount_cleanup(struct nfsmount *);
187 int nfs_mountinfo_assemble(struct nfsmount *, struct xdrbuf *);
188 int nfs4_mount_update_path_with_symlink(struct nfsmount *, struct nfs_fs_path *, uint32_t, fhandle_t *, int *, fhandle_t *, vfs_context_t);
189
190 /*
191 * NFS VFS operations.
192 */
193 int nfs_vfs_mount(mount_t, vnode_t, user_addr_t, vfs_context_t);
194 int nfs_vfs_start(mount_t, int, vfs_context_t);
195 int nfs_vfs_unmount(mount_t, int, vfs_context_t);
196 int nfs_vfs_root(mount_t, vnode_t *, vfs_context_t);
197 int nfs_vfs_quotactl(mount_t, int, uid_t, caddr_t, vfs_context_t);
198 int nfs_vfs_getattr(mount_t, struct vfs_attr *, vfs_context_t);
199 int nfs_vfs_sync(mount_t, int, vfs_context_t);
200 int nfs_vfs_vget(mount_t, ino64_t, vnode_t *, vfs_context_t);
201 int nfs_vfs_vptofh(vnode_t, int *, unsigned char *, vfs_context_t);
202 int nfs_vfs_fhtovp(mount_t, int, unsigned char *, vnode_t *, vfs_context_t);
203 int nfs_vfs_init(struct vfsconf *);
204 int nfs_vfs_sysctl(int *, u_int, user_addr_t, size_t *, user_addr_t, size_t, vfs_context_t);
205
206 struct vfsops nfs_vfsops = {
207 nfs_vfs_mount,
208 nfs_vfs_start,
209 nfs_vfs_unmount,
210 nfs_vfs_root,
211 nfs_vfs_quotactl,
212 nfs_vfs_getattr,
213 nfs_vfs_sync,
214 nfs_vfs_vget,
215 nfs_vfs_fhtovp,
216 nfs_vfs_vptofh,
217 nfs_vfs_init,
218 nfs_vfs_sysctl,
219 NULL, /* setattr */
220 { NULL, /* reserved */
221 NULL, /* reserved */
222 NULL, /* reserved */
223 NULL, /* reserved */
224 NULL, /* reserved */
225 NULL, /* reserved */
226 NULL } /* reserved */
227 };
228
229
230 /*
231 * version-specific NFS functions
232 */
233 int nfs3_mount(struct nfsmount *, vfs_context_t, nfsnode_t *);
234 int nfs4_mount(struct nfsmount *, vfs_context_t, nfsnode_t *);
235 int nfs3_fsinfo(struct nfsmount *, nfsnode_t, vfs_context_t);
236 int nfs3_update_statfs(struct nfsmount *, vfs_context_t);
237 int nfs4_update_statfs(struct nfsmount *, vfs_context_t);
238 #if !QUOTA
239 #define nfs3_getquota NULL
240 #define nfs4_getquota NULL
241 #else
242 int nfs3_getquota(struct nfsmount *, vfs_context_t, uid_t, int, struct dqblk *);
243 int nfs4_getquota(struct nfsmount *, vfs_context_t, uid_t, int, struct dqblk *);
244 #endif
245
246 struct nfs_funcs nfs3_funcs = {
247 nfs3_mount,
248 nfs3_update_statfs,
249 nfs3_getquota,
250 nfs3_access_rpc,
251 nfs3_getattr_rpc,
252 nfs3_setattr_rpc,
253 nfs3_read_rpc_async,
254 nfs3_read_rpc_async_finish,
255 nfs3_readlink_rpc,
256 nfs3_write_rpc_async,
257 nfs3_write_rpc_async_finish,
258 nfs3_commit_rpc,
259 nfs3_lookup_rpc_async,
260 nfs3_lookup_rpc_async_finish,
261 nfs3_remove_rpc,
262 nfs3_rename_rpc,
263 nfs3_setlock_rpc,
264 nfs3_unlock_rpc,
265 nfs3_getlock_rpc
266 };
267 struct nfs_funcs nfs4_funcs = {
268 nfs4_mount,
269 nfs4_update_statfs,
270 nfs4_getquota,
271 nfs4_access_rpc,
272 nfs4_getattr_rpc,
273 nfs4_setattr_rpc,
274 nfs4_read_rpc_async,
275 nfs4_read_rpc_async_finish,
276 nfs4_readlink_rpc,
277 nfs4_write_rpc_async,
278 nfs4_write_rpc_async_finish,
279 nfs4_commit_rpc,
280 nfs4_lookup_rpc_async,
281 nfs4_lookup_rpc_async_finish,
282 nfs4_remove_rpc,
283 nfs4_rename_rpc,
284 nfs4_setlock_rpc,
285 nfs4_unlock_rpc,
286 nfs4_getlock_rpc
287 };
288
289 /*
290 * Called once to initialize data structures...
291 */
292 int
293 nfs_vfs_init(__unused struct vfsconf *vfsp)
294 {
295 int i;
296
297 /*
298 * Check to see if major data structures haven't bloated.
299 */
300 if (sizeof (struct nfsnode) > NFS_NODEALLOC) {
301 printf("struct nfsnode bloated (> %dbytes)\n", NFS_NODEALLOC);
302 printf("Try reducing NFS_SMALLFH\n");
303 }
304 if (sizeof (struct nfsmount) > NFS_MNTALLOC)
305 printf("struct nfsmount bloated (> %dbytes)\n", NFS_MNTALLOC);
306
307 nfs_ticks = (hz * NFS_TICKINTVL + 500) / 1000;
308 if (nfs_ticks < 1)
309 nfs_ticks = 1;
310
311 /* init async I/O thread pool state */
312 TAILQ_INIT(&nfsiodfree);
313 TAILQ_INIT(&nfsiodwork);
314 TAILQ_INIT(&nfsiodmounts);
315 nfsiod_lck_grp = lck_grp_alloc_init("nfsiod", LCK_GRP_ATTR_NULL);
316 nfsiod_mutex = lck_mtx_alloc_init(nfsiod_lck_grp, LCK_ATTR_NULL);
317
318 /* init lock groups, etc. */
319 nfs_mount_grp = lck_grp_alloc_init("nfs_mount", LCK_GRP_ATTR_NULL);
320 nfs_open_grp = lck_grp_alloc_init("nfs_open", LCK_GRP_ATTR_NULL);
321 nfs_global_grp = lck_grp_alloc_init("nfs_global", LCK_GRP_ATTR_NULL);
322
323 nfs_global_mutex = lck_mtx_alloc_init(nfs_global_grp, LCK_ATTR_NULL);
324
325 /* init request list mutex */
326 nfs_request_grp = lck_grp_alloc_init("nfs_request", LCK_GRP_ATTR_NULL);
327 nfs_request_mutex = lck_mtx_alloc_init(nfs_request_grp, LCK_ATTR_NULL);
328
329 /* initialize NFS request list */
330 TAILQ_INIT(&nfs_reqq);
331
332 nfs_nbinit(); /* Init the nfsbuf table */
333 nfs_nhinit(); /* Init the nfsnode table */
334 nfs_lockinit(); /* Init the nfs lock state */
335 nfs_gss_init(); /* Init RPCSEC_GSS security */
336
337 /* NFSv4 stuff */
338 NFS4_PER_FS_ATTRIBUTES(nfs_fs_attr_bitmap);
339 NFS4_PER_OBJECT_ATTRIBUTES(nfs_object_attr_bitmap);
340 NFS4_DEFAULT_ATTRIBUTES(nfs_getattr_bitmap);
341 for (i=0; i < NFS_ATTR_BITMAP_LEN; i++)
342 nfs_getattr_bitmap[i] &= nfs_object_attr_bitmap[i];
343 TAILQ_INIT(&nfsclientids);
344
345 /* initialize NFS timer callouts */
346 nfs_request_timer_call = thread_call_allocate(nfs_request_timer, NULL);
347 nfs_buf_timer_call = thread_call_allocate(nfs_buf_timer, NULL);
348 nfs4_callback_timer_call = thread_call_allocate(nfs4_callback_timer, NULL);
349
350 return (0);
351 }
352
353 /*
354 * nfs statfs call
355 */
356 int
357 nfs3_update_statfs(struct nfsmount *nmp, vfs_context_t ctx)
358 {
359 nfsnode_t np;
360 int error = 0, lockerror, status, nfsvers;
361 u_int64_t xid;
362 struct nfsm_chain nmreq, nmrep;
363 uint32_t val = 0;
364
365 nfsvers = nmp->nm_vers;
366 np = nmp->nm_dnp;
367 if (!np)
368 return (ENXIO);
369 if ((error = vnode_get(NFSTOV(np))))
370 return (error);
371
372 nfsm_chain_null(&nmreq);
373 nfsm_chain_null(&nmrep);
374
375 nfsm_chain_build_alloc_init(error, &nmreq, NFSX_FH(nfsvers));
376 nfsm_chain_add_fh(error, &nmreq, nfsvers, np->n_fhp, np->n_fhsize);
377 nfsm_chain_build_done(error, &nmreq);
378 nfsmout_if(error);
379 error = nfs_request2(np, NULL, &nmreq, NFSPROC_FSSTAT, vfs_context_thread(ctx),
380 vfs_context_ucred(ctx), NULL, R_SOFT, &nmrep, &xid, &status);
381 if (error == ETIMEDOUT)
382 goto nfsmout;
383 if ((lockerror = nfs_node_lock(np)))
384 error = lockerror;
385 if (nfsvers == NFS_VER3)
386 nfsm_chain_postop_attr_update(error, &nmrep, np, &xid);
387 if (!lockerror)
388 nfs_node_unlock(np);
389 if (!error)
390 error = status;
391 nfsm_assert(error, NFSTONMP(np), ENXIO);
392 nfsmout_if(error);
393 lck_mtx_lock(&nmp->nm_lock);
394 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_SPACE_TOTAL);
395 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_SPACE_FREE);
396 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_SPACE_AVAIL);
397 if (nfsvers == NFS_VER3) {
398 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_FILES_AVAIL);
399 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_FILES_TOTAL);
400 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_FILES_FREE);
401 nmp->nm_fsattr.nfsa_bsize = NFS_FABLKSIZE;
402 nfsm_chain_get_64(error, &nmrep, nmp->nm_fsattr.nfsa_space_total);
403 nfsm_chain_get_64(error, &nmrep, nmp->nm_fsattr.nfsa_space_free);
404 nfsm_chain_get_64(error, &nmrep, nmp->nm_fsattr.nfsa_space_avail);
405 nfsm_chain_get_64(error, &nmrep, nmp->nm_fsattr.nfsa_files_total);
406 nfsm_chain_get_64(error, &nmrep, nmp->nm_fsattr.nfsa_files_free);
407 nfsm_chain_get_64(error, &nmrep, nmp->nm_fsattr.nfsa_files_avail);
408 // skip invarsec
409 } else {
410 nfsm_chain_adv(error, &nmrep, NFSX_UNSIGNED); // skip tsize?
411 nfsm_chain_get_32(error, &nmrep, nmp->nm_fsattr.nfsa_bsize);
412 nfsm_chain_get_32(error, &nmrep, val);
413 nfsmout_if(error);
414 if (nmp->nm_fsattr.nfsa_bsize <= 0)
415 nmp->nm_fsattr.nfsa_bsize = NFS_FABLKSIZE;
416 nmp->nm_fsattr.nfsa_space_total = (uint64_t)val * nmp->nm_fsattr.nfsa_bsize;
417 nfsm_chain_get_32(error, &nmrep, val);
418 nfsmout_if(error);
419 nmp->nm_fsattr.nfsa_space_free = (uint64_t)val * nmp->nm_fsattr.nfsa_bsize;
420 nfsm_chain_get_32(error, &nmrep, val);
421 nfsmout_if(error);
422 nmp->nm_fsattr.nfsa_space_avail = (uint64_t)val * nmp->nm_fsattr.nfsa_bsize;
423 }
424 lck_mtx_unlock(&nmp->nm_lock);
425 nfsmout:
426 nfsm_chain_cleanup(&nmreq);
427 nfsm_chain_cleanup(&nmrep);
428 vnode_put(NFSTOV(np));
429 return (error);
430 }
431
432 int
433 nfs4_update_statfs(struct nfsmount *nmp, vfs_context_t ctx)
434 {
435 nfsnode_t np;
436 int error = 0, lockerror, status, nfsvers, numops;
437 u_int64_t xid;
438 struct nfsm_chain nmreq, nmrep;
439 uint32_t bitmap[NFS_ATTR_BITMAP_LEN];
440 struct nfs_vattr nvattr;
441 struct nfsreq_secinfo_args si;
442
443 nfsvers = nmp->nm_vers;
444 np = nmp->nm_dnp;
445 if (!np)
446 return (ENXIO);
447 if ((error = vnode_get(NFSTOV(np))))
448 return (error);
449
450 NFSREQ_SECINFO_SET(&si, np, NULL, 0, NULL, 0);
451 NVATTR_INIT(&nvattr);
452 nfsm_chain_null(&nmreq);
453 nfsm_chain_null(&nmrep);
454
455 // PUTFH + GETATTR
456 numops = 2;
457 nfsm_chain_build_alloc_init(error, &nmreq, 15 * NFSX_UNSIGNED);
458 nfsm_chain_add_compound_header(error, &nmreq, "statfs", numops);
459 numops--;
460 nfsm_chain_add_32(error, &nmreq, NFS_OP_PUTFH);
461 nfsm_chain_add_fh(error, &nmreq, nfsvers, np->n_fhp, np->n_fhsize);
462 numops--;
463 nfsm_chain_add_32(error, &nmreq, NFS_OP_GETATTR);
464 NFS_COPY_ATTRIBUTES(nfs_getattr_bitmap, bitmap);
465 NFS4_STATFS_ATTRIBUTES(bitmap);
466 nfsm_chain_add_bitmap_supported(error, &nmreq, bitmap, nmp, np);
467 nfsm_chain_build_done(error, &nmreq);
468 nfsm_assert(error, (numops == 0), EPROTO);
469 nfsmout_if(error);
470 error = nfs_request2(np, NULL, &nmreq, NFSPROC4_COMPOUND,
471 vfs_context_thread(ctx), vfs_context_ucred(ctx),
472 NULL, R_SOFT, &nmrep, &xid, &status);
473 nfsm_chain_skip_tag(error, &nmrep);
474 nfsm_chain_get_32(error, &nmrep, numops);
475 nfsm_chain_op_check(error, &nmrep, NFS_OP_PUTFH);
476 nfsm_chain_op_check(error, &nmrep, NFS_OP_GETATTR);
477 nfsm_assert(error, NFSTONMP(np), ENXIO);
478 nfsmout_if(error);
479 lck_mtx_lock(&nmp->nm_lock);
480 error = nfs4_parsefattr(&nmrep, &nmp->nm_fsattr, &nvattr, NULL, NULL, NULL);
481 lck_mtx_unlock(&nmp->nm_lock);
482 nfsmout_if(error);
483 if ((lockerror = nfs_node_lock(np)))
484 error = lockerror;
485 if (!error)
486 nfs_loadattrcache(np, &nvattr, &xid, 0);
487 if (!lockerror)
488 nfs_node_unlock(np);
489 nfsm_assert(error, NFSTONMP(np), ENXIO);
490 nfsmout_if(error);
491 nmp->nm_fsattr.nfsa_bsize = NFS_FABLKSIZE;
492 nfsmout:
493 NVATTR_CLEANUP(&nvattr);
494 nfsm_chain_cleanup(&nmreq);
495 nfsm_chain_cleanup(&nmrep);
496 vnode_put(NFSTOV(np));
497 return (error);
498 }
499
500
501 /*
502 * The NFS VFS_GETATTR function: "statfs"-type information is retrieved
503 * using the nf_update_statfs() function, and other attributes are cobbled
504 * together from whatever sources we can (getattr, fsinfo, pathconf).
505 */
506 int
507 nfs_vfs_getattr(mount_t mp, struct vfs_attr *fsap, vfs_context_t ctx)
508 {
509 struct nfsmount *nmp;
510 uint32_t bsize;
511 int error = 0, nfsvers;
512
513 nmp = VFSTONFS(mp);
514 if (nfs_mount_gone(nmp))
515 return (ENXIO);
516 nfsvers = nmp->nm_vers;
517
518 if (VFSATTR_IS_ACTIVE(fsap, f_bsize) ||
519 VFSATTR_IS_ACTIVE(fsap, f_iosize) ||
520 VFSATTR_IS_ACTIVE(fsap, f_blocks) ||
521 VFSATTR_IS_ACTIVE(fsap, f_bfree) ||
522 VFSATTR_IS_ACTIVE(fsap, f_bavail) ||
523 VFSATTR_IS_ACTIVE(fsap, f_bused) ||
524 VFSATTR_IS_ACTIVE(fsap, f_files) ||
525 VFSATTR_IS_ACTIVE(fsap, f_ffree)) {
526 int statfsrate = nfs_statfs_rate_limit;
527 int refresh = 1;
528
529 /*
530 * Are we rate-limiting statfs RPCs?
531 * (Treat values less than 1 or greater than 1,000,000 as no limit.)
532 */
533 if ((statfsrate > 0) && (statfsrate < 1000000)) {
534 struct timeval now;
535 uint32_t stamp;
536
537 microuptime(&now);
538 lck_mtx_lock(&nmp->nm_lock);
539 stamp = (now.tv_sec * statfsrate) + (now.tv_usec / (1000000/statfsrate));
540 if (stamp != nmp->nm_fsattrstamp) {
541 refresh = 1;
542 nmp->nm_fsattrstamp = stamp;
543 } else {
544 refresh = 0;
545 }
546 lck_mtx_unlock(&nmp->nm_lock);
547 }
548
549 if (refresh && !nfs_use_cache(nmp))
550 error = nmp->nm_funcs->nf_update_statfs(nmp, ctx);
551 if ((error == ESTALE) || (error == ETIMEDOUT))
552 error = 0;
553 if (error)
554 return (error);
555
556 lck_mtx_lock(&nmp->nm_lock);
557 VFSATTR_RETURN(fsap, f_iosize, nfs_iosize);
558 VFSATTR_RETURN(fsap, f_bsize, nmp->nm_fsattr.nfsa_bsize);
559 bsize = nmp->nm_fsattr.nfsa_bsize;
560 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_SPACE_TOTAL))
561 VFSATTR_RETURN(fsap, f_blocks, nmp->nm_fsattr.nfsa_space_total / bsize);
562 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_SPACE_FREE))
563 VFSATTR_RETURN(fsap, f_bfree, nmp->nm_fsattr.nfsa_space_free / bsize);
564 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_SPACE_AVAIL))
565 VFSATTR_RETURN(fsap, f_bavail, nmp->nm_fsattr.nfsa_space_avail / bsize);
566 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_SPACE_TOTAL) &&
567 NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_SPACE_FREE))
568 VFSATTR_RETURN(fsap, f_bused,
569 (nmp->nm_fsattr.nfsa_space_total / bsize) -
570 (nmp->nm_fsattr.nfsa_space_free / bsize));
571 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_FILES_TOTAL))
572 VFSATTR_RETURN(fsap, f_files, nmp->nm_fsattr.nfsa_files_total);
573 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_FILES_FREE))
574 VFSATTR_RETURN(fsap, f_ffree, nmp->nm_fsattr.nfsa_files_free);
575 lck_mtx_unlock(&nmp->nm_lock);
576 }
577
578 if (VFSATTR_IS_ACTIVE(fsap, f_capabilities)) {
579 u_int32_t caps, valid;
580 nfsnode_t np = nmp->nm_dnp;
581
582 nfsm_assert(error, VFSTONFS(mp) && np, ENXIO);
583 if (error)
584 return (error);
585 lck_mtx_lock(&nmp->nm_lock);
586
587 /*
588 * The capabilities[] array defines what this volume supports.
589 *
590 * The valid[] array defines which bits this code understands
591 * the meaning of (whether the volume has that capability or not).
592 * Any zero bits here means "I don't know what you're asking about"
593 * and the caller cannot tell whether that capability is
594 * present or not.
595 */
596 caps = valid = 0;
597 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_SYMLINK_SUPPORT)) {
598 valid |= VOL_CAP_FMT_SYMBOLICLINKS;
599 if (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_SYMLINK)
600 caps |= VOL_CAP_FMT_SYMBOLICLINKS;
601 }
602 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_LINK_SUPPORT)) {
603 valid |= VOL_CAP_FMT_HARDLINKS;
604 if (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_LINK)
605 caps |= VOL_CAP_FMT_HARDLINKS;
606 }
607 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_CASE_INSENSITIVE)) {
608 valid |= VOL_CAP_FMT_CASE_SENSITIVE;
609 if (!(nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_CASE_INSENSITIVE))
610 caps |= VOL_CAP_FMT_CASE_SENSITIVE;
611 }
612 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_CASE_PRESERVING)) {
613 valid |= VOL_CAP_FMT_CASE_PRESERVING;
614 if (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_CASE_PRESERVING)
615 caps |= VOL_CAP_FMT_CASE_PRESERVING;
616 }
617 /* Note: VOL_CAP_FMT_2TB_FILESIZE is actually used to test for "large file support" */
618 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_MAXFILESIZE)) {
619 /* Is server's max file size at least 4GB? */
620 if (nmp->nm_fsattr.nfsa_maxfilesize >= 0x100000000ULL)
621 caps |= VOL_CAP_FMT_2TB_FILESIZE;
622 } else if (nfsvers >= NFS_VER3) {
623 /*
624 * NFSv3 and up supports 64 bits of file size.
625 * So, we'll just assume maxfilesize >= 4GB
626 */
627 caps |= VOL_CAP_FMT_2TB_FILESIZE;
628 }
629 if (nfsvers >= NFS_VER4) {
630 caps |= VOL_CAP_FMT_HIDDEN_FILES;
631 valid |= VOL_CAP_FMT_HIDDEN_FILES;
632 // VOL_CAP_FMT_OPENDENYMODES
633 // caps |= VOL_CAP_FMT_OPENDENYMODES;
634 // valid |= VOL_CAP_FMT_OPENDENYMODES;
635 }
636 fsap->f_capabilities.capabilities[VOL_CAPABILITIES_FORMAT] =
637 // VOL_CAP_FMT_PERSISTENTOBJECTIDS |
638 // VOL_CAP_FMT_SYMBOLICLINKS |
639 // VOL_CAP_FMT_HARDLINKS |
640 // VOL_CAP_FMT_JOURNAL |
641 // VOL_CAP_FMT_JOURNAL_ACTIVE |
642 // VOL_CAP_FMT_NO_ROOT_TIMES |
643 // VOL_CAP_FMT_SPARSE_FILES |
644 // VOL_CAP_FMT_ZERO_RUNS |
645 // VOL_CAP_FMT_CASE_SENSITIVE |
646 // VOL_CAP_FMT_CASE_PRESERVING |
647 // VOL_CAP_FMT_FAST_STATFS |
648 // VOL_CAP_FMT_2TB_FILESIZE |
649 // VOL_CAP_FMT_OPENDENYMODES |
650 // VOL_CAP_FMT_HIDDEN_FILES |
651 caps;
652 fsap->f_capabilities.valid[VOL_CAPABILITIES_FORMAT] =
653 VOL_CAP_FMT_PERSISTENTOBJECTIDS |
654 // VOL_CAP_FMT_SYMBOLICLINKS |
655 // VOL_CAP_FMT_HARDLINKS |
656 // VOL_CAP_FMT_JOURNAL |
657 // VOL_CAP_FMT_JOURNAL_ACTIVE |
658 // VOL_CAP_FMT_NO_ROOT_TIMES |
659 // VOL_CAP_FMT_SPARSE_FILES |
660 // VOL_CAP_FMT_ZERO_RUNS |
661 // VOL_CAP_FMT_CASE_SENSITIVE |
662 // VOL_CAP_FMT_CASE_PRESERVING |
663 VOL_CAP_FMT_FAST_STATFS |
664 VOL_CAP_FMT_2TB_FILESIZE |
665 // VOL_CAP_FMT_OPENDENYMODES |
666 // VOL_CAP_FMT_HIDDEN_FILES |
667 valid;
668
669 /*
670 * We don't support most of the interfaces.
671 *
672 * We MAY support locking, but we don't have any easy way of probing.
673 * We can tell if there's no lockd running or if locks have been
674 * disabled for a mount, so we can definitely answer NO in that case.
675 * Any attempt to send a request to lockd to test for locking support
676 * may cause the lazily-launched locking daemons to be started
677 * unnecessarily. So we avoid that. However, we do record if we ever
678 * successfully perform a lock operation on a mount point, so if it
679 * looks like lock ops have worked, we do report that we support them.
680 */
681 caps = valid = 0;
682 if (nfsvers >= NFS_VER4) {
683 caps = VOL_CAP_INT_ADVLOCK | VOL_CAP_INT_FLOCK;
684 valid = VOL_CAP_INT_ADVLOCK | VOL_CAP_INT_FLOCK;
685 if (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_ACL)
686 caps |= VOL_CAP_INT_EXTENDED_SECURITY;
687 valid |= VOL_CAP_INT_EXTENDED_SECURITY;
688 if (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_NAMED_ATTR)
689 caps |= VOL_CAP_INT_EXTENDED_ATTR;
690 valid |= VOL_CAP_INT_EXTENDED_ATTR;
691 #if NAMEDSTREAMS
692 if (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_NAMED_ATTR)
693 caps |= VOL_CAP_INT_NAMEDSTREAMS;
694 valid |= VOL_CAP_INT_NAMEDSTREAMS;
695 #endif
696 } else if (nmp->nm_lockmode == NFS_LOCK_MODE_DISABLED) {
697 /* locks disabled on this mount, so they definitely won't work */
698 valid = VOL_CAP_INT_ADVLOCK | VOL_CAP_INT_FLOCK;
699 } else if (nmp->nm_state & NFSSTA_LOCKSWORK) {
700 caps = VOL_CAP_INT_ADVLOCK | VOL_CAP_INT_FLOCK;
701 valid = VOL_CAP_INT_ADVLOCK | VOL_CAP_INT_FLOCK;
702 }
703 fsap->f_capabilities.capabilities[VOL_CAPABILITIES_INTERFACES] =
704 // VOL_CAP_INT_SEARCHFS |
705 // VOL_CAP_INT_ATTRLIST |
706 // VOL_CAP_INT_NFSEXPORT |
707 // VOL_CAP_INT_READDIRATTR |
708 // VOL_CAP_INT_EXCHANGEDATA |
709 // VOL_CAP_INT_COPYFILE |
710 // VOL_CAP_INT_ALLOCATE |
711 // VOL_CAP_INT_VOL_RENAME |
712 // VOL_CAP_INT_ADVLOCK |
713 // VOL_CAP_INT_FLOCK |
714 // VOL_CAP_INT_EXTENDED_SECURITY |
715 // VOL_CAP_INT_USERACCESS |
716 // VOL_CAP_INT_MANLOCK |
717 // VOL_CAP_INT_NAMEDSTREAMS |
718 // VOL_CAP_INT_EXTENDED_ATTR |
719 VOL_CAP_INT_REMOTE_EVENT |
720 caps;
721 fsap->f_capabilities.valid[VOL_CAPABILITIES_INTERFACES] =
722 VOL_CAP_INT_SEARCHFS |
723 VOL_CAP_INT_ATTRLIST |
724 VOL_CAP_INT_NFSEXPORT |
725 VOL_CAP_INT_READDIRATTR |
726 VOL_CAP_INT_EXCHANGEDATA |
727 VOL_CAP_INT_COPYFILE |
728 VOL_CAP_INT_ALLOCATE |
729 VOL_CAP_INT_VOL_RENAME |
730 // VOL_CAP_INT_ADVLOCK |
731 // VOL_CAP_INT_FLOCK |
732 // VOL_CAP_INT_EXTENDED_SECURITY |
733 // VOL_CAP_INT_USERACCESS |
734 // VOL_CAP_INT_MANLOCK |
735 // VOL_CAP_INT_NAMEDSTREAMS |
736 // VOL_CAP_INT_EXTENDED_ATTR |
737 VOL_CAP_INT_REMOTE_EVENT |
738 valid;
739
740 fsap->f_capabilities.capabilities[VOL_CAPABILITIES_RESERVED1] = 0;
741 fsap->f_capabilities.valid[VOL_CAPABILITIES_RESERVED1] = 0;
742
743 fsap->f_capabilities.capabilities[VOL_CAPABILITIES_RESERVED2] = 0;
744 fsap->f_capabilities.valid[VOL_CAPABILITIES_RESERVED2] = 0;
745
746 VFSATTR_SET_SUPPORTED(fsap, f_capabilities);
747 lck_mtx_unlock(&nmp->nm_lock);
748 }
749
750 if (VFSATTR_IS_ACTIVE(fsap, f_attributes)) {
751 fsap->f_attributes.validattr.commonattr = 0;
752 fsap->f_attributes.validattr.volattr =
753 ATTR_VOL_CAPABILITIES | ATTR_VOL_ATTRIBUTES;
754 fsap->f_attributes.validattr.dirattr = 0;
755 fsap->f_attributes.validattr.fileattr = 0;
756 fsap->f_attributes.validattr.forkattr = 0;
757
758 fsap->f_attributes.nativeattr.commonattr = 0;
759 fsap->f_attributes.nativeattr.volattr =
760 ATTR_VOL_CAPABILITIES | ATTR_VOL_ATTRIBUTES;
761 fsap->f_attributes.nativeattr.dirattr = 0;
762 fsap->f_attributes.nativeattr.fileattr = 0;
763 fsap->f_attributes.nativeattr.forkattr = 0;
764
765 VFSATTR_SET_SUPPORTED(fsap, f_attributes);
766 }
767
768 return (error);
769 }
770
771 /*
772 * nfs version 3 fsinfo rpc call
773 */
774 int
775 nfs3_fsinfo(struct nfsmount *nmp, nfsnode_t np, vfs_context_t ctx)
776 {
777 int error = 0, lockerror, status, nmlocked = 0;
778 u_int64_t xid;
779 uint32_t val, prefsize, maxsize;
780 struct nfsm_chain nmreq, nmrep;
781
782 nfsm_chain_null(&nmreq);
783 nfsm_chain_null(&nmrep);
784
785 nfsm_chain_build_alloc_init(error, &nmreq, NFSX_FH(nmp->nm_vers));
786 nfsm_chain_add_fh(error, &nmreq, nmp->nm_vers, np->n_fhp, np->n_fhsize);
787 nfsm_chain_build_done(error, &nmreq);
788 nfsmout_if(error);
789 error = nfs_request(np, NULL, &nmreq, NFSPROC_FSINFO, ctx, NULL, &nmrep, &xid, &status);
790 if ((lockerror = nfs_node_lock(np)))
791 error = lockerror;
792 nfsm_chain_postop_attr_update(error, &nmrep, np, &xid);
793 if (!lockerror)
794 nfs_node_unlock(np);
795 if (!error)
796 error = status;
797 nfsmout_if(error);
798
799 lck_mtx_lock(&nmp->nm_lock);
800 nmlocked = 1;
801
802 nfsm_chain_get_32(error, &nmrep, maxsize);
803 nfsm_chain_get_32(error, &nmrep, prefsize);
804 nfsmout_if(error);
805 nmp->nm_fsattr.nfsa_maxread = maxsize;
806 if (prefsize < nmp->nm_rsize)
807 nmp->nm_rsize = (prefsize + NFS_FABLKSIZE - 1) &
808 ~(NFS_FABLKSIZE - 1);
809 if ((maxsize > 0) && (maxsize < nmp->nm_rsize)) {
810 nmp->nm_rsize = maxsize & ~(NFS_FABLKSIZE - 1);
811 if (nmp->nm_rsize == 0)
812 nmp->nm_rsize = maxsize;
813 }
814 nfsm_chain_adv(error, &nmrep, NFSX_UNSIGNED); // skip rtmult
815
816 nfsm_chain_get_32(error, &nmrep, maxsize);
817 nfsm_chain_get_32(error, &nmrep, prefsize);
818 nfsmout_if(error);
819 nmp->nm_fsattr.nfsa_maxwrite = maxsize;
820 if (prefsize < nmp->nm_wsize)
821 nmp->nm_wsize = (prefsize + NFS_FABLKSIZE - 1) &
822 ~(NFS_FABLKSIZE - 1);
823 if ((maxsize > 0) && (maxsize < nmp->nm_wsize)) {
824 nmp->nm_wsize = maxsize & ~(NFS_FABLKSIZE - 1);
825 if (nmp->nm_wsize == 0)
826 nmp->nm_wsize = maxsize;
827 }
828 nfsm_chain_adv(error, &nmrep, NFSX_UNSIGNED); // skip wtmult
829
830 nfsm_chain_get_32(error, &nmrep, prefsize);
831 nfsmout_if(error);
832 if ((prefsize > 0) && (prefsize < nmp->nm_readdirsize))
833 nmp->nm_readdirsize = prefsize;
834 if ((nmp->nm_fsattr.nfsa_maxread > 0) &&
835 (nmp->nm_fsattr.nfsa_maxread < nmp->nm_readdirsize))
836 nmp->nm_readdirsize = nmp->nm_fsattr.nfsa_maxread;
837
838 nfsm_chain_get_64(error, &nmrep, nmp->nm_fsattr.nfsa_maxfilesize);
839
840 nfsm_chain_adv(error, &nmrep, 2 * NFSX_UNSIGNED); // skip time_delta
841
842 /* convert FS properties to our own flags */
843 nfsm_chain_get_32(error, &nmrep, val);
844 nfsmout_if(error);
845 if (val & NFSV3FSINFO_LINK)
846 nmp->nm_fsattr.nfsa_flags |= NFS_FSFLAG_LINK;
847 if (val & NFSV3FSINFO_SYMLINK)
848 nmp->nm_fsattr.nfsa_flags |= NFS_FSFLAG_SYMLINK;
849 if (val & NFSV3FSINFO_HOMOGENEOUS)
850 nmp->nm_fsattr.nfsa_flags |= NFS_FSFLAG_HOMOGENEOUS;
851 if (val & NFSV3FSINFO_CANSETTIME)
852 nmp->nm_fsattr.nfsa_flags |= NFS_FSFLAG_SET_TIME;
853 nmp->nm_state |= NFSSTA_GOTFSINFO;
854 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_MAXREAD);
855 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_MAXWRITE);
856 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_MAXFILESIZE);
857 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_LINK_SUPPORT);
858 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_SYMLINK_SUPPORT);
859 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_HOMOGENEOUS);
860 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_CANSETTIME);
861 nfsmout:
862 if (nmlocked)
863 lck_mtx_unlock(&nmp->nm_lock);
864 nfsm_chain_cleanup(&nmreq);
865 nfsm_chain_cleanup(&nmrep);
866 return (error);
867 }
868
869 /*
870 * Mount a remote root fs via. nfs. This depends on the info in the
871 * nfs_diskless structure that has been filled in properly by some primary
872 * bootstrap.
873 * It goes something like this:
874 * - do enough of "ifconfig" by calling ifioctl() so that the system
875 * can talk to the server
876 * - If nfs_diskless.mygateway is filled in, use that address as
877 * a default gateway.
878 * - hand craft the swap nfs vnode hanging off a fake mount point
879 * if swdevt[0].sw_dev == NODEV
880 * - build the rootfs mount point and call mountnfs() to do the rest.
881 */
882 int
883 nfs_mountroot(void)
884 {
885 struct nfs_diskless nd;
886 mount_t mp = NULL;
887 vnode_t vp = NULL;
888 vfs_context_t ctx;
889 int error;
890 #if !defined(NO_MOUNT_PRIVATE)
891 mount_t mppriv = NULL;
892 vnode_t vppriv = NULL;
893 #endif /* NO_MOUNT_PRIVATE */
894 int v3, sotype;
895
896 /*
897 * Call nfs_boot_init() to fill in the nfs_diskless struct.
898 * Note: networking must already have been configured before
899 * we're called.
900 */
901 bzero((caddr_t) &nd, sizeof(nd));
902 error = nfs_boot_init(&nd);
903 if (error)
904 panic("nfs_boot_init: unable to initialize NFS root system information, "
905 "error %d, check configuration: %s\n", error, PE_boot_args());
906
907 /*
908 * Try NFSv3 first, then fallback to NFSv2.
909 * Likewise, try TCP first, then fall back to UDP.
910 */
911 v3 = 1;
912 sotype = SOCK_STREAM;
913
914 tryagain:
915 error = nfs_boot_getfh(&nd, v3, sotype);
916 if (error) {
917 if (error == EHOSTDOWN || error == EHOSTUNREACH) {
918 if (nd.nd_root.ndm_mntfrom)
919 FREE_ZONE(nd.nd_root.ndm_mntfrom,
920 MAXPATHLEN, M_NAMEI);
921 if (nd.nd_root.ndm_path)
922 FREE_ZONE(nd.nd_root.ndm_path,
923 MAXPATHLEN, M_NAMEI);
924 if (nd.nd_private.ndm_mntfrom)
925 FREE_ZONE(nd.nd_private.ndm_mntfrom,
926 MAXPATHLEN, M_NAMEI);
927 if (nd.nd_private.ndm_path)
928 FREE_ZONE(nd.nd_private.ndm_path,
929 MAXPATHLEN, M_NAMEI);
930 return (error);
931 }
932 if (v3) {
933 if (sotype == SOCK_STREAM) {
934 printf("NFS mount (v3,TCP) failed with error %d, trying UDP...\n", error);
935 sotype = SOCK_DGRAM;
936 goto tryagain;
937 }
938 printf("NFS mount (v3,UDP) failed with error %d, trying v2...\n", error);
939 v3 = 0;
940 sotype = SOCK_STREAM;
941 goto tryagain;
942 } else if (sotype == SOCK_STREAM) {
943 printf("NFS mount (v2,TCP) failed with error %d, trying UDP...\n", error);
944 sotype = SOCK_DGRAM;
945 goto tryagain;
946 } else {
947 printf("NFS mount (v2,UDP) failed with error %d, giving up...\n", error);
948 }
949 switch(error) {
950 case EPROGUNAVAIL:
951 panic("NFS mount failed: NFS server mountd not responding, check server configuration: %s", PE_boot_args());
952 case EACCES:
953 case EPERM:
954 panic("NFS mount failed: NFS server refused mount, check server configuration: %s", PE_boot_args());
955 default:
956 panic("NFS mount failed with error %d, check configuration: %s", error, PE_boot_args());
957 }
958 }
959
960 ctx = vfs_context_kernel();
961
962 /*
963 * Create the root mount point.
964 */
965 #if !defined(NO_MOUNT_PRIVATE)
966 {
967 //PWC hack until we have a real "mount" tool to remount root rw
968 int rw_root=0;
969 int flags = MNT_ROOTFS|MNT_RDONLY;
970 PE_parse_boot_argn("-rwroot_hack", &rw_root, sizeof (rw_root));
971 if(rw_root)
972 {
973 flags = MNT_ROOTFS;
974 kprintf("-rwroot_hack in effect: mounting root fs read/write\n");
975 }
976
977 if ((error = nfs_mount_diskless(&nd.nd_root, "/", flags, &vp, &mp, ctx)))
978 #else
979 if ((error = nfs_mount_diskless(&nd.nd_root, "/", MNT_ROOTFS, &vp, &mp, ctx)))
980 #endif /* NO_MOUNT_PRIVATE */
981 {
982 if (v3) {
983 if (sotype == SOCK_STREAM) {
984 printf("NFS root mount (v3,TCP) failed with %d, trying UDP...\n", error);
985 sotype = SOCK_DGRAM;
986 goto tryagain;
987 }
988 printf("NFS root mount (v3,UDP) failed with %d, trying v2...\n", error);
989 v3 = 0;
990 sotype = SOCK_STREAM;
991 goto tryagain;
992 } else if (sotype == SOCK_STREAM) {
993 printf("NFS root mount (v2,TCP) failed with %d, trying UDP...\n", error);
994 sotype = SOCK_DGRAM;
995 goto tryagain;
996 } else {
997 printf("NFS root mount (v2,UDP) failed with error %d, giving up...\n", error);
998 }
999 panic("NFS root mount failed with error %d, check configuration: %s\n", error, PE_boot_args());
1000 }
1001 }
1002 printf("root on %s\n", nd.nd_root.ndm_mntfrom);
1003
1004 vfs_unbusy(mp);
1005 mount_list_add(mp);
1006 rootvp = vp;
1007
1008 #if !defined(NO_MOUNT_PRIVATE)
1009 if (nd.nd_private.ndm_saddr.sin_addr.s_addr) {
1010 error = nfs_mount_diskless_private(&nd.nd_private, "/private",
1011 0, &vppriv, &mppriv, ctx);
1012 if (error)
1013 panic("NFS /private mount failed with error %d, check configuration: %s\n", error, PE_boot_args());
1014 printf("private on %s\n", nd.nd_private.ndm_mntfrom);
1015
1016 vfs_unbusy(mppriv);
1017 mount_list_add(mppriv);
1018 }
1019
1020 #endif /* NO_MOUNT_PRIVATE */
1021
1022 if (nd.nd_root.ndm_mntfrom)
1023 FREE_ZONE(nd.nd_root.ndm_mntfrom, MAXPATHLEN, M_NAMEI);
1024 if (nd.nd_root.ndm_path)
1025 FREE_ZONE(nd.nd_root.ndm_path, MAXPATHLEN, M_NAMEI);
1026 if (nd.nd_private.ndm_mntfrom)
1027 FREE_ZONE(nd.nd_private.ndm_mntfrom, MAXPATHLEN, M_NAMEI);
1028 if (nd.nd_private.ndm_path)
1029 FREE_ZONE(nd.nd_private.ndm_path, MAXPATHLEN, M_NAMEI);
1030
1031 /* Get root attributes (for the time). */
1032 error = nfs_getattr(VTONFS(vp), NULL, ctx, NGA_UNCACHED);
1033 if (error)
1034 panic("NFS mount: failed to get attributes for root directory, error %d, check server", error);
1035 return (0);
1036 }
1037
1038 /*
1039 * Internal version of mount system call for diskless setup.
1040 */
1041 static int
1042 nfs_mount_diskless(
1043 struct nfs_dlmount *ndmntp,
1044 const char *mntname,
1045 int mntflag,
1046 vnode_t *vpp,
1047 mount_t *mpp,
1048 vfs_context_t ctx)
1049 {
1050 mount_t mp;
1051 int error, numcomps;
1052 char *xdrbuf, *p, *cp, *frompath, *endserverp;
1053 char uaddr[MAX_IPv4_STR_LEN];
1054 struct xdrbuf xb;
1055 uint32_t mattrs[NFS_MATTR_BITMAP_LEN];
1056 uint32_t mflags_mask[NFS_MFLAG_BITMAP_LEN];
1057 uint32_t mflags[NFS_MFLAG_BITMAP_LEN];
1058 uint32_t argslength_offset, attrslength_offset, end_offset;
1059
1060 if ((error = vfs_rootmountalloc("nfs", ndmntp->ndm_mntfrom, &mp))) {
1061 printf("nfs_mount_diskless: NFS not configured\n");
1062 return (error);
1063 }
1064
1065 mp->mnt_flag |= mntflag;
1066 if (!(mntflag & MNT_RDONLY))
1067 mp->mnt_flag &= ~MNT_RDONLY;
1068
1069 /* find the server-side path being mounted */
1070 frompath = ndmntp->ndm_mntfrom;
1071 if (*frompath == '[') { /* skip IPv6 literal address */
1072 while (*frompath && (*frompath != ']'))
1073 frompath++;
1074 if (*frompath == ']')
1075 frompath++;
1076 }
1077 while (*frompath && (*frompath != ':'))
1078 frompath++;
1079 endserverp = frompath;
1080 while (*frompath && (*frompath == ':'))
1081 frompath++;
1082 /* count fs location path components */
1083 p = frompath;
1084 while (*p && (*p == '/'))
1085 p++;
1086 numcomps = 0;
1087 while (*p) {
1088 numcomps++;
1089 while (*p && (*p != '/'))
1090 p++;
1091 while (*p && (*p == '/'))
1092 p++;
1093 }
1094
1095 /* convert address to universal address string */
1096 if (inet_ntop(AF_INET, &ndmntp->ndm_saddr.sin_addr, uaddr, sizeof(uaddr)) != uaddr) {
1097 printf("nfs_mount_diskless: bad address\n");
1098 return (EINVAL);
1099 }
1100
1101 /* prepare mount attributes */
1102 NFS_BITMAP_ZERO(mattrs, NFS_MATTR_BITMAP_LEN);
1103 NFS_BITMAP_SET(mattrs, NFS_MATTR_NFS_VERSION);
1104 NFS_BITMAP_SET(mattrs, NFS_MATTR_SOCKET_TYPE);
1105 NFS_BITMAP_SET(mattrs, NFS_MATTR_NFS_PORT);
1106 NFS_BITMAP_SET(mattrs, NFS_MATTR_FH);
1107 NFS_BITMAP_SET(mattrs, NFS_MATTR_FS_LOCATIONS);
1108 NFS_BITMAP_SET(mattrs, NFS_MATTR_MNTFLAGS);
1109
1110 /* prepare mount flags */
1111 NFS_BITMAP_ZERO(mflags_mask, NFS_MFLAG_BITMAP_LEN);
1112 NFS_BITMAP_ZERO(mflags, NFS_MFLAG_BITMAP_LEN);
1113 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_RESVPORT);
1114 NFS_BITMAP_SET(mflags, NFS_MFLAG_RESVPORT);
1115
1116 /* build xdr buffer */
1117 xb_init_buffer(&xb, NULL, 0);
1118 xb_add_32(error, &xb, NFS_ARGSVERSION_XDR);
1119 argslength_offset = xb_offset(&xb);
1120 xb_add_32(error, &xb, 0); // args length
1121 xb_add_32(error, &xb, NFS_XDRARGS_VERSION_0);
1122 xb_add_bitmap(error, &xb, mattrs, NFS_MATTR_BITMAP_LEN);
1123 attrslength_offset = xb_offset(&xb);
1124 xb_add_32(error, &xb, 0); // attrs length
1125 xb_add_32(error, &xb, ndmntp->ndm_nfsv3 ? 3 : 2); // NFS version
1126 xb_add_string(error, &xb, ((ndmntp->ndm_sotype == SOCK_DGRAM) ? "udp" : "tcp"), 3);
1127 xb_add_32(error, &xb, ntohs(ndmntp->ndm_saddr.sin_port)); // NFS port
1128 xb_add_fh(error, &xb, &ndmntp->ndm_fh[0], ndmntp->ndm_fhlen);
1129 /* fs location */
1130 xb_add_32(error, &xb, 1); /* fs location count */
1131 xb_add_32(error, &xb, 1); /* server count */
1132 xb_add_string(error, &xb, ndmntp->ndm_mntfrom, (endserverp - ndmntp->ndm_mntfrom)); /* server name */
1133 xb_add_32(error, &xb, 1); /* address count */
1134 xb_add_string(error, &xb, uaddr, strlen(uaddr)); /* address */
1135 xb_add_32(error, &xb, 0); /* empty server info */
1136 xb_add_32(error, &xb, numcomps); /* pathname component count */
1137 p = frompath;
1138 while (*p && (*p == '/'))
1139 p++;
1140 while (*p) {
1141 cp = p;
1142 while (*p && (*p != '/'))
1143 p++;
1144 xb_add_string(error, &xb, cp, (p - cp)); /* component */
1145 if (error)
1146 break;
1147 while (*p && (*p == '/'))
1148 p++;
1149 }
1150 xb_add_32(error, &xb, 0); /* empty fsl info */
1151 xb_add_32(error, &xb, mntflag); /* MNT flags */
1152 xb_build_done(error, &xb);
1153
1154 /* update opaque counts */
1155 end_offset = xb_offset(&xb);
1156 if (!error) {
1157 error = xb_seek(&xb, argslength_offset);
1158 xb_add_32(error, &xb, end_offset - argslength_offset + XDRWORD/*version*/);
1159 }
1160 if (!error) {
1161 error = xb_seek(&xb, attrslength_offset);
1162 xb_add_32(error, &xb, end_offset - attrslength_offset - XDRWORD/*don't include length field*/);
1163 }
1164 if (error) {
1165 printf("nfs_mount_diskless: error %d assembling mount args\n", error);
1166 xb_cleanup(&xb);
1167 return (error);
1168 }
1169 /* grab the assembled buffer */
1170 xdrbuf = xb_buffer_base(&xb);
1171 xb.xb_flags &= ~XB_CLEANUP;
1172
1173 /* do the mount */
1174 if ((error = mountnfs(xdrbuf, mp, ctx, vpp))) {
1175 printf("nfs_mountroot: mount %s failed: %d\n", mntname, error);
1176 // XXX vfs_rootmountfailed(mp);
1177 mount_list_lock();
1178 mp->mnt_vtable->vfc_refcount--;
1179 mount_list_unlock();
1180 vfs_unbusy(mp);
1181 mount_lock_destroy(mp);
1182 #if CONFIG_MACF
1183 mac_mount_label_destroy(mp);
1184 #endif
1185 FREE_ZONE(mp, sizeof(struct mount), M_MOUNT);
1186 } else {
1187 *mpp = mp;
1188 }
1189 xb_cleanup(&xb);
1190 return (error);
1191 }
1192
1193 #if !defined(NO_MOUNT_PRIVATE)
1194 /*
1195 * Internal version of mount system call to mount "/private"
1196 * separately in diskless setup
1197 */
1198 static int
1199 nfs_mount_diskless_private(
1200 struct nfs_dlmount *ndmntp,
1201 const char *mntname,
1202 int mntflag,
1203 vnode_t *vpp,
1204 mount_t *mpp,
1205 vfs_context_t ctx)
1206 {
1207 mount_t mp;
1208 int error, numcomps;
1209 proc_t procp;
1210 struct vfstable *vfsp;
1211 struct nameidata nd;
1212 vnode_t vp;
1213 char *xdrbuf = NULL, *p, *cp, *frompath, *endserverp;
1214 char uaddr[MAX_IPv4_STR_LEN];
1215 struct xdrbuf xb;
1216 uint32_t mattrs[NFS_MATTR_BITMAP_LEN];
1217 uint32_t mflags_mask[NFS_MFLAG_BITMAP_LEN], mflags[NFS_MFLAG_BITMAP_LEN];
1218 uint32_t argslength_offset, attrslength_offset, end_offset;
1219
1220 procp = current_proc(); /* XXX */
1221 xb_init(&xb, 0);
1222
1223 {
1224 /*
1225 * mimic main()!. Temporarily set up rootvnode and other stuff so
1226 * that namei works. Need to undo this because main() does it, too
1227 */
1228 struct filedesc *fdp; /* pointer to file descriptor state */
1229 fdp = procp->p_fd;
1230 mountlist.tqh_first->mnt_flag |= MNT_ROOTFS;
1231
1232 /* Get the vnode for '/'. Set fdp->fd_cdir to reference it. */
1233 if (VFS_ROOT(mountlist.tqh_first, &rootvnode, NULL))
1234 panic("cannot find root vnode");
1235 error = vnode_ref(rootvnode);
1236 if (error) {
1237 printf("nfs_mountroot: vnode_ref() failed on root vnode!\n");
1238 goto out;
1239 }
1240 fdp->fd_cdir = rootvnode;
1241 fdp->fd_rdir = NULL;
1242 }
1243
1244 /*
1245 * Get vnode to be covered
1246 */
1247 NDINIT(&nd, LOOKUP, OP_LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE,
1248 CAST_USER_ADDR_T(mntname), ctx);
1249 if ((error = namei(&nd))) {
1250 printf("nfs_mountroot: private namei failed!\n");
1251 goto out;
1252 }
1253 {
1254 /* undo vnode_ref() in mimic main()! */
1255 vnode_rele(rootvnode);
1256 }
1257 nameidone(&nd);
1258 vp = nd.ni_vp;
1259
1260 if ((error = VNOP_FSYNC(vp, MNT_WAIT, ctx)) ||
1261 (error = buf_invalidateblks(vp, BUF_WRITE_DATA, 0, 0))) {
1262 vnode_put(vp);
1263 goto out;
1264 }
1265 if (vnode_vtype(vp) != VDIR) {
1266 vnode_put(vp);
1267 error = ENOTDIR;
1268 goto out;
1269 }
1270 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
1271 if (!strncmp(vfsp->vfc_name, "nfs", sizeof(vfsp->vfc_name)))
1272 break;
1273 if (vfsp == NULL) {
1274 printf("nfs_mountroot: private NFS not configured\n");
1275 vnode_put(vp);
1276 error = ENODEV;
1277 goto out;
1278 }
1279 if (vnode_mountedhere(vp) != NULL) {
1280 vnode_put(vp);
1281 error = EBUSY;
1282 goto out;
1283 }
1284
1285 /*
1286 * Allocate and initialize the filesystem.
1287 */
1288 mp = _MALLOC_ZONE((u_int32_t)sizeof(struct mount), M_MOUNT, M_WAITOK);
1289 if (!mp) {
1290 printf("nfs_mountroot: unable to allocate mount structure\n");
1291 vnode_put(vp);
1292 error = ENOMEM;
1293 goto out;
1294 }
1295 bzero((char *)mp, sizeof(struct mount));
1296
1297 /* Initialize the default IO constraints */
1298 mp->mnt_maxreadcnt = mp->mnt_maxwritecnt = MAXPHYS;
1299 mp->mnt_segreadcnt = mp->mnt_segwritecnt = 32;
1300 mp->mnt_ioflags = 0;
1301 mp->mnt_realrootvp = NULLVP;
1302 mp->mnt_authcache_ttl = CACHED_LOOKUP_RIGHT_TTL;
1303
1304 mount_lock_init(mp);
1305 TAILQ_INIT(&mp->mnt_vnodelist);
1306 TAILQ_INIT(&mp->mnt_workerqueue);
1307 TAILQ_INIT(&mp->mnt_newvnodes);
1308 (void)vfs_busy(mp, LK_NOWAIT);
1309 TAILQ_INIT(&mp->mnt_vnodelist);
1310 mount_list_lock();
1311 vfsp->vfc_refcount++;
1312 mount_list_unlock();
1313 mp->mnt_vtable = vfsp;
1314 mp->mnt_op = vfsp->vfc_vfsops;
1315 // mp->mnt_stat.f_type = vfsp->vfc_typenum;
1316 mp->mnt_flag = mntflag;
1317 mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
1318 strncpy(mp->mnt_vfsstat.f_fstypename, vfsp->vfc_name, MFSNAMELEN-1);
1319 vp->v_mountedhere = mp;
1320 mp->mnt_vnodecovered = vp;
1321 vp = NULLVP;
1322 mp->mnt_vfsstat.f_owner = kauth_cred_getuid(kauth_cred_get());
1323 (void) copystr(mntname, mp->mnt_vfsstat.f_mntonname, MAXPATHLEN - 1, 0);
1324 (void) copystr(ndmntp->ndm_mntfrom, mp->mnt_vfsstat.f_mntfromname, MAXPATHLEN - 1, 0);
1325 #if CONFIG_MACF
1326 mac_mount_label_init(mp);
1327 mac_mount_label_associate(ctx, mp);
1328 #endif
1329
1330 /* find the server-side path being mounted */
1331 frompath = ndmntp->ndm_mntfrom;
1332 if (*frompath == '[') { /* skip IPv6 literal address */
1333 while (*frompath && (*frompath != ']'))
1334 frompath++;
1335 if (*frompath == ']')
1336 frompath++;
1337 }
1338 while (*frompath && (*frompath != ':'))
1339 frompath++;
1340 endserverp = frompath;
1341 while (*frompath && (*frompath == ':'))
1342 frompath++;
1343 /* count fs location path components */
1344 p = frompath;
1345 while (*p && (*p == '/'))
1346 p++;
1347 numcomps = 0;
1348 while (*p) {
1349 numcomps++;
1350 while (*p && (*p != '/'))
1351 p++;
1352 while (*p && (*p == '/'))
1353 p++;
1354 }
1355
1356 /* convert address to universal address string */
1357 if (inet_ntop(AF_INET, &ndmntp->ndm_saddr.sin_addr, uaddr, sizeof(uaddr)) != uaddr) {
1358 printf("nfs_mountroot: bad address\n");
1359 error = EINVAL;
1360 goto out;
1361 }
1362
1363 /* prepare mount attributes */
1364 NFS_BITMAP_ZERO(mattrs, NFS_MATTR_BITMAP_LEN);
1365 NFS_BITMAP_SET(mattrs, NFS_MATTR_NFS_VERSION);
1366 NFS_BITMAP_SET(mattrs, NFS_MATTR_SOCKET_TYPE);
1367 NFS_BITMAP_SET(mattrs, NFS_MATTR_NFS_PORT);
1368 NFS_BITMAP_SET(mattrs, NFS_MATTR_FH);
1369 NFS_BITMAP_SET(mattrs, NFS_MATTR_FS_LOCATIONS);
1370 NFS_BITMAP_SET(mattrs, NFS_MATTR_MNTFLAGS);
1371
1372 /* prepare mount flags */
1373 NFS_BITMAP_ZERO(mflags_mask, NFS_MFLAG_BITMAP_LEN);
1374 NFS_BITMAP_ZERO(mflags, NFS_MFLAG_BITMAP_LEN);
1375 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_RESVPORT);
1376 NFS_BITMAP_SET(mflags, NFS_MFLAG_RESVPORT);
1377
1378 /* build xdr buffer */
1379 xb_init_buffer(&xb, NULL, 0);
1380 xb_add_32(error, &xb, NFS_ARGSVERSION_XDR);
1381 argslength_offset = xb_offset(&xb);
1382 xb_add_32(error, &xb, 0); // args length
1383 xb_add_32(error, &xb, NFS_XDRARGS_VERSION_0);
1384 xb_add_bitmap(error, &xb, mattrs, NFS_MATTR_BITMAP_LEN);
1385 attrslength_offset = xb_offset(&xb);
1386 xb_add_32(error, &xb, 0); // attrs length
1387 xb_add_32(error, &xb, ndmntp->ndm_nfsv3 ? 3 : 2); // NFS version
1388 xb_add_string(error, &xb, ((ndmntp->ndm_sotype == SOCK_DGRAM) ? "udp" : "tcp"), 3);
1389 xb_add_32(error, &xb, ntohs(ndmntp->ndm_saddr.sin_port)); // NFS port
1390 xb_add_fh(error, &xb, &ndmntp->ndm_fh[0], ndmntp->ndm_fhlen);
1391 /* fs location */
1392 xb_add_32(error, &xb, 1); /* fs location count */
1393 xb_add_32(error, &xb, 1); /* server count */
1394 xb_add_string(error, &xb, ndmntp->ndm_mntfrom, (endserverp - ndmntp->ndm_mntfrom)); /* server name */
1395 xb_add_32(error, &xb, 1); /* address count */
1396 xb_add_string(error, &xb, uaddr, strlen(uaddr)); /* address */
1397 xb_add_32(error, &xb, 0); /* empty server info */
1398 xb_add_32(error, &xb, numcomps); /* pathname component count */
1399 p = frompath;
1400 while (*p && (*p == '/'))
1401 p++;
1402 while (*p) {
1403 cp = p;
1404 while (*p && (*p != '/'))
1405 p++;
1406 xb_add_string(error, &xb, cp, (p - cp)); /* component */
1407 if (error)
1408 break;
1409 while (*p && (*p == '/'))
1410 p++;
1411 }
1412 xb_add_32(error, &xb, 0); /* empty fsl info */
1413 xb_add_32(error, &xb, mntflag); /* MNT flags */
1414 xb_build_done(error, &xb);
1415
1416 /* update opaque counts */
1417 end_offset = xb_offset(&xb);
1418 if (!error) {
1419 error = xb_seek(&xb, argslength_offset);
1420 xb_add_32(error, &xb, end_offset - argslength_offset + XDRWORD/*version*/);
1421 }
1422 if (!error) {
1423 error = xb_seek(&xb, attrslength_offset);
1424 xb_add_32(error, &xb, end_offset - attrslength_offset - XDRWORD/*don't include length field*/);
1425 }
1426 if (error) {
1427 printf("nfs_mountroot: error %d assembling mount args\n", error);
1428 goto out;
1429 }
1430 /* grab the assembled buffer */
1431 xdrbuf = xb_buffer_base(&xb);
1432 xb.xb_flags &= ~XB_CLEANUP;
1433
1434 /* do the mount */
1435 if ((error = mountnfs(xdrbuf, mp, ctx, &vp))) {
1436 printf("nfs_mountroot: mount %s failed: %d\n", mntname, error);
1437 vnode_put(mp->mnt_vnodecovered);
1438 mount_list_lock();
1439 vfsp->vfc_refcount--;
1440 mount_list_unlock();
1441 vfs_unbusy(mp);
1442 mount_lock_destroy(mp);
1443 #if CONFIG_MACF
1444 mac_mount_label_destroy(mp);
1445 #endif
1446 FREE_ZONE(mp, sizeof (struct mount), M_MOUNT);
1447 goto out;
1448 }
1449
1450 *mpp = mp;
1451 *vpp = vp;
1452 out:
1453 xb_cleanup(&xb);
1454 return (error);
1455 }
1456 #endif /* NO_MOUNT_PRIVATE */
1457
1458 /*
1459 * Convert old style NFS mount args to XDR.
1460 */
1461 static int
1462 nfs_convert_old_nfs_args(mount_t mp, user_addr_t data, vfs_context_t ctx, int argsversion, int inkernel, char **xdrbufp)
1463 {
1464 int error = 0, args64bit, argsize, numcomps;
1465 struct user_nfs_args args;
1466 struct nfs_args tempargs;
1467 caddr_t argsp;
1468 size_t len;
1469 u_char nfh[NFS4_FHSIZE];
1470 char *mntfrom, *endserverp, *frompath, *p, *cp;
1471 struct sockaddr_storage ss;
1472 void *sinaddr;
1473 char uaddr[MAX_IPv6_STR_LEN];
1474 uint32_t mattrs[NFS_MATTR_BITMAP_LEN];
1475 uint32_t mflags_mask[NFS_MFLAG_BITMAP_LEN], mflags[NFS_MFLAG_BITMAP_LEN];
1476 uint32_t nfsvers, nfslockmode = 0, argslength_offset, attrslength_offset, end_offset;
1477 struct xdrbuf xb;
1478
1479 *xdrbufp = NULL;
1480
1481 /* allocate a temporary buffer for mntfrom */
1482 MALLOC_ZONE(mntfrom, char*, MAXPATHLEN, M_NAMEI, M_WAITOK);
1483 if (!mntfrom)
1484 return (ENOMEM);
1485
1486 args64bit = (inkernel || vfs_context_is64bit(ctx));
1487 argsp = args64bit ? (void*)&args : (void*)&tempargs;
1488
1489 argsize = args64bit ? sizeof(args) : sizeof(tempargs);
1490 switch (argsversion) {
1491 case 3:
1492 argsize -= NFS_ARGSVERSION4_INCSIZE;
1493 case 4:
1494 argsize -= NFS_ARGSVERSION5_INCSIZE;
1495 case 5:
1496 argsize -= NFS_ARGSVERSION6_INCSIZE;
1497 case 6:
1498 break;
1499 default:
1500 error = EPROGMISMATCH;
1501 goto nfsmout;
1502 }
1503
1504 /* read in the structure */
1505 if (inkernel)
1506 bcopy(CAST_DOWN(void *, data), argsp, argsize);
1507 else
1508 error = copyin(data, argsp, argsize);
1509 nfsmout_if(error);
1510
1511 if (!args64bit) {
1512 args.addrlen = tempargs.addrlen;
1513 args.sotype = tempargs.sotype;
1514 args.proto = tempargs.proto;
1515 args.fhsize = tempargs.fhsize;
1516 args.flags = tempargs.flags;
1517 args.wsize = tempargs.wsize;
1518 args.rsize = tempargs.rsize;
1519 args.readdirsize = tempargs.readdirsize;
1520 args.timeo = tempargs.timeo;
1521 args.retrans = tempargs.retrans;
1522 args.maxgrouplist = tempargs.maxgrouplist;
1523 args.readahead = tempargs.readahead;
1524 args.leaseterm = tempargs.leaseterm;
1525 args.deadthresh = tempargs.deadthresh;
1526 args.addr = CAST_USER_ADDR_T(tempargs.addr);
1527 args.fh = CAST_USER_ADDR_T(tempargs.fh);
1528 args.hostname = CAST_USER_ADDR_T(tempargs.hostname);
1529 if (args.version >= 4) {
1530 args.acregmin = tempargs.acregmin;
1531 args.acregmax = tempargs.acregmax;
1532 args.acdirmin = tempargs.acdirmin;
1533 args.acdirmax = tempargs.acdirmax;
1534 }
1535 if (args.version >= 5)
1536 args.auth = tempargs.auth;
1537 if (args.version >= 6)
1538 args.deadtimeout = tempargs.deadtimeout;
1539 }
1540
1541 if ((args.fhsize < 0) || (args.fhsize > NFS4_FHSIZE)) {
1542 error = EINVAL;
1543 goto nfsmout;
1544 }
1545 if (args.fhsize > 0) {
1546 if (inkernel)
1547 bcopy(CAST_DOWN(void *, args.fh), (caddr_t)nfh, args.fhsize);
1548 else
1549 error = copyin(args.fh, (caddr_t)nfh, args.fhsize);
1550 nfsmout_if(error);
1551 }
1552
1553 if (inkernel)
1554 error = copystr(CAST_DOWN(void *, args.hostname), mntfrom, MAXPATHLEN-1, &len);
1555 else
1556 error = copyinstr(args.hostname, mntfrom, MAXPATHLEN-1, &len);
1557 nfsmout_if(error);
1558 bzero(&mntfrom[len], MAXPATHLEN - len);
1559
1560 /* find the server-side path being mounted */
1561 frompath = mntfrom;
1562 if (*frompath == '[') { /* skip IPv6 literal address */
1563 while (*frompath && (*frompath != ']'))
1564 frompath++;
1565 if (*frompath == ']')
1566 frompath++;
1567 }
1568 while (*frompath && (*frompath != ':'))
1569 frompath++;
1570 endserverp = frompath;
1571 while (*frompath && (*frompath == ':'))
1572 frompath++;
1573 /* count fs location path components */
1574 p = frompath;
1575 while (*p && (*p == '/'))
1576 p++;
1577 numcomps = 0;
1578 while (*p) {
1579 numcomps++;
1580 while (*p && (*p != '/'))
1581 p++;
1582 while (*p && (*p == '/'))
1583 p++;
1584 }
1585
1586 /* copy socket address */
1587 if (inkernel)
1588 bcopy(CAST_DOWN(void *, args.addr), &ss, args.addrlen);
1589 else {
1590 if ((size_t)args.addrlen > sizeof (struct sockaddr_storage))
1591 error = EINVAL;
1592 else
1593 error = copyin(args.addr, &ss, args.addrlen);
1594 }
1595 nfsmout_if(error);
1596 ss.ss_len = args.addrlen;
1597
1598 /* convert address to universal address string */
1599 if (ss.ss_family == AF_INET)
1600 sinaddr = &((struct sockaddr_in*)&ss)->sin_addr;
1601 else if (ss.ss_family == AF_INET6)
1602 sinaddr = &((struct sockaddr_in6*)&ss)->sin6_addr;
1603 else
1604 sinaddr = NULL;
1605 if (!sinaddr || (inet_ntop(ss.ss_family, sinaddr, uaddr, sizeof(uaddr)) != uaddr)) {
1606 error = EINVAL;
1607 goto nfsmout;
1608 }
1609
1610 /* prepare mount flags */
1611 NFS_BITMAP_ZERO(mflags_mask, NFS_MFLAG_BITMAP_LEN);
1612 NFS_BITMAP_ZERO(mflags, NFS_MFLAG_BITMAP_LEN);
1613 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_SOFT);
1614 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_INTR);
1615 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_RESVPORT);
1616 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_NOCONNECT);
1617 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_DUMBTIMER);
1618 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_CALLUMNT);
1619 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_RDIRPLUS);
1620 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_NONEGNAMECACHE);
1621 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_MUTEJUKEBOX);
1622 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_NOQUOTA);
1623 if (args.flags & NFSMNT_SOFT)
1624 NFS_BITMAP_SET(mflags, NFS_MFLAG_SOFT);
1625 if (args.flags & NFSMNT_INT)
1626 NFS_BITMAP_SET(mflags, NFS_MFLAG_INTR);
1627 if (args.flags & NFSMNT_RESVPORT)
1628 NFS_BITMAP_SET(mflags, NFS_MFLAG_RESVPORT);
1629 if (args.flags & NFSMNT_NOCONN)
1630 NFS_BITMAP_SET(mflags, NFS_MFLAG_NOCONNECT);
1631 if (args.flags & NFSMNT_DUMBTIMR)
1632 NFS_BITMAP_SET(mflags, NFS_MFLAG_DUMBTIMER);
1633 if (args.flags & NFSMNT_CALLUMNT)
1634 NFS_BITMAP_SET(mflags, NFS_MFLAG_CALLUMNT);
1635 if (args.flags & NFSMNT_RDIRPLUS)
1636 NFS_BITMAP_SET(mflags, NFS_MFLAG_RDIRPLUS);
1637 if (args.flags & NFSMNT_NONEGNAMECACHE)
1638 NFS_BITMAP_SET(mflags, NFS_MFLAG_NONEGNAMECACHE);
1639 if (args.flags & NFSMNT_MUTEJUKEBOX)
1640 NFS_BITMAP_SET(mflags, NFS_MFLAG_MUTEJUKEBOX);
1641 if (args.flags & NFSMNT_NOQUOTA)
1642 NFS_BITMAP_SET(mflags, NFS_MFLAG_NOQUOTA);
1643
1644 /* prepare mount attributes */
1645 NFS_BITMAP_ZERO(mattrs, NFS_MATTR_BITMAP_LEN);
1646 NFS_BITMAP_SET(mattrs, NFS_MATTR_FLAGS);
1647 NFS_BITMAP_SET(mattrs, NFS_MATTR_NFS_VERSION);
1648 NFS_BITMAP_SET(mattrs, NFS_MATTR_SOCKET_TYPE);
1649 NFS_BITMAP_SET(mattrs, NFS_MATTR_NFS_PORT);
1650 NFS_BITMAP_SET(mattrs, NFS_MATTR_FH);
1651 NFS_BITMAP_SET(mattrs, NFS_MATTR_FS_LOCATIONS);
1652 NFS_BITMAP_SET(mattrs, NFS_MATTR_MNTFLAGS);
1653 NFS_BITMAP_SET(mattrs, NFS_MATTR_MNTFROM);
1654 if (args.flags & NFSMNT_NFSV4)
1655 nfsvers = 4;
1656 else if (args.flags & NFSMNT_NFSV3)
1657 nfsvers = 3;
1658 else
1659 nfsvers = 2;
1660 if ((args.flags & NFSMNT_RSIZE) && (args.rsize > 0))
1661 NFS_BITMAP_SET(mattrs, NFS_MATTR_READ_SIZE);
1662 if ((args.flags & NFSMNT_WSIZE) && (args.wsize > 0))
1663 NFS_BITMAP_SET(mattrs, NFS_MATTR_WRITE_SIZE);
1664 if ((args.flags & NFSMNT_TIMEO) && (args.timeo > 0))
1665 NFS_BITMAP_SET(mattrs, NFS_MATTR_REQUEST_TIMEOUT);
1666 if ((args.flags & NFSMNT_RETRANS) && (args.retrans > 0))
1667 NFS_BITMAP_SET(mattrs, NFS_MATTR_SOFT_RETRY_COUNT);
1668 if ((args.flags & NFSMNT_MAXGRPS) && (args.maxgrouplist > 0))
1669 NFS_BITMAP_SET(mattrs, NFS_MATTR_MAX_GROUP_LIST);
1670 if ((args.flags & NFSMNT_READAHEAD) && (args.readahead > 0))
1671 NFS_BITMAP_SET(mattrs, NFS_MATTR_READAHEAD);
1672 if ((args.flags & NFSMNT_READDIRSIZE) && (args.readdirsize > 0))
1673 NFS_BITMAP_SET(mattrs, NFS_MATTR_READDIR_SIZE);
1674 if ((args.flags & NFSMNT_NOLOCKS) ||
1675 (args.flags & NFSMNT_LOCALLOCKS)) {
1676 NFS_BITMAP_SET(mattrs, NFS_MATTR_LOCK_MODE);
1677 if (args.flags & NFSMNT_NOLOCKS)
1678 nfslockmode = NFS_LOCK_MODE_DISABLED;
1679 else if (args.flags & NFSMNT_LOCALLOCKS)
1680 nfslockmode = NFS_LOCK_MODE_LOCAL;
1681 else
1682 nfslockmode = NFS_LOCK_MODE_ENABLED;
1683 }
1684 if (args.version >= 4) {
1685 if ((args.flags & NFSMNT_ACREGMIN) && (args.acregmin > 0))
1686 NFS_BITMAP_SET(mattrs, NFS_MATTR_ATTRCACHE_REG_MIN);
1687 if ((args.flags & NFSMNT_ACREGMAX) && (args.acregmax > 0))
1688 NFS_BITMAP_SET(mattrs, NFS_MATTR_ATTRCACHE_REG_MAX);
1689 if ((args.flags & NFSMNT_ACDIRMIN) && (args.acdirmin > 0))
1690 NFS_BITMAP_SET(mattrs, NFS_MATTR_ATTRCACHE_DIR_MIN);
1691 if ((args.flags & NFSMNT_ACDIRMAX) && (args.acdirmax > 0))
1692 NFS_BITMAP_SET(mattrs, NFS_MATTR_ATTRCACHE_DIR_MAX);
1693 }
1694 if (args.version >= 5) {
1695 if ((args.flags & NFSMNT_SECFLAVOR) || (args.flags & NFSMNT_SECSYSOK))
1696 NFS_BITMAP_SET(mattrs, NFS_MATTR_SECURITY);
1697 }
1698 if (args.version >= 6) {
1699 if ((args.flags & NFSMNT_DEADTIMEOUT) && (args.deadtimeout > 0))
1700 NFS_BITMAP_SET(mattrs, NFS_MATTR_DEAD_TIMEOUT);
1701 }
1702
1703 /* build xdr buffer */
1704 xb_init_buffer(&xb, NULL, 0);
1705 xb_add_32(error, &xb, args.version);
1706 argslength_offset = xb_offset(&xb);
1707 xb_add_32(error, &xb, 0); // args length
1708 xb_add_32(error, &xb, NFS_XDRARGS_VERSION_0);
1709 xb_add_bitmap(error, &xb, mattrs, NFS_MATTR_BITMAP_LEN);
1710 attrslength_offset = xb_offset(&xb);
1711 xb_add_32(error, &xb, 0); // attrs length
1712 xb_add_bitmap(error, &xb, mflags_mask, NFS_MFLAG_BITMAP_LEN); /* mask */
1713 xb_add_bitmap(error, &xb, mflags, NFS_MFLAG_BITMAP_LEN); /* value */
1714 xb_add_32(error, &xb, nfsvers);
1715 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_READ_SIZE))
1716 xb_add_32(error, &xb, args.rsize);
1717 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_WRITE_SIZE))
1718 xb_add_32(error, &xb, args.wsize);
1719 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_READDIR_SIZE))
1720 xb_add_32(error, &xb, args.readdirsize);
1721 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_READAHEAD))
1722 xb_add_32(error, &xb, args.readahead);
1723 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_ATTRCACHE_REG_MIN)) {
1724 xb_add_32(error, &xb, args.acregmin);
1725 xb_add_32(error, &xb, 0);
1726 }
1727 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_ATTRCACHE_REG_MAX)) {
1728 xb_add_32(error, &xb, args.acregmax);
1729 xb_add_32(error, &xb, 0);
1730 }
1731 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_ATTRCACHE_DIR_MIN)) {
1732 xb_add_32(error, &xb, args.acdirmin);
1733 xb_add_32(error, &xb, 0);
1734 }
1735 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_ATTRCACHE_DIR_MAX)) {
1736 xb_add_32(error, &xb, args.acdirmax);
1737 xb_add_32(error, &xb, 0);
1738 }
1739 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_LOCK_MODE))
1740 xb_add_32(error, &xb, nfslockmode);
1741 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_SECURITY)) {
1742 uint32_t flavors[2], i=0;
1743 if (args.flags & NFSMNT_SECFLAVOR)
1744 flavors[i++] = args.auth;
1745 if ((args.flags & NFSMNT_SECSYSOK) && ((i == 0) || (flavors[0] != RPCAUTH_SYS)))
1746 flavors[i++] = RPCAUTH_SYS;
1747 xb_add_word_array(error, &xb, flavors, i);
1748 }
1749 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_MAX_GROUP_LIST))
1750 xb_add_32(error, &xb, args.maxgrouplist);
1751 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_SOCKET_TYPE))
1752 xb_add_string(error, &xb, ((args.sotype == SOCK_DGRAM) ? "udp" : "tcp"), 3);
1753 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_NFS_PORT))
1754 xb_add_32(error, &xb, ((ss.ss_family == AF_INET) ?
1755 ntohs(((struct sockaddr_in*)&ss)->sin_port) :
1756 ntohs(((struct sockaddr_in6*)&ss)->sin6_port)));
1757 /* NFS_MATTR_MOUNT_PORT (not available in old args) */
1758 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_REQUEST_TIMEOUT)) {
1759 /* convert from .1s increments to time */
1760 xb_add_32(error, &xb, args.timeo/10);
1761 xb_add_32(error, &xb, (args.timeo%10)*100000000);
1762 }
1763 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_SOFT_RETRY_COUNT))
1764 xb_add_32(error, &xb, args.retrans);
1765 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_DEAD_TIMEOUT)) {
1766 xb_add_32(error, &xb, args.deadtimeout);
1767 xb_add_32(error, &xb, 0);
1768 }
1769 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_FH))
1770 xb_add_fh(error, &xb, &nfh[0], args.fhsize);
1771 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_FS_LOCATIONS)) {
1772 xb_add_32(error, &xb, 1); /* fs location count */
1773 xb_add_32(error, &xb, 1); /* server count */
1774 xb_add_string(error, &xb, mntfrom, (endserverp - mntfrom)); /* server name */
1775 xb_add_32(error, &xb, 1); /* address count */
1776 xb_add_string(error, &xb, uaddr, strlen(uaddr)); /* address */
1777 xb_add_32(error, &xb, 0); /* empty server info */
1778 xb_add_32(error, &xb, numcomps); /* pathname component count */
1779 nfsmout_if(error);
1780 p = frompath;
1781 while (*p && (*p == '/'))
1782 p++;
1783 while (*p) {
1784 cp = p;
1785 while (*p && (*p != '/'))
1786 p++;
1787 xb_add_string(error, &xb, cp, (p - cp)); /* component */
1788 nfsmout_if(error);
1789 while (*p && (*p == '/'))
1790 p++;
1791 }
1792 xb_add_32(error, &xb, 0); /* empty fsl info */
1793 }
1794 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_MNTFLAGS))
1795 xb_add_32(error, &xb, (vfs_flags(mp) & MNT_VISFLAGMASK)); /* VFS MNT_* flags */
1796 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_MNTFROM))
1797 xb_add_string(error, &xb, mntfrom, strlen(mntfrom)); /* fixed f_mntfromname */
1798 xb_build_done(error, &xb);
1799
1800 /* update opaque counts */
1801 end_offset = xb_offset(&xb);
1802 error = xb_seek(&xb, argslength_offset);
1803 xb_add_32(error, &xb, end_offset - argslength_offset + XDRWORD/*version*/);
1804 nfsmout_if(error);
1805 error = xb_seek(&xb, attrslength_offset);
1806 xb_add_32(error, &xb, end_offset - attrslength_offset - XDRWORD/*don't include length field*/);
1807
1808 if (!error) {
1809 /* grab the assembled buffer */
1810 *xdrbufp = xb_buffer_base(&xb);
1811 xb.xb_flags &= ~XB_CLEANUP;
1812 }
1813 nfsmout:
1814 xb_cleanup(&xb);
1815 FREE_ZONE(mntfrom, MAXPATHLEN, M_NAMEI);
1816 return (error);
1817 }
1818
1819 /*
1820 * VFS Operations.
1821 *
1822 * mount system call
1823 */
1824 int
1825 nfs_vfs_mount(mount_t mp, vnode_t vp, user_addr_t data, vfs_context_t ctx)
1826 {
1827 int error = 0, inkernel = vfs_iskernelmount(mp);
1828 uint32_t argsversion, argslength;
1829 char *xdrbuf = NULL;
1830
1831 /* read in version */
1832 if (inkernel)
1833 bcopy(CAST_DOWN(void *, data), &argsversion, sizeof(argsversion));
1834 else if ((error = copyin(data, &argsversion, sizeof(argsversion))))
1835 return (error);
1836
1837 /* If we have XDR args, then all values in the buffer are in network order */
1838 if (argsversion == htonl(NFS_ARGSVERSION_XDR))
1839 argsversion = NFS_ARGSVERSION_XDR;
1840
1841 switch (argsversion) {
1842 case 3:
1843 case 4:
1844 case 5:
1845 case 6:
1846 /* convert old-style args to xdr */
1847 error = nfs_convert_old_nfs_args(mp, data, ctx, argsversion, inkernel, &xdrbuf);
1848 break;
1849 case NFS_ARGSVERSION_XDR:
1850 /* copy in xdr buffer */
1851 if (inkernel)
1852 bcopy(CAST_DOWN(void *, (data + XDRWORD)), &argslength, XDRWORD);
1853 else
1854 error = copyin((data + XDRWORD), &argslength, XDRWORD);
1855 if (error)
1856 break;
1857 argslength = ntohl(argslength);
1858 /* put a reasonable limit on the size of the XDR args */
1859 if (argslength > 16*1024) {
1860 error = E2BIG;
1861 break;
1862 }
1863 /* allocate xdr buffer */
1864 xdrbuf = xb_malloc(xdr_rndup(argslength));
1865 if (!xdrbuf) {
1866 error = ENOMEM;
1867 break;
1868 }
1869 if (inkernel)
1870 bcopy(CAST_DOWN(void *, data), xdrbuf, argslength);
1871 else
1872 error = copyin(data, xdrbuf, argslength);
1873 break;
1874 default:
1875 error = EPROGMISMATCH;
1876 }
1877
1878 if (error) {
1879 if (xdrbuf)
1880 xb_free(xdrbuf);
1881 return (error);
1882 }
1883 error = mountnfs(xdrbuf, mp, ctx, &vp);
1884 return (error);
1885 }
1886
1887 /*
1888 * Common code for mount and mountroot
1889 */
1890
1891 /* Set up an NFSv2/v3 mount */
1892 int
1893 nfs3_mount(
1894 struct nfsmount *nmp,
1895 vfs_context_t ctx,
1896 nfsnode_t *npp)
1897 {
1898 int error = 0;
1899 struct nfs_vattr nvattr;
1900 u_int64_t xid;
1901
1902 *npp = NULL;
1903
1904 if (!nmp->nm_fh)
1905 return (EINVAL);
1906
1907 /*
1908 * Get file attributes for the mountpoint. These are needed
1909 * in order to properly create the root vnode.
1910 */
1911 error = nfs3_getattr_rpc(NULL, nmp->nm_mountp, nmp->nm_fh->fh_data, nmp->nm_fh->fh_len, 0,
1912 ctx, &nvattr, &xid);
1913 if (error)
1914 goto out;
1915
1916 error = nfs_nget(nmp->nm_mountp, NULL, NULL, nmp->nm_fh->fh_data, nmp->nm_fh->fh_len,
1917 &nvattr, &xid, RPCAUTH_UNKNOWN, NG_MARKROOT, npp);
1918 if (*npp)
1919 nfs_node_unlock(*npp);
1920 if (error)
1921 goto out;
1922
1923 /*
1924 * Try to make sure we have all the general info from the server.
1925 */
1926 if (nmp->nm_vers == NFS_VER2) {
1927 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_MAXNAME);
1928 nmp->nm_fsattr.nfsa_maxname = NFS_MAXNAMLEN;
1929 } else if (nmp->nm_vers == NFS_VER3) {
1930 /* get the NFSv3 FSINFO */
1931 error = nfs3_fsinfo(nmp, *npp, ctx);
1932 if (error)
1933 goto out;
1934 /* If the server indicates all pathconf info is */
1935 /* the same, grab a copy of that info now */
1936 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_HOMOGENEOUS) &&
1937 (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_HOMOGENEOUS)) {
1938 struct nfs_fsattr nfsa;
1939 if (!nfs3_pathconf_rpc(*npp, &nfsa, ctx)) {
1940 /* cache a copy of the results */
1941 lck_mtx_lock(&nmp->nm_lock);
1942 nfs3_pathconf_cache(nmp, &nfsa);
1943 lck_mtx_unlock(&nmp->nm_lock);
1944 }
1945 }
1946 }
1947 out:
1948 if (*npp && error) {
1949 vnode_put(NFSTOV(*npp));
1950 vnode_recycle(NFSTOV(*npp));
1951 *npp = NULL;
1952 }
1953 return (error);
1954 }
1955
1956 /*
1957 * Update an NFSv4 mount path with the contents of the symlink.
1958 *
1959 * Read the link for the given file handle.
1960 * Insert the link's components into the path.
1961 */
1962 int
1963 nfs4_mount_update_path_with_symlink(struct nfsmount *nmp, struct nfs_fs_path *nfsp, uint32_t curcomp, fhandle_t *dirfhp, int *depthp, fhandle_t *fhp, vfs_context_t ctx)
1964 {
1965 int error = 0, status, numops;
1966 uint32_t len = 0, comp, newcomp, linkcompcount;
1967 u_int64_t xid;
1968 struct nfsm_chain nmreq, nmrep;
1969 struct nfsreq rq, *req = &rq;
1970 struct nfsreq_secinfo_args si;
1971 char *link = NULL, *p, *q, ch;
1972 struct nfs_fs_path nfsp2;
1973
1974 bzero(&nfsp2, sizeof(nfsp2));
1975 if (dirfhp->fh_len)
1976 NFSREQ_SECINFO_SET(&si, NULL, dirfhp->fh_data, dirfhp->fh_len, nfsp->np_components[curcomp], 0);
1977 else
1978 NFSREQ_SECINFO_SET(&si, NULL, NULL, 0, nfsp->np_components[curcomp], 0);
1979 nfsm_chain_null(&nmreq);
1980 nfsm_chain_null(&nmrep);
1981
1982 MALLOC_ZONE(link, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
1983 if (!link)
1984 error = ENOMEM;
1985
1986 // PUTFH, READLINK
1987 numops = 2;
1988 nfsm_chain_build_alloc_init(error, &nmreq, 12 * NFSX_UNSIGNED);
1989 nfsm_chain_add_compound_header(error, &nmreq, "readlink", numops);
1990 numops--;
1991 nfsm_chain_add_32(error, &nmreq, NFS_OP_PUTFH);
1992 nfsm_chain_add_fh(error, &nmreq, NFS_VER4, fhp->fh_data, fhp->fh_len);
1993 numops--;
1994 nfsm_chain_add_32(error, &nmreq, NFS_OP_READLINK);
1995 nfsm_chain_build_done(error, &nmreq);
1996 nfsm_assert(error, (numops == 0), EPROTO);
1997 nfsmout_if(error);
1998
1999 error = nfs_request_async(NULL, nmp->nm_mountp, &nmreq, NFSPROC4_COMPOUND,
2000 vfs_context_thread(ctx), vfs_context_ucred(ctx), &si, 0, NULL, &req);
2001 if (!error)
2002 error = nfs_request_async_finish(req, &nmrep, &xid, &status);
2003
2004 nfsm_chain_skip_tag(error, &nmrep);
2005 nfsm_chain_get_32(error, &nmrep, numops);
2006 nfsm_chain_op_check(error, &nmrep, NFS_OP_PUTFH);
2007 nfsm_chain_op_check(error, &nmrep, NFS_OP_READLINK);
2008 nfsm_chain_get_32(error, &nmrep, len);
2009 nfsmout_if(error);
2010 if (len == 0)
2011 error = ENOENT;
2012 else if (len >= MAXPATHLEN)
2013 len = MAXPATHLEN - 1;
2014 nfsm_chain_get_opaque(error, &nmrep, len, link);
2015 nfsmout_if(error);
2016 /* make sure link string is terminated properly */
2017 link[len] = '\0';
2018
2019 /* count the number of components in link */
2020 p = link;
2021 while (*p && (*p == '/'))
2022 p++;
2023 linkcompcount = 0;
2024 while (*p) {
2025 linkcompcount++;
2026 while (*p && (*p != '/'))
2027 p++;
2028 while (*p && (*p == '/'))
2029 p++;
2030 }
2031
2032 /* free up used components */
2033 for (comp=0; comp <= curcomp; comp++) {
2034 if (nfsp->np_components[comp]) {
2035 FREE(nfsp->np_components[comp], M_TEMP);
2036 nfsp->np_components[comp] = NULL;
2037 }
2038 }
2039
2040 /* set up new path */
2041 nfsp2.np_compcount = nfsp->np_compcount - curcomp - 1 + linkcompcount;
2042 MALLOC(nfsp2.np_components, char **, nfsp2.np_compcount*sizeof(char*), M_TEMP, M_WAITOK|M_ZERO);
2043 if (!nfsp2.np_components) {
2044 error = ENOMEM;
2045 goto nfsmout;
2046 }
2047
2048 /* add link components */
2049 p = link;
2050 while (*p && (*p == '/'))
2051 p++;
2052 for (newcomp=0; newcomp < linkcompcount; newcomp++) {
2053 /* find end of component */
2054 q = p;
2055 while (*q && (*q != '/'))
2056 q++;
2057 MALLOC(nfsp2.np_components[newcomp], char *, q-p+1, M_TEMP, M_WAITOK|M_ZERO);
2058 if (!nfsp2.np_components[newcomp]) {
2059 error = ENOMEM;
2060 break;
2061 }
2062 ch = *q;
2063 *q = '\0';
2064 strlcpy(nfsp2.np_components[newcomp], p, q-p+1);
2065 *q = ch;
2066 p = q;
2067 while (*p && (*p == '/'))
2068 p++;
2069 }
2070 nfsmout_if(error);
2071
2072 /* add remaining components */
2073 for(comp = curcomp + 1; comp < nfsp->np_compcount; comp++,newcomp++) {
2074 nfsp2.np_components[newcomp] = nfsp->np_components[comp];
2075 nfsp->np_components[comp] = NULL;
2076 }
2077
2078 /* move new path into place */
2079 FREE(nfsp->np_components, M_TEMP);
2080 nfsp->np_components = nfsp2.np_components;
2081 nfsp->np_compcount = nfsp2.np_compcount;
2082 nfsp2.np_components = NULL;
2083
2084 /* for absolute link, let the caller now that the next dirfh is root */
2085 if (link[0] == '/') {
2086 dirfhp->fh_len = 0;
2087 *depthp = 0;
2088 }
2089 nfsmout:
2090 if (link)
2091 FREE_ZONE(link, MAXPATHLEN, M_NAMEI);
2092 if (nfsp2.np_components) {
2093 for (comp=0; comp < nfsp2.np_compcount; comp++)
2094 if (nfsp2.np_components[comp])
2095 FREE(nfsp2.np_components[comp], M_TEMP);
2096 FREE(nfsp2.np_components, M_TEMP);
2097 }
2098 nfsm_chain_cleanup(&nmreq);
2099 nfsm_chain_cleanup(&nmrep);
2100 return (error);
2101 }
2102
2103 /* Set up an NFSv4 mount */
2104 int
2105 nfs4_mount(
2106 struct nfsmount *nmp,
2107 vfs_context_t ctx,
2108 nfsnode_t *npp)
2109 {
2110 struct nfsm_chain nmreq, nmrep;
2111 int error = 0, numops, status, interval, isdotdot, loopcnt = 0, depth = 0;
2112 struct nfs_fs_path fspath, *nfsp, fspath2;
2113 uint32_t bitmap[NFS_ATTR_BITMAP_LEN], comp, comp2;
2114 fhandle_t fh, dirfh;
2115 struct nfs_vattr nvattr;
2116 u_int64_t xid;
2117 struct nfsreq rq, *req = &rq;
2118 struct nfsreq_secinfo_args si;
2119 struct nfs_sec sec;
2120 struct nfs_fs_locations nfsls;
2121
2122 *npp = NULL;
2123 fh.fh_len = dirfh.fh_len = 0;
2124 TAILQ_INIT(&nmp->nm_open_owners);
2125 TAILQ_INIT(&nmp->nm_delegations);
2126 TAILQ_INIT(&nmp->nm_dreturnq);
2127 nmp->nm_stategenid = 1;
2128 NVATTR_INIT(&nvattr);
2129 bzero(&nfsls, sizeof(nfsls));
2130 nfsm_chain_null(&nmreq);
2131 nfsm_chain_null(&nmrep);
2132
2133 /*
2134 * If no security flavors were specified we'll want to default to the server's
2135 * preferred flavor. For NFSv4.0 we need a file handle and name to get that via
2136 * SECINFO, so we'll do that on the last component of the server path we are
2137 * mounting. If we are mounting the server's root, we'll need to defer the
2138 * SECINFO call to the first successful LOOKUP request.
2139 */
2140 if (!nmp->nm_sec.count)
2141 nmp->nm_state |= NFSSTA_NEEDSECINFO;
2142
2143 /* make a copy of the current location's path */
2144 nfsp = &nmp->nm_locations.nl_locations[nmp->nm_locations.nl_current.nli_loc]->nl_path;
2145 bzero(&fspath, sizeof(fspath));
2146 fspath.np_compcount = nfsp->np_compcount;
2147 if (fspath.np_compcount > 0) {
2148 MALLOC(fspath.np_components, char **, fspath.np_compcount*sizeof(char*), M_TEMP, M_WAITOK|M_ZERO);
2149 if (!fspath.np_components) {
2150 error = ENOMEM;
2151 goto nfsmout;
2152 }
2153 for (comp=0; comp < nfsp->np_compcount; comp++) {
2154 int slen = strlen(nfsp->np_components[comp]);
2155 MALLOC(fspath.np_components[comp], char *, slen+1, M_TEMP, M_WAITOK|M_ZERO);
2156 if (!fspath.np_components[comp]) {
2157 error = ENOMEM;
2158 break;
2159 }
2160 strlcpy(fspath.np_components[comp], nfsp->np_components[comp], slen+1);
2161 }
2162 if (error)
2163 goto nfsmout;
2164 }
2165
2166 /* for mirror mounts, we can just use the file handle passed in */
2167 if (nmp->nm_fh) {
2168 dirfh.fh_len = nmp->nm_fh->fh_len;
2169 bcopy(nmp->nm_fh->fh_data, dirfh.fh_data, dirfh.fh_len);
2170 NFSREQ_SECINFO_SET(&si, NULL, dirfh.fh_data, dirfh.fh_len, NULL, 0);
2171 goto gotfh;
2172 }
2173
2174 /* otherwise, we need to get the fh for the directory we are mounting */
2175
2176 /* if no components, just get root */
2177 if (fspath.np_compcount == 0) {
2178 nocomponents:
2179 // PUTROOTFH + GETATTR(FH)
2180 NFSREQ_SECINFO_SET(&si, NULL, NULL, 0, NULL, 0);
2181 numops = 2;
2182 nfsm_chain_build_alloc_init(error, &nmreq, 9 * NFSX_UNSIGNED);
2183 nfsm_chain_add_compound_header(error, &nmreq, "mount", numops);
2184 numops--;
2185 nfsm_chain_add_32(error, &nmreq, NFS_OP_PUTROOTFH);
2186 numops--;
2187 nfsm_chain_add_32(error, &nmreq, NFS_OP_GETATTR);
2188 NFS_CLEAR_ATTRIBUTES(bitmap);
2189 NFS4_DEFAULT_ATTRIBUTES(bitmap);
2190 NFS_BITMAP_SET(bitmap, NFS_FATTR_FILEHANDLE);
2191 nfsm_chain_add_bitmap(error, &nmreq, bitmap, NFS_ATTR_BITMAP_LEN);
2192 nfsm_chain_build_done(error, &nmreq);
2193 nfsm_assert(error, (numops == 0), EPROTO);
2194 nfsmout_if(error);
2195 error = nfs_request_async(NULL, nmp->nm_mountp, &nmreq, NFSPROC4_COMPOUND,
2196 vfs_context_thread(ctx), vfs_context_ucred(ctx), &si, 0, NULL, &req);
2197 if (!error)
2198 error = nfs_request_async_finish(req, &nmrep, &xid, &status);
2199 nfsm_chain_skip_tag(error, &nmrep);
2200 nfsm_chain_get_32(error, &nmrep, numops);
2201 nfsm_chain_op_check(error, &nmrep, NFS_OP_PUTROOTFH);
2202 nfsm_chain_op_check(error, &nmrep, NFS_OP_GETATTR);
2203 nfsmout_if(error);
2204 NFS_CLEAR_ATTRIBUTES(nmp->nm_fsattr.nfsa_bitmap);
2205 error = nfs4_parsefattr(&nmrep, &nmp->nm_fsattr, &nvattr, &dirfh, NULL, NULL);
2206 if (!error && !NFS_BITMAP_ISSET(&nvattr.nva_bitmap, NFS_FATTR_FILEHANDLE)) {
2207 printf("nfs: mount didn't return filehandle?\n");
2208 error = EBADRPC;
2209 }
2210 nfsmout_if(error);
2211 nfsm_chain_cleanup(&nmrep);
2212 nfsm_chain_null(&nmreq);
2213 NVATTR_CLEANUP(&nvattr);
2214 goto gotfh;
2215 }
2216
2217 /* look up each path component */
2218 for (comp=0; comp < fspath.np_compcount; ) {
2219 isdotdot = 0;
2220 if (fspath.np_components[comp][0] == '.') {
2221 if (fspath.np_components[comp][1] == '\0') {
2222 /* skip "." */
2223 comp++;
2224 continue;
2225 }
2226 /* treat ".." specially */
2227 if ((fspath.np_components[comp][1] == '.') &&
2228 (fspath.np_components[comp][2] == '\0'))
2229 isdotdot = 1;
2230 if (isdotdot && (dirfh.fh_len == 0)) {
2231 /* ".." in root directory is same as "." */
2232 comp++;
2233 continue;
2234 }
2235 }
2236 // PUT(ROOT)FH + LOOKUP(P) + GETFH + GETATTR
2237 if (dirfh.fh_len == 0)
2238 NFSREQ_SECINFO_SET(&si, NULL, NULL, 0, isdotdot ? NULL : fspath.np_components[comp], 0);
2239 else
2240 NFSREQ_SECINFO_SET(&si, NULL, dirfh.fh_data, dirfh.fh_len, isdotdot ? NULL : fspath.np_components[comp], 0);
2241 numops = 4;
2242 nfsm_chain_build_alloc_init(error, &nmreq, 18 * NFSX_UNSIGNED);
2243 nfsm_chain_add_compound_header(error, &nmreq, "mount", numops);
2244 numops--;
2245 if (dirfh.fh_len) {
2246 nfsm_chain_add_32(error, &nmreq, NFS_OP_PUTFH);
2247 nfsm_chain_add_fh(error, &nmreq, NFS_VER4, dirfh.fh_data, dirfh.fh_len);
2248 } else {
2249 nfsm_chain_add_32(error, &nmreq, NFS_OP_PUTROOTFH);
2250 }
2251 numops--;
2252 if (isdotdot) {
2253 nfsm_chain_add_32(error, &nmreq, NFS_OP_LOOKUPP);
2254 } else {
2255 nfsm_chain_add_32(error, &nmreq, NFS_OP_LOOKUP);
2256 nfsm_chain_add_name(error, &nmreq,
2257 fspath.np_components[comp], strlen(fspath.np_components[comp]), nmp);
2258 }
2259 numops--;
2260 nfsm_chain_add_32(error, &nmreq, NFS_OP_GETFH);
2261 numops--;
2262 nfsm_chain_add_32(error, &nmreq, NFS_OP_GETATTR);
2263 NFS_CLEAR_ATTRIBUTES(bitmap);
2264 NFS4_DEFAULT_ATTRIBUTES(bitmap);
2265 /* if no namedattr support or component is ".zfs", clear NFS_FATTR_NAMED_ATTR */
2266 if (NMFLAG(nmp, NONAMEDATTR) || !strcmp(fspath.np_components[comp], ".zfs"))
2267 NFS_BITMAP_CLR(bitmap, NFS_FATTR_NAMED_ATTR);
2268 nfsm_chain_add_bitmap(error, &nmreq, bitmap, NFS_ATTR_BITMAP_LEN);
2269 nfsm_chain_build_done(error, &nmreq);
2270 nfsm_assert(error, (numops == 0), EPROTO);
2271 nfsmout_if(error);
2272 error = nfs_request_async(NULL, nmp->nm_mountp, &nmreq, NFSPROC4_COMPOUND,
2273 vfs_context_thread(ctx), vfs_context_ucred(ctx), &si, 0, NULL, &req);
2274 if (!error)
2275 error = nfs_request_async_finish(req, &nmrep, &xid, &status);
2276 nfsm_chain_skip_tag(error, &nmrep);
2277 nfsm_chain_get_32(error, &nmrep, numops);
2278 nfsm_chain_op_check(error, &nmrep, dirfh.fh_len ? NFS_OP_PUTFH : NFS_OP_PUTROOTFH);
2279 nfsm_chain_op_check(error, &nmrep, isdotdot ? NFS_OP_LOOKUPP : NFS_OP_LOOKUP);
2280 nfsmout_if(error);
2281 nfsm_chain_op_check(error, &nmrep, NFS_OP_GETFH);
2282 nfsm_chain_get_32(error, &nmrep, fh.fh_len);
2283 nfsm_chain_get_opaque(error, &nmrep, fh.fh_len, fh.fh_data);
2284 nfsm_chain_op_check(error, &nmrep, NFS_OP_GETATTR);
2285 if (!error) {
2286 NFS_CLEAR_ATTRIBUTES(nmp->nm_fsattr.nfsa_bitmap);
2287 error = nfs4_parsefattr(&nmrep, &nmp->nm_fsattr, &nvattr, NULL, NULL, &nfsls);
2288 }
2289 nfsm_chain_cleanup(&nmrep);
2290 nfsm_chain_null(&nmreq);
2291 if (error) {
2292 /* LOOKUP succeeded but GETATTR failed? This could be a referral. */
2293 /* Try the lookup again with a getattr for fs_locations. */
2294 nfs_fs_locations_cleanup(&nfsls);
2295 error = nfs4_get_fs_locations(nmp, NULL, dirfh.fh_data, dirfh.fh_len, fspath.np_components[comp], ctx, &nfsls);
2296 if (!error && (nfsls.nl_numlocs < 1))
2297 error = ENOENT;
2298 nfsmout_if(error);
2299 if (++loopcnt > MAXSYMLINKS) {
2300 /* too many symlink/referral redirections */
2301 error = ELOOP;
2302 goto nfsmout;
2303 }
2304 /* tear down the current connection */
2305 nfs_disconnect(nmp);
2306 /* replace fs locations */
2307 nfs_fs_locations_cleanup(&nmp->nm_locations);
2308 nmp->nm_locations = nfsls;
2309 bzero(&nfsls, sizeof(nfsls));
2310 /* initiate a connection using the new fs locations */
2311 error = nfs_mount_connect(nmp);
2312 if (!error && !(nmp->nm_locations.nl_current.nli_flags & NLI_VALID))
2313 error = EIO;
2314 nfsmout_if(error);
2315 /* add new server's remote path to beginning of our path and continue */
2316 nfsp = &nmp->nm_locations.nl_locations[nmp->nm_locations.nl_current.nli_loc]->nl_path;
2317 bzero(&fspath2, sizeof(fspath2));
2318 fspath2.np_compcount = (fspath.np_compcount - comp - 1) + nfsp->np_compcount;
2319 if (fspath2.np_compcount > 0) {
2320 MALLOC(fspath2.np_components, char **, fspath2.np_compcount*sizeof(char*), M_TEMP, M_WAITOK|M_ZERO);
2321 if (!fspath2.np_components) {
2322 error = ENOMEM;
2323 goto nfsmout;
2324 }
2325 for (comp2=0; comp2 < nfsp->np_compcount; comp2++) {
2326 int slen = strlen(nfsp->np_components[comp2]);
2327 MALLOC(fspath2.np_components[comp2], char *, slen+1, M_TEMP, M_WAITOK|M_ZERO);
2328 if (!fspath2.np_components[comp2]) {
2329 /* clean up fspath2, then error out */
2330 while (comp2 > 0) {
2331 comp2--;
2332 FREE(fspath2.np_components[comp2], M_TEMP);
2333 }
2334 FREE(fspath2.np_components, M_TEMP);
2335 error = ENOMEM;
2336 goto nfsmout;
2337 }
2338 strlcpy(fspath2.np_components[comp2], nfsp->np_components[comp2], slen+1);
2339 }
2340 if ((fspath.np_compcount - comp - 1) > 0)
2341 bcopy(&fspath.np_components[comp+1], &fspath2.np_components[nfsp->np_compcount], (fspath.np_compcount - comp - 1)*sizeof(char*));
2342 /* free up unused parts of old path (prior components and component array) */
2343 do {
2344 FREE(fspath.np_components[comp], M_TEMP);
2345 } while (comp-- > 0);
2346 FREE(fspath.np_components, M_TEMP);
2347 /* put new path in place */
2348 fspath = fspath2;
2349 }
2350 /* reset dirfh and component index */
2351 dirfh.fh_len = 0;
2352 comp = 0;
2353 NVATTR_CLEANUP(&nvattr);
2354 if (fspath.np_compcount == 0)
2355 goto nocomponents;
2356 continue;
2357 }
2358 nfsmout_if(error);
2359 /* if file handle is for a symlink, then update the path with the symlink contents */
2360 if (NFS_BITMAP_ISSET(&nvattr.nva_bitmap, NFS_FATTR_TYPE) && (nvattr.nva_type == VLNK)) {
2361 if (++loopcnt > MAXSYMLINKS)
2362 error = ELOOP;
2363 else
2364 error = nfs4_mount_update_path_with_symlink(nmp, &fspath, comp, &dirfh, &depth, &fh, ctx);
2365 nfsmout_if(error);
2366 /* directory file handle is either left the same or reset to root (if link was absolute) */
2367 /* path traversal starts at beginning of the path again */
2368 comp = 0;
2369 NVATTR_CLEANUP(&nvattr);
2370 nfs_fs_locations_cleanup(&nfsls);
2371 continue;
2372 }
2373 NVATTR_CLEANUP(&nvattr);
2374 nfs_fs_locations_cleanup(&nfsls);
2375 /* not a symlink... */
2376 if ((nmp->nm_state & NFSSTA_NEEDSECINFO) && (comp == (fspath.np_compcount-1)) && !isdotdot) {
2377 /* need to get SECINFO for the directory being mounted */
2378 if (dirfh.fh_len == 0)
2379 NFSREQ_SECINFO_SET(&si, NULL, NULL, 0, isdotdot ? NULL : fspath.np_components[comp], 0);
2380 else
2381 NFSREQ_SECINFO_SET(&si, NULL, dirfh.fh_data, dirfh.fh_len, isdotdot ? NULL : fspath.np_components[comp], 0);
2382 sec.count = NX_MAX_SEC_FLAVORS;
2383 error = nfs4_secinfo_rpc(nmp, &si, vfs_context_ucred(ctx), sec.flavors, &sec.count);
2384 /* [sigh] some implementations return "illegal" error for unsupported ops */
2385 if (error == NFSERR_OP_ILLEGAL)
2386 error = 0;
2387 nfsmout_if(error);
2388 /* set our default security flavor to the first in the list */
2389 if (sec.count)
2390 nmp->nm_auth = sec.flavors[0];
2391 nmp->nm_state &= ~NFSSTA_NEEDSECINFO;
2392 }
2393 /* advance directory file handle, component index, & update depth */
2394 dirfh = fh;
2395 comp++;
2396 if (!isdotdot) /* going down the hierarchy */
2397 depth++;
2398 else if (--depth <= 0) /* going up the hierarchy */
2399 dirfh.fh_len = 0; /* clear dirfh when we hit root */
2400 }
2401
2402 gotfh:
2403 /* get attrs for mount point root */
2404 numops = NMFLAG(nmp, NONAMEDATTR) ? 2 : 3; // PUTFH + GETATTR + OPENATTR
2405 nfsm_chain_build_alloc_init(error, &nmreq, 25 * NFSX_UNSIGNED);
2406 nfsm_chain_add_compound_header(error, &nmreq, "mount", numops);
2407 numops--;
2408 nfsm_chain_add_32(error, &nmreq, NFS_OP_PUTFH);
2409 nfsm_chain_add_fh(error, &nmreq, NFS_VER4, dirfh.fh_data, dirfh.fh_len);
2410 numops--;
2411 nfsm_chain_add_32(error, &nmreq, NFS_OP_GETATTR);
2412 NFS_CLEAR_ATTRIBUTES(bitmap);
2413 NFS4_DEFAULT_ATTRIBUTES(bitmap);
2414 /* if no namedattr support or last component is ".zfs", clear NFS_FATTR_NAMED_ATTR */
2415 if (NMFLAG(nmp, NONAMEDATTR) || ((fspath.np_compcount > 0) && !strcmp(fspath.np_components[fspath.np_compcount-1], ".zfs")))
2416 NFS_BITMAP_CLR(bitmap, NFS_FATTR_NAMED_ATTR);
2417 nfsm_chain_add_bitmap(error, &nmreq, bitmap, NFS_ATTR_BITMAP_LEN);
2418 if (!NMFLAG(nmp, NONAMEDATTR)) {
2419 numops--;
2420 nfsm_chain_add_32(error, &nmreq, NFS_OP_OPENATTR);
2421 nfsm_chain_add_32(error, &nmreq, 0);
2422 }
2423 nfsm_chain_build_done(error, &nmreq);
2424 nfsm_assert(error, (numops == 0), EPROTO);
2425 nfsmout_if(error);
2426 error = nfs_request_async(NULL, nmp->nm_mountp, &nmreq, NFSPROC4_COMPOUND,
2427 vfs_context_thread(ctx), vfs_context_ucred(ctx), &si, 0, NULL, &req);
2428 if (!error)
2429 error = nfs_request_async_finish(req, &nmrep, &xid, &status);
2430 nfsm_chain_skip_tag(error, &nmrep);
2431 nfsm_chain_get_32(error, &nmrep, numops);
2432 nfsm_chain_op_check(error, &nmrep, NFS_OP_PUTFH);
2433 nfsm_chain_op_check(error, &nmrep, NFS_OP_GETATTR);
2434 nfsmout_if(error);
2435 NFS_CLEAR_ATTRIBUTES(nmp->nm_fsattr.nfsa_bitmap);
2436 error = nfs4_parsefattr(&nmrep, &nmp->nm_fsattr, &nvattr, NULL, NULL, NULL);
2437 nfsmout_if(error);
2438 if (!NMFLAG(nmp, NONAMEDATTR)) {
2439 nfsm_chain_op_check(error, &nmrep, NFS_OP_OPENATTR);
2440 if (error == ENOENT)
2441 error = 0;
2442 /* [sigh] some implementations return "illegal" error for unsupported ops */
2443 if (error || !NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_supp_attr, NFS_FATTR_NAMED_ATTR)) {
2444 nmp->nm_fsattr.nfsa_flags &= ~NFS_FSFLAG_NAMED_ATTR;
2445 } else {
2446 nmp->nm_fsattr.nfsa_flags |= NFS_FSFLAG_NAMED_ATTR;
2447 }
2448 } else {
2449 nmp->nm_fsattr.nfsa_flags &= ~NFS_FSFLAG_NAMED_ATTR;
2450 }
2451 if (NMFLAG(nmp, NOACL)) /* make sure ACL support is turned off */
2452 nmp->nm_fsattr.nfsa_flags &= ~NFS_FSFLAG_ACL;
2453 if (NMFLAG(nmp, ACLONLY) && !(nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_ACL))
2454 NFS_BITMAP_CLR(nmp->nm_flags, NFS_MFLAG_ACLONLY);
2455 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_supp_attr, NFS_FATTR_FH_EXPIRE_TYPE)) {
2456 uint32_t fhtype = ((nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_FHTYPE_MASK) >> NFS_FSFLAG_FHTYPE_SHIFT);
2457 if (fhtype != NFS_FH_PERSISTENT)
2458 printf("nfs: warning: non-persistent file handles! for %s\n", vfs_statfs(nmp->nm_mountp)->f_mntfromname);
2459 }
2460
2461 /* make sure it's a directory */
2462 if (!NFS_BITMAP_ISSET(&nvattr.nva_bitmap, NFS_FATTR_TYPE) || (nvattr.nva_type != VDIR)) {
2463 error = ENOTDIR;
2464 goto nfsmout;
2465 }
2466
2467 /* save the NFS fsid */
2468 nmp->nm_fsid = nvattr.nva_fsid;
2469
2470 /* create the root node */
2471 error = nfs_nget(nmp->nm_mountp, NULL, NULL, dirfh.fh_data, dirfh.fh_len, &nvattr, &xid, rq.r_auth, NG_MARKROOT, npp);
2472 nfsmout_if(error);
2473
2474 if (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_ACL)
2475 vfs_setextendedsecurity(nmp->nm_mountp);
2476
2477 /* adjust I/O sizes to server limits */
2478 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_MAXREAD) && (nmp->nm_fsattr.nfsa_maxread > 0)) {
2479 if (nmp->nm_fsattr.nfsa_maxread < (uint64_t)nmp->nm_rsize) {
2480 nmp->nm_rsize = nmp->nm_fsattr.nfsa_maxread & ~(NFS_FABLKSIZE - 1);
2481 if (nmp->nm_rsize == 0)
2482 nmp->nm_rsize = nmp->nm_fsattr.nfsa_maxread;
2483 }
2484 }
2485 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_MAXWRITE) && (nmp->nm_fsattr.nfsa_maxwrite > 0)) {
2486 if (nmp->nm_fsattr.nfsa_maxwrite < (uint64_t)nmp->nm_wsize) {
2487 nmp->nm_wsize = nmp->nm_fsattr.nfsa_maxwrite & ~(NFS_FABLKSIZE - 1);
2488 if (nmp->nm_wsize == 0)
2489 nmp->nm_wsize = nmp->nm_fsattr.nfsa_maxwrite;
2490 }
2491 }
2492
2493 /* set up lease renew timer */
2494 nmp->nm_renew_timer = thread_call_allocate(nfs4_renew_timer, nmp);
2495 interval = nmp->nm_fsattr.nfsa_lease / 2;
2496 if (interval < 1)
2497 interval = 1;
2498 nfs_interval_timer_start(nmp->nm_renew_timer, interval * 1000);
2499
2500 nfsmout:
2501 if (fspath.np_components) {
2502 for (comp=0; comp < fspath.np_compcount; comp++)
2503 if (fspath.np_components[comp])
2504 FREE(fspath.np_components[comp], M_TEMP);
2505 FREE(fspath.np_components, M_TEMP);
2506 }
2507 NVATTR_CLEANUP(&nvattr);
2508 nfs_fs_locations_cleanup(&nfsls);
2509 if (*npp)
2510 nfs_node_unlock(*npp);
2511 nfsm_chain_cleanup(&nmreq);
2512 nfsm_chain_cleanup(&nmrep);
2513 return (error);
2514 }
2515
2516 /*
2517 * Thread to handle initial NFS mount connection.
2518 */
2519 void
2520 nfs_mount_connect_thread(void *arg, __unused wait_result_t wr)
2521 {
2522 struct nfsmount *nmp = arg;
2523 int error = 0, savederror = 0, slpflag = (NMFLAG(nmp, INTR) ? PCATCH : 0);
2524 int done = 0, timeo, tries, maxtries;
2525
2526 if (NM_OMFLAG(nmp, MNTQUICK)) {
2527 timeo = 8;
2528 maxtries = 1;
2529 } else {
2530 timeo = 30;
2531 maxtries = 2;
2532 }
2533
2534 for (tries = 0; tries < maxtries; tries++) {
2535 error = nfs_connect(nmp, 1, timeo);
2536 switch (error) {
2537 case ETIMEDOUT:
2538 case EAGAIN:
2539 case EPIPE:
2540 case EADDRNOTAVAIL:
2541 case ENETDOWN:
2542 case ENETUNREACH:
2543 case ENETRESET:
2544 case ECONNABORTED:
2545 case ECONNRESET:
2546 case EISCONN:
2547 case ENOTCONN:
2548 case ESHUTDOWN:
2549 case ECONNREFUSED:
2550 case EHOSTDOWN:
2551 case EHOSTUNREACH:
2552 /* just keep retrying on any of these errors */
2553 break;
2554 case 0:
2555 default:
2556 /* looks like we got an answer... */
2557 done = 1;
2558 break;
2559 }
2560
2561 /* save the best error */
2562 if (nfs_connect_error_class(error) >= nfs_connect_error_class(savederror))
2563 savederror = error;
2564 if (done) {
2565 error = savederror;
2566 break;
2567 }
2568
2569 /* pause before next attempt */
2570 if ((error = nfs_sigintr(nmp, NULL, current_thread(), 0)))
2571 break;
2572 error = tsleep(nmp, PSOCK|slpflag, "nfs_mount_connect_retry", 2*hz);
2573 if (error && (error != EWOULDBLOCK))
2574 break;
2575 error = savederror;
2576 }
2577
2578 /* update status of mount connect */
2579 lck_mtx_lock(&nmp->nm_lock);
2580 if (!nmp->nm_mounterror)
2581 nmp->nm_mounterror = error;
2582 nmp->nm_state &= ~NFSSTA_MOUNT_THREAD;
2583 lck_mtx_unlock(&nmp->nm_lock);
2584 wakeup(&nmp->nm_nss);
2585 }
2586
2587 int
2588 nfs_mount_connect(struct nfsmount *nmp)
2589 {
2590 int error = 0, slpflag;
2591 thread_t thd;
2592 struct timespec ts = { 2, 0 };
2593
2594 /*
2595 * Set up the socket. Perform initial search for a location/server/address to
2596 * connect to and negotiate any unspecified mount parameters. This work is
2597 * done on a kernel thread to satisfy reserved port usage needs.
2598 */
2599 slpflag = NMFLAG(nmp, INTR) ? PCATCH : 0;
2600 lck_mtx_lock(&nmp->nm_lock);
2601 /* set flag that the thread is running */
2602 nmp->nm_state |= NFSSTA_MOUNT_THREAD;
2603 if (kernel_thread_start(nfs_mount_connect_thread, nmp, &thd) != KERN_SUCCESS) {
2604 nmp->nm_state &= ~NFSSTA_MOUNT_THREAD;
2605 nmp->nm_mounterror = EIO;
2606 printf("nfs mount %s start socket connect thread failed\n", vfs_statfs(nmp->nm_mountp)->f_mntfromname);
2607 } else {
2608 thread_deallocate(thd);
2609 }
2610
2611 /* wait until mount connect thread is finished/gone */
2612 while (nmp->nm_state & NFSSTA_MOUNT_THREAD) {
2613 error = msleep(&nmp->nm_nss, &nmp->nm_lock, slpflag|PSOCK, "nfsconnectthread", &ts);
2614 if ((error && (error != EWOULDBLOCK)) || ((error = nfs_sigintr(nmp, NULL, current_thread(), 1)))) {
2615 /* record error */
2616 if (!nmp->nm_mounterror)
2617 nmp->nm_mounterror = error;
2618 /* signal the thread that we are aborting */
2619 nmp->nm_sockflags |= NMSOCK_UNMOUNT;
2620 if (nmp->nm_nss)
2621 wakeup(nmp->nm_nss);
2622 /* and continue waiting on it to finish */
2623 slpflag = 0;
2624 }
2625 }
2626 lck_mtx_unlock(&nmp->nm_lock);
2627
2628 /* grab mount connect status */
2629 error = nmp->nm_mounterror;
2630
2631 return (error);
2632 }
2633
2634 /*
2635 * Common code to mount an NFS file system.
2636 */
2637 int
2638 mountnfs(
2639 char *xdrbuf,
2640 mount_t mp,
2641 vfs_context_t ctx,
2642 vnode_t *vpp)
2643 {
2644 struct nfsmount *nmp;
2645 nfsnode_t np;
2646 int error = 0;
2647 struct vfsstatfs *sbp;
2648 struct xdrbuf xb;
2649 uint32_t i, val, vers = 0, minorvers, maxio, iosize, len;
2650 uint32_t *mattrs;
2651 uint32_t *mflags_mask;
2652 uint32_t *mflags;
2653 uint32_t argslength, attrslength;
2654 struct nfs_location_index firstloc = { NLI_VALID, 0, 0, 0 };
2655
2656 /* make sure mbuf constants are set up */
2657 if (!nfs_mbuf_mhlen)
2658 nfs_mbuf_init();
2659
2660 if (vfs_flags(mp) & MNT_UPDATE) {
2661 nmp = VFSTONFS(mp);
2662 /* update paths, file handles, etc, here XXX */
2663 xb_free(xdrbuf);
2664 return (0);
2665 } else {
2666 /* allocate an NFS mount structure for this mount */
2667 MALLOC_ZONE(nmp, struct nfsmount *,
2668 sizeof (struct nfsmount), M_NFSMNT, M_WAITOK);
2669 if (!nmp) {
2670 xb_free(xdrbuf);
2671 return (ENOMEM);
2672 }
2673 bzero((caddr_t)nmp, sizeof (struct nfsmount));
2674 lck_mtx_init(&nmp->nm_lock, nfs_mount_grp, LCK_ATTR_NULL);
2675 TAILQ_INIT(&nmp->nm_resendq);
2676 TAILQ_INIT(&nmp->nm_iodq);
2677 TAILQ_INIT(&nmp->nm_gsscl);
2678 TAILQ_INIT(&nmp->nm_gssnccl);
2679 LIST_INIT(&nmp->nm_monlist);
2680 vfs_setfsprivate(mp, nmp);
2681 vfs_getnewfsid(mp);
2682 nmp->nm_mountp = mp;
2683 vfs_setauthopaque(mp);
2684
2685 nfs_nhinit_finish();
2686
2687 nmp->nm_args = xdrbuf;
2688
2689 /* set up defaults */
2690 nmp->nm_ref = 0;
2691 nmp->nm_vers = 0;
2692 nmp->nm_timeo = NFS_TIMEO;
2693 nmp->nm_retry = NFS_RETRANS;
2694 nmp->nm_sotype = 0;
2695 nmp->nm_sofamily = 0;
2696 nmp->nm_nfsport = 0;
2697 nmp->nm_wsize = NFS_WSIZE;
2698 nmp->nm_rsize = NFS_RSIZE;
2699 nmp->nm_readdirsize = NFS_READDIRSIZE;
2700 nmp->nm_numgrps = NFS_MAXGRPS;
2701 nmp->nm_readahead = NFS_DEFRAHEAD;
2702 nmp->nm_tprintf_delay = nfs_tprintf_delay;
2703 if (nmp->nm_tprintf_delay < 0)
2704 nmp->nm_tprintf_delay = 0;
2705 nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
2706 if (nmp->nm_tprintf_initial_delay < 0)
2707 nmp->nm_tprintf_initial_delay = 0;
2708 nmp->nm_acregmin = NFS_MINATTRTIMO;
2709 nmp->nm_acregmax = NFS_MAXATTRTIMO;
2710 nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
2711 nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
2712 nmp->nm_auth = RPCAUTH_SYS;
2713 nmp->nm_iodlink.tqe_next = NFSNOLIST;
2714 nmp->nm_deadtimeout = 0;
2715 nmp->nm_curdeadtimeout = 0;
2716 NFS_BITMAP_SET(nmp->nm_flags, NFS_MFLAG_NOACL);
2717 nmp->nm_realm = NULL;
2718 nmp->nm_principal = NULL;
2719 nmp->nm_sprinc = NULL;
2720 }
2721
2722 mattrs = nmp->nm_mattrs;
2723 mflags = nmp->nm_mflags;
2724 mflags_mask = nmp->nm_mflags_mask;
2725
2726 /* set up NFS mount with args */
2727 xb_init_buffer(&xb, xdrbuf, 2*XDRWORD);
2728 xb_get_32(error, &xb, val); /* version */
2729 xb_get_32(error, &xb, argslength); /* args length */
2730 nfsmerr_if(error);
2731 xb_init_buffer(&xb, xdrbuf, argslength); /* restart parsing with actual buffer length */
2732 xb_get_32(error, &xb, val); /* version */
2733 xb_get_32(error, &xb, argslength); /* args length */
2734 xb_get_32(error, &xb, val); /* XDR args version */
2735 if (val != NFS_XDRARGS_VERSION_0)
2736 error = EINVAL;
2737 len = NFS_MATTR_BITMAP_LEN;
2738 xb_get_bitmap(error, &xb, mattrs, len); /* mount attribute bitmap */
2739 attrslength = 0;
2740 xb_get_32(error, &xb, attrslength); /* attrs length */
2741 if (!error && (attrslength > (argslength - ((4+NFS_MATTR_BITMAP_LEN+1)*XDRWORD))))
2742 error = EINVAL;
2743 nfsmerr_if(error);
2744 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_FLAGS)) {
2745 len = NFS_MFLAG_BITMAP_LEN;
2746 xb_get_bitmap(error, &xb, mflags_mask, len); /* mount flag mask */
2747 len = NFS_MFLAG_BITMAP_LEN;
2748 xb_get_bitmap(error, &xb, mflags, len); /* mount flag values */
2749 if (!error) {
2750 /* clear all mask bits and OR in all the ones that are set */
2751 nmp->nm_flags[0] &= ~mflags_mask[0];
2752 nmp->nm_flags[0] |= (mflags_mask[0] & mflags[0]);
2753 }
2754 }
2755 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_NFS_VERSION)) {
2756 xb_get_32(error, &xb, vers);
2757 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_NFS_MINOR_VERSION))
2758 xb_get_32(error, &xb, minorvers);
2759 else
2760 minorvers = 0;
2761 nfsmerr_if(error);
2762 switch (vers) {
2763 case 2:
2764 nmp->nm_vers = NFS_VER2;
2765 break;
2766 case 3:
2767 nmp->nm_vers = NFS_VER3;
2768 break;
2769 case 4:
2770 switch (minorvers) {
2771 case 0:
2772 nmp->nm_vers = NFS_VER4;
2773 break;
2774 default:
2775 error = EINVAL;
2776 }
2777 break;
2778 default:
2779 error = EINVAL;
2780 }
2781 }
2782 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_NFS_MINOR_VERSION)) {
2783 /* should have also gotten NFS version (and already gotten minorvers) */
2784 if (!NFS_BITMAP_ISSET(mattrs, NFS_MATTR_NFS_VERSION))
2785 error = EINVAL;
2786 }
2787 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_READ_SIZE))
2788 xb_get_32(error, &xb, nmp->nm_rsize);
2789 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_WRITE_SIZE))
2790 xb_get_32(error, &xb, nmp->nm_wsize);
2791 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_READDIR_SIZE))
2792 xb_get_32(error, &xb, nmp->nm_readdirsize);
2793 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_READAHEAD))
2794 xb_get_32(error, &xb, nmp->nm_readahead);
2795 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_ATTRCACHE_REG_MIN)) {
2796 xb_get_32(error, &xb, nmp->nm_acregmin);
2797 xb_skip(error, &xb, XDRWORD);
2798 }
2799 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_ATTRCACHE_REG_MAX)) {
2800 xb_get_32(error, &xb, nmp->nm_acregmax);
2801 xb_skip(error, &xb, XDRWORD);
2802 }
2803 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_ATTRCACHE_DIR_MIN)) {
2804 xb_get_32(error, &xb, nmp->nm_acdirmin);
2805 xb_skip(error, &xb, XDRWORD);
2806 }
2807 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_ATTRCACHE_DIR_MAX)) {
2808 xb_get_32(error, &xb, nmp->nm_acdirmax);
2809 xb_skip(error, &xb, XDRWORD);
2810 }
2811 nfsmerr_if(error);
2812 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_LOCK_MODE)) {
2813 xb_get_32(error, &xb, val);
2814 switch (val) {
2815 case NFS_LOCK_MODE_DISABLED:
2816 case NFS_LOCK_MODE_LOCAL:
2817 if (nmp->nm_vers >= NFS_VER4) {
2818 /* disabled/local lock mode only allowed on v2/v3 */
2819 error = EINVAL;
2820 break;
2821 }
2822 /* FALLTHROUGH */
2823 case NFS_LOCK_MODE_ENABLED:
2824 nmp->nm_lockmode = val;
2825 break;
2826 default:
2827 error = EINVAL;
2828 }
2829 }
2830 nfsmerr_if(error);
2831 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_SECURITY)) {
2832 uint32_t seccnt;
2833 xb_get_32(error, &xb, seccnt);
2834 if (!error && ((seccnt < 1) || (seccnt > NX_MAX_SEC_FLAVORS)))
2835 error = EINVAL;
2836 nfsmerr_if(error);
2837 nmp->nm_sec.count = seccnt;
2838 for (i=0; i < seccnt; i++) {
2839 xb_get_32(error, &xb, nmp->nm_sec.flavors[i]);
2840 /* Check for valid security flavor */
2841 switch (nmp->nm_sec.flavors[i]) {
2842 case RPCAUTH_NONE:
2843 case RPCAUTH_SYS:
2844 case RPCAUTH_KRB5:
2845 case RPCAUTH_KRB5I:
2846 case RPCAUTH_KRB5P:
2847 break;
2848 default:
2849 error = EINVAL;
2850 }
2851 }
2852 /* start with the first flavor */
2853 nmp->nm_auth = nmp->nm_sec.flavors[0];
2854 }
2855 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_MAX_GROUP_LIST))
2856 xb_get_32(error, &xb, nmp->nm_numgrps);
2857 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_SOCKET_TYPE)) {
2858 char sotype[6];
2859
2860 xb_get_32(error, &xb, val);
2861 if (!error && ((val < 3) || (val > 5)))
2862 error = EINVAL;
2863 nfsmerr_if(error);
2864 error = xb_get_bytes(&xb, sotype, val, 0);
2865 nfsmerr_if(error);
2866 sotype[val] = '\0';
2867 if (!strcmp(sotype, "tcp")) {
2868 nmp->nm_sotype = SOCK_STREAM;
2869 } else if (!strcmp(sotype, "udp")) {
2870 nmp->nm_sotype = SOCK_DGRAM;
2871 } else if (!strcmp(sotype, "tcp4")) {
2872 nmp->nm_sotype = SOCK_STREAM;
2873 nmp->nm_sofamily = AF_INET;
2874 } else if (!strcmp(sotype, "udp4")) {
2875 nmp->nm_sotype = SOCK_DGRAM;
2876 nmp->nm_sofamily = AF_INET;
2877 } else if (!strcmp(sotype, "tcp6")) {
2878 nmp->nm_sotype = SOCK_STREAM;
2879 nmp->nm_sofamily = AF_INET6;
2880 } else if (!strcmp(sotype, "udp6")) {
2881 nmp->nm_sotype = SOCK_DGRAM;
2882 nmp->nm_sofamily = AF_INET6;
2883 } else if (!strcmp(sotype, "inet4")) {
2884 nmp->nm_sofamily = AF_INET;
2885 } else if (!strcmp(sotype, "inet6")) {
2886 nmp->nm_sofamily = AF_INET6;
2887 } else if (!strcmp(sotype, "inet")) {
2888 nmp->nm_sofamily = 0; /* ok */
2889 } else {
2890 error = EINVAL;
2891 }
2892 if (!error && (nmp->nm_vers >= NFS_VER4) && nmp->nm_sotype &&
2893 (nmp->nm_sotype != SOCK_STREAM))
2894 error = EINVAL; /* NFSv4 is only allowed over TCP. */
2895 nfsmerr_if(error);
2896 }
2897 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_NFS_PORT))
2898 xb_get_32(error, &xb, nmp->nm_nfsport);
2899 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_MOUNT_PORT))
2900 xb_get_32(error, &xb, nmp->nm_mountport);
2901 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_REQUEST_TIMEOUT)) {
2902 /* convert from time to 0.1s units */
2903 xb_get_32(error, &xb, nmp->nm_timeo);
2904 xb_get_32(error, &xb, val);
2905 nfsmerr_if(error);
2906 if (val >= 1000000000)
2907 error = EINVAL;
2908 nfsmerr_if(error);
2909 nmp->nm_timeo *= 10;
2910 nmp->nm_timeo += (val+100000000-1)/100000000;
2911 /* now convert to ticks */
2912 nmp->nm_timeo = (nmp->nm_timeo * NFS_HZ + 5) / 10;
2913 }
2914 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_SOFT_RETRY_COUNT)) {
2915 xb_get_32(error, &xb, val);
2916 if (!error && (val > 1))
2917 nmp->nm_retry = val;
2918 }
2919 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_DEAD_TIMEOUT)) {
2920 xb_get_32(error, &xb, nmp->nm_deadtimeout);
2921 xb_skip(error, &xb, XDRWORD);
2922 }
2923 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_FH)) {
2924 nfsmerr_if(error);
2925 MALLOC(nmp->nm_fh, fhandle_t *, sizeof(fhandle_t), M_TEMP, M_WAITOK|M_ZERO);
2926 if (!nmp->nm_fh)
2927 error = ENOMEM;
2928 xb_get_32(error, &xb, nmp->nm_fh->fh_len);
2929 nfsmerr_if(error);
2930 error = xb_get_bytes(&xb, (char*)&nmp->nm_fh->fh_data[0], nmp->nm_fh->fh_len, 0);
2931 }
2932 nfsmerr_if(error);
2933 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_FS_LOCATIONS)) {
2934 uint32_t loc, serv, addr, comp;
2935 struct nfs_fs_location *fsl;
2936 struct nfs_fs_server *fss;
2937 struct nfs_fs_path *fsp;
2938
2939 xb_get_32(error, &xb, nmp->nm_locations.nl_numlocs); /* fs location count */
2940 /* sanity check location count */
2941 if (!error && ((nmp->nm_locations.nl_numlocs < 1) || (nmp->nm_locations.nl_numlocs > 256)))
2942 error = EINVAL;
2943 nfsmerr_if(error);
2944 MALLOC(nmp->nm_locations.nl_locations, struct nfs_fs_location **, nmp->nm_locations.nl_numlocs * sizeof(struct nfs_fs_location*), M_TEMP, M_WAITOK|M_ZERO);
2945 if (!nmp->nm_locations.nl_locations)
2946 error = ENOMEM;
2947 for (loc = 0; loc < nmp->nm_locations.nl_numlocs; loc++) {
2948 nfsmerr_if(error);
2949 MALLOC(fsl, struct nfs_fs_location *, sizeof(struct nfs_fs_location), M_TEMP, M_WAITOK|M_ZERO);
2950 if (!fsl)
2951 error = ENOMEM;
2952 nmp->nm_locations.nl_locations[loc] = fsl;
2953 xb_get_32(error, &xb, fsl->nl_servcount); /* server count */
2954 /* sanity check server count */
2955 if (!error && ((fsl->nl_servcount < 1) || (fsl->nl_servcount > 256)))
2956 error = EINVAL;
2957 nfsmerr_if(error);
2958 MALLOC(fsl->nl_servers, struct nfs_fs_server **, fsl->nl_servcount * sizeof(struct nfs_fs_server*), M_TEMP, M_WAITOK|M_ZERO);
2959 if (!fsl->nl_servers)
2960 error = ENOMEM;
2961 for (serv = 0; serv < fsl->nl_servcount; serv++) {
2962 nfsmerr_if(error);
2963 MALLOC(fss, struct nfs_fs_server *, sizeof(struct nfs_fs_server), M_TEMP, M_WAITOK|M_ZERO);
2964 if (!fss)
2965 error = ENOMEM;
2966 fsl->nl_servers[serv] = fss;
2967 xb_get_32(error, &xb, val); /* server name length */
2968 /* sanity check server name length */
2969 if (!error && ((val < 1) || (val > MAXPATHLEN)))
2970 error = EINVAL;
2971 nfsmerr_if(error);
2972 MALLOC(fss->ns_name, char *, val+1, M_TEMP, M_WAITOK|M_ZERO);
2973 if (!fss->ns_name)
2974 error = ENOMEM;
2975 nfsmerr_if(error);
2976 error = xb_get_bytes(&xb, fss->ns_name, val, 0); /* server name */
2977 xb_get_32(error, &xb, fss->ns_addrcount); /* address count */
2978 /* sanity check address count (OK to be zero) */
2979 if (!error && (fss->ns_addrcount > 256))
2980 error = EINVAL;
2981 nfsmerr_if(error);
2982 if (fss->ns_addrcount > 0) {
2983 MALLOC(fss->ns_addresses, char **, fss->ns_addrcount * sizeof(char *), M_TEMP, M_WAITOK|M_ZERO);
2984 if (!fss->ns_addresses)
2985 error = ENOMEM;
2986 for (addr = 0; addr < fss->ns_addrcount; addr++) {
2987 xb_get_32(error, &xb, val); /* address length */
2988 /* sanity check address length */
2989 if (!error && ((val < 1) || (val > 128)))
2990 error = EINVAL;
2991 nfsmerr_if(error);
2992 MALLOC(fss->ns_addresses[addr], char *, val+1, M_TEMP, M_WAITOK|M_ZERO);
2993 if (!fss->ns_addresses[addr])
2994 error = ENOMEM;
2995 nfsmerr_if(error);
2996 error = xb_get_bytes(&xb, fss->ns_addresses[addr], val, 0); /* address */
2997 }
2998 }
2999 xb_get_32(error, &xb, val); /* server info length */
3000 xb_skip(error, &xb, val); /* skip server info */
3001 }
3002 /* get pathname */
3003 fsp = &fsl->nl_path;
3004 xb_get_32(error, &xb, fsp->np_compcount); /* component count */
3005 /* sanity check component count */
3006 if (!error && (fsp->np_compcount > MAXPATHLEN))
3007 error = EINVAL;
3008 nfsmerr_if(error);
3009 if (fsp->np_compcount) {
3010 MALLOC(fsp->np_components, char **, fsp->np_compcount * sizeof(char*), M_TEMP, M_WAITOK|M_ZERO);
3011 if (!fsp->np_components)
3012 error = ENOMEM;
3013 }
3014 for (comp = 0; comp < fsp->np_compcount; comp++) {
3015 xb_get_32(error, &xb, val); /* component length */
3016 /* sanity check component length */
3017 if (!error && (val == 0)) {
3018 /*
3019 * Apparently some people think a path with zero components should
3020 * be encoded with one zero-length component. So, just ignore any
3021 * zero length components.
3022 */
3023 comp--;
3024 fsp->np_compcount--;
3025 if (fsp->np_compcount == 0) {
3026 FREE(fsp->np_components, M_TEMP);
3027 fsp->np_components = NULL;
3028 }
3029 continue;
3030 }
3031 if (!error && ((val < 1) || (val > MAXPATHLEN)))
3032 error = EINVAL;
3033 nfsmerr_if(error);
3034 MALLOC(fsp->np_components[comp], char *, val+1, M_TEMP, M_WAITOK|M_ZERO);
3035 if (!fsp->np_components[comp])
3036 error = ENOMEM;
3037 nfsmerr_if(error);
3038 error = xb_get_bytes(&xb, fsp->np_components[comp], val, 0); /* component */
3039 }
3040 xb_get_32(error, &xb, val); /* fs location info length */
3041 xb_skip(error, &xb, val); /* skip fs location info */
3042 }
3043 }
3044 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_MNTFLAGS))
3045 xb_skip(error, &xb, XDRWORD);
3046 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_MNTFROM)) {
3047 xb_get_32(error, &xb, len);
3048 nfsmerr_if(error);
3049 val = len;
3050 if (val >= sizeof(vfs_statfs(mp)->f_mntfromname))
3051 val = sizeof(vfs_statfs(mp)->f_mntfromname) - 1;
3052 error = xb_get_bytes(&xb, vfs_statfs(mp)->f_mntfromname, val, 0);
3053 if ((len - val) > 0)
3054 xb_skip(error, &xb, len - val);
3055 nfsmerr_if(error);
3056 vfs_statfs(mp)->f_mntfromname[val] = '\0';
3057 }
3058 nfsmerr_if(error);
3059
3060 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_REALM)) {
3061 xb_get_32(error, &xb, len);
3062 if (!error && ((len < 1) || (len > MAXPATHLEN)))
3063 error=EINVAL;
3064 nfsmerr_if(error);
3065 /* allocate an extra byte for a leading '@' if its not already prepended to the realm */
3066 MALLOC(nmp->nm_realm, char *, len+2, M_TEMP, M_WAITOK|M_ZERO);
3067 if (!nmp->nm_realm)
3068 error = ENOMEM;
3069 nfsmerr_if(error);
3070 error = xb_get_bytes(&xb, nmp->nm_realm, len, 0);
3071 if (error == 0 && *nmp->nm_realm != '@') {
3072 bcopy(nmp->nm_realm, &nmp->nm_realm[1], len);
3073 nmp->nm_realm[0] = '@';
3074 }
3075 }
3076 nfsmerr_if(error);
3077
3078 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_PRINCIPAL)) {
3079 xb_get_32(error, &xb, len);
3080 if (!error && ((len < 1) || (len > MAXPATHLEN)))
3081 error=EINVAL;
3082 nfsmerr_if(error);
3083 MALLOC(nmp->nm_principal, char *, len+1, M_TEMP, M_WAITOK|M_ZERO);
3084 if (!nmp->nm_principal)
3085 error = ENOMEM;
3086 nfsmerr_if(error);
3087 error = xb_get_bytes(&xb, nmp->nm_principal, len, 0);
3088 }
3089 nfsmerr_if(error);
3090
3091 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_SVCPRINCIPAL)) {
3092 xb_get_32(error, &xb, len);
3093 if (!error && ((len < 1) || (len > MAXPATHLEN)))
3094 error=EINVAL;
3095 nfsmerr_if(error);
3096 MALLOC(nmp->nm_sprinc, char *, len+1, M_TEMP, M_WAITOK|M_ZERO);
3097 if (!nmp->nm_sprinc)
3098 error = ENOMEM;
3099 nfsmerr_if(error);
3100 error = xb_get_bytes(&xb, nmp->nm_sprinc, len, 0);
3101 }
3102 nfsmerr_if(error);
3103
3104 /*
3105 * Sanity check/finalize settings.
3106 */
3107
3108 if (nmp->nm_timeo < NFS_MINTIMEO)
3109 nmp->nm_timeo = NFS_MINTIMEO;
3110 else if (nmp->nm_timeo > NFS_MAXTIMEO)
3111 nmp->nm_timeo = NFS_MAXTIMEO;
3112 if (nmp->nm_retry > NFS_MAXREXMIT)
3113 nmp->nm_retry = NFS_MAXREXMIT;
3114
3115 if (nmp->nm_numgrps > NFS_MAXGRPS)
3116 nmp->nm_numgrps = NFS_MAXGRPS;
3117 if (nmp->nm_readahead > NFS_MAXRAHEAD)
3118 nmp->nm_readahead = NFS_MAXRAHEAD;
3119 if (nmp->nm_acregmin > nmp->nm_acregmax)
3120 nmp->nm_acregmin = nmp->nm_acregmax;
3121 if (nmp->nm_acdirmin > nmp->nm_acdirmax)
3122 nmp->nm_acdirmin = nmp->nm_acdirmax;
3123
3124 /* need at least one fs location */
3125 if (nmp->nm_locations.nl_numlocs < 1)
3126 error = EINVAL;
3127 nfsmerr_if(error);
3128
3129 /* init mount's mntfromname to first location */
3130 if (!NM_OMATTR_GIVEN(nmp, MNTFROM))
3131 nfs_location_mntfromname(&nmp->nm_locations, firstloc,
3132 vfs_statfs(mp)->f_mntfromname, sizeof(vfs_statfs(mp)->f_mntfromname), 0);
3133
3134 /* Need to save the mounting credential for v4. */
3135 nmp->nm_mcred = vfs_context_ucred(ctx);
3136 if (IS_VALID_CRED(nmp->nm_mcred))
3137 kauth_cred_ref(nmp->nm_mcred);
3138
3139 /*
3140 * If a reserved port is required, check for that privilege.
3141 * (Note that mirror mounts are exempt because the privilege was
3142 * already checked for the original mount.)
3143 */
3144 if (NMFLAG(nmp, RESVPORT) && !vfs_iskernelmount(mp))
3145 error = priv_check_cred(nmp->nm_mcred, PRIV_NETINET_RESERVEDPORT, 0);
3146 nfsmerr_if(error);
3147
3148 /* do mount's initial socket connection */
3149 error = nfs_mount_connect(nmp);
3150 nfsmerr_if(error);
3151
3152 /* set up the version-specific function tables */
3153 if (nmp->nm_vers < NFS_VER4)
3154 nmp->nm_funcs = &nfs3_funcs;
3155 else
3156 nmp->nm_funcs = &nfs4_funcs;
3157
3158 /* sanity check settings now that version/connection is set */
3159 if (nmp->nm_vers == NFS_VER2) /* ignore RDIRPLUS on NFSv2 */
3160 NFS_BITMAP_CLR(nmp->nm_flags, NFS_MFLAG_RDIRPLUS);
3161 if (nmp->nm_vers >= NFS_VER4) {
3162 if (NFS_BITMAP_ISSET(nmp->nm_flags, NFS_MFLAG_ACLONLY)) /* aclonly trumps noacl */
3163 NFS_BITMAP_CLR(nmp->nm_flags, NFS_MFLAG_NOACL);
3164 NFS_BITMAP_CLR(nmp->nm_flags, NFS_MFLAG_CALLUMNT);
3165 if (nmp->nm_lockmode != NFS_LOCK_MODE_ENABLED)
3166 error = EINVAL; /* disabled/local lock mode only allowed on v2/v3 */
3167 } else {
3168 /* ignore these if not v4 */
3169 NFS_BITMAP_CLR(nmp->nm_flags, NFS_MFLAG_NOCALLBACK);
3170 NFS_BITMAP_CLR(nmp->nm_flags, NFS_MFLAG_NONAMEDATTR);
3171 NFS_BITMAP_CLR(nmp->nm_flags, NFS_MFLAG_NOACL);
3172 NFS_BITMAP_CLR(nmp->nm_flags, NFS_MFLAG_ACLONLY);
3173 }
3174 nfsmerr_if(error);
3175
3176 if (nmp->nm_sotype == SOCK_DGRAM) {
3177 /* I/O size defaults for UDP are different */
3178 if (!NFS_BITMAP_ISSET(mattrs, NFS_MATTR_READ_SIZE))
3179 nmp->nm_rsize = NFS_DGRAM_RSIZE;
3180 if (!NFS_BITMAP_ISSET(mattrs, NFS_MATTR_WRITE_SIZE))
3181 nmp->nm_wsize = NFS_DGRAM_WSIZE;
3182 }
3183
3184 /* round down I/O sizes to multiple of NFS_FABLKSIZE */
3185 nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1);
3186 if (nmp->nm_rsize <= 0)
3187 nmp->nm_rsize = NFS_FABLKSIZE;
3188 nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1);
3189 if (nmp->nm_wsize <= 0)
3190 nmp->nm_wsize = NFS_FABLKSIZE;
3191
3192 /* and limit I/O sizes to maximum allowed */
3193 maxio = (nmp->nm_vers == NFS_VER2) ? NFS_V2MAXDATA :
3194 (nmp->nm_sotype == SOCK_DGRAM) ? NFS_MAXDGRAMDATA : NFS_MAXDATA;
3195 if (maxio > NFS_MAXBSIZE)
3196 maxio = NFS_MAXBSIZE;
3197 if (nmp->nm_rsize > maxio)
3198 nmp->nm_rsize = maxio;
3199 if (nmp->nm_wsize > maxio)
3200 nmp->nm_wsize = maxio;
3201
3202 if (nmp->nm_readdirsize > maxio)
3203 nmp->nm_readdirsize = maxio;
3204 if (nmp->nm_readdirsize > nmp->nm_rsize)
3205 nmp->nm_readdirsize = nmp->nm_rsize;
3206
3207 /* Set up the sockets and related info */
3208 if (nmp->nm_sotype == SOCK_DGRAM)
3209 TAILQ_INIT(&nmp->nm_cwndq);
3210
3211 /*
3212 * Get the root node/attributes from the NFS server and
3213 * do any basic, version-specific setup.
3214 */
3215 error = nmp->nm_funcs->nf_mount(nmp, ctx, &np);
3216 nfsmerr_if(error);
3217
3218 /*
3219 * A reference count is needed on the node representing the
3220 * remote root. If this object is not persistent, then backward
3221 * traversals of the mount point (i.e. "..") will not work if
3222 * the node gets flushed out of the cache.
3223 */
3224 nmp->nm_dnp = np;
3225 *vpp = NFSTOV(np);
3226 /* get usecount and drop iocount */
3227 error = vnode_ref(*vpp);
3228 vnode_put(*vpp);
3229 if (error) {
3230 vnode_recycle(*vpp);
3231 goto nfsmerr;
3232 }
3233
3234 /*
3235 * Do statfs to ensure static info gets set to reasonable values.
3236 */
3237 if ((error = nmp->nm_funcs->nf_update_statfs(nmp, ctx))) {
3238 int error2 = vnode_getwithref(*vpp);
3239 vnode_rele(*vpp);
3240 if (!error2)
3241 vnode_put(*vpp);
3242 vnode_recycle(*vpp);
3243 goto nfsmerr;
3244 }
3245 sbp = vfs_statfs(mp);
3246 sbp->f_bsize = nmp->nm_fsattr.nfsa_bsize;
3247 sbp->f_blocks = nmp->nm_fsattr.nfsa_space_total / sbp->f_bsize;
3248 sbp->f_bfree = nmp->nm_fsattr.nfsa_space_free / sbp->f_bsize;
3249 sbp->f_bavail = nmp->nm_fsattr.nfsa_space_avail / sbp->f_bsize;
3250 sbp->f_bused = (nmp->nm_fsattr.nfsa_space_total / sbp->f_bsize) -
3251 (nmp->nm_fsattr.nfsa_space_free / sbp->f_bsize);
3252 sbp->f_files = nmp->nm_fsattr.nfsa_files_total;
3253 sbp->f_ffree = nmp->nm_fsattr.nfsa_files_free;
3254 sbp->f_iosize = nfs_iosize;
3255
3256 /*
3257 * Calculate the size used for I/O buffers. Use the larger
3258 * of the two sizes to minimise NFS requests but make sure
3259 * that it is at least one VM page to avoid wasting buffer
3260 * space and to allow easy mmapping of I/O buffers.
3261 * The read/write RPC calls handle the splitting up of
3262 * buffers into multiple requests if the buffer size is
3263 * larger than the I/O size.
3264 */
3265 iosize = max(nmp->nm_rsize, nmp->nm_wsize);
3266 if (iosize < PAGE_SIZE)
3267 iosize = PAGE_SIZE;
3268 nmp->nm_biosize = trunc_page_32(iosize);
3269
3270 /* For NFSv3 and greater, there is a (relatively) reliable ACCESS call. */
3271 if (nmp->nm_vers > NFS_VER2)
3272 vfs_setauthopaqueaccess(mp);
3273
3274 switch (nmp->nm_lockmode) {
3275 case NFS_LOCK_MODE_DISABLED:
3276 break;
3277 case NFS_LOCK_MODE_LOCAL:
3278 vfs_setlocklocal(nmp->nm_mountp);
3279 break;
3280 case NFS_LOCK_MODE_ENABLED:
3281 default:
3282 if (nmp->nm_vers <= NFS_VER3)
3283 nfs_lockd_mount_register(nmp);
3284 break;
3285 }
3286
3287 /* success! */
3288 lck_mtx_lock(&nmp->nm_lock);
3289 nmp->nm_state |= NFSSTA_MOUNTED;
3290 lck_mtx_unlock(&nmp->nm_lock);
3291 return (0);
3292 nfsmerr:
3293 nfs_mount_cleanup(nmp);
3294 return (error);
3295 }
3296
3297 #if CONFIG_TRIGGERS
3298
3299 /*
3300 * We've detected a file system boundary on the server and
3301 * need to mount a new file system so that our file systems
3302 * MIRROR the file systems on the server.
3303 *
3304 * Build the mount arguments for the new mount and call kernel_mount().
3305 */
3306 int
3307 nfs_mirror_mount_domount(vnode_t dvp, vnode_t vp, vfs_context_t ctx)
3308 {
3309 nfsnode_t np = VTONFS(vp);
3310 nfsnode_t dnp = VTONFS(dvp);
3311 struct nfsmount *nmp = NFSTONMP(np);
3312 char fstype[MFSTYPENAMELEN], *mntfromname = NULL, *path = NULL, *relpath, *p, *cp;
3313 int error = 0, pathbuflen = MAXPATHLEN, i, mntflags = 0, referral, skipcopy = 0;
3314 size_t nlen;
3315 struct xdrbuf xb, xbnew;
3316 uint32_t mattrs[NFS_MATTR_BITMAP_LEN];
3317 uint32_t newmattrs[NFS_MATTR_BITMAP_LEN];
3318 uint32_t newmflags[NFS_MFLAG_BITMAP_LEN];
3319 uint32_t newmflags_mask[NFS_MFLAG_BITMAP_LEN];
3320 uint32_t argslength = 0, val, count, mlen, mlen2, rlen, relpathcomps;
3321 uint32_t argslength_offset, attrslength_offset, end_offset;
3322 uint32_t numlocs, loc, numserv, serv, numaddr, addr, numcomp, comp;
3323 char buf[XDRWORD];
3324 struct nfs_fs_locations nfsls;
3325
3326 referral = (np->n_vattr.nva_flags & NFS_FFLAG_TRIGGER_REFERRAL);
3327 if (referral)
3328 bzero(&nfsls, sizeof(nfsls));
3329
3330 xb_init(&xbnew, 0);
3331
3332 if (!nmp || (nmp->nm_state & (NFSSTA_FORCE|NFSSTA_DEAD)))
3333 return (ENXIO);
3334
3335 /* allocate a couple path buffers we need */
3336 MALLOC_ZONE(mntfromname, char *, pathbuflen, M_NAMEI, M_WAITOK);
3337 if (!mntfromname) {
3338 error = ENOMEM;
3339 goto nfsmerr;
3340 }
3341 MALLOC_ZONE(path, char *, pathbuflen, M_NAMEI, M_WAITOK);
3342 if (!path) {
3343 error = ENOMEM;
3344 goto nfsmerr;
3345 }
3346
3347 /* get the path for the directory being mounted on */
3348 error = vn_getpath(vp, path, &pathbuflen);
3349 if (error) {
3350 error = ENOMEM;
3351 goto nfsmerr;
3352 }
3353
3354 /*
3355 * Set up the mntfromname for the new mount based on the
3356 * current mount's mntfromname and the directory's path
3357 * relative to the current mount's mntonname.
3358 * Set up relpath to point at the relative path on the current mount.
3359 * Also, count the number of components in relpath.
3360 * We'll be adding those to each fs location path in the new args.
3361 */
3362 nlen = strlcpy(mntfromname, vfs_statfs(nmp->nm_mountp)->f_mntfromname, MAXPATHLEN);
3363 if ((nlen > 0) && (mntfromname[nlen-1] == '/')) { /* avoid double '/' in new name */
3364 mntfromname[nlen-1] = '\0';
3365 nlen--;
3366 }
3367 relpath = mntfromname + nlen;
3368 nlen = strlcat(mntfromname, path + strlen(vfs_statfs(nmp->nm_mountp)->f_mntonname), MAXPATHLEN);
3369 if (nlen >= MAXPATHLEN) {
3370 error = ENAMETOOLONG;
3371 goto nfsmerr;
3372 }
3373 /* count the number of components in relpath */
3374 p = relpath;
3375 while (*p && (*p == '/'))
3376 p++;
3377 relpathcomps = 0;
3378 while (*p) {
3379 relpathcomps++;
3380 while (*p && (*p != '/'))
3381 p++;
3382 while (*p && (*p == '/'))
3383 p++;
3384 }
3385
3386 /* grab a copy of the file system type */
3387 vfs_name(vnode_mount(vp), fstype);
3388
3389 /* for referrals, fetch the fs locations */
3390 if (referral) {
3391 const char *vname = vnode_getname(NFSTOV(np));
3392 if (!vname) {
3393 error = ENOENT;
3394 } else {
3395 error = nfs4_get_fs_locations(nmp, dnp, NULL, 0, vname, ctx, &nfsls);
3396 vnode_putname(vname);
3397 if (!error && (nfsls.nl_numlocs < 1))
3398 error = ENOENT;
3399 }
3400 nfsmerr_if(error);
3401 }
3402
3403 /* set up NFS mount args based on current mount args */
3404
3405 #define xb_copy_32(E, XBSRC, XBDST, V) \
3406 do { \
3407 if (E) break; \
3408 xb_get_32((E), (XBSRC), (V)); \
3409 if (skipcopy) break; \
3410 xb_add_32((E), (XBDST), (V)); \
3411 } while (0)
3412 #define xb_copy_opaque(E, XBSRC, XBDST) \
3413 do { \
3414 uint32_t __count, __val; \
3415 xb_copy_32((E), (XBSRC), (XBDST), __count); \
3416 if (E) break; \
3417 __count = nfsm_rndup(__count); \
3418 __count /= XDRWORD; \
3419 while (__count-- > 0) \
3420 xb_copy_32((E), (XBSRC), (XBDST), __val); \
3421 } while (0)
3422
3423 xb_init_buffer(&xb, nmp->nm_args, 2*XDRWORD);
3424 xb_get_32(error, &xb, val); /* version */
3425 xb_get_32(error, &xb, argslength); /* args length */
3426 xb_init_buffer(&xb, nmp->nm_args, argslength);
3427
3428 xb_init_buffer(&xbnew, NULL, 0);
3429 xb_copy_32(error, &xb, &xbnew, val); /* version */
3430 argslength_offset = xb_offset(&xbnew);
3431 xb_copy_32(error, &xb, &xbnew, val); /* args length */
3432 xb_copy_32(error, &xb, &xbnew, val); /* XDR args version */
3433 count = NFS_MATTR_BITMAP_LEN;
3434 xb_get_bitmap(error, &xb, mattrs, count); /* mount attribute bitmap */
3435 nfsmerr_if(error);
3436 for (i = 0; i < NFS_MATTR_BITMAP_LEN; i++)
3437 newmattrs[i] = mattrs[i];
3438 if (referral)
3439 NFS_BITMAP_SET(newmattrs, NFS_MATTR_FS_LOCATIONS);
3440 else
3441 NFS_BITMAP_SET(newmattrs, NFS_MATTR_FH);
3442 NFS_BITMAP_SET(newmattrs, NFS_MATTR_FLAGS);
3443 NFS_BITMAP_SET(newmattrs, NFS_MATTR_MNTFLAGS);
3444 NFS_BITMAP_CLR(newmattrs, NFS_MATTR_MNTFROM);
3445 xb_add_bitmap(error, &xbnew, newmattrs, NFS_MATTR_BITMAP_LEN);
3446 attrslength_offset = xb_offset(&xbnew);
3447 xb_copy_32(error, &xb, &xbnew, val); /* attrs length */
3448 NFS_BITMAP_ZERO(newmflags_mask, NFS_MFLAG_BITMAP_LEN);
3449 NFS_BITMAP_ZERO(newmflags, NFS_MFLAG_BITMAP_LEN);
3450 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_FLAGS)) {
3451 count = NFS_MFLAG_BITMAP_LEN;
3452 xb_get_bitmap(error, &xb, newmflags_mask, count); /* mount flag mask bitmap */
3453 count = NFS_MFLAG_BITMAP_LEN;
3454 xb_get_bitmap(error, &xb, newmflags, count); /* mount flag bitmap */
3455 }
3456 NFS_BITMAP_SET(newmflags_mask, NFS_MFLAG_EPHEMERAL);
3457 NFS_BITMAP_SET(newmflags, NFS_MFLAG_EPHEMERAL);
3458 xb_add_bitmap(error, &xbnew, newmflags_mask, NFS_MFLAG_BITMAP_LEN);
3459 xb_add_bitmap(error, &xbnew, newmflags, NFS_MFLAG_BITMAP_LEN);
3460 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_NFS_VERSION))
3461 xb_copy_32(error, &xb, &xbnew, val);
3462 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_NFS_MINOR_VERSION))
3463 xb_copy_32(error, &xb, &xbnew, val);
3464 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_READ_SIZE))
3465 xb_copy_32(error, &xb, &xbnew, val);
3466 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_WRITE_SIZE))
3467 xb_copy_32(error, &xb, &xbnew, val);
3468 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_READDIR_SIZE))
3469 xb_copy_32(error, &xb, &xbnew, val);
3470 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_READAHEAD))
3471 xb_copy_32(error, &xb, &xbnew, val);
3472 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_ATTRCACHE_REG_MIN)) {
3473 xb_copy_32(error, &xb, &xbnew, val);
3474 xb_copy_32(error, &xb, &xbnew, val);
3475 }
3476 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_ATTRCACHE_REG_MAX)) {
3477 xb_copy_32(error, &xb, &xbnew, val);
3478 xb_copy_32(error, &xb, &xbnew, val);
3479 }
3480 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_ATTRCACHE_DIR_MIN)) {
3481 xb_copy_32(error, &xb, &xbnew, val);
3482 xb_copy_32(error, &xb, &xbnew, val);
3483 }
3484 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_ATTRCACHE_DIR_MAX)) {
3485 xb_copy_32(error, &xb, &xbnew, val);
3486 xb_copy_32(error, &xb, &xbnew, val);
3487 }
3488 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_LOCK_MODE))
3489 xb_copy_32(error, &xb, &xbnew, val);
3490 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_SECURITY)) {
3491 xb_copy_32(error, &xb, &xbnew, count);
3492 while (!error && (count-- > 0))
3493 xb_copy_32(error, &xb, &xbnew, val);
3494 }
3495 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_MAX_GROUP_LIST))
3496 xb_copy_32(error, &xb, &xbnew, val);
3497 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_SOCKET_TYPE))
3498 xb_copy_opaque(error, &xb, &xbnew);
3499 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_NFS_PORT))
3500 xb_copy_32(error, &xb, &xbnew, val);
3501 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_MOUNT_PORT))
3502 xb_copy_32(error, &xb, &xbnew, val);
3503 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_REQUEST_TIMEOUT)) {
3504 xb_copy_32(error, &xb, &xbnew, val);
3505 xb_copy_32(error, &xb, &xbnew, val);
3506 }
3507 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_SOFT_RETRY_COUNT))
3508 xb_copy_32(error, &xb, &xbnew, val);
3509 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_DEAD_TIMEOUT)) {
3510 xb_copy_32(error, &xb, &xbnew, val);
3511 xb_copy_32(error, &xb, &xbnew, val);
3512 }
3513 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_FH)) {
3514 xb_get_32(error, &xb, count);
3515 xb_skip(error, &xb, count);
3516 }
3517 if (!referral) {
3518 /* set the initial file handle to the directory's file handle */
3519 xb_add_fh(error, &xbnew, np->n_fhp, np->n_fhsize);
3520 }
3521 /* copy/extend/skip fs locations */
3522 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_FS_LOCATIONS)) {
3523 numlocs = numserv = numaddr = numcomp = 0;
3524 if (referral) /* don't copy the fs locations for a referral */
3525 skipcopy = 1;
3526 xb_copy_32(error, &xb, &xbnew, numlocs); /* location count */
3527 for (loc = 0; !error && (loc < numlocs); loc++) {
3528 xb_copy_32(error, &xb, &xbnew, numserv); /* server count */
3529 for (serv = 0; !error && (serv < numserv); serv++) {
3530 xb_copy_opaque(error, &xb, &xbnew); /* server name */
3531 xb_copy_32(error, &xb, &xbnew, numaddr); /* address count */
3532 for (addr = 0; !error && (addr < numaddr); addr++)
3533 xb_copy_opaque(error, &xb, &xbnew); /* address */
3534 xb_copy_opaque(error, &xb, &xbnew); /* server info */
3535 }
3536 /* pathname */
3537 xb_get_32(error, &xb, numcomp); /* component count */
3538 if (!skipcopy)
3539 xb_add_32(error, &xbnew, numcomp+relpathcomps); /* new component count */
3540 for (comp = 0; !error && (comp < numcomp); comp++)
3541 xb_copy_opaque(error, &xb, &xbnew); /* component */
3542 /* add additional components */
3543 for (comp = 0; !skipcopy && !error && (comp < relpathcomps); comp++) {
3544 p = relpath;
3545 while (*p && (*p == '/'))
3546 p++;
3547 while (*p && !error) {
3548 cp = p;
3549 while (*p && (*p != '/'))
3550 p++;
3551 xb_add_string(error, &xbnew, cp, (p - cp)); /* component */
3552 while (*p && (*p == '/'))
3553 p++;
3554 }
3555 }
3556 xb_copy_opaque(error, &xb, &xbnew); /* fs location info */
3557 }
3558 if (referral)
3559 skipcopy = 0;
3560 }
3561 if (referral) {
3562 /* add referral's fs locations */
3563 xb_add_32(error, &xbnew, nfsls.nl_numlocs); /* FS_LOCATIONS */
3564 for (loc = 0; !error && (loc < nfsls.nl_numlocs); loc++) {
3565 xb_add_32(error, &xbnew, nfsls.nl_locations[loc]->nl_servcount);
3566 for (serv = 0; !error && (serv < nfsls.nl_locations[loc]->nl_servcount); serv++) {
3567 xb_add_string(error, &xbnew, nfsls.nl_locations[loc]->nl_servers[serv]->ns_name,
3568 strlen(nfsls.nl_locations[loc]->nl_servers[serv]->ns_name));
3569 xb_add_32(error, &xbnew, nfsls.nl_locations[loc]->nl_servers[serv]->ns_addrcount);
3570 for (addr = 0; !error && (addr < nfsls.nl_locations[loc]->nl_servers[serv]->ns_addrcount); addr++)
3571 xb_add_string(error, &xbnew, nfsls.nl_locations[loc]->nl_servers[serv]->ns_addresses[addr],
3572 strlen(nfsls.nl_locations[loc]->nl_servers[serv]->ns_addresses[addr]));
3573 xb_add_32(error, &xbnew, 0); /* empty server info */
3574 }
3575 xb_add_32(error, &xbnew, nfsls.nl_locations[loc]->nl_path.np_compcount);
3576 for (comp = 0; !error && (comp < nfsls.nl_locations[loc]->nl_path.np_compcount); comp++)
3577 xb_add_string(error, &xbnew, nfsls.nl_locations[loc]->nl_path.np_components[comp],
3578 strlen(nfsls.nl_locations[loc]->nl_path.np_components[comp]));
3579 xb_add_32(error, &xbnew, 0); /* empty fs location info */
3580 }
3581 }
3582 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_MNTFLAGS))
3583 xb_get_32(error, &xb, mntflags);
3584 /*
3585 * We add the following mount flags to the ones for the mounted-on mount:
3586 * MNT_DONTBROWSE - to keep the mount from showing up as a separate volume
3587 * MNT_AUTOMOUNTED - to keep DiskArb from retriggering the mount after
3588 * an unmount (looking for /.autodiskmounted)
3589 */
3590 mntflags |= (MNT_AUTOMOUNTED | MNT_DONTBROWSE);
3591 xb_add_32(error, &xbnew, mntflags);
3592 if (!referral && NFS_BITMAP_ISSET(mattrs, NFS_MATTR_MNTFROM)) {
3593 /* copy mntfrom string and add relpath */
3594 rlen = strlen(relpath);
3595 xb_get_32(error, &xb, mlen);
3596 nfsmerr_if(error);
3597 mlen2 = mlen + ((relpath[0] != '/') ? 1 : 0) + rlen;
3598 xb_add_32(error, &xbnew, mlen2);
3599 count = mlen/XDRWORD;
3600 /* copy the original string */
3601 while (count-- > 0)
3602 xb_copy_32(error, &xb, &xbnew, val);
3603 if (!error && (mlen % XDRWORD)) {
3604 error = xb_get_bytes(&xb, buf, mlen%XDRWORD, 0);
3605 if (!error)
3606 error = xb_add_bytes(&xbnew, buf, mlen%XDRWORD, 1);
3607 }
3608 /* insert a '/' if the relative path doesn't start with one */
3609 if (!error && (relpath[0] != '/')) {
3610 buf[0] = '/';
3611 error = xb_add_bytes(&xbnew, buf, 1, 1);
3612 }
3613 /* add the additional relative path */
3614 if (!error)
3615 error = xb_add_bytes(&xbnew, relpath, rlen, 1);
3616 /* make sure the resulting string has the right number of pad bytes */
3617 if (!error && (mlen2 != nfsm_rndup(mlen2))) {
3618 bzero(buf, sizeof(buf));
3619 count = nfsm_rndup(mlen2) - mlen2;
3620 error = xb_add_bytes(&xbnew, buf, count, 1);
3621 }
3622 }
3623 xb_build_done(error, &xbnew);
3624
3625 /* update opaque counts */
3626 end_offset = xb_offset(&xbnew);
3627 if (!error) {
3628 error = xb_seek(&xbnew, argslength_offset);
3629 argslength = end_offset - argslength_offset + XDRWORD/*version*/;
3630 xb_add_32(error, &xbnew, argslength);
3631 }
3632 if (!error) {
3633 error = xb_seek(&xbnew, attrslength_offset);
3634 xb_add_32(error, &xbnew, end_offset - attrslength_offset - XDRWORD/*don't include length field*/);
3635 }
3636 nfsmerr_if(error);
3637
3638 /*
3639 * For kernel_mount() call, use the existing mount flags (instead of the
3640 * original flags) because flags like MNT_NOSUID and MNT_NODEV may have
3641 * been silently enforced.
3642 */
3643 mntflags = vnode_vfsvisflags(vp);
3644 mntflags |= (MNT_AUTOMOUNTED | MNT_DONTBROWSE);
3645
3646 /* do the mount */
3647 error = kernel_mount(fstype, dvp, vp, path, xb_buffer_base(&xbnew), argslength,
3648 mntflags, KERNEL_MOUNT_PERMIT_UNMOUNT | KERNEL_MOUNT_NOAUTH, ctx);
3649
3650 nfsmerr:
3651 if (error)
3652 printf("nfs: mirror mount of %s on %s failed (%d)\n",
3653 mntfromname, path, error);
3654 /* clean up */
3655 xb_cleanup(&xbnew);
3656 if (referral)
3657 nfs_fs_locations_cleanup(&nfsls);
3658 if (path)
3659 FREE_ZONE(path, MAXPATHLEN, M_NAMEI);
3660 if (mntfromname)
3661 FREE_ZONE(mntfromname, MAXPATHLEN, M_NAMEI);
3662 if (!error)
3663 nfs_ephemeral_mount_harvester_start();
3664 return (error);
3665 }
3666
3667 /*
3668 * trigger vnode functions
3669 */
3670
3671 resolver_result_t
3672 nfs_mirror_mount_trigger_resolve(
3673 vnode_t vp,
3674 const struct componentname *cnp,
3675 enum path_operation pop,
3676 __unused int flags,
3677 __unused void *data,
3678 vfs_context_t ctx)
3679 {
3680 nfsnode_t np = VTONFS(vp);
3681 vnode_t pvp = NULLVP;
3682 int error = 0;
3683 resolver_result_t result;
3684
3685 /*
3686 * We have a trigger node that doesn't have anything mounted on it yet.
3687 * We'll do the mount if either:
3688 * (a) this isn't the last component of the path OR
3689 * (b) this is an op that looks like it should trigger the mount.
3690 */
3691 if (cnp->cn_flags & ISLASTCN) {
3692 switch (pop) {
3693 case OP_MOUNT:
3694 case OP_UNMOUNT:
3695 case OP_STATFS:
3696 case OP_LINK:
3697 case OP_UNLINK:
3698 case OP_RENAME:
3699 case OP_MKNOD:
3700 case OP_MKFIFO:
3701 case OP_SYMLINK:
3702 case OP_ACCESS:
3703 case OP_GETATTR:
3704 case OP_MKDIR:
3705 case OP_RMDIR:
3706 case OP_REVOKE:
3707 case OP_GETXATTR:
3708 case OP_LISTXATTR:
3709 /* don't perform the mount for these operations */
3710 result = vfs_resolver_result(np->n_trigseq, RESOLVER_NOCHANGE, 0);
3711 #ifdef NFS_TRIGGER_DEBUG
3712 NP(np, "nfs trigger RESOLVE: no change, last %d nameiop %d, seq %d",
3713 (cnp->cn_flags & ISLASTCN) ? 1 : 0, cnp->cn_nameiop, np->n_trigseq);
3714 #endif
3715 return (result);
3716 case OP_OPEN:
3717 case OP_CHDIR:
3718 case OP_CHROOT:
3719 case OP_TRUNCATE:
3720 case OP_COPYFILE:
3721 case OP_PATHCONF:
3722 case OP_READLINK:
3723 case OP_SETATTR:
3724 case OP_EXCHANGEDATA:
3725 case OP_SEARCHFS:
3726 case OP_FSCTL:
3727 case OP_SETXATTR:
3728 case OP_REMOVEXATTR:
3729 default:
3730 /* go ahead and do the mount */
3731 break;
3732 }
3733 }
3734
3735 if (vnode_mountedhere(vp) != NULL) {
3736 /*
3737 * Um... there's already something mounted.
3738 * Been there. Done that. Let's just say it succeeded.
3739 */
3740 error = 0;
3741 goto skipmount;
3742 }
3743
3744 if ((error = nfs_node_set_busy(np, vfs_context_thread(ctx)))) {
3745 result = vfs_resolver_result(np->n_trigseq, RESOLVER_ERROR, error);
3746 #ifdef NFS_TRIGGER_DEBUG
3747 NP(np, "nfs trigger RESOLVE: busy error %d, last %d nameiop %d, seq %d",
3748 error, (cnp->cn_flags & ISLASTCN) ? 1 : 0, cnp->cn_nameiop, np->n_trigseq);
3749 #endif
3750 return (result);
3751 }
3752
3753 pvp = vnode_getparent(vp);
3754 if (pvp == NULLVP)
3755 error = EINVAL;
3756 if (!error)
3757 error = nfs_mirror_mount_domount(pvp, vp, ctx);
3758 skipmount:
3759 if (!error)
3760 np->n_trigseq++;
3761 result = vfs_resolver_result(np->n_trigseq, error ? RESOLVER_ERROR : RESOLVER_RESOLVED, error);
3762 #ifdef NFS_TRIGGER_DEBUG
3763 NP(np, "nfs trigger RESOLVE: %s %d, last %d nameiop %d, seq %d",
3764 error ? "error" : "resolved", error,
3765 (cnp->cn_flags & ISLASTCN) ? 1 : 0, cnp->cn_nameiop, np->n_trigseq);
3766 #endif
3767
3768 if (pvp != NULLVP)
3769 vnode_put(pvp);
3770 nfs_node_clear_busy(np);
3771 return (result);
3772 }
3773
3774 resolver_result_t
3775 nfs_mirror_mount_trigger_unresolve(
3776 vnode_t vp,
3777 int flags,
3778 __unused void *data,
3779 vfs_context_t ctx)
3780 {
3781 nfsnode_t np = VTONFS(vp);
3782 mount_t mp;
3783 int error;
3784 resolver_result_t result;
3785
3786 if ((error = nfs_node_set_busy(np, vfs_context_thread(ctx)))) {
3787 result = vfs_resolver_result(np->n_trigseq, RESOLVER_ERROR, error);
3788 #ifdef NFS_TRIGGER_DEBUG
3789 NP(np, "nfs trigger UNRESOLVE: busy error %d, seq %d", error, np->n_trigseq);
3790 #endif
3791 return (result);
3792 }
3793
3794 mp = vnode_mountedhere(vp);
3795 if (!mp)
3796 error = EINVAL;
3797 if (!error)
3798 error = vfs_unmountbyfsid(&(vfs_statfs(mp)->f_fsid), flags, ctx);
3799 if (!error)
3800 np->n_trigseq++;
3801 result = vfs_resolver_result(np->n_trigseq, error ? RESOLVER_ERROR : RESOLVER_UNRESOLVED, error);
3802 #ifdef NFS_TRIGGER_DEBUG
3803 NP(np, "nfs trigger UNRESOLVE: %s %d, seq %d",
3804 error ? "error" : "unresolved", error, np->n_trigseq);
3805 #endif
3806 nfs_node_clear_busy(np);
3807 return (result);
3808 }
3809
3810 resolver_result_t
3811 nfs_mirror_mount_trigger_rearm(
3812 vnode_t vp,
3813 __unused int flags,
3814 __unused void *data,
3815 vfs_context_t ctx)
3816 {
3817 nfsnode_t np = VTONFS(vp);
3818 int error;
3819 resolver_result_t result;
3820
3821 if ((error = nfs_node_set_busy(np, vfs_context_thread(ctx)))) {
3822 result = vfs_resolver_result(np->n_trigseq, RESOLVER_ERROR, error);
3823 #ifdef NFS_TRIGGER_DEBUG
3824 NP(np, "nfs trigger REARM: busy error %d, seq %d", error, np->n_trigseq);
3825 #endif
3826 return (result);
3827 }
3828
3829 np->n_trigseq++;
3830 result = vfs_resolver_result(np->n_trigseq,
3831 vnode_mountedhere(vp) ? RESOLVER_RESOLVED : RESOLVER_UNRESOLVED, 0);
3832 #ifdef NFS_TRIGGER_DEBUG
3833 NP(np, "nfs trigger REARM: %s, seq %d",
3834 vnode_mountedhere(vp) ? "resolved" : "unresolved", np->n_trigseq);
3835 #endif
3836 nfs_node_clear_busy(np);
3837 return (result);
3838 }
3839
3840 /*
3841 * Periodically attempt to unmount ephemeral (mirror) mounts in an attempt to limit
3842 * the number of unused mounts.
3843 */
3844
3845 #define NFS_EPHEMERAL_MOUNT_HARVEST_INTERVAL 120 /* how often the harvester runs */
3846 struct nfs_ephemeral_mount_harvester_info {
3847 fsid_t fsid; /* FSID that we need to try to unmount */
3848 uint32_t mountcount; /* count of ephemeral mounts seen in scan */
3849 };
3850 /* various globals for the harvester */
3851 static thread_call_t nfs_ephemeral_mount_harvester_timer = NULL;
3852 static int nfs_ephemeral_mount_harvester_on = 0;
3853
3854 kern_return_t thread_terminate(thread_t);
3855
3856 static int
3857 nfs_ephemeral_mount_harvester_callback(mount_t mp, void *arg)
3858 {
3859 struct nfs_ephemeral_mount_harvester_info *hinfo = arg;
3860 struct nfsmount *nmp;
3861 struct timeval now;
3862
3863 if (strcmp(mp->mnt_vfsstat.f_fstypename, "nfs"))
3864 return (VFS_RETURNED);
3865 nmp = VFSTONFS(mp);
3866 if (!nmp || !NMFLAG(nmp, EPHEMERAL))
3867 return (VFS_RETURNED);
3868 hinfo->mountcount++;
3869
3870 /* avoid unmounting mounts that have been triggered within the last harvest interval */
3871 microtime(&now);
3872 if ((nmp->nm_mounttime >> 32) > ((uint32_t)now.tv_sec - NFS_EPHEMERAL_MOUNT_HARVEST_INTERVAL))
3873 return (VFS_RETURNED);
3874
3875 if (hinfo->fsid.val[0] || hinfo->fsid.val[1]) {
3876 /* attempt to unmount previously-found ephemeral mount */
3877 vfs_unmountbyfsid(&hinfo->fsid, 0, vfs_context_kernel());
3878 hinfo->fsid.val[0] = hinfo->fsid.val[1] = 0;
3879 }
3880
3881 /*
3882 * We can't call unmount here since we hold a mount iter ref
3883 * on mp so save its fsid for the next call iteration to unmount.
3884 */
3885 hinfo->fsid.val[0] = mp->mnt_vfsstat.f_fsid.val[0];
3886 hinfo->fsid.val[1] = mp->mnt_vfsstat.f_fsid.val[1];
3887
3888 return (VFS_RETURNED);
3889 }
3890
3891 /*
3892 * Spawn a thread to do the ephemeral mount harvesting.
3893 */
3894 static void
3895 nfs_ephemeral_mount_harvester_timer_func(void)
3896 {
3897 thread_t thd;
3898
3899 if (kernel_thread_start(nfs_ephemeral_mount_harvester, NULL, &thd) == KERN_SUCCESS)
3900 thread_deallocate(thd);
3901 }
3902
3903 /*
3904 * Iterate all mounts looking for NFS ephemeral mounts to try to unmount.
3905 */
3906 void
3907 nfs_ephemeral_mount_harvester(__unused void *arg, __unused wait_result_t wr)
3908 {
3909 struct nfs_ephemeral_mount_harvester_info hinfo;
3910 uint64_t deadline;
3911
3912 hinfo.mountcount = 0;
3913 hinfo.fsid.val[0] = hinfo.fsid.val[1] = 0;
3914 vfs_iterate(VFS_ITERATE_TAIL_FIRST, nfs_ephemeral_mount_harvester_callback, &hinfo);
3915 if (hinfo.fsid.val[0] || hinfo.fsid.val[1]) {
3916 /* attempt to unmount last found ephemeral mount */
3917 vfs_unmountbyfsid(&hinfo.fsid, 0, vfs_context_kernel());
3918 }
3919
3920 lck_mtx_lock(nfs_global_mutex);
3921 if (!hinfo.mountcount) {
3922 /* no more ephemeral mounts - don't need timer */
3923 nfs_ephemeral_mount_harvester_on = 0;
3924 } else {
3925 /* re-arm the timer */
3926 clock_interval_to_deadline(NFS_EPHEMERAL_MOUNT_HARVEST_INTERVAL, NSEC_PER_SEC, &deadline);
3927 thread_call_enter_delayed(nfs_ephemeral_mount_harvester_timer, deadline);
3928 nfs_ephemeral_mount_harvester_on = 1;
3929 }
3930 lck_mtx_unlock(nfs_global_mutex);
3931
3932 /* thread done */
3933 thread_terminate(current_thread());
3934 }
3935
3936 /*
3937 * Make sure the NFS ephemeral mount harvester timer is running.
3938 */
3939 void
3940 nfs_ephemeral_mount_harvester_start(void)
3941 {
3942 uint64_t deadline;
3943
3944 lck_mtx_lock(nfs_global_mutex);
3945 if (nfs_ephemeral_mount_harvester_on) {
3946 lck_mtx_unlock(nfs_global_mutex);
3947 return;
3948 }
3949 if (nfs_ephemeral_mount_harvester_timer == NULL)
3950 nfs_ephemeral_mount_harvester_timer = thread_call_allocate((thread_call_func_t)nfs_ephemeral_mount_harvester_timer_func, NULL);
3951 clock_interval_to_deadline(NFS_EPHEMERAL_MOUNT_HARVEST_INTERVAL, NSEC_PER_SEC, &deadline);
3952 thread_call_enter_delayed(nfs_ephemeral_mount_harvester_timer, deadline);
3953 nfs_ephemeral_mount_harvester_on = 1;
3954 lck_mtx_unlock(nfs_global_mutex);
3955 }
3956
3957 #endif
3958
3959 /*
3960 * Send a MOUNT protocol MOUNT request to the server to get the initial file handle (and security).
3961 */
3962 int
3963 nfs3_mount_rpc(struct nfsmount *nmp, struct sockaddr *sa, int sotype, int nfsvers, char *path, vfs_context_t ctx, int timeo, fhandle_t *fh, struct nfs_sec *sec)
3964 {
3965 int error = 0, slen, mntproto;
3966 thread_t thd = vfs_context_thread(ctx);
3967 kauth_cred_t cred = vfs_context_ucred(ctx);
3968 uint64_t xid = 0;
3969 struct nfsm_chain nmreq, nmrep;
3970 mbuf_t mreq;
3971 uint32_t mntvers, mntport, val;
3972 struct sockaddr_storage ss;
3973 struct sockaddr *saddr = (struct sockaddr*)&ss;
3974
3975 nfsm_chain_null(&nmreq);
3976 nfsm_chain_null(&nmrep);
3977
3978 mntvers = (nfsvers == NFS_VER2) ? RPCMNT_VER1 : RPCMNT_VER3;
3979 mntproto = (NM_OMFLAG(nmp, MNTUDP) || (sotype == SOCK_DGRAM)) ? IPPROTO_UDP : IPPROTO_TCP;
3980 sec->count = 0;
3981
3982 bcopy(sa, saddr, min(sizeof(ss), sa->sa_len));
3983 if (saddr->sa_family == AF_INET) {
3984 if (nmp->nm_mountport)
3985 ((struct sockaddr_in*)saddr)->sin_port = htons(nmp->nm_mountport);
3986 mntport = ntohs(((struct sockaddr_in*)saddr)->sin_port);
3987 } else {
3988 if (nmp->nm_mountport)
3989 ((struct sockaddr_in6*)saddr)->sin6_port = htons(nmp->nm_mountport);
3990 mntport = ntohs(((struct sockaddr_in6*)saddr)->sin6_port);
3991 }
3992
3993 while (!mntport) {
3994 error = nfs_portmap_lookup(nmp, ctx, saddr, NULL, RPCPROG_MNT, mntvers, mntproto, timeo);
3995 nfsmout_if(error);
3996 if (saddr->sa_family == AF_INET)
3997 mntport = ntohs(((struct sockaddr_in*)saddr)->sin_port);
3998 else
3999 mntport = ntohs(((struct sockaddr_in6*)saddr)->sin6_port);
4000 if (!mntport) {
4001 /* if not found and TCP, then retry with UDP */
4002 if (mntproto == IPPROTO_UDP) {
4003 error = EPROGUNAVAIL;
4004 break;
4005 }
4006 mntproto = IPPROTO_UDP;
4007 bcopy(sa, saddr, min(sizeof(ss), sa->sa_len));
4008 }
4009 }
4010 nfsmout_if(error || !mntport);
4011
4012 /* MOUNT protocol MOUNT request */
4013 slen = strlen(path);
4014 nfsm_chain_build_alloc_init(error, &nmreq, NFSX_UNSIGNED + nfsm_rndup(slen));
4015 nfsm_chain_add_name(error, &nmreq, path, slen, nmp);
4016 nfsm_chain_build_done(error, &nmreq);
4017 nfsmout_if(error);
4018 error = nfsm_rpchead2(nmp, (mntproto == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM,
4019 RPCPROG_MNT, mntvers, RPCMNT_MOUNT,
4020 RPCAUTH_SYS, cred, NULL, nmreq.nmc_mhead, &xid, &mreq);
4021 nfsmout_if(error);
4022 nmreq.nmc_mhead = NULL;
4023 error = nfs_aux_request(nmp, thd, saddr, NULL,
4024 ((mntproto == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM),
4025 mreq, R_XID32(xid), 1, timeo, &nmrep);
4026 nfsmout_if(error);
4027 nfsm_chain_get_32(error, &nmrep, val);
4028 if (!error && val)
4029 error = val;
4030 nfsm_chain_get_fh(error, &nmrep, nfsvers, fh);
4031 if (!error && (nfsvers > NFS_VER2)) {
4032 sec->count = NX_MAX_SEC_FLAVORS;
4033 error = nfsm_chain_get_secinfo(&nmrep, &sec->flavors[0], &sec->count);
4034 }
4035 nfsmout:
4036 nfsm_chain_cleanup(&nmreq);
4037 nfsm_chain_cleanup(&nmrep);
4038 return (error);
4039 }
4040
4041
4042 /*
4043 * Send a MOUNT protocol UNMOUNT request to tell the server we've unmounted it.
4044 */
4045 void
4046 nfs3_umount_rpc(struct nfsmount *nmp, vfs_context_t ctx, int timeo)
4047 {
4048 int error = 0, slen, mntproto;
4049 thread_t thd = vfs_context_thread(ctx);
4050 kauth_cred_t cred = vfs_context_ucred(ctx);
4051 char *path;
4052 uint64_t xid = 0;
4053 struct nfsm_chain nmreq, nmrep;
4054 mbuf_t mreq;
4055 uint32_t mntvers, mntport;
4056 struct sockaddr_storage ss;
4057 struct sockaddr *saddr = (struct sockaddr*)&ss;
4058
4059 if (!nmp->nm_saddr)
4060 return;
4061
4062 nfsm_chain_null(&nmreq);
4063 nfsm_chain_null(&nmrep);
4064
4065 mntvers = (nmp->nm_vers == NFS_VER2) ? RPCMNT_VER1 : RPCMNT_VER3;
4066 mntproto = (NM_OMFLAG(nmp, MNTUDP) || (nmp->nm_sotype == SOCK_DGRAM)) ? IPPROTO_UDP : IPPROTO_TCP;
4067 mntport = nmp->nm_mountport;
4068
4069 bcopy(nmp->nm_saddr, saddr, min(sizeof(ss), nmp->nm_saddr->sa_len));
4070 if (saddr->sa_family == AF_INET)
4071 ((struct sockaddr_in*)saddr)->sin_port = htons(mntport);
4072 else
4073 ((struct sockaddr_in6*)saddr)->sin6_port = htons(mntport);
4074
4075 while (!mntport) {
4076 error = nfs_portmap_lookup(nmp, ctx, saddr, NULL, RPCPROG_MNT, mntvers, mntproto, timeo);
4077 nfsmout_if(error);
4078 if (saddr->sa_family == AF_INET)
4079 mntport = ntohs(((struct sockaddr_in*)saddr)->sin_port);
4080 else
4081 mntport = ntohs(((struct sockaddr_in6*)saddr)->sin6_port);
4082 /* if not found and mntvers > VER1, then retry with VER1 */
4083 if (!mntport) {
4084 if (mntvers > RPCMNT_VER1) {
4085 mntvers = RPCMNT_VER1;
4086 } else if (mntproto == IPPROTO_TCP) {
4087 mntproto = IPPROTO_UDP;
4088 mntvers = (nmp->nm_vers == NFS_VER2) ? RPCMNT_VER1 : RPCMNT_VER3;
4089 } else {
4090 break;
4091 }
4092 bcopy(nmp->nm_saddr, saddr, min(sizeof(ss), nmp->nm_saddr->sa_len));
4093 }
4094 }
4095 nfsmout_if(!mntport);
4096
4097 /* MOUNT protocol UNMOUNT request */
4098 path = &vfs_statfs(nmp->nm_mountp)->f_mntfromname[0];
4099 while (*path && (*path != '/'))
4100 path++;
4101 slen = strlen(path);
4102 nfsm_chain_build_alloc_init(error, &nmreq, NFSX_UNSIGNED + nfsm_rndup(slen));
4103 nfsm_chain_add_name(error, &nmreq, path, slen, nmp);
4104 nfsm_chain_build_done(error, &nmreq);
4105 nfsmout_if(error);
4106 error = nfsm_rpchead2(nmp, (mntproto == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM,
4107 RPCPROG_MNT, RPCMNT_VER1, RPCMNT_UMOUNT,
4108 RPCAUTH_SYS, cred, NULL, nmreq.nmc_mhead, &xid, &mreq);
4109 nfsmout_if(error);
4110 nmreq.nmc_mhead = NULL;
4111 error = nfs_aux_request(nmp, thd, saddr, NULL,
4112 ((mntproto == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM),
4113 mreq, R_XID32(xid), 1, timeo, &nmrep);
4114 nfsmout:
4115 nfsm_chain_cleanup(&nmreq);
4116 nfsm_chain_cleanup(&nmrep);
4117 }
4118
4119 /*
4120 * unmount system call
4121 */
4122 int
4123 nfs_vfs_unmount(
4124 mount_t mp,
4125 int mntflags,
4126 __unused vfs_context_t ctx)
4127 {
4128 struct nfsmount *nmp;
4129 vnode_t vp;
4130 int error, flags = 0;
4131 struct timespec ts = { 1, 0 };
4132
4133 nmp = VFSTONFS(mp);
4134 lck_mtx_lock(&nmp->nm_lock);
4135 /*
4136 * Set the flag indicating that an unmount attempt is in progress.
4137 */
4138 nmp->nm_state |= NFSSTA_UNMOUNTING;
4139 /*
4140 * During a force unmount we want to...
4141 * Mark that we are doing a force unmount.
4142 * Make the mountpoint soft.
4143 */
4144 if (mntflags & MNT_FORCE) {
4145 flags |= FORCECLOSE;
4146 nmp->nm_state |= NFSSTA_FORCE;
4147 NFS_BITMAP_SET(nmp->nm_flags, NFS_MFLAG_SOFT);
4148 }
4149 /*
4150 * Wait for any in-progress monitored node scan to complete.
4151 */
4152 while (nmp->nm_state & NFSSTA_MONITOR_SCAN)
4153 msleep(&nmp->nm_state, &nmp->nm_lock, PZERO-1, "nfswaitmonscan", &ts);
4154 /*
4155 * Goes something like this..
4156 * - Call vflush() to clear out vnodes for this file system,
4157 * except for the swap files. Deal with them in 2nd pass.
4158 * - Decrement reference on the vnode representing remote root.
4159 * - Clean up the NFS mount structure.
4160 */
4161 vp = NFSTOV(nmp->nm_dnp);
4162 lck_mtx_unlock(&nmp->nm_lock);
4163
4164 /*
4165 * vflush will check for busy vnodes on mountpoint.
4166 * Will do the right thing for MNT_FORCE. That is, we should
4167 * not get EBUSY back.
4168 */
4169 error = vflush(mp, vp, SKIPSWAP | flags);
4170 if (mntflags & MNT_FORCE) {
4171 error = vflush(mp, NULLVP, flags); /* locks vp in the process */
4172 } else {
4173 if (vnode_isinuse(vp, 1))
4174 error = EBUSY;
4175 else
4176 error = vflush(mp, vp, flags);
4177 }
4178 if (error) {
4179 lck_mtx_lock(&nmp->nm_lock);
4180 nmp->nm_state &= ~NFSSTA_UNMOUNTING;
4181 lck_mtx_unlock(&nmp->nm_lock);
4182 return (error);
4183 }
4184
4185 lck_mtx_lock(&nmp->nm_lock);
4186 nmp->nm_dnp = NULL;
4187 lck_mtx_unlock(&nmp->nm_lock);
4188
4189 /*
4190 * Release the root vnode reference held by mountnfs()
4191 */
4192 error = vnode_get(vp);
4193 vnode_rele(vp);
4194 if (!error)
4195 vnode_put(vp);
4196
4197 vflush(mp, NULLVP, FORCECLOSE);
4198
4199 /* Wait for all other references to be released and free the mount */
4200 nfs_mount_drain_and_cleanup(nmp);
4201
4202 return (0);
4203 }
4204
4205 /*
4206 * cleanup/destroy NFS fs locations structure
4207 */
4208 void
4209 nfs_fs_locations_cleanup(struct nfs_fs_locations *nfslsp)
4210 {
4211 struct nfs_fs_location *fsl;
4212 struct nfs_fs_server *fss;
4213 struct nfs_fs_path *fsp;
4214 uint32_t loc, serv, addr, comp;
4215
4216 /* free up fs locations */
4217 if (!nfslsp->nl_numlocs || !nfslsp->nl_locations)
4218 return;
4219
4220 for (loc = 0; loc < nfslsp->nl_numlocs; loc++) {
4221 fsl = nfslsp->nl_locations[loc];
4222 if (!fsl)
4223 continue;
4224 if ((fsl->nl_servcount > 0) && fsl->nl_servers) {
4225 for (serv = 0; serv < fsl->nl_servcount; serv++) {
4226 fss = fsl->nl_servers[serv];
4227 if (!fss)
4228 continue;
4229 if ((fss->ns_addrcount > 0) && fss->ns_addresses) {
4230 for (addr = 0; addr < fss->ns_addrcount; addr++)
4231 FREE(fss->ns_addresses[addr], M_TEMP);
4232 FREE(fss->ns_addresses, M_TEMP);
4233 }
4234 FREE(fss->ns_name, M_TEMP);
4235 FREE(fss, M_TEMP);
4236 }
4237 FREE(fsl->nl_servers, M_TEMP);
4238 }
4239 fsp = &fsl->nl_path;
4240 if (fsp->np_compcount && fsp->np_components) {
4241 for (comp = 0; comp < fsp->np_compcount; comp++)
4242 if (fsp->np_components[comp])
4243 FREE(fsp->np_components[comp], M_TEMP);
4244 FREE(fsp->np_components, M_TEMP);
4245 }
4246 FREE(fsl, M_TEMP);
4247 }
4248 FREE(nfslsp->nl_locations, M_TEMP);
4249 nfslsp->nl_numlocs = 0;
4250 nfslsp->nl_locations = NULL;
4251 }
4252
4253 void
4254 nfs_mount_rele(struct nfsmount *nmp)
4255 {
4256 int wup = 0;
4257
4258 lck_mtx_lock(&nmp->nm_lock);
4259 if (nmp->nm_ref < 1)
4260 panic("nfs zombie mount underflow\n");
4261 nmp->nm_ref--;
4262 if (nmp->nm_ref == 0)
4263 wup = nmp->nm_state & NFSSTA_MOUNT_DRAIN;
4264 lck_mtx_unlock(&nmp->nm_lock);
4265 if (wup)
4266 wakeup(&nmp->nm_ref);
4267 }
4268
4269 void
4270 nfs_mount_drain_and_cleanup(struct nfsmount *nmp)
4271 {
4272 lck_mtx_lock(&nmp->nm_lock);
4273 nmp->nm_state |= NFSSTA_MOUNT_DRAIN;
4274 while (nmp->nm_ref > 0) {
4275 msleep(&nmp->nm_ref, &nmp->nm_lock, PZERO-1, "nfs_mount_drain", NULL);
4276 }
4277 assert(nmp->nm_ref == 0);
4278 lck_mtx_unlock(&nmp->nm_lock);
4279 nfs_mount_cleanup(nmp);
4280 }
4281
4282 /*
4283 * nfs_mount_zombie
4284 */
4285 void
4286 nfs_mount_zombie(struct nfsmount *nmp, int nm_state_flags)
4287 {
4288 struct nfsreq *req, *treq;
4289 struct nfs_reqqhead iodq;
4290 struct timespec ts = { 1, 0 };
4291 struct nfs_open_owner *noop, *nextnoop;
4292 nfsnode_t np;
4293 int docallback;
4294
4295 lck_mtx_lock(&nmp->nm_lock);
4296 nmp->nm_state |= nm_state_flags;
4297 nmp->nm_ref++;
4298 lck_mtx_unlock(&nmp->nm_lock);
4299
4300 /* stop callbacks */
4301 if ((nmp->nm_vers >= NFS_VER4) && !NMFLAG(nmp, NOCALLBACK) && nmp->nm_cbid)
4302 nfs4_mount_callback_shutdown(nmp);
4303
4304 /* Destroy any RPCSEC_GSS contexts */
4305 if (!TAILQ_EMPTY(&nmp->nm_gsscl))
4306 nfs_gss_clnt_ctx_unmount(nmp);
4307
4308 /* mark the socket for termination */
4309 lck_mtx_lock(&nmp->nm_lock);
4310 nmp->nm_sockflags |= NMSOCK_UNMOUNT;
4311
4312 /* Have the socket thread send the unmount RPC, if requested/appropriate. */
4313 if ((nmp->nm_vers < NFS_VER4) && (nmp->nm_state & NFSSTA_MOUNTED) &&
4314 !(nmp->nm_state & (NFSSTA_FORCE|NFSSTA_DEAD)) && NMFLAG(nmp, CALLUMNT))
4315 nfs_mount_sock_thread_wake(nmp);
4316
4317 /* wait for the socket thread to terminate */
4318 while (nmp->nm_sockthd && current_thread() != nmp->nm_sockthd) {
4319 wakeup(&nmp->nm_sockthd);
4320 msleep(&nmp->nm_sockthd, &nmp->nm_lock, PZERO-1, "nfswaitsockthd", &ts);
4321 }
4322 lck_mtx_unlock(&nmp->nm_lock);
4323
4324 /* tear down the socket */
4325 nfs_disconnect(nmp);
4326
4327 lck_mtx_lock(&nmp->nm_lock);
4328
4329 if ((nmp->nm_vers >= NFS_VER4) && !NMFLAG(nmp, NOCALLBACK) && nmp->nm_cbid) {
4330 /* clear out any pending delegation return requests */
4331 while ((np = TAILQ_FIRST(&nmp->nm_dreturnq))) {
4332 TAILQ_REMOVE(&nmp->nm_dreturnq, np, n_dreturn);
4333 np->n_dreturn.tqe_next = NFSNOLIST;
4334 }
4335 }
4336
4337 /* cancel any renew timer */
4338 if ((nmp->nm_vers >= NFS_VER4) && nmp->nm_renew_timer) {
4339 thread_call_cancel(nmp->nm_renew_timer);
4340 thread_call_free(nmp->nm_renew_timer);
4341 }
4342
4343 lck_mtx_unlock(&nmp->nm_lock);
4344
4345 if (nmp->nm_state & NFSSTA_MOUNTED)
4346 switch (nmp->nm_lockmode) {
4347 case NFS_LOCK_MODE_DISABLED:
4348 case NFS_LOCK_MODE_LOCAL:
4349 break;
4350 case NFS_LOCK_MODE_ENABLED:
4351 default:
4352 if (nmp->nm_vers <= NFS_VER3) {
4353 nfs_lockd_mount_unregister(nmp);
4354 nmp->nm_lockmode = NFS_LOCK_MODE_DISABLED;
4355 }
4356 break;
4357 }
4358
4359 if ((nmp->nm_vers >= NFS_VER4) && nmp->nm_longid) {
4360 /* remove/deallocate the client ID data */
4361 lck_mtx_lock(nfs_global_mutex);
4362 TAILQ_REMOVE(&nfsclientids, nmp->nm_longid, nci_link);
4363 if (nmp->nm_longid->nci_id)
4364 FREE(nmp->nm_longid->nci_id, M_TEMP);
4365 FREE(nmp->nm_longid, M_TEMP);
4366 lck_mtx_unlock(nfs_global_mutex);
4367 }
4368
4369 /*
4370 * Loop through outstanding request list and remove dangling
4371 * references to defunct nfsmount struct
4372 */
4373 TAILQ_INIT(&iodq);
4374 lck_mtx_lock(nfs_request_mutex);
4375 TAILQ_FOREACH(req, &nfs_reqq, r_chain) {
4376 if (req->r_nmp == nmp) {
4377 if (req->r_callback.rcb_func && !(req->r_flags & R_WAITSENT)) {
4378 /* async I/O RPC needs to be finished */
4379 lck_mtx_lock(nfsiod_mutex);
4380 if (req->r_achain.tqe_next == NFSREQNOLIST) {
4381 TAILQ_INSERT_TAIL(&iodq, req, r_achain);
4382 }
4383 lck_mtx_unlock(nfsiod_mutex);
4384 }
4385 wakeup(req);
4386 }
4387 }
4388 lck_mtx_unlock(nfs_request_mutex);
4389
4390 /* finish any async I/O RPCs queued up */
4391 lck_mtx_lock(nfsiod_mutex);
4392 if (nmp->nm_iodlink.tqe_next != NFSNOLIST)
4393 TAILQ_REMOVE(&nfsiodmounts, nmp, nm_iodlink);
4394 TAILQ_CONCAT(&iodq, &nmp->nm_iodq, r_achain);
4395 lck_mtx_unlock(nfsiod_mutex);
4396 TAILQ_FOREACH_SAFE(req, &iodq, r_achain, treq) {
4397 TAILQ_REMOVE(&iodq, req, r_achain);
4398 lck_mtx_lock(nfsiod_mutex);
4399 req->r_achain.tqe_next = NFSIODCOMPLETING;
4400 lck_mtx_unlock(nfsiod_mutex);
4401 lck_mtx_lock(&req->r_mtx);
4402 req->r_error = ENXIO;
4403 docallback = !(req->r_flags & R_WAITSENT);
4404 lck_mtx_unlock(&req->r_mtx);
4405 if (docallback)
4406 req->r_callback.rcb_func(req);
4407 }
4408
4409 /* clean up common state */
4410 lck_mtx_lock(&nmp->nm_lock);
4411 while ((np = LIST_FIRST(&nmp->nm_monlist))) {
4412 LIST_REMOVE(np, n_monlink);
4413 np->n_monlink.le_next = NFSNOLIST;
4414 }
4415 TAILQ_FOREACH_SAFE(noop, &nmp->nm_open_owners, noo_link, nextnoop) {
4416 TAILQ_REMOVE(&nmp->nm_open_owners, noop, noo_link);
4417 noop->noo_flags &= ~NFS_OPEN_OWNER_LINK;
4418 if (noop->noo_refcnt)
4419 continue;
4420 nfs_open_owner_destroy(noop);
4421 }
4422 lck_mtx_unlock(&nmp->nm_lock);
4423
4424 /* clean up NFSv4 state */
4425 if (nmp->nm_vers >= NFS_VER4) {
4426 lck_mtx_lock(&nmp->nm_lock);
4427 while ((np = TAILQ_FIRST(&nmp->nm_delegations))) {
4428 TAILQ_REMOVE(&nmp->nm_delegations, np, n_dlink);
4429 np->n_dlink.tqe_next = NFSNOLIST;
4430 }
4431 lck_mtx_unlock(&nmp->nm_lock);
4432 }
4433
4434 nfs_mount_rele(nmp);
4435 }
4436
4437 /*
4438 * cleanup/destroy an nfsmount
4439 */
4440 void
4441 nfs_mount_cleanup(struct nfsmount *nmp)
4442 {
4443 if (!nmp)
4444 return;
4445
4446 nfs_mount_zombie(nmp, 0);
4447
4448 NFS_VFS_DBG("Unmounting %s from %s\n",
4449 vfs_statfs(nmp->nm_mountp)->f_mntfromname,
4450 vfs_statfs(nmp->nm_mountp)->f_mntonname);
4451 NFS_VFS_DBG("nfs state = %x\n", nmp->nm_state);
4452 NFS_VFS_DBG("nfs socket flags = %x\n", nmp->nm_sockflags);
4453 NFS_VFS_DBG("nfs mount ref count is %d\n", nmp->nm_ref);
4454 NFS_VFS_DBG("mount ref count is %d\n", nmp->nm_mountp->mnt_count);
4455
4456 if (nmp->nm_mountp)
4457 vfs_setfsprivate(nmp->nm_mountp, NULL);
4458
4459 lck_mtx_lock(&nmp->nm_lock);
4460 if (nmp->nm_ref)
4461 panic("Some one has grabbed a ref %d\n", nmp->nm_ref);
4462
4463 if (nmp->nm_saddr)
4464 FREE(nmp->nm_saddr, M_SONAME);
4465 if ((nmp->nm_vers < NFS_VER4) && nmp->nm_rqsaddr)
4466 FREE(nmp->nm_rqsaddr, M_SONAME);
4467
4468 if (IS_VALID_CRED(nmp->nm_mcred))
4469 kauth_cred_unref(&nmp->nm_mcred);
4470
4471 nfs_fs_locations_cleanup(&nmp->nm_locations);
4472
4473 if (nmp->nm_realm)
4474 FREE(nmp->nm_realm, M_TEMP);
4475 if (nmp->nm_principal)
4476 FREE(nmp->nm_principal, M_TEMP);
4477 if (nmp->nm_sprinc)
4478 FREE(nmp->nm_sprinc, M_TEMP);
4479
4480 if (nmp->nm_args)
4481 xb_free(nmp->nm_args);
4482
4483 lck_mtx_unlock(&nmp->nm_lock);
4484
4485 lck_mtx_destroy(&nmp->nm_lock, nfs_mount_grp);
4486 if (nmp->nm_fh)
4487 FREE(nmp->nm_fh, M_TEMP);
4488 FREE_ZONE((caddr_t)nmp, sizeof (struct nfsmount), M_NFSMNT);
4489 }
4490
4491 /*
4492 * Return root of a filesystem
4493 */
4494 int
4495 nfs_vfs_root(mount_t mp, vnode_t *vpp, __unused vfs_context_t ctx)
4496 {
4497 vnode_t vp;
4498 struct nfsmount *nmp;
4499 int error;
4500 u_int32_t vpid;
4501
4502 nmp = VFSTONFS(mp);
4503 if (!nmp || !nmp->nm_dnp)
4504 return (ENXIO);
4505 vp = NFSTOV(nmp->nm_dnp);
4506 vpid = vnode_vid(vp);
4507 while ((error = vnode_getwithvid(vp, vpid))) {
4508 /* vnode_get() may return ENOENT if the dir changes. */
4509 /* If that happens, just try it again, else return the error. */
4510 if ((error != ENOENT) || (vnode_vid(vp) == vpid))
4511 return (error);
4512 vpid = vnode_vid(vp);
4513 }
4514 *vpp = vp;
4515 return (0);
4516 }
4517
4518 /*
4519 * Do operations associated with quotas
4520 */
4521 #if !QUOTA
4522 int
4523 nfs_vfs_quotactl(
4524 __unused mount_t mp,
4525 __unused int cmds,
4526 __unused uid_t uid,
4527 __unused caddr_t datap,
4528 __unused vfs_context_t context)
4529 {
4530 return (ENOTSUP);
4531 }
4532 #else
4533
4534 int
4535 nfs3_getquota(struct nfsmount *nmp, vfs_context_t ctx, uid_t id, int type, struct dqblk *dqb)
4536 {
4537 int error = 0, slen, timeo;
4538 int rqport = 0, rqproto, rqvers = (type == GRPQUOTA) ? RPCRQUOTA_EXT_VER : RPCRQUOTA_VER;
4539 thread_t thd = vfs_context_thread(ctx);
4540 kauth_cred_t cred = vfs_context_ucred(ctx);
4541 char *path;
4542 uint64_t xid = 0;
4543 struct nfsm_chain nmreq, nmrep;
4544 mbuf_t mreq;
4545 uint32_t val = 0, bsize = 0;
4546 struct sockaddr *rqsaddr;
4547 struct timeval now;
4548
4549 if (!nmp->nm_saddr)
4550 return (ENXIO);
4551
4552 if (NMFLAG(nmp, NOQUOTA))
4553 return (ENOTSUP);
4554
4555 if (!nmp->nm_rqsaddr)
4556 MALLOC(nmp->nm_rqsaddr, struct sockaddr *, sizeof(struct sockaddr_storage), M_SONAME, M_WAITOK|M_ZERO);
4557 if (!nmp->nm_rqsaddr)
4558 return (ENOMEM);
4559 rqsaddr = nmp->nm_rqsaddr;
4560 if (rqsaddr->sa_family == AF_INET6)
4561 rqport = ntohs(((struct sockaddr_in6*)rqsaddr)->sin6_port);
4562 else if (rqsaddr->sa_family == AF_INET)
4563 rqport = ntohs(((struct sockaddr_in*)rqsaddr)->sin_port);
4564
4565 timeo = NMFLAG(nmp, SOFT) ? 10 : 60;
4566 rqproto = IPPROTO_UDP; /* XXX should prefer TCP if mount is TCP */
4567
4568 /* check if we have a recently cached rquota port */
4569 microuptime(&now);
4570 if (!rqport || ((nmp->nm_rqsaddrstamp + 60) >= (uint32_t)now.tv_sec)) {
4571 /* send portmap request to get rquota port */
4572 bcopy(nmp->nm_saddr, rqsaddr, min(sizeof(struct sockaddr_storage), nmp->nm_saddr->sa_len));
4573 error = nfs_portmap_lookup(nmp, ctx, rqsaddr, NULL, RPCPROG_RQUOTA, rqvers, rqproto, timeo);
4574 if (error)
4575 return (error);
4576 if (rqsaddr->sa_family == AF_INET6)
4577 rqport = ntohs(((struct sockaddr_in6*)rqsaddr)->sin6_port);
4578 else if (rqsaddr->sa_family == AF_INET)
4579 rqport = ntohs(((struct sockaddr_in*)rqsaddr)->sin_port);
4580 else
4581 return (EIO);
4582 if (!rqport)
4583 return (ENOTSUP);
4584 microuptime(&now);
4585 nmp->nm_rqsaddrstamp = now.tv_sec;
4586 }
4587
4588 /* rquota request */
4589 nfsm_chain_null(&nmreq);
4590 nfsm_chain_null(&nmrep);
4591 path = &vfs_statfs(nmp->nm_mountp)->f_mntfromname[0];
4592 while (*path && (*path != '/'))
4593 path++;
4594 slen = strlen(path);
4595 nfsm_chain_build_alloc_init(error, &nmreq, 3 * NFSX_UNSIGNED + nfsm_rndup(slen));
4596 nfsm_chain_add_name(error, &nmreq, path, slen, nmp);
4597 if (type == GRPQUOTA)
4598 nfsm_chain_add_32(error, &nmreq, type);
4599 nfsm_chain_add_32(error, &nmreq, id);
4600 nfsm_chain_build_done(error, &nmreq);
4601 nfsmout_if(error);
4602 error = nfsm_rpchead2(nmp, (rqproto == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM,
4603 RPCPROG_RQUOTA, rqvers, RPCRQUOTA_GET,
4604 RPCAUTH_SYS, cred, NULL, nmreq.nmc_mhead, &xid, &mreq);
4605 nfsmout_if(error);
4606 nmreq.nmc_mhead = NULL;
4607 error = nfs_aux_request(nmp, thd, rqsaddr, NULL,
4608 (rqproto == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM,
4609 mreq, R_XID32(xid), 0, timeo, &nmrep);
4610 nfsmout_if(error);
4611
4612 /* parse rquota response */
4613 nfsm_chain_get_32(error, &nmrep, val);
4614 if (!error && (val != RQUOTA_STAT_OK)) {
4615 if (val == RQUOTA_STAT_NOQUOTA)
4616 error = ENOENT;
4617 else if (val == RQUOTA_STAT_EPERM)
4618 error = EPERM;
4619 else
4620 error = EIO;
4621 }
4622 nfsm_chain_get_32(error, &nmrep, bsize);
4623 nfsm_chain_adv(error, &nmrep, NFSX_UNSIGNED);
4624 nfsm_chain_get_32(error, &nmrep, val);
4625 nfsmout_if(error);
4626 dqb->dqb_bhardlimit = (uint64_t)val * bsize;
4627 nfsm_chain_get_32(error, &nmrep, val);
4628 nfsmout_if(error);
4629 dqb->dqb_bsoftlimit = (uint64_t)val * bsize;
4630 nfsm_chain_get_32(error, &nmrep, val);
4631 nfsmout_if(error);
4632 dqb->dqb_curbytes = (uint64_t)val * bsize;
4633 nfsm_chain_get_32(error, &nmrep, dqb->dqb_ihardlimit);
4634 nfsm_chain_get_32(error, &nmrep, dqb->dqb_isoftlimit);
4635 nfsm_chain_get_32(error, &nmrep, dqb->dqb_curinodes);
4636 nfsm_chain_get_32(error, &nmrep, dqb->dqb_btime);
4637 nfsm_chain_get_32(error, &nmrep, dqb->dqb_itime);
4638 nfsmout_if(error);
4639 dqb->dqb_id = id;
4640 nfsmout:
4641 nfsm_chain_cleanup(&nmreq);
4642 nfsm_chain_cleanup(&nmrep);
4643 return (error);
4644 }
4645
4646 int
4647 nfs4_getquota(struct nfsmount *nmp, vfs_context_t ctx, uid_t id, int type, struct dqblk *dqb)
4648 {
4649 nfsnode_t np;
4650 int error = 0, status, nfsvers, numops;
4651 u_int64_t xid;
4652 struct nfsm_chain nmreq, nmrep;
4653 uint32_t bitmap[NFS_ATTR_BITMAP_LEN];
4654 thread_t thd = vfs_context_thread(ctx);
4655 kauth_cred_t cred = vfs_context_ucred(ctx);
4656 struct nfsreq_secinfo_args si;
4657
4658 if (type != USRQUOTA) /* NFSv4 only supports user quotas */
4659 return (ENOTSUP);
4660
4661 /* first check that the server supports any of the quota attributes */
4662 if (!NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_supp_attr, NFS_FATTR_QUOTA_AVAIL_HARD) &&
4663 !NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_supp_attr, NFS_FATTR_QUOTA_AVAIL_SOFT) &&
4664 !NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_supp_attr, NFS_FATTR_QUOTA_USED))
4665 return (ENOTSUP);
4666
4667 /*
4668 * The credential passed to the server needs to have
4669 * an effective uid that matches the given uid.
4670 */
4671 if (id != kauth_cred_getuid(cred)) {
4672 struct posix_cred temp_pcred;
4673 posix_cred_t pcred = posix_cred_get(cred);
4674 bzero(&temp_pcred, sizeof(temp_pcred));
4675 temp_pcred.cr_uid = id;
4676 temp_pcred.cr_ngroups = pcred->cr_ngroups;
4677 bcopy(pcred->cr_groups, temp_pcred.cr_groups, sizeof(temp_pcred.cr_groups));
4678 cred = posix_cred_create(&temp_pcred);
4679 if (!IS_VALID_CRED(cred))
4680 return (ENOMEM);
4681 } else {
4682 kauth_cred_ref(cred);
4683 }
4684
4685 nfsvers = nmp->nm_vers;
4686 np = nmp->nm_dnp;
4687 if (!np)
4688 error = ENXIO;
4689 if (error || ((error = vnode_get(NFSTOV(np))))) {
4690 kauth_cred_unref(&cred);
4691 return(error);
4692 }
4693
4694 NFSREQ_SECINFO_SET(&si, np, NULL, 0, NULL, 0);
4695 nfsm_chain_null(&nmreq);
4696 nfsm_chain_null(&nmrep);
4697
4698 // PUTFH + GETATTR
4699 numops = 2;
4700 nfsm_chain_build_alloc_init(error, &nmreq, 15 * NFSX_UNSIGNED);
4701 nfsm_chain_add_compound_header(error, &nmreq, "quota", numops);
4702 numops--;
4703 nfsm_chain_add_32(error, &nmreq, NFS_OP_PUTFH);
4704 nfsm_chain_add_fh(error, &nmreq, nfsvers, np->n_fhp, np->n_fhsize);
4705 numops--;
4706 nfsm_chain_add_32(error, &nmreq, NFS_OP_GETATTR);
4707 NFS_CLEAR_ATTRIBUTES(bitmap);
4708 NFS_BITMAP_SET(bitmap, NFS_FATTR_QUOTA_AVAIL_HARD);
4709 NFS_BITMAP_SET(bitmap, NFS_FATTR_QUOTA_AVAIL_SOFT);
4710 NFS_BITMAP_SET(bitmap, NFS_FATTR_QUOTA_USED);
4711 nfsm_chain_add_bitmap_supported(error, &nmreq, bitmap, nmp, NULL);
4712 nfsm_chain_build_done(error, &nmreq);
4713 nfsm_assert(error, (numops == 0), EPROTO);
4714 nfsmout_if(error);
4715 error = nfs_request2(np, NULL, &nmreq, NFSPROC4_COMPOUND, thd, cred, &si, 0, &nmrep, &xid, &status);
4716 nfsm_chain_skip_tag(error, &nmrep);
4717 nfsm_chain_get_32(error, &nmrep, numops);
4718 nfsm_chain_op_check(error, &nmrep, NFS_OP_PUTFH);
4719 nfsm_chain_op_check(error, &nmrep, NFS_OP_GETATTR);
4720 nfsm_assert(error, NFSTONMP(np), ENXIO);
4721 nfsmout_if(error);
4722 error = nfs4_parsefattr(&nmrep, NULL, NULL, NULL, dqb, NULL);
4723 nfsmout_if(error);
4724 nfsm_assert(error, NFSTONMP(np), ENXIO);
4725 nfsmout:
4726 nfsm_chain_cleanup(&nmreq);
4727 nfsm_chain_cleanup(&nmrep);
4728 vnode_put(NFSTOV(np));
4729 kauth_cred_unref(&cred);
4730 return (error);
4731 }
4732
4733 int
4734 nfs_vfs_quotactl(mount_t mp, int cmds, uid_t uid, caddr_t datap, vfs_context_t ctx)
4735 {
4736 struct nfsmount *nmp;
4737 int cmd, type, error, nfsvers;
4738 uid_t euid = kauth_cred_getuid(vfs_context_ucred(ctx));
4739 struct dqblk *dqb = (struct dqblk*)datap;
4740
4741 nmp = VFSTONFS(mp);
4742 if (nfs_mount_gone(nmp))
4743 return (ENXIO);
4744 nfsvers = nmp->nm_vers;
4745
4746 if (uid == ~0U)
4747 uid = euid;
4748
4749 /* we can only support Q_GETQUOTA */
4750 cmd = cmds >> SUBCMDSHIFT;
4751 switch (cmd) {
4752 case Q_GETQUOTA:
4753 break;
4754 case Q_QUOTAON:
4755 case Q_QUOTAOFF:
4756 case Q_SETQUOTA:
4757 case Q_SETUSE:
4758 case Q_SYNC:
4759 case Q_QUOTASTAT:
4760 return (ENOTSUP);
4761 default:
4762 return (EINVAL);
4763 }
4764
4765 type = cmds & SUBCMDMASK;
4766 if ((u_int)type >= MAXQUOTAS)
4767 return (EINVAL);
4768 if ((uid != euid) && ((error = vfs_context_suser(ctx))))
4769 return (error);
4770
4771 if (vfs_busy(mp, LK_NOWAIT))
4772 return (0);
4773 bzero(dqb, sizeof(*dqb));
4774 error = nmp->nm_funcs->nf_getquota(nmp, ctx, uid, type, dqb);
4775 vfs_unbusy(mp);
4776 return (error);
4777 }
4778 #endif
4779
4780 /*
4781 * Flush out the buffer cache
4782 */
4783 int nfs_sync_callout(vnode_t, void *);
4784
4785 struct nfs_sync_cargs {
4786 vfs_context_t ctx;
4787 int waitfor;
4788 int error;
4789 };
4790
4791 int
4792 nfs_sync_callout(vnode_t vp, void *arg)
4793 {
4794 struct nfs_sync_cargs *cargs = (struct nfs_sync_cargs*)arg;
4795 nfsnode_t np = VTONFS(vp);
4796 int error;
4797
4798 if (np->n_flag & NREVOKE) {
4799 vn_revoke(vp, REVOKEALL, cargs->ctx);
4800 return (VNODE_RETURNED);
4801 }
4802
4803 if (LIST_EMPTY(&np->n_dirtyblkhd))
4804 return (VNODE_RETURNED);
4805 if (np->n_wrbusy > 0)
4806 return (VNODE_RETURNED);
4807 if (np->n_bflag & (NBFLUSHINPROG|NBINVALINPROG))
4808 return (VNODE_RETURNED);
4809
4810 error = nfs_flush(np, cargs->waitfor, vfs_context_thread(cargs->ctx), 0);
4811 if (error)
4812 cargs->error = error;
4813
4814 return (VNODE_RETURNED);
4815 }
4816
4817 int
4818 nfs_vfs_sync(mount_t mp, int waitfor, vfs_context_t ctx)
4819 {
4820 struct nfs_sync_cargs cargs;
4821
4822 cargs.waitfor = waitfor;
4823 cargs.ctx = ctx;
4824 cargs.error = 0;
4825
4826 vnode_iterate(mp, 0, nfs_sync_callout, &cargs);
4827
4828 return (cargs.error);
4829 }
4830
4831 /*
4832 * NFS flat namespace lookup.
4833 * Currently unsupported.
4834 */
4835 /*ARGSUSED*/
4836 int
4837 nfs_vfs_vget(
4838 __unused mount_t mp,
4839 __unused ino64_t ino,
4840 __unused vnode_t *vpp,
4841 __unused vfs_context_t ctx)
4842 {
4843
4844 return (ENOTSUP);
4845 }
4846
4847 /*
4848 * At this point, this should never happen
4849 */
4850 /*ARGSUSED*/
4851 int
4852 nfs_vfs_fhtovp(
4853 __unused mount_t mp,
4854 __unused int fhlen,
4855 __unused unsigned char *fhp,
4856 __unused vnode_t *vpp,
4857 __unused vfs_context_t ctx)
4858 {
4859
4860 return (ENOTSUP);
4861 }
4862
4863 /*
4864 * Vnode pointer to File handle, should never happen either
4865 */
4866 /*ARGSUSED*/
4867 int
4868 nfs_vfs_vptofh(
4869 __unused vnode_t vp,
4870 __unused int *fhlenp,
4871 __unused unsigned char *fhp,
4872 __unused vfs_context_t ctx)
4873 {
4874
4875 return (ENOTSUP);
4876 }
4877
4878 /*
4879 * Vfs start routine, a no-op.
4880 */
4881 /*ARGSUSED*/
4882 int
4883 nfs_vfs_start(
4884 __unused mount_t mp,
4885 __unused int flags,
4886 __unused vfs_context_t ctx)
4887 {
4888
4889 return (0);
4890 }
4891
4892 /*
4893 * Build the mount info buffer for NFS_MOUNTINFO.
4894 */
4895 int
4896 nfs_mountinfo_assemble(struct nfsmount *nmp, struct xdrbuf *xb)
4897 {
4898 struct xdrbuf xbinfo, xborig;
4899 char sotype[6];
4900 uint32_t origargsvers, origargslength;
4901 uint32_t infolength_offset, curargsopaquelength_offset, curargslength_offset, attrslength_offset, curargs_end_offset, end_offset;
4902 uint32_t miattrs[NFS_MIATTR_BITMAP_LEN];
4903 uint32_t miflags_mask[NFS_MIFLAG_BITMAP_LEN];
4904 uint32_t miflags[NFS_MIFLAG_BITMAP_LEN];
4905 uint32_t mattrs[NFS_MATTR_BITMAP_LEN];
4906 uint32_t mflags_mask[NFS_MFLAG_BITMAP_LEN];
4907 uint32_t mflags[NFS_MFLAG_BITMAP_LEN];
4908 uint32_t loc, serv, addr, comp;
4909 int i, timeo, error = 0;
4910
4911 /* set up mount info attr and flag bitmaps */
4912 NFS_BITMAP_ZERO(miattrs, NFS_MIATTR_BITMAP_LEN);
4913 NFS_BITMAP_SET(miattrs, NFS_MIATTR_FLAGS);
4914 NFS_BITMAP_SET(miattrs, NFS_MIATTR_ORIG_ARGS);
4915 NFS_BITMAP_SET(miattrs, NFS_MIATTR_CUR_ARGS);
4916 NFS_BITMAP_SET(miattrs, NFS_MIATTR_CUR_LOC_INDEX);
4917 NFS_BITMAP_ZERO(miflags_mask, NFS_MIFLAG_BITMAP_LEN);
4918 NFS_BITMAP_ZERO(miflags, NFS_MIFLAG_BITMAP_LEN);
4919 NFS_BITMAP_SET(miflags_mask, NFS_MIFLAG_DEAD);
4920 NFS_BITMAP_SET(miflags_mask, NFS_MIFLAG_NOTRESP);
4921 NFS_BITMAP_SET(miflags_mask, NFS_MIFLAG_RECOVERY);
4922 if (nmp->nm_state & NFSSTA_DEAD)
4923 NFS_BITMAP_SET(miflags, NFS_MIFLAG_DEAD);
4924 if ((nmp->nm_state & (NFSSTA_TIMEO|NFSSTA_JUKEBOXTIMEO)) ||
4925 ((nmp->nm_state & NFSSTA_LOCKTIMEO) && (nmp->nm_lockmode == NFS_LOCK_MODE_ENABLED)))
4926 NFS_BITMAP_SET(miflags, NFS_MIFLAG_NOTRESP);
4927 if (nmp->nm_state & NFSSTA_RECOVER)
4928 NFS_BITMAP_SET(miflags, NFS_MIFLAG_RECOVERY);
4929
4930 /* get original mount args length */
4931 xb_init_buffer(&xborig, nmp->nm_args, 2*XDRWORD);
4932 xb_get_32(error, &xborig, origargsvers); /* version */
4933 xb_get_32(error, &xborig, origargslength); /* args length */
4934 nfsmerr_if(error);
4935
4936 /* set up current mount attributes bitmap */
4937 NFS_BITMAP_ZERO(mattrs, NFS_MATTR_BITMAP_LEN);
4938 NFS_BITMAP_SET(mattrs, NFS_MATTR_FLAGS);
4939 NFS_BITMAP_SET(mattrs, NFS_MATTR_NFS_VERSION);
4940 if (nmp->nm_vers >= NFS_VER4)
4941 NFS_BITMAP_SET(mattrs, NFS_MATTR_NFS_MINOR_VERSION);
4942 NFS_BITMAP_SET(mattrs, NFS_MATTR_READ_SIZE);
4943 NFS_BITMAP_SET(mattrs, NFS_MATTR_WRITE_SIZE);
4944 NFS_BITMAP_SET(mattrs, NFS_MATTR_READDIR_SIZE);
4945 NFS_BITMAP_SET(mattrs, NFS_MATTR_READAHEAD);
4946 NFS_BITMAP_SET(mattrs, NFS_MATTR_ATTRCACHE_REG_MIN);
4947 NFS_BITMAP_SET(mattrs, NFS_MATTR_ATTRCACHE_REG_MAX);
4948 NFS_BITMAP_SET(mattrs, NFS_MATTR_ATTRCACHE_DIR_MIN);
4949 NFS_BITMAP_SET(mattrs, NFS_MATTR_ATTRCACHE_DIR_MAX);
4950 NFS_BITMAP_SET(mattrs, NFS_MATTR_LOCK_MODE);
4951 NFS_BITMAP_SET(mattrs, NFS_MATTR_SECURITY);
4952 NFS_BITMAP_SET(mattrs, NFS_MATTR_MAX_GROUP_LIST);
4953 NFS_BITMAP_SET(mattrs, NFS_MATTR_SOCKET_TYPE);
4954 NFS_BITMAP_SET(mattrs, NFS_MATTR_NFS_PORT);
4955 if ((nmp->nm_vers < NFS_VER4) && nmp->nm_mountport)
4956 NFS_BITMAP_SET(mattrs, NFS_MATTR_MOUNT_PORT);
4957 NFS_BITMAP_SET(mattrs, NFS_MATTR_REQUEST_TIMEOUT);
4958 if (NMFLAG(nmp, SOFT))
4959 NFS_BITMAP_SET(mattrs, NFS_MATTR_SOFT_RETRY_COUNT);
4960 if (nmp->nm_deadtimeout)
4961 NFS_BITMAP_SET(mattrs, NFS_MATTR_DEAD_TIMEOUT);
4962 if (nmp->nm_fh)
4963 NFS_BITMAP_SET(mattrs, NFS_MATTR_FH);
4964 NFS_BITMAP_SET(mattrs, NFS_MATTR_FS_LOCATIONS);
4965 NFS_BITMAP_SET(mattrs, NFS_MATTR_MNTFLAGS);
4966 if (origargsvers < NFS_ARGSVERSION_XDR)
4967 NFS_BITMAP_SET(mattrs, NFS_MATTR_MNTFROM);
4968 if (nmp->nm_realm)
4969 NFS_BITMAP_SET(mattrs, NFS_MATTR_REALM);
4970 if (nmp->nm_principal)
4971 NFS_BITMAP_SET(mattrs, NFS_MATTR_PRINCIPAL);
4972 if (nmp->nm_sprinc)
4973 NFS_BITMAP_SET(mattrs, NFS_MATTR_SVCPRINCIPAL);
4974
4975 /* set up current mount flags bitmap */
4976 /* first set the flags that we will be setting - either on OR off */
4977 NFS_BITMAP_ZERO(mflags_mask, NFS_MFLAG_BITMAP_LEN);
4978 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_SOFT);
4979 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_INTR);
4980 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_RESVPORT);
4981 if (nmp->nm_sotype == SOCK_DGRAM)
4982 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_NOCONNECT);
4983 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_DUMBTIMER);
4984 if (nmp->nm_vers < NFS_VER4)
4985 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_CALLUMNT);
4986 if (nmp->nm_vers >= NFS_VER3)
4987 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_RDIRPLUS);
4988 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_NONEGNAMECACHE);
4989 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_MUTEJUKEBOX);
4990 if (nmp->nm_vers >= NFS_VER4) {
4991 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_EPHEMERAL);
4992 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_NOCALLBACK);
4993 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_NONAMEDATTR);
4994 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_NOACL);
4995 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_ACLONLY);
4996 }
4997 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_NFC);
4998 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_NOQUOTA);
4999 if (nmp->nm_vers < NFS_VER4)
5000 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_MNTUDP);
5001 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_MNTQUICK);
5002 /* now set the flags that should be set */
5003 NFS_BITMAP_ZERO(mflags, NFS_MFLAG_BITMAP_LEN);
5004 if (NMFLAG(nmp, SOFT))
5005 NFS_BITMAP_SET(mflags, NFS_MFLAG_SOFT);
5006 if (NMFLAG(nmp, INTR))
5007 NFS_BITMAP_SET(mflags, NFS_MFLAG_INTR);
5008 if (NMFLAG(nmp, RESVPORT))
5009 NFS_BITMAP_SET(mflags, NFS_MFLAG_RESVPORT);
5010 if ((nmp->nm_sotype == SOCK_DGRAM) && NMFLAG(nmp, NOCONNECT))
5011 NFS_BITMAP_SET(mflags, NFS_MFLAG_NOCONNECT);
5012 if (NMFLAG(nmp, DUMBTIMER))
5013 NFS_BITMAP_SET(mflags, NFS_MFLAG_DUMBTIMER);
5014 if ((nmp->nm_vers < NFS_VER4) && NMFLAG(nmp, CALLUMNT))
5015 NFS_BITMAP_SET(mflags, NFS_MFLAG_CALLUMNT);
5016 if ((nmp->nm_vers >= NFS_VER3) && NMFLAG(nmp, RDIRPLUS))
5017 NFS_BITMAP_SET(mflags, NFS_MFLAG_RDIRPLUS);
5018 if (NMFLAG(nmp, NONEGNAMECACHE))
5019 NFS_BITMAP_SET(mflags, NFS_MFLAG_NONEGNAMECACHE);
5020 if (NMFLAG(nmp, MUTEJUKEBOX))
5021 NFS_BITMAP_SET(mflags, NFS_MFLAG_MUTEJUKEBOX);
5022 if (nmp->nm_vers >= NFS_VER4) {
5023 if (NMFLAG(nmp, EPHEMERAL))
5024 NFS_BITMAP_SET(mflags, NFS_MFLAG_EPHEMERAL);
5025 if (NMFLAG(nmp, NOCALLBACK))
5026 NFS_BITMAP_SET(mflags, NFS_MFLAG_NOCALLBACK);
5027 if (NMFLAG(nmp, NONAMEDATTR))
5028 NFS_BITMAP_SET(mflags, NFS_MFLAG_NONAMEDATTR);
5029 if (NMFLAG(nmp, NOACL))
5030 NFS_BITMAP_SET(mflags, NFS_MFLAG_NOACL);
5031 if (NMFLAG(nmp, ACLONLY))
5032 NFS_BITMAP_SET(mflags, NFS_MFLAG_ACLONLY);
5033 }
5034 if (NMFLAG(nmp, NFC))
5035 NFS_BITMAP_SET(mflags, NFS_MFLAG_NFC);
5036 if (NMFLAG(nmp, NOQUOTA) || ((nmp->nm_vers >= NFS_VER4) &&
5037 !NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_supp_attr, NFS_FATTR_QUOTA_AVAIL_HARD) &&
5038 !NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_supp_attr, NFS_FATTR_QUOTA_AVAIL_SOFT) &&
5039 !NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_supp_attr, NFS_FATTR_QUOTA_USED)))
5040 NFS_BITMAP_SET(mflags, NFS_MFLAG_NOQUOTA);
5041 if ((nmp->nm_vers < NFS_VER4) && NMFLAG(nmp, MNTUDP))
5042 NFS_BITMAP_SET(mflags, NFS_MFLAG_MNTUDP);
5043 if (NMFLAG(nmp, MNTQUICK))
5044 NFS_BITMAP_SET(mflags, NFS_MFLAG_MNTQUICK);
5045
5046 /* assemble info buffer: */
5047 xb_init_buffer(&xbinfo, NULL, 0);
5048 xb_add_32(error, &xbinfo, NFS_MOUNT_INFO_VERSION);
5049 infolength_offset = xb_offset(&xbinfo);
5050 xb_add_32(error, &xbinfo, 0);
5051 xb_add_bitmap(error, &xbinfo, miattrs, NFS_MIATTR_BITMAP_LEN);
5052 xb_add_bitmap(error, &xbinfo, miflags, NFS_MIFLAG_BITMAP_LEN);
5053 xb_add_32(error, &xbinfo, origargslength);
5054 if (!error)
5055 error = xb_add_bytes(&xbinfo, nmp->nm_args, origargslength, 0);
5056
5057 /* the opaque byte count for the current mount args values: */
5058 curargsopaquelength_offset = xb_offset(&xbinfo);
5059 xb_add_32(error, &xbinfo, 0);
5060
5061 /* Encode current mount args values */
5062 xb_add_32(error, &xbinfo, NFS_ARGSVERSION_XDR);
5063 curargslength_offset = xb_offset(&xbinfo);
5064 xb_add_32(error, &xbinfo, 0);
5065 xb_add_32(error, &xbinfo, NFS_XDRARGS_VERSION_0);
5066 xb_add_bitmap(error, &xbinfo, mattrs, NFS_MATTR_BITMAP_LEN);
5067 attrslength_offset = xb_offset(&xbinfo);
5068 xb_add_32(error, &xbinfo, 0);
5069 xb_add_bitmap(error, &xbinfo, mflags_mask, NFS_MFLAG_BITMAP_LEN);
5070 xb_add_bitmap(error, &xbinfo, mflags, NFS_MFLAG_BITMAP_LEN);
5071 xb_add_32(error, &xbinfo, nmp->nm_vers); /* NFS_VERSION */
5072 if (nmp->nm_vers >= NFS_VER4)
5073 xb_add_32(error, &xbinfo, 0); /* NFS_MINOR_VERSION */
5074 xb_add_32(error, &xbinfo, nmp->nm_rsize); /* READ_SIZE */
5075 xb_add_32(error, &xbinfo, nmp->nm_wsize); /* WRITE_SIZE */
5076 xb_add_32(error, &xbinfo, nmp->nm_readdirsize); /* READDIR_SIZE */
5077 xb_add_32(error, &xbinfo, nmp->nm_readahead); /* READAHEAD */
5078 xb_add_32(error, &xbinfo, nmp->nm_acregmin); /* ATTRCACHE_REG_MIN */
5079 xb_add_32(error, &xbinfo, 0); /* ATTRCACHE_REG_MIN */
5080 xb_add_32(error, &xbinfo, nmp->nm_acregmax); /* ATTRCACHE_REG_MAX */
5081 xb_add_32(error, &xbinfo, 0); /* ATTRCACHE_REG_MAX */
5082 xb_add_32(error, &xbinfo, nmp->nm_acdirmin); /* ATTRCACHE_DIR_MIN */
5083 xb_add_32(error, &xbinfo, 0); /* ATTRCACHE_DIR_MIN */
5084 xb_add_32(error, &xbinfo, nmp->nm_acdirmax); /* ATTRCACHE_DIR_MAX */
5085 xb_add_32(error, &xbinfo, 0); /* ATTRCACHE_DIR_MAX */
5086 xb_add_32(error, &xbinfo, nmp->nm_lockmode); /* LOCK_MODE */
5087 if (nmp->nm_sec.count) {
5088 xb_add_32(error, &xbinfo, nmp->nm_sec.count); /* SECURITY */
5089 nfsmerr_if(error);
5090 for (i=0; i < nmp->nm_sec.count; i++)
5091 xb_add_32(error, &xbinfo, nmp->nm_sec.flavors[i]);
5092 } else if (nmp->nm_servsec.count) {
5093 xb_add_32(error, &xbinfo, nmp->nm_servsec.count); /* SECURITY */
5094 nfsmerr_if(error);
5095 for (i=0; i < nmp->nm_servsec.count; i++)
5096 xb_add_32(error, &xbinfo, nmp->nm_servsec.flavors[i]);
5097 } else {
5098 xb_add_32(error, &xbinfo, 1); /* SECURITY */
5099 xb_add_32(error, &xbinfo, nmp->nm_auth);
5100 }
5101 xb_add_32(error, &xbinfo, nmp->nm_numgrps); /* MAX_GROUP_LIST */
5102 nfsmerr_if(error);
5103 snprintf(sotype, sizeof(sotype), "%s%s", (nmp->nm_sotype == SOCK_DGRAM) ? "udp" : "tcp",
5104 nmp->nm_sofamily ? (nmp->nm_sofamily == AF_INET) ? "4" : "6" : "");
5105 xb_add_string(error, &xbinfo, sotype, strlen(sotype)); /* SOCKET_TYPE */
5106 xb_add_32(error, &xbinfo, ntohs(((struct sockaddr_in*)nmp->nm_saddr)->sin_port)); /* NFS_PORT */
5107 if ((nmp->nm_vers < NFS_VER4) && nmp->nm_mountport)
5108 xb_add_32(error, &xbinfo, nmp->nm_mountport); /* MOUNT_PORT */
5109 timeo = (nmp->nm_timeo * 10) / NFS_HZ;
5110 xb_add_32(error, &xbinfo, timeo/10); /* REQUEST_TIMEOUT */
5111 xb_add_32(error, &xbinfo, (timeo%10)*100000000); /* REQUEST_TIMEOUT */
5112 if (NMFLAG(nmp, SOFT))
5113 xb_add_32(error, &xbinfo, nmp->nm_retry); /* SOFT_RETRY_COUNT */
5114 if (nmp->nm_deadtimeout) {
5115 xb_add_32(error, &xbinfo, nmp->nm_deadtimeout); /* DEAD_TIMEOUT */
5116 xb_add_32(error, &xbinfo, 0); /* DEAD_TIMEOUT */
5117 }
5118 if (nmp->nm_fh)
5119 xb_add_fh(error, &xbinfo, &nmp->nm_fh->fh_data[0], nmp->nm_fh->fh_len); /* FH */
5120 xb_add_32(error, &xbinfo, nmp->nm_locations.nl_numlocs); /* FS_LOCATIONS */
5121 for (loc = 0; !error && (loc < nmp->nm_locations.nl_numlocs); loc++) {
5122 xb_add_32(error, &xbinfo, nmp->nm_locations.nl_locations[loc]->nl_servcount);
5123 for (serv = 0; !error && (serv < nmp->nm_locations.nl_locations[loc]->nl_servcount); serv++) {
5124 xb_add_string(error, &xbinfo, nmp->nm_locations.nl_locations[loc]->nl_servers[serv]->ns_name,
5125 strlen(nmp->nm_locations.nl_locations[loc]->nl_servers[serv]->ns_name));
5126 xb_add_32(error, &xbinfo, nmp->nm_locations.nl_locations[loc]->nl_servers[serv]->ns_addrcount);
5127 for (addr = 0; !error && (addr < nmp->nm_locations.nl_locations[loc]->nl_servers[serv]->ns_addrcount); addr++)
5128 xb_add_string(error, &xbinfo, nmp->nm_locations.nl_locations[loc]->nl_servers[serv]->ns_addresses[addr],
5129 strlen(nmp->nm_locations.nl_locations[loc]->nl_servers[serv]->ns_addresses[addr]));
5130 xb_add_32(error, &xbinfo, 0); /* empty server info */
5131 }
5132 xb_add_32(error, &xbinfo, nmp->nm_locations.nl_locations[loc]->nl_path.np_compcount);
5133 for (comp = 0; !error && (comp < nmp->nm_locations.nl_locations[loc]->nl_path.np_compcount); comp++)
5134 xb_add_string(error, &xbinfo, nmp->nm_locations.nl_locations[loc]->nl_path.np_components[comp],
5135 strlen(nmp->nm_locations.nl_locations[loc]->nl_path.np_components[comp]));
5136 xb_add_32(error, &xbinfo, 0); /* empty fs location info */
5137 }
5138 xb_add_32(error, &xbinfo, vfs_flags(nmp->nm_mountp)); /* MNTFLAGS */
5139 if (origargsvers < NFS_ARGSVERSION_XDR)
5140 xb_add_string(error, &xbinfo, vfs_statfs(nmp->nm_mountp)->f_mntfromname,
5141 strlen(vfs_statfs(nmp->nm_mountp)->f_mntfromname)); /* MNTFROM */
5142 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_REALM))
5143 xb_add_string(error, &xbinfo, nmp->nm_realm, strlen(nmp->nm_realm));
5144 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_PRINCIPAL))
5145 xb_add_string(error, &xbinfo, nmp->nm_principal, strlen(nmp->nm_principal));
5146 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_SVCPRINCIPAL))
5147 xb_add_string(error, &xbinfo, nmp->nm_sprinc, strlen(nmp->nm_sprinc));
5148
5149 curargs_end_offset = xb_offset(&xbinfo);
5150
5151 /* NFS_MIATTR_CUR_LOC_INDEX */
5152 xb_add_32(error, &xbinfo, nmp->nm_locations.nl_current.nli_flags);
5153 xb_add_32(error, &xbinfo, nmp->nm_locations.nl_current.nli_loc);
5154 xb_add_32(error, &xbinfo, nmp->nm_locations.nl_current.nli_serv);
5155 xb_add_32(error, &xbinfo, nmp->nm_locations.nl_current.nli_addr);
5156
5157 xb_build_done(error, &xbinfo);
5158
5159 /* update opaque counts */
5160 end_offset = xb_offset(&xbinfo);
5161 if (!error) {
5162 error = xb_seek(&xbinfo, attrslength_offset);
5163 xb_add_32(error, &xbinfo, curargs_end_offset - attrslength_offset - XDRWORD/*don't include length field*/);
5164 }
5165 if (!error) {
5166 error = xb_seek(&xbinfo, curargslength_offset);
5167 xb_add_32(error, &xbinfo, curargs_end_offset - curargslength_offset + XDRWORD/*version*/);
5168 }
5169 if (!error) {
5170 error = xb_seek(&xbinfo, curargsopaquelength_offset);
5171 xb_add_32(error, &xbinfo, curargs_end_offset - curargslength_offset + XDRWORD/*version*/);
5172 }
5173 if (!error) {
5174 error = xb_seek(&xbinfo, infolength_offset);
5175 xb_add_32(error, &xbinfo, end_offset - infolength_offset + XDRWORD/*version*/);
5176 }
5177 nfsmerr_if(error);
5178
5179 /* copy result xdrbuf to caller */
5180 *xb = xbinfo;
5181
5182 /* and mark the local copy as not needing cleanup */
5183 xbinfo.xb_flags &= ~XB_CLEANUP;
5184 nfsmerr:
5185 xb_cleanup(&xbinfo);
5186 return (error);
5187 }
5188
5189 /*
5190 * Do that sysctl thang...
5191 */
5192 int
5193 nfs_vfs_sysctl(int *name, u_int namelen, user_addr_t oldp, size_t *oldlenp,
5194 user_addr_t newp, size_t newlen, vfs_context_t ctx)
5195 {
5196 int error = 0, val;
5197 int softnobrowse;
5198 struct sysctl_req *req = NULL;
5199 union union_vfsidctl vc;
5200 mount_t mp;
5201 struct nfsmount *nmp = NULL;
5202 struct vfsquery vq;
5203 struct nfsreq *rq;
5204 boolean_t is_64_bit;
5205 fsid_t fsid;
5206 struct xdrbuf xb;
5207 struct netfs_status *nsp = NULL;
5208 int timeoutmask;
5209 uint pos, totlen, count, numThreads;
5210 #if NFSSERVER
5211 struct nfs_exportfs *nxfs;
5212 struct nfs_export *nx;
5213 struct nfs_active_user_list *ulist;
5214 struct nfs_export_stat_desc stat_desc;
5215 struct nfs_export_stat_rec statrec;
5216 struct nfs_user_stat_node *unode, *unode_next;
5217 struct nfs_user_stat_desc ustat_desc;
5218 struct nfs_user_stat_user_rec ustat_rec;
5219 struct nfs_user_stat_path_rec upath_rec;
5220 uint bytes_avail, bytes_total, recs_copied;
5221 uint numExports, numRecs;
5222 #endif /* NFSSERVER */
5223
5224 /*
5225 * All names at this level are terminal.
5226 */
5227 if (namelen > 1)
5228 return (ENOTDIR); /* overloaded */
5229
5230 is_64_bit = vfs_context_is64bit(ctx);
5231
5232 /* common code for "new style" VFS_CTL sysctl, get the mount. */
5233 switch (name[0]) {
5234 case VFS_CTL_TIMEO:
5235 case VFS_CTL_NOLOCKS:
5236 case VFS_CTL_NSTATUS:
5237 case VFS_CTL_QUERY:
5238 req = CAST_DOWN(struct sysctl_req *, oldp);
5239 if (req == NULL) {
5240 return EFAULT;
5241 }
5242 error = SYSCTL_IN(req, &vc, is_64_bit? sizeof(vc.vc64):sizeof(vc.vc32));
5243 if (error)
5244 return (error);
5245 mp = vfs_getvfs(&vc.vc32.vc_fsid); /* works for 32 and 64 */
5246 if (mp == NULL)
5247 return (ENOENT);
5248 nmp = VFSTONFS(mp);
5249 if (!nmp)
5250 return (ENOENT);
5251 bzero(&vq, sizeof(vq));
5252 req->newidx = 0;
5253 if (is_64_bit) {
5254 req->newptr = vc.vc64.vc_ptr;
5255 req->newlen = (size_t)vc.vc64.vc_len;
5256 } else {
5257 req->newptr = CAST_USER_ADDR_T(vc.vc32.vc_ptr);
5258 req->newlen = vc.vc32.vc_len;
5259 }
5260 break;
5261 }
5262
5263 switch(name[0]) {
5264 case NFS_NFSSTATS:
5265 if (!oldp) {
5266 *oldlenp = sizeof nfsstats;
5267 return (0);
5268 }
5269
5270 if (*oldlenp < sizeof nfsstats) {
5271 *oldlenp = sizeof nfsstats;
5272 return (ENOMEM);
5273 }
5274
5275 error = copyout(&nfsstats, oldp, sizeof nfsstats);
5276 if (error)
5277 return (error);
5278
5279 if (newp && newlen != sizeof nfsstats)
5280 return (EINVAL);
5281
5282 if (newp)
5283 return copyin(newp, &nfsstats, sizeof nfsstats);
5284 return (0);
5285 case NFS_MOUNTINFO:
5286 /* read in the fsid */
5287 if (*oldlenp < sizeof(fsid))
5288 return (EINVAL);
5289 if ((error = copyin(oldp, &fsid, sizeof(fsid))))
5290 return (error);
5291 /* swizzle it back to host order */
5292 fsid.val[0] = ntohl(fsid.val[0]);
5293 fsid.val[1] = ntohl(fsid.val[1]);
5294 /* find mount and make sure it's NFS */
5295 if (((mp = vfs_getvfs(&fsid))) == NULL)
5296 return (ENOENT);
5297 if (strcmp(mp->mnt_vfsstat.f_fstypename, "nfs"))
5298 return (EINVAL);
5299 if (((nmp = VFSTONFS(mp))) == NULL)
5300 return (ENOENT);
5301 xb_init(&xb, 0);
5302 if ((error = nfs_mountinfo_assemble(nmp, &xb)))
5303 return (error);
5304 if (*oldlenp < xb.xb_u.xb_buffer.xbb_len)
5305 error = ENOMEM;
5306 else
5307 error = copyout(xb_buffer_base(&xb), oldp, xb.xb_u.xb_buffer.xbb_len);
5308 *oldlenp = xb.xb_u.xb_buffer.xbb_len;
5309 xb_cleanup(&xb);
5310 break;
5311 #if NFSSERVER
5312 case NFS_EXPORTSTATS:
5313 /* setup export stat descriptor */
5314 stat_desc.rec_vers = NFS_EXPORT_STAT_REC_VERSION;
5315
5316 if (!nfsrv_is_initialized()) {
5317 stat_desc.rec_count = 0;
5318 if (oldp && (*oldlenp >= sizeof(struct nfs_export_stat_desc)))
5319 error = copyout(&stat_desc, oldp, sizeof(struct nfs_export_stat_desc));
5320 *oldlenp = sizeof(struct nfs_export_stat_desc);
5321 return (error);
5322 }
5323
5324 /* Count the number of exported directories */
5325 lck_rw_lock_shared(&nfsrv_export_rwlock);
5326 numExports = 0;
5327 LIST_FOREACH(nxfs, &nfsrv_exports, nxfs_next)
5328 LIST_FOREACH(nx, &nxfs->nxfs_exports, nx_next)
5329 numExports += 1;
5330
5331 /* update stat descriptor's export record count */
5332 stat_desc.rec_count = numExports;
5333
5334 /* calculate total size of required buffer */
5335 totlen = sizeof(struct nfs_export_stat_desc) + (numExports * sizeof(struct nfs_export_stat_rec));
5336
5337 /* Check caller's buffer */
5338 if (oldp == 0) {
5339 lck_rw_done(&nfsrv_export_rwlock);
5340 /* indicate required buffer len */
5341 *oldlenp = totlen;
5342 return (0);
5343 }
5344
5345 /* We require the caller's buffer to be at least large enough to hold the descriptor */
5346 if (*oldlenp < sizeof(struct nfs_export_stat_desc)) {
5347 lck_rw_done(&nfsrv_export_rwlock);
5348 /* indicate required buffer len */
5349 *oldlenp = totlen;
5350 return (ENOMEM);
5351 }
5352
5353 /* indicate required buffer len */
5354 *oldlenp = totlen;
5355
5356 /* check if export table is empty */
5357 if (!numExports) {
5358 lck_rw_done(&nfsrv_export_rwlock);
5359 error = copyout(&stat_desc, oldp, sizeof(struct nfs_export_stat_desc));
5360 return (error);
5361 }
5362
5363 /* calculate how many actual export stat records fit into caller's buffer */
5364 numRecs = (*oldlenp - sizeof(struct nfs_export_stat_desc)) / sizeof(struct nfs_export_stat_rec);
5365
5366 if (!numRecs) {
5367 /* caller's buffer can only accomodate descriptor */
5368 lck_rw_done(&nfsrv_export_rwlock);
5369 stat_desc.rec_count = 0;
5370 error = copyout(&stat_desc, oldp, sizeof(struct nfs_export_stat_desc));
5371 return (error);
5372 }
5373
5374 /* adjust to actual number of records to copyout to caller's buffer */
5375 if (numRecs > numExports)
5376 numRecs = numExports;
5377
5378 /* set actual number of records we are returning */
5379 stat_desc.rec_count = numRecs;
5380
5381 /* first copy out the stat descriptor */
5382 pos = 0;
5383 error = copyout(&stat_desc, oldp + pos, sizeof(struct nfs_export_stat_desc));
5384 if (error) {
5385 lck_rw_done(&nfsrv_export_rwlock);
5386 return (error);
5387 }
5388 pos += sizeof(struct nfs_export_stat_desc);
5389
5390 /* Loop through exported directories */
5391 count = 0;
5392 LIST_FOREACH(nxfs, &nfsrv_exports, nxfs_next) {
5393 LIST_FOREACH(nx, &nxfs->nxfs_exports, nx_next) {
5394
5395 if (count >= numRecs)
5396 break;
5397
5398 /* build exported filesystem path */
5399 snprintf(statrec.path, sizeof(statrec.path), "%s%s%s",
5400 nxfs->nxfs_path, ((nxfs->nxfs_path[1] && nx->nx_path[0]) ? "/" : ""),
5401 nx->nx_path);
5402
5403 /* build the 64-bit export stat counters */
5404 statrec.ops = ((uint64_t)nx->nx_stats.ops.hi << 32) |
5405 nx->nx_stats.ops.lo;
5406 statrec.bytes_read = ((uint64_t)nx->nx_stats.bytes_read.hi << 32) |
5407 nx->nx_stats.bytes_read.lo;
5408 statrec.bytes_written = ((uint64_t)nx->nx_stats.bytes_written.hi << 32) |
5409 nx->nx_stats.bytes_written.lo;
5410 error = copyout(&statrec, oldp + pos, sizeof(statrec));
5411 if (error) {
5412 lck_rw_done(&nfsrv_export_rwlock);
5413 return (error);
5414 }
5415 /* advance buffer position */
5416 pos += sizeof(statrec);
5417 }
5418 }
5419 lck_rw_done(&nfsrv_export_rwlock);
5420 break;
5421 case NFS_USERSTATS:
5422 /* init structures used for copying out of kernel */
5423 ustat_desc.rec_vers = NFS_USER_STAT_REC_VERSION;
5424 ustat_rec.rec_type = NFS_USER_STAT_USER_REC;
5425 upath_rec.rec_type = NFS_USER_STAT_PATH_REC;
5426
5427 /* initialize counters */
5428 bytes_total = sizeof(struct nfs_user_stat_desc);
5429 bytes_avail = *oldlenp;
5430 recs_copied = 0;
5431
5432 if (!nfsrv_is_initialized()) /* NFS server not initialized, so no stats */
5433 goto ustat_skip;
5434
5435 /* reclaim old expired user nodes */
5436 nfsrv_active_user_list_reclaim();
5437
5438 /* reserve space for the buffer descriptor */
5439 if (bytes_avail >= sizeof(struct nfs_user_stat_desc))
5440 bytes_avail -= sizeof(struct nfs_user_stat_desc);
5441 else
5442 bytes_avail = 0;
5443
5444 /* put buffer position past the buffer descriptor */
5445 pos = sizeof(struct nfs_user_stat_desc);
5446
5447 /* Loop through exported directories */
5448 lck_rw_lock_shared(&nfsrv_export_rwlock);
5449 LIST_FOREACH(nxfs, &nfsrv_exports, nxfs_next) {
5450 LIST_FOREACH(nx, &nxfs->nxfs_exports, nx_next) {
5451 /* copy out path */
5452 if (bytes_avail >= sizeof(struct nfs_user_stat_path_rec)) {
5453 snprintf(upath_rec.path, sizeof(upath_rec.path), "%s%s%s",
5454 nxfs->nxfs_path, ((nxfs->nxfs_path[1] && nx->nx_path[0]) ? "/" : ""),
5455 nx->nx_path);
5456
5457 error = copyout(&upath_rec, oldp + pos, sizeof(struct nfs_user_stat_path_rec));
5458 if (error) {
5459 /* punt */
5460 goto ustat_done;
5461 }
5462
5463 pos += sizeof(struct nfs_user_stat_path_rec);
5464 bytes_avail -= sizeof(struct nfs_user_stat_path_rec);
5465 recs_copied++;
5466 }
5467 else {
5468 /* Caller's buffer is exhausted */
5469 bytes_avail = 0;
5470 }
5471
5472 bytes_total += sizeof(struct nfs_user_stat_path_rec);
5473
5474 /* Scan through all user nodes of this export */
5475 ulist = &nx->nx_user_list;
5476 lck_mtx_lock(&ulist->user_mutex);
5477 for (unode = TAILQ_FIRST(&ulist->user_lru); unode; unode = unode_next) {
5478 unode_next = TAILQ_NEXT(unode, lru_link);
5479
5480 /* copy out node if there is space */
5481 if (bytes_avail >= sizeof(struct nfs_user_stat_user_rec)) {
5482 /* prepare a user stat rec for copying out */
5483 ustat_rec.uid = unode->uid;
5484 bcopy(&unode->sock, &ustat_rec.sock, unode->sock.ss_len);
5485 ustat_rec.ops = unode->ops;
5486 ustat_rec.bytes_read = unode->bytes_read;
5487 ustat_rec.bytes_written = unode->bytes_written;
5488 ustat_rec.tm_start = unode->tm_start;
5489 ustat_rec.tm_last = unode->tm_last;
5490
5491 error = copyout(&ustat_rec, oldp + pos, sizeof(struct nfs_user_stat_user_rec));
5492
5493 if (error) {
5494 /* punt */
5495 lck_mtx_unlock(&ulist->user_mutex);
5496 goto ustat_done;
5497 }
5498
5499 pos += sizeof(struct nfs_user_stat_user_rec);
5500 bytes_avail -= sizeof(struct nfs_user_stat_user_rec);
5501 recs_copied++;
5502 }
5503 else {
5504 /* Caller's buffer is exhausted */
5505 bytes_avail = 0;
5506 }
5507 bytes_total += sizeof(struct nfs_user_stat_user_rec);
5508 }
5509 /* can unlock this export's list now */
5510 lck_mtx_unlock(&ulist->user_mutex);
5511 }
5512 }
5513
5514 ustat_done:
5515 /* unlock the export table */
5516 lck_rw_done(&nfsrv_export_rwlock);
5517
5518 ustat_skip:
5519 /* indicate number of actual records copied */
5520 ustat_desc.rec_count = recs_copied;
5521
5522 if (!error) {
5523 /* check if there was enough room for the buffer descriptor */
5524 if (*oldlenp >= sizeof(struct nfs_user_stat_desc))
5525 error = copyout(&ustat_desc, oldp, sizeof(struct nfs_user_stat_desc));
5526 else
5527 error = ENOMEM;
5528
5529 /* always indicate required buffer size */
5530 *oldlenp = bytes_total;
5531 }
5532 break;
5533 case NFS_USERCOUNT:
5534 if (!oldp) {
5535 *oldlenp = sizeof(nfsrv_user_stat_node_count);
5536 return (0);
5537 }
5538
5539 if (*oldlenp < sizeof(nfsrv_user_stat_node_count)) {
5540 *oldlenp = sizeof(nfsrv_user_stat_node_count);
5541 return (ENOMEM);
5542 }
5543
5544 if (nfsrv_is_initialized()) {
5545 /* reclaim old expired user nodes */
5546 nfsrv_active_user_list_reclaim();
5547 }
5548
5549 error = copyout(&nfsrv_user_stat_node_count, oldp, sizeof(nfsrv_user_stat_node_count));
5550 break;
5551 #endif /* NFSSERVER */
5552 case VFS_CTL_NOLOCKS:
5553 if (req->oldptr != USER_ADDR_NULL) {
5554 lck_mtx_lock(&nmp->nm_lock);
5555 val = (nmp->nm_lockmode == NFS_LOCK_MODE_DISABLED) ? 1 : 0;
5556 lck_mtx_unlock(&nmp->nm_lock);
5557 error = SYSCTL_OUT(req, &val, sizeof(val));
5558 if (error)
5559 return (error);
5560 }
5561 if (req->newptr != USER_ADDR_NULL) {
5562 error = SYSCTL_IN(req, &val, sizeof(val));
5563 if (error)
5564 return (error);
5565 lck_mtx_lock(&nmp->nm_lock);
5566 if (nmp->nm_lockmode == NFS_LOCK_MODE_LOCAL) {
5567 /* can't toggle locks when using local locks */
5568 error = EINVAL;
5569 } else if ((nmp->nm_vers >= NFS_VER4) && val) {
5570 /* can't disable locks for NFSv4 */
5571 error = EINVAL;
5572 } else if (val) {
5573 if ((nmp->nm_vers <= NFS_VER3) && (nmp->nm_lockmode == NFS_LOCK_MODE_ENABLED))
5574 nfs_lockd_mount_unregister(nmp);
5575 nmp->nm_lockmode = NFS_LOCK_MODE_DISABLED;
5576 nmp->nm_state &= ~NFSSTA_LOCKTIMEO;
5577 } else {
5578 if ((nmp->nm_vers <= NFS_VER3) && (nmp->nm_lockmode == NFS_LOCK_MODE_DISABLED))
5579 nfs_lockd_mount_register(nmp);
5580 nmp->nm_lockmode = NFS_LOCK_MODE_ENABLED;
5581 }
5582 lck_mtx_unlock(&nmp->nm_lock);
5583 }
5584 break;
5585 case VFS_CTL_QUERY:
5586 lck_mtx_lock(&nmp->nm_lock);
5587 /* XXX don't allow users to know about/disconnect unresponsive, soft, nobrowse mounts */
5588 softnobrowse = (NMFLAG(nmp, SOFT) && (vfs_flags(nmp->nm_mountp) & MNT_DONTBROWSE));
5589 if (!softnobrowse && (nmp->nm_state & NFSSTA_TIMEO))
5590 vq.vq_flags |= VQ_NOTRESP;
5591 if (!softnobrowse && (nmp->nm_state & NFSSTA_JUKEBOXTIMEO) && !NMFLAG(nmp, MUTEJUKEBOX))
5592 vq.vq_flags |= VQ_NOTRESP;
5593 if (!softnobrowse && (nmp->nm_state & NFSSTA_LOCKTIMEO) &&
5594 (nmp->nm_lockmode == NFS_LOCK_MODE_ENABLED))
5595 vq.vq_flags |= VQ_NOTRESP;
5596 if (nmp->nm_state & NFSSTA_DEAD)
5597 vq.vq_flags |= VQ_DEAD;
5598 lck_mtx_unlock(&nmp->nm_lock);
5599 error = SYSCTL_OUT(req, &vq, sizeof(vq));
5600 break;
5601 case VFS_CTL_TIMEO:
5602 if (req->oldptr != USER_ADDR_NULL) {
5603 lck_mtx_lock(&nmp->nm_lock);
5604 val = nmp->nm_tprintf_initial_delay;
5605 lck_mtx_unlock(&nmp->nm_lock);
5606 error = SYSCTL_OUT(req, &val, sizeof(val));
5607 if (error)
5608 return (error);
5609 }
5610 if (req->newptr != USER_ADDR_NULL) {
5611 error = SYSCTL_IN(req, &val, sizeof(val));
5612 if (error)
5613 return (error);
5614 lck_mtx_lock(&nmp->nm_lock);
5615 if (val < 0)
5616 nmp->nm_tprintf_initial_delay = 0;
5617 else
5618 nmp->nm_tprintf_initial_delay = val;
5619 lck_mtx_unlock(&nmp->nm_lock);
5620 }
5621 break;
5622 case VFS_CTL_NSTATUS:
5623 /*
5624 * Return the status of this mount. This is much more
5625 * information than VFS_CTL_QUERY. In addition to the
5626 * vq_flags return the significant mount options along
5627 * with the list of threads blocked on the mount and
5628 * how long the threads have been waiting.
5629 */
5630
5631 lck_mtx_lock(nfs_request_mutex);
5632 lck_mtx_lock(&nmp->nm_lock);
5633
5634 /*
5635 * Count the number of requests waiting for a reply.
5636 * Note: there could be multiple requests from the same thread.
5637 */
5638 numThreads = 0;
5639 TAILQ_FOREACH(rq, &nfs_reqq, r_chain) {
5640 if (rq->r_nmp == nmp)
5641 numThreads++;
5642 }
5643
5644 /* Calculate total size of result buffer */
5645 totlen = sizeof(struct netfs_status) + (numThreads * sizeof(uint64_t));
5646
5647 if (req->oldptr == USER_ADDR_NULL) { // Caller is querying buffer size
5648 lck_mtx_unlock(&nmp->nm_lock);
5649 lck_mtx_unlock(nfs_request_mutex);
5650 return SYSCTL_OUT(req, NULL, totlen);
5651 }
5652 if (req->oldlen < totlen) { // Check if caller's buffer is big enough
5653 lck_mtx_unlock(&nmp->nm_lock);
5654 lck_mtx_unlock(nfs_request_mutex);
5655 return (ERANGE);
5656 }
5657
5658 MALLOC(nsp, struct netfs_status *, totlen, M_TEMP, M_WAITOK|M_ZERO);
5659 if (nsp == NULL) {
5660 lck_mtx_unlock(&nmp->nm_lock);
5661 lck_mtx_unlock(nfs_request_mutex);
5662 return (ENOMEM);
5663 }
5664 timeoutmask = NFSSTA_TIMEO | NFSSTA_LOCKTIMEO | NFSSTA_JUKEBOXTIMEO;
5665 if (nmp->nm_state & timeoutmask)
5666 nsp->ns_status |= VQ_NOTRESP;
5667 if (nmp->nm_state & NFSSTA_DEAD)
5668 nsp->ns_status |= VQ_DEAD;
5669
5670 (void) nfs_mountopts(nmp, nsp->ns_mountopts, sizeof(nsp->ns_mountopts));
5671 nsp->ns_threadcount = numThreads;
5672
5673 /*
5674 * Get the thread ids of threads waiting for a reply
5675 * and find the longest wait time.
5676 */
5677 if (numThreads > 0) {
5678 struct timeval now;
5679 time_t sendtime;
5680
5681 microuptime(&now);
5682 count = 0;
5683 sendtime = now.tv_sec;
5684 TAILQ_FOREACH(rq, &nfs_reqq, r_chain) {
5685 if (rq->r_nmp == nmp) {
5686 if (rq->r_start < sendtime)
5687 sendtime = rq->r_start;
5688 // A thread_id of zero is used to represent an async I/O request.
5689 nsp->ns_threadids[count] =
5690 rq->r_thread ? thread_tid(rq->r_thread) : 0;
5691 if (++count >= numThreads)
5692 break;
5693 }
5694 }
5695 nsp->ns_waittime = now.tv_sec - sendtime;
5696 }
5697
5698 lck_mtx_unlock(&nmp->nm_lock);
5699 lck_mtx_unlock(nfs_request_mutex);
5700
5701 error = SYSCTL_OUT(req, nsp, totlen);
5702 FREE(nsp, M_TEMP);
5703 break;
5704 default:
5705 return (ENOTSUP);
5706 }
5707 return (error);
5708 }