From: Brian Wellington Date: Tue, 22 Jan 2002 22:05:59 +0000 (+0000) Subject: 1190. [func] Add the "rndc freeze" and"rndc unfreeze" commands. X-Git-Tag: v9.0.1^2~8616 X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=cde7dfea4c1267a2b526114f4ea80fe9db1fc557;p=thirdparty%2Fbind9.git 1190. [func] Add the "rndc freeze" and"rndc unfreeze" commands. [RT #2394] Basically, "freeze" disables dynamic updates to a zone, syncs the journal file into the master file, and removes the journal. This allows manual edits of a dynamic zone file without stopping the server, since the zone is temporarily considered non-dynamic. "unfreeze" re-enables dynamic updates to a zone. So, instead of the old: rndc stop edit master file remove journal restart server you can now do: rndc freeze zone edit master file rndc reload zone rndc unfreeze zone which doesn't require stopping the server. About everyone here at the secure dynamic update workshop wanted this. It will be documented soon. --- diff --git a/CHANGES b/CHANGES index 6797b52f246..b9688519d51 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +1190. [func] Add the "rndc freeze" and"rndc unfreeze" commands. + [RT #2394] + 1189. [bug] On some systems, malloc(0) returns NULL, which could cause the caller to report an out of memory error. [RT #2398] diff --git a/bin/named/control.c b/bin/named/control.c index b32005891b0..2725a1cabcb 100644 --- a/bin/named/control.c +++ b/bin/named/control.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: control.c,v 1.10 2001/12/01 00:34:22 marka Exp $ */ +/* $Id: control.c,v 1.11 2002/01/22 22:05:46 bwelling Exp $ */ #include @@ -117,6 +117,10 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) { result = ns_server_flushname(ns_g_server, command); } else if (command_compare(command, NS_COMMAND_STATUS)) { result = ns_server_status(ns_g_server, text); + } else if (command_compare(command, NS_COMMAND_FREEZE)) { + result = ns_server_freeze(ns_g_server, ISC_TRUE, command); + } else if (command_compare(command, NS_COMMAND_UNFREEZE)) { + result = ns_server_freeze(ns_g_server, ISC_FALSE, command); } else { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_WARNING, diff --git a/bin/named/include/named/control.h b/bin/named/include/named/control.h index 9ff44a064bc..15678e5b190 100644 --- a/bin/named/include/named/control.h +++ b/bin/named/include/named/control.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: control.h,v 1.8 2001/11/27 04:06:10 marka Exp $ */ +/* $Id: control.h,v 1.9 2002/01/22 22:05:51 bwelling Exp $ */ #ifndef NAMED_CONTROL_H #define NAMED_CONTROL_H 1 @@ -45,6 +45,8 @@ #define NS_COMMAND_FLUSH "flush" #define NS_COMMAND_FLUSHNAME "flushname" #define NS_COMMAND_STATUS "status" +#define NS_COMMAND_FREEZE "freeze" +#define NS_COMMAND_UNFREEZE "unfreeze" isc_result_t ns_controls_create(ns_server_t *server, ns_controls_t **ctrlsp); diff --git a/bin/named/include/named/server.h b/bin/named/include/named/server.h index 7a1dd83c46e..e5d0f475b3a 100644 --- a/bin/named/include/named/server.h +++ b/bin/named/include/named/server.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: server.h,v 1.63 2001/11/27 04:06:11 marka Exp $ */ +/* $Id: server.h,v 1.64 2002/01/22 22:05:52 bwelling Exp $ */ #ifndef NAMED_SERVER_H #define NAMED_SERVER_H 1 @@ -185,4 +185,10 @@ ns_server_flushname(ns_server_t *server, char *args); isc_result_t ns_server_status(ns_server_t *server, 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); + #endif /* NAMED_SERVER_H */ diff --git a/bin/named/server.c b/bin/named/server.c index 487efa3f08d..20111acfa7f 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: server.c,v 1.367 2002/01/04 02:32:04 gson Exp $ */ +/* $Id: server.c,v 1.368 2002/01/22 22:05:48 bwelling Exp $ */ #include @@ -2841,3 +2841,63 @@ ns_server_status(ns_server_t *server, isc_buffer_t *text) { isc_buffer_add(text, n); return (ISC_R_SUCCESS); } + +/* + * Act on a "freeze" or "unfreeze" 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; + dns_zone_t *zone = NULL; + dns_zonetype_t type; + char classstr[DNS_RDATACLASS_FORMATSIZE]; + char zonename[DNS_NAME_FORMATSIZE]; + dns_view_t *view; + char *journal; + const char *vname, *sep; + + result = zone_from_args(server, args, &zone); + if (result != ISC_R_SUCCESS) + return (result); + if (zone == NULL) + return (ISC_R_UNEXPECTEDEND); + type = dns_zone_gettype(zone); + if (type != dns_zone_master) { + dns_zone_detach(&zone); + return (ISC_R_NOTFOUND); + } + + if (freeze) { + result = dns_zone_flush(zone); + 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); + + 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)); + 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", + zonename, classstr, sep, vname, + isc_result_totext(result)); + dns_zone_detach(&zone); + return (result); +} diff --git a/bin/named/update.c b/bin/named/update.c index 0263d351eac..2d1d0ffff48 100644 --- a/bin/named/update.c +++ b/bin/named/update.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: update.c,v 1.95 2002/01/22 21:45:07 gson Exp $ */ +/* $Id: update.c,v 1.96 2002/01/22 22:05:49 bwelling Exp $ */ #include @@ -2163,6 +2163,8 @@ update_action(isc_task_t *task, isc_event_t *event) { * Check Requestor's Permissions. It seems a bit silly to do this * only after prerequisite testing, but that is what RFC2136 says. */ + if (dns_zone_getupdatedisabled(zone)) + FAILC(DNS_R_REFUSED, "dynamic update temporarily disabled"); if (ssutable == NULL) { char msg[DNS_RDATACLASS_FORMATSIZE + DNS_NAME_FORMATSIZE + sizeof("update '/'")]; diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h index 98f3a2d58ca..6cb8f96c832 100644 --- a/lib/dns/include/dns/zone.h +++ b/lib/dns/include/dns/zone.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.h,v 1.110 2002/01/22 21:52:32 gson Exp $ */ +/* $Id: zone.h,v 1.111 2002/01/22 22:05:56 bwelling Exp $ */ #ifndef DNS_ZONE_H #define DNS_ZONE_H 1 @@ -758,6 +758,12 @@ dns_zone_clearxfracl(dns_zone_t *zone); * 'zone' to be a valid zone. */ +isc_boolean_t +dns_zone_getupdatedisabled(dns_zone_t *zone); + +void +dns_zone_setupdatedisabled(dns_zone_t *zone, isc_boolean_t state); + void dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity); /* diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 96b7ab0c6d8..b1f716e55ea 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.c,v 1.359 2002/01/21 11:00:20 bwelling Exp $ */ +/* $Id: zone.c,v 1.360 2002/01/22 22:05:53 bwelling Exp $ */ #include @@ -185,6 +185,7 @@ struct dns_zone { dns_acl_t *notify_acl; dns_acl_t *query_acl; dns_acl_t *xfr_acl; + isc_boolean_t update_disabled; dns_severity_t check_names; ISC_LIST(dns_notify_t) notifies; dns_request_t *request; @@ -537,6 +538,7 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) { zone->notify_acl = NULL; zone->query_acl = NULL; zone->xfr_acl = NULL; + zone->update_disabled = ISC_FALSE; zone->check_names = dns_severity_ignore; zone->request = NULL; zone->lctx = NULL; @@ -908,8 +910,8 @@ zone_isdynamic(dns_zone_t *zone) { return (ISC_TF(zone->type == dns_zone_slave || zone->type == dns_zone_stub || - zone->ssutable != NULL || - (zone->update_acl != NULL && + (!zone->update_disabled && zone->ssutable != NULL) || + (!zone->update_disabled && zone->update_acl != NULL && ! (zone->update_acl->length == 1 && zone->update_acl->elements[0].negative == ISC_TRUE && @@ -4469,6 +4471,19 @@ dns_zone_clearxfracl(dns_zone_t *zone) { UNLOCK_ZONE(zone); } +isc_boolean_t +dns_zone_getupdatedisabled(dns_zone_t *zone) { + REQUIRE(DNS_ZONE_VALID(zone)); + return (zone->update_disabled); + +} + +void +dns_zone_setupdatedisabled(dns_zone_t *zone, isc_boolean_t state) { + REQUIRE(DNS_ZONE_VALID(zone)); + zone->update_disabled = state; +} + void dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {