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