Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * linux/fs/nfs/dns_resolve.c
0004  *
0005  * Copyright (c) 2009 Trond Myklebust <Trond.Myklebust@netapp.com>
0006  *
0007  * Resolves DNS hostnames into valid ip addresses
0008  */
0009 
0010 #ifdef CONFIG_NFS_USE_KERNEL_DNS
0011 
0012 #include <linux/module.h>
0013 #include <linux/sunrpc/clnt.h>
0014 #include <linux/sunrpc/addr.h>
0015 #include <linux/dns_resolver.h>
0016 #include "dns_resolve.h"
0017 
0018 ssize_t nfs_dns_resolve_name(struct net *net, char *name, size_t namelen,
0019         struct sockaddr *sa, size_t salen)
0020 {
0021     ssize_t ret;
0022     char *ip_addr = NULL;
0023     int ip_len;
0024 
0025     ip_len = dns_query(net, NULL, name, namelen, NULL, &ip_addr, NULL,
0026                false);
0027     if (ip_len > 0)
0028         ret = rpc_pton(net, ip_addr, ip_len, sa, salen);
0029     else
0030         ret = -ESRCH;
0031     kfree(ip_addr);
0032     return ret;
0033 }
0034 
0035 #else
0036 
0037 #include <linux/module.h>
0038 #include <linux/hash.h>
0039 #include <linux/string.h>
0040 #include <linux/kmod.h>
0041 #include <linux/slab.h>
0042 #include <linux/socket.h>
0043 #include <linux/seq_file.h>
0044 #include <linux/inet.h>
0045 #include <linux/sunrpc/clnt.h>
0046 #include <linux/sunrpc/addr.h>
0047 #include <linux/sunrpc/cache.h>
0048 #include <linux/sunrpc/svcauth.h>
0049 #include <linux/sunrpc/rpc_pipe_fs.h>
0050 #include <linux/nfs_fs.h>
0051 
0052 #include "nfs4_fs.h"
0053 #include "dns_resolve.h"
0054 #include "cache_lib.h"
0055 #include "netns.h"
0056 
0057 #define NFS_DNS_HASHBITS 4
0058 #define NFS_DNS_HASHTBL_SIZE (1 << NFS_DNS_HASHBITS)
0059 
0060 struct nfs_dns_ent {
0061     struct cache_head h;
0062 
0063     char *hostname;
0064     size_t namelen;
0065 
0066     struct sockaddr_storage addr;
0067     size_t addrlen;
0068     struct rcu_head rcu_head;
0069 };
0070 
0071 
0072 static void nfs_dns_ent_update(struct cache_head *cnew,
0073         struct cache_head *ckey)
0074 {
0075     struct nfs_dns_ent *new;
0076     struct nfs_dns_ent *key;
0077 
0078     new = container_of(cnew, struct nfs_dns_ent, h);
0079     key = container_of(ckey, struct nfs_dns_ent, h);
0080 
0081     memcpy(&new->addr, &key->addr, key->addrlen);
0082     new->addrlen = key->addrlen;
0083 }
0084 
0085 static void nfs_dns_ent_init(struct cache_head *cnew,
0086         struct cache_head *ckey)
0087 {
0088     struct nfs_dns_ent *new;
0089     struct nfs_dns_ent *key;
0090 
0091     new = container_of(cnew, struct nfs_dns_ent, h);
0092     key = container_of(ckey, struct nfs_dns_ent, h);
0093 
0094     kfree(new->hostname);
0095     new->hostname = kmemdup_nul(key->hostname, key->namelen, GFP_KERNEL);
0096     if (new->hostname) {
0097         new->namelen = key->namelen;
0098         nfs_dns_ent_update(cnew, ckey);
0099     } else {
0100         new->namelen = 0;
0101         new->addrlen = 0;
0102     }
0103 }
0104 
0105 static void nfs_dns_ent_free_rcu(struct rcu_head *head)
0106 {
0107     struct nfs_dns_ent *item;
0108 
0109     item = container_of(head, struct nfs_dns_ent, rcu_head);
0110     kfree(item->hostname);
0111     kfree(item);
0112 }
0113 
0114 static void nfs_dns_ent_put(struct kref *ref)
0115 {
0116     struct nfs_dns_ent *item;
0117 
0118     item = container_of(ref, struct nfs_dns_ent, h.ref);
0119     call_rcu(&item->rcu_head, nfs_dns_ent_free_rcu);
0120 }
0121 
0122 static struct cache_head *nfs_dns_ent_alloc(void)
0123 {
0124     struct nfs_dns_ent *item = kmalloc(sizeof(*item), GFP_KERNEL);
0125 
0126     if (item != NULL) {
0127         item->hostname = NULL;
0128         item->namelen = 0;
0129         item->addrlen = 0;
0130         return &item->h;
0131     }
0132     return NULL;
0133 };
0134 
0135 static unsigned int nfs_dns_hash(const struct nfs_dns_ent *key)
0136 {
0137     return hash_str(key->hostname, NFS_DNS_HASHBITS);
0138 }
0139 
0140 static void nfs_dns_request(struct cache_detail *cd,
0141         struct cache_head *ch,
0142         char **bpp, int *blen)
0143 {
0144     struct nfs_dns_ent *key = container_of(ch, struct nfs_dns_ent, h);
0145 
0146     qword_add(bpp, blen, key->hostname);
0147     (*bpp)[-1] = '\n';
0148 }
0149 
0150 static int nfs_dns_upcall(struct cache_detail *cd,
0151         struct cache_head *ch)
0152 {
0153     struct nfs_dns_ent *key = container_of(ch, struct nfs_dns_ent, h);
0154 
0155     if (test_and_set_bit(CACHE_PENDING, &ch->flags))
0156         return 0;
0157     if (!nfs_cache_upcall(cd, key->hostname))
0158         return 0;
0159     clear_bit(CACHE_PENDING, &ch->flags);
0160     return sunrpc_cache_pipe_upcall_timeout(cd, ch);
0161 }
0162 
0163 static int nfs_dns_match(struct cache_head *ca,
0164         struct cache_head *cb)
0165 {
0166     struct nfs_dns_ent *a;
0167     struct nfs_dns_ent *b;
0168 
0169     a = container_of(ca, struct nfs_dns_ent, h);
0170     b = container_of(cb, struct nfs_dns_ent, h);
0171 
0172     if (a->namelen == 0 || a->namelen != b->namelen)
0173         return 0;
0174     return memcmp(a->hostname, b->hostname, a->namelen) == 0;
0175 }
0176 
0177 static int nfs_dns_show(struct seq_file *m, struct cache_detail *cd,
0178         struct cache_head *h)
0179 {
0180     struct nfs_dns_ent *item;
0181     long ttl;
0182 
0183     if (h == NULL) {
0184         seq_puts(m, "# ip address      hostname        ttl\n");
0185         return 0;
0186     }
0187     item = container_of(h, struct nfs_dns_ent, h);
0188     ttl = item->h.expiry_time - seconds_since_boot();
0189     if (ttl < 0)
0190         ttl = 0;
0191 
0192     if (!test_bit(CACHE_NEGATIVE, &h->flags)) {
0193         char buf[INET6_ADDRSTRLEN+IPV6_SCOPE_ID_LEN+1];
0194 
0195         rpc_ntop((struct sockaddr *)&item->addr, buf, sizeof(buf));
0196         seq_printf(m, "%15s ", buf);
0197     } else
0198         seq_puts(m, "<none>          ");
0199     seq_printf(m, "%15s %ld\n", item->hostname, ttl);
0200     return 0;
0201 }
0202 
0203 static struct nfs_dns_ent *nfs_dns_lookup(struct cache_detail *cd,
0204         struct nfs_dns_ent *key)
0205 {
0206     struct cache_head *ch;
0207 
0208     ch = sunrpc_cache_lookup_rcu(cd,
0209             &key->h,
0210             nfs_dns_hash(key));
0211     if (!ch)
0212         return NULL;
0213     return container_of(ch, struct nfs_dns_ent, h);
0214 }
0215 
0216 static struct nfs_dns_ent *nfs_dns_update(struct cache_detail *cd,
0217         struct nfs_dns_ent *new,
0218         struct nfs_dns_ent *key)
0219 {
0220     struct cache_head *ch;
0221 
0222     ch = sunrpc_cache_update(cd,
0223             &new->h, &key->h,
0224             nfs_dns_hash(key));
0225     if (!ch)
0226         return NULL;
0227     return container_of(ch, struct nfs_dns_ent, h);
0228 }
0229 
0230 static int nfs_dns_parse(struct cache_detail *cd, char *buf, int buflen)
0231 {
0232     char buf1[NFS_DNS_HOSTNAME_MAXLEN+1];
0233     struct nfs_dns_ent key, *item;
0234     unsigned int ttl;
0235     ssize_t len;
0236     int ret = -EINVAL;
0237 
0238     if (buf[buflen-1] != '\n')
0239         goto out;
0240     buf[buflen-1] = '\0';
0241 
0242     len = qword_get(&buf, buf1, sizeof(buf1));
0243     if (len <= 0)
0244         goto out;
0245     key.addrlen = rpc_pton(cd->net, buf1, len,
0246             (struct sockaddr *)&key.addr,
0247             sizeof(key.addr));
0248 
0249     len = qword_get(&buf, buf1, sizeof(buf1));
0250     if (len <= 0)
0251         goto out;
0252 
0253     key.hostname = buf1;
0254     key.namelen = len;
0255     memset(&key.h, 0, sizeof(key.h));
0256 
0257     if (get_uint(&buf, &ttl) < 0)
0258         goto out;
0259     if (ttl == 0)
0260         goto out;
0261     key.h.expiry_time = ttl + seconds_since_boot();
0262 
0263     ret = -ENOMEM;
0264     item = nfs_dns_lookup(cd, &key);
0265     if (item == NULL)
0266         goto out;
0267 
0268     if (key.addrlen == 0)
0269         set_bit(CACHE_NEGATIVE, &key.h.flags);
0270 
0271     item = nfs_dns_update(cd, &key, item);
0272     if (item == NULL)
0273         goto out;
0274 
0275     ret = 0;
0276     cache_put(&item->h, cd);
0277 out:
0278     return ret;
0279 }
0280 
0281 static int do_cache_lookup(struct cache_detail *cd,
0282         struct nfs_dns_ent *key,
0283         struct nfs_dns_ent **item,
0284         struct nfs_cache_defer_req *dreq)
0285 {
0286     int ret = -ENOMEM;
0287 
0288     *item = nfs_dns_lookup(cd, key);
0289     if (*item) {
0290         ret = cache_check(cd, &(*item)->h, &dreq->req);
0291         if (ret)
0292             *item = NULL;
0293     }
0294     return ret;
0295 }
0296 
0297 static int do_cache_lookup_nowait(struct cache_detail *cd,
0298         struct nfs_dns_ent *key,
0299         struct nfs_dns_ent **item)
0300 {
0301     int ret = -ENOMEM;
0302 
0303     *item = nfs_dns_lookup(cd, key);
0304     if (!*item)
0305         goto out_err;
0306     ret = -ETIMEDOUT;
0307     if (!test_bit(CACHE_VALID, &(*item)->h.flags)
0308             || (*item)->h.expiry_time < seconds_since_boot()
0309             || cd->flush_time > (*item)->h.last_refresh)
0310         goto out_put;
0311     ret = -ENOENT;
0312     if (test_bit(CACHE_NEGATIVE, &(*item)->h.flags))
0313         goto out_put;
0314     return 0;
0315 out_put:
0316     cache_put(&(*item)->h, cd);
0317 out_err:
0318     *item = NULL;
0319     return ret;
0320 }
0321 
0322 static int do_cache_lookup_wait(struct cache_detail *cd,
0323         struct nfs_dns_ent *key,
0324         struct nfs_dns_ent **item)
0325 {
0326     struct nfs_cache_defer_req *dreq;
0327     int ret = -ENOMEM;
0328 
0329     dreq = nfs_cache_defer_req_alloc();
0330     if (!dreq)
0331         goto out;
0332     ret = do_cache_lookup(cd, key, item, dreq);
0333     if (ret == -EAGAIN) {
0334         ret = nfs_cache_wait_for_upcall(dreq);
0335         if (!ret)
0336             ret = do_cache_lookup_nowait(cd, key, item);
0337     }
0338     nfs_cache_defer_req_put(dreq);
0339 out:
0340     return ret;
0341 }
0342 
0343 ssize_t nfs_dns_resolve_name(struct net *net, char *name,
0344         size_t namelen, struct sockaddr *sa, size_t salen)
0345 {
0346     struct nfs_dns_ent key = {
0347         .hostname = name,
0348         .namelen = namelen,
0349     };
0350     struct nfs_dns_ent *item = NULL;
0351     ssize_t ret;
0352     struct nfs_net *nn = net_generic(net, nfs_net_id);
0353 
0354     ret = do_cache_lookup_wait(nn->nfs_dns_resolve, &key, &item);
0355     if (ret == 0) {
0356         if (salen >= item->addrlen) {
0357             memcpy(sa, &item->addr, item->addrlen);
0358             ret = item->addrlen;
0359         } else
0360             ret = -EOVERFLOW;
0361         cache_put(&item->h, nn->nfs_dns_resolve);
0362     } else if (ret == -ENOENT)
0363         ret = -ESRCH;
0364     return ret;
0365 }
0366 
0367 static struct cache_detail nfs_dns_resolve_template = {
0368     .owner      = THIS_MODULE,
0369     .hash_size  = NFS_DNS_HASHTBL_SIZE,
0370     .name       = "dns_resolve",
0371     .cache_put  = nfs_dns_ent_put,
0372     .cache_upcall   = nfs_dns_upcall,
0373     .cache_request  = nfs_dns_request,
0374     .cache_parse    = nfs_dns_parse,
0375     .cache_show = nfs_dns_show,
0376     .match      = nfs_dns_match,
0377     .init       = nfs_dns_ent_init,
0378     .update     = nfs_dns_ent_update,
0379     .alloc      = nfs_dns_ent_alloc,
0380 };
0381 
0382 
0383 int nfs_dns_resolver_cache_init(struct net *net)
0384 {
0385     int err;
0386     struct nfs_net *nn = net_generic(net, nfs_net_id);
0387 
0388     nn->nfs_dns_resolve = cache_create_net(&nfs_dns_resolve_template, net);
0389     if (IS_ERR(nn->nfs_dns_resolve))
0390         return PTR_ERR(nn->nfs_dns_resolve);
0391 
0392     err = nfs_cache_register_net(net, nn->nfs_dns_resolve);
0393     if (err)
0394         goto err_reg;
0395     return 0;
0396 
0397 err_reg:
0398     cache_destroy_net(nn->nfs_dns_resolve, net);
0399     return err;
0400 }
0401 
0402 void nfs_dns_resolver_cache_destroy(struct net *net)
0403 {
0404     struct nfs_net *nn = net_generic(net, nfs_net_id);
0405 
0406     nfs_cache_unregister_net(net, nn->nfs_dns_resolve);
0407     cache_destroy_net(nn->nfs_dns_resolve, net);
0408 }
0409 
0410 static int nfs4_dns_net_init(struct net *net)
0411 {
0412     return nfs_dns_resolver_cache_init(net);
0413 }
0414 
0415 static void nfs4_dns_net_exit(struct net *net)
0416 {
0417     nfs_dns_resolver_cache_destroy(net);
0418 }
0419 
0420 static struct pernet_operations nfs4_dns_resolver_ops = {
0421     .init = nfs4_dns_net_init,
0422     .exit = nfs4_dns_net_exit,
0423 };
0424 
0425 static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event,
0426                void *ptr)
0427 {
0428     struct super_block *sb = ptr;
0429     struct net *net = sb->s_fs_info;
0430     struct nfs_net *nn = net_generic(net, nfs_net_id);
0431     struct cache_detail *cd = nn->nfs_dns_resolve;
0432     int ret = 0;
0433 
0434     if (cd == NULL)
0435         return 0;
0436 
0437     if (!try_module_get(THIS_MODULE))
0438         return 0;
0439 
0440     switch (event) {
0441     case RPC_PIPEFS_MOUNT:
0442         ret = nfs_cache_register_sb(sb, cd);
0443         break;
0444     case RPC_PIPEFS_UMOUNT:
0445         nfs_cache_unregister_sb(sb, cd);
0446         break;
0447     default:
0448         ret = -ENOTSUPP;
0449         break;
0450     }
0451     module_put(THIS_MODULE);
0452     return ret;
0453 }
0454 
0455 static struct notifier_block nfs_dns_resolver_block = {
0456     .notifier_call  = rpc_pipefs_event,
0457 };
0458 
0459 int nfs_dns_resolver_init(void)
0460 {
0461     int err;
0462 
0463     err = register_pernet_subsys(&nfs4_dns_resolver_ops);
0464     if (err < 0)
0465         goto out;
0466     err = rpc_pipefs_notifier_register(&nfs_dns_resolver_block);
0467     if (err < 0)
0468         goto out1;
0469     return 0;
0470 out1:
0471     unregister_pernet_subsys(&nfs4_dns_resolver_ops);
0472 out:
0473     return err;
0474 }
0475 
0476 void nfs_dns_resolver_destroy(void)
0477 {
0478     rpc_pipefs_notifier_unregister(&nfs_dns_resolver_block);
0479     unregister_pernet_subsys(&nfs4_dns_resolver_ops);
0480 }
0481 #endif