« Return to Thread: [PATCH 0/5] cifs: clean up show_options code and add support for mounting link-local addresses

[PATCH 4/5] cifs: have cifs parse scope_id out of IPv6 addresses and use it

by Jeff Layton-2 :: Rate this Message:

Reply to Author | View in Thread

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: Jeff Layton <jlayton@...>
---
 fs/cifs/connect.c     |    6 ++++--
 fs/cifs/dns_resolve.c |    4 ++--
 fs/cifs/netmisc.c     |   34 ++++++++++++++++++++++++++++------
 3 files changed, 34 insertions(+), 10 deletions(-)

diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 6a91b5f..c9e489c 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1374,8 +1374,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;
diff --git a/fs/cifs/dns_resolve.c b/fs/cifs/dns_resolve.c
index 91b5500..8794814 100644
--- a/fs/cifs/dns_resolve.c
+++ b/fs/cifs/dns_resolve.c
@@ -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;
  }
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index 00e6e35..bd6d689 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -158,25 +158,47 @@ 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;
+ 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;
  }
 
- return 0;
+ /* 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;
 }
 
 /*****************************************************************************
--
1.6.0.6

_______________________________________________
linux-cifs-client mailing list
linux-cifs-client@...
https://lists.samba.org/mailman/listinfo/linux-cifs-client

 « Return to Thread: [PATCH 0/5] cifs: clean up show_options code and add support for mounting link-local addresses