NFS: handle interface identifiers in incoming IPv6 addresses

Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
From: Linux Kernel Mailing List
Date: Wednesday, July 16, 2008 - 4:02 pm

Gitweb:     http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=d8e774...
Commit:     d8e7748ab8322171ebfd78f6155ff35e7d57ac32
Parent:     ce3b7e1906ebbe96753fe090b36de6ffb8e0e0e7
Author:     Chuck Lever <chuck.lever@oracle.com>
AuthorDate: Mon Jun 23 12:37:01 2008 -0400
Committer:  Trond Myklebust <Trond.Myklebust@netapp.com>
CommitDate: Wed Jul 9 12:09:29 2008 -0400

    NFS: handle interface identifiers in incoming IPv6 addresses
    
    Add support in the kernel NFS client's address parser for interface
    identifiers.
    
    IPv6 link-local addresses require an additional "interface identifier",
    which is a network device name or an integer that indexes the array of
    local network interfaces.  They are suffixed to the address with a '%'.
    For example:
    
    	fe80::215:c5ff:fe3b:e1b2%2
    
    indicates an interface index of 2.  Or
    
    	fe80::215:c5ff:fe3b:e1b2%eth0
    
    indicates that requests should be routed through the eth0 device.
    Without the interface ID, link-local addresses are not usable for NFS.
    
    Both the kernel NFS client mount option parser and the mount.nfs command
    can take either form.  The mount.nfs command always passes the address
    through getnameinfo(3), which usually re-writes interface indices as
    device names.
    
    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
---
 fs/nfs/super.c |   41 ++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 40 insertions(+), 1 deletions(-)

diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index d27aa1d..73a8e59 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -47,6 +47,7 @@
 #include <linux/inet.h>
 #include <linux/in6.h>
 #include <net/ipv6.h>
+#include <linux/netdevice.h>
 #include <linux/nfs_xdr.h>
 #include <linux/magic.h>
 #include <linux/parser.h>
@@ -725,12 +726,48 @@ static void nfs_parse_ipv4_address(char *string, size_t str_len,
 	*addr_len = 0;
 }
 
+#define IPV6_SCOPE_DELIMITER	'%'
+
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+static void nfs_parse_ipv6_scope_id(const char *string, const size_t str_len,
+				    const char *delim,
+				    struct sockaddr_in6 *sin6)
+{
+	char *p;
+	size_t len;
+
+	if (!(ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL))
+		return ;
+	if (*delim != IPV6_SCOPE_DELIMITER)
+		return;
+
+	len = (string + str_len) - delim - 1;
+	p = kstrndup(delim + 1, len, GFP_KERNEL);
+	if (p) {
+		unsigned long scope_id = 0;
+		struct net_device *dev;
+
+		dev = dev_get_by_name(&init_net, p);
+		if (dev != NULL) {
+			scope_id = dev->ifindex;
+			dev_put(dev);
+		} else {
+			/* scope_id is set to zero on error */
+			strict_strtoul(p, 10, &scope_id);
+		}
+
+		kfree(p);
+		sin6->sin6_scope_id = scope_id;
+		dfprintk(MOUNT, "NFS: IPv6 scope ID = %lu\n", scope_id);
+	}
+}
+
 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;
+	const char *delim;
 
 	if (str_len <= INET6_ADDRSTRLEN) {
 		dfprintk(MOUNT, "NFS: parsing IPv6 address %*s\n",
@@ -738,8 +775,10 @@ static void nfs_parse_ipv6_address(char *string, size_t str_len,
 
 		sin6->sin6_family = AF_INET6;
 		*addr_len = sizeof(*sin6);
-		if (in6_pton(string, str_len, addr, '\0', NULL))
+		if (in6_pton(string, str_len, addr, IPV6_SCOPE_DELIMITER, &delim)) {
+			nfs_parse_ipv6_scope_id(string, str_len, delim, sin6);
 			return;
+		}
 	}
 
 	sap->sa_family = AF_UNSPEC;
--
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
NFS: handle interface identifiers in incoming IPv6 addresses, Linux Kernel Mailing ..., (Wed Jul 16, 4:02 pm)