NFS: Support non-IPv4 addresses in nfs_parsed_mount_data
Replace the nfs_server and mount_server address fields in the nfs_parsed_mount_data structure with a "struct sockaddr_storage" instead of a "struct sockaddr_in". Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Cc: Aurelien Charbon <aurelien.charbon@ext.bull.net> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
parent
9412b92772
commit
4c56801770
|
@ -581,7 +581,7 @@ static int nfs_init_server(struct nfs_server *server,
|
||||||
struct nfs_client_initdata cl_init = {
|
struct nfs_client_initdata cl_init = {
|
||||||
.hostname = data->nfs_server.hostname,
|
.hostname = data->nfs_server.hostname,
|
||||||
.addr = (const struct sockaddr *)&data->nfs_server.address,
|
.addr = (const struct sockaddr *)&data->nfs_server.address,
|
||||||
.addrlen = sizeof(data->nfs_server.address),
|
.addrlen = data->nfs_server.addrlen,
|
||||||
.rpc_ops = &nfs_v2_clientops,
|
.rpc_ops = &nfs_v2_clientops,
|
||||||
};
|
};
|
||||||
struct nfs_client *clp;
|
struct nfs_client *clp;
|
||||||
|
@ -1018,7 +1018,7 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
|
||||||
error = nfs4_set_client(server,
|
error = nfs4_set_client(server,
|
||||||
data->nfs_server.hostname,
|
data->nfs_server.hostname,
|
||||||
(struct sockaddr *)&data->nfs_server.address,
|
(struct sockaddr *)&data->nfs_server.address,
|
||||||
sizeof(data->nfs_server.address),
|
data->nfs_server.addrlen,
|
||||||
data->client_address,
|
data->client_address,
|
||||||
data->auth_flavors[0],
|
data->auth_flavors[0],
|
||||||
data->nfs_server.protocol,
|
data->nfs_server.protocol,
|
||||||
|
|
|
@ -42,7 +42,8 @@ struct nfs_parsed_mount_data {
|
||||||
char *client_address;
|
char *client_address;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct sockaddr_in address;
|
struct sockaddr_storage address;
|
||||||
|
size_t addrlen;
|
||||||
char *hostname;
|
char *hostname;
|
||||||
unsigned int version;
|
unsigned int version;
|
||||||
unsigned short port;
|
unsigned short port;
|
||||||
|
@ -50,7 +51,8 @@ struct nfs_parsed_mount_data {
|
||||||
} mount_server;
|
} mount_server;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct sockaddr_in address;
|
struct sockaddr_storage address;
|
||||||
|
size_t addrlen;
|
||||||
char *hostname;
|
char *hostname;
|
||||||
char *export_path;
|
char *export_path;
|
||||||
int protocol;
|
int protocol;
|
||||||
|
|
|
@ -649,15 +649,18 @@ static int nfs_verify_server_address(struct sockaddr *addr)
|
||||||
* to punt the mount.
|
* to punt the mount.
|
||||||
*/
|
*/
|
||||||
static void nfs_parse_server_address(char *value,
|
static void nfs_parse_server_address(char *value,
|
||||||
struct sockaddr *sap)
|
struct sockaddr *sap,
|
||||||
|
size_t *len)
|
||||||
{
|
{
|
||||||
struct sockaddr_in *ap = (void *)sap;
|
struct sockaddr_in *ap = (void *)sap;
|
||||||
|
|
||||||
ap->sin_family = AF_INET;
|
ap->sin_family = AF_INET;
|
||||||
|
*len = sizeof(*ap);
|
||||||
if (in4_pton(value, -1, (u8 *)&ap->sin_addr.s_addr, '\0', NULL))
|
if (in4_pton(value, -1, (u8 *)&ap->sin_addr.s_addr, '\0', NULL))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sap->sa_family = AF_UNSPEC;
|
sap->sa_family = AF_UNSPEC;
|
||||||
|
*len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -984,7 +987,8 @@ static int nfs_parse_mount_options(char *raw,
|
||||||
if (string == NULL)
|
if (string == NULL)
|
||||||
goto out_nomem;
|
goto out_nomem;
|
||||||
nfs_parse_server_address(string, (struct sockaddr *)
|
nfs_parse_server_address(string, (struct sockaddr *)
|
||||||
&mnt->nfs_server.address);
|
&mnt->nfs_server.address,
|
||||||
|
&mnt->nfs_server.addrlen);
|
||||||
kfree(string);
|
kfree(string);
|
||||||
break;
|
break;
|
||||||
case Opt_clientaddr:
|
case Opt_clientaddr:
|
||||||
|
@ -1004,7 +1008,8 @@ static int nfs_parse_mount_options(char *raw,
|
||||||
if (string == NULL)
|
if (string == NULL)
|
||||||
goto out_nomem;
|
goto out_nomem;
|
||||||
nfs_parse_server_address(string, (struct sockaddr *)
|
nfs_parse_server_address(string, (struct sockaddr *)
|
||||||
&mnt->mount_server.address);
|
&mnt->mount_server.address,
|
||||||
|
&mnt->mount_server.addrlen);
|
||||||
kfree(string);
|
kfree(string);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1049,9 +1054,9 @@ out_unknown:
|
||||||
static int nfs_try_mount(struct nfs_parsed_mount_data *args,
|
static int nfs_try_mount(struct nfs_parsed_mount_data *args,
|
||||||
struct nfs_fh *root_fh)
|
struct nfs_fh *root_fh)
|
||||||
{
|
{
|
||||||
struct sockaddr_in sin;
|
struct sockaddr *sap = (struct sockaddr *)&args->mount_server.address;
|
||||||
int status;
|
|
||||||
char *hostname;
|
char *hostname;
|
||||||
|
int status;
|
||||||
|
|
||||||
if (args->mount_server.version == 0) {
|
if (args->mount_server.version == 0) {
|
||||||
if (args->flags & NFS_MOUNT_VER3)
|
if (args->flags & NFS_MOUNT_VER3)
|
||||||
|
@ -1068,21 +1073,23 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args,
|
||||||
/*
|
/*
|
||||||
* Construct the mount server's address.
|
* Construct the mount server's address.
|
||||||
*/
|
*/
|
||||||
if (args->mount_server.address.sin_addr.s_addr != INADDR_ANY)
|
if (args->mount_server.address.ss_family == AF_UNSPEC) {
|
||||||
sin = args->mount_server.address;
|
memcpy(sap, &args->nfs_server.address,
|
||||||
else
|
args->nfs_server.addrlen);
|
||||||
sin = args->nfs_server.address;
|
args->mount_server.addrlen = args->nfs_server.addrlen;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* autobind will be used if mount_server.port == 0
|
* autobind will be used if mount_server.port == 0
|
||||||
*/
|
*/
|
||||||
nfs_set_port((struct sockaddr *)&sin, args->mount_server.port);
|
nfs_set_port(sap, args->mount_server.port);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now ask the mount server to map our export path
|
* Now ask the mount server to map our export path
|
||||||
* to a file handle.
|
* to a file handle.
|
||||||
*/
|
*/
|
||||||
status = nfs_mount((struct sockaddr *) &sin,
|
status = nfs_mount(sap,
|
||||||
sizeof(sin),
|
args->mount_server.addrlen,
|
||||||
hostname,
|
hostname,
|
||||||
args->nfs_server.export_path,
|
args->nfs_server.export_path,
|
||||||
args->mount_server.version,
|
args->mount_server.version,
|
||||||
|
@ -1165,9 +1172,6 @@ static int nfs_validate_mount_data(void *options,
|
||||||
memset(mntfh->data + mntfh->size, 0,
|
memset(mntfh->data + mntfh->size, 0,
|
||||||
sizeof(mntfh->data) - mntfh->size);
|
sizeof(mntfh->data) - mntfh->size);
|
||||||
|
|
||||||
if (!nfs_verify_server_address((struct sockaddr *) &data->addr))
|
|
||||||
goto out_no_address;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Translate to nfs_parsed_mount_data, which nfs_fill_super
|
* Translate to nfs_parsed_mount_data, which nfs_fill_super
|
||||||
* can deal with.
|
* can deal with.
|
||||||
|
@ -1182,7 +1186,14 @@ static int nfs_validate_mount_data(void *options,
|
||||||
args->acregmax = data->acregmax;
|
args->acregmax = data->acregmax;
|
||||||
args->acdirmin = data->acdirmin;
|
args->acdirmin = data->acdirmin;
|
||||||
args->acdirmax = data->acdirmax;
|
args->acdirmax = data->acdirmax;
|
||||||
args->nfs_server.address = data->addr;
|
|
||||||
|
memcpy(&args->nfs_server.address, &data->addr,
|
||||||
|
sizeof(data->addr));
|
||||||
|
args->nfs_server.addrlen = sizeof(data->addr);
|
||||||
|
if (!nfs_verify_server_address((struct sockaddr *)
|
||||||
|
&args->nfs_server.address))
|
||||||
|
goto out_no_address;
|
||||||
|
|
||||||
if (!(data->flags & NFS_MOUNT_TCP))
|
if (!(data->flags & NFS_MOUNT_TCP))
|
||||||
args->nfs_server.protocol = XPRT_TRANSPORT_UDP;
|
args->nfs_server.protocol = XPRT_TRANSPORT_UDP;
|
||||||
/* N.B. caller will free nfs_server.hostname in all cases */
|
/* N.B. caller will free nfs_server.hostname in all cases */
|
||||||
|
@ -1655,6 +1666,7 @@ static int nfs4_validate_mount_data(void *options,
|
||||||
struct nfs_parsed_mount_data *args,
|
struct nfs_parsed_mount_data *args,
|
||||||
const char *dev_name)
|
const char *dev_name)
|
||||||
{
|
{
|
||||||
|
struct sockaddr_in *ap;
|
||||||
struct nfs4_mount_data *data = (struct nfs4_mount_data *)options;
|
struct nfs4_mount_data *data = (struct nfs4_mount_data *)options;
|
||||||
char *c;
|
char *c;
|
||||||
|
|
||||||
|
@ -1675,11 +1687,13 @@ static int nfs4_validate_mount_data(void *options,
|
||||||
|
|
||||||
switch (data->version) {
|
switch (data->version) {
|
||||||
case 1:
|
case 1:
|
||||||
if (data->host_addrlen != sizeof(args->nfs_server.address))
|
ap = (struct sockaddr_in *)&args->nfs_server.address;
|
||||||
|
if (data->host_addrlen > sizeof(args->nfs_server.address))
|
||||||
goto out_no_address;
|
goto out_no_address;
|
||||||
if (copy_from_user(&args->nfs_server.address,
|
if (data->host_addrlen == 0)
|
||||||
data->host_addr,
|
goto out_no_address;
|
||||||
sizeof(args->nfs_server.address)))
|
args->nfs_server.addrlen = data->host_addrlen;
|
||||||
|
if (copy_from_user(ap, data->host_addr, data->host_addrlen))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if (!nfs_verify_server_address((struct sockaddr *)
|
if (!nfs_verify_server_address((struct sockaddr *)
|
||||||
&args->nfs_server.address))
|
&args->nfs_server.address))
|
||||||
|
|
Loading…
Reference in New Issue