]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
resolved: fix mistaking QU bit for cache-flush bit
authorSergey Bugaev <bugaevc@gmail.com>
Fri, 19 Feb 2021 13:50:23 +0000 (16:50 +0300)
committerSergey Bugaev <bugaevc@gmail.com>
Wed, 31 Mar 2021 09:54:08 +0000 (12:54 +0300)
RFC 6762 defines the top bit in RRs to mean cache flush (section 10.2),
and the top bit in questions to mean that a unicast reply is wanted
(section 5.4).

dns_packet_read_key() is used for parsing both questions and RRs.
When called from dns_packet_extract_question(), the top bit being set
should not result in the packet being rejected as invalid.

Fixes https://github.com/systemd/systemd/issues/17973

src/resolve/resolved-dns-packet.c
src/resolve/resolved-dns-packet.h
src/resolve/resolved-dns-rr.h
src/resolve/resolved-mdns.c

index ab1b658237277dd7aeffadfb982baffa2f1c0da4..a197f94bcfdf84ede66a57154a3df9e7a076b695 100644 (file)
@@ -627,7 +627,7 @@ int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *k, const DnsAnswer
         if (r < 0)
                 goto fail;
 
-        class = flags & DNS_ANSWER_CACHE_FLUSH ? k->class | MDNS_RR_CACHE_FLUSH : k->class;
+        class = flags & DNS_ANSWER_CACHE_FLUSH ? k->class | MDNS_RR_CACHE_FLUSH_OR_QU : k->class;
         r = dns_packet_append_uint16(p, class, NULL);
         if (r < 0)
                 goto fail;
@@ -1628,12 +1628,12 @@ static int dns_packet_read_type_windows(DnsPacket *p, Bitmap **types, size_t siz
 int dns_packet_read_key(
                 DnsPacket *p,
                 DnsResourceKey **ret,
-                bool *ret_cache_flush,
+                bool *ret_cache_flush_or_qu,
                 size_t *ret_start) {
 
         _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder;
         _cleanup_free_ char *name = NULL;
-        bool cache_flush = false;
+        bool cache_flush_or_qu = false;
         uint16_t class, type;
         int r;
 
@@ -1653,11 +1653,11 @@ int dns_packet_read_key(
                 return r;
 
         if (p->protocol == DNS_PROTOCOL_MDNS) {
-                /* See RFC6762, Section 10.2 */
+                /* See RFC6762, sections 5.4 and 10.2 */
 
-                if (type != DNS_TYPE_OPT && (class & MDNS_RR_CACHE_FLUSH)) {
-                        class &= ~MDNS_RR_CACHE_FLUSH;
-                        cache_flush = true;
+                if (type != DNS_TYPE_OPT && (class & MDNS_RR_CACHE_FLUSH_OR_QU)) {
+                        class &= ~MDNS_RR_CACHE_FLUSH_OR_QU;
+                        cache_flush_or_qu = true;
                 }
         }
 
@@ -1672,8 +1672,8 @@ int dns_packet_read_key(
                 *ret = key;
         }
 
-        if (ret_cache_flush)
-                *ret_cache_flush = cache_flush;
+        if (ret_cache_flush_or_qu)
+                *ret_cache_flush_or_qu = cache_flush_or_qu;
         if (ret_start)
                 *ret_start = rewinder.saved_rindex;
 
@@ -2221,15 +2221,12 @@ static int dns_packet_extract_question(DnsPacket *p, DnsQuestion **ret_question)
 
                 for (i = 0; i < n; i++) {
                         _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
-                        bool cache_flush;
+                        bool qu;
 
-                        r = dns_packet_read_key(p, &key, &cache_flush, NULL);
+                        r = dns_packet_read_key(p, &key, &qu, NULL);
                         if (r < 0)
                                 return r;
 
-                        if (cache_flush)
-                                return -EBADMSG;
-
                         if (!dns_type_is_valid_query(key->type))
                                 return -EBADMSG;
 
@@ -2240,7 +2237,7 @@ static int dns_packet_extract_question(DnsPacket *p, DnsQuestion **ret_question)
                                 /* Already in the Question, let's skip */
                                 continue;
 
-                        r = dns_question_add_raw(question, key, 0);
+                        r = dns_question_add_raw(question, key, qu ? DNS_QUESTION_WANTS_UNICAST_REPLY : 0);
                         if (r < 0)
                                 return r;
                 }
index 7b2abe3e7643bb2c77ff1180dce713650c72d322..e9820795c0593a8385137a5f64cdacfaec69cf18 100644 (file)
@@ -233,7 +233,7 @@ int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start);
 int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start);
 int dns_packet_read_raw_string(DnsPacket *p, const void **ret, size_t *size, size_t *start);
 int dns_packet_read_name(DnsPacket *p, char **ret, bool allow_compression, size_t *start);
-int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, bool *ret_cache_flush, size_t *start);
+int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, bool *ret_cache_flush_or_qu, size_t *start);
 int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, bool *ret_cache_flush, size_t *start);
 
 void dns_packet_rewind(DnsPacket *p, size_t idx);
index ab48ea5f2a091297168491c236adad1b68f9404b..43bbcb30735b77c3b1e8bc7f5a09d89298afa0ee 100644 (file)
@@ -16,12 +16,12 @@ typedef struct DnsResourceRecord DnsResourceRecord;
 typedef struct DnsTxtItem DnsTxtItem;
 
 /* DNSKEY RR flags */
-#define DNSKEY_FLAG_SEP      (UINT16_C(1) << 0)
-#define DNSKEY_FLAG_REVOKE   (UINT16_C(1) << 7)
-#define DNSKEY_FLAG_ZONE_KEY (UINT16_C(1) << 8)
+#define DNSKEY_FLAG_SEP            (UINT16_C(1) << 0)
+#define DNSKEY_FLAG_REVOKE         (UINT16_C(1) << 7)
+#define DNSKEY_FLAG_ZONE_KEY       (UINT16_C(1) << 8)
 
 /* mDNS RR flags */
-#define MDNS_RR_CACHE_FLUSH  (UINT16_C(1) << 15)
+#define MDNS_RR_CACHE_FLUSH_OR_QU  (UINT16_C(1) << 15)
 
 /* DNSSEC algorithm identifiers, see
  * http://tools.ietf.org/html/rfc4034#appendix-A.1 and
index 2857b58e89e287003b63b99d6f820e601c2ec8a5..4b6df10614050cd0022fd0ee3ef395a22245e713 100644 (file)
@@ -10,7 +10,7 @@
 #include "resolved-mdns.h"
 #include "sort-util.h"
 
-#define CLEAR_CACHE_FLUSH(x) (~MDNS_RR_CACHE_FLUSH & (x))
+#define CLEAR_CACHE_FLUSH(x) (~MDNS_RR_CACHE_FLUSH_OR_QU & (x))
 
 void manager_mdns_stop(Manager *m) {
         assert(m);