Merge pull request #2042 from poettering/resolved-various-3

resolved: Flush caches more agressively, fixes #2038
This commit is contained in:
Tom Gundersen 2015-11-27 01:18:38 +01:00
commit 90c739259f
6 changed files with 44 additions and 18 deletions

4
TODO
View file

@ -183,16 +183,12 @@ Features:
we always process them before we process client requests we always process them before we process client requests
- DNSSEC - DNSSEC
- add display of private key types (http://tools.ietf.org/html/rfc4034#appendix-A.1.1)? - add display of private key types (http://tools.ietf.org/html/rfc4034#appendix-A.1.1)?
- DNS
- search paths
- mDNS/DNS-SD - mDNS/DNS-SD
- mDNS RR resolving - mDNS RR resolving
- service registration - service registration
- service/domain/types browsing - service/domain/types browsing
- avahi compat - avahi compat
- DNS-SD service registration from socket units - DNS-SD service registration from socket units
- edns0
- cname on PTR (?)
- resolved should optionally register additional per-interface LLMNR - resolved should optionally register additional per-interface LLMNR
names, so that for the container case we can establish the same name names, so that for the container case we can establish the same name
(maybe "host") for referencing the server, everywhere. (maybe "host") for referencing the server, everywhere.

View file

@ -44,7 +44,7 @@ int in_addr_is_link_local(int family, const union in_addr_union *u) {
assert(u); assert(u);
if (family == AF_INET) if (family == AF_INET)
return (be32toh(u->in.s_addr) & 0xFFFF0000) == (169U << 24 | 254U << 16); return (be32toh(u->in.s_addr) & UINT32_C(0xFFFF0000)) == (UINT32_C(169) << 24 | UINT32_C(254) << 16);
if (family == AF_INET6) if (family == AF_INET6)
return IN6_IS_ADDR_LINKLOCAL(&u->in6); return IN6_IS_ADDR_LINKLOCAL(&u->in6);
@ -52,6 +52,19 @@ int in_addr_is_link_local(int family, const union in_addr_union *u) {
return -EAFNOSUPPORT; return -EAFNOSUPPORT;
} }
int in_addr_is_localhost(int family, const union in_addr_union *u) {
assert(u);
if (family == AF_INET)
/* All of 127.x.x.x is localhost. */
return (be32toh(u->in.s_addr) & UINT32_C(0xFF000000)) == UINT32_C(127) << 24;
if (family == AF_INET)
return IN6_IS_ADDR_LOOPBACK(&u->in6);
return -EAFNOSUPPORT;
}
int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_union *b) { int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_union *b) {
assert(a); assert(a);
assert(b); assert(b);

View file

@ -33,6 +33,7 @@ union in_addr_union {
int in_addr_is_null(int family, const union in_addr_union *u); int in_addr_is_null(int family, const union in_addr_union *u);
int in_addr_is_link_local(int family, const union in_addr_union *u); int in_addr_is_link_local(int family, const union in_addr_union *u);
int in_addr_is_localhost(int family, const union in_addr_union *u);
int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_union *b); int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_union *b);
int in_addr_prefix_intersect(int family, const union in_addr_union *a, unsigned aprefixlen, const union in_addr_union *b, unsigned bprefixlen); int in_addr_prefix_intersect(int family, const union in_addr_union *a, unsigned aprefixlen, const union in_addr_union *b, unsigned bprefixlen);
int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen); int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen);

View file

