Commit 07567a55 authored by Wang Lei's avatar Wang Lei Committed by Steve French

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: default avatarWang Lei <wang840925@gmail.com>
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Signed-off-by: default avatarSteve French <sfrench@us.ibm.com>
parent 1a4240f4
...@@ -2,6 +2,7 @@ config AFS_FS ...@@ -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.
......
...@@ -13,6 +13,7 @@ ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -201,14 +223,12 @@ int afs_cell_init(char *rootcell)
} }
cp = strchr(rootcell, ':'); cp = strchr(rootcell, ':');
if (!cp) { if (!cp)
printk(KERN_ERR "kAFS: no VL server IP addresses specified\n"); _debug("kAFS: no VL server IP addresses specified");
_leave(" = -EINVAL"); else
return -EINVAL; *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));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment