* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: zone.c,v 1.470.12.12 2009/07/11 04:28:14 marka Exp $ */
+/* $Id: zone.c,v 1.470.12.13 2009/10/05 21:57:42 each Exp $ */
/*! \file */
isc_time_t dumptime;
isc_time_t loadtime;
isc_time_t notifytime;
- isc_uint32_t serial;
isc_uint32_t refresh;
isc_uint32_t retry;
isc_uint32_t expire;
isc_time_settoepoch(&zone->dumptime);
isc_time_settoepoch(&zone->loadtime);
zone->notifytime = now;
- zone->serial = 0;
zone->refresh = DNS_ZONE_DEFAULTREFRESH;
zone->retry = DNS_ZONE_DEFAULTRETRY;
zone->expire = 0;
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);
}
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);
* 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: "
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 has gone backwards");
- else if (serial == zone->serial && !hasinclude)
+ else if (serial == oldserial && !hasinclude)
dns_zone_log(zone, ISC_LOG_ERROR,
"zone serial unchanged. "
"zone may fail to transfer "
"to slaves.");
}
- zone->serial = serial;
zone->refresh = RANGE(refresh,
zone->minrefresh, zone->maxrefresh);
zone->retry = RANGE(retry,
zone_settimer(zone, &now);
if (! dns_db_ispersistent(db))
- dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u%s",
- zone->serial,
+ dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u%s", serial,
dns_db_issecure(db) ? " (signed)" : "");
return (result);
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;
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,
}
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)
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;
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",
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");
/*
* 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]",
zone_unload(zone);
goto next_master;
}
- zone->serial = serial;
zone->refresh = RANGE(refresh, zone->minrefresh,
zone->maxrefresh);
zone->retry = RANGE(retry, zone->minretry,
buf[0] = '\0';
dns_zone_log(zone, ISC_LOG_INFO,
"transferred serial %u%s",
- zone->serial, buf);
+ serial, buf);
}
/*