@ -177,6 +177,14 @@ void dns_packet_rewind(DnsPacket *p, size_t idx);
int dns_packet_skip_question(DnsPacket *p); int dns_packet_skip_question(DnsPacket *p);
int dns_packet_extract(DnsPacket *p); int dns_packet_extract(DnsPacket *p);
static inline bool DNS_PACKET_SHALL_CACHE(DnsPacket *p) {
/* Never cache data originating from localhost, under the
* assumption, that it's coming from a locally DNS forwarder
* or server, that is caching on its own. */
return in_addr_is_localhost(p->family, &p->sender) == 0;
}
enum { enum {
DNS_RCODE_SUCCESS = 0, DNS_RCODE_SUCCESS = 0,
DNS_RCODE_FORMERR = 1, DNS_RCODE_FORMERR = 1,

View file

@ -478,7 +478,8 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
} }
/* According to RFC 4795, section 2.9. only the RRs from the answer section shall be cached */ /* According to RFC 4795, section 2.9. only the RRs from the answer section shall be cached */
dns_cache_put(&t->scope->cache, t->key, DNS_PACKET_RCODE(p), p->answer, DNS_PACKET_ANCOUNT(p), 0, p->family, &p->sender); if (DNS_PACKET_SHALL_CACHE(p))
dns_cache_put(&t->scope->cache, t->key, DNS_PACKET_RCODE(p), p->answer, DNS_PACKET_ANCOUNT(p), 0, p->family, &p->sender);
if (DNS_PACKET_RCODE(p) == DNS_RCODE_SUCCESS) if (DNS_PACKET_RCODE(p) == DNS_RCODE_SUCCESS)
dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS); dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);

View file

@ -50,9 +50,9 @@ int manager_read_resolv_conf(Manager *m) {
r = stat("/etc/resolv.conf", &st); r = stat("/etc/resolv.conf", &st);
if (r < 0) { if (r < 0) {
if (errno == ENOENT) if (errno == ENOENT)
r = 0; return 0;
else
r = log_warning_errno(errno, "Failed to stat /etc/resolv.conf: %m"); r = log_warning_errno(errno, "Failed to stat /etc/resolv.conf: %m");
goto clear; goto clear;
} }
@ -61,22 +61,18 @@ int manager_read_resolv_conf(Manager *m) {
if (t == m->resolv_conf_mtime) if (t == m->resolv_conf_mtime)
return 0; return 0;
m->resolv_conf_mtime = t;
/* Is it symlinked to our own file? */ /* Is it symlinked to our own file? */
if (stat("/run/systemd/resolve/resolv.conf", &own) >= 0 && if (stat("/run/systemd/resolve/resolv.conf", &own) >= 0 &&
st.st_dev == own.st_dev && st.st_dev == own.st_dev &&
st.st_ino == own.st_ino) { st.st_ino == own.st_ino)
r = 0; return 0;
goto clear;
}
f = fopen("/etc/resolv.conf", "re"); f = fopen("/etc/resolv.conf", "re");
if (!f) { if (!f) {
if (errno == ENOENT) if (errno == ENOENT)
r = 0; return 0;
else
r = log_warning_errno(errno, "Failed to open /etc/resolv.conf: %m"); r = log_warning_errno(errno, "Failed to open /etc/resolv.conf: %m");
goto clear; goto clear;
} }
@ -115,6 +111,8 @@ int manager_read_resolv_conf(Manager *m) {
} }
} }
m->resolv_conf_mtime = t;
/* Flush out all servers and search domains that are still /* Flush out all servers and search domains that are still
* marked. Those are then ones that didn't appear in the new * marked. Those are then ones that didn't appear in the new
* /etc/resolv.conf */ * /etc/resolv.conf */
@ -131,6 +129,15 @@ int manager_read_resolv_conf(Manager *m) {
* resolve VPN domains. */ * resolve VPN domains. */
manager_set_dns_server(m, m->dns_servers); manager_set_dns_server(m, m->dns_servers);
/* Unconditionally flush the cache when /etc/resolv.conf is
* modified, even if the data it contained was completely
* identical to the previous version we used. We do this
* because altering /etc/resolv.conf is typically done when
* the network configuration changes, and that should be
* enough to flush the global unicast DNS cache. */
if (m->unicast_scope)
dns_cache_flush(&m->unicast_scope->cache);
return 0; return 0;
clear: clear: