Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 101935
b: refs/heads/master
c: ce3b7e1
h: refs/heads/master
i:
  101933: 568f1d8
  101931: f84c5fe
  101927: 4d56726
  101919: e19e146
v: v3
  • Loading branch information
Chuck Lever authored and Trond Myklebust committed Jul 9, 2008
1 parent 727e14a commit 55b2bfd
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 31 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d1aa08257312f1439c1ab7c8a18e3856f9530f46
refs/heads/master: ce3b7e1906ebbe96753fe090b36de6ffb8e0e0e7
100 changes: 70 additions & 30 deletions trunk/fs/nfs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
if (str_len <= INET_ADDRSTRLEN) {
dfprintk(MOUNT, "NFS: parsing IPv4 address %*s\n",
(int)str_len, string);

sin->sin_family = AF_INET;
*addr_len = sizeof(*sin);
if (in4_pton(string, str_len, addr, '\0', NULL))
return;
} else {
struct sockaddr_in *ap = (struct sockaddr_in *)sap;
u8 *addr = (u8 *)&ap->sin_addr.s_addr;
}

sap->sa_family = AF_UNSPEC;
*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);

ap->sin_family = AF_INET;
*len = sizeof(*ap);
if (in4_pton(value, -1, addr, '\0', NULL))
sin6->sin6_family = AF_INET6;
*addr_len = sizeof(*sin6);
if (in6_pton(string, str_len, addr, '\0', NULL))
return;
}

sap->sa_family = AF_UNSPEC;
*len = 0;
*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);
}

/*
Expand Down Expand Up @@ -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:
Expand All @@ -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;

Expand Down
7 changes: 7 additions & 0 deletions trunk/include/linux/inet.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 55b2bfd

Please sign in to comment.