mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 03:36:19 +00:00
NFS: Add string length argument to nfs_parse_server_address
To make nfs_parse_server_address() more generally useful, allow it to accept input strings that are not terminated with '\0'. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
parent
d1aa082573
commit
ce3b7e1906
2 changed files with 78 additions and 31 deletions
102
fs/nfs/super.c
102
fs/nfs/super.c
|
@ -705,38 +705,76 @@ static int nfs_verify_server_address(struct sockaddr *addr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse string addresses passed in via a mount option,
|
||||
* and construct a sockaddr based on the result.
|
||||
*
|
||||
* If address parsing fails, set the sockaddr's address
|
||||
* family to AF_UNSPEC to force nfs_verify_server_address()
|
||||
* to punt the mount.
|
||||
*/
|
||||
static void nfs_parse_server_address(char *value,
|
||||
struct sockaddr *sap,
|
||||
size_t *len)
|
||||
static void nfs_parse_ipv4_address(char *string, size_t str_len,
|
||||
struct sockaddr *sap, size_t *addr_len)
|
||||
{
|
||||
if (strchr(value, ':')) {
|
||||
struct sockaddr_in6 *ap = (struct sockaddr_in6 *)sap;
|
||||
u8 *addr = (u8 *)&ap->sin6_addr.in6_u;
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *)sap;
|
||||
u8 *addr = (u8 *)&sin->sin_addr.s_addr;
|
||||
|
||||
ap->sin6_family = AF_INET6;
|
||||
*len = sizeof(*ap);
|
||||
if (in6_pton(value, -1, addr, '\0', NULL))
|
||||
return;
|
||||
} else {
|
||||
struct sockaddr_in *ap = (struct sockaddr_in *)sap;
|
||||
u8 *addr = (u8 *)&ap->sin_addr.s_addr;
|
||||
if (str_len <= INET_ADDRSTRLEN) {
|
||||
dfprintk(MOUNT, "NFS: parsing IPv4 address %*s\n",
|
||||
(int)str_len, string);
|
||||
|
||||
ap->sin_family = AF_INET;
|
||||
*len = sizeof(*ap);
|
||||
if (in4_pton(value, -1, addr, '\0', NULL))
|
||||
sin->sin_family = AF_INET;
|
||||
*addr_len = sizeof(*sin);
|
||||
if (in4_pton(string, str_len, addr, '\0', NULL))
|
||||
return;
|
||||
}
|
||||
|
||||
sap->sa_family = AF_UNSPEC;
|
||||
*len = 0;
|
||||
*addr_len = 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
||||
static void nfs_parse_ipv6_address(char *string, size_t str_len,
|
||||
struct sockaddr *sap, size_t *addr_len)
|
||||
{
|
||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
|
||||
u8 *addr = (u8 *)&sin6->sin6_addr.in6_u;
|
||||
|
||||
if (str_len <= INET6_ADDRSTRLEN) {
|
||||
dfprintk(MOUNT, "NFS: parsing IPv6 address %*s\n",
|
||||
(int)str_len, string);
|
||||
|
||||
sin6->sin6_family = AF_INET6;
|
||||
*addr_len = sizeof(*sin6);
|
||||
if (in6_pton(string, str_len, addr, '\0', NULL))
|
||||
return;
|
||||
}
|
||||
|
||||
sap->sa_family = AF_UNSPEC;
|
||||
*addr_len = 0;
|
||||
}
|
||||
#else
|
||||
static void nfs_parse_ipv6_address(char *string, size_t str_len,
|
||||
struct sockaddr *sap, size_t *addr_len)
|
||||
{
|
||||
sap->sa_family = AF_UNSPEC;
|
||||
*addr_len = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Construct a sockaddr based on the contents of a string that contains
|
||||
* an IP address in presentation format.
|
||||
*
|
||||
* If there is a problem constructing the new sockaddr, set the address
|
||||
* family to AF_UNSPEC.
|
||||
*/
|
||||
static void nfs_parse_ip_address(char *string, size_t str_len,
|
||||
struct sockaddr *sap, size_t *addr_len)
|
||||
{
|
||||
unsigned int i, colons;
|
||||
|
||||
colons = 0;
|
||||
for (i = 0; i < str_len; i++)
|
||||
if (string[i] == ':')
|
||||
colons++;
|
||||
|
||||
if (colons >= 2)
|
||||
nfs_parse_ipv6_address(string, str_len, sap, addr_len);
|
||||
else
|
||||
nfs_parse_ipv4_address(string, str_len, sap, addr_len);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1070,9 +1108,10 @@ static int nfs_parse_mount_options(char *raw,
|
|||
string = match_strdup(args);
|
||||
if (string == NULL)
|
||||
goto out_nomem;
|
||||
nfs_parse_server_address(string, (struct sockaddr *)
|
||||
&mnt->nfs_server.address,
|
||||
&mnt->nfs_server.addrlen);
|
||||
nfs_parse_ip_address(string, strlen(string),
|
||||
(struct sockaddr *)
|
||||
&mnt->nfs_server.address,
|
||||
&mnt->nfs_server.addrlen);
|
||||
kfree(string);
|
||||
break;
|
||||
case Opt_clientaddr:
|
||||
|
@ -1093,9 +1132,10 @@ static int nfs_parse_mount_options(char *raw,
|
|||
string = match_strdup(args);
|
||||
if (string == NULL)
|
||||
goto out_nomem;
|
||||
nfs_parse_server_address(string, (struct sockaddr *)
|
||||
&mnt->mount_server.address,
|
||||
&mnt->mount_server.addrlen);
|
||||
nfs_parse_ip_address(string, strlen(string),
|
||||
(struct sockaddr *)
|
||||
&mnt->mount_server.address,
|
||||
&mnt->mount_server.addrlen);
|
||||
kfree(string);
|
||||
break;
|
||||
|
||||
|
|
|
@ -44,6 +44,13 @@
|
|||
|
||||
#include <linux/types.h>
|
||||
|
||||
/*
|
||||
* These mimic similar macros defined in user-space for inet_ntop(3).
|
||||
* See /usr/include/netinet/in.h .
|
||||
*/
|
||||
#define INET_ADDRSTRLEN (16)
|
||||
#define INET6_ADDRSTRLEN (48)
|
||||
|
||||
extern __be32 in_aton(const char *str);
|
||||
extern int in4_pton(const char *src, int srclen, u8 *dst, int delim, const char **end);
|
||||
extern int in6_pton(const char *src, int srclen, u8 *dst, int delim, const char **end);
|
||||
|
|
Loading…
Reference in a new issue