1 /* 2 * linux/fs/nfs/dns_resolve.c 3 * 4 * Copyright (c) 2009 Trond Myklebust <Trond.Myklebust@netapp.com> 5 * 6 * Resolves DNS hostnames into valid ip addresses 7 */ 8 9 #ifdef CONFIG_NFS_USE_KERNEL_DNS 10 11 #include <linux/sunrpc/clnt.h> 12 #include <linux/dns_resolver.h> 13 #include "dns_resolve.h" 14 15 ssize_t nfs_dns_resolve_name(struct net *net, char *name, size_t namelen, 16 struct sockaddr *sa, size_t salen) 17 { 18 ssize_t ret; 19 char *ip_addr = NULL; 20 int ip_len; 21 22 ip_len = dns_query(NULL, name, namelen, NULL, &ip_addr, NULL); 23 if (ip_len > 0) 24 ret = rpc_pton(net, ip_addr, ip_len, sa, salen); 25 else 26 ret = -ESRCH; 27 kfree(ip_addr); 28 return ret; 29 } 30 31 #else 32 33 #include <linux/hash.h> 34 #include <linux/string.h> 35 #include <linux/kmod.h> 36 #include <linux/slab.h> 37 #include <linux/module.h> 38 #include <linux/socket.h> 39 #include <linux/seq_file.h> 40 #include <linux/inet.h> 41 #include <linux/sunrpc/clnt.h> 42 #include <linux/sunrpc/cache.h> 43 #include <linux/sunrpc/svcauth.h> 44 #include <linux/sunrpc/rpc_pipe_fs.h> 45 46 #include "dns_resolve.h" 47 #include "cache_lib.h" 48 #include "netns.h" 49 50 #define NFS_DNS_HASHBITS 4 51 #define NFS_DNS_HASHTBL_SIZE (1 << NFS_DNS_HASHBITS) 52 53 struct nfs_dns_ent { 54 struct cache_head h; 55 56 char *hostname; 57 size_t namelen; 58 59 struct sockaddr_storage addr; 60 size_t addrlen; 61 }; 62 63 64 static void nfs_dns_ent_update(struct cache_head *cnew, 65 struct cache_head *ckey) 66 { 67 struct nfs_dns_ent *new; 68 struct nfs_dns_ent *key; 69 70 new = container_of(cnew, struct nfs_dns_ent, h); 71 key = container_of(ckey, struct nfs_dns_ent, h); 72 73 memcpy(&new->addr, &key->addr, key->addrlen); 74 new->addrlen = key->addrlen; 75 } 76 77 static void nfs_dns_ent_init(struct cache_head *cnew, 78 struct cache_head *ckey) 79 { 80 struct nfs_dns_ent *new; 81 struct nfs_dns_ent *key; 82 83 new = container_of(cnew, struct nfs_dns_ent, h); 84 key = container_of(ckey, struct nfs_dns_ent, h); 85 86 kfree(new->hostname); 87 new->hostname = kstrndup(key->hostname, key->namelen, GFP_KERNEL); 88 if (new->hostname) { 89 new->namelen = key->namelen; 90 nfs_dns_ent_update(cnew, ckey); 91 } else { 92 new->namelen = 0; 93 new->addrlen = 0; 94 } 95 } 96 97 static void nfs_dns_ent_put(struct kref *ref) 98 { 99 struct nfs_dns_ent *item; 100 101 item = container_of(ref, struct nfs_dns_ent, h.ref); 102 kfree(item->hostname); 103 kfree(item); 104 } 105 106 static struct cache_head *nfs_dns_ent_alloc(void) 107 { 108 struct nfs_dns_ent *item = kmalloc(sizeof(*item), GFP_KERNEL); 109 110 if (item != NULL) { 111 item->hostname = NULL; 112 item->namelen = 0; 113 item->addrlen = 0; 114 return &item->h; 115 } 116 return NULL; 117 }; 118 119 static unsigned int nfs_dns_hash(const struct nfs_dns_ent *key) 120 { 121 return hash_str(key->hostname, NFS_DNS_HASHBITS); 122 } 123 124 static void nfs_dns_request(struct cache_detail *cd, 125 struct cache_head *ch, 126 char **bpp, int *blen) 127 { 128 struct nfs_dns_ent *key = container_of(ch, struct nfs_dns_ent, h); 129 130 qword_add(bpp, blen, key->hostname); 131 (*bpp)[-1] = '\n'; 132 } 133 134 static int nfs_dns_upcall(struct cache_detail *cd, 135 struct cache_head *ch) 136 { 137 struct nfs_dns_ent *key = container_of(ch, struct nfs_dns_ent, h); 138 int ret; 139 140 ret = nfs_cache_upcall(cd, key->hostname); 141 if (ret) 142 ret = sunrpc_cache_pipe_upcall(cd, ch, nfs_dns_request); 143 return ret; 144 } 145 146 static int nfs_dns_match(struct cache_head *ca, 147 struct cache_head *cb) 148 { 149 struct nfs_dns_ent *a; 150 struct nfs_dns_ent *b; 151 152 a = container_of(ca, struct nfs_dns_ent, h); 153 b = container_of(cb, struct nfs_dns_ent, h); 154 155 if (a->namelen == 0 || a->namelen != b->namelen) 156 return 0; 157 return memcmp(a->hostname, b->hostname, a->namelen) == 0; 158 } 159 160 static int nfs_dns_show(struct seq_file *m, struct cache_detail *cd, 161 struct cache_head *h) 162 { 163 struct nfs_dns_ent *item; 164 long ttl; 165 166 if (h == NULL) { 167 seq_puts(m, "# ip address hostname ttl\n"); 168 return 0; 169 } 170 item = container_of(h, struct nfs_dns_ent, h); 171 ttl = item->h.expiry_time - seconds_since_boot(); 172 if (ttl < 0) 173 ttl = 0; 174 175 if (!test_bit(CACHE_NEGATIVE, &h->flags)) { 176 char buf[INET6_ADDRSTRLEN+IPV6_SCOPE_ID_LEN+1]; 177 178 rpc_ntop((struct sockaddr *)&item->addr, buf, sizeof(buf)); 179 seq_printf(m, "%15s ", buf); 180 } else 181 seq_puts(m, "<none> "); 182 seq_printf(m, "%15s %ld\n", item->hostname, ttl); 183 return 0; 184 } 185 186 static struct nfs_dns_ent *nfs_dns_lookup(struct cache_detail *cd, 187 struct nfs_dns_ent *key) 188 { 189 struct cache_head *ch; 190 191 ch = sunrpc_cache_lookup(cd, 192 &key->h, 193 nfs_dns_hash(key)); 194 if (!ch) 195 return NULL; 196 return container_of(ch, struct nfs_dns_ent, h); 197 } 198 199 static struct nfs_dns_ent *nfs_dns_update(struct cache_detail *cd, 200 struct nfs_dns_ent *new, 201 struct nfs_dns_ent *key) 202 { 203 struct cache_head *ch; 204 205 ch = sunrpc_cache_update(cd, 206 &new->h, &key->h, 207 nfs_dns_hash(key)); 208 if (!ch) 209 return NULL; 210 return container_of(ch, struct nfs_dns_ent, h); 211 } 212 213 static int nfs_dns_parse(struct cache_detail *cd, char *buf, int buflen) 214 { 215 char buf1[NFS_DNS_HOSTNAME_MAXLEN+1]; 216 struct nfs_dns_ent key, *item; 217 unsigned long ttl; 218 ssize_t len; 219 int ret = -EINVAL; 220 221 if (buf[buflen-1] != '\n') 222 goto out; 223 buf[buflen-1] = '\0'; 224 225 len = qword_get(&buf, buf1, sizeof(buf1)); 226 if (len <= 0) 227 goto out; 228 key.addrlen = rpc_pton(cd->net, buf1, len, 229 (struct sockaddr *)&key.addr, 230 sizeof(key.addr)); 231 232 len = qword_get(&buf, buf1, sizeof(buf1)); 233 if (len <= 0) 234 goto out; 235 236 key.hostname = buf1; 237 key.namelen = len; 238 memset(&key.h, 0, sizeof(key.h)); 239 240 ttl = get_expiry(&buf); 241 if (ttl == 0) 242 goto out; 243 key.h.expiry_time = ttl + seconds_since_boot(); 244 245 ret = -ENOMEM; 246 item = nfs_dns_lookup(cd, &key); 247 if (item == NULL) 248 goto out; 249 250 if (key.addrlen == 0) 251 set_bit(CACHE_NEGATIVE, &key.h.flags); 252 253 item = nfs_dns_update(cd, &key, item); 254 if (item == NULL) 255 goto out; 256 257 ret = 0; 258 cache_put(&item->h, cd); 259 out: 260 return ret; 261 } 262 263 static int do_cache_lookup(struct cache_detail *cd, 264 struct nfs_dns_ent *key, 265 struct nfs_dns_ent **item, 266 struct nfs_cache_defer_req *dreq) 267 { 268 int ret = -ENOMEM; 269 270 *item = nfs_dns_lookup(cd, key); 271 if (*item) { 272 ret = cache_check(cd, &(*item)->h, &dreq->req); 273 if (ret) 274 *item = NULL; 275 } 276 return ret; 277 } 278 279 static int do_cache_lookup_nowait(struct cache_detail *cd, 280 struct nfs_dns_ent *key, 281 struct nfs_dns_ent **item) 282 { 283 int ret = -ENOMEM; 284 285 *item = nfs_dns_lookup(cd, key); 286 if (!*item) 287 goto out_err; 288 ret = -ETIMEDOUT; 289 if (!test_bit(CACHE_VALID, &(*item)->h.flags) 290 || (*item)->h.expiry_time < seconds_since_boot() 291 || cd->flush_time > (*item)->h.last_refresh) 292 goto out_put; 293 ret = -ENOENT; 294 if (test_bit(CACHE_NEGATIVE, &(*item)->h.flags)) 295 goto out_put; 296 return 0; 297 out_put: 298 cache_put(&(*item)->h, cd); 299 out_err: 300 *item = NULL; 301 return ret; 302 } 303 304 static int do_cache_lookup_wait(struct cache_detail *cd, 305 struct nfs_dns_ent *key, 306 struct nfs_dns_ent **item) 307 { 308 struct nfs_cache_defer_req *dreq; 309 int ret = -ENOMEM; 310 311 dreq = nfs_cache_defer_req_alloc(); 312 if (!dreq) 313 goto out; 314 ret = do_cache_lookup(cd, key, item, dreq); 315 if (ret == -EAGAIN) { 316 ret = nfs_cache_wait_for_upcall(dreq); 317 if (!ret) 318 ret = do_cache_lookup_nowait(cd, key, item); 319 } 320 nfs_cache_defer_req_put(dreq); 321 out: 322 return ret; 323 } 324 325 ssize_t nfs_dns_resolve_name(struct net *net, char *name, 326 size_t namelen, struct sockaddr *sa, size_t salen) 327 { 328 struct nfs_dns_ent key = { 329 .hostname = name, 330 .namelen = namelen, 331 }; 332 struct nfs_dns_ent *item = NULL; 333 ssize_t ret; 334 struct nfs_net *nn = net_generic(net, nfs_net_id); 335 336 ret = do_cache_lookup_wait(nn->nfs_dns_resolve, &key, &item); 337 if (ret == 0) { 338 if (salen >= item->addrlen) { 339 memcpy(sa, &item->addr, item->addrlen); 340 ret = item->addrlen; 341 } else 342 ret = -EOVERFLOW; 343 cache_put(&item->h, nn->nfs_dns_resolve); 344 } else if (ret == -ENOENT) 345 ret = -ESRCH; 346 return ret; 347 } 348 349 int nfs_dns_resolver_cache_init(struct net *net) 350 { 351 int err = -ENOMEM; 352 struct nfs_net *nn = net_generic(net, nfs_net_id); 353 struct cache_detail *cd; 354 struct cache_head **tbl; 355 356 cd = kzalloc(sizeof(struct cache_detail), GFP_KERNEL); 357 if (cd == NULL) 358 goto err_cd; 359 360 tbl = kzalloc(NFS_DNS_HASHTBL_SIZE * sizeof(struct cache_head *), 361 GFP_KERNEL); 362 if (tbl == NULL) 363 goto err_tbl; 364 365 cd->owner = THIS_MODULE, 366 cd->hash_size = NFS_DNS_HASHTBL_SIZE, 367 cd->hash_table = tbl, 368 cd->name = "dns_resolve", 369 cd->cache_put = nfs_dns_ent_put, 370 cd->cache_upcall = nfs_dns_upcall, 371 cd->cache_parse = nfs_dns_parse, 372 cd->cache_show = nfs_dns_show, 373 cd->match = nfs_dns_match, 374 cd->init = nfs_dns_ent_init, 375 cd->update = nfs_dns_ent_update, 376 cd->alloc = nfs_dns_ent_alloc, 377 378 nfs_cache_init(cd); 379 err = nfs_cache_register_net(net, cd); 380 if (err) 381 goto err_reg; 382 nn->nfs_dns_resolve = cd; 383 return 0; 384 385 err_reg: 386 nfs_cache_destroy(cd); 387 kfree(cd->hash_table); 388 err_tbl: 389 kfree(cd); 390 err_cd: 391 return err; 392 } 393 394 void nfs_dns_resolver_cache_destroy(struct net *net) 395 { 396 struct nfs_net *nn = net_generic(net, nfs_net_id); 397 struct cache_detail *cd = nn->nfs_dns_resolve; 398 399 nfs_cache_unregister_net(net, cd); 400 nfs_cache_destroy(cd); 401 kfree(cd->hash_table); 402 kfree(cd); 403 } 404 405 static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event, 406 void *ptr) 407 { 408 struct super_block *sb = ptr; 409 struct net *net = sb->s_fs_info; 410 struct nfs_net *nn = net_generic(net, nfs_net_id); 411 struct cache_detail *cd = nn->nfs_dns_resolve; 412 int ret = 0; 413 414 if (cd == NULL) 415 return 0; 416 417 if (!try_module_get(THIS_MODULE)) 418 return 0; 419 420 switch (event) { 421 case RPC_PIPEFS_MOUNT: 422 ret = nfs_cache_register_sb(sb, cd); 423 break; 424 case RPC_PIPEFS_UMOUNT: 425 nfs_cache_unregister_sb(sb, cd); 426 break; 427 default: 428 ret = -ENOTSUPP; 429 break; 430 } 431 module_put(THIS_MODULE); 432 return ret; 433 } 434 435 static struct notifier_block nfs_dns_resolver_block = { 436 .notifier_call = rpc_pipefs_event, 437 }; 438 439 int nfs_dns_resolver_init(void) 440 { 441 return rpc_pipefs_notifier_register(&nfs_dns_resolver_block); 442 } 443 444 void nfs_dns_resolver_destroy(void) 445 { 446 rpc_pipefs_notifier_unregister(&nfs_dns_resolver_block); 447 } 448 #endif 449