Merge pull request #2042 from poettering/resolved-various-3
resolved: Flush caches more agressively, fixes #2038
This commit is contained in:
commit
90c739259f
4
TODO
4
TODO
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in a new issue