瀏覽代碼

DNS: Make AFS go to the DNS for AFSDB records for unknown cells

Add DNS query support for AFS so that it can get the IP addresses of Volume
Location servers from the DNS using an AFSDB record.

This requires userspace support.  /etc/request-key.conf must be configured to
invoke a helper for dns_resolver type keys with a subtype of "afsdb:" in the
description.

Signed-off-by: Wang Lei <wang840925@gmail.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Wang Lei 15 年之前
父節點
當前提交
07567a5509
共有 2 個文件被更改,包括 31 次插入10 次删除
  1. 1 0
      fs/afs/Kconfig
  2. 30 10
      fs/afs/cell.c

+ 1 - 0
fs/afs/Kconfig

@@ -2,6 +2,7 @@ config AFS_FS
 	tristate "Andrew File System support (AFS) (EXPERIMENTAL)"
 	tristate "Andrew File System support (AFS) (EXPERIMENTAL)"
 	depends on INET && EXPERIMENTAL
 	depends on INET && EXPERIMENTAL
 	select AF_RXRPC
 	select AF_RXRPC
+	select DNS_RESOLVER
 	help
 	help
 	  If you say Y here, you will get an experimental Andrew File System
 	  If you say Y here, you will get an experimental Andrew File System
 	  driver. It currently only supports unsecured read-only AFS access.
 	  driver. It currently only supports unsecured read-only AFS access.

+ 30 - 10
fs/afs/cell.c

@@ -13,6 +13,7 @@
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/key.h>
 #include <linux/key.h>
 #include <linux/ctype.h>
 #include <linux/ctype.h>
+#include <linux/dns_resolver.h>
 #include <linux/sched.h>
 #include <linux/sched.h>
 #include <keys/rxrpc-type.h>
 #include <keys/rxrpc-type.h>
 #include "internal.h"
 #include "internal.h"
@@ -36,6 +37,8 @@ static struct afs_cell *afs_cell_alloc(const char *name, char *vllist)
 	struct key *key;
 	struct key *key;
 	size_t namelen;
 	size_t namelen;
 	char keyname[4 + AFS_MAXCELLNAME + 1], *cp, *dp, *next;
 	char keyname[4 + AFS_MAXCELLNAME + 1], *cp, *dp, *next;
+	char  *dvllist = NULL, *_vllist = NULL;
+	char  delimiter = ':';
 	int ret;
 	int ret;
 
 
 	_enter("%s,%s", name, vllist);
 	_enter("%s,%s", name, vllist);
@@ -43,8 +46,10 @@ static struct afs_cell *afs_cell_alloc(const char *name, char *vllist)
 	BUG_ON(!name); /* TODO: want to look up "this cell" in the cache */
 	BUG_ON(!name); /* TODO: want to look up "this cell" in the cache */
 
 
 	namelen = strlen(name);
 	namelen = strlen(name);
-	if (namelen > AFS_MAXCELLNAME)
+	if (namelen > AFS_MAXCELLNAME) {
+		_leave(" = -ENAMETOOLONG");
 		return ERR_PTR(-ENAMETOOLONG);
 		return ERR_PTR(-ENAMETOOLONG);
+	}
 
 
 	/* allocate and initialise a cell record */
 	/* allocate and initialise a cell record */
 	cell = kzalloc(sizeof(struct afs_cell) + namelen + 1, GFP_KERNEL);
 	cell = kzalloc(sizeof(struct afs_cell) + namelen + 1, GFP_KERNEL);
@@ -64,15 +69,31 @@ static struct afs_cell *afs_cell_alloc(const char *name, char *vllist)
 	INIT_LIST_HEAD(&cell->vl_list);
 	INIT_LIST_HEAD(&cell->vl_list);
 	spin_lock_init(&cell->vl_lock);
 	spin_lock_init(&cell->vl_lock);
 
 
+	/* if the ip address is invalid, try dns query */
+	if (!vllist || strlen(vllist) < 7) {
+		ret = dns_query("afsdb", name, namelen, "ipv4", &dvllist, NULL);
+		if (ret < 0) {
+			_leave(" = %d", ret);
+			return ERR_PTR(ret);
+		}
+		_vllist = dvllist;
+
+		/* change the delimiter for user-space reply */
+		delimiter = ',';
+
+	} else {
+		_vllist = vllist;
+	}
+
 	/* fill in the VL server list from the rest of the string */
 	/* fill in the VL server list from the rest of the string */
 	do {
 	do {
 		unsigned a, b, c, d;
 		unsigned a, b, c, d;
 
 
-		next = strchr(vllist, ':');
+		next = strchr(_vllist, delimiter);
 		if (next)
 		if (next)
 			*next++ = 0;
 			*next++ = 0;
 
 
-		if (sscanf(vllist, "%u.%u.%u.%u", &a, &b, &c, &d) != 4)
+		if (sscanf(_vllist, "%u.%u.%u.%u", &a, &b, &c, &d) != 4)
 			goto bad_address;
 			goto bad_address;
 
 
 		if (a > 255 || b > 255 || c > 255 || d > 255)
 		if (a > 255 || b > 255 || c > 255 || d > 255)
@@ -81,7 +102,7 @@ static struct afs_cell *afs_cell_alloc(const char *name, char *vllist)
 		cell->vl_addrs[cell->vl_naddrs++].s_addr =
 		cell->vl_addrs[cell->vl_naddrs++].s_addr =
 			htonl((a << 24) | (b << 16) | (c << 8) | d);
 			htonl((a << 24) | (b << 16) | (c << 8) | d);
 
 
-	} while (cell->vl_naddrs < AFS_CELL_MAX_ADDRS && (vllist = next));
+	} while (cell->vl_naddrs < AFS_CELL_MAX_ADDRS && (_vllist = next));
 
 
 	/* create a key to represent an anonymous user */
 	/* create a key to represent an anonymous user */
 	memcpy(keyname, "afs@", 4);
 	memcpy(keyname, "afs@", 4);
@@ -110,6 +131,7 @@ static struct afs_cell *afs_cell_alloc(const char *name, char *vllist)
 	ret = -EINVAL;
 	ret = -EINVAL;
 error:
 error:
 	key_put(cell->anonymous_key);
 	key_put(cell->anonymous_key);
+	kfree(dvllist);
 	kfree(cell);
 	kfree(cell);
 	_leave(" = %d", ret);
 	_leave(" = %d", ret);
 	return ERR_PTR(ret);
 	return ERR_PTR(ret);
@@ -201,14 +223,12 @@ int afs_cell_init(char *rootcell)
 	}
 	}
 
 
 	cp = strchr(rootcell, ':');
 	cp = strchr(rootcell, ':');
-	if (!cp) {
-		printk(KERN_ERR "kAFS: no VL server IP addresses specified\n");
-		_leave(" = -EINVAL");
-		return -EINVAL;
-	}
+	if (!cp)
+		_debug("kAFS: no VL server IP addresses specified");
+	else
+		*cp++ = 0;
 
 
 	/* allocate a cell record for the root cell */
 	/* allocate a cell record for the root cell */
-	*cp++ = 0;
 	new_root = afs_cell_create(rootcell, cp);
 	new_root = afs_cell_create(rootcell, cp);
 	if (IS_ERR(new_root)) {
 	if (IS_ERR(new_root)) {
 		_leave(" = %ld", PTR_ERR(new_root));
 		_leave(" = %ld", PTR_ERR(new_root));