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