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