Skip to content

Commit

Permalink
DNS: Make AFS go to the DNS for AFSDB records for unknown cells
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
weylan authored and Steve French committed Aug 5, 2010
1 parent 1a4240f commit 07567a5
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 10 deletions.
1 change: 1 addition & 0 deletions fs/afs/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ config AFS_FS
tristate "Andrew File System support (AFS) (EXPERIMENTAL)"
depends on INET && EXPERIMENTAL
select AF_RXRPC
select DNS_RESOLVER
help
If you say Y here, you will get an experimental Andrew File System
driver. It currently only supports unsecured read-only AFS access.
Expand Down
40 changes: 30 additions & 10 deletions fs/afs/cell.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <linux/slab.h>
#include <linux/key.h>
#include <linux/ctype.h>
#include <linux/dns_resolver.h>
#include <linux/sched.h>
#include <keys/rxrpc-type.h>
#include "internal.h"
Expand All @@ -36,15 +37,19 @@ static struct afs_cell *afs_cell_alloc(const char *name, char *vllist)
struct key *key;
size_t namelen;
char keyname[4 + AFS_MAXCELLNAME + 1], *cp, *dp, *next;
char *dvllist = NULL, *_vllist = NULL;
char delimiter = ':';
int ret;

_enter("%s,%s", name, vllist);

BUG_ON(!name); /* TODO: want to look up "this cell" in the cache */

namelen = strlen(name);
if (namelen > AFS_MAXCELLNAME)
if (namelen > AFS_MAXCELLNAME) {
_leave(" = -ENAMETOOLONG");
return ERR_PTR(-ENAMETOOLONG);
}

/* allocate and initialise a cell record */
cell = kzalloc(sizeof(struct afs_cell) + namelen + 1, GFP_KERNEL);
Expand All @@ -64,15 +69,31 @@ static struct afs_cell *afs_cell_alloc(const char *name, char *vllist)
INIT_LIST_HEAD(&cell->vl_list);
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 */
do {
unsigned a, b, c, d;

next = strchr(vllist, ':');
next = strchr(_vllist, delimiter);
if (next)
*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;

if (a > 255 || b > 255 || c > 255 || d > 255)
Expand All @@ -81,7 +102,7 @@ static struct afs_cell *afs_cell_alloc(const char *name, char *vllist)
cell->vl_addrs[cell->vl_naddrs++].s_addr =
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 */
memcpy(keyname, "afs@", 4);
Expand Down Expand Up @@ -110,6 +131,7 @@ static struct afs_cell *afs_cell_alloc(const char *name, char *vllist)
ret = -EINVAL;
error:
key_put(cell->anonymous_key);
kfree(dvllist);
kfree(cell);
_leave(" = %d", ret);
return ERR_PTR(ret);
Expand Down Expand Up @@ -201,14 +223,12 @@ int afs_cell_init(char *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 */
*cp++ = 0;
new_root = afs_cell_create(rootcell, cp);
if (IS_ERR(new_root)) {
_leave(" = %ld", PTR_ERR(new_root));
Expand Down

0 comments on commit 07567a5

Please sign in to comment.