]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
resolved: never cache RRs originating from localhost
authorLennart Poettering <lennart@poettering.net>
Thu, 26 Nov 2015 23:41:32 +0000 (00:41 +0100)
committerLennart Poettering <lennart@poettering.net>
Thu, 26 Nov 2015 23:46:51 +0000 (00:46 +0100)
After all, this is likely a local DNS forwarder that caches anyway,
hence there's no point in caching twice.

Fixes #2038.

src/basic/in-addr-util.c
src/basic/in-addr-util.h
src/resolve/resolved-dns-packet.h
src/resolve/resolved-dns-transaction.c

index f4e24121e7b80b8a0c49e1df2f81a2f45ea9dcc7..1f61b68efdb3333776fed35ab411abe2d6216906 100644 (file)
@@ -44,7 +44,7 @@ int in_addr_is_link_local(int family, const union in_addr_union *u) {
         assert(u);
 
         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)
                 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;
 }
 
+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) {
         assert(a);
         assert(b);
index 51af08868cda48af0db4681613a5be4b853234ac..58f55b341850c866d39f724e2c04d833f2301f8c 100644 (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_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_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);
index 48df5dfc53224276a9231cafc09552cdb07d4dfa..90b5a7c8bd81a130fb83f1f9212c80101a400b90 100644 (file)
@@ -177,6 +177,14 @@ void dns_packet_rewind(DnsPacket *p, size_t idx);
 int dns_packet_skip_question(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 {
         DNS_RCODE_SUCCESS = 0,
         DNS_RCODE_FORMERR = 1,
index c65c9c9f492160772f6a834a09b94c49414e4694..8c4f23a4dae36014db106f98370db6e0850cd451 100644 (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 */
-        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)
                 dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);