From: Aram Sargsyan Date: Thu, 27 Feb 2025 11:52:30 +0000 (+0000) Subject: Fix a bug in dns_zone_getprimaryaddr() X-Git-Tag: ondrej/lock-free-qpzone-reads-v1~12^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7293cb0612e9362ad78f5c318b767a4f8ce16451;p=thirdparty%2Fbind9.git Fix a bug in dns_zone_getprimaryaddr() When all the addresses were already iterated over, the dns_remote_curraddr() function asserts. So before calling it, dns_zone_getprimaryaddr() now checks the address list using the dns_remote_done() function. This also means that instead of returning 'isc_sockaddr_t' it now returns 'isc_result_t' and writes the primary's address into the provided pointer only when returning success. --- diff --git a/bin/named/statschannel.c b/bin/named/statschannel.c index 4df131de2f9..e872d492b35 100644 --- a/bin/named/statschannel.c +++ b/bin/named/statschannel.c @@ -1617,9 +1617,13 @@ xfrin_xmlrender(dns_zone_t *zone, void *arg) { isc_sockaddr_format(addrp, addr_buf, sizeof(addr_buf)); TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR addr_buf)); } else if (is_presoa) { - addr = dns_zone_getprimaryaddr(zone); - isc_sockaddr_format(&addr, addr_buf, sizeof(addr_buf)); - TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR addr_buf)); + if (dns_zone_getprimaryaddr(zone, &addr) == ISC_R_SUCCESS) { + isc_sockaddr_format(&addr, addr_buf, sizeof(addr_buf)); + TRY0(xmlTextWriterWriteString(writer, + ISC_XMLCHAR addr_buf)); + } else { + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-")); + } } else { TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-")); } @@ -2671,10 +2675,15 @@ xfrin_jsonrender(dns_zone_t *zone, void *arg) { json_object_object_add(xfrinobj, "remoteaddr", json_object_new_string(addr_buf)); } else if (is_presoa) { - addr = dns_zone_getprimaryaddr(zone); - isc_sockaddr_format(&addr, addr_buf, sizeof(addr_buf)); - json_object_object_add(xfrinobj, "remoteaddr", - json_object_new_string(addr_buf)); + if (dns_zone_getprimaryaddr(zone, &addr) == ISC_R_SUCCESS) { + isc_sockaddr_format(&addr, addr_buf, sizeof(addr_buf)); + json_object_object_add( + xfrinobj, "remoteaddr", + json_object_new_string(addr_buf)); + } else { + json_object_object_add(xfrinobj, "remoteaddr", + json_object_new_string("-")); + } } else { json_object_object_add(xfrinobj, "remoteaddr", json_object_new_string("-")); diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h index 63b39eb1b87..02ae1e99d5e 100644 --- a/lib/dns/include/dns/zone.h +++ b/lib/dns/include/dns/zone.h @@ -1539,14 +1539,19 @@ dns_zone_getsourceaddr(dns_zone_t *zone); * \li 'zone' has a non-empty primaries list. */ -isc_sockaddr_t -dns_zone_getprimaryaddr(dns_zone_t *zone); +isc_result_t +dns_zone_getprimaryaddr(dns_zone_t *zone, isc_sockaddr_t *dest); /*%< - * Get the zone's current primary server. + * Get the zone's current primary server into '*dest'. * * Requires: * \li 'zone' to be a valid zone. * \li 'zone' has a non-empty primaries list. + * \li 'dest' != NULL. + * + * Returns: + *\li #ISC_R_SUCCESS if the current primary server was found + *\li #ISC_R_NOMORE if all the primaries were already iterated over */ isc_time_t diff --git a/lib/dns/zone.c b/lib/dns/zone.c index ca1d48e1eec..536c8f3752a 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -18385,18 +18385,22 @@ dns_zone_getsourceaddr(dns_zone_t *zone) { return sourceaddr; } -isc_sockaddr_t -dns_zone_getprimaryaddr(dns_zone_t *zone) { - isc_sockaddr_t curraddr; +isc_result_t +dns_zone_getprimaryaddr(dns_zone_t *zone, isc_sockaddr_t *dest) { + isc_result_t result = ISC_R_NOMORE; REQUIRE(DNS_ZONE_VALID(zone)); + REQUIRE(dest != NULL); LOCK_ZONE(zone); INSIST(dns_remote_count(&zone->primaries) > 0); - curraddr = dns_remote_curraddr(&zone->primaries); + if (!dns_remote_done(&zone->primaries)) { + *dest = dns_remote_curraddr(&zone->primaries); + result = ISC_R_SUCCESS; + } UNLOCK_ZONE(zone); - return curraddr; + return result; } isc_time_t