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