Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ce3b7e19 authored by Chuck Lever's avatar Chuck Lever Committed by Trond Myklebust
Browse files

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: default avatarChuck Lever <chuck.lever@oracle.com>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent d1aa0825
Loading
Loading
Loading
Loading
+70 −30
Original line number Diff line number Diff line
@@ -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;

	if (str_len <= INET_ADDRSTRLEN) {
		dfprintk(MOUNT, "NFS: parsing IPv4 address %*s\n",
				(int)str_len, string);

		ap->sin6_family = AF_INET6;
		*len = sizeof(*ap);
		if (in6_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;
	} 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;

		ap->sin_family = AF_INET;
		*len = sizeof(*ap);
		if (in4_pton(value, -1, addr, '\0', NULL))
	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;
	*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);
}

/*
@@ -1070,7 +1108,8 @@ 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 *)
			nfs_parse_ip_address(string, strlen(string),
					     (struct sockaddr *)
						&mnt->nfs_server.address,
					     &mnt->nfs_server.addrlen);
			kfree(string);
@@ -1093,7 +1132,8 @@ 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 *)
			nfs_parse_ip_address(string, strlen(string),
					     (struct sockaddr *)
						&mnt->mount_server.address,
					     &mnt->mount_server.addrlen);
			kfree(string);
+7 −0
Original line number Diff line number Diff line
@@ -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);