aboutsummaryrefslogtreecommitdiffstats
path: root/fs/afs/cell.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/afs/cell.c')
-rw-r--r--fs/afs/cell.c96
1 files changed, 72 insertions, 24 deletions
diff --git a/fs/afs/cell.c b/fs/afs/cell.c
index e19c13f059ed..0d5eeadf6121 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"
@@ -30,21 +31,24 @@ static struct afs_cell *afs_cell_root;
30 * allocate a cell record and fill in its name, VL server address list and 31 * allocate a cell record and fill in its name, VL server address list and
31 * allocate an anonymous key 32 * allocate an anonymous key
32 */ 33 */
33static struct afs_cell *afs_cell_alloc(const char *name, char *vllist) 34static struct afs_cell *afs_cell_alloc(const char *name, unsigned namelen,
35 char *vllist)
34{ 36{
35 struct afs_cell *cell; 37 struct afs_cell *cell;
36 struct key *key; 38 struct key *key;
37 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", namelen, namelen, name ?: "", vllist);
42 45
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 if (namelen > AFS_MAXCELLNAME) {
46 if (namelen > AFS_MAXCELLNAME) 49 _leave(" = -ENAMETOOLONG");
47 return ERR_PTR(-ENAMETOOLONG); 50 return ERR_PTR(-ENAMETOOLONG);
51 }
48 52
49 /* allocate and initialise a cell record */ 53 /* allocate and initialise a cell record */
50 cell = kzalloc(sizeof(struct afs_cell) + namelen + 1, GFP_KERNEL); 54 cell = kzalloc(sizeof(struct afs_cell) + namelen + 1, GFP_KERNEL);
@@ -64,15 +68,35 @@ static struct afs_cell *afs_cell_alloc(const char *name, char *vllist)
64 INIT_LIST_HEAD(&cell->vl_list); 68 INIT_LIST_HEAD(&cell->vl_list);
65 spin_lock_init(&cell->vl_lock); 69 spin_lock_init(&cell->vl_lock);
66 70
71 /* if the ip address is invalid, try dns query */
72 if (!vllist || strlen(vllist) < 7) {
73 ret = dns_query("afsdb", name, namelen, "ipv4", &dvllist, NULL);
74 if (ret < 0) {
75 if (ret == -ENODATA || ret == -EAGAIN || ret == -ENOKEY)
76 /* translate these errors into something
77 * userspace might understand */
78 ret = -EDESTADDRREQ;
79 _leave(" = %d", ret);
80 return ERR_PTR(ret);
81 }
82 _vllist = dvllist;
83
84 /* change the delimiter for user-space reply */
85 delimiter = ',';
86
87 } else {
88 _vllist = vllist;
89 }
90
67 /* fill in the VL server list from the rest of the string */ 91 /* fill in the VL server list from the rest of the string */
68 do { 92 do {
69 unsigned a, b, c, d; 93 unsigned a, b, c, d;
70 94
71 next = strchr(vllist, ':'); 95 next = strchr(_vllist, delimiter);
72 if (next) 96 if (next)
73 *next++ = 0; 97 *next++ = 0;
74 98
75 if (sscanf(vllist, "%u.%u.%u.%u", &a, &b, &c, &d) != 4) 99 if (sscanf(_vllist, "%u.%u.%u.%u", &a, &b, &c, &d) != 4)
76 goto bad_address; 100 goto bad_address;
77 101
78 if (a > 255 || b > 255 || c > 255 || d > 255) 102 if (a > 255 || b > 255 || c > 255 || d > 255)
@@ -81,7 +105,7 @@ static struct afs_cell *afs_cell_alloc(const char *name, char *vllist)
81 cell->vl_addrs[cell->vl_naddrs++].s_addr = 105 cell->vl_addrs[cell->vl_naddrs++].s_addr =
82 htonl((a << 24) | (b << 16) | (c << 8) | d); 106 htonl((a << 24) | (b << 16) | (c << 8) | d);
83 107
84 } while (cell->vl_naddrs < AFS_CELL_MAX_ADDRS && (vllist = next)); 108 } while (cell->vl_naddrs < AFS_CELL_MAX_ADDRS && (_vllist = next));
85 109
86 /* create a key to represent an anonymous user */ 110 /* create a key to represent an anonymous user */
87 memcpy(keyname, "afs@", 4); 111 memcpy(keyname, "afs@", 4);
@@ -110,32 +134,36 @@ bad_address:
110 ret = -EINVAL; 134 ret = -EINVAL;
111error: 135error:
112 key_put(cell->anonymous_key); 136 key_put(cell->anonymous_key);
137 kfree(dvllist);
113 kfree(cell); 138 kfree(cell);
114 _leave(" = %d", ret); 139 _leave(" = %d", ret);
115 return ERR_PTR(ret); 140 return ERR_PTR(ret);
116} 141}
117 142
118/* 143/*
119 * create a cell record 144 * afs_cell_crate() - create a cell record
120 * - "name" is the name of the cell 145 * @name: is the name of the cell.
121 * - "vllist" is a colon separated list of IP addresses in "a.b.c.d" format 146 * @namsesz: is the strlen of the cell name.
147 * @vllist: is a colon separated list of IP addresses in "a.b.c.d" format.
148 * @retref: is T to return the cell reference when the cell exists.
122 */ 149 */
123struct afs_cell *afs_cell_create(const char *name, char *vllist) 150struct afs_cell *afs_cell_create(const char *name, unsigned namesz,
151 char *vllist, bool retref)
124{ 152{
125 struct afs_cell *cell; 153 struct afs_cell *cell;
126 int ret; 154 int ret;
127 155
128 _enter("%s,%s", name, vllist); 156 _enter("%*.*s,%s", namesz, namesz, name ?: "", vllist);
129 157
130 down_write(&afs_cells_sem); 158 down_write(&afs_cells_sem);
131 read_lock(&afs_cells_lock); 159 read_lock(&afs_cells_lock);
132 list_for_each_entry(cell, &afs_cells, link) { 160 list_for_each_entry(cell, &afs_cells, link) {
133 if (strcasecmp(cell->name, name) == 0) 161 if (strncasecmp(cell->name, name, namesz) == 0)
134 goto duplicate_name; 162 goto duplicate_name;
135 } 163 }
136 read_unlock(&afs_cells_lock); 164 read_unlock(&afs_cells_lock);
137 165
138 cell = afs_cell_alloc(name, vllist); 166 cell = afs_cell_alloc(name, namesz, vllist);
139 if (IS_ERR(cell)) { 167 if (IS_ERR(cell)) {
140 _leave(" = %ld", PTR_ERR(cell)); 168 _leave(" = %ld", PTR_ERR(cell));
141 up_write(&afs_cells_sem); 169 up_write(&afs_cells_sem);
@@ -175,8 +203,18 @@ error:
175 return ERR_PTR(ret); 203 return ERR_PTR(ret);
176 204
177duplicate_name: 205duplicate_name:
206 if (retref && !IS_ERR(cell))
207 afs_get_cell(cell);
208
178 read_unlock(&afs_cells_lock); 209 read_unlock(&afs_cells_lock);
179 up_write(&afs_cells_sem); 210 up_write(&afs_cells_sem);
211
212 if (retref) {
213 _leave(" = %p", cell);
214 return cell;
215 }
216
217 _leave(" = -EEXIST");
180 return ERR_PTR(-EEXIST); 218 return ERR_PTR(-EEXIST);
181} 219}
182 220
@@ -201,15 +239,13 @@ int afs_cell_init(char *rootcell)
201 } 239 }
202 240
203 cp = strchr(rootcell, ':'); 241 cp = strchr(rootcell, ':');
204 if (!cp) { 242 if (!cp)
205 printk(KERN_ERR "kAFS: no VL server IP addresses specified\n"); 243 _debug("kAFS: no VL server IP addresses specified");
206 _leave(" = -EINVAL"); 244 else
207 return -EINVAL; 245 *cp++ = 0;
208 }
209 246
210 /* allocate a cell record for the root cell */ 247 /* allocate a cell record for the root cell */
211 *cp++ = 0; 248 new_root = afs_cell_create(rootcell, strlen(rootcell), cp, false);
212 new_root = afs_cell_create(rootcell, cp);
213 if (IS_ERR(new_root)) { 249 if (IS_ERR(new_root)) {
214 _leave(" = %ld", PTR_ERR(new_root)); 250 _leave(" = %ld", PTR_ERR(new_root));
215 return PTR_ERR(new_root); 251 return PTR_ERR(new_root);
@@ -229,11 +265,12 @@ int afs_cell_init(char *rootcell)
229/* 265/*
230 * lookup a cell record 266 * lookup a cell record
231 */ 267 */
232struct afs_cell *afs_cell_lookup(const char *name, unsigned namesz) 268struct afs_cell *afs_cell_lookup(const char *name, unsigned namesz,
269 bool dns_cell)
233{ 270{
234 struct afs_cell *cell; 271 struct afs_cell *cell;
235 272
236 _enter("\"%*.*s\",", namesz, namesz, name ? name : ""); 273 _enter("\"%*.*s\",", namesz, namesz, name ?: "");
237 274
238 down_read(&afs_cells_sem); 275 down_read(&afs_cells_sem);
239 read_lock(&afs_cells_lock); 276 read_lock(&afs_cells_lock);
@@ -247,6 +284,8 @@ struct afs_cell *afs_cell_lookup(const char *name, unsigned namesz)
247 } 284 }
248 } 285 }
249 cell = ERR_PTR(-ENOENT); 286 cell = ERR_PTR(-ENOENT);
287 if (dns_cell)
288 goto create_cell;
250 found: 289 found:
251 ; 290 ;
252 } else { 291 } else {
@@ -269,6 +308,15 @@ struct afs_cell *afs_cell_lookup(const char *name, unsigned namesz)
269 up_read(&afs_cells_sem); 308 up_read(&afs_cells_sem);
270 _leave(" = %p", cell); 309 _leave(" = %p", cell);
271 return cell; 310 return cell;
311
312create_cell:
313 read_unlock(&afs_cells_lock);
314 up_read(&afs_cells_sem);
315
316 cell = afs_cell_create(name, namesz, NULL, true);
317
318 _leave(" = %p", cell);
319 return cell;
272} 320}
273 321
274#if 0 322#if 0