From d4c4edff1fd88df3106703b7c0194f22ed4a8ad2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Tue, 26 Aug 2025 17:52:45 +0200 Subject: [PATCH 1/2] Preserve ZEROTTL attribute when replacing NS RRset Previously, BIND 9 would drop the ZEROTTL attribute when updating previously cached NS entry with ZEROTTL attribute set. Co-authored-by: Jinmei Tatuya (cherry picked from commit 982ca161c26c2e6cd90b19888331bb015dcbae1f) --- lib/dns/rbtdb.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index b69b87bb0c..2ec9b93941 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -6642,7 +6642,7 @@ find_header: return ISC_R_SUCCESS; } /* - * If we have will be replacing a NS RRset force its TTL + * If we will be replacing a NS RRset force its TTL * to be no more than the current NS RRset's TTL. This * ensures the delegations that are withdrawn are honoured. */ @@ -6651,6 +6651,11 @@ find_header: !newheader_nx && header->trust <= newheader->trust) { if (newheader->rdh_ttl > header->rdh_ttl) { + if (ZEROTTL(header)) { + RDATASET_ATTR_SET( + newheader, + RDATASET_ATTR_ZEROTTL); + } newheader->rdh_ttl = header->rdh_ttl; } } From 0cd65c605c937ba92ee0e95790484b91b428dd91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Tue, 26 Aug 2025 18:18:12 +0200 Subject: [PATCH 2/2] Don't preserve cache entries if new TTL is smaller than existing Under certain circumstances, cache entries with equivalent rdataset might not get replaced. Previously such entry would get preserved regardless of the new TTL and expire time on the existing header would get updated when the expire time was less than the expire time on the existing header. Change the logic to preserve the existing header only if the new expire time is larger than the existing one and replace the existing cache entry when the new expire time is less than the existing one. Co-authored-by: Jinmei Tatuya (cherry picked from commit 9f7ba584cf46ffbb17c0793d19a334533914aba8) --- lib/dns/rbtdb.c | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index 2ec9b93941..54363c0319 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -6595,29 +6595,23 @@ find_header: } } /* - * Don't replace existing NS, A and AAAA RRsets in the - * cache if they are already exist. This prevents named - * being locked to old servers. Don't lower trust of - * existing record if the update is forced. Nothing - * special to be done w.r.t stale data; it gets replaced - * normally further down. + * Don't replace existing NS in the cache if they already exist + * and replacing the existing one would increase the TTL. This + * prevents named being locked to old servers. Don't lower trust + * of existing record if the update is forced. Nothing special + * to be done w.r.t stale data; it gets replaced normally + * further down. */ if (IS_CACHE(rbtdb) && ACTIVE(header, now) && header->type == dns_rdatatype_ns && !header_nx && !newheader_nx && header->trust >= newheader->trust && + header->rdh_ttl < newheader->rdh_ttl && dns_rdataslab_equalx((unsigned char *)header, (unsigned char *)newheader, (unsigned int)(sizeof(*newheader)), rbtdb->common.rdclass, (dns_rdatatype_t)header->type)) { - /* - * Honour the new ttl if it is less than the - * older one. - */ - if (header->rdh_ttl > newheader->rdh_ttl) { - set_ttl(rbtdb, header, newheader->rdh_ttl); - } if (header->last_used != now) { update_header(rbtdb, header, now); } @@ -6667,17 +6661,11 @@ find_header: header->type == RBTDB_RDATATYPE_SIGDS) && !header_nx && !newheader_nx && header->trust >= newheader->trust && + header->rdh_ttl < newheader->rdh_ttl && dns_rdataslab_equal((unsigned char *)header, (unsigned char *)newheader, (unsigned int)(sizeof(*newheader)))) { - /* - * Honour the new ttl if it is less than the - * older one. - */ - if (header->rdh_ttl > newheader->rdh_ttl) { - set_ttl(rbtdb, header, newheader->rdh_ttl); - } if (header->last_used != now) { update_header(rbtdb, header, now); }