1594. [bug] 'rndc dumpdb' could prevent named from answering

queries while the dump was in progress.  [RT #10565]
This commit is contained in:
Mark Andrews
2004-04-08 00:10:42 +00:00
parent 71ff97b91b
commit 0822cc5065
2 changed files with 231 additions and 38 deletions

View File

@@ -25,7 +25,8 @@
1595. [func] New notify type 'master-only'. Enable notify for
master zones only.
1594. [placeholder] rt10565
1594. [bug] 'rndc dumpdb' could prevent named from answering
queries while the dump was in progress. [RT #10565]
1593. [bug] rndc should return "unknown command" to unknown
commands. [RT# 10642]

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: server.c,v 1.419 2004/03/14 23:00:47 marka Exp $ */
/* $Id: server.c,v 1.420 2004/04/08 00:10:42 marka Exp $ */
#include <config.h>
@@ -49,6 +49,7 @@
#include <dns/journal.h>
#include <dns/keytable.h>
#include <dns/master.h>
#include <dns/masterdump.h>
#include <dns/order.h>
#include <dns/peer.h>
#include <dns/portlist.h>
@@ -129,6 +130,32 @@ struct ns_dispatch {
ISC_LINK(struct ns_dispatch) link;
};
struct dumpcontext {
isc_mem_t *mctx;
isc_boolean_t dumpcache;
isc_boolean_t dumpzones;
FILE *fp;
ISC_LIST(struct viewlistentry) viewlist;
struct viewlistentry *view;
struct zonelistentry *zone;
dns_dumpctx_t *mdctx;
dns_db_t *db;
dns_db_t *cache;
isc_task_t *task;
dns_dbversion_t *version;
};
struct viewlistentry {
dns_view_t *view;
ISC_LINK(struct viewlistentry) link;
ISC_LIST(struct zonelistentry) zonelist;
};
struct zonelistentry {
dns_zone_t *zone;
ISC_LINK(struct zonelistentry) link;
};
static void
fatal(const char *msg, isc_result_t result);
@@ -3518,32 +3545,206 @@ ns_server_dumpstats(ns_server_t *server) {
}
static isc_result_t
printzone(dns_zone_t *zone, void *uap) {
FILE *fp = uap;
char buf[1024+32];
isc_result_t result;
add_zone_tolist(dns_zone_t *zone, void *uap) {
struct dumpcontext *dctx = uap;
struct zonelistentry *zle;
dns_zone_name(zone, buf, sizeof(buf));
fprintf(fp, ";\n; Zone dump of '%s'\n;\n", buf);
result = dns_zone_dumptostream(zone, fp);
if (result == ISC_R_NOTIMPLEMENTED) {
fprintf(fp, "; %s\n", dns_result_totext(result));
result = ISC_R_SUCCESS;
}
zle = isc_mem_get(dctx->mctx, sizeof *zle);
if (zle == NULL)
return (ISC_R_NOMEMORY);
zle->zone = NULL;
dns_zone_attach(zone, &zle->zone);
ISC_LINK_INIT(zle, link);
ISC_LIST_APPEND(ISC_LIST_TAIL(dctx->viewlist)->zonelist, zle, link);
return (ISC_R_SUCCESS);
}
static isc_result_t
add_view_tolist(struct dumpcontext *dctx, dns_view_t *view) {
struct viewlistentry *vle;
isc_result_t result = ISC_R_SUCCESS;
vle = isc_mem_get(dctx->mctx, sizeof *vle);
if (vle == NULL)
return (ISC_R_NOMEMORY);
vle->view = NULL;
dns_view_attach(view, &vle->view);
ISC_LINK_INIT(vle, link);
ISC_LIST_INIT(vle->zonelist);
ISC_LIST_APPEND(dctx->viewlist, vle, link);
if (dctx->dumpzones)
result = dns_zt_apply(view->zonetable, ISC_TRUE,
add_zone_tolist, dctx);
return (result);
}
static void
dumpcontext_destroy(struct dumpcontext *dctx) {
struct viewlistentry *vle;
struct zonelistentry *zle;
vle = ISC_LIST_HEAD(dctx->viewlist);
while (vle != NULL) {
ISC_LIST_UNLINK(dctx->viewlist, vle, link);
zle = ISC_LIST_HEAD(vle->zonelist);
while (zle != NULL) {
ISC_LIST_UNLINK(vle->zonelist, zle, link);
dns_zone_detach(&zle->zone);
isc_mem_put(dctx->mctx, zle, sizeof *zle);
zle = ISC_LIST_HEAD(vle->zonelist);
}
dns_view_detach(&vle->view);
isc_mem_put(dctx->mctx, vle, sizeof *vle);
vle = ISC_LIST_HEAD(dctx->viewlist);
}
if (dctx->version != NULL)
dns_db_closeversion(dctx->db, &dctx->version, ISC_FALSE);
if (dctx->db != NULL)
dns_db_detach(&dctx->db);
if (dctx->cache != NULL)
dns_db_detach(&dctx->cache);
if (dctx->task != NULL)
isc_task_detach(&dctx->task);
if (dctx->fp != NULL)
(void)isc_stdio_close(dctx->fp);
if (dctx->mdctx != NULL)
dns_dumpctx_detach(&dctx->mdctx);
isc_mem_put(dctx->mctx, dctx, sizeof *dctx);
}
static void
dumpdone(void *arg, isc_result_t result) {
struct dumpcontext *dctx = arg;
char buf[1024+32];
const dns_master_style_t *style;
if (result != ISC_R_SUCCESS)
goto cleanup;
if (dctx->mdctx != NULL)
dns_dumpctx_detach(&dctx->mdctx);
if (dctx->view == NULL) {
dctx->view = ISC_LIST_HEAD(dctx->viewlist);
if (dctx->view == NULL)
goto done;
INSIST(dctx->zone == NULL);
}
nextview:
fprintf(dctx->fp, ";\n; Start view %s\n;\n", dctx->view->view->name);
if (dctx->zone == NULL && dctx->cache == NULL && dctx->dumpcache) {
style = &dns_master_style_cache;
/* start cache dump */
if (dctx->view->view->cachedb != NULL)
dns_db_attach(dctx->view->view->cachedb, &dctx->cache);
if (dctx->cache != NULL) {
fprintf(dctx->fp, ";\n; Cache dump of view '%s'\n;\n",
dctx->view->view->name);
result = dns_master_dumptostreaminc(dctx->mctx,
dctx->cache, NULL,
style, dctx->fp,
dctx->task,
dumpdone, dctx,
&dctx->mdctx);
if (result == DNS_R_CONTINUE)
return;
if (result == ISC_R_NOTIMPLEMENTED)
fprintf(dctx->fp, "; %s\n",
dns_result_totext(result));
else if (result != ISC_R_SUCCESS)
goto cleanup;
}
}
if (dctx->cache != NULL) {
dns_adb_dump(dctx->view->view->adb, dctx->fp);
dns_db_detach(&dctx->cache);
}
if (dctx->dumpzones) {
style = &dns_master_style_full;
nextzone:
if (dctx->version != NULL)
dns_db_closeversion(dctx->db, &dctx->version,
ISC_FALSE);
if (dctx->db != NULL)
dns_db_detach(&dctx->db);
if (dctx->zone == NULL)
dctx->zone = ISC_LIST_HEAD(dctx->view->zonelist);
else
dctx->zone = ISC_LIST_NEXT(dctx->zone, link);
if (dctx->zone != NULL) {
/* start zone dump */
dns_zone_name(dctx->zone->zone, buf, sizeof(buf));
fprintf(dctx->fp, ";\n; Zone dump of '%s'\n;\n", buf);
result = dns_zone_getdb(dctx->zone->zone, &dctx->db);
if (result != ISC_R_SUCCESS) {
fprintf(dctx->fp, "; %s\n",
dns_result_totext(result));
goto nextzone;
}
dns_db_currentversion(dctx->db, &dctx->version);
result = dns_master_dumptostreaminc(dctx->mctx,
dctx->db,
dctx->version,
style, dctx->fp,
dctx->task,
dumpdone, dctx,
&dctx->mdctx);
if (result == DNS_R_CONTINUE)
return;
if (result == ISC_R_NOTIMPLEMENTED)
fprintf(dctx->fp, "; %s\n",
dns_result_totext(result));
if (result != ISC_R_SUCCESS)
goto cleanup;
}
}
if (dctx->view != NULL)
dctx->view = ISC_LIST_NEXT(dctx->view, link);
if (dctx->view != NULL)
goto nextview;
done:
fprintf(dctx->fp, "; Dump complete\n");
result = isc_stdio_flush(dctx->fp);
if (result == ISC_R_SUCCESS)
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_SERVER, ISC_LOG_INFO,
"dumpdb complete");
cleanup:
if (result != ISC_R_SUCCESS)
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_SERVER, ISC_LOG_INFO,
"dumpdb failed: %s", dns_result_totext(result));
dumpcontext_destroy(dctx);
}
isc_result_t
ns_server_dumpdb(ns_server_t *server, char *args) {
FILE *fp = NULL;
struct dumpcontext *dctx = NULL;
dns_view_t *view;
isc_result_t result;
isc_boolean_t zones = ISC_FALSE;
isc_boolean_t cache = ISC_TRUE;
char *ptr;
const char *sep;
CHECKMF(isc_stdio_open(server->dumpfile, "w", &fp),
dctx = isc_mem_get(server->mctx, sizeof(*dctx));
if (dctx == NULL)
return (ISC_R_NOMEMORY);
dctx->mctx = server->mctx;
dctx->dumpcache = ISC_TRUE;
dctx->dumpzones = ISC_FALSE;
dctx->fp = NULL;
ISC_LIST_INIT(dctx->viewlist);
dctx->view = NULL;
dctx->zone = NULL;
dctx->cache = NULL;
dctx->mdctx = NULL;
dctx->db = NULL;
dctx->cache = NULL;
dctx->task = NULL;
dctx->version = NULL;
isc_task_attach(server->task, &dctx->task);
CHECKMF(isc_stdio_open(server->dumpfile, "w", &dctx->fp),
"could not open dump file", server->dumpfile);
/* Skip the command name. */
@@ -3558,16 +3759,16 @@ ns_server_dumpdb(ns_server_t *server, char *args) {
ptr = next_token(&args, " \t");
if (ptr != NULL && strcmp(ptr, "-all") == 0) {
zones = ISC_TRUE;
cache = ISC_TRUE;
dctx->dumpzones = ISC_TRUE;
dctx->dumpcache = ISC_TRUE;
ptr = next_token(&args, " \t");
} else if (ptr != NULL && strcmp(ptr, "-cache") == 0) {
zones = ISC_FALSE;
cache = ISC_TRUE;
dctx->dumpzones = ISC_FALSE;
dctx->dumpcache = ISC_TRUE;
ptr = next_token(&args, " \t");
} else if (ptr != NULL && strcmp(ptr, "-zones") == 0) {
zones = ISC_TRUE;
cache = ISC_FALSE;
dctx->dumpzones = ISC_TRUE;
dctx->dumpcache = ISC_FALSE;
ptr = next_token(&args, " \t");
}
@@ -3577,23 +3778,14 @@ ns_server_dumpdb(ns_server_t *server, char *args) {
{
if (ptr != NULL && strcmp(view->name, ptr) != 0)
continue;
fprintf(fp, ";\n; Start view %s\n;\n", view->name);
if (cache && view->cachedb != NULL)
CHECKM(dns_view_dumpdbtostream(view, fp),
"could not dump cache");
if (zones && view->zonetable != NULL)
CHECKM(dns_zt_apply(view->zonetable, ISC_TRUE,
printzone, fp),
"could not dump zones");
CHECK(add_view_tolist(dctx, view));
}
fprintf(fp, "; Dump complete\n");
result = isc_stdio_flush(fp);
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_SERVER, ISC_LOG_INFO,
"dumpdb complete");
dumpdone(dctx, ISC_R_SUCCESS);
return (ISC_R_SUCCESS);
cleanup:
if (fp != NULL)
(void)isc_stdio_close(fp);
if (dctx != NULL)
dumpcontext_destroy(dctx);
return (result);
}