Author: rodrigc
Date: Mon Mar 23 08:33:19 2009
New Revision: 190315
URL: http://svn.freebsd.org/changeset/base/190315

Log:
  MFC 183005, 187812:
  
  Add code to parse mount options passed as individual
  items of the nmount() iovec.

Modified:
  stable/7/sys/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)
  stable/7/sys/dev/ath/ath_hal/   (props changed)
  stable/7/sys/dev/cxgb/   (props changed)
  stable/7/sys/nfsclient/nfs_vfsops.c

Modified: stable/7/sys/nfsclient/nfs_vfsops.c
==============================================================================
--- stable/7/sys/nfsclient/nfs_vfsops.c Mon Mar 23 05:46:28 2009        
(r190314)
+++ stable/7/sys/nfsclient/nfs_vfsops.c Mon Mar 23 08:33:19 2009        
(r190315)
@@ -717,7 +717,15 @@ nfs_decode_args(struct mount *mp, struct
        }
 }
 
-static const char *nfs_opts[] = { "from", "nfs_args", NULL };
+static const char *nfs_opts[] = { "from", "nfs_args",
+    "noatime", "noexec", "suiddir", "nosuid", "nosymfollow", "union",
+    "noclusterr", "noclusterw", "multilabel", "acls", "force", "update",
+    "async", "dumbtimer", "noconn", "nolockd", "intr", "rdirplus", "resvport",
+    "readdirsize", "soft", "hard", "mntudp", "tcp", "udp", "wsize", "rsize",
+    "retrans", "acregmin", "acregmax", "acdirmin", "acdirmax", 
+    "deadthresh", "hostname", "timeout", "addr", "fh", "nfsv3",
+    "maxgroups",
+    NULL };
 
 /*
  * VFS Operations.
@@ -732,13 +740,20 @@ static const char *nfs_opts[] = { "from"
 static int
 nfs_mount(struct mount *mp, struct thread *td)
 {
-       int error;
+       int error, ret, has_nfs_args_opt;
+       int has_addr_opt, has_fh_opt, has_hostname_opt;
        struct nfs_args args;
        struct sockaddr *nam;
        struct vnode *vp;
        char hst[MNAMELEN];
        size_t len;
        u_char nfh[NFSX_V3FHMAX];
+       char *opt;
+
+       has_nfs_args_opt = 0;
+       has_addr_opt = 0;
+       has_fh_opt = 0;
+       has_hostname_opt = 0;
 
        if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {
                error = EINVAL;
@@ -750,12 +765,223 @@ nfs_mount(struct mount *mp, struct threa
                goto out;
        }
 
-       error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args, sizeof args);
-       if (error)
-               goto out;
+       /*
+        * The old mount_nfs program passed the struct nfs_args
+        * from userspace to kernel.  The new mount_nfs program
+        * passes string options via nmount() from userspace to kernel
+        * and we populate the struct nfs_args in the kernel.
+        */
+       if (vfs_getopt(mp->mnt_optnew, "nfs_args", NULL, NULL) == 0) {
+               error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args,
+                   sizeof args);
+               if (error)
+                       goto out;
+
+               if (args.version != NFS_ARGSVERSION) {
+                       error = EPROGMISMATCH;
+                       goto out;
+               }
+               has_nfs_args_opt = 1;
+       }
 
