From 2c27fbca2d88214bd305272308a370a962818f1e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 1 Aug 2014 18:09:07 +0200 Subject: [PATCH] resolved: flush cache each time we change to a different DNS server --- src/resolve/resolved-dns-scope.c | 8 ++++---- src/resolve/resolved-dns-scope.h | 2 +- src/resolve/resolved-dns-server.c | 6 +++--- src/resolve/resolved-dns-transaction.c | 11 ++++++++++- src/resolve/resolved-link.c | 9 ++++++--- src/resolve/resolved-link.h | 2 ++ src/resolve/resolved-manager.c | 17 ++++++++++------- src/resolve/resolved-manager.h | 3 ++- 8 files changed, 38 insertions(+), 20 deletions(-) diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index 42a2fc4c7..291d0356b 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -85,7 +85,7 @@ DnsScope* dns_scope_free(DnsScope *s) { return NULL; } -DnsServer *dns_scope_get_server(DnsScope *s) { +DnsServer *dns_scope_get_dns_server(DnsScope *s) { assert(s); if (s->protocol != DNS_PROTOCOL_DNS) @@ -133,7 +133,7 @@ int dns_scope_send(DnsScope *s, DnsPacket *p) { if (DNS_PACKET_QDCOUNT(p) > 1) return -ENOTSUP; - srv = dns_scope_get_server(s); + srv = dns_scope_get_dns_server(s); if (!srv) return -ESRCH; @@ -197,7 +197,7 @@ int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *add if (family == AF_UNSPEC) { DnsServer *srv; - srv = dns_scope_get_server(s); + srv = dns_scope_get_dns_server(s); if (!srv) return -ESRCH; @@ -384,7 +384,7 @@ int dns_scope_good_dns_server(DnsScope *s, int family, const union in_addr_union if (s->link) return !!link_find_dns_server(s->link, family, address); else - return manager_known_dns_server(s->manager, family, address); + return !!manager_find_dns_server(s->manager, family, address); } static int dns_scope_make_reply_packet( diff --git a/src/resolve/resolved-dns-scope.h b/src/resolve/resolved-dns-scope.h index 8f4206834..313c6178d 100644 --- a/src/resolve/resolved-dns-scope.h +++ b/src/resolve/resolved-dns-scope.h @@ -70,7 +70,7 @@ DnsScopeMatch dns_scope_good_domain(DnsScope *s, const char *domain); int dns_scope_good_key(DnsScope *s, DnsResourceKey *key); int dns_scope_good_dns_server(DnsScope *s, int family, const union in_addr_union *address); -DnsServer *dns_scope_get_server(DnsScope *s); +DnsServer *dns_scope_get_dns_server(DnsScope *s); void dns_scope_next_dns_server(DnsScope *s); int dns_scope_llmnr_membership(DnsScope *s, bool b); diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c index 2c413370e..30d9c8b34 100644 --- a/src/resolve/resolved-dns-server.c +++ b/src/resolve/resolved-dns-server.c @@ -64,7 +64,7 @@ int dns_server_new( if (type != DNS_SERVER_FALLBACK && s->manager->current_dns_server && s->manager->current_dns_server->type == DNS_SERVER_FALLBACK) - s->manager->current_dns_server = NULL; + manager_set_dns_server(s->manager, NULL); if (ret) *ret = s; @@ -88,10 +88,10 @@ DnsServer* dns_server_free(DnsServer *s) { } if (s->link && s->link->current_dns_server == s) - s->link->current_dns_server = NULL; + link_set_dns_server(s->link, NULL); if (s->manager && s->manager->current_dns_server == s) - s->manager->current_dns_server = NULL; + manager_set_dns_server(s->manager, NULL); free(s); diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c index faa1de914..48da432a1 100644 --- a/src/resolve/resolved-dns-transaction.c +++ b/src/resolve/resolved-dns-transaction.c @@ -465,12 +465,19 @@ int dns_transaction_go(DnsTransaction *t) { t->cached = dns_answer_unref(t->cached); t->cached_rcode = 0; - /* First, let's try the cache */ + /* Before trying the cache, let's make sure we figured out a + * server to use. Should this cause a change of server this + * might flush the cache. */ + dns_scope_get_dns_server(t->scope); + + /* Let's then prune all outdated entries */ dns_cache_prune(&t->scope->cache); + r = dns_cache_lookup(&t->scope->cache, t->question, &t->cached_rcode, &t->cached); if (r < 0) return r; if (r > 0) { + log_debug("Cache hit!"); if (t->cached_rcode == DNS_RCODE_SUCCESS) dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS); else @@ -478,6 +485,8 @@ int dns_transaction_go(DnsTransaction *t) { return 0; } + log_debug("Cache miss!"); + /* Otherwise, we need to ask the network */ r = dns_transaction_make_packet(t); if (r == -EDOM) { diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c index 7418ea1ed..2c02f0947 100644 --- a/src/resolve/resolved-link.c +++ b/src/resolve/resolved-link.c @@ -248,7 +248,7 @@ DnsServer* link_find_dns_server(Link *l, int family, const union in_addr_union * return NULL; } -static DnsServer* link_set_dns_server(Link *l, DnsServer *s) { +DnsServer* link_set_dns_server(Link *l, DnsServer *s) { assert(l); if (l->current_dns_server == s) @@ -259,10 +259,13 @@ static DnsServer* link_set_dns_server(Link *l, DnsServer *s) { in_addr_to_string(s->family, &s->address, &ip); log_info("Switching to DNS server %s for interface %s.", strna(ip), l->name); - } else - log_info("No DNS server set for interface %s.", l->name); + } l->current_dns_server = s; + + if (l->unicast_scope) + dns_cache_flush(&l->unicast_scope->cache); + return s; } diff --git a/src/resolve/resolved-link.h b/src/resolve/resolved-link.h index d29311e04..38bb39271 100644 --- a/src/resolve/resolved-link.h +++ b/src/resolve/resolved-link.h @@ -77,6 +77,8 @@ int link_update_monitor(Link *l); bool link_relevant(Link *l, int family); LinkAddress* link_find_address(Link *l, int family, const union in_addr_union *in_addr); void link_add_rrs(Link *l, bool force_remove); + +DnsServer* link_set_dns_server(Link *l, DnsServer *s); DnsServer* link_find_dns_server(Link *l, int family, const union in_addr_union *in_addr); DnsServer* link_get_dns_server(Link *l); void link_next_dns_server(Link *l); diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index ba2380d68..5ed7a9fd1 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -1053,7 +1053,7 @@ int manager_send(Manager *m, int fd, int ifindex, int family, const union in_add return -EAFNOSUPPORT; } -bool manager_known_dns_server(Manager *m, int family, const union in_addr_union *in_addr) { +DnsServer* manager_find_dns_server(Manager *m, int family, const union in_addr_union *in_addr) { DnsServer *s; assert(m); @@ -1061,16 +1061,16 @@ bool manager_known_dns_server(Manager *m, int family, const union in_addr_union LIST_FOREACH(servers, s, m->dns_servers) if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0) - return true; + return s; LIST_FOREACH(servers, s, m->fallback_dns_servers) if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0) - return true; + return s; - return false; + return NULL; } -static DnsServer *manager_set_dns_server(Manager *m, DnsServer *s) { +DnsServer *manager_set_dns_server(Manager *m, DnsServer *s) { assert(m); if (m->current_dns_server == s) @@ -1081,10 +1081,13 @@ static DnsServer *manager_set_dns_server(Manager *m, DnsServer *s) { in_addr_to_string(s->family, &s->address, &ip); log_info("Switching to system DNS server %s.", strna(ip)); - } else - log_info("No system DNS server set."); + } m->current_dns_server = s; + + if (m->unicast_scope) + dns_cache_flush(&m->unicast_scope->cache); + return s; } diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h index 7bb18c0d6..31d670da4 100644 --- a/src/resolve/resolved-manager.h +++ b/src/resolve/resolved-manager.h @@ -117,7 +117,8 @@ Manager* manager_free(Manager *m); int manager_read_resolv_conf(Manager *m); int manager_write_resolv_conf(Manager *m); -bool manager_known_dns_server(Manager *m, int family, const union in_addr_union *in_addr); +DnsServer *manager_set_dns_server(Manager *m, DnsServer *s); +DnsServer *manager_find_dns_server(Manager *m, int family, const union in_addr_union *in_addr); DnsServer *manager_get_dns_server(Manager *m); void manager_next_dns_server(Manager *m); -- 2.30.2