diff options
Diffstat (limited to 'fs/afs/cell.c')
-rw-r--r-- | fs/afs/cell.c | 40 |
1 files changed, 30 insertions, 10 deletions
diff --git a/fs/afs/cell.c b/fs/afs/cell.c index e19c13f059ed..ffea35c63879 100644 --- a/fs/afs/cell.c +++ b/fs/afs/cell.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | #include <linux/key.h> | 14 | #include <linux/key.h> |
15 | #include <linux/ctype.h> | 15 | #include <linux/ctype.h> |
16 | #include <linux/dns_resolver.h> | ||
16 | #include <linux/sched.h> | 17 | #include <linux/sched.h> |
17 | #include <keys/rxrpc-type.h> | 18 | #include <keys/rxrpc-type.h> |
18 | #include "internal.h" | 19 | #include "internal.h" |
@@ -36,6 +37,8 @@ static struct afs_cell *afs_cell_alloc(const char *name, char *vllist) | |||
36 | struct key *key; | 37 | struct key *key; |
37 | size_t namelen; | 38 | size_t namelen; |
38 | char keyname[4 + AFS_MAXCELLNAME + 1], *cp, *dp, *next; | 39 | char keyname[4 + AFS_MAXCELLNAME + 1], *cp, *dp, *next; |
40 | char *dvllist = NULL, *_vllist = NULL; | ||
41 | char delimiter = ':'; | ||
39 | int ret; | 42 | int ret; |
40 | 43 | ||
41 | _enter("%s,%s", name, vllist); | 44 | _enter("%s,%s", name, vllist); |
@@ -43,8 +46,10 @@ static struct afs_cell *afs_cell_alloc(const char *name, char *vllist) | |||
43 | BUG_ON(!name); /* TODO: want to look up "this cell" in the cache */ | 46 | BUG_ON(!name); /* TODO: want to look up "this cell" in the cache */ |
44 | 47 | ||
45 | namelen = strlen(name); | 48 | namelen = strlen(name); |
46 | if (namelen > AFS_MAXCELLNAME) | 49 | if (namelen > AFS_MAXCELLNAME) { |
50 | _leave(" = -ENAMETOOLONG"); | ||
47 | return ERR_PTR(-ENAMETOOLONG); | 51 | return ERR_PTR(-ENAMETOOLONG); |
52 | } | ||
48 | 53 | ||
49 | /* allocate and initialise a cell record */ | 54 | /* allocate and initialise a cell record */ |
50 | cell = kzalloc(sizeof(struct afs_cell) + namelen + 1, GFP_KERNEL); | 55 | 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 | INIT_LIST_HEAD(&cell->vl_list); | 69 | INIT_LIST_HEAD(&cell->vl_list); |
65 | spin_lock_init(&cell->vl_lock); | 70 | spin_lock_init(&cell->vl_lock); |
66 | 71 | ||
72 | /* if the ip address is invalid, try dns query */ | ||
73 | if (!vllist || strlen(vllist) < 7) { | ||
74 | ret = dns_query("afsdb", name, namelen, "ipv4", &dvllist, NULL); | ||
75 | if (ret < 0) { | ||
76 | _leave(" = %d", ret); | ||
77 | return ERR_PTR(ret); | ||
78 | } | ||
79 | _vllist = dvllist; | ||
80 | |||
81 | /* change the delimiter for user-space reply */ | ||
82 | delimiter = ','; | ||
83 | |||
84 | } else { | ||
85 | _vllist = vllist; | ||
86 | } | ||
87 | |||
67 | /* fill in the VL server list from the rest of the string */ | 88 | /* fill in the VL server list from the rest of the string */ |
68 | do { | 89 | do { |
69 | unsigned a, b, c, d; | 90 | unsigned a, b, c, d; |
70 | 91 | ||
71 | next = strchr(vllist, ':'); | 92 | next = strchr(_vllist, delimiter); |
72 | if (next) | 93 | if (next) |
73 | *next++ = 0; | 94 | *next++ = 0; |
74 | 95 | ||
75 | if (sscanf(vllist, "%u.%u.%u.%u", &a, &b, &c, &d) != 4) | 96 | if (sscanf(_vllist, "%u.%u.%u.%u", &a, &b, &c, &d) != 4) |
76 | goto bad_address; | 97 | goto bad_address; |
77 | 98 | ||
78 | if (a > 255 || b > 255 || c > 255 || d > 255) | 99 | 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 | cell->vl_addrs[cell->vl_naddrs++].s_addr = | 102 | cell->vl_addrs[cell->vl_naddrs++].s_addr = |
82 | htonl((a << 24) | (b << 16) | (c << 8) | d); | 103 | htonl((a << 24) | (b << 16) | (c << 8) | d); |
83 | 104 | ||
84 | } while (cell->vl_naddrs < AFS_CELL_MAX_ADDRS && (vllist = next)); | 105 | } while (cell->vl_naddrs < AFS_CELL_MAX_ADDRS && (_vllist = next)); |
85 | 106 | ||
86 | /* create a key to represent an anonymous user */ | 107 | /* create a key to represent an anonymous user */ |
87 | memcpy(keyname, "afs@", 4); | 108 | memcpy(keyname, "afs@", 4); |
@@ -110,6 +131,7 @@ bad_address: | |||
110 | ret = -EINVAL; | 131 | ret = -EINVAL; |
111 | error: | 132 | error: |
112 | key_put(cell->anonymous_key); | 133 | key_put(cell->anonymous_key); |
134 | kfree(dvllist); | ||
113 | kfree(cell); | 135 | kfree(cell); |
114 | _leave(" = %d", ret); | 136 | _leave(" = %d", ret); |
115 | return ERR_PTR(ret); | 137 | return ERR_PTR(ret); |
@@ -201,14 +223,12 @@ int afs_cell_init(char *rootcell) | |||
201 | } | 223 | } |
202 | 224 | ||
203 | cp = strchr(rootcell, ':'); | 225 | cp = strchr(rootcell, ':'); |
204 | if (!cp) { | 226 | if (!cp) |
205 | printk(KERN_ERR "kAFS: no VL server IP addresses specified\n"); | 227 | _debug("kAFS: no VL server IP addresses specified"); |
206 | _leave(" = -EINVAL"); | 228 | else |
207 | return -EINVAL; | 229 | *cp++ = 0; |
208 | } | ||
209 | 230 | ||
210 | /* allocate a cell record for the root cell */ | 231 | /* allocate a cell record for the root cell */ |
211 | *cp++ = 0; | ||
212 | new_root = afs_cell_create(rootcell, cp); | 232 | new_root = afs_cell_create(rootcell, cp); |
213 | if (IS_ERR(new_root)) { | 233 | if (IS_ERR(new_root)) { |
214 | _leave(" = %ld", PTR_ERR(new_root)); | 234 | _leave(" = %ld", PTR_ERR(new_root)); |