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