mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
2704. [bug] Serial of dynamic and stub zones could be inconsistent
with their SOA serial. [RT #19387]
This commit is contained in:
parent
3c52c4e44c
commit
3ff75c89eb
5 changed files with 91 additions and 40 deletions
3
CHANGES
3
CHANGES
|
|
@ -1,3 +1,6 @@
|
|||
2704. [bug] Serial of dynamic and stub zones could be inconsistent
|
||||
with their SOA serial. [RT #19387]
|
||||
|
||||
2703. [func] Introduce an OpenSSL "engine" argument with -E
|
||||
for all binaries which can take benefit of
|
||||
crypto hardware. [RT #20230]
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: statschannel.c,v 1.22 2009/02/17 03:40:28 marka Exp $ */
|
||||
/* $Id: statschannel.c,v 1.23 2009/10/05 19:39:20 each Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
|
|
@ -678,9 +678,11 @@ zone_xmlrender(dns_zone_t *zone, void *arg) {
|
|||
xmlTextWriterWriteString(writer, ISC_XMLCHAR buf);
|
||||
xmlTextWriterEndElement(writer);
|
||||
|
||||
serial = dns_zone_getserial(zone);
|
||||
xmlTextWriterStartElement(writer, ISC_XMLCHAR "serial");
|
||||
xmlTextWriterWriteFormatString(writer, "%u", serial);
|
||||
if (dns_zone_getserial2(zone, &serial) == ISC_R_SUCCESS)
|
||||
xmlTextWriterWriteFormatString(writer, "%u", serial);
|
||||
else
|
||||
xmlTextWriterWriteString(writer, ISC_XMLCHAR "-");
|
||||
xmlTextWriterEndElement(writer);
|
||||
|
||||
zonestats = dns_zone_getrequeststats(zone);
|
||||
|
|
@ -729,7 +731,7 @@ generatexml(ns_server_t *server, int *buflen, xmlChar **buf) {
|
|||
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "bind"));
|
||||
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "statistics"));
|
||||
TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "version",
|
||||
ISC_XMLCHAR "2.1"));
|
||||
ISC_XMLCHAR "2.2"));
|
||||
|
||||
/* Set common fields for statistics dump */
|
||||
dumparg.type = statsformat_xml;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: zone.h,v 1.166 2009/07/02 07:39:03 marka Exp $ */
|
||||
/* $Id: zone.h,v 1.167 2009/10/05 19:39:20 each Exp $ */
|
||||
|
||||
#ifndef DNS_ZONE_H
|
||||
#define DNS_ZONE_H 1
|
||||
|
|
@ -150,13 +150,24 @@ dns_zone_getclass(dns_zone_t *zone);
|
|||
*\li 'zone' to be a valid zone.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_zone_getserial2(dns_zone_t *zone, isc_uint32_t *serialp);
|
||||
|
||||
isc_uint32_t
|
||||
dns_zone_getserial(dns_zone_t *zone);
|
||||
/*%<
|
||||
* Returns the current serial number of the zone.
|
||||
* Returns the current serial number of the zone. On success, the SOA
|
||||
* serial of the zone will be copied into '*serialp'.
|
||||
* dns_zone_getserial() cannot catch failure cases and is deprecated by
|
||||
* dns_zone_getserial2().
|
||||
*
|
||||
* Requires:
|
||||
*\li 'zone' to be a valid zone.
|
||||
*\li 'serialp' to be non NULL
|
||||
*
|
||||
* Returns:
|
||||
*\li #ISC_R_SUCCESS
|
||||
*\li #DNS_R_NOTLOADED zone DB is not loaded
|
||||
*/
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -731,6 +731,7 @@ dns_zone_getprivatetype
|
|||
dns_zone_getqueryacl
|
||||
dns_zone_getrequeststats
|
||||
dns_zone_getserial
|
||||
dns_zone_getserial2
|
||||
dns_zone_getsigresigninginterval
|
||||
dns_zone_getsigvalidityinterval
|
||||
dns_zone_getssutable
|
||||
|
|
|
|||
102
lib/dns/zone.c
102
lib/dns/zone.c
|
|
@ -15,7 +15,7 @@
|
|||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: zone.c,v 1.507 2009/09/22 08:38:14 fdupont Exp $ */
|
||||
/* $Id: zone.c,v 1.508 2009/10/05 19:39:20 each Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
|
|
@ -207,7 +207,6 @@ struct dns_zone {
|
|||
isc_time_t nsec3chaintime;
|
||||
isc_time_t refreshkeytime; /* Used by key zones */
|
||||
isc_uint32_t refreshkeycount;
|
||||
isc_uint32_t serial;
|
||||
isc_uint32_t refresh;
|
||||
isc_uint32_t retry;
|
||||
isc_uint32_t expire;
|
||||
|
|
@ -748,7 +747,6 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
|
|||
isc_time_settoepoch(&zone->nsec3chaintime);
|
||||
isc_time_settoepoch(&zone->refreshkeytime);
|
||||
zone->refreshkeycount = 0;
|
||||
zone->serial = 0;
|
||||
zone->refresh = DNS_ZONE_DEFAULTREFRESH;
|
||||
zone->retry = DNS_ZONE_DEFAULTRETRY;
|
||||
zone->expire = 0;
|
||||
|
|
@ -997,16 +995,35 @@ dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
|
|||
UNLOCK_ZONE(zone);
|
||||
}
|
||||
|
||||
isc_uint32_t
|
||||
dns_zone_getserial(dns_zone_t *zone) {
|
||||
isc_uint32_t serial;
|
||||
isc_result_t
|
||||
dns_zone_getserial2(dns_zone_t *zone, isc_uint32_t *serialp) {
|
||||
isc_result_t result;
|
||||
|
||||
REQUIRE(DNS_ZONE_VALID(zone));
|
||||
REQUIRE(serialp != NULL);
|
||||
|
||||
LOCK_ZONE(zone);
|
||||
serial = zone->serial;
|
||||
ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
|
||||
if (zone->db != NULL) {
|
||||
result = zone_get_from_db(zone, zone->db, NULL, NULL, serialp,
|
||||
NULL, NULL, NULL, NULL, NULL);
|
||||
} else
|
||||
result = DNS_R_NOTLOADED;
|
||||
ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
|
||||
UNLOCK_ZONE(zone);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
isc_uint32_t
|
||||
dns_zone_getserial(dns_zone_t *zone) {
|
||||
isc_result_t result;
|
||||
isc_uint32_t serial;
|
||||
|
||||
result = dns_zone_getserial2(zone, &serial);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
serial = 0; /* XXX: not really correct, but no other choice */
|
||||
|
||||
return (serial);
|
||||
}
|
||||
|
||||
|
|
@ -3086,7 +3103,7 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
|
|||
unsigned int soacount = 0;
|
||||
unsigned int nscount = 0;
|
||||
unsigned int errors = 0;
|
||||
isc_uint32_t serial, refresh, retry, expire, minimum;
|
||||
isc_uint32_t serial, oldserial, refresh, retry, expire, minimum;
|
||||
isc_time_t now;
|
||||
isc_boolean_t needdump = ISC_FALSE;
|
||||
isc_boolean_t hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
|
||||
|
|
@ -3238,14 +3255,18 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
|
|||
* This is checked in zone_replacedb() for slave zones
|
||||
* as they don't reload from disk.
|
||||
*/
|
||||
result = zone_get_from_db(zone, zone->db, NULL, NULL,
|
||||
&oldserial, NULL, NULL, NULL,
|
||||
NULL, NULL);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
|
||||
!isc_serial_gt(serial, zone->serial)) {
|
||||
!isc_serial_gt(serial, oldserial)) {
|
||||
isc_uint32_t serialmin, serialmax;
|
||||
|
||||
INSIST(zone->type == dns_zone_master);
|
||||
|
||||
serialmin = (zone->serial + 1) & 0xffffffffU;
|
||||
serialmax = (zone->serial + 0x7fffffffU) &
|
||||
serialmin = (oldserial + 1) & 0xffffffffU;
|
||||
serialmax = (oldserial + 0x7fffffffU) &
|
||||
0xffffffffU;
|
||||
dns_zone_log(zone, ISC_LOG_ERROR,
|
||||
"ixfr-from-differences: "
|
||||
|
|
@ -3254,11 +3275,11 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
|
|||
serialmax);
|
||||
result = DNS_R_BADZONE;
|
||||
goto cleanup;
|
||||
} else if (!isc_serial_ge(serial, zone->serial))
|
||||
} else if (!isc_serial_ge(serial, oldserial))
|
||||
dns_zone_log(zone, ISC_LOG_ERROR,
|
||||
"zone serial (%u/%u) has gone "
|
||||
"backwards", serial, zone->serial);
|
||||
else if (serial == zone->serial && !hasinclude)
|
||||
"backwards", serial, oldserial);
|
||||
else if (serial == oldserial && !hasinclude)
|
||||
dns_zone_log(zone, ISC_LOG_ERROR,
|
||||
"zone serial (%u) unchanged. "
|
||||
"zone may fail to transfer "
|
||||
|
|
@ -3275,7 +3296,6 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
|
|||
"3 * refresh.");
|
||||
}
|
||||
|
||||
zone->serial = serial;
|
||||
zone->refresh = RANGE(refresh,
|
||||
zone->minrefresh, zone->maxrefresh);
|
||||
zone->retry = RANGE(retry,
|
||||
|
|
@ -3311,7 +3331,6 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
|
|||
break;
|
||||
|
||||
case dns_zone_key:
|
||||
zone->serial = serial;
|
||||
result = sync_keyzone(zone, db);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
|
|
@ -3374,9 +3393,8 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
|
|||
}
|
||||
|
||||
if (! dns_db_ispersistent(db))
|
||||
dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u%s",
|
||||
zone->serial,
|
||||
dns_db_issecure(db) ? " (signed)" : "");
|
||||
dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u%s", serial,
|
||||
dns_db_issecure(db) ? " (DNSSEC signed)" : "");
|
||||
|
||||
return (result);
|
||||
|
||||
|
|
@ -8766,7 +8784,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
|
|||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
dns_rdata_soa_t soa;
|
||||
isc_result_t result;
|
||||
isc_uint32_t serial;
|
||||
isc_uint32_t serial, oldserial;
|
||||
unsigned int j;
|
||||
|
||||
zone = revent->ev_arg;
|
||||
|
|
@ -8989,12 +9007,17 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
|
|||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
|
||||
serial = soa.serial;
|
||||
|
||||
zone_debuglog(zone, me, 1, "serial: new %u, old %u",
|
||||
serial, zone->serial);
|
||||
if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
|
||||
result = dns_zone_getserial2(zone, &oldserial);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
zone_debuglog(zone, me, 1, "serial: new %u, old %u",
|
||||
serial, oldserial);
|
||||
} else
|
||||
zone_debuglog(zone, me, 1, "serial: new %u, old not loaded",
|
||||
serial);
|
||||
if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
|
||||
DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
|
||||
isc_serial_gt(serial, zone->serial)) {
|
||||
isc_serial_gt(serial, oldserial)) {
|
||||
if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
|
||||
&zone->sourceaddr, &now)) {
|
||||
dns_zone_log(zone, ISC_LOG_INFO,
|
||||
|
|
@ -9018,7 +9041,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
|
|||
}
|
||||
if (msg != NULL)
|
||||
dns_message_destroy(&msg);
|
||||
} else if (isc_serial_eq(soa.serial, zone->serial)) {
|
||||
} else if (isc_serial_eq(soa.serial, oldserial)) {
|
||||
if (zone->masterfile != NULL) {
|
||||
result = ISC_R_FAILURE;
|
||||
if (zone->journal != NULL)
|
||||
|
|
@ -9051,7 +9074,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
|
|||
if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER))
|
||||
dns_zone_log(zone, ISC_LOG_INFO, "serial number (%u) "
|
||||
"received from master %s < ours (%u)",
|
||||
soa.serial, master, zone->serial);
|
||||
soa.serial, master, oldserial);
|
||||
else
|
||||
zone_debuglog(zone, me, 1, "ahead");
|
||||
zone->mastersok[zone->curmaster] = ISC_TRUE;
|
||||
|
|
@ -10186,13 +10209,21 @@ dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
|
|||
if (result == ISC_R_SUCCESS)
|
||||
result = dns_rdataset_first(rdataset);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
isc_uint32_t serial = 0;
|
||||
isc_uint32_t serial = 0, oldserial;
|
||||
|
||||
dns_rdataset_current(rdataset, &rdata);
|
||||
result = dns_rdata_tostruct(&rdata, &soa, NULL);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
serial = soa.serial;
|
||||
if (isc_serial_le(serial, zone->serial)) {
|
||||
/*
|
||||
* The following should safely be performed without DB
|
||||
* lock and succeed in this context.
|
||||
*/
|
||||
result = zone_get_from_db(zone, zone->db, NULL, NULL,
|
||||
&oldserial, NULL, NULL, NULL,
|
||||
NULL, NULL);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
if (isc_serial_le(serial, oldserial)) {
|
||||
dns_zone_log(zone, ISC_LOG_INFO,
|
||||
"notify from %s: "
|
||||
"zone is up to date",
|
||||
|
|
@ -10870,7 +10901,7 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
|
|||
if (zone->db != NULL && zone->journal != NULL &&
|
||||
DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
|
||||
!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
|
||||
isc_uint32_t serial;
|
||||
isc_uint32_t serial, oldserial;
|
||||
|
||||
dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
|
||||
|
||||
|
|
@ -10885,11 +10916,15 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
|
|||
/*
|
||||
* This is checked in zone_postload() for master zones.
|
||||
*/
|
||||
result = zone_get_from_db(zone, zone->db, NULL, NULL,
|
||||
&oldserial, NULL, NULL, NULL, NULL,
|
||||
NULL);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
if (zone->type == dns_zone_slave &&
|
||||
!isc_serial_gt(serial, zone->serial)) {
|
||||
!isc_serial_gt(serial, oldserial)) {
|
||||
isc_uint32_t serialmin, serialmax;
|
||||
serialmin = (zone->serial + 1) & 0xffffffffU;
|
||||
serialmax = (zone->serial + 0x7fffffffU) & 0xffffffffU;
|
||||
serialmin = (oldserial + 1) & 0xffffffffU;
|
||||
serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
|
||||
dns_zone_log(zone, ISC_LOG_ERROR,
|
||||
"ixfr-from-differences: failed: "
|
||||
"new serial (%u) out of range [%u - %u]",
|
||||
|
|
@ -11082,7 +11117,6 @@ zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
|
|||
zone_unload(zone);
|
||||
goto next_master;
|
||||
}
|
||||
zone->serial = serial;
|
||||
zone->refresh = RANGE(refresh, zone->minrefresh,
|
||||
zone->maxrefresh);
|
||||
zone->retry = RANGE(retry, zone->minretry,
|
||||
|
|
@ -11120,7 +11154,7 @@ zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
|
|||
buf[0] = '\0';
|
||||
dns_zone_log(zone, ISC_LOG_INFO,
|
||||
"transferred serial %u%s",
|
||||
zone->serial, buf);
|
||||
serial, buf);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in a new issue