dns-packet: only set mDNS cache-flush bit in responses
dns_packet_append_key() ORs MDNS_RR_CACHE_FLUSH_OR_QU into the CLASS
field of any RR whose answer item carries DNS_ANSWER_CACHE_FLUSH,
regardless of the packet the RR is appended to.
Since 748a548e1b ("resolved: set cache-flush bit on mDNS responses"),
every RR of an mDNS zone, except DNS-SD service enumeration PTRs,
carries that flag. The Authority Section of mDNS probes (RFC 6762,
section 8.2) is filled from our mDNS zone via dns_zone_lookup(), which
applies the flag to items still in probing state too, hence probes are
sent with class 0x8001 in their Authority Section.
RFC 6762, section 10.2, scopes the cache-flush bit to announcements and
responses. Peers ignore it for probe tiebreaking, so this is not an
interoperability issue, but there is no reason to set it there.
Only set the bit when the packet is a response. mDNS responses,
announcements and goodbye packets are all built by
dns_scope_make_reply_packet(), which sets QR before appending any RR, so
they keep the bit. The Known-Answer list of queries is unaffected, as it
is appended without flags already.
See: https://github.com/systemd/systemd/pull/43627
(cherry picked from commit 1c57b40fc1451b1f518e6168dbd28bf1e5fa2b4d)
This commit is contained in:
committed by
Luca Boccassi
parent
03ae6cf3ce
commit
f2de9253da
@@ -214,6 +214,71 @@ TEST(packet_append_key_single_soa_any_class) {
|
||||
ASSERT_EQ(memcmp(DNS_PACKET_DATA(packet), data, sizeof(data)), 0);
|
||||
}
|
||||
|
||||
TEST(packet_append_key_cache_flush_mdns) {
|
||||
_cleanup_(dns_packet_unrefp) DnsPacket *packet = NULL;
|
||||
DnsResourceKey *key = NULL;
|
||||
|
||||
ASSERT_OK(dns_packet_new(&packet, DNS_PROTOCOL_MDNS, 0, DNS_PACKET_SIZE_MAX));
|
||||
ASSERT_NOT_NULL(packet);
|
||||
|
||||
DNS_PACKET_ID(packet) = htobe16(42);
|
||||
DNS_PACKET_HEADER(packet)->flags = htobe16(DNS_PACKET_MAKE_FLAGS(1, 0, 1, 0, 0, 0, 0, 0, DNS_RCODE_SUCCESS));
|
||||
DNS_PACKET_HEADER(packet)->ancount = htobe16(1);
|
||||
|
||||
key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, "example.local");
|
||||
ASSERT_NOT_NULL(key);
|
||||
ASSERT_OK(dns_packet_append_key(packet, key, DNS_ANSWER_CACHE_FLUSH, NULL));
|
||||
dns_resource_key_unref(key);
|
||||
|
||||
const uint8_t data[] = {
|
||||
0x00, 0x2a, BIT_QR | BIT_AA, DNS_RCODE_SUCCESS,
|
||||
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
/* name */ 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
|
||||
0x05, 'l', 'o', 'c', 'a', 'l',
|
||||
0x00,
|
||||
/* A */ 0x00, 0x01,
|
||||
/* IN + cache-flush */
|
||||
0x80, 0x01
|
||||
};
|
||||
|
||||
ASSERT_EQ(packet->size, sizeof(data));
|
||||
ASSERT_EQ(memcmp(DNS_PACKET_DATA(packet), data, sizeof(data)), 0);
|
||||
}
|
||||
|
||||
/* mDNS probes carry the proposed RRs from our mDNS zone in the Authority Section. Those items carry
|
||||
* DNS_ANSWER_CACHE_FLUSH, but the cache-flush bit is only set in responses, never in queries. See RFC 6762,
|
||||
* sections 8.2 and 10.2. */
|
||||
TEST(packet_append_key_cache_flush_mdns_query) {
|
||||
_cleanup_(dns_packet_unrefp) DnsPacket *packet = NULL;
|
||||
DnsResourceKey *key = NULL;
|
||||
|
||||
ASSERT_OK(dns_packet_new(&packet, DNS_PROTOCOL_MDNS, 0, DNS_PACKET_SIZE_MAX));
|
||||
ASSERT_NOT_NULL(packet);
|
||||
|
||||
DNS_PACKET_HEADER(packet)->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0, 0, 0, 0, 0, 0, 0, 0, DNS_RCODE_SUCCESS));
|
||||
DNS_PACKET_HEADER(packet)->nscount = htobe16(1);
|
||||
|
||||
key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, "example.local");
|
||||
ASSERT_NOT_NULL(key);
|
||||
ASSERT_OK(dns_packet_append_key(packet, key, DNS_ANSWER_CACHE_FLUSH, NULL));
|
||||
dns_resource_key_unref(key);
|
||||
|
||||
const uint8_t data[] = {
|
||||
0x00, 0x00, 0x00, DNS_RCODE_SUCCESS,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
|
||||
|
||||
/* name */ 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
|
||||
0x05, 'l', 'o', 'c', 'a', 'l',
|
||||
0x00,
|
||||
/* A */ 0x00, 0x01,
|
||||
/* IN */ 0x00, 0x01
|
||||
};
|
||||
|
||||
ASSERT_EQ(packet->size, sizeof(data));
|
||||
ASSERT_EQ(memcmp(DNS_PACKET_DATA(packet), data, sizeof(data)), 0);
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
* dns_packet_append_question()
|
||||
* ================================================================ */
|
||||
|
||||
@@ -723,7 +723,11 @@ 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_OR_QU : k->class;
|
||||
/* The rules for setting the cache-flush bit apply to responses and announcements only, see RFC 6762,
|
||||
* section 10.2. Hence never set it in queries (the Authority Section of probes is filled from our
|
||||
* mDNS zone, see section 8.2). */
|
||||
class = DNS_PACKET_QR(p) && FLAGS_SET(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;
|
||||
|
||||
Reference in New Issue
Block a user