resolved: fix mistaking QU bit for cache-flush bit
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
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user