Add functionality to serve stale DNS records

This commit is contained in:
Dan Streetman 2023-07-07 15:49:35 -04:00
Родитель ad37bfd7fb
Коммит 7a29ef4dc8
3 изменённых файлов: 545 добавлений и 1 удалений

Просмотреть файл

@ -0,0 +1,512 @@
From 5ed91481abea382dc486507556e5cdf0f36b796f Mon Sep 17 00:00:00 2001
From: Kiran Vemula <vemulakiran@gmail.com>
Date: Thu, 8 Jun 2023 18:42:11 +0530
Subject: [PATCH] resolved: added serve stale feature implementation of RFC
8767
serve stale feature to keep the DNS resource records beyond TTL to return them as stale records in case of upstream server is not reachable or returns negative response.
SD_RESOLVED_NO_STALE flag has been added to disable serving stale records via dbus.
added serve stale test cases to TEST-75-RESOLVED
Fixes: #21815
---
man/org.freedesktop.resolve1.xml | 6 ++-
man/resolvectl.xml | 8 ++++
man/resolved.conf.xml | 15 ++++++
shell-completion/bash/resolvectl | 2 +-
src/resolve/resolvectl.c | 10 ++++
src/resolve/resolved-bus.c | 1 +
src/resolve/resolved-def.h | 3 ++
src/resolve/resolved-dns-cache.c | 64 +++++++++++++++++++------
src/resolve/resolved-dns-cache.h | 3 +-
src/resolve/resolved-dns-transaction.c | 20 +++++++-
src/resolve/resolved-gperf.gperf | 1 +
src/resolve/resolved-link.c | 3 +-
src/resolve/resolved-manager.h | 1 +
src/resolve/resolved-mdns.c | 3 +-
src/resolve/resolved-varlink.c | 1 +
src/resolve/resolved.conf.in | 1 +
test/TEST-75-RESOLVED/test.sh | 5 ++
test/knot-data/zones/unsigned.test.zone | 1 +
test/units/testsuite-75.sh | 63 ++++++++++++++++++++++++
19 files changed, 189 insertions(+), 22 deletions(-)
diff --git a/man/org.freedesktop.resolve1.xml b/man/org.freedesktop.resolve1.xml
index a2b4490fc7..403eb14538 100644
--- a/man/org.freedesktop.resolve1.xml
+++ b/man/org.freedesktop.resolve1.xml
@@ -464,6 +464,7 @@ node /org/freedesktop/resolve1 {
#define SD_RESOLVED_FROM_ZONE (UINT64_C(1) &lt;&lt; 21)
#define SD_RESOLVED_FROM_TRUST_ANCHOR (UINT64_C(1) &lt;&lt; 22)
#define SD_RESOLVED_FROM_NETWORK (UINT64_C(1) &lt;&lt; 23)
+#define SD_RESOLVED_NO_STALE (UINT64_C(1) &lt;&lt; 24)
</programlisting>
<para>On input, the first five flags control the protocols to use for the look-up. They refer to
@@ -513,13 +514,14 @@ node /org/freedesktop/resolve1 {
<para>NO_VALIDATE can be set to disable validation via DNSSEC even if it would normally be used.
</para>
- <para>The next four flags allow disabling certain sources during resolution. NO_SYNTHESIZE disables
+ <para>The next six flags allow disabling certain sources during resolution. NO_SYNTHESIZE disables
synthetic records, e.g. the local host name, see section SYNTHETIC RECORDS in
<citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
for more information. NO_CACHE disables the use of the cache of previously resolved records. NO_ZONE
disables answers using locally registered public LLMNR/mDNS resource records. NO_TRUST_ANCHOR
disables answers using locally configured trust anchors. NO_NETWORK requires all answers to be
- provided without using the network, i.e. either from local sources or the cache.</para>
+ provided without using the network, i.e. either from local sources or the cache. NO_STALE flag
+ can be set to disable answering request with stale records.</para>
<para>With REQUIRE_PRIMARY the request must be answered from a "primary" answer, i.e. not from
resource records acquired as a side-effect of a previous transaction.</para>
diff --git a/man/resolvectl.xml b/man/resolvectl.xml
index 37a51b4760..ed3918307c 100644
--- a/man/resolvectl.xml
+++ b/man/resolvectl.xml
@@ -379,6 +379,14 @@
query response are shown. Otherwise, this output is suppressed.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>--stale-data=</option><replaceable>BOOL</replaceable></term>
+
+ <listitem><para>Takes a boolean parameter; used in conjunction with <command>query</command>. If true
+ (the default), lookups are answered with stale data (expired resource records) if
+ possible. If false, the stale data is not considered for the lookup request.</para></listitem>
+ </varlistentry>
+
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />
<xi:include href="standard-options.xml" xpointer="no-pager" />
diff --git a/man/resolved.conf.xml b/man/resolved.conf.xml
index 2b9f482971..81401043a3 100644
--- a/man/resolved.conf.xml
+++ b/man/resolved.conf.xml
@@ -329,6 +329,21 @@ DNSStubListenerExtra=udp:[2001:db8:0:f102::13]:9953</programlisting>
url="https://www.iab.org/documents/correspondence-reports-documents/2013-2/iab-statement-dotless-domains-considered-harmful/">IAB
Statement</ulink>, and may create a privacy and security risk.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term>StaleRetentionSec=<replaceable>SECONDS</replaceable></term>
+ <listitem><para>Takes a duration value, which determines the length of time DNS resource records can be retained
+ in the cache beyond their Time To Live (TTL). This allows these records to be returned as stale records.
+ By default, this value is set to zero, meaning that DNS resource records are not stored in the cache after their TTL expires.</para>
+
+ <para>This is useful when a DNS server failure occurs or becomes unreachable.
+ In such cases, systemd-resolved continues to use the stale records to answer DNS queries, particularly when no valid response
+ can be obtained from the upstream DNS servers. However, this doesn't apply to NXDOMAIN responses, as those are still perfectly valid responses.
+ This feature enhances resilience against DNS infrastructure failures and outages.</para>
+
+ <para>systemd-resolved always attempts to reach the upstream DNS servers first, before providing the client application with any stale data.
+ If this feature is enabled, cache will not be flushed when changing servers.</para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
diff --git a/shell-completion/bash/resolvectl b/shell-completion/bash/resolvectl
index 21f80143c3..779842ea11 100644
--- a/shell-completion/bash/resolvectl
+++ b/shell-completion/bash/resolvectl
@@ -37,6 +37,6 @@ _resolvectl() {
[STANDALONE]='-h --help --version --no-pager -4 -6
--service-address=no --service-txt=no
- --cname=no --search=no --legend=no'
+ --cname=no --search=no --legend=no --stale-data=no'
[ARG]='-i --interface -p --protocol -t --type -c --class --raw'
)
local -A VERBS=(
diff --git a/src/resolve/resolvectl.c b/src/resolve/resolvectl.c
index d6ecaed3c6..72aa778792 100644
--- a/src/resolve/resolvectl.c
+++ b/src/resolve/resolvectl.c
@@ -2671,6 +2671,7 @@ static int native_help(void) {
" --validate=BOOL Allow DNSSEC validation (default: yes)\n"
" --synthesize=BOOL Allow synthetic response (default: yes)\n"
" --cache=BOOL Allow response from cache (default: yes)\n"
+ " --stale-data=BOOL Allow response from cache with stale data (default: yes)\n"
" --zone=BOOL Allow response from locally registered mDNS/LLMNR\n"
" records (default: yes)\n"
" --trust-anchor=BOOL Allow response from local trust anchor (default: yes)\n"
@@ -3024,6 +3025,7 @@ static int native_parse_argv(int argc, char *argv[]) {
ARG_RAW,
ARG_SEARCH,
ARG_NO_PAGER,
+ ARG_STALE_DATA
};
static const struct option options[] = {
@@ -3046,6 +3048,7 @@ static int native_parse_argv(int argc, char *argv[]) {
{ "raw", optional_argument, NULL, ARG_RAW },
{ "search", required_argument, NULL, ARG_SEARCH },
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
+ { "stale-data", required_argument, NULL, ARG_STALE_DATA },
{}
};
@@ -3183,6 +3186,13 @@ static int native_parse_argv(int argc, char *argv[]) {
SET_FLAG(arg_flags, SD_RESOLVED_NO_CACHE, r == 0);
break;
+ case ARG_STALE_DATA:
+ r = parse_boolean_argument("--stale-data=", optarg, NULL);
+ if (r < 0)
+ return r;
+ SET_FLAG(arg_flags, SD_RESOLVED_NO_STALE, r == 0);
+ break;
+
case ARG_ZONE:
r = parse_boolean_argument("--zone=", optarg, NULL);
if (r < 0)
diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c
index 334ae8dcff..459adfec5c 100644
--- a/src/resolve/resolved-bus.c
+++ b/src/resolve/resolved-bus.c
@@ -298,6 +298,7 @@ static int validate_and_mangle_flags(
SD_RESOLVED_NO_ZONE|
SD_RESOLVED_NO_TRUST_ANCHOR|
SD_RESOLVED_NO_NETWORK|
+ SD_RESOLVED_NO_STALE|
ok))
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
diff --git a/src/resolve/resolved-def.h b/src/resolve/resolved-def.h
index 36092afa48..b7a44f9571 100644
--- a/src/resolve/resolved-def.h
+++ b/src/resolve/resolved-def.h
@@ -70,6 +70,9 @@
/* Output: Result was (at least partially) answered from network */
#define SD_RESOLVED_FROM_NETWORK (UINT64_C(1) << 23)
+/* Input: Don't answer request with stale data */
+#define SD_RESOLVED_NO_STALE (UINT64_C(1) << 24)
+
#define SD_RESOLVED_LLMNR (SD_RESOLVED_LLMNR_IPV4|SD_RESOLVED_LLMNR_IPV6)
#define SD_RESOLVED_MDNS (SD_RESOLVED_MDNS_IPV4|SD_RESOLVED_MDNS_IPV6)
#define SD_RESOLVED_PROTOCOLS_ALL (SD_RESOLVED_MDNS|SD_RESOLVED_LLMNR|SD_RESOLVED_DNS)
diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c
index 089ed3aa0a..3f8378ae30 100644
--- a/src/resolve/resolved-dns-cache.c
+++ b/src/resolve/resolved-dns-cache.c
@@ -15,9 +15,12 @@
* leave DNS caches unbounded, but that's crazy. */
#define CACHE_MAX 4096
-/* We never keep any item longer than 2h in our cache */
+/* We never keep any item longer than 2h in our cache unless StaleRetentionSec is greater than zero. */
#define CACHE_TTL_MAX_USEC (2 * USEC_PER_HOUR)
+/* The max TTL for stale data is set to 30 seconds. See RFC 8767, Section 6. */
+#define CACHE_STALE_TTL_MAX_USEC (30 * USEC_PER_SEC)
+
/* How long to cache strange rcodes, i.e. rcodes != SUCCESS and != NXDOMAIN (specifically: that's only SERVFAIL for
* now) */
#define CACHE_TTL_STRANGE_RCODE_USEC (10 * USEC_PER_SEC)
@@ -42,7 +45,8 @@ struct DnsCacheItem {
DnsAnswer *answer; /* The full validated answer, if this is an RRset acquired via a "primary" lookup */
DnsPacket *full_packet; /* The full packet this information was acquired with */
- usec_t until;
+ usec_t until; /* If StaleRetentionSec is greater than zero, until is set to a duration of StaleRetentionSec from the time of TTL expiry. If StaleRetentionSec is zero, both until and until_valid will be set to ttl. */
+ usec_t until_valid; /* The key is for storing the time when the TTL set to expire. */
uint64_t query_flags; /* SD_RESOLVED_AUTHENTICATED and/or SD_RESOLVED_CONFIDENTIAL */
DnssecResult dnssec_result;
@@ -313,7 +317,7 @@ static DnsCacheItem* dns_cache_get(DnsCache *c, DnsResourceRecord *rr) {
return NULL;
}
-static usec_t calculate_until(
+static usec_t calculate_until_valid(
DnsResourceRecord *rr,
uint32_t min_ttl,
uint32_t nsec_ttl,
@@ -352,6 +356,13 @@ static usec_t calculate_until(
return timestamp + u;
}
+static usec_t calculate_until(
+ usec_t until_valid,
+ usec_t stale_retention_usec) {
+
+ return stale_retention_usec > 0 ? usec_add(until_valid, stale_retention_usec) : until_valid;
+}
+
static void dns_cache_item_update_positive(
DnsCache *c,
DnsCacheItem *i,
@@ -365,7 +376,8 @@ static void dns_cache_item_update_positive(
usec_t timestamp,
int ifindex,
int owner_family,
- const union in_addr_union *owner_address) {
+ const union in_addr_union *owner_address,
+ usec_t stale_retention_usec) {
assert(c);
assert(i);
@@ -395,7 +407,8 @@ static void dns_cache_item_update_positive(
dns_packet_unref(i->full_packet);
i->full_packet = full_packet;
- i->until = calculate_until(rr, min_ttl, UINT32_MAX, timestamp, false);
+ i->until_valid = calculate_until_valid(rr, min_ttl, UINT32_MAX, timestamp, false);
+ i->until = calculate_until(i->until_valid, stale_retention_usec);
i->query_flags = query_flags & CACHEABLE_QUERY_FLAGS;
i->shared_owner = shared_owner;
i->dnssec_result = dnssec_result;
@@ -419,7 +432,8 @@ static int dns_cache_put_positive(
usec_t timestamp,
int ifindex,
int owner_family,
- const union in_addr_union *owner_address) {
+ const union in_addr_union *owner_address,
+ usec_t stale_retention_usec) {
_cleanup_(dns_cache_item_freep) DnsCacheItem *i = NULL;
char key_str[DNS_RESOURCE_KEY_STRING_MAX];
@@ -467,7 +481,8 @@ static int dns_cache_put_positive(
timestamp,
ifindex,
owner_family,
- owner_address);
+ owner_address,
+ stale_retention_usec);
return 0;
}
@@ -482,13 +497,19 @@ static int dns_cache_put_positive(
if (!i)
return -ENOMEM;
+ /* If StaleRetentionSec is greater than zero, the 'until' property is set to a duration
+ * of StaleRetentionSec from the time of TTL expiry.
+ * If StaleRetentionSec is zero, both the 'until' and 'until_valid' are set to the TTL duration,
+ * leading to the eviction of the record once the TTL expires.*/
+ usec_t until_valid = calculate_until_valid(rr, min_ttl, UINT32_MAX, timestamp, false);
*i = (DnsCacheItem) {
.type = DNS_CACHE_POSITIVE,
.key = dns_resource_key_ref(rr->key),
.rr = dns_resource_record_ref(rr),
.answer = dns_answer_ref(answer),
.full_packet = dns_packet_ref(full_packet),
- .until = calculate_until(rr, min_ttl, UINT32_MAX, timestamp, false),
+ .until = calculate_until(until_valid, stale_retention_usec),
+ .until_valid = until_valid,
.query_flags = query_flags & CACHEABLE_QUERY_FLAGS,
.shared_owner = shared_owner,
.dnssec_result = dnssec_result,
@@ -594,7 +615,7 @@ static int dns_cache_put_negative(
* of some other RR. Let's better take the lowest option here than a needlessly high one */
i->until =
i->type == DNS_CACHE_RCODE ? timestamp + CACHE_TTL_STRANGE_RCODE_USEC :
- calculate_until(soa, dns_answer_min_ttl(answer), nsec_ttl, timestamp, true);
+ calculate_until_valid(soa, dns_answer_min_ttl(answer), nsec_ttl, timestamp, true);
if (i->type == DNS_CACHE_NXDOMAIN) {
/* NXDOMAIN entries should apply equally to all types, so we use ANY as
@@ -689,7 +710,8 @@ int dns_cache_put(
DnssecResult dnssec_result,
uint32_t nsec_ttl,
int owner_family,
- const union in_addr_union *owner_address) {
+ const union in_addr_union *owner_address,
+ usec_t stale_retention_usec) {
DnsResourceRecord *soa = NULL;
bool weird_rcode = false;
@@ -784,7 +806,8 @@ int dns_cache_put(
timestamp,
item->ifindex,
owner_family,
- owner_address);
+ owner_address,
+ stale_retention_usec);
if (r < 0)
goto fail;
}
@@ -840,7 +863,8 @@ int dns_cache_put(
nsec_ttl,
timestamp,
soa,
- owner_family, owner_address);
+ owner_family,
+ owner_address);
if (r < 0)
goto fail;
@@ -1033,6 +1057,14 @@ int dns_cache_lookup(
goto miss;
}
+ /* Skip the next part if ttl is expired and requested with no stale flag. */
+ if (FLAGS_SET(query_flags, SD_RESOLVED_NO_STALE) && j->until_valid < current) {
+ log_debug("Requested with no stale and TTL expired for %s",
+ dns_resource_key_to_string(key, key_str, sizeof key_str));
+
+ goto miss;
+ }
+
if (j->type == DNS_CACHE_NXDOMAIN)
nxdomain = true;
else if (j->type == DNS_CACHE_RCODE)
@@ -1065,6 +1097,10 @@ int dns_cache_lookup(
dnssec_result = _DNSSEC_RESULT_INVALID;
}
+ /* If the question is being resolved using stale data, the clamp TTL will be set to CACHE_STALE_TTL_MAX_USEC. */
+ usec_t until = FLAGS_SET(query_flags, SD_RESOLVED_NO_STALE) ? j->until_valid
+ : usec_add(current, CACHE_STALE_TTL_MAX_USEC);
+
/* Append the answer RRs to our answer. Ideally we have the answer object, which we
* preferably use. But if the cached entry was generated as "side-effect" of a reply,
* i.e. from validated auxiliary records rather than from the main reply, then we use the
@@ -1085,7 +1121,7 @@ int dns_cache_lookup(
item->flags,
item->rrsig,
query_flags,
- j->until,
+ until,
current);
if (r < 0)
return r;
@@ -1100,7 +1136,7 @@ int dns_cache_lookup(
FLAGS_SET(j->query_flags, SD_RESOLVED_AUTHENTICATED) ? DNS_ANSWER_AUTHENTICATED : 0,
NULL,
query_flags,
- j->until,
+ until,
current);
if (r < 0)
return r;
diff --git a/src/resolve/resolved-dns-cache.h b/src/resolve/resolved-dns-cache.h
index bc045bc80c..d078ae9872 100644
--- a/src/resolve/resolved-dns-cache.h
+++ b/src/resolve/resolved-dns-cache.h
@@ -34,7 +34,8 @@ int dns_cache_put(
DnssecResult dnssec_result,
uint32_t nsec_ttl,
int owner_family,
- const union in_addr_union *owner_address);
+ const union in_addr_union *owner_address,
+ usec_t stale_retention_usec);
int dns_cache_lookup(
DnsCache *c,
diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c
index 400ca0d2e8..8fa48c0b43 100644
--- a/src/resolve/resolved-dns-transaction.c
+++ b/src/resolve/resolved-dns-transaction.c
@@ -836,7 +836,8 @@ static void dns_transaction_cache_answer(DnsTransaction *t) {
t->answer_dnssec_result,
t->answer_nsec_ttl,
t->received->family,
- &t->received->sender);
+ &t->received->sender,
+ t->scope->manager->stale_retention_usec);
}
static bool dns_transaction_dnssec_is_live(DnsTransaction *t) {
@@ -1726,10 +1727,18 @@ static int dns_transaction_prepare(DnsTransaction *t, usec_t ts) {
/* Let's then prune all outdated entries */
dns_cache_prune(&t->scope->cache);
+ /* For the initial attempt or when no stale data is requested, disable serve stale
+ * and answer the question from the cache (honors ttl property).
+ * On the second attempt, if StaleRetentionSec is greater than zero,
+ * try to answer the question using stale date (honors until property) */
+ uint64_t query_flags = t->query_flags;
+ if (t->n_attempts == 1 || t->scope->manager->stale_retention_usec == 0)
+ query_flags |= SD_RESOLVED_NO_STALE;
+
r = dns_cache_lookup(
&t->scope->cache,
dns_transaction_key(t),
- t->query_flags,
+ query_flags,
&t->answer_rcode,
&t->answer,
&t->received,
@@ -1745,6 +1754,13 @@ static int dns_transaction_prepare(DnsTransaction *t, usec_t ts) {
* packet. */
dns_transaction_reset_answer(t);
else {
+ if (t->n_attempts > 1 && !FLAGS_SET(query_flags, SD_RESOLVED_NO_STALE)) {
+ char key_str[DNS_RESOURCE_KEY_STRING_MAX];
+ log_debug("Serve Stale response rcode=%s for %s",
+ dns_rcode_to_string(t->answer_rcode),
+ dns_resource_key_to_string(dns_transaction_key(t), key_str, sizeof key_str));
+ }
+
t->answer_source = DNS_TRANSACTION_CACHE;
if (t->answer_rcode == DNS_RCODE_SUCCESS)
dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
diff --git a/src/resolve/resolved-gperf.gperf b/src/resolve/resolved-gperf.gperf
index eab4c7ee14..68839352f5 100644
--- a/src/resolve/resolved-gperf.gperf
+++ b/src/resolve/resolved-gperf.gperf
@@ -32,3 +32,4 @@ Resolve.ReadEtcHosts, config_parse_bool, 0,
Resolve.ResolveUnicastSingleLabel, config_parse_bool, 0, offsetof(Manager, resolve_unicast_single_label)
Resolve.DNSStubListenerExtra, config_parse_dns_stub_listener_extra, 0, offsetof(Manager, dns_extra_stub_listeners)
Resolve.CacheFromLocalhost, config_parse_bool, 0, offsetof(Manager, cache_from_localhost)
+Resolve.StaleRetentionSec, config_parse_sec, 0, offsetof(Manager, stale_retention_usec)
diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c
index 9385b75e4b..dd5daddce4 100644
--- a/src/resolve/resolved-link.c
+++ b/src/resolve/resolved-link.c
@@ -738,7 +738,8 @@ DnsServer* link_set_dns_server(Link *l, DnsServer *s) {
dns_server_unref(l->current_dns_server);
l->current_dns_server = dns_server_ref(s);
- if (l->unicast_scope)
+ /* Skip flushing the cache if server stale feature is enabled. */
+ if (l->unicast_scope && l->manager->stale_retention_usec == 0)
dns_cache_flush(&l->unicast_scope->cache);
return s;
diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h
index f8f3af6fd0..46f6b4fedc 100644
--- a/src/resolve/resolved-manager.h
+++ b/src/resolve/resolved-manager.h
@@ -42,6 +42,7 @@ struct Manager {
DnsCacheMode enable_cache;
bool cache_from_localhost;
DnsStubListenerMode dns_stub_listener_mode;
+ usec_t stale_retention_usec;
#if ENABLE_DNS_OVER_TLS
DnsTlsManagerData dnstls_data;
diff --git a/src/resolve/resolved-mdns.c b/src/resolve/resolved-mdns.c
index cf6c22df3b..d4a919fc60 100644
--- a/src/resolve/resolved-mdns.c
+++ b/src/resolve/resolved-mdns.c
@@ -408,7 +408,7 @@ static int on_mdns_packet(sd_event_source *s, int fd, uint32_t revents, void *us
dns_transaction_process_reply(t, p, false);
}
- dns_cache_put(&scope->cache, scope->manager->enable_cache, NULL, DNS_PACKET_RCODE(p), p->answer, NULL, false, _DNSSEC_RESULT_INVALID, UINT32_MAX, p->family, &p->sender);
+ dns_cache_put(&scope->cache, scope->manager->enable_cache, NULL, DNS_PACKET_RCODE(p), p->answer, NULL, false, _DNSSEC_RESULT_INVALID, UINT32_MAX, p->family, &p->sender, scope->manager->stale_retention_usec);
} else if (dns_packet_validate_query(p) > 0) {
log_debug("Got mDNS query packet for id %u", DNS_PACKET_ID(p));
diff --git a/src/resolve/resolved-varlink.c b/src/resolve/resolved-varlink.c
index fc224f627e..99022f5d2d 100644
--- a/src/resolve/resolved-varlink.c
+++ b/src/resolve/resolved-varlink.c
@@ -128,6 +128,7 @@ static bool validate_and_mangle_flags(
SD_RESOLVED_NO_ZONE|
SD_RESOLVED_NO_TRUST_ANCHOR|
SD_RESOLVED_NO_NETWORK|
+ SD_RESOLVED_NO_STALE|
ok))
return false;
diff --git a/src/resolve/resolved.conf.in b/src/resolve/resolved.conf.in
index 6d4176df52..f003574ac5 100644
--- a/src/resolve/resolved.conf.in
+++ b/src/resolve/resolved.conf.in
@@ -32,3 +32,4 @@
#DNSStubListenerExtra=
#ReadEtcHosts=yes
#ResolveUnicastSingleLabel=no
+#StaleRetentionSec=0

Просмотреть файл

@ -0,0 +1,27 @@
From 88c6f8f894435c38a075dd268d34f7bcc839dfd2 Mon Sep 17 00:00:00 2001
From: Kiran Vemula <vemulakiran@gmail.com>
Date: Fri, 16 Jun 2023 17:34:37 +0530
Subject: [PATCH] resolved: Initialize until_valid while storing
negative/NXDOMAIN response in the cache
Initialize until_valid is properly for negative response, the cached negative responses can be used to answer the queries before contacting upstream server.
---
src/resolve/resolved-dns-cache.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c
index 3f8378ae30..9d2a2fa1ac 100644
--- a/src/resolve/resolved-dns-cache.c
+++ b/src/resolve/resolved-dns-cache.c
@@ -613,7 +613,7 @@ static int dns_cache_put_negative(
/* Determine how long to cache this entry. In case we have some RRs in the answer use the lowest TTL
* of any of them. Typically that's the SOA's TTL, which is OK, but could possibly be lower because
* of some other RR. Let's better take the lowest option here than a needlessly high one */
- i->until =
+ i->until = i->until_valid =
i->type == DNS_CACHE_RCODE ? timestamp + CACHE_TTL_STRANGE_RCODE_USEC :
calculate_until_valid(soa, dns_answer_min_ttl(answer), nsec_ttl, timestamp, true);
--
2.34.1

Просмотреть файл

@ -1,7 +1,7 @@
Summary: Systemd-250
Name: systemd
Version: 250.3
Release: 16%{?dist}
Release: 17%{?dist}
License: LGPLv2+ AND GPLv2+ AND MIT
Vendor: Microsoft Corporation
Distribution: Mariner
@ -25,6 +25,8 @@ Patch3: CVE-2022-3821.patch
Patch4: CVE-2022-45873.patch
Patch5: backport-helper-util-macros.patch
Patch6: CVE-2022-4415.patch
Patch7: serve-stale-0001-resolved-added-serve-stale-feature-implementation-of.patch
Patch8: serve-stale-0002-resolved-Initialize-until_valid-while-storing-negati.patch
BuildRequires: audit-devel
BuildRequires: cryptsetup-devel
BuildRequires: docbook-dtd-xml
@ -281,6 +283,9 @@ fi
%files lang -f %{name}.lang
%changelog
* Fri Jul 07 2023 Dan Streetman <ddstreet@ieee.org> - 250.3-17
- Add support to systemd-resolved to serve stale dns data
* Tue Jun 20 2023 Chris Gunn <chrisgun@microsoft.com> - 250.3-16
- Enable audit integration