NFS: Introduce nfs4_validate_mount_options
authorChuck Lever <chuck.lever@oracle.com>
Sun, 1 Jul 2007 16:13:01 +0000 (12:13 -0400)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Wed, 11 Jul 2007 03:40:45 +0000 (23:40 -0400)
Refactor NFSv4 mount processing to break out mount data validation
in the same way it's broken out in the NFSv2/v3 mount path.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
fs/nfs/super.c

index baf75e9..ed3ec44 100644 (file)
@@ -814,6 +814,89 @@ static void nfs4_fill_super(struct super_block *sb)
 }
 
 /*
+ * Validate NFSv4 mount options
+ */
+static int nfs4_validate_mount_data(struct nfs4_mount_data **options,
+                                   const char *dev_name,
+                                   struct sockaddr_in *addr,
+                                   rpc_authflavor_t *authflavour,
+                                   char **hostname,
+                                   char **mntpath,
+                                   char **ip_addr)
+{
+       struct nfs4_mount_data *data = *options;
+       char *c;
+
+       if (data == NULL)
+               goto out_no_data;
+
+       switch (data->version) {
+       case 1:
+               if (data->host_addrlen != sizeof(*addr))
+                       goto out_no_address;
+               if (copy_from_user(addr, data->host_addr, sizeof(*addr)))
+                       return -EFAULT;
+               if (addr->sin_port == 0)
+                       addr->sin_port = htons(NFS_PORT);
+               if (!nfs_verify_server_address((struct sockaddr *) addr))
+                       goto out_no_address;
+
+               switch (data->auth_flavourlen) {
+               case 0:
+                       *authflavour = RPC_AUTH_UNIX;
+                       break;
+               case 1:
+                       if (copy_from_user(authflavour, data->auth_flavours,
+                                          sizeof(*authflavour)))
+                               return -EFAULT;
+                       break;
+               default:
+                       goto out_inval_auth;
+               }
+
+               c = strndup_user(data->hostname.data, NFS4_MAXNAMLEN);
+               if (IS_ERR(c))
+                       return PTR_ERR(c);
+               *hostname = c;
+
+               c = strndup_user(data->mnt_path.data, NFS4_MAXPATHLEN);
+               if (IS_ERR(c))
+                       return PTR_ERR(c);
+               *mntpath = c;
+               dfprintk(MOUNT, "NFS: MNTPATH: '%s'\n", *mntpath);
+
+               c = strndup_user(data->client_addr.data, 16);
+               if (IS_ERR(c))
+                       return PTR_ERR(c);
+               *ip_addr = c;
+
+               break;
+       default:
+               goto out_bad_version;
+       }
+
+       return 0;
+
+out_no_data:
+       dfprintk(MOUNT, "NFS4: mount program didn't pass any mount data\n");
+       return -EINVAL;
+
+out_inval_auth:
+       dfprintk(MOUNT, "NFS4: Invalid number of RPC auth flavours %d\n",
+                data->auth_flavourlen);
+       return -EINVAL;
+
+out_no_address:
+       dfprintk(MOUNT, "NFS4: mount program didn't pass remote address\n");
+       return -EINVAL;
+
+out_bad_version:
+       dfprintk(MOUNT, "NFS4: bad nfs_mount_data version %d\n",
+                data->version);
+       return -EINVAL;
+}
+
+/*
  * Get the superblock for an NFS4 mountpoint
  */
 static int nfs4_get_sb(struct file_system_type *fs_type,
@@ -826,68 +909,14 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
        rpc_authflavor_t authflavour;
        struct nfs_fh mntfh;
        struct dentry *mntroot;
-       char *p, *mntpath = NULL, *hostname = NULL, *ip_addr = NULL;
+       char *mntpath = NULL, *hostname = NULL, *ip_addr = NULL;
        int error;
 
-       if (data == NULL) {
-               dprintk("%s: missing data argument\n", __FUNCTION__);
-               return -EINVAL;
-       }
-       if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) {
-               dprintk("%s: bad mount version\n", __FUNCTION__);
-               return -EINVAL;
-       }
-
-       /* We now require that the mount process passes the remote address */
-       if (data->host_addrlen != sizeof(addr))
-               return -EINVAL;
-
-       if (copy_from_user(&addr, data->host_addr, sizeof(addr)))
-               return -EFAULT;
-
-       if (!nfs_verify_server_address((struct sockaddr *) &addr)) {
-               dprintk("%s: mount program didn't pass remote IP address!\n",
-                               __FUNCTION__);
-               return -EINVAL;
-       }
-
-       /* RFC3530: The default port for NFS is 2049 */
-       if (addr.sin_port == 0)
-               addr.sin_port = htons(NFS_PORT);
-
-       /* Grab the authentication type */
-       authflavour = RPC_AUTH_UNIX;
-       if (data->auth_flavourlen != 0) {
-               if (data->auth_flavourlen != 1) {
-                       dprintk("%s: Invalid number of RPC auth flavours %d.\n",
-                                       __FUNCTION__, data->auth_flavourlen);
-                       error = -EINVAL;
-                       goto out;
-               }
-
-               if (copy_from_user(&authflavour, data->auth_flavours,
-                                  sizeof(authflavour))) {
-                       error = -EFAULT;
-                       goto out;
-               }
-       }
-
-       p = strndup_user(data->hostname.data, NFS4_MAXNAMLEN);
-       if (IS_ERR(p))
-               goto out_err;
-       hostname = p;
-
-       p = strndup_user(data->mnt_path.data, NFS4_MAXPATHLEN);
-       if (IS_ERR(p))
-               goto out_err;
-       mntpath = p;
-
-       dprintk("MNTPATH: %s\n", mntpath);
-
-       p = strndup_user(data->client_addr.data, 16);
-       if (IS_ERR(p))
-               goto out_err;
-       ip_addr = p;
+       /* Validate the mount data */
+       error = nfs4_validate_mount_data(&data, dev_name, &addr, &authflavour,
+                                        &hostname, &mntpath, &ip_addr);
+       if (error < 0)
+               goto out;
 
        /* Get a volume representation */
        server = nfs4_create_server(data, hostname, &addr, mntpath, ip_addr,
@@ -932,10 +961,6 @@ out:
        kfree(hostname);
        return error;
 
-out_err:
-       error = PTR_ERR(p);
-       goto out;
-
 out_free:
        nfs_free_server(server);
        goto out;