1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 1989, 1993, 1995
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Rick Macklem at The University of Guelph.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  *	from nfs_vfsops.c	8.12 (Berkeley) 5/20/95
35  */
36 
37 #include <sys/cdefs.h>
38 __FBSDID("$FreeBSD: stable/12/sys/fs/nfsclient/nfs_clvfsops.c 372569 2022-09-19 00:52:36Z rmacklem $");
39 
40 
41 #include "opt_bootp.h"
42 #include "opt_nfsroot.h"
43 
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/kernel.h>
47 #include <sys/bio.h>
48 #include <sys/buf.h>
49 #include <sys/clock.h>
50 #include <sys/jail.h>
51 #include <sys/limits.h>
52 #include <sys/lock.h>
53 #include <sys/malloc.h>
54 #include <sys/mbuf.h>
55 #include <sys/module.h>
56 #include <sys/mount.h>
57 #include <sys/proc.h>
58 #include <sys/socket.h>
59 #include <sys/socketvar.h>
60 #include <sys/sockio.h>
61 #include <sys/sysctl.h>
62 #include <sys/vnode.h>
63 #include <sys/signalvar.h>
64 
65 #include <vm/vm.h>
66 #include <vm/vm_extern.h>
67 #include <vm/uma.h>
68 
69 #include <net/if.h>
70 #include <net/route.h>
71 #include <netinet/in.h>
72 
73 #include <fs/nfs/nfsport.h>
74 #include <fs/nfsclient/nfsnode.h>
75 #include <fs/nfsclient/nfsmount.h>
76 #include <fs/nfsclient/nfs.h>
77 #include <nfs/nfsdiskless.h>
78 
79 FEATURE(nfscl, "NFSv4 client");
80 
81 extern int nfscl_ticks;
82 extern struct timeval nfsboottime;
83 extern int nfsrv_useacl;
84 extern int nfscl_debuglevel;
85 extern enum nfsiod_state ncl_iodwant[NFS_MAXASYNCDAEMON];
86 extern struct nfsmount *ncl_iodmount[NFS_MAXASYNCDAEMON];
87 extern struct mtx ncl_iod_mutex;
88 NFSCLSTATEMUTEX;
89 extern struct mtx nfsrv_dslock_mtx;
90 
91 MALLOC_DEFINE(M_NEWNFSREQ, "newnfsclient_req", "NFS request header");
92 MALLOC_DEFINE(M_NEWNFSMNT, "newnfsmnt", "NFS mount struct");
93 
94 SYSCTL_DECL(_vfs_nfs);
95 static int nfs_ip_paranoia = 1;
96 SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs_ip_paranoia, CTLFLAG_RW,
97     &nfs_ip_paranoia, 0, "");
98 static int nfs_tprintf_initial_delay = NFS_TPRINTF_INITIAL_DELAY;
99 SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_INITIAL_DELAY,
100         downdelayinitial, CTLFLAG_RW, &nfs_tprintf_initial_delay, 0, "");
101 /* how long between console messages "nfs server foo not responding" */
102 static int nfs_tprintf_delay = NFS_TPRINTF_DELAY;
103 SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_DELAY,
104         downdelayinterval, CTLFLAG_RW, &nfs_tprintf_delay, 0, "");
105 #ifdef NFS_DEBUG
106 int nfs_debug;
107 SYSCTL_INT(_vfs_nfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0,
108     "Toggle debug flag");
109 #endif
110 
111 static int	nfs_mountroot(struct mount *);
112 static void	nfs_sec_name(char *, int *);
113 static void	nfs_decode_args(struct mount *mp, struct nfsmount *nmp,
114 		    struct nfs_args *argp, const char *, struct ucred *,
115 		    struct thread *);
116 static int	mountnfs(struct nfs_args *, struct mount *,
117 		    struct sockaddr *, char *, u_char *, int, u_char *, int,
118 		    u_char *, int, struct vnode **, struct ucred *,
119 		    struct thread *, int, int, int);
120 static void	nfs_getnlminfo(struct vnode *, uint8_t *, size_t *,
121 		    struct sockaddr_storage *, int *, off_t *,
122 		    struct timeval *);
123 static vfs_mount_t nfs_mount;
124 static vfs_cmount_t nfs_cmount;
125 static vfs_unmount_t nfs_unmount;
126 static vfs_root_t nfs_root;
127 static vfs_statfs_t nfs_statfs;
128 static vfs_sync_t nfs_sync;
129 static vfs_sysctl_t nfs_sysctl;
130 static vfs_purge_t nfs_purge;
131 
132 /*
133  * nfs vfs operations.
134  */
135 static struct vfsops nfs_vfsops = {
136 	.vfs_init =		ncl_init,
137 	.vfs_mount =		nfs_mount,
138 	.vfs_cmount =		nfs_cmount,
139 	.vfs_root =		nfs_root,
140 	.vfs_statfs =		nfs_statfs,
141 	.vfs_sync =		nfs_sync,
142 	.vfs_uninit =		ncl_uninit,
143 	.vfs_unmount =		nfs_unmount,
144 	.vfs_sysctl =		nfs_sysctl,
145 	.vfs_purge =		nfs_purge,
146 };
147 VFS_SET(nfs_vfsops, nfs, VFCF_NETWORK | VFCF_SBDRY);
148 
149 /* So that loader and kldload(2) can find us, wherever we are.. */
150 MODULE_VERSION(nfs, 1);
151 MODULE_DEPEND(nfs, nfscommon, 1, 1, 1);
152 MODULE_DEPEND(nfs, krpc, 1, 1, 1);
153 MODULE_DEPEND(nfs, nfssvc, 1, 1, 1);
154 MODULE_DEPEND(nfs, nfslock, 1, 1, 1);
155 MODULE_DEPEND(nfs, xdr, 1, 1, 1);
156 
157 /*
158  * This structure is now defined in sys/nfs/nfs_diskless.c so that it
159  * can be shared by both NFS clients. It is declared here so that it
160  * will be defined for kernels built without NFS_ROOT, although it
161  * isn't used in that case.
162  */
163 #if !defined(NFS_ROOT)
164 struct nfs_diskless	nfs_diskless = { { { 0 } } };
165 struct nfsv3_diskless	nfsv3_diskless = { { { 0 } } };
166 int			nfs_diskless_valid = 0;
167 #endif
168 
169 SYSCTL_INT(_vfs_nfs, OID_AUTO, diskless_valid, CTLFLAG_RD,
170     &nfs_diskless_valid, 0,
171     "Has the diskless struct been filled correctly");
172 
173 SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
174     nfsv3_diskless.root_hostnam, 0, "Path to nfs root");
175 
176 SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD,
177     &nfsv3_diskless.root_saddr, sizeof(nfsv3_diskless.root_saddr),
178     "%Ssockaddr_in", "Diskless root nfs address");
179 
180 
181 void		newnfsargs_ntoh(struct nfs_args *);
182 static int	nfs_mountdiskless(char *,
183 		    struct sockaddr_in *, struct nfs_args *,
184 		    struct thread *, struct vnode **, struct mount *);
185 static void	nfs_convert_diskless(void);
186 static void	nfs_convert_oargs(struct nfs_args *args,
187 		    struct onfs_args *oargs);
188 
189 int
newnfs_iosize(struct nfsmount * nmp)190 newnfs_iosize(struct nfsmount *nmp)
191 {
192 	int iosize, maxio;
193 
194 	/* First, set the upper limit for iosize */
195 	if (nmp->nm_flag & NFSMNT_NFSV4) {
196 		maxio = NFS_MAXBSIZE;
197 	} else if (nmp->nm_flag & NFSMNT_NFSV3) {
198 		if (nmp->nm_sotype == SOCK_DGRAM)
199 			maxio = NFS_MAXDGRAMDATA;
200 		else
201 			maxio = NFS_MAXBSIZE;
202 	} else {
203 		maxio = NFS_V2MAXDATA;
204 	}
205 	if (nmp->nm_rsize > maxio || nmp->nm_rsize == 0)
206 		nmp->nm_rsize = maxio;
207 	if (nmp->nm_rsize > NFS_MAXBSIZE)
208 		nmp->nm_rsize = NFS_MAXBSIZE;
209 	if (nmp->nm_readdirsize > maxio || nmp->nm_readdirsize == 0)
210 		nmp->nm_readdirsize = maxio;
211 	if (nmp->nm_readdirsize > nmp->nm_rsize)
212 		nmp->nm_readdirsize = nmp->nm_rsize;
213 	if (nmp->nm_wsize > maxio || nmp->nm_wsize == 0)
214 		nmp->nm_wsize = maxio;
215 	if (nmp->nm_wsize > NFS_MAXBSIZE)
216 		nmp->nm_wsize = NFS_MAXBSIZE;
217 
218 	/*
219 	 * Calculate the size used for io buffers.  Use the larger
220 	 * of the two sizes to minimise nfs requests but make sure
221 	 * that it is at least one VM page to avoid wasting buffer
222 	 * space.  It must also be at least NFS_DIRBLKSIZ, since
223 	 * that is the buffer size used for directories.
224 	 */
225 	iosize = imax(nmp->nm_rsize, nmp->nm_wsize);
226 	iosize = imax(iosize, PAGE_SIZE);
227 	iosize = imax(iosize, NFS_DIRBLKSIZ);
228 	nmp->nm_mountp->mnt_stat.f_iosize = iosize;
229 	return (iosize);
230 }
231 
232 static void
nfs_convert_oargs(struct nfs_args * args,struct onfs_args * oargs)233 nfs_convert_oargs(struct nfs_args *args, struct onfs_args *oargs)
234 {
235 
236 	args->version = NFS_ARGSVERSION;
237 	args->addr = oargs->addr;
238 	args->addrlen = oargs->addrlen;
239 	args->sotype = oargs->sotype;
240 	args->proto = oargs->proto;
241 	args->fh = oargs->fh;
242 	args->fhsize = oargs->fhsize;
243 	args->flags = oargs->flags;
244 	args->wsize = oargs->wsize;
245 	args->rsize = oargs->rsize;
246 	args->readdirsize = oargs->readdirsize;
247 	args->timeo = oargs->timeo;
248 	args->retrans = oargs->retrans;
249 	args->readahead = oargs->readahead;
250 	args->hostname = oargs->hostname;
251 }
252 
253 static void
nfs_convert_diskless(void)254 nfs_convert_diskless(void)
255 {
256 
257 	bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif,
258 		sizeof(struct ifaliasreq));
259 	bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
260 		sizeof(struct sockaddr_in));
261 	nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
262 	if (nfsv3_diskless.root_args.flags & NFSMNT_NFSV3) {
263 		nfsv3_diskless.root_fhsize = NFSX_MYFH;
264 		bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_MYFH);
265 	} else {
266 		nfsv3_diskless.root_fhsize = NFSX_V2FH;
267 		bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V2FH);
268 	}
269 	bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
270 		sizeof(struct sockaddr_in));
271 	bcopy(nfs_diskless.root_hostnam, nfsv3_diskless.root_hostnam, MNAMELEN);
272 	nfsv3_diskless.root_time = nfs_diskless.root_time;
273 	bcopy(nfs_diskless.my_hostnam, nfsv3_diskless.my_hostnam,
274 		MAXHOSTNAMELEN);
275 	nfs_diskless_valid = 3;
276 }
277 
278 /*
279  * nfs statfs call
280  */
281 static int
nfs_statfs(struct mount * mp,struct statfs * sbp)282 nfs_statfs(struct mount *mp, struct statfs *sbp)
283 {
284 	struct vnode *vp;
285 	struct thread *td;
286 	struct nfsmount *nmp = VFSTONFS(mp);
287 	struct nfsvattr nfsva;
288 	struct nfsfsinfo fs;
289 	struct nfsstatfs sb;
290 	int error = 0, attrflag, gotfsinfo = 0, ret;
291 	struct nfsnode *np;
292 
293 	td = curthread;
294 
295 	error = vfs_busy(mp, MBF_NOWAIT);
296 	if (error)
297 		return (error);
298 	error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
299 	if (error) {
300 		vfs_unbusy(mp);
301 		return (error);
302 	}
303 	vp = NFSTOV(np);
304 	mtx_lock(&nmp->nm_mtx);
305 	if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
306 		mtx_unlock(&nmp->nm_mtx);
307 		error = nfsrpc_fsinfo(vp, &fs, td->td_ucred, td, &nfsva,
308 		    &attrflag, NULL);
309 		if (!error)
310 			gotfsinfo = 1;
311 	} else
312 		mtx_unlock(&nmp->nm_mtx);
313 	if (!error)
314 		error = nfsrpc_statfs(vp, &sb, &fs, td->td_ucred, td, &nfsva,
315 		    &attrflag, NULL);
316 	if (error != 0)
317 		NFSCL_DEBUG(2, "statfs=%d\n", error);
318 	if (attrflag == 0) {
319 		ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
320 		    td->td_ucred, td, &nfsva, NULL, NULL);
321 		if (ret) {
322 			/*
323 			 * Just set default values to get things going.
324 			 */
325 			NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
326 			nfsva.na_vattr.va_type = VDIR;
327 			nfsva.na_vattr.va_mode = 0777;
328 			nfsva.na_vattr.va_nlink = 100;
329 			nfsva.na_vattr.va_uid = (uid_t)0;
330 			nfsva.na_vattr.va_gid = (gid_t)0;
331 			nfsva.na_vattr.va_fileid = 2;
332 			nfsva.na_vattr.va_gen = 1;
333 			nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
334 			nfsva.na_vattr.va_size = 512 * 1024;
335 		}
336 	}
337 	(void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1);
338 	if (!error) {
339 	    mtx_lock(&nmp->nm_mtx);
340 	    if (gotfsinfo || (nmp->nm_flag & NFSMNT_NFSV4))
341 		nfscl_loadfsinfo(nmp, &fs);
342 	    nfscl_loadsbinfo(nmp, &sb, sbp);
343 	    sbp->f_iosize = newnfs_iosize(nmp);
344 	    mtx_unlock(&nmp->nm_mtx);
345 	    if (sbp != &mp->mnt_stat) {
346 		bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
347 		bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
348 	    }
349 	    strncpy(&sbp->f_fstypename[0], mp->mnt_vfc->vfc_name, MFSNAMELEN);
350 	} else if (NFS_ISV4(vp)) {
351 		error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
352 	}
353 	vput(vp);
354 	vfs_unbusy(mp);
355 	return (error);
356 }
357 
358 /*
359  * nfs version 3 fsinfo rpc call
360  */
361 int
ncl_fsinfo(struct nfsmount * nmp,struct vnode * vp,struct ucred * cred,struct thread * td)362 ncl_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct ucred *cred,
363     struct thread *td)
364 {
365 	struct nfsfsinfo fs;
366 	struct nfsvattr nfsva;
367 	int error, attrflag;
368 
369 	error = nfsrpc_fsinfo(vp, &fs, cred, td, &nfsva, &attrflag, NULL);
370 	if (!error) {
371 		if (attrflag)
372 			(void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0,
373 			    1);
374 		mtx_lock(&nmp->nm_mtx);
375 		nfscl_loadfsinfo(nmp, &fs);
376 		mtx_unlock(&nmp->nm_mtx);
377 	}
378 	return (error);
379 }
380 
381 /*
382  * Mount a remote root fs via. nfs. This depends on the info in the
383  * nfs_diskless structure that has been filled in properly by some primary
384  * bootstrap.
385  * It goes something like this:
386  * - do enough of "ifconfig" by calling ifioctl() so that the system
387  *   can talk to the server
388  * - If nfs_diskless.mygateway is filled in, use that address as
389  *   a default gateway.
390  * - build the rootfs mount point and call mountnfs() to do the rest.
391  *
392  * It is assumed to be safe to read, modify, and write the nfsv3_diskless
393  * structure, as well as other global NFS client variables here, as
394  * nfs_mountroot() will be called once in the boot before any other NFS
395  * client activity occurs.
396  */
397 static int
nfs_mountroot(struct mount * mp)398 nfs_mountroot(struct mount *mp)
399 {
400 	struct thread *td = curthread;
401 	struct nfsv3_diskless *nd = &nfsv3_diskless;
402 	struct socket *so;
403 	struct vnode *vp;
404 	struct ifreq ir;
405 	int error;
406 	u_long l;
407 	char buf[128];
408 	char *cp;
409 
410 #if defined(BOOTP_NFSROOT) && defined(BOOTP)
411 	bootpc_init();		/* use bootp to get nfs_diskless filled in */
412 #elif defined(NFS_ROOT)
413 	nfs_setup_diskless();
414 #endif
415 
416 	if (nfs_diskless_valid == 0)
417 		return (-1);
418 	if (nfs_diskless_valid == 1)
419 		nfs_convert_diskless();
420 
421 	/*
422 	 * Do enough of ifconfig(8) so that the critical net interface can
423 	 * talk to the server.
424 	 */
425 	error = socreate(nd->myif.ifra_addr.sa_family, &so, nd->root_args.sotype, 0,
426 	    td->td_ucred, td);
427 	if (error)
428 		panic("nfs_mountroot: socreate(%04x): %d",
429 			nd->myif.ifra_addr.sa_family, error);
430 
431 #if 0 /* XXX Bad idea */
432 	/*
433 	 * We might not have been told the right interface, so we pass
434 	 * over the first ten interfaces of the same kind, until we get
435 	 * one of them configured.
436 	 */
437 
438 	for (i = strlen(nd->myif.ifra_name) - 1;
439 		nd->myif.ifra_name[i] >= '0' &&
440 		nd->myif.ifra_name[i] <= '9';
441 		nd->myif.ifra_name[i] ++) {
442 		error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
443 		if(!error)
444 			break;
445 	}
446 #endif
447 	error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
448 	if (error)
449 		panic("nfs_mountroot: SIOCAIFADDR: %d", error);
450 	if ((cp = kern_getenv("boot.netif.mtu")) != NULL) {
451 		ir.ifr_mtu = strtol(cp, NULL, 10);
452 		bcopy(nd->myif.ifra_name, ir.ifr_name, IFNAMSIZ);
453 		freeenv(cp);
454 		error = ifioctl(so, SIOCSIFMTU, (caddr_t)&ir, td);
455 		if (error)
456 			printf("nfs_mountroot: SIOCSIFMTU: %d", error);
457 	}
458 	soclose(so);
459 
460 	/*
461 	 * If the gateway field is filled in, set it as the default route.
462 	 * Note that pxeboot will set a default route of 0 if the route
463 	 * is not set by the DHCP server.  Check also for a value of 0
464 	 * to avoid panicking inappropriately in that situation.
465 	 */
466 	if (nd->mygateway.sin_len != 0 &&
467 	    nd->mygateway.sin_addr.s_addr != 0) {
468 		struct sockaddr_in mask, sin;
469 
470 		bzero((caddr_t)&mask, sizeof(mask));
471 		sin = mask;
472 		sin.sin_family = AF_INET;
473 		sin.sin_len = sizeof(sin);
474                 /* XXX MRT use table 0 for this sort of thing */
475 		CURVNET_SET(TD_TO_VNET(td));
476 		error = rtrequest_fib(RTM_ADD, (struct sockaddr *)&sin,
477 		    (struct sockaddr *)&nd->mygateway,
478 		    (struct sockaddr *)&mask,
479 		    RTF_UP | RTF_GATEWAY, NULL, RT_DEFAULT_FIB);
480 		CURVNET_RESTORE();
481 		if (error)
482 			panic("nfs_mountroot: RTM_ADD: %d", error);
483 	}
484 
485 	/*
486 	 * Create the rootfs mount point.
487 	 */
488 	nd->root_args.fh = nd->root_fh;
489 	nd->root_args.fhsize = nd->root_fhsize;
490 	l = ntohl(nd->root_saddr.sin_addr.s_addr);
491 	snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
492 		(l >> 24) & 0xff, (l >> 16) & 0xff,
493 		(l >>  8) & 0xff, (l >>  0) & 0xff, nd->root_hostnam);
494 	printf("NFS ROOT: %s\n", buf);
495 	nd->root_args.hostname = buf;
496 	if ((error = nfs_mountdiskless(buf,
497 	    &nd->root_saddr, &nd->root_args, td, &vp, mp)) != 0) {
498 		return (error);
499 	}
500 
501 	/*
502 	 * This is not really an nfs issue, but it is much easier to
503 	 * set hostname here and then let the "/etc/rc.xxx" files
504 	 * mount the right /var based upon its preset value.
505 	 */
506 	mtx_lock(&prison0.pr_mtx);
507 	strlcpy(prison0.pr_hostname, nd->my_hostnam,
508 	    sizeof(prison0.pr_hostname));
509 	mtx_unlock(&prison0.pr_mtx);
510 	inittodr(ntohl(nd->root_time));
511 	return (0);
512 }
513 
514 /*
515  * Internal version of mount system call for diskless setup.
516  */
517 static int
nfs_mountdiskless(char * path,struct sockaddr_in * sin,struct nfs_args * args,struct thread * td,struct vnode ** vpp,struct mount * mp)518 nfs_mountdiskless(char *path,
519     struct sockaddr_in *sin, struct nfs_args *args, struct thread *td,
520     struct vnode **vpp, struct mount *mp)
521 {
522 	struct sockaddr *nam;
523 	int dirlen, error;
524 	char *dirpath;
525 
526 	/*
527 	 * Find the directory path in "path", which also has the server's
528 	 * name/ip address in it.
529 	 */
530 	dirpath = strchr(path, ':');
531 	if (dirpath != NULL)
532 		dirlen = strlen(++dirpath);
533 	else
534 		dirlen = 0;
535 	nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK);
536 	if ((error = mountnfs(args, mp, nam, path, NULL, 0, dirpath, dirlen,
537 	    NULL, 0, vpp, td->td_ucred, td, NFS_DEFAULT_NAMETIMEO,
538 	    NFS_DEFAULT_NEGNAMETIMEO, 0)) != 0) {
539 		printf("nfs_mountroot: mount %s on /: %d\n", path, error);
540 		return (error);
541 	}
542 	return (0);
543 }
544 
545 static void
nfs_sec_name(char * sec,int * flagsp)546 nfs_sec_name(char *sec, int *flagsp)
547 {
548 	if (!strcmp(sec, "krb5"))
549 		*flagsp |= NFSMNT_KERB;
550 	else if (!strcmp(sec, "krb5i"))
551 		*flagsp |= (NFSMNT_KERB | NFSMNT_INTEGRITY);
552 	else if (!strcmp(sec, "krb5p"))
553 		*flagsp |= (NFSMNT_KERB | NFSMNT_PRIVACY);
554 }
555 
556 static void
nfs_decode_args(struct mount * mp,struct nfsmount * nmp,struct nfs_args * argp,const char * hostname,struct ucred * cred,struct thread * td)557 nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp,
558     const char *hostname, struct ucred *cred, struct thread *td)
559 {
560 	int adjsock;
561 	char *p;
562 
563 	/*
564 	 * Set read-only flag if requested; otherwise, clear it if this is
565 	 * an update.  If this is not an update, then either the read-only
566 	 * flag is already clear, or this is a root mount and it was set
567 	 * intentionally at some previous point.
568 	 */
569 	if (vfs_getopt(mp->mnt_optnew, "ro", NULL, NULL) == 0) {
570 		MNT_ILOCK(mp);
571 		mp->mnt_flag |= MNT_RDONLY;
572 		MNT_IUNLOCK(mp);
573 	} else if (mp->mnt_flag & MNT_UPDATE) {
574 		MNT_ILOCK(mp);
575 		mp->mnt_flag &= ~MNT_RDONLY;
576 		MNT_IUNLOCK(mp);
577 	}
578 
579 	/*
580 	 * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
581 	 * no sense in that context.  Also, set up appropriate retransmit
582 	 * and soft timeout behavior.
583 	 */
584 	if (argp->sotype == SOCK_STREAM) {
585 		nmp->nm_flag &= ~NFSMNT_NOCONN;
586 		nmp->nm_timeo = NFS_MAXTIMEO;
587 		if ((argp->flags & NFSMNT_NFSV4) != 0)
588 			nmp->nm_retry = INT_MAX;
589 		else
590 			nmp->nm_retry = NFS_RETRANS_TCP;
591 	}
592 
593 	/* Also clear RDIRPLUS if NFSv2, it crashes some servers */
594 	if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
595 		argp->flags &= ~NFSMNT_RDIRPLUS;
596 		nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
597 	}
598 
599 	/* Clear ONEOPENOWN for NFSv2, 3 and 4.0. */
600 	if (nmp->nm_minorvers == 0) {
601 		argp->flags &= ~NFSMNT_ONEOPENOWN;
602 		nmp->nm_flag &= ~NFSMNT_ONEOPENOWN;
603 	}
604 
605 	/* Re-bind if rsrvd port requested and wasn't on one */
606 	adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
607 		  && (argp->flags & NFSMNT_RESVPORT);
608 	/* Also re-bind if we're switching to/from a connected UDP socket */
609 	adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
610 		    (argp->flags & NFSMNT_NOCONN));
611 
612 	/* Update flags atomically.  Don't change the lock bits. */
613 	nmp->nm_flag = argp->flags | nmp->nm_flag;
614 
615 	if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
616 		nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
617 		if (nmp->nm_timeo < NFS_MINTIMEO)
618 			nmp->nm_timeo = NFS_MINTIMEO;
619 		else if (nmp->nm_timeo > NFS_MAXTIMEO)
620 			nmp->nm_timeo = NFS_MAXTIMEO;
621 	}
622 
623 	if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
624 		nmp->nm_retry = argp->retrans;
625 		if (nmp->nm_retry > NFS_MAXREXMIT)
626 			nmp->nm_retry = NFS_MAXREXMIT;
627 	}
628 
629 	if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
630 		nmp->nm_wsize = argp->wsize;
631 		/*
632 		 * Clip at the power of 2 below the size. There is an
633 		 * issue (not isolated) that causes intermittent page
634 		 * faults if this is not done.
635 		 */
636 		if (nmp->nm_wsize > NFS_FABLKSIZE)
637 			nmp->nm_wsize = 1 << (fls(nmp->nm_wsize) - 1);
638 		else
639 			nmp->nm_wsize = NFS_FABLKSIZE;
640 	}
641 
642 	if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
643 		nmp->nm_rsize = argp->rsize;
644 		/*
645 		 * Clip at the power of 2 below the size. There is an
646 		 * issue (not isolated) that causes intermittent page
647 		 * faults if this is not done.
648 		 */
649 		if (nmp->nm_rsize > NFS_FABLKSIZE)
650 			nmp->nm_rsize = 1 << (fls(nmp->nm_rsize) - 1);
651 		else
652 			nmp->nm_rsize = NFS_FABLKSIZE;
653 	}
654 
655 	if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
656 		nmp->nm_readdirsize = argp->readdirsize;
657 	}
658 
659 	if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0)
660 		nmp->nm_acregmin = argp->acregmin;
661 	else
662 		nmp->nm_acregmin = NFS_MINATTRTIMO;
663 	if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0)
664 		nmp->nm_acregmax = argp->acregmax;
665 	else
666 		nmp->nm_acregmax = NFS_MAXATTRTIMO;
667 	if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0)
668 		nmp->nm_acdirmin = argp->acdirmin;
669 	else
670 		nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
671 	if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0)
672 		nmp->nm_acdirmax = argp->acdirmax;
673 	else
674 		nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
675 	if (nmp->nm_acdirmin > nmp->nm_acdirmax)
676 		nmp->nm_acdirmin = nmp->nm_acdirmax;
677 	if (nmp->nm_acregmin > nmp->nm_acregmax)
678 		nmp->nm_acregmin = nmp->nm_acregmax;
679 
680 	if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) {
681 		if (argp->readahead <= NFS_MAXRAHEAD)
682 			nmp->nm_readahead = argp->readahead;
683 		else
684 			nmp->nm_readahead = NFS_MAXRAHEAD;
685 	}
686 	if ((argp->flags & NFSMNT_WCOMMITSIZE) && argp->wcommitsize >= 0) {
687 		if (argp->wcommitsize < nmp->nm_wsize)
688 			nmp->nm_wcommitsize = nmp->nm_wsize;
689 		else
690 			nmp->nm_wcommitsize = argp->wcommitsize;
691 	}
692 
693 	adjsock |= ((nmp->nm_sotype != argp->sotype) ||
694 		    (nmp->nm_soproto != argp->proto));
695 
696 	if (nmp->nm_client != NULL && adjsock) {
697 		int haslock = 0, error = 0;
698 
699 		if (nmp->nm_sotype == SOCK_STREAM) {
700 			error = newnfs_sndlock(&nmp->nm_sockreq.nr_lock);
701 			if (!error)
702 				haslock = 1;
703 		}
704 		if (!error) {
705 		    newnfs_disconnect(&nmp->nm_sockreq);
706 		    if (haslock)
707 			newnfs_sndunlock(&nmp->nm_sockreq.nr_lock);
708 		    nmp->nm_sotype = argp->sotype;
709 		    nmp->nm_soproto = argp->proto;
710 		    if (nmp->nm_sotype == SOCK_DGRAM)
711 			while (newnfs_connect(nmp, &nmp->nm_sockreq,
712 			    cred, td, 0)) {
713 				printf("newnfs_args: retrying connect\n");
714 				(void) nfs_catnap(PSOCK, 0, "nfscon");
715 			}
716 		}
717 	} else {
718 		nmp->nm_sotype = argp->sotype;
719 		nmp->nm_soproto = argp->proto;
720 	}
721 
722 	if (hostname != NULL) {
723 		strlcpy(nmp->nm_hostname, hostname,
724 		    sizeof(nmp->nm_hostname));
725 		p = strchr(nmp->nm_hostname, ':');
726 		if (p != NULL)
727 			*p = '\0';
728 	}
729 }
730 
731 static const char *nfs_opts[] = { "from", "nfs_args",
732     "noac", "noatime", "noexec", "suiddir", "nosuid", "nosymfollow", "union",
733     "noclusterr", "noclusterw", "multilabel", "acls", "force", "update",
734     "async", "noconn", "nolockd", "conn", "lockd", "intr", "rdirplus",
735     "readdirsize", "soft", "hard", "mntudp", "tcp", "udp", "wsize", "rsize",
736     "retrans", "actimeo", "acregmin", "acregmax", "acdirmin", "acdirmax",
737     "resvport", "readahead", "hostname", "timeo", "timeout", "addr", "fh",
738     "nfsv3", "sec", "principal", "nfsv4", "gssname", "allgssname", "dirpath",
739     "minorversion", "nametimeo", "negnametimeo", "nocto", "noncontigwr",
740     "pnfs", "wcommitsize", "oneopenown",
741     NULL };
742 
743 /*
744  * Parse the "from" mountarg, passed by the generic mount(8) program
745  * or the mountroot code.  This is used when rerooting into NFS.
746  *
747  * Note that the "hostname" is actually a "hostname:/share/path" string.
748  */
749 static int
nfs_mount_parse_from(struct vfsoptlist * opts,char ** hostnamep,struct sockaddr_in ** sinp,char * dirpath,size_t dirpathsize,int * dirlenp)750 nfs_mount_parse_from(struct vfsoptlist *opts, char **hostnamep,
751     struct sockaddr_in **sinp, char *dirpath, size_t dirpathsize, int *dirlenp)
752 {
753 	char *nam, *delimp, *hostp, *spec;
754 	int error, have_bracket = 0, offset, rv, speclen;
755 	struct sockaddr_in *sin;
756 	size_t len;
757 
758 	error = vfs_getopt(opts, "from", (void **)&spec, &speclen);
759 	if (error != 0)
760 		return (error);
761 	nam = malloc(MNAMELEN + 1, M_TEMP, M_WAITOK);
762 
763 	/*
764 	 * This part comes from sbin/mount_nfs/mount_nfs.c:getnfsargs().
765 	 */
766 	if (*spec == '[' && (delimp = strchr(spec + 1, ']')) != NULL &&
767 	    *(delimp + 1) == ':') {
768 		hostp = spec + 1;
769 		spec = delimp + 2;
770 		have_bracket = 1;
771 	} else if ((delimp = strrchr(spec, ':')) != NULL) {
772 		hostp = spec;
773 		spec = delimp + 1;
774 	} else if ((delimp = strrchr(spec, '@')) != NULL) {
775 		printf("%s: path@server syntax is deprecated, "
776 		    "use server:path\n", __func__);
777 		hostp = delimp + 1;
778 	} else {
779 		printf("%s: no <host>:<dirpath> nfs-name\n", __func__);
780 		free(nam, M_TEMP);
781 		return (EINVAL);
782 	}
783 	*delimp = '\0';
784 
785 	/*
786 	 * If there has been a trailing slash at mounttime it seems
787 	 * that some mountd implementations fail to remove the mount
788 	 * entries from their mountlist while unmounting.
789 	 */
790 	for (speclen = strlen(spec);
791 	    speclen > 1 && spec[speclen - 1] == '/';
792 	    speclen--)
793 		spec[speclen - 1] = '\0';
794 	if (strlen(hostp) + strlen(spec) + 1 > MNAMELEN) {
795 		printf("%s: %s:%s: name too long", __func__, hostp, spec);
796 		free(nam, M_TEMP);
797 		return (EINVAL);
798 	}
799 	/* Make both '@' and ':' notations equal */
800 	if (*hostp != '\0') {
801 		len = strlen(hostp);
802 		offset = 0;
803 		if (have_bracket)
804 			nam[offset++] = '[';
805 		memmove(nam + offset, hostp, len);
806 		if (have_bracket)
807 			nam[len + offset++] = ']';
808 		nam[len + offset++] = ':';
809 		memmove(nam + len + offset, spec, speclen);
810 		nam[len + speclen + offset] = '\0';
811 	} else
812 		nam[0] = '\0';
813 
814 	/*
815 	 * XXX: IPv6
816 	 */
817 	sin = malloc(sizeof(*sin), M_SONAME, M_WAITOK);
818 	rv = inet_pton(AF_INET, hostp, &sin->sin_addr);
819 	if (rv != 1) {
820 		printf("%s: cannot parse '%s', inet_pton() returned %d\n",
821 		    __func__, hostp, rv);
822 		free(nam, M_TEMP);
823 		free(sin, M_SONAME);
824 		return (EINVAL);
825 	}
826 
827 	sin->sin_len = sizeof(*sin);
828 	sin->sin_family = AF_INET;
829 	/*
830 	 * XXX: hardcoded port number.
831 	 */
832 	sin->sin_port = htons(2049);
833 
834 	*hostnamep = strdup(nam, M_NEWNFSMNT);
835 	*sinp = sin;
836 	strlcpy(dirpath, spec, dirpathsize);
837 	*dirlenp = strlen(dirpath);
838 
839 	free(nam, M_TEMP);
840 	return (0);
841 }
842 
843 /*
844  * VFS Operations.
845  *
846  * mount system call
847  * It seems a bit dumb to copyinstr() the host and path here and then
848  * bcopy() them in mountnfs(), but I wanted to detect errors before
849  * doing the getsockaddr() call because getsockaddr() allocates an mbuf and
850  * an error after that means that I have to release the mbuf.
851  */
852 /* ARGSUSED */
853 static int
nfs_mount(struct mount * mp)854 nfs_mount(struct mount *mp)
855 {
856 	struct nfs_args args = {
857 	    .version = NFS_ARGSVERSION,
858 	    .addr = NULL,
859 	    .addrlen = sizeof (struct sockaddr_in),
860 	    .sotype = SOCK_STREAM,
861 	    .proto = 0,
862 	    .fh = NULL,
863 	    .fhsize = 0,
864 	    .flags = NFSMNT_RESVPORT,
865 	    .wsize = NFS_WSIZE,
866 	    .rsize = NFS_RSIZE,
867 	    .readdirsize = NFS_READDIRSIZE,
868 	    .timeo = 10,
869 	    .retrans = NFS_RETRANS,
870 	    .readahead = NFS_DEFRAHEAD,
871 	    .wcommitsize = 0,			/* was: NQ_DEFLEASE */
872 	    .hostname = NULL,
873 	    .acregmin = NFS_MINATTRTIMO,
874 	    .acregmax = NFS_MAXATTRTIMO,
875 	    .acdirmin = NFS_MINDIRATTRTIMO,
876 	    .acdirmax = NFS_MAXDIRATTRTIMO,
877 	};
878 	int error = 0, ret, len;
879 	struct sockaddr *nam = NULL;
880 	struct vnode *vp;
881 	struct thread *td;
882 	char *hst;
883 	u_char nfh[NFSX_FHMAX], krbname[100], dirpath[100], srvkrbname[100];
884 	char *cp, *opt, *name, *secname;
885 	int nametimeo = NFS_DEFAULT_NAMETIMEO;
886 	int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO;
887 	int minvers = 0;
888 	int dirlen, has_nfs_args_opt, has_nfs_from_opt,
889 	    krbnamelen, srvkrbnamelen;
890 	size_t hstlen;
891 
892 	has_nfs_args_opt = 0;
893 	has_nfs_from_opt = 0;
894 	hst = malloc(MNAMELEN, M_TEMP, M_WAITOK);
895 	if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {
896 		error = EINVAL;
897 		goto out;
898 	}
899 
900 	td = curthread;
901 	if ((mp->mnt_flag & (MNT_ROOTFS | MNT_UPDATE)) == MNT_ROOTFS &&
902 	    nfs_diskless_valid != 0) {
903 		error = nfs_mountroot(mp);
904 		goto out;
905 	}
906 
907 	nfscl_init();
908 
909 	/*
910 	 * The old mount_nfs program passed the struct nfs_args
911 	 * from userspace to kernel.  The new mount_nfs program
912 	 * passes string options via nmount() from userspace to kernel
913 	 * and we populate the struct nfs_args in the kernel.
914 	 */
915 	if (vfs_getopt(mp->mnt_optnew, "nfs_args", NULL, NULL) == 0) {
916 		error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args,
917 		    sizeof(args));
918 		if (error != 0)
919 			goto out;
920 
921 		if (args.version != NFS_ARGSVERSION) {
922 			error = EPROGMISMATCH;
923 			goto out;
924 		}
925 		has_nfs_args_opt = 1;
926 	}
927 
928 	/* Handle the new style options. */
929 	if (vfs_getopt(mp->mnt_optnew, "noac", NULL, NULL) == 0) {
930 		args.acdirmin = args.acdirmax =
931 		    args.acregmin = args.acregmax = 0;
932 		args.flags |= NFSMNT_ACDIRMIN | NFSMNT_ACDIRMAX |
933 		    NFSMNT_ACREGMIN | NFSMNT_ACREGMAX;
934 	}
935 	if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0)
936 		args.flags |= NFSMNT_NOCONN;
937 	if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0)
938 		args.flags &= ~NFSMNT_NOCONN;
939 	if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0)
940 		args.flags |= NFSMNT_NOLOCKD;
941 	if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0)
942 		args.flags &= ~NFSMNT_NOLOCKD;
943 	if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0)
944 		args.flags |= NFSMNT_INT;
945 	if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0)
946 		args.flags |= NFSMNT_RDIRPLUS;
947 	if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0)
948 		args.flags |= NFSMNT_RESVPORT;
949 	if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0)
950 		args.flags &= ~NFSMNT_RESVPORT;
951 	if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0)
952 		args.flags |= NFSMNT_SOFT;
953 	if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0)
954 		args.flags &= ~NFSMNT_SOFT;
955 	if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0)
956 		args.sotype = SOCK_DGRAM;
957 	if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0)
958 		args.sotype = SOCK_DGRAM;
959 	if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0)
960 		args.sotype = SOCK_STREAM;
961 	if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0)
962 		args.flags |= NFSMNT_NFSV3;
963 	if (vfs_getopt(mp->mnt_optnew, "nfsv4", NULL, NULL) == 0) {
964 		args.flags |= NFSMNT_NFSV4;
965 		args.sotype = SOCK_STREAM;
966 	}
967 	if (vfs_getopt(mp->mnt_optnew, "allgssname", NULL, NULL) == 0)
968 		args.flags |= NFSMNT_ALLGSSNAME;
969 	if (vfs_getopt(mp->mnt_optnew, "nocto", NULL, NULL) == 0)
970 		args.flags |= NFSMNT_NOCTO;
971 	if (vfs_getopt(mp->mnt_optnew, "noncontigwr", NULL, NULL) == 0)
972 		args.flags |= NFSMNT_NONCONTIGWR;
973 	if (vfs_getopt(mp->mnt_optnew, "pnfs", NULL, NULL) == 0)
974 		args.flags |= NFSMNT_PNFS;
975 	if (vfs_getopt(mp->mnt_optnew, "oneopenown", NULL, NULL) == 0)
976 		args.flags |= NFSMNT_ONEOPENOWN;
977 	if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
978 		if (opt == NULL) {
979 			vfs_mount_error(mp, "illegal readdirsize");
980 			error = EINVAL;
981 			goto out;
982 		}
983 		ret = sscanf(opt, "%d", &args.readdirsize);
984 		if (ret != 1 || args.readdirsize <= 0) {
985 			vfs_mount_error(mp, "illegal readdirsize: %s",
986 			    opt);
987 			error = EINVAL;
988 			goto out;
989 		}
990 		args.flags |= NFSMNT_READDIRSIZE;
991 	}
992 	if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) {
993 		if (opt == NULL) {
994 			vfs_mount_error(mp, "illegal readahead");
995 			error = EINVAL;
996 			goto out;
997 		}
998 		ret = sscanf(opt, "%d", &args.readahead);
999 		if (ret != 1 || args.readahead <= 0) {
1000 			vfs_mount_error(mp, "illegal readahead: %s",
1001 			    opt);
1002 			error = EINVAL;
1003 			goto out;
1004 		}
1005 		args.flags |= NFSMNT_READAHEAD;
1006 	}
1007 	if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) {
1008 		if (opt == NULL) {
1009 			vfs_mount_error(mp, "illegal wsize");
1010 			error = EINVAL;
1011 			goto out;
1012 		}
1013 		ret = sscanf(opt, "%d", &args.wsize);
1014 		if (ret != 1 || args.wsize <= 0) {
1015 			vfs_mount_error(mp, "illegal wsize: %s",
1016 			    opt);
1017 			error = EINVAL;
1018 			goto out;
1019 		}
1020 		args.flags |= NFSMNT_WSIZE;
1021 	}
1022 	if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) {
1023 		if (opt == NULL) {
1024 			vfs_mount_error(mp, "illegal rsize");
1025 			error = EINVAL;
1026 			goto out;
1027 		}
1028 		ret = sscanf(opt, "%d", &args.rsize);
1029 		if (ret != 1 || args.rsize <= 0) {
1030 			vfs_mount_error(mp, "illegal wsize: %s",
1031 			    opt);
1032 			error = EINVAL;
1033 			goto out;
1034 		}
1035 		args.flags |= NFSMNT_RSIZE;
1036 	}
1037 	if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) {
1038 		if (opt == NULL) {
1039 			vfs_mount_error(mp, "illegal retrans");
1040 			error = EINVAL;
1041 			goto out;
1042 		}
1043 		ret = sscanf(opt, "%d", &args.retrans);
1044 		if (ret != 1 || args.retrans <= 0) {
1045 			vfs_mount_error(mp, "illegal retrans: %s",
1046 			    opt);
1047 			error = EINVAL;
1048 			goto out;
1049 		}
1050 		args.flags |= NFSMNT_RETRANS;
1051 	}
1052 	if (vfs_getopt(mp->mnt_optnew, "actimeo", (void **)&opt, NULL) == 0) {
1053 		ret = sscanf(opt, "%d", &args.acregmin);
1054 		if (ret != 1 || args.acregmin < 0) {
1055 			vfs_mount_error(mp, "illegal actimeo: %s",
1056 			    opt);
1057 			error = EINVAL;
1058 			goto out;
1059 		}
1060 		args.acdirmin = args.acdirmax = args.acregmax = args.acregmin;
1061 		args.flags |= NFSMNT_ACDIRMIN | NFSMNT_ACDIRMAX |
1062 		    NFSMNT_ACREGMIN | NFSMNT_ACREGMAX;
1063 	}
1064 	if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) {
1065 		ret = sscanf(opt, "%d", &args.acregmin);
1066 		if (ret != 1 || args.acregmin < 0) {
1067 			vfs_mount_error(mp, "illegal acregmin: %s",
1068 			    opt);
1069 			error = EINVAL;
1070 			goto out;
1071 		}
1072 		args.flags |= NFSMNT_ACREGMIN;
1073 	}
1074 	if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) {
1075 		ret = sscanf(opt, "%d", &args.acregmax);
1076 		if (ret != 1 || args.acregmax < 0) {
1077 			vfs_mount_error(mp, "illegal acregmax: %s",
1078 			    opt);
1079 			error = EINVAL;
1080 			goto out;
1081 		}
1082 		args.flags |= NFSMNT_ACREGMAX;
1083 	}
1084 	if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) {
1085 		ret = sscanf(opt, "%d", &args.acdirmin);
1086 		if (ret != 1 || args.acdirmin < 0) {
1087 			vfs_mount_error(mp, "illegal acdirmin: %s",
1088 			    opt);
1089 			error = EINVAL;
1090 			goto out;
1091 		}
1092 		args.flags |= NFSMNT_ACDIRMIN;
1093 	}
1094 	if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) {
1095 		ret = sscanf(opt, "%d", &args.acdirmax);
1096 		if (ret != 1 || args.acdirmax < 0) {
1097 			vfs_mount_error(mp, "illegal acdirmax: %s",
1098 			    opt);
1099 			error = EINVAL;
1100 			goto out;
1101 		}
1102 		args.flags |= NFSMNT_ACDIRMAX;
1103 	}
1104 	if (vfs_getopt(mp->mnt_optnew, "wcommitsize", (void **)&opt, NULL) == 0) {
1105 		ret = sscanf(opt, "%d", &args.wcommitsize);
1106 		if (ret != 1 || args.wcommitsize < 0) {
1107 			vfs_mount_error(mp, "illegal wcommitsize: %s", opt);
1108 			error = EINVAL;
1109 			goto out;
1110 		}
1111 		args.flags |= NFSMNT_WCOMMITSIZE;
1112 	}
1113 	if (vfs_getopt(mp->mnt_optnew, "timeo", (void **)&opt, NULL) == 0) {
1114 		ret = sscanf(opt, "%d", &args.timeo);
1115 		if (ret != 1 || args.timeo <= 0) {
1116 			vfs_mount_error(mp, "illegal timeo: %s",
1117 			    opt);
1118 			error = EINVAL;
1119 			goto out;
1120 		}
1121 		args.flags |= NFSMNT_TIMEO;
1122 	}
1123 	if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) {
1124 		ret = sscanf(opt, "%d", &args.timeo);
1125 		if (ret != 1 || args.timeo <= 0) {
1126 			vfs_mount_error(mp, "illegal timeout: %s",
1127 			    opt);
1128 			error = EINVAL;
1129 			goto out;
1130 		}
1131 		args.flags |= NFSMNT_TIMEO;
1132 	}
1133 	if (vfs_getopt(mp->mnt_optnew, "nametimeo", (void **)&opt, NULL) == 0) {
1134 		ret = sscanf(opt, "%d", &nametimeo);
1135 		if (ret != 1 || nametimeo < 0) {
1136 			vfs_mount_error(mp, "illegal nametimeo: %s", opt);
1137 			error = EINVAL;
1138 			goto out;
1139 		}
1140 	}
1141 	if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL)
1142 	    == 0) {
1143 		ret = sscanf(opt, "%d", &negnametimeo);
1144 		if (ret != 1 || negnametimeo < 0) {
1145 			vfs_mount_error(mp, "illegal negnametimeo: %s",
1146 			    opt);
1147 			error = EINVAL;
1148 			goto out;
1149 		}
1150 	}
1151 	if (vfs_getopt(mp->mnt_optnew, "minorversion", (void **)&opt, NULL) ==
1152 	    0) {
1153 		ret = sscanf(opt, "%d", &minvers);
1154 		if (ret != 1 || minvers < 0 || minvers > 1 ||
1155 		    (args.flags & NFSMNT_NFSV4) == 0) {
1156 			vfs_mount_error(mp, "illegal minorversion: %s", opt);
1157 			error = EINVAL;
1158 			goto out;
1159 		}
1160 	}
1161 	if (vfs_getopt(mp->mnt_optnew, "sec",
1162 		(void **) &secname, NULL) == 0)
1163 		nfs_sec_name(secname, &args.flags);
1164 
1165 	if (mp->mnt_flag & MNT_UPDATE) {
1166 		struct nfsmount *nmp = VFSTONFS(mp);
1167 
1168 		if (nmp == NULL) {
1169 			error = EIO;
1170 			goto out;
1171 		}
1172 
1173 		/*
1174 		 * If a change from TCP->UDP is done and there are thread(s)
1175 		 * that have I/O RPC(s) in progress with a transfer size
1176 		 * greater than NFS_MAXDGRAMDATA, those thread(s) will be
1177 		 * hung, retrying the RPC(s) forever. Usually these threads
1178 		 * will be seen doing an uninterruptible sleep on wait channel
1179 		 * "nfsreq".
1180 		 */
1181 		if (args.sotype == SOCK_DGRAM && nmp->nm_sotype == SOCK_STREAM)
1182 			tprintf(td->td_proc, LOG_WARNING,
1183 	"Warning: mount -u that changes TCP->UDP can result in hung threads\n");
1184 
1185 		/*
1186 		 * When doing an update, we can't change version,
1187 		 * security, switch lockd strategies, change cookie
1188 		 * translation or switch oneopenown.
1189 		 */
1190 		args.flags = (args.flags &
1191 		    ~(NFSMNT_NFSV3 |
1192 		      NFSMNT_NFSV4 |
1193 		      NFSMNT_KERB |
1194 		      NFSMNT_INTEGRITY |
1195 		      NFSMNT_PRIVACY |
1196 		      NFSMNT_ONEOPENOWN |
1197 		      NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) |
1198 		    (nmp->nm_flag &
1199 			(NFSMNT_NFSV3 |
1200 			 NFSMNT_NFSV4 |
1201 			 NFSMNT_KERB |
1202 			 NFSMNT_INTEGRITY |
1203 			 NFSMNT_PRIVACY |
1204 			 NFSMNT_ONEOPENOWN |
1205 			 NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/));
1206 		nfs_decode_args(mp, nmp, &args, NULL, td->td_ucred, td);
1207 		goto out;
1208 	}
1209 
1210 	/*
1211 	 * Make the nfs_ip_paranoia sysctl serve as the default connection
1212 	 * or no-connection mode for those protocols that support
1213 	 * no-connection mode (the flag will be cleared later for protocols
1214 	 * that do not support no-connection mode).  This will allow a client
1215 	 * to receive replies from a different IP then the request was
1216 	 * sent to.  Note: default value for nfs_ip_paranoia is 1 (paranoid),
1217 	 * not 0.
1218 	 */
1219 	if (nfs_ip_paranoia == 0)
1220 		args.flags |= NFSMNT_NOCONN;
1221 
1222 	if (has_nfs_args_opt != 0) {
1223 		/*
1224 		 * In the 'nfs_args' case, the pointers in the args
1225 		 * structure are in userland - we copy them in here.
1226 		 */
1227 		if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) {
1228 			vfs_mount_error(mp, "Bad file handle");
1229 			error = EINVAL;
1230 			goto out;
1231 		}
1232 		error = copyin((caddr_t)args.fh, (caddr_t)nfh,
1233 		    args.fhsize);
1234 		if (error != 0)
1235 			goto out;
1236 		error = copyinstr(args.hostname, hst, MNAMELEN - 1, &hstlen);
1237 		if (error != 0)
1238 			goto out;
1239 		bzero(&hst[hstlen], MNAMELEN - hstlen);
1240 		args.hostname = hst;
1241 		/* getsockaddr() call must be after above copyin() calls */
1242 		error = getsockaddr(&nam, (caddr_t)args.addr,
1243 		    args.addrlen);
1244 		if (error != 0)
1245 			goto out;
1246 	} else if (nfs_mount_parse_from(mp->mnt_optnew,
1247 	    &args.hostname, (struct sockaddr_in **)&nam, dirpath,
1248 	    sizeof(dirpath), &dirlen) == 0) {
1249 		has_nfs_from_opt = 1;
1250 		bcopy(args.hostname, hst, MNAMELEN);
1251 		hst[MNAMELEN - 1] = '\0';
1252 
1253 		/*
1254 		 * This only works with NFSv4 for now.
1255 		 */
1256 		args.fhsize = 0;
1257 		args.flags |= NFSMNT_NFSV4;
1258 		args.sotype = SOCK_STREAM;
1259 	} else {
1260 		if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
1261 		    &args.fhsize) == 0) {
1262 			if (args.fhsize < 0 || args.fhsize > NFSX_FHMAX) {
1263 				vfs_mount_error(mp, "Bad file handle");
1264 				error = EINVAL;
1265 				goto out;
1266 			}
1267 			bcopy(args.fh, nfh, args.fhsize);
1268 		} else {
1269 			args.fhsize = 0;
1270 		}
1271 		(void) vfs_getopt(mp->mnt_optnew, "hostname",
1272 		    (void **)&args.hostname, &len);
1273 		if (args.hostname == NULL) {
1274 			vfs_mount_error(mp, "Invalid hostname");
1275 			error = EINVAL;
1276 			goto out;
1277 		}
1278 		if (len >= MNAMELEN) {
1279 			vfs_mount_error(mp, "Hostname too long");
1280 			error = EINVAL;
1281 			goto out;
1282 		}
1283 		bcopy(args.hostname, hst, len);
1284 		hst[len] = '\0';
1285 	}
1286 
1287 	if (vfs_getopt(mp->mnt_optnew, "principal", (void **)&name, NULL) == 0)
1288 		strlcpy(srvkrbname, name, sizeof (srvkrbname));
1289 	else {
1290 		snprintf(srvkrbname, sizeof (srvkrbname), "nfs@%s", hst);
1291 		cp = strchr(srvkrbname, ':');
1292 		if (cp != NULL)
1293 			*cp = '\0';
1294 	}
1295 	srvkrbnamelen = strlen(srvkrbname);
1296 
1297 	if (vfs_getopt(mp->mnt_optnew, "gssname", (void **)&name, NULL) == 0)
1298 		strlcpy(krbname, name, sizeof (krbname));
1299 	else
1300 		krbname[0] = '\0';
1301 	krbnamelen = strlen(krbname);
1302 
1303 	if (has_nfs_from_opt == 0) {
1304 		if (vfs_getopt(mp->mnt_optnew,
1305 		    "dirpath", (void **)&name, NULL) == 0)
1306 			strlcpy(dirpath, name, sizeof (dirpath));
1307 		else
1308 			dirpath[0] = '\0';
1309 		dirlen = strlen(dirpath);
1310 	}
1311 
1312 	if (has_nfs_args_opt == 0 && has_nfs_from_opt == 0) {
1313 		if (vfs_getopt(mp->mnt_optnew, "addr",
1314 		    (void **)&args.addr, &args.addrlen) == 0) {
1315 			if (args.addrlen > SOCK_MAXADDRLEN) {
1316 				error = ENAMETOOLONG;
1317 				goto out;
1318 			}
1319 			nam = malloc(args.addrlen, M_SONAME, M_WAITOK);
1320 			bcopy(args.addr, nam, args.addrlen);
1321 			nam->sa_len = args.addrlen;
1322 		} else {
1323 			vfs_mount_error(mp, "No server address");
1324 			error = EINVAL;
1325 			goto out;
1326 		}
1327 	}
1328 
1329 	args.fh = nfh;
1330 	error = mountnfs(&args, mp, nam, hst, krbname, krbnamelen, dirpath,
1331 	    dirlen, srvkrbname, srvkrbnamelen, &vp, td->td_ucred, td,
1332 	    nametimeo, negnametimeo, minvers);
1333 out:
1334 	if (!error) {
1335 		MNT_ILOCK(mp);
1336 		mp->mnt_kern_flag |= MNTK_LOOKUP_SHARED | MNTK_NO_IOPF |
1337 		    MNTK_USES_BCACHE;
1338 		if ((VFSTONFS(mp)->nm_flag & NFSMNT_NFSV4) != 0)
1339 			mp->mnt_kern_flag |= MNTK_NULL_NOCACHE;
1340 		MNT_IUNLOCK(mp);
1341 	}
1342 	free(hst, M_TEMP);
1343 	return (error);
1344 }
1345 
1346 
1347 /*
1348  * VFS Operations.
1349  *
1350  * mount system call
1351  * It seems a bit dumb to copyinstr() the host and path here and then
1352  * bcopy() them in mountnfs(), but I wanted to detect errors before
1353  * doing the getsockaddr() call because getsockaddr() allocates an mbuf and
1354  * an error after that means that I have to release the mbuf.
1355  */
1356 /* ARGSUSED */
1357 static int
nfs_cmount(struct mntarg * ma,void * data,uint64_t flags)1358 nfs_cmount(struct mntarg *ma, void *data, uint64_t flags)
1359 {
1360 	int error;
1361 	struct nfs_args args;
1362 
1363 	error = copyin(data, &args, sizeof (struct nfs_args));
1364 	if (error)
1365 		return error;
1366 
1367 	ma = mount_arg(ma, "nfs_args", &args, sizeof args);
1368 
1369 	error = kernel_mount(ma, flags);
1370 	return (error);
1371 }
1372 
1373 /*
1374  * Common code for mount and mountroot
1375  */
1376 static int
mountnfs(struct nfs_args * argp,struct mount * mp,struct sockaddr * nam,char * hst,u_char * krbname,int krbnamelen,u_char * dirpath,int dirlen,u_char * srvkrbname,int srvkrbnamelen,struct vnode ** vpp,struct ucred * cred,struct thread * td,int nametimeo,int negnametimeo,int minvers)1377 mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
1378     char *hst, u_char *krbname, int krbnamelen, u_char *dirpath, int dirlen,
1379     u_char *srvkrbname, int srvkrbnamelen, struct vnode **vpp,
1380     struct ucred *cred, struct thread *td, int nametimeo, int negnametimeo,
1381     int minvers)
1382 {
1383 	struct nfsmount *nmp;
1384 	struct nfsnode *np;
1385 	int error, trycnt, ret;
1386 	struct nfsvattr nfsva;
1387 	struct nfsclclient *clp;
1388 	struct nfsclds *dsp, *tdsp;
1389 	uint32_t lease;
1390 	static u_int64_t clval = 0;
1391 
1392 	NFSCL_DEBUG(3, "in mnt\n");
1393 	clp = NULL;
1394 	if (mp->mnt_flag & MNT_UPDATE) {
1395 		nmp = VFSTONFS(mp);
1396 		printf("%s: MNT_UPDATE is no longer handled here\n", __func__);
1397 		free(nam, M_SONAME);
1398 		return (0);
1399 	} else {
1400 		nmp = malloc(sizeof (struct nfsmount) +
1401 		    krbnamelen + dirlen + srvkrbnamelen + 2,
1402 		    M_NEWNFSMNT, M_WAITOK | M_ZERO);
1403 		TAILQ_INIT(&nmp->nm_bufq);
1404 		TAILQ_INIT(&nmp->nm_sess);
1405 		if (clval == 0)
1406 			clval = (u_int64_t)nfsboottime.tv_sec;
1407 		nmp->nm_clval = clval++;
1408 		nmp->nm_krbnamelen = krbnamelen;
1409 		nmp->nm_dirpathlen = dirlen;
1410 		nmp->nm_srvkrbnamelen = srvkrbnamelen;
1411 		if (td->td_ucred->cr_uid != (uid_t)0) {
1412 			/*
1413 			 * nm_uid is used to get KerberosV credentials for
1414 			 * the nfsv4 state handling operations if there is
1415 			 * no host based principal set. Use the uid of
1416 			 * this user if not root, since they are doing the
1417 			 * mount. I don't think setting this for root will
1418 			 * work, since root normally does not have user
1419 			 * credentials in a credentials cache.
1420 			 */
1421 			nmp->nm_uid = td->td_ucred->cr_uid;
1422 		} else {
1423 			/*
1424 			 * Just set to -1, so it won't be used.
1425 			 */
1426 			nmp->nm_uid = (uid_t)-1;
1427 		}
1428 
1429 		/* Copy and null terminate all the names */
1430 		if (nmp->nm_krbnamelen > 0) {
1431 			bcopy(krbname, nmp->nm_krbname, nmp->nm_krbnamelen);
1432 			nmp->nm_name[nmp->nm_krbnamelen] = '\0';
1433 		}
1434 		if (nmp->nm_dirpathlen > 0) {
1435 			bcopy(dirpath, NFSMNT_DIRPATH(nmp),
1436 			    nmp->nm_dirpathlen);
1437 			nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1438 			    + 1] = '\0';
1439 		}
1440 		if (nmp->nm_srvkrbnamelen > 0) {
1441 			bcopy(srvkrbname, NFSMNT_SRVKRBNAME(nmp),
1442 			    nmp->nm_srvkrbnamelen);
1443 			nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1444 			    + nmp->nm_srvkrbnamelen + 2] = '\0';
1445 		}
1446 		nmp->nm_sockreq.nr_cred = crhold(cred);
1447 		mtx_init(&nmp->nm_sockreq.nr_mtx, "nfssock", NULL, MTX_DEF);
1448 		mp->mnt_data = nmp;
1449 		nmp->nm_getinfo = nfs_getnlminfo;
1450 		nmp->nm_vinvalbuf = ncl_vinvalbuf;
1451 	}
1452 	vfs_getnewfsid(mp);
1453 	nmp->nm_mountp = mp;
1454 	mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF | MTX_DUPOK);
1455 
1456 	/*
1457 	 * Since nfs_decode_args() might optionally set them, these
1458 	 * need to be set to defaults before the call, so that the
1459 	 * optional settings aren't overwritten.
1460 	 */
1461 	nmp->nm_nametimeo = nametimeo;
1462 	nmp->nm_negnametimeo = negnametimeo;
1463 	nmp->nm_timeo = NFS_TIMEO;
1464 	nmp->nm_retry = NFS_RETRANS;
1465 	nmp->nm_readahead = NFS_DEFRAHEAD;
1466 
1467 	/* This is empirical approximation of sqrt(hibufspace) * 256. */
1468 	nmp->nm_wcommitsize = NFS_MAXBSIZE / 256;
1469 	while ((long)nmp->nm_wcommitsize * nmp->nm_wcommitsize < hibufspace)
1470 		nmp->nm_wcommitsize *= 2;
1471 	nmp->nm_wcommitsize *= 256;
1472 
1473 	if ((argp->flags & NFSMNT_NFSV4) != 0)
1474 		nmp->nm_minorvers = minvers;
1475 	else
1476 		nmp->nm_minorvers = 0;
1477 
1478 	nfs_decode_args(mp, nmp, argp, hst, cred, td);
1479 
1480 	/*
1481 	 * V2 can only handle 32 bit filesizes.  A 4GB-1 limit may be too
1482 	 * high, depending on whether we end up with negative offsets in
1483 	 * the client or server somewhere.  2GB-1 may be safer.
1484 	 *
1485 	 * For V3, ncl_fsinfo will adjust this as necessary.  Assume maximum
1486 	 * that we can handle until we find out otherwise.
1487 	 */
1488 	if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0)
1489 		nmp->nm_maxfilesize = 0xffffffffLL;
1490 	else
1491 		nmp->nm_maxfilesize = OFF_MAX;
1492 
1493 	if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
1494 		nmp->nm_wsize = NFS_WSIZE;
1495 		nmp->nm_rsize = NFS_RSIZE;
1496 		nmp->nm_readdirsize = NFS_READDIRSIZE;
1497 	}
1498 	nmp->nm_numgrps = NFS_MAXGRPS;
1499 	nmp->nm_tprintf_delay = nfs_tprintf_delay;
1500 	if (nmp->nm_tprintf_delay < 0)
1501 		nmp->nm_tprintf_delay = 0;
1502 	nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
1503 	if (nmp->nm_tprintf_initial_delay < 0)
1504 		nmp->nm_tprintf_initial_delay = 0;
1505 	nmp->nm_fhsize = argp->fhsize;
1506 	if (nmp->nm_fhsize > 0)
1507 		bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
1508 	bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
1509 	nmp->nm_nam = nam;
1510 	/* Set up the sockets and per-host congestion */
1511 	nmp->nm_sotype = argp->sotype;
1512 	nmp->nm_soproto = argp->proto;
1513 	nmp->nm_sockreq.nr_prog = NFS_PROG;
1514 	if ((argp->flags & NFSMNT_NFSV4))
1515 		nmp->nm_sockreq.nr_vers = NFS_VER4;
1516 	else if ((argp->flags & NFSMNT_NFSV3))
1517 		nmp->nm_sockreq.nr_vers = NFS_VER3;
1518 	else
1519 		nmp->nm_sockreq.nr_vers = NFS_VER2;
1520 
1521 
1522 	if ((error = newnfs_connect(nmp, &nmp->nm_sockreq, cred, td, 0)))
1523 		goto bad;
1524 	/* For NFSv4.1, get the clientid now. */
1525 	if (nmp->nm_minorvers > 0) {
1526 		NFSCL_DEBUG(3, "at getcl\n");
1527 		error = nfscl_getcl(mp, cred, td, 0, true, &clp);
1528 		NFSCL_DEBUG(3, "aft getcl=%d\n", error);
1529 		if (error != 0)
1530 			goto bad;
1531 	}
1532 
1533 	if (nmp->nm_fhsize == 0 && (nmp->nm_flag & NFSMNT_NFSV4) &&
1534 	    nmp->nm_dirpathlen > 0) {
1535 		NFSCL_DEBUG(3, "in dirp\n");
1536 		/*
1537 		 * If the fhsize on the mount point == 0 for V4, the mount
1538 		 * path needs to be looked up.
1539 		 */
1540 		trycnt = 3;
1541 		do {
1542 			error = nfsrpc_getdirpath(nmp, NFSMNT_DIRPATH(nmp),
1543 			    cred, td);
1544 			NFSCL_DEBUG(3, "aft dirp=%d\n", error);
1545 			if (error)
1546 				(void) nfs_catnap(PZERO, error, "nfsgetdirp");
1547 		} while (error && --trycnt > 0);
1548 		if (error)
1549 			goto bad;
1550 	}
1551 
1552 	/*
1553 	 * A reference count is needed on the nfsnode representing the
1554 	 * remote root.  If this object is not persistent, then backward
1555 	 * traversals of the mount point (i.e. "..") will not work if
1556 	 * the nfsnode gets flushed out of the cache. Ufs does not have
1557 	 * this problem, because one can identify root inodes by their
1558 	 * number == UFS_ROOTINO (2).
1559 	 */
1560 	if (nmp->nm_fhsize > 0) {
1561 		/*
1562 		 * Set f_iosize to NFS_DIRBLKSIZ so that bo_bsize gets set
1563 		 * non-zero for the root vnode. f_iosize will be set correctly
1564 		 * by nfs_statfs() before any I/O occurs.
1565 		 */
1566 		mp->mnt_stat.f_iosize = NFS_DIRBLKSIZ;
1567 		error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np,
1568 		    LK_EXCLUSIVE);
1569 		if (error)
1570 			goto bad;
1571 		*vpp = NFSTOV(np);
1572 
1573 		/*
1574 		 * Get file attributes and transfer parameters for the
1575 		 * mountpoint.  This has the side effect of filling in
1576 		 * (*vpp)->v_type with the correct value.
1577 		 */
1578 		ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
1579 		    cred, td, &nfsva, NULL, &lease);
1580 		if (ret) {
1581 			/*
1582 			 * Just set default values to get things going.
1583 			 */
1584 			NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
1585 			nfsva.na_vattr.va_type = VDIR;
1586 			nfsva.na_vattr.va_mode = 0777;
1587 			nfsva.na_vattr.va_nlink = 100;
1588 			nfsva.na_vattr.va_uid = (uid_t)0;
1589 			nfsva.na_vattr.va_gid = (gid_t)0;
1590 			nfsva.na_vattr.va_fileid = 2;
1591 			nfsva.na_vattr.va_gen = 1;
1592 			nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
1593 			nfsva.na_vattr.va_size = 512 * 1024;
1594 			lease = 60;
1595 		}
1596 		(void) nfscl_loadattrcache(vpp, &nfsva, NULL, NULL, 0, 1);
1597 		if (nmp->nm_minorvers > 0) {
1598 			NFSCL_DEBUG(3, "lease=%d\n", (int)lease);
1599 			NFSLOCKCLSTATE();
1600 			clp->nfsc_renew = NFSCL_RENEW(lease);
1601 			clp->nfsc_expire = NFSD_MONOSEC + clp->nfsc_renew;
1602 			clp->nfsc_clientidrev++;
1603 			if (clp->nfsc_clientidrev == 0)
1604 				clp->nfsc_clientidrev++;
1605 			NFSUNLOCKCLSTATE();
1606 			/*
1607 			 * Mount will succeed, so the renew thread can be
1608 			 * started now.
1609 			 */
1610 			nfscl_start_renewthread(clp);
1611 			nfscl_clientrelease(clp);
1612 		}
1613 		if (argp->flags & NFSMNT_NFSV3)
1614 			ncl_fsinfo(nmp, *vpp, cred, td);
1615 
1616 		/* Mark if the mount point supports NFSv4 ACLs. */
1617 		if ((argp->flags & NFSMNT_NFSV4) != 0 && nfsrv_useacl != 0 &&
1618 		    ret == 0 &&
1619 		    NFSISSET_ATTRBIT(&nfsva.na_suppattr, NFSATTRBIT_ACL)) {
1620 			MNT_ILOCK(mp);
1621 			mp->mnt_flag |= MNT_NFS4ACLS;
1622 			MNT_IUNLOCK(mp);
1623 		}
1624 
1625 		/*
1626 		 * Lose the lock but keep the ref.
1627 		 */
1628 		NFSVOPUNLOCK(*vpp, 0);
1629 		return (0);
1630 	}
1631 	error = EIO;
1632 
1633 bad:
1634 	if (clp != NULL)
1635 		nfscl_clientrelease(clp);
1636 	newnfs_disconnect(&nmp->nm_sockreq);
1637 	crfree(nmp->nm_sockreq.nr_cred);
1638 	if (nmp->nm_sockreq.nr_auth != NULL)
1639 		AUTH_DESTROY(nmp->nm_sockreq.nr_auth);
1640 	mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1641 	mtx_destroy(&nmp->nm_mtx);
1642 	if (nmp->nm_clp != NULL) {
1643 		NFSLOCKCLSTATE();
1644 		LIST_REMOVE(nmp->nm_clp, nfsc_list);
1645 		NFSUNLOCKCLSTATE();
1646 		free(nmp->nm_clp, M_NFSCLCLIENT);
1647 	}
1648 	TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp) {
1649 		if (dsp != TAILQ_FIRST(&nmp->nm_sess) &&
1650 		    dsp->nfsclds_sockp != NULL)
1651 			newnfs_disconnect(dsp->nfsclds_sockp);
1652 		nfscl_freenfsclds(dsp);
1653 	}
1654 	free(nmp, M_NEWNFSMNT);
1655 	free(nam, M_SONAME);
1656 	return (error);
1657 }
1658 
1659 /*
1660  * unmount system call
1661  */
1662 static int
nfs_unmount(struct mount * mp,int mntflags)1663 nfs_unmount(struct mount *mp, int mntflags)
1664 {
1665 	struct thread *td;
1666 	struct nfsmount *nmp;
1667 	int error, flags = 0, i, trycnt = 0;
1668 	struct nfsclds *dsp, *tdsp;
1669 	struct nfscldeleg *dp, *ndp;
1670 	struct nfscldeleghead dh;
1671 
1672 	td = curthread;
1673 	TAILQ_INIT(&dh);
1674 
1675 	if (mntflags & MNT_FORCE)
1676 		flags |= FORCECLOSE;
1677 	nmp = VFSTONFS(mp);
1678 	error = 0;
1679 	/*
1680 	 * Goes something like this..
1681 	 * - Call vflush() to clear out vnodes for this filesystem
1682 	 * - Close the socket
1683 	 * - Free up the data structures
1684 	 */
1685 	/* In the forced case, cancel any outstanding requests. */
1686 	if (mntflags & MNT_FORCE) {
1687 		NFSDDSLOCK();
1688 		if (nfsv4_findmirror(nmp) != NULL)
1689 			error = ENXIO;
1690 		NFSDDSUNLOCK();
1691 		if (error)
1692 			goto out;
1693 		error = newnfs_nmcancelreqs(nmp);
1694 		if (error)
1695 			goto out;
1696 		/* For a forced close, get rid of the renew thread now */
1697 		nfscl_umount(nmp, td, &dh);
1698 	}
1699 	/* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
1700 	do {
1701 		error = vflush(mp, 1, flags, td);
1702 		if ((mntflags & MNT_FORCE) && error != 0 && ++trycnt < 30)
1703 			(void) nfs_catnap(PSOCK, error, "newndm");
1704 	} while ((mntflags & MNT_FORCE) && error != 0 && trycnt < 30);
1705 	if (error)
1706 		goto out;
1707 
1708 	/*
1709 	 * We are now committed to the unmount.
1710 	 */
1711 	if ((mntflags & MNT_FORCE) == 0)
1712 		nfscl_umount(nmp, td, NULL);
1713 	else {
1714 		mtx_lock(&nmp->nm_mtx);
1715 		nmp->nm_privflag |= NFSMNTP_FORCEDISM;
1716 		mtx_unlock(&nmp->nm_mtx);
1717 	}
1718 	/* Make sure no nfsiods are assigned to this mount. */
1719 	NFSLOCKIOD();
1720 	for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
1721 		if (ncl_iodmount[i] == nmp) {
1722 			ncl_iodwant[i] = NFSIOD_AVAILABLE;
1723 			ncl_iodmount[i] = NULL;
1724 		}
1725 	NFSUNLOCKIOD();
1726 
1727 	/*
1728 	 * We can now set mnt_data to NULL and wait for
1729 	 * nfssvc(NFSSVC_FORCEDISM) to complete.
1730 	 */
1731 	mtx_lock(&mountlist_mtx);
1732 	mtx_lock(&nmp->nm_mtx);
1733 	mp->mnt_data = NULL;
1734 	mtx_unlock(&mountlist_mtx);
1735 	while ((nmp->nm_privflag & NFSMNTP_CANCELRPCS) != 0)
1736 		msleep(nmp, &nmp->nm_mtx, PVFS, "nfsfdism", 0);
1737 	mtx_unlock(&nmp->nm_mtx);
1738 
1739 	newnfs_disconnect(&nmp->nm_sockreq);
1740 	crfree(nmp->nm_sockreq.nr_cred);
1741 	free(nmp->nm_nam, M_SONAME);
1742 	if (nmp->nm_sockreq.nr_auth != NULL)
1743 		AUTH_DESTROY(nmp->nm_sockreq.nr_auth);
1744 	mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1745 	mtx_destroy(&nmp->nm_mtx);
1746 	TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp) {
1747 		if (dsp != TAILQ_FIRST(&nmp->nm_sess) &&
1748 		    dsp->nfsclds_sockp != NULL)
1749 			newnfs_disconnect(dsp->nfsclds_sockp);
1750 		nfscl_freenfsclds(dsp);
1751 	}
1752 	free(nmp, M_NEWNFSMNT);
1753 
1754 	/* Free up the delegation structures for forced dismounts. */
1755 	TAILQ_FOREACH_SAFE(dp, &dh, nfsdl_list, ndp) {
1756 		TAILQ_REMOVE(&dh, dp, nfsdl_list);
1757 		free(dp, M_NFSCLDELEG);
1758 	}
1759 out:
1760 	return (error);
1761 }
1762 
1763 /*
1764  * Return root of a filesystem
1765  */
1766 static int
nfs_root(struct mount * mp,int flags,struct vnode ** vpp)1767 nfs_root(struct mount *mp, int flags, struct vnode **vpp)
1768 {
1769 	struct vnode *vp;
1770 	struct nfsmount *nmp;
1771 	struct nfsnode *np;
1772 	int error;
1773 
1774 	nmp = VFSTONFS(mp);
1775 	error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, flags);
1776 	if (error)
1777 		return error;
1778 	vp = NFSTOV(np);
1779 	/*
1780 	 * Get transfer parameters and attributes for root vnode once.
1781 	 */
1782 	mtx_lock(&nmp->nm_mtx);
1783 	if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
1784 		mtx_unlock(&nmp->nm_mtx);
1785 		ncl_fsinfo(nmp, vp, curthread->td_ucred, curthread);
1786 	} else
1787 		mtx_unlock(&nmp->nm_mtx);
1788 	if (vp->v_type == VNON)
1789 	    vp->v_type = VDIR;
1790 	vp->v_vflag |= VV_ROOT;
1791 	*vpp = vp;
1792 	return (0);
1793 }
1794 
1795 /*
1796  * Flush out the buffer cache
1797  */
1798 /* ARGSUSED */
1799 static int
nfs_sync(struct mount * mp,int waitfor)1800 nfs_sync(struct mount *mp, int waitfor)
1801 {
1802 	struct vnode *vp, *mvp;
1803 	struct thread *td;
1804 	int error, allerror = 0;
1805 
1806 	td = curthread;
1807 
1808 	MNT_ILOCK(mp);
1809 	/*
1810 	 * If a forced dismount is in progress, return from here so that
1811 	 * the umount(2) syscall doesn't get stuck in VFS_SYNC() before
1812 	 * calling VFS_UNMOUNT().
1813 	 */
1814 	if (NFSCL_FORCEDISM(mp)) {
1815 		MNT_IUNLOCK(mp);
1816 		return (EBADF);
1817 	}
1818 	MNT_IUNLOCK(mp);
1819 
1820 	/*
1821 	 * Force stale buffer cache information to be flushed.
1822 	 */
1823 loop:
1824 	MNT_VNODE_FOREACH_ALL(vp, mp, mvp) {
1825 		/* XXX Racy bv_cnt check. */
1826 		if (NFSVOPISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
1827 		    waitfor == MNT_LAZY) {
1828 			VI_UNLOCK(vp);
1829 			continue;
1830 		}
1831 		if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
1832 			MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
1833 			goto loop;
1834 		}
1835 		error = VOP_FSYNC(vp, waitfor, td);
1836 		if (error)
1837 			allerror = error;
1838 		NFSVOPUNLOCK(vp, 0);
1839 		vrele(vp);
1840 	}
1841 	return (allerror);
1842 }
1843 
1844 static int
nfs_sysctl(struct mount * mp,fsctlop_t op,struct sysctl_req * req)1845 nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
1846 {
1847 	struct nfsmount *nmp = VFSTONFS(mp);
1848 	struct vfsquery vq;
1849 	int error;
1850 
1851 	bzero(&vq, sizeof(vq));
1852 	switch (op) {
1853 #if 0
1854 	case VFS_CTL_NOLOCKS:
1855 		val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0;
1856  		if (req->oldptr != NULL) {
1857  			error = SYSCTL_OUT(req, &val, sizeof(val));
1858  			if (error)
1859  				return (error);
1860  		}
1861  		if (req->newptr != NULL) {
1862  			error = SYSCTL_IN(req, &val, sizeof(val));
1863  			if (error)
1864  				return (error);
1865 			if (val)
1866 				nmp->nm_flag |= NFSMNT_NOLOCKS;
1867 			else
1868 				nmp->nm_flag &= ~NFSMNT_NOLOCKS;
1869  		}
1870 		break;
1871 #endif
1872 	case VFS_CTL_QUERY:
1873 		mtx_lock(&nmp->nm_mtx);
1874 		if (nmp->nm_state & NFSSTA_TIMEO)
1875 			vq.vq_flags |= VQ_NOTRESP;
1876 		mtx_unlock(&nmp->nm_mtx);
1877 #if 0
1878 		if (!(nmp->nm_flag & NFSMNT_NOLOCKS) &&
1879 		    (nmp->nm_state & NFSSTA_LOCKTIMEO))
1880 			vq.vq_flags |= VQ_NOTRESPLOCK;
1881 #endif
1882 		error = SYSCTL_OUT(req, &vq, sizeof(vq));
1883 		break;
1884  	case VFS_CTL_TIMEO:
1885  		if (req->oldptr != NULL) {
1886  			error = SYSCTL_OUT(req, &nmp->nm_tprintf_initial_delay,
1887  			    sizeof(nmp->nm_tprintf_initial_delay));
1888  			if (error)
1889  				return (error);
1890  		}
1891  		if (req->newptr != NULL) {
1892 			error = vfs_suser(mp, req->td);
1893 			if (error)
1894 				return (error);
1895  			error = SYSCTL_IN(req, &nmp->nm_tprintf_initial_delay,
1896  			    sizeof(nmp->nm_tprintf_initial_delay));
1897  			if (error)
1898  				return (error);
1899  			if (nmp->nm_tprintf_initial_delay < 0)
1900  				nmp->nm_tprintf_initial_delay = 0;
1901  		}
1902 		break;
1903 	default:
1904 		return (ENOTSUP);
1905 	}
1906 	return (0);
1907 }
1908 
1909 /*
1910  * Purge any RPCs in progress, so that they will all return errors.
1911  * This allows dounmount() to continue as far as VFS_UNMOUNT() for a
1912  * forced dismount.
1913  */
1914 static void
nfs_purge(struct mount * mp)1915 nfs_purge(struct mount *mp)
1916 {
1917 	struct nfsmount *nmp = VFSTONFS(mp);
1918 
1919 	newnfs_nmcancelreqs(nmp);
1920 }
1921 
1922 /*
1923  * Extract the information needed by the nlm from the nfs vnode.
1924  */
1925 static void
nfs_getnlminfo(struct vnode * vp,uint8_t * fhp,size_t * fhlenp,struct sockaddr_storage * sp,int * is_v3p,off_t * sizep,struct timeval * timeop)1926 nfs_getnlminfo(struct vnode *vp, uint8_t *fhp, size_t *fhlenp,
1927     struct sockaddr_storage *sp, int *is_v3p, off_t *sizep,
1928     struct timeval *timeop)
1929 {
1930 	struct nfsmount *nmp;
1931 	struct nfsnode *np = VTONFS(vp);
1932 
1933 	nmp = VFSTONFS(vp->v_mount);
1934 	if (fhlenp != NULL)
1935 		*fhlenp = (size_t)np->n_fhp->nfh_len;
1936 	if (fhp != NULL)
1937 		bcopy(np->n_fhp->nfh_fh, fhp, np->n_fhp->nfh_len);
1938 	if (sp != NULL)
1939 		bcopy(nmp->nm_nam, sp, min(nmp->nm_nam->sa_len, sizeof(*sp)));
1940 	if (is_v3p != NULL)
1941 		*is_v3p = NFS_ISV3(vp);
1942 	if (sizep != NULL)
1943 		*sizep = np->n_size;
1944 	if (timeop != NULL) {
1945 		timeop->tv_sec = nmp->nm_timeo / NFS_HZ;
1946 		timeop->tv_usec = (nmp->nm_timeo % NFS_HZ) * (1000000 / NFS_HZ);
1947 	}
1948 }
1949 
1950 /*
1951  * This function prints out an option name, based on the conditional
1952  * argument.
1953  */
nfscl_printopt(struct nfsmount * nmp,int testval,char * opt,char ** buf,size_t * blen)1954 static __inline void nfscl_printopt(struct nfsmount *nmp, int testval,
1955     char *opt, char **buf, size_t *blen)
1956 {
1957 	int len;
1958 
1959 	if (testval != 0 && *blen > strlen(opt)) {
1960 		len = snprintf(*buf, *blen, "%s", opt);
1961 		if (len != strlen(opt))
1962 			printf("EEK!!\n");
1963 		*buf += len;
1964 		*blen -= len;
1965 	}
1966 }
1967 
1968 /*
1969  * This function printf out an options integer value.
1970  */
nfscl_printoptval(struct nfsmount * nmp,int optval,char * opt,char ** buf,size_t * blen)1971 static __inline void nfscl_printoptval(struct nfsmount *nmp, int optval,
1972     char *opt, char **buf, size_t *blen)
1973 {
1974 	int len;
1975 
1976 	if (*blen > strlen(opt) + 1) {
1977 		/* Could result in truncated output string. */
1978 		len = snprintf(*buf, *blen, "%s=%d", opt, optval);
1979 		if (len < *blen) {
1980 			*buf += len;
1981 			*blen -= len;
1982 		}
1983 	}
1984 }
1985 
1986 /*
1987  * Load the option flags and values into the buffer.
1988  */
nfscl_retopts(struct nfsmount * nmp,char * buffer,size_t buflen)1989 void nfscl_retopts(struct nfsmount *nmp, char *buffer, size_t buflen)
1990 {
1991 	char *buf;
1992 	size_t blen;
1993 
1994 	buf = buffer;
1995 	blen = buflen;
1996 	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV4) != 0, "nfsv4", &buf,
1997 	    &blen);
1998 	if ((nmp->nm_flag & NFSMNT_NFSV4) != 0) {
1999 		nfscl_printoptval(nmp, nmp->nm_minorvers, ",minorversion", &buf,
2000 		    &blen);
2001 		nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_PNFS) != 0, ",pnfs",
2002 		    &buf, &blen);
2003 		nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_ONEOPENOWN) != 0 &&
2004 		    nmp->nm_minorvers > 0, ",oneopenown", &buf, &blen);
2005 	}
2006 	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV3) != 0, "nfsv3", &buf,
2007 	    &blen);
2008 	nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0,
2009 	    "nfsv2", &buf, &blen);
2010 	nfscl_printopt(nmp, nmp->nm_sotype == SOCK_STREAM, ",tcp", &buf, &blen);
2011 	nfscl_printopt(nmp, nmp->nm_sotype != SOCK_STREAM, ",udp", &buf, &blen);
2012 	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RESVPORT) != 0, ",resvport",
2013 	    &buf, &blen);
2014 	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCONN) != 0, ",noconn",
2015 	    &buf, &blen);
2016 	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) == 0, ",hard", &buf,
2017 	    &blen);
2018 	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) != 0, ",soft", &buf,
2019 	    &blen);
2020 	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_INT) != 0, ",intr", &buf,
2021 	    &blen);
2022 	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) == 0, ",cto", &buf,
2023 	    &blen);
2024 	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) != 0, ",nocto", &buf,
2025 	    &blen);
2026 	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NONCONTIGWR) != 0,
2027 	    ",noncontigwr", &buf, &blen);
2028 	nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) ==
2029 	    0, ",lockd", &buf, &blen);
2030 	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOLOCKD) != 0, ",nolockd",
2031 	    &buf, &blen);
2032 	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RDIRPLUS) != 0, ",rdirplus",
2033 	    &buf, &blen);
2034 	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_KERB) == 0, ",sec=sys",
2035 	    &buf, &blen);
2036 	nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
2037 	    NFSMNT_PRIVACY)) == NFSMNT_KERB, ",sec=krb5", &buf, &blen);
2038 	nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
2039 	    NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_INTEGRITY), ",sec=krb5i",
2040 	    &buf, &blen);
2041 	nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
2042 	    NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_PRIVACY), ",sec=krb5p",
2043 	    &buf, &blen);
2044 	nfscl_printoptval(nmp, nmp->nm_acdirmin, ",acdirmin", &buf, &blen);
2045 	nfscl_printoptval(nmp, nmp->nm_acdirmax, ",acdirmax", &buf, &blen);
2046 	nfscl_printoptval(nmp, nmp->nm_acregmin, ",acregmin", &buf, &blen);
2047 	nfscl_printoptval(nmp, nmp->nm_acregmax, ",acregmax", &buf, &blen);
2048 	nfscl_printoptval(nmp, nmp->nm_nametimeo, ",nametimeo", &buf, &blen);
2049 	nfscl_printoptval(nmp, nmp->nm_negnametimeo, ",negnametimeo", &buf,
2050 	    &blen);
2051 	nfscl_printoptval(nmp, nmp->nm_rsize, ",rsize", &buf, &blen);
2052 	nfscl_printoptval(nmp, nmp->nm_wsize, ",wsize", &buf, &blen);
2053 	nfscl_printoptval(nmp, nmp->nm_readdirsize, ",readdirsize", &buf,
2054 	    &blen);
2055 	nfscl_printoptval(nmp, nmp->nm_readahead, ",readahead", &buf, &blen);
2056 	nfscl_printoptval(nmp, nmp->nm_wcommitsize, ",wcommitsize", &buf,
2057 	    &blen);
2058 	nfscl_printoptval(nmp, nmp->nm_timeo, ",timeout", &buf, &blen);
2059 	nfscl_printoptval(nmp, nmp->nm_retry, ",retrans", &buf, &blen);
2060 }
2061 
2062