resolved: flush cache each time we change to a different DNS server

This commit is contained in:
Lennart Poettering 2014-08-01 18:09:07 +02:00
parent 5cb36f41f0
commit 2c27fbca2d
8 changed files with 38 additions and 20 deletions

View File

@ -85,7 +85,7 @@ DnsScope* dns_scope_free(DnsScope *s) {
return NULL; return NULL;
} }
DnsServer *dns_scope_get_server(DnsScope *s) { DnsServer *dns_scope_get_dns_server(DnsScope *s) {
assert(s); assert(s);
if (s->protocol != DNS_PROTOCOL_DNS) if (s->protocol != DNS_PROTOCOL_DNS)
@ -133,7 +133,7 @@ int dns_scope_send(DnsScope *s, DnsPacket *p) {
if (DNS_PACKET_QDCOUNT(p) > 1) if (DNS_PACKET_QDCOUNT(p) > 1)
return -ENOTSUP; return -ENOTSUP;
srv = dns_scope_get_server(s); srv = dns_scope_get_dns_server(s);
if (!srv) if (!srv)
return -ESRCH; 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) { if (family == AF_UNSPEC) {
DnsServer *srv; DnsServer *srv;
srv = dns_scope_get_server(s); srv = dns_scope_get_dns_server(s);
if (!srv) if (!srv)
return -ESRCH; return -ESRCH;
@ -384,7 +384,7 @@ int dns_scope_good_dns_server(DnsScope *s, int family, const union in_addr_union
if (s->link) if (s->link)
return !!link_find_dns_server(s->link, family, address); return !!link_find_dns_server(s->link, family, address);
else 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( static int dns_scope_make_reply_packet(

View File

@ -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_key(DnsScope *s, DnsResourceKey *key);
int dns_scope_good_dns_server(DnsScope *s, int family, const union in_addr_union *address); 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); void dns_scope_next_dns_server(DnsScope *s);
int dns_scope_llmnr_membership(DnsScope *s, bool b); int dns_scope_llmnr_membership(DnsScope *s, bool b);

View File

@ -64,7 +64,7 @@ int dns_server_new(
if (type != DNS_SERVER_FALLBACK && if (type != DNS_SERVER_FALLBACK &&
s->manager->current_dns_server && s->manager->current_dns_server &&
s->manager->current_dns_server->type == DNS_SERVER_FALLBACK) s->manager->current_dns_server->type == DNS_SERVER_FALLBACK)
s->manager->current_dns_server = NULL; manager_set_dns_server(s->manager, NULL);
if (ret) if (ret)
*ret = s; *ret = s;
@ -88,10 +88,10 @@ DnsServer* dns_server_free(DnsServer *s) {
} }
if (s->link && s->link->current_dns_server == 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) if (s->manager && s->manager->current_dns_server == s)
s->manager->current_dns_server = NULL; manager_set_dns_server(s->manager, NULL);
free(s); free(s);

View File

@ -465,12 +465,19 @@ int dns_transaction_go(DnsTransaction *t) {
t->cached = dns_answer_unref(t->cached); t->cached = dns_answer_unref(t->cached);
t->cached_rcode = 0; 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); dns_cache_prune(&t->scope->cache);
r = dns_cache_lookup(&t->scope->cache, t->question, &t->cached_rcode, &t->cached); r = dns_cache_lookup(&t->scope->cache, t->question, &t->cached_rcode, &t->cached);
if (r < 0) if (r < 0)
return r; return r;
if (r > 0) { if (r > 0) {
log_debug("Cache hit!");
if (t->cached_rcode == DNS_RCODE_SUCCESS) if (t->cached_rcode == DNS_RCODE_SUCCESS)
dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS); dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
else else
@ -478,6 +485,8 @@ int dns_transaction_go(DnsTransaction *t) {
return 0; return 0;
} }
log_debug("Cache miss!");
/* Otherwise, we need to ask the network */ /* Otherwise, we need to ask the network */
r = dns_transaction_make_packet(t); r = dns_transaction_make_packet(t);
if (r == -EDOM) { if (r == -EDOM) {

View File

@ -248,7 +248,7 @@ DnsServer* link_find_dns_server(Link *l, int family, const union in_addr_union *
return NULL; return NULL;
} }
static DnsServer* link_set_dns_server(Link *l, DnsServer *s) { DnsServer* link_set_dns_server(Link *l, DnsServer *s) {
assert(l); assert(l);
if (l->current_dns_server == s) 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); in_addr_to_string(s->family, &s->address, &ip);
log_info("Switching to DNS server %s for interface %s.", strna(ip), l->name); 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; l->current_dns_server = s;
if (l->unicast_scope)
dns_cache_flush(&l->unicast_scope->cache);
return s; return s;
} }

View File

@ -77,6 +77,8 @@ int link_update_monitor(Link *l);
bool link_relevant(Link *l, int family); bool link_relevant(Link *l, int family);
LinkAddress* link_find_address(Link *l, int family, const union in_addr_union *in_addr); LinkAddress* link_find_address(Link *l, int family, const union in_addr_union *in_addr);
void link_add_rrs(Link *l, bool force_remove); 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_find_dns_server(Link *l, int family, const union in_addr_union *in_addr);
DnsServer* link_get_dns_server(Link *l); DnsServer* link_get_dns_server(Link *l);
void link_next_dns_server(Link *l); void link_next_dns_server(Link *l);

View File

@ -1053,7 +1053,7 @@ int manager_send(Manager *m, int fd, int ifindex, int family, const union in_add
return -EAFNOSUPPORT; 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; DnsServer *s;
assert(m); 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) LIST_FOREACH(servers, s, m->dns_servers)
if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0) 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) LIST_FOREACH(servers, s, m->fallback_dns_servers)
if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0) 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); assert(m);
if (m->current_dns_server == s) 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); in_addr_to_string(s->family, &s->address, &ip);
log_info("Switching to system DNS server %s.", strna(ip)); log_info("Switching to system DNS server %s.", strna(ip));
} else }
log_info("No system DNS server set.");
m->current_dns_server = s; m->current_dns_server = s;
if (m->unicast_scope)
dns_cache_flush(&m->unicast_scope->cache);
return s; return s;
} }

View File

@ -117,7 +117,8 @@ Manager* manager_free(Manager *m);
int manager_read_resolv_conf(Manager *m); int manager_read_resolv_conf(Manager *m);
int manager_write_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); DnsServer *manager_get_dns_server(Manager *m);
void manager_next_dns_server(Manager *m); void manager_next_dns_server(Manager *m);