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 long 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 ttl = get_expiry(&buf); 244 if (ttl == 0) 245 goto out; 246 key.h.expiry_time = ttl + seconds_since_boot(); 247 248 ret = -ENOMEM; 249 item = nfs_dns_lookup(cd, &key); 250 if (item == NULL) 251 goto out; 252 253 if (key.addrlen == 0) 254 set_bit(CACHE_NEGATIVE, &key.h.flags); 255 256 item = nfs_dns_update(cd, &key, item); 257 if (item == NULL) 258 goto out; 259 260 ret = 0; 261 cache_put(&item->h, cd); 262 out: 263 return ret; 264 } 265 266 static int do_cache_lookup(struct cache_detail *cd, 267 struct nfs_dns_ent *key, 268 struct nfs_dns_ent **item, 269 struct nfs_cache_defer_req *dreq) 270 { 271 int ret = -ENOMEM; 272 273 *item = nfs_dns_lookup(cd, key); 274 if (*item) { 275 ret = cache_check(cd, &(*item)->h, &dreq->req); 276 if (ret) 277 *item = NULL; 278 } 279 return ret; 280 } 281 282 static int do_cache_lookup_nowait(struct cache_detail *cd, 283 struct nfs_dns_ent *key, 284 struct nfs_dns_ent **item) 285 { 286 int ret = -ENOMEM; 287 288 *item = nfs_dns_lookup(cd, key); 289 if (!*item) 290 goto out_err; 291 ret = -ETIMEDOUT; 292 if (!test_bit(CACHE_VALID, &(*item)->h.flags) 293 || (*item)->h.expiry_time < seconds_since_boot() 294 || cd->flush_time > (*item)->h.last_refresh) 295 goto out_put; 296 ret = -ENOENT; 297 if (test_bit(CACHE_NEGATIVE, &(*item)->h.flags)) 298 goto out_put; 299 return 0; 300 out_put: 301 cache_put(&(*item)->h, cd); 302 out_err: 303 *item = NULL; 304 return ret; 305 } 306 307 static int do_cache_lookup_wait(struct cache_detail *cd, 308 struct nfs_dns_ent *key, 309 struct nfs_dns_ent **item) 310 { 311 struct nfs_cache_defer_req *dreq; 312 int ret = -ENOMEM; 313 314 dreq = nfs_cache_defer_req_alloc(); 315 if (!dreq) 316 goto out; 317 ret = do_cache_lookup(cd, key, item, dreq); 318 if (ret == -EAGAIN) { 319 ret = nfs_cache_wait_for_upcall(dreq); 320 if (!ret) 321 ret = do_cache_lookup_nowait(cd, key, item); 322 } 323 nfs_cache_defer_req_put(dreq); 324 out: 325 return ret; 326 } 327 328 ssize_t nfs_dns_resolve_name(struct net *net, char *name, 329 size_t namelen, struct sockaddr *sa, size_t salen) 330 { 331 struct nfs_dns_ent key = { 332 .hostname = name, 333 .namelen = namelen, 334 }; 335 struct nfs_dns_ent *item = NULL; 336 ssize_t ret; 337 struct nfs_net *nn = net_generic(net, nfs_net_id); 338 339 ret = do_cache_lookup_wait(nn->nfs_dns_resolve, &key, &item); 340 if (ret == 0) { 341 if (salen >= item->addrlen) { 342 memcpy(sa, &item->addr, item->addrlen); 343 ret = item->addrlen; 344 } else 345 ret = -EOVERFLOW; 346 cache_put(&item->h, nn->nfs_dns_resolve); 347 } else if (ret == -ENOENT) 348 ret = -ESRCH; 349 return ret; 350 } 351 EXPORT_SYMBOL_GPL(nfs_dns_resolve_name); 352 353 int nfs_dns_resolver_cache_init(struct net *net) 354 { 355 int err = -ENOMEM; 356 struct nfs_net *nn = net_generic(net, nfs_net_id); 357 struct cache_detail *cd; 358 struct cache_head **tbl; 359 360 cd = kzalloc(sizeof(struct cache_detail), GFP_KERNEL); 361 if (cd == NULL) 362 goto err_cd; 363 364 tbl = kzalloc(NFS_DNS_HASHTBL_SIZE * sizeof(struct cache_head *), 365 GFP_KERNEL); 366 if (tbl == NULL) 367 goto err_tbl; 368 369 cd->owner = THIS_MODULE, 370 cd->hash_size = NFS_DNS_HASHTBL_SIZE, 371 cd->hash_table = tbl, 372 cd->name = "dns_resolve", 373 cd->cache_put = nfs_dns_ent_put, 374 cd->cache_upcall = nfs_dns_upcall, 375 cd->cache_parse = nfs_dns_parse, 376 cd->cache_show = nfs_dns_show, 377 cd->match = nfs_dns_match, 378 cd->init = nfs_dns_ent_init, 379 cd->update = nfs_dns_ent_update, 380 cd->alloc = nfs_dns_ent_alloc, 381 382 nfs_cache_init(cd); 383 err = nfs_cache_register_net(net, cd); 384 if (err) 385 goto err_reg; 386 nn->nfs_dns_resolve = cd; 387 return 0; 388 389 err_reg: 390 nfs_cache_destroy(cd); 391 kfree(cd->hash_table); 392 err_tbl: 393 kfree(cd); 394 err_cd: 395 return err; 396 } 397 398 void nfs_dns_resolver_cache_destroy(struct net *net) 399 { 400 struct nfs_net *nn = net_generic(net, nfs_net_id); 401 struct cache_detail *cd = nn->nfs_dns_resolve; 402 403 nfs_cache_unregister_net(net, cd); 404 nfs_cache_destroy(cd); 405 kfree(cd->hash_table); 406 kfree(cd); 407 } 408 409 static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event, 410 void *ptr) 411 { 412 struct super_block *sb = ptr; 413 struct net *net = sb->s_fs_info; 414 struct nfs_net *nn = net_generic(net, nfs_net_id); 415 struct cache_detail *cd = nn->nfs_dns_resolve; 416 int ret = 0; 417 418 if (cd == NULL) 419 return 0; 420 421 if (!try_module_get(THIS_MODULE)) 422 return 0; 423 424 switch (event) { 425 case RPC_PIPEFS_MOUNT: 426 ret = nfs_cache_register_sb(sb, cd); 427 break; 428 case RPC_PIPEFS_UMOUNT: 429 nfs_cache_unregister_sb(sb, cd); 430 break; 431 default: 432 ret = -ENOTSUPP; 433 break; 434 } 435 module_put(THIS_MODULE); 436 return ret; 437 } 438 439 static struct notifier_block nfs_dns_resolver_block = { 440 .notifier_call = rpc_pipefs_event, 441 }; 442 443 int nfs_dns_resolver_init(void) 444 { 445 return rpc_pipefs_notifier_register(&nfs_dns_resolver_block); 446 } 447 448 void nfs_dns_resolver_destroy(void) 449 { 450 rpc_pipefs_notifier_unregister(&nfs_dns_resolver_block); 451 } 452 #endif 453