Commit cde7dfea authored by Brian Wellington's avatar Brian Wellington

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.
parent 915c16e8
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]
......
......@@ -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 <config.h>
......@@ -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,
......
......@@ -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);
......
......@@ -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 */
......@@ -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 <config.h>
......@@ -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);
}
......@@ -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 <config.h>
......@@ -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 '/'")];
......
......@@ -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);
/*
......
......@@ -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 <config.h>
......@@ -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) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment