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