diff --git a/CHANGES b/CHANGES index 8317c0a0e4..e419b2afc0 100644 --- a/CHANGES +++ b/CHANGES @@ -3,7 +3,7 @@ 1797. [func] named-checkconf now check acls to verify that they only refer to existing acls. [RT #13101] -1796. [placeholder] rt12498 +1796. [func] "rndc freeze/thaw" now freezes/thaws all zones. 1795. [placeholder] rt13396 diff --git a/bin/named/server.c b/bin/named/server.c index 0dc6cdf049..b2a6e4ad6b 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: server.c,v 1.436 2005/01/12 01:56:07 marka Exp $ */ +/* $Id: server.c,v 1.437 2005/01/14 03:28:07 marka Exp $ */ #include @@ -4109,11 +4109,11 @@ ns_server_status(ns_server_t *server, isc_buffer_t *text) { } /* - * Act on a "freeze" or "unfreeze" command from the command channel. + * 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) { - isc_result_t result; + isc_result_t result, tresult; dns_zone_t *zone = NULL; dns_zonetype_t type; char classstr[DNS_RDATACLASS_FORMATSIZE]; @@ -4126,8 +4126,26 @@ ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args) { result = zone_from_args(server, args, &zone); if (result != ISC_R_SUCCESS) return (result); - if (zone == NULL) - return (ISC_R_UNEXPECTEDEND); + if (zone == NULL) { + result = isc_task_beginexclusive(server->task); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + tresult = ISC_R_SUCCESS; + for (view = ISC_LIST_HEAD(server->viewlist); + view != NULL; + view = ISC_LIST_NEXT(view, link)) { + result = dns_view_freezezones(view, freeze); + if (result != ISC_R_SUCCESS && + tresult == ISC_R_SUCCESS) + tresult = result; + } + isc_task_endexclusive(server->task); + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_INFO, + "%s all zones: %s", + freeze ? "freezing" : "thawing", + isc_result_totext(tresult)); + return (tresult); + } type = dns_zone_gettype(zone); if (type != dns_zone_master) { dns_zone_detach(&zone); @@ -4173,7 +4191,7 @@ ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "%s zone '%s/%s'%s%s: %s", - freeze ? "freezing" : "unfreezing", + freeze ? "freezing" : "thawing", zonename, classstr, sep, vname, isc_result_totext(result)); dns_zone_detach(&zone); diff --git a/bin/rndc/rndc.c b/bin/rndc/rndc.c index d2f16edc56..8b0aea4732 100644 --- a/bin/rndc/rndc.c +++ b/bin/rndc/rndc.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rndc.c,v 1.100 2004/10/11 05:30:20 marka Exp $ */ +/* $Id: rndc.c,v 1.101 2005/01/14 03:28:07 marka Exp $ */ /* * Principal Author: DCL @@ -100,8 +100,10 @@ command is one of the following:\n\ Schedule immediate maintenance for a zone.\n\ retransfer zone [class [view]]\n\ Retransfer a single zone without checking serial number.\n\ + freeze Suspend updates to all dynamic zones.\n\ freeze zone [class [view]]\n\ Suspend updates to a dynamic zone.\n\ + thaw Enable updates to all dynamic zones and reload them.\n\ thaw zone [class [view]]\n\ Enable updates to a frozen dynamic zone and reload it.\n\ notify zone [class [view]]\n\ diff --git a/lib/dns/include/dns/view.h b/lib/dns/include/dns/view.h index 4570cfc70b..a6f359a66c 100644 --- a/lib/dns/include/dns/view.h +++ b/lib/dns/include/dns/view.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: view.h,v 1.92 2004/12/21 10:45:19 jinmei Exp $ */ +/* $Id: view.h,v 1.93 2005/01/14 03:28:08 marka Exp $ */ #ifndef DNS_VIEW_H #define DNS_VIEW_H 1 @@ -787,4 +787,12 @@ dns_view_getrootdelonly(dns_view_t *view); * 'view' is valid. */ +isc_result_t +dns_view_freezezones(dns_view_t *view, isc_boolean_t freeze); +/* + * Freeze/thaw updates to master zones. + * + * Requires: + * 'view' is valid. + */ #endif /* DNS_VIEW_H */ diff --git a/lib/dns/include/dns/zt.h b/lib/dns/include/dns/zt.h index cfd77a85a3..63ab5fa0c7 100644 --- a/lib/dns/include/dns/zt.h +++ b/lib/dns/include/dns/zt.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zt.h,v 1.30 2004/03/05 05:09:48 marka Exp $ */ +/* $Id: zt.h,v 1.31 2005/01/14 03:28:09 marka Exp $ */ #ifndef DNS_ZT_H #define DNS_ZT_H 1 @@ -145,9 +145,21 @@ dns_zt_loadnew(dns_zt_t *zt, isc_boolean_t stop); * 'zt' to be valid */ +isc_result_t +dns_zt_freezezones(dns_zt_t *zt, isc_boolean_t freeze); +/* + * Freeze/thaw updates to master zones. + * Any pending updates will be flushed. + * Zones will be reloaded on thaw. + */ + isc_result_t dns_zt_apply(dns_zt_t *zt, isc_boolean_t stop, isc_result_t (*action)(dns_zone_t *, void *), void *uap); + +isc_result_t +dns_zt_apply2(dns_zt_t *zt, isc_boolean_t stop, isc_result_t *sub, + isc_result_t (*action)(dns_zone_t *, void *), void *uap); /* * Apply a given 'action' to all zone zones in the table. * If 'stop' is 'ISC_TRUE' then walking the zone tree will stop if @@ -158,7 +170,9 @@ dns_zt_apply(dns_zt_t *zt, isc_boolean_t stop, * 'action' to be non NULL. * * Returns: - * ISC_R_SUCCESS if action was applied to all nodes. + * ISC_R_SUCCESS if action was applied to all nodes. If 'stop' is + * ISC_FALSE and 'sub' is non NULL then the first error (if any) + * reported by 'action' is returned in '*sub'; * any error code from 'action'. */ diff --git a/lib/dns/view.c b/lib/dns/view.c index 6a3fa54e66..61b208ced1 100644 --- a/lib/dns/view.c +++ b/lib/dns/view.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: view.c,v 1.128 2004/12/29 23:01:13 marka Exp $ */ +/* $Id: view.c,v 1.129 2005/01/14 03:28:07 marka Exp $ */ #include @@ -1348,3 +1348,9 @@ dns_view_getrootdelonly(dns_view_t *view) { REQUIRE(DNS_VIEW_VALID(view)); return (view->rootdelonly); } + +isc_result_t +dns_view_freezezones(dns_view_t *view, isc_boolean_t value) { + REQUIRE(DNS_VIEW_VALID(view)); + return (dns_zt_freezezones(view->zonetable, value)); +} diff --git a/lib/dns/zt.c b/lib/dns/zt.c index 4b942f6dbb..6fbd260d64 100644 --- a/lib/dns/zt.c +++ b/lib/dns/zt.c @@ -15,16 +15,22 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zt.c,v 1.38 2004/03/05 05:09:27 marka Exp $ */ +/* $Id: zt.c,v 1.39 2005/01/14 03:28:07 marka Exp $ */ #include +#include #include #include +#include #include +#include +#include #include +#include #include +#include #include #include @@ -51,6 +57,9 @@ load(dns_zone_t *zone, void *uap); static isc_result_t loadnew(dns_zone_t *zone, void *uap); +static isc_result_t +freezezones(dns_zone_t *zone, void *uap); + isc_result_t dns_zt_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, dns_zt_t **ztp) { dns_zt_t *zt; @@ -265,13 +274,91 @@ loadnew(dns_zone_t *zone, void *uap) { return (result); } +isc_result_t +dns_zt_freezezones(dns_zt_t *zt, isc_boolean_t freeze) { + isc_result_t result, tresult; + + REQUIRE(VALID_ZT(zt)); + + RWLOCK(&zt->rwlock, isc_rwlocktype_read); + result = dns_zt_apply2(zt, ISC_FALSE, &tresult, freezezones, &freeze); + RWUNLOCK(&zt->rwlock, isc_rwlocktype_read); + return ((result == ISC_R_SUCCESS) ? tresult : result); +} + +static isc_result_t +freezezones(dns_zone_t *zone, void *uap) { + isc_boolean_t freeze = *(isc_boolean_t *)uap; + isc_boolean_t frozen; + isc_result_t result = ISC_R_SUCCESS; + char classstr[DNS_RDATACLASS_FORMATSIZE]; + char zonename[DNS_NAME_FORMATSIZE]; + dns_view_t *view; + char *journal; + const char *vname; + const char *sep; + int level; + + if (dns_zone_gettype(zone) != dns_zone_master) + return (ISC_R_SUCCESS); + + frozen = dns_zone_getupdatedisabled(zone); + if (freeze) { + if (frozen) + result = DNS_R_FROZEN; + if (result == ISC_R_SUCCESS) + result = dns_zone_flush(zone); + if (result == ISC_R_SUCCESS) { + journal = dns_zone_getjournal(zone); + if (journal != NULL) + (void)isc_file_remove(journal); + } + } else { + if (frozen) { + result = dns_zone_load(zone); + if (result == DNS_R_CONTINUE || + result == DNS_R_UPTODATE) + result = ISC_R_SUCCESS; + } + } + if (result == ISC_R_SUCCESS) + dns_zone_setupdatedisabled(zone, freeze); + view = dns_zone_getview(zone); + if (strcmp(view->name, "_bind") == 0 || + strcmp(view->name, "_default") == 0) + { + vname = ""; + sep = ""; + } else { + vname = view->name; + sep = " "; + } + dns_rdataclass_format(dns_zone_getclass(zone), classstr, + sizeof(classstr)); + dns_name_format(dns_zone_getorigin(zone), zonename, sizeof(zonename)); + level = (result != ISC_R_SUCCESS) ? ISC_LOG_ERROR : ISC_LOG_DEBUG(1); + isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE, + level, "%s zone '%s/%s'%s%s: %s", + freeze ? "freezing" : "thawing", + zonename, classstr, sep, vname, + isc_result_totext(result)); + return (result); +} + isc_result_t dns_zt_apply(dns_zt_t *zt, isc_boolean_t stop, isc_result_t (*action)(dns_zone_t *, void *), void *uap) +{ + return (dns_zt_apply2(zt, stop, NULL, action, uap)); +} + +isc_result_t +dns_zt_apply2(dns_zt_t *zt, isc_boolean_t stop, isc_result_t *sub, + isc_result_t (*action)(dns_zone_t *, void *), void *uap) { dns_rbtnode_t *node; dns_rbtnodechain_t chain; - isc_result_t result; + isc_result_t result, tresult = ISC_R_SUCCESS; dns_zone_t *zone; REQUIRE(VALID_ZT(zt)); @@ -292,8 +379,13 @@ dns_zt_apply(dns_zt_t *zt, isc_boolean_t stop, zone = node->data; if (zone != NULL) result = (action)(zone, uap); - if (result != ISC_R_SUCCESS && stop) + if (result != ISC_R_SUCCESS && stop) { + tresult = result; goto cleanup; /* don't break */ + } else if (result != ISC_R_SUCCESS && + tresult != ISC_R_SUCCESS) + tresult = result; + } result = dns_rbtnodechain_next(&chain, NULL, NULL); } @@ -302,6 +394,8 @@ dns_zt_apply(dns_zt_t *zt, isc_boolean_t stop, cleanup: dns_rbtnodechain_invalidate(&chain); + if (sub != NULL) + *sub = tresult; return (result); }