Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Wang Lei and committed by
Steve French
07567a55 1a4240f4

+31 -10
+1
fs/afs/Kconfig
··· 2 2 tristate "Andrew File System support (AFS) (EXPERIMENTAL)" 3 3 depends on INET && EXPERIMENTAL 4 4 select AF_RXRPC 5 + select DNS_RESOLVER 5 6 help 6 7 If you say Y here, you will get an experimental Andrew File System 7 8 driver. It currently only supports unsecured read-only AFS access.
+30 -10
fs/afs/cell.c
··· 13 13 #include <linux/slab.h> 14 14 #include <linux/key.h> 15 15 #include <linux/ctype.h> 16 + #include <linux/dns_resolver.h> 16 17 #include <linux/sched.h> 17 18 #include <keys/rxrpc-type.h> 18 19 #include "internal.h" ··· 37 36 struct key *key; 38 37 size_t namelen; 39 38 char keyname[4 + AFS_MAXCELLNAME + 1], *cp, *dp, *next; 39 + char *dvllist = NULL, *_vllist = NULL; 40 + char delimiter = ':'; 40 41 int ret; 41 42 42 43 _enter("%s,%s", name, vllist); ··· 46 43 BUG_ON(!name); /* TODO: want to look up "this cell" in the cache */ 47 44 48 45 namelen = strlen(name); 49 - if (namelen > AFS_MAXCELLNAME) 46 + if (namelen > AFS_MAXCELLNAME) { 47 + _leave(" = -ENAMETOOLONG"); 50 48 return ERR_PTR(-ENAMETOOLONG); 49 + } 51 50 52 51 /* allocate and initialise a cell record */ 53 52 cell = kzalloc(sizeof(struct afs_cell) + namelen + 1, GFP_KERNEL); ··· 69 64 INIT_LIST_HEAD(&cell->vl_list); 70 65 spin_lock_init(&cell->vl_lock); 71 66 67 + /* if the ip address is invalid, try dns query */ 68 + if (!vllist || strlen(vllist) < 7) { 69 + ret = dns_query("afsdb", name, namelen, "ipv4", &dvllist, NULL); 70 + if (ret < 0) { 71 + _leave(" = %d", ret); 72 + return ERR_PTR(ret); 73 + } 74 + _vllist = dvllist; 75 + 76 + /* change the delimiter for user-space reply */ 77 + delimiter = ','; 78 + 79 + } else { 80 + _vllist = vllist; 81 + } 82 + 72 83 /* fill in the VL server list from the rest of the string */ 73 84 do { 74 85 unsigned a, b, c, d; 75 86 76 - next = strchr(vllist, ':'); 87 + next = strchr(_vllist, delimiter); 77 88 if (next) 78 89 *next++ = 0; 79 90 80 - if (sscanf(vllist, "%u.%u.%u.%u", &a, &b, &c, &d) != 4) 91 + if (sscanf(_vllist, "%u.%u.%u.%u", &a, &b, &c, &d) != 4) 81 92 goto bad_address; 82 93 83 94 if (a > 255 || b > 255 || c > 255 || d > 255) ··· 102 81 cell->vl_addrs[cell->vl_naddrs++].s_addr = 103 82 htonl((a << 24) | (b << 16) | (c << 8) | d); 104 83 105 - } while (cell->vl_naddrs < AFS_CELL_MAX_ADDRS && (vllist = next)); 84 + } while (cell->vl_naddrs < AFS_CELL_MAX_ADDRS && (_vllist = next)); 106 85 107 86 /* create a key to represent an anonymous user */ 108 87 memcpy(keyname, "afs@", 4); ··· 131 110 ret = -EINVAL; 132 111 error: 133 112 key_put(cell->anonymous_key); 113 + kfree(dvllist); 134 114 kfree(cell); 135 115 _leave(" = %d", ret); 136 116 return ERR_PTR(ret); ··· 223 201 } 224 202 225 203 cp = strchr(rootcell, ':'); 226 - if (!cp) { 227 - printk(KERN_ERR "kAFS: no VL server IP addresses specified\n"); 228 - _leave(" = -EINVAL"); 229 - return -EINVAL; 230 - } 204 + if (!cp) 205 + _debug("kAFS: no VL server IP addresses specified"); 206 + else 207 + *cp++ = 0; 231 208 232 209 /* allocate a cell record for the root cell */ 233 - *cp++ = 0; 234 210 new_root = afs_cell_create(rootcell, cp); 235 211 if (IS_ERR(new_root)) { 236 212 _leave(" = %ld", PTR_ERR(new_root));