diff --git a/CHANGES b/CHANGES index 6797b52f24..b9688519d5 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 b32005891b..2725a1cabc 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 9ff44a064b..15678e5b19 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 7a1dd83c46..e5d0f475b3 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 487efa3f08..20111acfa7 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 0263d351ea..2d1d0ffff4 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 98f3a2d58c..6cb8f96c83 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 96b7ab0c6d..b1f716e55e 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) {