-       if (args.version != NFS_ARGSVERSION) {
-               error = EPROGMISMATCH;
+       if (vfs_getopt(mp->mnt_optnew, "dumbtimer", NULL, NULL) == 0)
+               args.flags |= NFSMNT_DUMBTIMR;
+       if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0)
+               args.flags |= NFSMNT_NOCONN;
+       if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0)
+               args.flags |= NFSMNT_NOCONN;
+       if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0)
+               args.flags |= NFSMNT_NOLOCKD;
+       if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0)
+               args.flags &= ~NFSMNT_NOLOCKD;
+       if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0)
+               args.flags |= NFSMNT_INT;
+       if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0)
+               args.flags |= NFSMNT_RDIRPLUS;
+       if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0)
+               args.flags |= NFSMNT_RESVPORT;
+       if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0)
+               args.flags &= ~NFSMNT_RESVPORT;
+       if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0)
+               args.flags |= NFSMNT_SOFT;
+       if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0)
+               args.flags &= ~NFSMNT_SOFT;
+       if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0)
+               args.sotype = SOCK_DGRAM;
+       if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0)
+               args.sotype = SOCK_DGRAM;
+       if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0)
+               args.sotype = SOCK_STREAM;
+       if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0)
+               args.flags |= NFSMNT_NFSV3;
+       if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 
0) {
+               if (opt == NULL) { 
+                       vfs_mount_error(mp, "illegal readdirsize");
+                       error = EINVAL;
+                       goto out;
+               }
+               ret = sscanf(opt, "%d", &args.readdirsize);
+               if (ret != 1 || args.readdirsize <= 0) {
+                       vfs_mount_error(mp, "illegal readdirsize: %s",
+                           opt);
+                       error = EINVAL;
+                       goto out;
+               }
+               args.flags |= NFSMNT_READDIRSIZE;
+       }
+       if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) {
+               if (opt == NULL) { 
+                       vfs_mount_error(mp, "illegal readahead");
+                       error = EINVAL;
+                       goto out;
+               }
+               ret = sscanf(opt, "%d", &args.readahead);
+               if (ret != 1 || args.readahead <= 0) {
+                       vfs_mount_error(mp, "illegal readahead: %s",
+                           opt);
+                       error = EINVAL;
+                       goto out;
+               }
+               args.flags |= NFSMNT_READAHEAD;
+       }
+       if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) {
+               if (opt == NULL) { 
+                       vfs_mount_error(mp, "illegal wsize");
+                       error = EINVAL;
+                       goto out;
+               }
+               ret = sscanf(opt, "%d", &args.wsize);
+               if (ret != 1 || args.wsize <= 0) {
+                       vfs_mount_error(mp, "illegal wsize: %s",
+                           opt);
+                       error = EINVAL;
+                       goto out;
+               }
+               args.flags |= NFSMNT_WSIZE;
+       }
+       if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) {
+               if (opt == NULL) { 
+                       vfs_mount_error(mp, "illegal rsize");
+                       error = EINVAL;
+                       goto out;
+               }
+               ret = sscanf(opt, "%d", &args.rsize);
+               if (ret != 1 || args.rsize <= 0) {
+                       vfs_mount_error(mp, "illegal wsize: %s",
+                           opt);
+                       error = EINVAL;
+                       goto out;
+               }
+               args.flags |= NFSMNT_RSIZE;
+       }
+       if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) {
+               if (opt == NULL) { 
+                       vfs_mount_error(mp, "illegal retrans");
+                       error = EINVAL;
+                       goto out;
+               }
+               ret = sscanf(opt, "%d", &args.retrans);
+               if (ret != 1 || args.retrans <= 0) {
+                       vfs_mount_error(mp, "illegal retrans: %s",
+                           opt);
+                       error = EINVAL;
+                       goto out;
+               }
+               args.flags |= NFSMNT_RETRANS;
+       }
+       if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) {
+               ret = sscanf(opt, "%d", &args.acregmin);
+               if (ret != 1 || args.acregmin < 0) {
+                       vfs_mount_error(mp, "illegal acregmin: %s",
+                           opt);
+                       error = EINVAL;
+                       goto out;
+               }
+               args.flags |= NFSMNT_ACREGMIN;
+       }
+       if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) {
+               ret = sscanf(opt, "%d", &args.acregmax);
+               if (ret != 1 || args.acregmax < 0) {
+                       vfs_mount_error(mp, "illegal acregmax: %s",
+                           opt);
+                       error = EINVAL;
+                       goto out;
+               }
+               args.flags |= NFSMNT_ACREGMAX;
+       }
+       if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) {
+               ret = sscanf(opt, "%d", &args.acdirmin);
+               if (ret != 1 || args.acdirmin < 0) {
+                       vfs_mount_error(mp, "illegal acdirmin: %s",
+                           opt);
+                       error = EINVAL;
+                       goto out;
+               }
+               args.flags |= NFSMNT_ACDIRMIN;
+       }
+       if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) {
+               ret = sscanf(opt, "%d", &args.acdirmax);
+               if (ret != 1 || args.acdirmax < 0) {
+                       vfs_mount_error(mp, "illegal acdirmax: %s",
+                           opt);
+                       error = EINVAL;
+                       goto out;
+               }
+               args.flags |= NFSMNT_ACDIRMAX;
+       }
+       if (vfs_getopt(mp->mnt_optnew, "deadthresh", (void **)&opt, NULL) == 0) 
{
+               ret = sscanf(opt, "%d", &args.deadthresh);
+               if (ret != 1 || args.deadthresh <= 0) {
+                       vfs_mount_error(mp, "illegal deadthresh: %s",
+                           opt);
+                       error = EINVAL;
+                       goto out;
+               }
+               args.flags |= NFSMNT_DEADTHRESH;
+       }
+       if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) {
+               ret = sscanf(opt, "%d", &args.timeo);
+               if (ret != 1 || args.timeo <= 0) {
+                       vfs_mount_error(mp, "illegal timeout: %s",
+                           opt);
+                       error = EINVAL;
+                       goto out;
+               }
+               args.flags |= NFSMNT_TIMEO;
+       }
+       if (vfs_getopt(mp->mnt_optnew, "maxgroups", (void **)&opt, NULL) == 0) {
+               ret = sscanf(opt, "%d", &args.maxgrouplist);
+               if (ret != 1 || args.timeo <= 0) {
+                       vfs_mount_error(mp, "illegal maxgroups: %s",
+                           opt);
+                       error = EINVAL;
+                       goto out;
+               }
+               args.flags |= NFSMNT_MAXGRPS;
+       }
+       if (vfs_getopt(mp->mnt_optnew, "addr", (void **)&args.addr,
+               &args.addrlen) == 0) {
+               has_addr_opt = 1;
+               if (args.addrlen > SOCK_MAXADDRLEN) {
+                       error = ENAMETOOLONG;
+                       goto out;
+               }
+               MALLOC(nam, struct sockaddr *, args.addrlen, M_SONAME,
+                   M_WAITOK);
+               bcopy(args.addr, nam, args.addrlen);
+               nam->sa_len = args.addrlen;
+       }
+       if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
+               &args.fhsize) == 0) {
+               has_fh_opt = 1;
+       }
+       if (vfs_getopt(mp->mnt_optnew, "hostname", (void **)&args.hostname,
+               NULL) == 0) {
+               has_hostname_opt = 1;
+       }
+       if (args.hostname == NULL) {
+               vfs_mount_error(mp, "Invalid hostname");
+               error = EINVAL;
                goto out;
        }
        if (mp->mnt_flag & MNT_UPDATE) {
@@ -788,23 +1014,38 @@ nfs_mount(struct mount *mp, struct threa
         */
        if (nfs_ip_paranoia == 0)
                args.flags |= NFSMNT_NOCONN;
-       if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) {
-               error = EINVAL;
-               goto out;
+
+       if (has_nfs_args_opt) {
+               /*
+                * In the 'nfs_args' case, the pointers in the args
+                * structure are in userland - we copy them in here.
+                */
+               if (!has_fh_opt) {
+                       error = copyin((caddr_t)args.fh, (caddr_t)nfh,
+                           args.fhsize);
+                       if (error) {
+                               goto out;
+                       }
+                       args.fh = nfh;
+               }
+               if (!has_hostname_opt) {
+                       error = copyinstr(args.hostname, hst, MNAMELEN-1, &len);
+                       if (error) {
+                               goto out;
+                       }
+                       bzero(&hst[len], MNAMELEN - len);
+                       args.hostname = hst;
+               }
+               if (!has_addr_opt) {
+                       /* sockargs() call must be after above copyin() calls */
+                       error = getsockaddr(&nam, (caddr_t)args.addr,
+                           args.addrlen);
+                       if (error) {
+                               goto out;
+                       }
+               }
        }
-       error = copyin((caddr_t)args.fh, (caddr_t)nfh, args.fhsize);
-       if (error)
-               goto out;
-       error = copyinstr(args.hostname, hst, MNAMELEN-1, &len);
-       if (error)
-               goto out;
-       bzero(&hst[len], MNAMELEN - len);
-       /* sockargs() call must be after above copyin() calls */
-       error = getsockaddr(&nam, (caddr_t)args.addr, args.addrlen);
-       if (error)
-               goto out;
-       args.fh = nfh;
-       error = mountnfs(&args, mp, nam, hst, &vp, td->td_ucred);
+       error = mountnfs(&args, mp, nam, args.hostname, &vp, td->td_ucred);
 out:
        if (!error) {
                MNT_ILOCK(mp);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to