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

Commit 681bf72e authored by Jeff Layton's avatar Jeff Layton Committed by Steve French
Browse files

cifs: have cifs parse scope_id out of IPv6 addresses and use it



This patch has CIFS look for a '%' in an IPv6 address. If one is
present then it will try to treat that value as a numeric interface
index suitable for stuffing into the sin6_scope_id field.

This should allow people to mount servers on IPv6 link-local addresses.

Signed-off-by: default avatarJeff Layton <jlayton@redhat.com>
Acked-by: default avatarDavid Holder <david@erion.co.uk>
Signed-off-by: default avatarSteve French <sfrench@us.ibm.com>
parent 268875b9
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -1386,8 +1386,10 @@ cifs_find_tcp_session(struct sockaddr_storage *addr)
		     server->addr.sockAddr.sin_addr.s_addr))
			continue;
		else if (addr->ss_family == AF_INET6 &&
			 !ipv6_addr_equal(&server->addr.sockAddr6.sin6_addr,
					  &addr6->sin6_addr))
			 (!ipv6_addr_equal(&server->addr.sockAddr6.sin6_addr,
					   &addr6->sin6_addr) ||
			  server->addr.sockAddr6.sin6_scope_id !=
					   addr6->sin6_scope_id))
			continue;

		++server->srv_count;
+2 −2
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@
 * 		0 - name is not IP
 */
static int
is_ip(const char *name)
is_ip(char *name)
{
	struct sockaddr_storage ss;

@@ -57,7 +57,7 @@ dns_resolver_instantiate(struct key *key, const void *data,
	ip[datalen] = '\0';

	/* make sure this looks like an address */
	if (!is_ip((const char *) ip)) {
	if (!is_ip(ip)) {
		kfree(ip);
		return -EINVAL;
	}
+27 −5
Original line number Diff line number Diff line
@@ -158,27 +158,49 @@ cifs_inet_pton(const int address_family, const char *cp, void *dst)
/*
 * Try to convert a string to an IPv4 address and then attempt to convert
 * it to an IPv6 address if that fails. Set the family field if either
 * succeeds.
 * succeeds. If it's an IPv6 address and it has a '%' sign in it, try to
 * treat the part following it as a numeric sin6_scope_id.
 *
 * Returns 0 on failure.
 */
int
cifs_convert_address(char *src, void *dst)
{
	int rc;
	char *pct, *endp;
	struct sockaddr_in *s4 = (struct sockaddr_in *) dst;
	struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) dst;

	/* IPv4 address */
	if (cifs_inet_pton(AF_INET, src, &s4->sin_addr.s_addr)) {
		s4->sin_family = AF_INET;
		return 1;
	} else if (cifs_inet_pton(AF_INET6, src, &s6->sin6_addr.s6_addr)) {
		s6->sin6_family = AF_INET6;
		return 1;
	}

	/* temporarily terminate string */
	pct = strchr(src, '%');
	if (pct)
		*pct = '\0';

	rc = cifs_inet_pton(AF_INET6, src, &s6->sin6_addr.s6_addr);

	/* repair temp termination (if any) and make pct point to scopeid */
	if (pct)
		*pct++ = '%';

	if (!rc)
		return rc;

	s6->sin6_family = AF_INET6;
	if (pct) {
		s6->sin6_scope_id = (u32) simple_strtoul(pct, &endp, 0);
		if (!*pct || *endp)
			return 0;
	}

	return rc;
}

/*****************************************************************************
convert a NT status code to a dos class/code
 *****************************************************************************/