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