From: Mark Andrews Date: Thu, 2 Jul 2009 07:39:03 +0000 (+0000) Subject: 2920. [bug] Delay thawing the zone until the reload of it has X-Git-Tag: v9.5.2b1~36^2~21 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=109580e7e5c92b98c641836ccb5949b4802ffced;p=thirdparty%2Fbind9.git 2920. [bug] Delay thawing the zone until the reload of it has completed successfully. [RT #19750] --- diff --git a/CHANGES b/CHANGES index d1b23919940..d66efd15c9f 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +2920. [bug] Delay thawing the zone until the reload of it has + completed successfully. [RT #19750] + 2619. [func] Add support for RFC 5011, automatic trust anchor maintenance. The new "managed-keys" statement can be used in place of "trusted-keys" for zones which diff --git a/bin/named/control.c b/bin/named/control.c index 8bd8f6ce361..63f0979bbc8 100644 --- a/bin/named/control.c +++ b/bin/named/control.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: control.c,v 1.33 2007/09/13 04:45:18 each Exp $ */ +/* $Id: control.c,v 1.34 2009/07/02 07:39:02 marka Exp $ */ /*! \file */ @@ -170,10 +170,12 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) { } else if (command_compare(command, NS_COMMAND_TSIGDELETE)) { result = ns_server_tsigdelete(ns_g_server, command, text); } else if (command_compare(command, NS_COMMAND_FREEZE)) { - result = ns_server_freeze(ns_g_server, ISC_TRUE, command); + result = ns_server_freeze(ns_g_server, ISC_TRUE, command, + text); } else if (command_compare(command, NS_COMMAND_UNFREEZE) || command_compare(command, NS_COMMAND_THAW)) { - result = ns_server_freeze(ns_g_server, ISC_FALSE, command); + result = ns_server_freeze(ns_g_server, ISC_FALSE, command, + text); } else if (command_compare(command, NS_COMMAND_RECURSING)) { result = ns_server_dumprecursing(ns_g_server); } else if (command_compare(command, NS_COMMAND_TIMERPOKE)) { diff --git a/bin/named/include/named/server.h b/bin/named/include/named/server.h index b076cbaa3f1..4ade41a0085 100644 --- a/bin/named/include/named/server.h +++ b/bin/named/include/named/server.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: server.h,v 1.99 2009/06/30 02:52:32 each Exp $ */ +/* $Id: server.h,v 1.100 2009/07/02 07:39:02 marka Exp $ */ #ifndef NAMED_SERVER_H #define NAMED_SERVER_H 1 @@ -286,7 +286,8 @@ ns_server_tsigdelete(ns_server_t *server, char *command, isc_buffer_t *text); * Enable or disable updates for a zone. */ isc_result_t -ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args); +ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args, + isc_buffer_t *text); /*% * Dump the current recursive queries. diff --git a/bin/named/server.c b/bin/named/server.c index 890f5b46408..f14337c6f7e 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: server.c,v 1.536 2009/06/30 23:48:01 tbox Exp $ */ +/* $Id: server.c,v 1.537 2009/07/02 07:39:02 marka Exp $ */ /*! \file */ @@ -6218,7 +6218,9 @@ ns_server_tsiglist(ns_server_t *server, isc_buffer_t *text) { * Act on a "freeze" or "thaw" command from the command channel. */ isc_result_t -ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args) { +ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args, + isc_buffer_t *text) +{ isc_result_t result, tresult; dns_zone_t *zone = NULL; dns_zonetype_t type; @@ -6228,6 +6230,7 @@ ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args) { char *journal; const char *vname, *sep; isc_boolean_t frozen; + const char *msg = NULL; result = zone_from_args(server, args, &zone); if (result != ISC_R_SUCCESS) @@ -6260,25 +6263,47 @@ ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args) { frozen = dns_zone_getupdatedisabled(zone); if (freeze) { - if (frozen) + if (frozen) { + msg = "WARNING: The zone was already frozen.\n" + "Someone else may be editing it or " + "it may still be re-loading."; result = DNS_R_FROZEN; - if (result == ISC_R_SUCCESS) + } + if (result == ISC_R_SUCCESS) { result = dns_zone_flush(zone); + if (result != ISC_R_SUCCESS) + msg = "Flushing the zone updates to " + "disk failed."; + } if (result == ISC_R_SUCCESS) { journal = dns_zone_getjournal(zone); if (journal != NULL) (void)isc_file_remove(journal); } + if (result == ISC_R_SUCCESS) + dns_zone_setupdatedisabled(zone, freeze); } else { if (frozen) { - result = dns_zone_load(zone); - if (result == DNS_R_CONTINUE || - result == DNS_R_UPTODATE) + result = dns_zone_loadandthaw(zone); + switch (result) { + case ISC_R_SUCCESS: + case DNS_R_UPTODATE: + msg = "The zone reload and thaw was " + "successful."; + result = ISC_R_SUCCESS; + break; + case DNS_R_CONTINUE: + msg = "A zone reload and thaw was started.\n" + "Check the logs to see the result."; result = ISC_R_SUCCESS; + break; + } } } - if (result == ISC_R_SUCCESS) - dns_zone_setupdatedisabled(zone, freeze); + + if (msg != NULL && strlen(msg) < isc_buffer_availablelength(text)) + isc_buffer_putmem(text, (const unsigned char *)msg, + strlen(msg) + 1); view = dns_zone_getview(zone); if (strcmp(view->name, "_default") == 0 || diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h index 0f5c0023007..5b781d5e33c 100644 --- a/lib/dns/include/dns/zone.h +++ b/lib/dns/include/dns/zone.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.h,v 1.165 2009/06/30 02:52:32 each Exp $ */ +/* $Id: zone.h,v 1.166 2009/07/02 07:39:03 marka Exp $ */ #ifndef DNS_ZONE_H #define DNS_ZONE_H 1 @@ -257,6 +257,9 @@ dns_zone_load(dns_zone_t *zone); isc_result_t dns_zone_loadnew(dns_zone_t *zone); + +isc_result_t +dns_zone_loadandthaw(dns_zone_t *zone); /*%< * Cause the database to be loaded from its backing store. * Confirm that the minimum requirements for the zone type are @@ -265,6 +268,8 @@ dns_zone_loadnew(dns_zone_t *zone); * dns_zone_loadnew() only loads zones that are not yet loaded. * dns_zone_load() also loads zones that are already loaded and * and whose master file has changed since the last load. + * dns_zone_loadandthaw() is similar to dns_zone_load() but will + * also re-enable DNS UPDATEs when the load completes. * * Require: *\li 'zone' to be a valid zone. diff --git a/lib/dns/win32/libdns.def b/lib/dns/win32/libdns.def index ff1575b4a39..77c489832ec 100644 --- a/lib/dns/win32/libdns.def +++ b/lib/dns/win32/libdns.def @@ -743,6 +743,7 @@ dns_zone_iattach dns_zone_idetach dns_zone_isforced dns_zone_load +dns_zone_loadandthaw dns_zone_log dns_zone_maintenance dns_zone_markdirty diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 484318d05a3..7d785d17d0e 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.c,v 1.495 2009/06/30 23:48:01 tbox Exp $ */ +/* $Id: zone.c,v 1.496 2009/07/02 07:39:02 marka Exp $ */ /*! \file */ @@ -358,12 +358,15 @@ struct dns_zone { #define DNS_ZONEFLG_USEALTXFRSRC 0x00800000U #define DNS_ZONEFLG_SOABEFOREAXFR 0x01000000U #define DNS_ZONEFLG_NEEDCOMPACT 0x02000000U -#define DNS_ZONEFLG_REFRESHING 0x04000000U /*%< Refreshing keydata */ +#define DNS_ZONEFLG_REFRESHING 0x04000000U /*%< Refreshing keydata */ +#define DNS_ZONEFLG_THAW 0x08000000U #define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0) /* Flags for zone_load() */ #define DNS_ZONELOADFLAG_NOSTAT 0x00000001U /* Do not stat() master files */ +#define DNS_ZONELOADFLAG_THAW 0x00000002U /* Thaw the zone on successful + load. */ #define UNREACH_CHACHE_SIZE 10U #define UNREACH_HOLD_TIME 600 /* 10 minutes */ @@ -1342,7 +1345,9 @@ zone_load(dns_zone_t *zone, unsigned int flags) { INSIST(zone->type != dns_zone_none); if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) { - result = ISC_R_SUCCESS; + if ((flags & DNS_ZONELOADFLAG_THAW) != 0) + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW); + result = DNS_R_CONTINUE; goto cleanup; } @@ -1476,6 +1481,8 @@ zone_load(dns_zone_t *zone, unsigned int flags) { if (result == DNS_R_CONTINUE) { DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING); + if ((flags & DNS_ZONELOADFLAG_THAW) != 0) + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW); goto cleanup; } @@ -1498,6 +1505,30 @@ dns_zone_loadnew(dns_zone_t *zone) { return (zone_load(zone, DNS_ZONELOADFLAG_NOSTAT)); } +isc_result_t +dns_zone_loadandthaw(dns_zone_t *zone) { + isc_result_t result; + + result = zone_load(zone, DNS_ZONELOADFLAG_THAW); + switch (result) { + case DNS_R_CONTINUE: + /* Deferred thaw. */ + break; + case ISC_R_SUCCESS: + case DNS_R_UPTODATE: + case DNS_R_SEENINCLUDE: + zone->update_disabled = ISC_FALSE; + break; + case DNS_R_NOMASTERFILE: + zone->update_disabled = ISC_FALSE; + break; + default: + /* Error, remain in disabled state. */ + break; + } + return (result); +} + static unsigned int get_master_options(dns_zone_t *zone) { unsigned int options; @@ -11172,6 +11203,13 @@ zone_loaddone(void *arg, isc_result_t result) { (void)zone_postload(load->zone, load->db, load->loadtime, result); zonemgr_putio(&load->zone->readio); DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_LOADING); + /* + * Leave the zone frozen if the reload fails. + */ + if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) && + DNS_ZONE_FLAG(load->zone, DNS_ZONEFLG_THAW)) + zone->update_disabled = ISC_FALSE; + DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_THAW); UNLOCK_ZONE(load->zone); load->magic = 0;