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:
Chuck Lever 2007-12-10 14:59:28 -05:00 committed by Trond Myklebust
parent 9412b92772
commit 4c56801770
3 changed files with 40 additions and 24 deletions

View File

@ -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,

View File

@ -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;

View File

@ -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))