2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-29 13:38:26 +00:00

[master] rndc showzone / rndc delzone of non-added zones

4030.	[func]		"rndc delzone" is now applicable to zones that were
			configured in named.conf, as well as zones that
			were added via "rndc addzone". (Note, however, that
			if named.conf is not also modified, the deleted zone
			will return when named is reloaded.) [RT #37887]

4029.	[func]		"rndc showzone" displays the current configuration
			of a specified zone. [RT #37887]
This commit is contained in:
Evan Hunt 2015-01-06 22:57:57 -08:00
parent 651c5a50f4
commit 74eb2f5cbc
13 changed files with 622 additions and 317 deletions

View File

@ -1,3 +1,12 @@
4030. [func] "rndc delzone" is now applicable to zones that were
configured in named.conf, as well as zones that
were added via "rndc addzone". (Note, however, that
if named.conf is not also modified, the deleted zone
will return when named is reloaded.) [RT #37887]
4029. [func] "rndc showzone" displays the current configuration
of a specified zone. [RT #37887]
4028. [bug] $GENERATE with a zero step was not being caught as a 4028. [bug] $GENERATE with a zero step was not being caught as a
error. A $GENERATE with a / but no step was not being error. A $GENERATE with a / but no step was not being
caught as a error. [RT #38262] caught as a error. [RT #38262]

View File

@ -206,9 +206,11 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t **text) {
command_compare(command, NS_COMMAND_LOADKEYS)) { command_compare(command, NS_COMMAND_LOADKEYS)) {
result = ns_server_rekey(ns_g_server, command, text); result = ns_server_rekey(ns_g_server, command, text);
} else if (command_compare(command, NS_COMMAND_ADDZONE)) { } else if (command_compare(command, NS_COMMAND_ADDZONE)) {
result = ns_server_add_zone(ns_g_server, command, text); result = ns_server_addzone(ns_g_server, command, text);
} else if (command_compare(command, NS_COMMAND_DELZONE)) { } else if (command_compare(command, NS_COMMAND_DELZONE)) {
result = ns_server_del_zone(ns_g_server, command, text); result = ns_server_delzone(ns_g_server, command, text);
} else if (command_compare(command, NS_COMMAND_SHOWZONE)) {
result = ns_server_showzone(ns_g_server, command, text);
} else if (command_compare(command, NS_COMMAND_SIGNING)) { } else if (command_compare(command, NS_COMMAND_SIGNING)) {
result = ns_server_signing(ns_g_server, command, text); result = ns_server_signing(ns_g_server, command, text);
} else if (command_compare(command, NS_COMMAND_ZONESTATUS)) { } else if (command_compare(command, NS_COMMAND_ZONESTATUS)) {

View File

@ -63,6 +63,7 @@
#define NS_COMMAND_SIGN "sign" #define NS_COMMAND_SIGN "sign"
#define NS_COMMAND_LOADKEYS "loadkeys" #define NS_COMMAND_LOADKEYS "loadkeys"
#define NS_COMMAND_ADDZONE "addzone" #define NS_COMMAND_ADDZONE "addzone"
#define NS_COMMAND_SHOWZONE "showzone"
#define NS_COMMAND_DELZONE "delzone" #define NS_COMMAND_DELZONE "delzone"
#define NS_COMMAND_SYNC "sync" #define NS_COMMAND_SYNC "sync"
#define NS_COMMAND_SIGNING "signing" #define NS_COMMAND_SIGNING "signing"

View File

@ -67,6 +67,7 @@ EXTERN unsigned int ns_g_cpus_detected INIT(1);
EXTERN isc_timermgr_t * ns_g_timermgr INIT(NULL); EXTERN isc_timermgr_t * ns_g_timermgr INIT(NULL);
EXTERN isc_socketmgr_t * ns_g_socketmgr INIT(NULL); EXTERN isc_socketmgr_t * ns_g_socketmgr INIT(NULL);
EXTERN cfg_parser_t * ns_g_parser INIT(NULL); EXTERN cfg_parser_t * ns_g_parser INIT(NULL);
EXTERN cfg_parser_t * ns_g_addparser INIT(NULL);
EXTERN const char * ns_g_version INIT(VERSION); EXTERN const char * ns_g_version INIT(VERSION);
EXTERN const char * ns_g_product INIT(PRODUCT); EXTERN const char * ns_g_product INIT(PRODUCT);
EXTERN const char * ns_g_description INIT(DESCRIPTION); EXTERN const char * ns_g_description INIT(DESCRIPTION);

View File

@ -373,13 +373,19 @@ ns_server_validation(ns_server_t *server, char *args, isc_buffer_t **text);
* Add a zone to a running process * Add a zone to a running process
*/ */
isc_result_t isc_result_t
ns_server_add_zone(ns_server_t *server, char *args, isc_buffer_t **text); ns_server_addzone(ns_server_t *server, char *args, isc_buffer_t **text);
/*% /*%
* Deletes a zone from a running process * Deletes a zone from a running process
*/ */
isc_result_t isc_result_t
ns_server_del_zone(ns_server_t *server, char *args, isc_buffer_t **text); ns_server_delzone(ns_server_t *server, char *args, isc_buffer_t **text);
/*%
* Show current configuration for a given zone
*/
isc_result_t
ns_server_showzone(ns_server_t *server, char *args, isc_buffer_t **text);
/*% /*%
* Lists the status of the signing records for a given zone. * Lists the status of the signing records for a given zone.

View File

@ -247,9 +247,10 @@ struct zonelistentry {
*/ */
struct cfg_context { struct cfg_context {
isc_mem_t * mctx; isc_mem_t * mctx;
cfg_parser_t * parser; cfg_parser_t * conf_parser;
cfg_parser_t * add_parser;
cfg_obj_t * config; cfg_obj_t * config;
cfg_parser_t * nzparser; cfg_obj_t * vconfig;
cfg_obj_t * nzconfig; cfg_obj_t * nzconfig;
cfg_aclconfctx_t * actx; cfg_aclconfctx_t * actx;
}; };
@ -5307,13 +5308,11 @@ configure_session_key(const cfg_obj_t **maps, ns_server_t *server,
static isc_result_t static isc_result_t
setup_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, setup_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
cfg_parser_t *parser, cfg_aclconfctx_t *actx) cfg_parser_t *conf_parser, cfg_aclconfctx_t *actx)
{ {
isc_result_t result = ISC_R_SUCCESS; isc_result_t result = ISC_R_SUCCESS;
isc_boolean_t allow = ISC_FALSE; isc_boolean_t allow = ISC_FALSE;
struct cfg_context *nzcfg = NULL; struct cfg_context *nzcfg = NULL;
cfg_parser_t *nzparser = NULL;
cfg_obj_t *nzconfig = NULL;
const cfg_obj_t *maps[4]; const cfg_obj_t *maps[4];
const cfg_obj_t *options = NULL, *voptions = NULL; const cfg_obj_t *options = NULL, *voptions = NULL;
const cfg_obj_t *nz = NULL; const cfg_obj_t *nz = NULL;
@ -5346,33 +5345,31 @@ setup_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
return (ISC_R_NOMEMORY); return (ISC_R_NOMEMORY);
} }
memset(nzcfg, 0, sizeof(*nzcfg));
dns_view_setnewzones(view, allow, nzcfg, newzone_cfgctx_destroy); dns_view_setnewzones(view, allow, nzcfg, newzone_cfgctx_destroy);
memset(nzcfg, 0, sizeof(*nzcfg));
isc_mem_attach(view->mctx, &nzcfg->mctx);
cfg_obj_attach(config, &nzcfg->config); cfg_obj_attach(config, &nzcfg->config);
cfg_parser_attach(parser, &nzcfg->parser); if (vconfig != NULL)
cfg_obj_attach(vconfig, &nzcfg->vconfig);
/*
* We attach the parser that was used for config as well
* as the one that wil be used for added zones, to avoid
* a shutdown race later.
*/
cfg_parser_attach(conf_parser, &nzcfg->conf_parser);
cfg_parser_attach(ns_g_addparser, &nzcfg->add_parser);
isc_mem_attach(view->mctx, &nzcfg->mctx);
cfg_aclconfctx_attach(actx, &nzcfg->actx); cfg_aclconfctx_attach(actx, &nzcfg->actx);
/* /*
* Attempt to create a parser and parse the newzones * This may be called in multiple views, so we reset
* file. If successful, preserve both; otherwise leave * the parser each time.
* them NULL.
*/ */
result = cfg_parser_create(view->mctx, ns_g_lctx, &nzparser); cfg_parser_reset(ns_g_addparser);
if (result == ISC_R_SUCCESS) result = cfg_parse_file(ns_g_addparser, view->new_zone_file,
result = cfg_parse_file(nzparser, view->new_zone_file, &cfg_type_newzones, &nzcfg->nzconfig);
&cfg_type_newzones, &nzconfig);
if (result == ISC_R_SUCCESS) {
cfg_parser_attach(nzparser, &nzcfg->nzparser);
cfg_obj_attach(nzconfig, &nzcfg->nzconfig);
}
if (nzparser != NULL) {
if (nzconfig != NULL)
cfg_obj_destroy(nzparser, &nzconfig);
cfg_parser_destroy(&nzparser);
}
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
} }
@ -5948,9 +5945,9 @@ load_configuration(const char *filename, ns_server_t *server,
INSIST(view != NULL); INSIST(view != NULL);
num_zones += count_zones(voptions); num_zones += count_zones(voptions);
CHECK(setup_newzones(view, config, vconfig, conf_parser, CHECK(setup_newzones(view, config, vconfig, conf_parser,
ns_g_aclconfctx)); ns_g_aclconfctx));
nzctx = view->new_zone_config; nzctx = view->new_zone_config;
if (nzctx != NULL && nzctx->nzconfig != NULL) if (nzctx != NULL && nzctx->nzconfig != NULL)
num_zones += count_zones(nzctx->nzconfig); num_zones += count_zones(nzctx->nzconfig);
@ -5968,7 +5965,7 @@ load_configuration(const char *filename, ns_server_t *server,
num_zones = count_zones(config); num_zones = count_zones(config);
CHECK(setup_newzones(view, config, NULL, conf_parser, CHECK(setup_newzones(view, config, NULL, conf_parser,
ns_g_aclconfctx)); ns_g_aclconfctx));
nzctx = view->new_zone_config; nzctx = view->new_zone_config;
@ -6614,6 +6611,9 @@ run_server(isc_task_t *task, isc_event_t *event) {
CHECKFATAL(cfg_parser_create(ns_g_mctx, NULL, &ns_g_parser), CHECKFATAL(cfg_parser_create(ns_g_mctx, NULL, &ns_g_parser),
"creating default configuration parser"); "creating default configuration parser");
CHECKFATAL(cfg_parser_create(ns_g_mctx, NULL, &ns_g_addparser),
"creating additional configuration parser");
if (ns_g_lwresdonly) if (ns_g_lwresdonly)
CHECKFATAL(load_configuration(lwresd_g_conffile, server, CHECKFATAL(load_configuration(lwresd_g_conffile, server,
ISC_TRUE), ISC_TRUE),
@ -6663,6 +6663,7 @@ shutdown_server(isc_task_t *task, isc_event_t *event) {
cfg_obj_destroy(ns_g_parser, &ns_g_config); cfg_obj_destroy(ns_g_parser, &ns_g_config);
cfg_parser_destroy(&ns_g_parser); cfg_parser_destroy(&ns_g_parser);
cfg_parser_destroy(&ns_g_addparser);
for (view = ISC_LIST_HEAD(server->viewlist); for (view = ISC_LIST_HEAD(server->viewlist);
view != NULL; view != NULL;
@ -8948,40 +8949,45 @@ add_comment(FILE *fp, const char *viewname) {
* Act on an "addzone" command from the command channel. * Act on an "addzone" command from the command channel.
*/ */
isc_result_t isc_result_t
ns_server_add_zone(ns_server_t *server, char *args, isc_buffer_t **text) { ns_server_addzone(ns_server_t *server, char *args, isc_buffer_t **text) {
isc_result_t result, tresult; isc_result_t result, tresult;
isc_buffer_t argbuf; isc_buffer_t argbuf;
size_t arglen; size_t arglen;
cfg_parser_t *parser = NULL; cfg_obj_t *config = NULL;
cfg_obj_t *config = NULL; const cfg_obj_t *zlist = NULL;
const cfg_obj_t *vconfig = NULL; const cfg_obj_t *parms = NULL;
const cfg_obj_t *views = NULL; const cfg_obj_t *obj = NULL;
const cfg_obj_t *parms = NULL; const char *zonename;
const cfg_obj_t *obj = NULL; const char *classname = NULL;
const cfg_listelt_t *element; const char *argp;
const char *zonename; const char *viewname = NULL;
const char *classname = NULL; dns_rdataclass_t rdclass;
const char *argp; dns_view_t *view = NULL;
const char *viewname = NULL; isc_buffer_t buf;
dns_rdataclass_t rdclass; dns_fixedname_t fname;
dns_view_t *view = NULL; dns_name_t *dnsname;
isc_buffer_t buf; dns_zone_t *zone = NULL;
dns_fixedname_t fname; FILE *fp = NULL;
dns_name_t *dnsname; struct cfg_context *cfg = NULL;
dns_zone_t *zone = NULL; char namebuf[DNS_NAME_FORMATSIZE];
FILE *fp = NULL; off_t offset;
struct cfg_context *cfg = NULL;
char namebuf[DNS_NAME_FORMATSIZE];
off_t offset;
/* Try to parse the argument string */ /* Try to parse the argument string */
arglen = strlen(args); arglen = strlen(args);
isc_buffer_init(&argbuf, args, (unsigned int)arglen); isc_buffer_init(&argbuf, args, (unsigned int)arglen);
isc_buffer_add(&argbuf, strlen(args)); isc_buffer_add(&argbuf, strlen(args));
CHECK(cfg_parser_create(server->mctx, ns_g_lctx, &parser));
CHECK(cfg_parse_buffer(parser, &argbuf, &cfg_type_addzoneconf, /* convert "addzone" to "zone", for the parser's benefit */
&config)); isc_buffer_forward(&argbuf, 3);
CHECK(cfg_map_get(config, "addzone", &parms));
cfg_parser_reset(ns_g_addparser);
CHECK(cfg_parse_buffer(ns_g_addparser, &argbuf,
&cfg_type_addzoneconf, &config));
CHECK(cfg_map_get(config, "zone", &zlist));
if (! cfg_obj_islist(zlist))
CHECK(ISC_R_FAILURE);
parms = cfg_listelt_value(cfg_list_first(zlist));
zonename = cfg_obj_asstring(cfg_tuple_get(parms, "name")); zonename = cfg_obj_asstring(cfg_tuple_get(parms, "name"));
isc_buffer_constinit(&buf, zonename, strlen(zonename)); isc_buffer_constinit(&buf, zonename, strlen(zonename));
@ -9026,24 +9032,9 @@ ns_server_add_zone(ns_server_t *server, char *args, isc_buffer_t **text) {
/* Create our sub-zone anyway */ /* Create our sub-zone anyway */
dns_zone_detach(&zone); dns_zone_detach(&zone);
zone = NULL; zone = NULL;
} } else if (result != ISC_R_NOTFOUND)
else if (result != ISC_R_NOTFOUND)
goto cleanup; goto cleanup;
/* Find the view statement */
cfg_map_get(cfg->config, "view", &views);
for (element = cfg_list_first(views);
element != NULL;
element = cfg_list_next(element))
{
const char *vname;
vconfig = cfg_listelt_value(element);
vname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name"));
if (vname && !strcasecmp(vname, viewname))
break;
vconfig = NULL;
}
/* Open save file for write configuration */ /* Open save file for write configuration */
result = isc_stdio_open(view->new_zone_file, "a", &fp); result = isc_stdio_open(view->new_zone_file, "a", &fp);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
@ -9061,7 +9052,7 @@ ns_server_add_zone(ns_server_t *server, char *args, isc_buffer_t **text) {
result = isc_task_beginexclusive(server->task); result = isc_task_beginexclusive(server->task);
RUNTIME_CHECK(result == ISC_R_SUCCESS); RUNTIME_CHECK(result == ISC_R_SUCCESS);
dns_view_thaw(view); dns_view_thaw(view);
result = configure_zone(cfg->config, parms, vconfig, result = configure_zone(cfg->config, parms, cfg->vconfig,
server->mctx, view, NULL, cfg->actx, server->mctx, view, NULL, cfg->actx,
ISC_FALSE, ISC_FALSE); ISC_FALSE, ISC_FALSE);
dns_view_freeze(view); dns_view_freeze(view);
@ -9075,6 +9066,19 @@ ns_server_add_zone(ns_server_t *server, char *args, isc_buffer_t **text) {
/* Is it there yet? */ /* Is it there yet? */
CHECK(dns_zt_find(view->zonetable, dnsname, 0, NULL, &zone)); CHECK(dns_zt_find(view->zonetable, dnsname, 0, NULL, &zone));
/*
* If there wasn't a previous newzone config, just save the one
* we've created. If there was a previous one, merge the new
* zone into it.
*/
if (cfg->nzconfig == NULL)
cfg_obj_attach(config, &cfg->nzconfig);
else {
cfg_obj_t *p;
DE_CONST(parms, p);
cfg_parser_mapadd(cfg->add_parser, cfg->nzconfig, p, "zone");
}
/* /*
* Load the zone from the master file. If this fails, we'll * Load the zone from the master file. If this fails, we'll
* need to undo the configuration we've done already. * need to undo the configuration we've done already.
@ -9148,13 +9152,10 @@ ns_server_add_zone(ns_server_t *server, char *args, isc_buffer_t **text) {
cleanup: cleanup:
if (isc_buffer_usedlength(*text) > 0) if (isc_buffer_usedlength(*text) > 0)
(void) putnull(text); (void) putnull(text);
if (config != NULL)
cfg_obj_destroy(ns_g_addparser, &config);
if (fp != NULL) if (fp != NULL)
isc_stdio_close(fp); isc_stdio_close(fp);
if (parser != NULL) {
if (config != NULL)
cfg_obj_destroy(parser, &config);
cfg_parser_destroy(&parser);
}
if (zone != NULL) if (zone != NULL)
dns_zone_detach(&zone); dns_zone_detach(&zone);
if (view != NULL) if (view != NULL)
@ -9165,11 +9166,11 @@ ns_server_add_zone(ns_server_t *server, char *args, isc_buffer_t **text) {
static isc_boolean_t static isc_boolean_t
inuse(const char* file, isc_boolean_t first, isc_buffer_t **text) { inuse(const char* file, isc_boolean_t first, isc_buffer_t **text) {
#define INUSEMSG "The following files were in use and may now be removed:\n"
if (file != NULL && isc_file_exists(file)) { if (file != NULL && isc_file_exists(file)) {
if (first) if (first)
(void) putstr(text, INUSEMSG); (void) putstr(text,
"The following files were in use "
"and may now be removed:\n");
else else
(void) putstr(text, "\n"); (void) putstr(text, "\n");
(void) putstr(text, file); (void) putstr(text, file);
@ -9179,84 +9180,26 @@ inuse(const char* file, isc_boolean_t first, isc_buffer_t **text) {
return (first); return (first);
} }
/* static isc_result_t
* Act on a "delzone" command from the command channel. nzf_remove(const char *nzfile, const char *viewname, const char *zonename) {
*/ size_t znamelen;
isc_result_t
ns_server_del_zone(ns_server_t *server, char *args, isc_buffer_t **text) {
isc_result_t result; isc_result_t result;
dns_zone_t *zone = NULL;
dns_zone_t *raw = NULL;
dns_zone_t *mayberaw;
dns_view_t *view = NULL;
dns_db_t *dbp = NULL;
const char *filename = NULL;
char *tmpname = NULL;
char buf[1024];
const char *zonename = NULL;
size_t znamelen = 0;
FILE *ifp = NULL, *ofp = NULL; FILE *ifp = NULL, *ofp = NULL;
isc_boolean_t exclusive = ISC_FALSE; char tmp[1024], buf[1024];
isc_boolean_t cleanup = ISC_FALSE;
isc_boolean_t inheader = ISC_TRUE; isc_boolean_t inheader = ISC_TRUE;
const char *file, *arg;
/* Parse parameters */
(void) next_token(&args, " \t");
arg = next_token(&args, " \t");
if (arg != NULL &&
(strcmp(arg, "-clean") == 0 || strcmp(arg, "-clear") == 0)) {
cleanup = ISC_TRUE;
arg = next_token(&args, " \t");
}
CHECK(zone_from_args(server, args, arg, &zone, &zonename,
text, ISC_FALSE));
if (zone == NULL) {
result = ISC_R_UNEXPECTEDEND;
goto cleanup;
}
result = isc_task_beginexclusive(server->task);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
exclusive = ISC_TRUE;
/*
* Was this zone originally added at runtime?
* If not, we can't delete it now.
*/
if (!dns_zone_getadded(zone)) {
result = ISC_R_NOPERM;
goto cleanup;
}
INSIST(zonename != NULL);
znamelen = strlen(zonename); znamelen = strlen(zonename);
/* Dig out configuration for this zone */
view = dns_zone_getview(zone);
filename = view->new_zone_file;
if (filename == NULL) {
/* No adding zones in this view */
result = ISC_R_FAILURE;
goto cleanup;
}
/* Rewrite zone list */ /* Rewrite zone list */
result = isc_stdio_open(filename, "r", &ifp); result = isc_stdio_open(nzfile, "r", &ifp);
if (ifp != NULL && result == ISC_R_SUCCESS) { if (ifp != NULL && result == ISC_R_SUCCESS) {
char *found = NULL, *p = NULL; char *found = NULL, *p = NULL;
size_t n; size_t n;
/* Create a temporary file */ /* Create a temporary file */
CHECK(isc_string_printf(buf, 1023, "%s.%ld", filename, CHECK(isc_file_template("", "nzf-XXXXXXXX", tmp, sizeof(tmp)));
(long)getpid())); CHECK(isc_stdio_open(tmp, "w", &ofp));
if (!(tmpname = isc_mem_strdup(server->mctx, buf))) { CHECK(add_comment(ofp, viewname));
result = ISC_R_NOMEMORY;
goto cleanup;
}
CHECK(isc_stdio_open(tmpname, "w", &ofp));
CHECK(add_comment(ofp, view->name));
/* Look for the entry for that zone */ /* Look for the entry for that zone */
while (fgets(buf, 1024, ifp)) { while (fgets(buf, 1024, ifp)) {
@ -9302,20 +9245,20 @@ ns_server_del_zone(ns_server_t *server, char *args, isc_buffer_t **text) {
break; break;
} }
/* Copy the rest of the buffer out and continue */ /* Copy the buffer out and continue */
fputs(buf, ofp); fputs(buf, ofp);
} }
/* Skip over an option block (matching # of braces) */ /* Skip over an option block (matching # of braces) */
if (found) { if (found) {
int obrace = 0, cbrace = 0; int openbrace = 0, closebrace = 0;
for (;;) { for (;;) {
while (*p) { while (*p) {
if (*p == '{') obrace++; if (*p == '{') openbrace++;
if (*p == '}') cbrace++; else if (*p == '}') closebrace++;
p++; p++;
} }
if (obrace && (obrace == cbrace)) if (openbrace && (openbrace == closebrace))
break; break;
if (!fgets(buf, 1024, ifp)) if (!fgets(buf, 1024, ifp))
break; break;
@ -9333,7 +9276,7 @@ ns_server_del_zone(ns_server_t *server, char *args, isc_buffer_t **text) {
} }
/* Move temporary into place */ /* Move temporary into place */
CHECK(isc_file_rename(tmpname, view->new_zone_file)); CHECK(isc_file_rename(tmp, nzfile));
} else { } else {
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_SERVER, ISC_LOG_WARNING, NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
@ -9343,44 +9286,111 @@ ns_server_del_zone(ns_server_t *server, char *args, isc_buffer_t **text) {
} }
} }
cleanup:
if (ifp != NULL)
isc_stdio_close(ifp);
if (ofp != NULL)
isc_stdio_close(ofp);
return (result);
}
/*
* Act on a "delzone" command from the command channel.
*/
isc_result_t
ns_server_delzone(ns_server_t *server, char *args, isc_buffer_t **text) {
isc_result_t result, tresult;
dns_zone_t *zone = NULL;
dns_zone_t *raw = NULL;
dns_zone_t *mayberaw;
dns_view_t *view = NULL;
dns_db_t *dbp = NULL;
const char *zonename = NULL;
isc_boolean_t exclusive = ISC_FALSE;
isc_boolean_t cleanup = ISC_FALSE;
const char *file, *arg;
isc_boolean_t added;
/* Skip the command name. */
arg = next_token(&args, " \t");
if (arg == NULL)
return (ISC_R_UNEXPECTEDEND);
/* Find out what we are to do. */
arg = next_token(&args, " \t");
if (arg == NULL)
return (ISC_R_UNEXPECTEDEND);
if (strcmp(arg, "-clean") == 0 || strcmp(arg, "-clear") == 0) {
cleanup = ISC_TRUE;
arg = next_token(&args, " \t");
}
CHECK(zone_from_args(server, args, arg, &zone, &zonename,
text, ISC_FALSE));
if (zone == NULL) {
result = ISC_R_UNEXPECTEDEND;
goto cleanup;
}
INSIST(zonename != NULL);
result = isc_task_beginexclusive(server->task);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
exclusive = ISC_TRUE;
/* Dig out configuration for this zone */
view = dns_zone_getview(zone);
/* Stop answering for this zone */ /* Stop answering for this zone */
if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) {
dns_db_detach(&dbp); dns_db_detach(&dbp);
dns_zone_unload(zone); dns_zone_unload(zone);
} }
/* Remove the zone from the new_zone_file if applicable */
added = dns_zone_getadded(zone);
if (added && view->new_zone_file != NULL)
CHECK(nzf_remove(view->new_zone_file, view->name, zonename));
/* Clean up stub / slave zone files */ /* Clean up stub / slave zone files */
dns_zone_getraw(zone, &raw); dns_zone_getraw(zone, &raw);
mayberaw = (raw != NULL) ? raw : zone; mayberaw = (raw != NULL) ? raw : zone;
if (cleanup) {
isc_result_t tresult;
if (!added) {
TCHECK(putstr(text, "zone '"));
TCHECK(putstr(text, zonename));
TCHECK(putstr(text, "' is no longer loaded.\n"));
TCHECK(putstr(text, "To keep it from returning "));
TCHECK(putstr(text, "when the server is restarted, it\n"));
TCHECK(putstr(text, "must also be removed from named.conf."));
} else if (cleanup) {
file = dns_zone_getfile(mayberaw); file = dns_zone_getfile(mayberaw);
if (isc_file_exists(file)) isc_file_remove(file);
isc_file_remove(file);
file = dns_zone_getjournal(mayberaw); file = dns_zone_getjournal(mayberaw);
if (isc_file_exists(file)) isc_file_remove(file);
isc_file_remove(file);
if (zone != mayberaw) { if (zone != mayberaw) {
file = dns_zone_getfile(zone); file = dns_zone_getfile(zone);
if (isc_file_exists(file)) isc_file_remove(file);
isc_file_remove(file);
file = dns_zone_getjournal(zone); file = dns_zone_getjournal(zone);
if (isc_file_exists(file)) isc_file_remove(file);
isc_file_remove(file);
} }
TCHECK(putstr(text, "zone ")); TCHECK(putstr(text, "zone '"));
TCHECK(putstr(text, zonename)); TCHECK(putstr(text, zonename));
TCHECK(putstr(text, " and associated files deleted")); TCHECK(putstr(text, "' and associated files were deleted."));
TCHECK(putnull(text));
} else if (dns_zone_gettype(mayberaw) == dns_zone_slave || } else if (dns_zone_gettype(mayberaw) == dns_zone_slave ||
dns_zone_gettype(mayberaw) == dns_zone_stub) dns_zone_gettype(mayberaw) == dns_zone_stub)
{ {
isc_boolean_t first; isc_boolean_t first;
TCHECK(putstr(text, "zone '"));
TCHECK(putstr(text, zonename));
TCHECK(putstr(text, "' was deleted.\n"));
file = dns_zone_getfile(mayberaw); file = dns_zone_getfile(mayberaw);
first = inuse(file, ISC_TRUE, text); first = inuse(file, ISC_TRUE, text);
@ -9392,9 +9402,8 @@ ns_server_del_zone(ns_server_t *server, char *args, isc_buffer_t **text) {
first = inuse(file, first, text); first = inuse(file, first, text);
file = dns_zone_getjournal(zone); file = dns_zone_getjournal(zone);
(void)inuse(file, first, text); (void) inuse(file, first, text);
} }
(void) putnull(text);
} }
CHECK(dns_zt_unmount(view->zonetable, zone)); CHECK(dns_zt_unmount(view->zonetable, zone));
@ -9411,24 +9420,114 @@ ns_server_del_zone(ns_server_t *server, char *args, isc_buffer_t **text) {
cleanup: cleanup:
if (isc_buffer_usedlength(*text) > 0) if (isc_buffer_usedlength(*text) > 0)
(void) putnull(text); (void) putnull(text);
if (exclusive)
isc_task_endexclusive(server->task);
if (ifp != NULL)
isc_stdio_close(ifp);
if (ofp != NULL) {
isc_stdio_close(ofp);
isc_file_remove(tmpname);
}
if (tmpname != NULL)
isc_mem_free(server->mctx, tmpname);
if (raw != NULL) if (raw != NULL)
dns_zone_detach(&raw); dns_zone_detach(&raw);
if (exclusive)
isc_task_endexclusive(server->task);
if (zone != NULL) if (zone != NULL)
dns_zone_detach(&zone); dns_zone_detach(&zone);
return (result); return (result);
} }
/*
* Act on a "showzone" command from the command channel.
*/
static const cfg_obj_t *
find_name_in_list_from_map(const cfg_obj_t *config,
const char *map_key_for_list,
const char *name)
{
const cfg_obj_t *list = NULL;
const cfg_listelt_t *element;
const cfg_obj_t *result;
cfg_map_get(config, map_key_for_list, &list);
for (element = cfg_list_first(list);
element != NULL;
element = cfg_list_next(element))
{
const char *vname;
result = cfg_listelt_value(element);
INSIST(result != NULL);
vname = cfg_obj_asstring(cfg_tuple_get(result, "name"));
if (vname != NULL && !strcasecmp(vname, name))
break;
result = NULL;
}
return (result);
}
static void
dumpit(void *arg, const char *buf, int len) {
isc_buffer_t **tpp = arg;
putmem(tpp, buf, len);
}
isc_result_t
ns_server_showzone(ns_server_t *server, char *args, isc_buffer_t **text) {
isc_result_t result;
const cfg_obj_t *vconfig = NULL, *zconfig = NULL;
const char *zonename = NULL;
const cfg_obj_t *map;
dns_view_t *view = NULL;
dns_zone_t *zone = NULL;
struct cfg_context *cfg = NULL;
isc_boolean_t exclusive = ISC_FALSE;
/* Parse parameters */
CHECK(zone_from_args(server, args, NULL, &zone, &zonename,
text, ISC_TRUE));
if (zone == NULL) {
result = ISC_R_UNEXPECTEDEND;
goto cleanup;
}
view = dns_zone_getview(zone);
dns_zone_detach(&zone);
cfg = (struct cfg_context *) view->new_zone_config;
if (cfg == NULL) {
result = ISC_R_FAILURE;
goto cleanup;
}
result = isc_task_beginexclusive(server->task);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
exclusive = ISC_TRUE;
/* Find the view statement */
vconfig = find_name_in_list_from_map(cfg->config, "view", view->name);
/* Find the zone statement */
if (vconfig != NULL)
map = cfg_tuple_get(vconfig, "options");
else
map = cfg->config;
zconfig = find_name_in_list_from_map(map, "zone", zonename);
if (zconfig == NULL)
zconfig = find_name_in_list_from_map(cfg->nzconfig,
"zone", zonename);
if (zconfig == NULL)
CHECK(ISC_R_NOTFOUND);
putstr(text, "zone ");
cfg_printx(zconfig, CFG_PRINTER_ONELINE, dumpit, text);
putstr(text, ";");
result = ISC_R_SUCCESS;
cleanup:
if (isc_buffer_usedlength(*text) > 0)
(void) putnull(text);
if (exclusive)
isc_task_endexclusive(server->task);
return (result);
}
static void static void
newzone_cfgctx_destroy(void **cfgp) { newzone_cfgctx_destroy(void **cfgp) {
struct cfg_context *cfg; struct cfg_context *cfg;
@ -9437,20 +9536,22 @@ newzone_cfgctx_destroy(void **cfgp) {
cfg = *cfgp; cfg = *cfgp;
if (cfg->conf_parser != NULL) {
if (cfg->config != NULL)
cfg_obj_destroy(cfg->conf_parser, &cfg->config);
if (cfg->vconfig != NULL)
cfg_obj_destroy(cfg->conf_parser, &cfg->vconfig);
cfg_parser_destroy(&cfg->conf_parser);
}
if (cfg->add_parser != NULL) {
if (cfg->nzconfig != NULL)
cfg_obj_destroy(cfg->add_parser, &cfg->nzconfig);
cfg_parser_destroy(&cfg->add_parser);
}
if (cfg->actx != NULL) if (cfg->actx != NULL)
cfg_aclconfctx_detach(&cfg->actx); cfg_aclconfctx_detach(&cfg->actx);
if (cfg->parser != NULL) {
if (cfg->config != NULL)
cfg_obj_destroy(cfg->parser, &cfg->config);
cfg_parser_destroy(&cfg->parser);
}
if (cfg->nzparser != NULL) {
if (cfg->nzconfig != NULL)
cfg_obj_destroy(cfg->nzparser, &cfg->nzconfig);
cfg_parser_destroy(&cfg->nzparser);
}
isc_mem_putanddetach(&cfg->mctx, cfg, sizeof(*cfg)); isc_mem_putanddetach(&cfg->mctx, cfg, sizeof(*cfg));
*cfgp = NULL; *cfgp = NULL;
} }

View File

@ -730,9 +730,6 @@
<listitem> <listitem>
<para> <para>
Delete a zone while the server is running. Delete a zone while the server is running.
Only zones that were originally added via
<command>rndc addzone</command> can be deleted
in this manner.
</para> </para>
<para> <para>
If the <option>-clean</option> is specified, If the <option>-clean</option> is specified,
@ -744,6 +741,25 @@
be cleaned up will be reported in the output be cleaned up will be reported in the output
of the <command>rndc delzone</command> command.) of the <command>rndc delzone</command> command.)
</para> </para>
<para>
If the zone was originally added via
<command>rndc addzone</command>, then it will be
removed permanently. However, if it was originally
configured in <filename>named.conf</filename>, then
that original configuration is still in place; when
the server is restarted or reconfigured, the zone will
come back. To remove it permanently, it must also be
removed from <filename>named.conf</filename>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><userinput>showzone <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional> </userinput></term>
<listitem>
<para>
Print the configuration of a running zone.
</para>
</listitem> </listitem>
</varlistentry> </varlistentry>

View File

@ -92,6 +92,15 @@ n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret` status=`expr $status + $ret`
echo "I:checking rndc showzone with previously added zone ($n)"
ret=0
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 showzone previous.example > rndc.out.ns2.$n
expected='zone "previous.example" { type master; file "previous.db"; };'
[ "`cat rndc.out.ns2.$n`" = "$expected" ] || ret=1
n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
echo "I:deleting previously added zone ($n)" echo "I:deleting previously added zone ($n)"
ret=0 ret=0
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 delzone previous.example 2>&1 | sed 's/^/I:ns2 /' $RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 delzone previous.example 2>&1 | sed 's/^/I:ns2 /'
@ -130,13 +139,20 @@ n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret` status=`expr $status + $ret`
echo "I:attempt to delete a normally-loaded zone ($n)" echo "I:checking rndc showzone with a normally-loaded zone ($n)"
ret=0
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 showzone normal.example > rndc.out.ns2.$n
expected='zone "normal.example" { type master; file "normal.db"; };'
[ "`cat rndc.out.ns2.$n`" = "$expected" ] || ret=1
n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
echo "I:delete a normally-loaded zone ($n)"
ret=0 ret=0
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 delzone normal.example 2> rndc.out.ns2.$n $RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 delzone normal.example 2> rndc.out.ns2.$n
grep "permission denied" rndc.out.ns2.$n > /dev/null || ret=1
$DIG $DIGOPTS @10.53.0.2 a.normal.example a > dig.out.ns2.$n $DIG $DIGOPTS @10.53.0.2 a.normal.example a > dig.out.ns2.$n
grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1 grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1
grep '^a.normal.example' dig.out.ns2.$n > /dev/null || ret=1
n=`expr $n + 1` n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret` status=`expr $status + $ret`
@ -267,6 +283,14 @@ n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret` status=`expr $status + $ret`
echo "I:checking rndc showzone with newly added zone ($n)"
ret=0
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 showzone added.example in external > rndc.out.ns2.$n
expected='zone "added.example" in external { type master; file "added.db"; };'
[ "`cat rndc.out.ns2.$n`" = "$expected" ] || ret=1
n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
echo "I:deleting newly added zone ($n)" echo "I:deleting newly added zone ($n)"
ret=0 ret=0

View File

@ -5894,8 +5894,7 @@ options {
<listitem> <listitem>
<para> <para>
If <userinput>yes</userinput>, then zones can be If <userinput>yes</userinput>, then zones can be
added at runtime via <command>rndc addzone</command> added at runtime via <command>rndc addzone</command>.
or deleted via <command>rndc delzone</command>.
The default is <userinput>no</userinput>. The default is <userinput>no</userinput>.
</para> </para>
</listitem> </listitem>

View File

@ -251,6 +251,23 @@
line option. line option.
</para> </para>
</listitem> </listitem>
<listitem>
<para>
<command>rndc delzone</command> can now be applied to zones
which were configured in <filename>named.conf</filename>;
it is no longer restricted to zones which were added by
<command>rndc addzone</command>. (Note, however, that
this does not edit <filename>named.conf</filename>; the zone
must be removed from the configuration or it will return
when <command>named</command> is restarted or reloaded.)
</para>
</listitem>
<listitem>
<para>
<command>rndc showzone</command> displays the current
configuration for a specified zone.
</para>
</listitem>
</itemizedlist> </itemizedlist>
</sect2> </sect2>
<sect2 id="relnotes_changes"> <sect2 id="relnotes_changes">

View File

@ -39,7 +39,6 @@
#include <isc/types.h> #include <isc/types.h>
#include <isc/list.h> #include <isc/list.h>
/*** /***
*** Types *** Types
***/ ***/
@ -144,6 +143,26 @@ cfg_parse_buffer(cfg_parser_t *pctx, isc_buffer_t *buffer,
*\li others - file contains errors *\li others - file contains errors
*/ */
isc_result_t
cfg_parser_mapadd(cfg_parser_t *pctx, cfg_obj_t *mapobj,
cfg_obj_t *obj, const char *clause);
/*%<
* Add the object 'obj' to the specified clause in mapbody 'mapobj'.
* Used for adding new zones.
*
* Require:
* \li 'obj' is a valid cfg_obj_t.
* \li 'mapobj' is a valid cfg_obj_t of type map.
* \li 'pctx' is a valid cfg_parser_t.
*/
void
cfg_parser_reset(cfg_parser_t *pctx);
/*%<
* Reset an existing parser so it can be re-used for a new file or
* buffer.
*/
void void
cfg_parser_destroy(cfg_parser_t **pctxp); cfg_parser_destroy(cfg_parser_t **pctxp);
/*%< /*%<
@ -412,6 +431,7 @@ cfg_printx(const cfg_obj_t *obj, unsigned int flags,
void *closure); void *closure);
#define CFG_PRINTER_XKEY 0x1 /* '?' out shared keys. */ #define CFG_PRINTER_XKEY 0x1 /* '?' out shared keys. */
#define CFG_PRINTER_ONELINE 0x2 /* print config as a single line */
/*%< /*%<
* Print the configuration object 'obj' by repeatedly calling the * Print the configuration object 'obj' by repeatedly calling the
@ -475,7 +495,6 @@ cfg_obj_line(const cfg_obj_t *obj);
* Return the line in file where this object was defined. * Return the line in file where this object was defined.
*/ */
ISC_LANG_ENDDECLS ISC_LANG_ENDDECLS
#endif /* ISCCFG_CFG_H */ #endif /* ISCCFG_CFG_H */

View File

@ -304,9 +304,9 @@ parse_matchname(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
static void static void
doc_matchname(cfg_printer_t *pctx, const cfg_type_t *type) { doc_matchname(cfg_printer_t *pctx, const cfg_type_t *type) {
cfg_print_chars(pctx, "[ ", 2); cfg_print_cstr(pctx, "[ ");
cfg_doc_obj(pctx, type->of); cfg_doc_obj(pctx, type->of);
cfg_print_chars(pctx, " ]", 2); cfg_print_cstr(pctx, " ]");
} }
static const char *matchtype_enums[] = { static const char *matchtype_enums[] = {
@ -739,11 +739,11 @@ parse_boolorauto(cfg_parser_t *pctx, const cfg_type_t *type,
static void static void
print_boolorauto(cfg_printer_t *pctx, const cfg_obj_t *obj) { print_boolorauto(cfg_printer_t *pctx, const cfg_obj_t *obj) {
if (obj->type->rep == &cfg_rep_void) if (obj->type->rep == &cfg_rep_void)
cfg_print_chars(pctx, "auto", 4); cfg_print_cstr(pctx, "auto");
else if (obj->value.boolean) else if (obj->value.boolean)
cfg_print_chars(pctx, "yes", 3); cfg_print_cstr(pctx, "yes");
else else
cfg_print_chars(pctx, "no", 2); cfg_print_cstr(pctx, "no");
} }
static void static void
@ -1117,18 +1117,18 @@ doc_rpz_policy(cfg_printer_t *pctx, const cfg_type_t *type) {
/* /*
* This is cfg_doc_enum() without the trailing " )". * This is cfg_doc_enum() without the trailing " )".
*/ */
cfg_print_chars(pctx, "( ", 2); cfg_print_cstr(pctx, "( ");
for (p = type->of; *p != NULL; p++) { for (p = type->of; *p != NULL; p++) {
cfg_print_cstr(pctx, *p); cfg_print_cstr(pctx, *p);
if (p[1] != NULL) if (p[1] != NULL)
cfg_print_chars(pctx, " | ", 3); cfg_print_cstr(pctx, " | ");
} }
} }
static void static void
doc_rpz_cname(cfg_printer_t *pctx, const cfg_type_t *type) { doc_rpz_cname(cfg_printer_t *pctx, const cfg_type_t *type) {
cfg_doc_terminal(pctx, type); cfg_doc_terminal(pctx, type);
cfg_print_chars(pctx, " )", 2); cfg_print_cstr(pctx, " )");
} }
/* /*
@ -1232,9 +1232,9 @@ cfg_print_kv_tuple(cfg_printer_t *pctx, const cfg_obj_t *obj) {
if (fieldobj->type->print == cfg_print_void) if (fieldobj->type->print == cfg_print_void)
continue; continue;
if (i != 0) { if (i != 0) {
cfg_print_chars(pctx, " ", 1); cfg_print_cstr(pctx, " ");
cfg_print_cstr(pctx, f->name); cfg_print_cstr(pctx, f->name);
cfg_print_chars(pctx, " ", 1); cfg_print_cstr(pctx, " ");
} }
cfg_print_obj(pctx, fieldobj); cfg_print_obj(pctx, fieldobj);
} }
@ -1247,14 +1247,14 @@ cfg_doc_kv_tuple(cfg_printer_t *pctx, const cfg_type_t *type) {
fields = type->of; fields = type->of;
for (f = fields; f->name != NULL; f++) { for (f = fields; f->name != NULL; f++) {
if (f != fields) { if (f != fields) {
cfg_print_chars(pctx, " [ ", 3); cfg_print_cstr(pctx, " [ ");
cfg_print_cstr(pctx, f->name); cfg_print_cstr(pctx, f->name);
if (f->type->doc != cfg_doc_void) if (f->type->doc != cfg_doc_void)
cfg_print_chars(pctx, " ", 1); cfg_print_cstr(pctx, " ");
} }
cfg_doc_obj(pctx, f->type); cfg_doc_obj(pctx, f->type);
if (f != fields) if (f != fields)
cfg_print_chars(pctx, " ]", 2); cfg_print_cstr(pctx, " ]");
} }
} }
@ -1931,11 +1931,11 @@ static cfg_tuplefielddef_t addzone_fields[] = {
{ NULL, NULL, 0 } { NULL, NULL, 0 }
}; };
static cfg_type_t cfg_type_addzone = { static cfg_type_t cfg_type_addzone = {
"addzone", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple, addzone_fields }; "zone", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple, addzone_fields };
static cfg_clausedef_t static cfg_clausedef_t
addzoneconf_clauses[] = { addzoneconf_clauses[] = {
{ "addzone", &cfg_type_addzone, 0 }, { "zone", &cfg_type_addzone, CFG_CLAUSEFLAG_MULTI },
{ NULL, NULL, 0 } { NULL, NULL, 0 }
}; };
@ -2119,7 +2119,7 @@ static void
print_keyvalue(cfg_printer_t *pctx, const cfg_obj_t *obj) { print_keyvalue(cfg_printer_t *pctx, const cfg_obj_t *obj) {
const keyword_type_t *kw = obj->type->of; const keyword_type_t *kw = obj->type->of;
cfg_print_cstr(pctx, kw->name); cfg_print_cstr(pctx, kw->name);
cfg_print_chars(pctx, " ", 1); cfg_print_cstr(pctx, " ");
kw->type->print(pctx, obj); kw->type->print(pctx, obj);
} }
@ -2127,18 +2127,18 @@ static void
doc_keyvalue(cfg_printer_t *pctx, const cfg_type_t *type) { doc_keyvalue(cfg_printer_t *pctx, const cfg_type_t *type) {
const keyword_type_t *kw = type->of; const keyword_type_t *kw = type->of;
cfg_print_cstr(pctx, kw->name); cfg_print_cstr(pctx, kw->name);
cfg_print_chars(pctx, " ", 1); cfg_print_cstr(pctx, " ");
cfg_doc_obj(pctx, kw->type); cfg_doc_obj(pctx, kw->type);
} }
static void static void
doc_optional_keyvalue(cfg_printer_t *pctx, const cfg_type_t *type) { doc_optional_keyvalue(cfg_printer_t *pctx, const cfg_type_t *type) {
const keyword_type_t *kw = type->of; const keyword_type_t *kw = type->of;
cfg_print_chars(pctx, "[ ", 2); cfg_print_cstr(pctx, "[ ");
cfg_print_cstr(pctx, kw->name); cfg_print_cstr(pctx, kw->name);
cfg_print_chars(pctx, " ", 1); cfg_print_cstr(pctx, " ");
cfg_doc_obj(pctx, kw->type); cfg_doc_obj(pctx, kw->type);
cfg_print_chars(pctx, " ]", 2); cfg_print_cstr(pctx, " ]");
} }
static const char *dialup_enums[] = { static const char *dialup_enums[] = {
@ -2283,9 +2283,9 @@ doc_geoip(cfg_printer_t *pctx, const cfg_type_t *type) {
cfg_print_cstr(pctx, "[ db "); cfg_print_cstr(pctx, "[ db ");
cfg_doc_enum(pctx, &cfg_type_geoipdb); cfg_doc_enum(pctx, &cfg_type_geoipdb);
cfg_print_cstr(pctx, " ]"); cfg_print_cstr(pctx, " ]");
cfg_print_chars(pctx, " ", 1); cfg_print_cstr(pctx, " ");
cfg_doc_enum(pctx, &cfg_type_geoiptype); cfg_doc_enum(pctx, &cfg_type_geoiptype);
cfg_print_chars(pctx, " ", 1); cfg_print_cstr(pctx, " ");
cfg_print_cstr(pctx, "<quoted_string>"); cfg_print_cstr(pctx, "<quoted_string>");
} }
#endif /* HAVE_GEOIP */ #endif /* HAVE_GEOIP */
@ -2399,11 +2399,11 @@ static cfg_type_t cfg_type_controls = {
static void static void
doc_optional_bracketed_list(cfg_printer_t *pctx, const cfg_type_t *type) { doc_optional_bracketed_list(cfg_printer_t *pctx, const cfg_type_t *type) {
const keyword_type_t *kw = type->of; const keyword_type_t *kw = type->of;
cfg_print_chars(pctx, "[ ", 2); cfg_print_cstr(pctx, "[ ");
cfg_print_cstr(pctx, kw->name); cfg_print_cstr(pctx, kw->name);
cfg_print_chars(pctx, " ", 1); cfg_print_cstr(pctx, " ");
cfg_doc_obj(pctx, kw->type); cfg_doc_obj(pctx, kw->type);
cfg_print_chars(pctx, " ]", 2); cfg_print_cstr(pctx, " ]");
} }
static cfg_type_t cfg_type_optional_allow = { static cfg_type_t cfg_type_optional_allow = {
@ -2646,7 +2646,7 @@ static cfg_tuplefielddef_t negated_fields[] = {
static void static void
print_negated(cfg_printer_t *pctx, const cfg_obj_t *obj) { print_negated(cfg_printer_t *pctx, const cfg_obj_t *obj) {
cfg_print_chars(pctx, "!", 1); cfg_print_cstr(pctx, "!");
cfg_print_tuple(pctx, obj); cfg_print_tuple(pctx, obj);
} }
@ -2881,9 +2881,9 @@ static void
doc_logfile(cfg_printer_t *pctx, const cfg_type_t *type) { doc_logfile(cfg_printer_t *pctx, const cfg_type_t *type) {
UNUSED(type); UNUSED(type);
cfg_print_cstr(pctx, "<quoted_string>"); cfg_print_cstr(pctx, "<quoted_string>");
cfg_print_chars(pctx, " ", 1); cfg_print_cstr(pctx, " ");
cfg_print_cstr(pctx, "[ versions ( \"unlimited\" | <integer> ) ]"); cfg_print_cstr(pctx, "[ versions ( \"unlimited\" | <integer> ) ]");
cfg_print_chars(pctx, " ", 1); cfg_print_cstr(pctx, " ");
cfg_print_cstr(pctx, "[ size <size> ]"); cfg_print_cstr(pctx, "[ size <size> ]");
} }
@ -3049,25 +3049,25 @@ static cfg_type_t cfg_type_nameport = {
static void static void
doc_sockaddrnameport(cfg_printer_t *pctx, const cfg_type_t *type) { doc_sockaddrnameport(cfg_printer_t *pctx, const cfg_type_t *type) {
UNUSED(type); UNUSED(type);
cfg_print_chars(pctx, "( ", 2); cfg_print_cstr(pctx, "( ");
cfg_print_cstr(pctx, "<quoted_string>"); cfg_print_cstr(pctx, "<quoted_string>");
cfg_print_chars(pctx, " ", 1); cfg_print_cstr(pctx, " ");
cfg_print_cstr(pctx, "[ port <integer> ]"); cfg_print_cstr(pctx, "[ port <integer> ]");
cfg_print_chars(pctx, " ", 1); cfg_print_cstr(pctx, " ");
cfg_print_cstr(pctx, "[ dscp <integer> ]"); cfg_print_cstr(pctx, "[ dscp <integer> ]");
cfg_print_chars(pctx, " | ", 3); cfg_print_cstr(pctx, " | ");
cfg_print_cstr(pctx, "<ipv4_address>"); cfg_print_cstr(pctx, "<ipv4_address>");
cfg_print_chars(pctx, " ", 1); cfg_print_cstr(pctx, " ");
cfg_print_cstr(pctx, "[ port <integer> ]"); cfg_print_cstr(pctx, "[ port <integer> ]");
cfg_print_chars(pctx, " ", 1); cfg_print_cstr(pctx, " ");
cfg_print_cstr(pctx, "[ dscp <integer> ]"); cfg_print_cstr(pctx, "[ dscp <integer> ]");
cfg_print_chars(pctx, " | ", 3); cfg_print_cstr(pctx, " | ");
cfg_print_cstr(pctx, "<ipv6_address>"); cfg_print_cstr(pctx, "<ipv6_address>");
cfg_print_chars(pctx, " ", 1); cfg_print_cstr(pctx, " ");
cfg_print_cstr(pctx, "[ port <integer> ]"); cfg_print_cstr(pctx, "[ port <integer> ]");
cfg_print_chars(pctx, " ", 1); cfg_print_cstr(pctx, " ");
cfg_print_cstr(pctx, "[ dscp <integer> ]"); cfg_print_cstr(pctx, "[ dscp <integer> ]");
cfg_print_chars(pctx, " )", 2); cfg_print_cstr(pctx, " )");
} }
static isc_result_t static isc_result_t
@ -3141,17 +3141,17 @@ static cfg_type_t cfg_type_nameportiplist = {
static void static void
doc_masterselement(cfg_printer_t *pctx, const cfg_type_t *type) { doc_masterselement(cfg_printer_t *pctx, const cfg_type_t *type) {
UNUSED(type); UNUSED(type);
cfg_print_chars(pctx, "( ", 2); cfg_print_cstr(pctx, "( ");
cfg_print_cstr(pctx, "<masters>"); cfg_print_cstr(pctx, "<masters>");
cfg_print_chars(pctx, " | ", 3); cfg_print_cstr(pctx, " | ");
cfg_print_cstr(pctx, "<ipv4_address>"); cfg_print_cstr(pctx, "<ipv4_address>");
cfg_print_chars(pctx, " ", 1); cfg_print_cstr(pctx, " ");
cfg_print_cstr(pctx, "[ port <integer> ]"); cfg_print_cstr(pctx, "[ port <integer> ]");
cfg_print_chars(pctx, " | ", 3); cfg_print_cstr(pctx, " | ");
cfg_print_cstr(pctx, "<ipv6_address>"); cfg_print_cstr(pctx, "<ipv6_address>");
cfg_print_chars(pctx, " ", 1); cfg_print_cstr(pctx, " ");
cfg_print_cstr(pctx, "[ port <integer> ]"); cfg_print_cstr(pctx, "[ port <integer> ]");
cfg_print_chars(pctx, " )", 2); cfg_print_cstr(pctx, " )");
} }
static isc_result_t static isc_result_t

View File

@ -147,24 +147,34 @@ cfg_print_chars(cfg_printer_t *pctx, const char *text, int len) {
static void static void
print_open(cfg_printer_t *pctx) { print_open(cfg_printer_t *pctx) {
cfg_print_chars(pctx, "{\n", 2); if ((pctx->flags & CFG_PRINTER_ONELINE) != 0)
pctx->indent++; cfg_print_cstr(pctx, "{ ");
else {
cfg_print_cstr(pctx, "{\n");
pctx->indent++;
}
} }
static void static void
print_indent(cfg_printer_t *pctx) { print_indent(cfg_printer_t *pctx) {
int indent = pctx->indent; int indent = pctx->indent;
if ((pctx->flags & CFG_PRINTER_ONELINE) != 0) {
cfg_print_cstr(pctx, " ");
return;
}
while (indent > 0) { while (indent > 0) {
cfg_print_chars(pctx, "\t", 1); cfg_print_cstr(pctx, "\t");
indent--; indent--;
} }
} }
static void static void
print_close(cfg_printer_t *pctx) { print_close(cfg_printer_t *pctx) {
pctx->indent--; if ((pctx->flags & CFG_PRINTER_ONELINE) == 0) {
print_indent(pctx); pctx->indent--;
cfg_print_chars(pctx, "}", 1); print_indent(pctx);
}
cfg_print_cstr(pctx, "}");
} }
isc_result_t isc_result_t
@ -262,7 +272,7 @@ cfg_print_tuple(cfg_printer_t *pctx, const cfg_obj_t *obj) {
for (f = fields, i = 0; f->name != NULL; f++, i++) { for (f = fields, i = 0; f->name != NULL; f++, i++) {
const cfg_obj_t *fieldobj = obj->value.tuple[i]; const cfg_obj_t *fieldobj = obj->value.tuple[i];
if (need_space) if (need_space)
cfg_print_chars(pctx, " ", 1); cfg_print_cstr(pctx, " ");
cfg_print_obj(pctx, fieldobj); cfg_print_obj(pctx, fieldobj);
need_space = ISC_TF(fieldobj->type->print != cfg_print_void); need_space = ISC_TF(fieldobj->type->print != cfg_print_void);
} }
@ -276,7 +286,7 @@ cfg_doc_tuple(cfg_printer_t *pctx, const cfg_type_t *type) {
for (f = fields; f->name != NULL; f++) { for (f = fields; f->name != NULL; f++) {
if (need_space) if (need_space)
cfg_print_chars(pctx, " ", 1); cfg_print_cstr(pctx, " ");
cfg_doc_obj(pctx, f->type); cfg_doc_obj(pctx, f->type);
need_space = ISC_TF(f->type->print != cfg_print_void); need_space = ISC_TF(f->type->print != cfg_print_void);
} }
@ -481,6 +491,20 @@ cfg_parser_setcallback(cfg_parser_t *pctx,
pctx->callbackarg = arg; pctx->callbackarg = arg;
} }
void
cfg_parser_reset(cfg_parser_t *pctx) {
REQUIRE(pctx != NULL);
if (pctx->lexer != NULL)
isc_lex_close(pctx->lexer);
pctx->seen_eof = ISC_FALSE;
pctx->ungotten = ISC_FALSE;
pctx->errors = 0;
pctx->warnings = 0;
pctx->line = 0;
}
/* /*
* Parse a configuration using a pctx where a lexer has already * Parse a configuration using a pctx where a lexer has already
* been set up with a source. * been set up with a source.
@ -535,9 +559,12 @@ cfg_parse_buffer(cfg_parser_t *pctx, isc_buffer_t *buffer,
const cfg_type_t *type, cfg_obj_t **ret) const cfg_type_t *type, cfg_obj_t **ret)
{ {
isc_result_t result; isc_result_t result;
REQUIRE(buffer != NULL); REQUIRE(buffer != NULL);
CHECK(isc_lex_openbuffer(pctx->lexer, buffer)); CHECK(isc_lex_openbuffer(pctx->lexer, buffer));
CHECK(parse2(pctx, type, ret)); CHECK(parse2(pctx, type, ret));
cleanup: cleanup:
return (result); return (result);
} }
@ -821,13 +848,13 @@ cfg_parse_enum(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
void void
cfg_doc_enum(cfg_printer_t *pctx, const cfg_type_t *type) { cfg_doc_enum(cfg_printer_t *pctx, const cfg_type_t *type) {
const char * const *p; const char * const *p;
cfg_print_chars(pctx, "( ", 2); cfg_print_cstr(pctx, "( ");
for (p = type->of; *p != NULL; p++) { for (p = type->of; *p != NULL; p++) {
cfg_print_cstr(pctx, *p); cfg_print_cstr(pctx, *p);
if (p[1] != NULL) if (p[1] != NULL)
cfg_print_chars(pctx, " | ", 3); cfg_print_cstr(pctx, " | ");
} }
cfg_print_chars(pctx, " )", 2); cfg_print_cstr(pctx, " )");
} }
void void
@ -837,21 +864,21 @@ cfg_print_ustring(cfg_printer_t *pctx, const cfg_obj_t *obj) {
static void static void
print_qstring(cfg_printer_t *pctx, const cfg_obj_t *obj) { print_qstring(cfg_printer_t *pctx, const cfg_obj_t *obj) {
cfg_print_chars(pctx, "\"", 1); cfg_print_cstr(pctx, "\"");
cfg_print_ustring(pctx, obj); cfg_print_ustring(pctx, obj);
cfg_print_chars(pctx, "\"", 1); cfg_print_cstr(pctx, "\"");
} }
static void static void
print_sstring(cfg_printer_t *pctx, const cfg_obj_t *obj) { print_sstring(cfg_printer_t *pctx, const cfg_obj_t *obj) {
cfg_print_chars(pctx, "\"", 1); cfg_print_cstr(pctx, "\"");
if ((pctx->flags & CFG_PRINTER_XKEY) != 0) { if ((pctx->flags & CFG_PRINTER_XKEY) != 0) {
unsigned int len = obj->value.string.length; unsigned int len = obj->value.string.length;
while (len-- > 0) while (len-- > 0)
cfg_print_chars(pctx, "?", 1); cfg_print_cstr(pctx, "?");
} else } else
cfg_print_ustring(pctx, obj); cfg_print_ustring(pctx, obj);
cfg_print_chars(pctx, "\"", 1); cfg_print_cstr(pctx, "\"");
} }
static void static void
@ -958,9 +985,9 @@ cfg_parse_boolean(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
void void
cfg_print_boolean(cfg_printer_t *pctx, const cfg_obj_t *obj) { cfg_print_boolean(cfg_printer_t *pctx, const cfg_obj_t *obj) {
if (obj->value.boolean) if (obj->value.boolean)
cfg_print_chars(pctx, "yes", 3); cfg_print_cstr(pctx, "yes");
else else
cfg_print_chars(pctx, "no", 2); cfg_print_cstr(pctx, "no");
} }
cfg_type_t cfg_type_boolean = { cfg_type_t cfg_type_boolean = {
@ -994,8 +1021,9 @@ create_listelt(cfg_parser_t *pctx, cfg_listelt_t **eltp) {
} }
static void static void
free_list_elt(cfg_parser_t *pctx, cfg_listelt_t *elt) { free_listelt(cfg_parser_t *pctx, cfg_listelt_t *elt) {
cfg_obj_destroy(pctx, &elt->obj); if (elt->obj != NULL)
cfg_obj_destroy(pctx, &elt->obj);
isc_mem_put(pctx->mctx, elt, sizeof(*elt)); isc_mem_put(pctx->mctx, elt, sizeof(*elt));
} }
@ -1007,7 +1035,7 @@ free_list(cfg_parser_t *pctx, cfg_obj_t *obj) {
elt = next) elt = next)
{ {
next = ISC_LIST_NEXT(elt, link); next = ISC_LIST_NEXT(elt, link);
free_list_elt(pctx, elt); free_listelt(pctx, elt);
} }
} }
@ -1064,7 +1092,7 @@ parse_list(cfg_parser_t *pctx, const cfg_type_t *listtype, cfg_obj_t **ret)
cleanup: cleanup:
if (elt != NULL) if (elt != NULL)
free_list_elt(pctx, elt); free_listelt(pctx, elt);
CLEANUP_OBJ(listobj); CLEANUP_OBJ(listobj);
return (result); return (result);
} }
@ -1076,10 +1104,16 @@ print_list(cfg_printer_t *pctx, const cfg_obj_t *obj) {
for (elt = ISC_LIST_HEAD(*list); for (elt = ISC_LIST_HEAD(*list);
elt != NULL; elt != NULL;
elt = ISC_LIST_NEXT(elt, link)) { elt = ISC_LIST_NEXT(elt, link))
print_indent(pctx); {
cfg_print_obj(pctx, elt->obj); if ((pctx->flags & CFG_PRINTER_ONELINE) != 0) {
cfg_print_chars(pctx, ";\n", 2); cfg_print_obj(pctx, elt->obj);
cfg_print_cstr(pctx, "; ");
} else {
print_indent(pctx);
cfg_print_obj(pctx, elt->obj);
cfg_print_cstr(pctx, ";\n");
}
} }
} }
@ -1104,9 +1138,9 @@ cfg_print_bracketed_list(cfg_printer_t *pctx, const cfg_obj_t *obj) {
void void
cfg_doc_bracketed_list(cfg_printer_t *pctx, const cfg_type_t *type) { cfg_doc_bracketed_list(cfg_printer_t *pctx, const cfg_type_t *type) {
cfg_print_chars(pctx, "{ ", 2); cfg_print_cstr(pctx, "{ ");
cfg_doc_obj(pctx, type->of); cfg_doc_obj(pctx, type->of);
cfg_print_chars(pctx, "; ... }", 7); cfg_print_cstr(pctx, "; ... }");
} }
/* /*
@ -1152,7 +1186,7 @@ cfg_print_spacelist(cfg_printer_t *pctx, const cfg_obj_t *obj) {
elt = ISC_LIST_NEXT(elt, link)) { elt = ISC_LIST_NEXT(elt, link)) {
cfg_print_obj(pctx, elt->obj); cfg_print_obj(pctx, elt->obj);
if (ISC_LIST_NEXT(elt, link) != NULL) if (ISC_LIST_NEXT(elt, link) != NULL)
cfg_print_chars(pctx, " ", 1); cfg_print_cstr(pctx, " ");
} }
} }
@ -1476,10 +1510,24 @@ cfg_parse_netprefix_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **
return (parse_any_named_map(pctx, &cfg_type_netprefix, type, ret)); return (parse_any_named_map(pctx, &cfg_type_netprefix, type, ret));
} }
static void
print_symval(cfg_printer_t *pctx, const char *name, cfg_obj_t *obj) {
if ((pctx->flags & CFG_PRINTER_ONELINE) == 0)
print_indent(pctx);
cfg_print_cstr(pctx, name);
cfg_print_cstr(pctx, " ");
cfg_print_obj(pctx, obj);
if ((pctx->flags & CFG_PRINTER_ONELINE) == 0)
cfg_print_cstr(pctx, ";\n");
else
cfg_print_cstr(pctx, "; ");
}
void void
cfg_print_mapbody(cfg_printer_t *pctx, const cfg_obj_t *obj) { cfg_print_mapbody(cfg_printer_t *pctx, const cfg_obj_t *obj) {
isc_result_t result = ISC_R_SUCCESS; isc_result_t result = ISC_R_SUCCESS;
const cfg_clausedef_t * const *clauseset; const cfg_clausedef_t * const *clauseset;
for (clauseset = obj->value.map.clausesets; for (clauseset = obj->value.map.clausesets;
@ -1503,19 +1551,13 @@ cfg_print_mapbody(cfg_printer_t *pctx, const cfg_obj_t *obj) {
for (elt = ISC_LIST_HEAD(*list); for (elt = ISC_LIST_HEAD(*list);
elt != NULL; elt != NULL;
elt = ISC_LIST_NEXT(elt, link)) { elt = ISC_LIST_NEXT(elt, link)) {
print_indent(pctx); print_symval(pctx,
cfg_print_cstr(pctx, clause->name); clause->name,
cfg_print_chars(pctx, " ", 1); elt->obj);
cfg_print_obj(pctx, elt->obj);
cfg_print_chars(pctx, ";\n", 2);
} }
} else { } else {
/* Single-valued. */ /* Single-valued. */
print_indent(pctx); print_symval(pctx, clause->name, obj);
cfg_print_cstr(pctx, clause->name);
cfg_print_chars(pctx, " ", 1);
cfg_print_obj(pctx, obj);
cfg_print_chars(pctx, ";\n", 2);
} }
} else if (result == ISC_R_NOTFOUND) { } else if (result == ISC_R_NOTFOUND) {
; /* do nothing */ ; /* do nothing */
@ -1536,11 +1578,10 @@ cfg_doc_mapbody(cfg_printer_t *pctx, const cfg_type_t *type) {
clause->name != NULL; clause->name != NULL;
clause++) { clause++) {
cfg_print_cstr(pctx, clause->name); cfg_print_cstr(pctx, clause->name);
cfg_print_chars(pctx, " ", 1); cfg_print_cstr(pctx, " ");
cfg_doc_obj(pctx, clause->type); cfg_doc_obj(pctx, clause->type);
cfg_print_chars(pctx, ";", 1);
/* XXX print flags here? */ /* XXX print flags here? */
cfg_print_chars(pctx, "\n\n", 2); cfg_print_cstr(pctx, ";\n\n");
} }
} }
} }
@ -1562,7 +1603,7 @@ void
cfg_print_map(cfg_printer_t *pctx, const cfg_obj_t *obj) { cfg_print_map(cfg_printer_t *pctx, const cfg_obj_t *obj) {
if (obj->value.map.id != NULL) { if (obj->value.map.id != NULL) {
cfg_print_obj(pctx, obj->value.map.id); cfg_print_obj(pctx, obj->value.map.id);
cfg_print_chars(pctx, " ", 1); cfg_print_cstr(pctx, " ");
} }
print_open(pctx); print_open(pctx);
cfg_print_mapbody(pctx, obj); cfg_print_mapbody(pctx, obj);
@ -1576,9 +1617,9 @@ print_clause_flags(cfg_printer_t *pctx, unsigned int flags) {
for (p = flagtexts; p->flag != 0; p++) { for (p = flagtexts; p->flag != 0; p++) {
if ((flags & p->flag) != 0) { if ((flags & p->flag) != 0) {
if (first) if (first)
cfg_print_chars(pctx, " // ", 4); cfg_print_cstr(pctx, " // ");
else else
cfg_print_chars(pctx, ", ", 2); cfg_print_cstr(pctx, ", ");
cfg_print_cstr(pctx, p->text); cfg_print_cstr(pctx, p->text);
first = ISC_FALSE; first = ISC_FALSE;
} }
@ -1592,13 +1633,13 @@ cfg_doc_map(cfg_printer_t *pctx, const cfg_type_t *type) {
if (type->parse == cfg_parse_named_map) { if (type->parse == cfg_parse_named_map) {
cfg_doc_obj(pctx, &cfg_type_astring); cfg_doc_obj(pctx, &cfg_type_astring);
cfg_print_chars(pctx, " ", 1); cfg_print_cstr(pctx, " ");
} else if (type->parse == cfg_parse_addressed_map) { } else if (type->parse == cfg_parse_addressed_map) {
cfg_doc_obj(pctx, &cfg_type_netaddr); cfg_doc_obj(pctx, &cfg_type_netaddr);
cfg_print_chars(pctx, " ", 1); cfg_print_cstr(pctx, " ");
} else if (type->parse == cfg_parse_netprefix_map) { } else if (type->parse == cfg_parse_netprefix_map) {
cfg_doc_obj(pctx, &cfg_type_netprefix); cfg_doc_obj(pctx, &cfg_type_netprefix);
cfg_print_chars(pctx, " ", 1); cfg_print_cstr(pctx, " ");
} }
print_open(pctx); print_open(pctx);
@ -1610,11 +1651,11 @@ cfg_doc_map(cfg_printer_t *pctx, const cfg_type_t *type) {
print_indent(pctx); print_indent(pctx);
cfg_print_cstr(pctx, clause->name); cfg_print_cstr(pctx, clause->name);
if (clause->type->print != cfg_print_void) if (clause->type->print != cfg_print_void)
cfg_print_chars(pctx, " ", 1); cfg_print_cstr(pctx, " ");
cfg_doc_obj(pctx, clause->type); cfg_doc_obj(pctx, clause->type);
cfg_print_chars(pctx, ";", 1); cfg_print_cstr(pctx, ";");
print_clause_flags(pctx, clause->flags); print_clause_flags(pctx, clause->flags);
cfg_print_chars(pctx, "\n", 1); cfg_print_cstr(pctx, "\n");
} }
} }
print_close(pctx); print_close(pctx);
@ -1910,7 +1951,8 @@ cfg_print_rawaddr(cfg_printer_t *pctx, const isc_netaddr_t *na) {
isc_buffer_init(&buf, text, sizeof(text)); isc_buffer_init(&buf, text, sizeof(text));
result = isc_netaddr_totext(na, &buf); result = isc_netaddr_totext(na, &buf);
RUNTIME_CHECK(result == ISC_R_SUCCESS); RUNTIME_CHECK(result == ISC_R_SUCCESS);
cfg_print_chars(pctx, isc_buffer_base(&buf), isc_buffer_usedlength(&buf)); cfg_print_chars(pctx, isc_buffer_base(&buf),
isc_buffer_usedlength(&buf));
} }
isc_result_t isc_result_t
@ -1965,26 +2007,26 @@ cfg_doc_netaddr(cfg_printer_t *pctx, const cfg_type_t *type) {
const unsigned int *flagp = type->of; const unsigned int *flagp = type->of;
int n = 0; int n = 0;
if (*flagp != CFG_ADDR_V4OK && *flagp != CFG_ADDR_V6OK) if (*flagp != CFG_ADDR_V4OK && *flagp != CFG_ADDR_V6OK)
cfg_print_chars(pctx, "( ", 2); cfg_print_cstr(pctx, "( ");
if (*flagp & CFG_ADDR_V4OK) { if (*flagp & CFG_ADDR_V4OK) {
cfg_print_cstr(pctx, "<ipv4_address>"); cfg_print_cstr(pctx, "<ipv4_address>");
n++; n++;
} }
if (*flagp & CFG_ADDR_V6OK) { if (*flagp & CFG_ADDR_V6OK) {
if (n != 0) if (n != 0)
cfg_print_chars(pctx, " | ", 3); cfg_print_cstr(pctx, " | ");
cfg_print_cstr(pctx, "<ipv6_address>"); cfg_print_cstr(pctx, "<ipv6_address>");
n++; n++;
} }
if (*flagp & CFG_ADDR_WILDOK) { if (*flagp & CFG_ADDR_WILDOK) {
if (n != 0) if (n != 0)
cfg_print_chars(pctx, " | ", 3); cfg_print_cstr(pctx, " | ");
cfg_print_chars(pctx, "*", 1); cfg_print_cstr(pctx, "*");
n++; n++;
POST(n); POST(n);
} }
if (*flagp != CFG_ADDR_V4OK && *flagp != CFG_ADDR_V6OK) if (*flagp != CFG_ADDR_V4OK && *flagp != CFG_ADDR_V6OK)
cfg_print_chars(pctx, " )", 2); cfg_print_cstr(pctx, " )");
} }
cfg_type_t cfg_type_netaddr = { cfg_type_t cfg_type_netaddr = {
@ -2071,7 +2113,7 @@ print_netprefix(cfg_printer_t *pctx, const cfg_obj_t *obj) {
const cfg_netprefix_t *p = &obj->value.netprefix; const cfg_netprefix_t *p = &obj->value.netprefix;
cfg_print_rawaddr(pctx, &p->address); cfg_print_rawaddr(pctx, &p->address);
cfg_print_chars(pctx, "/", 1); cfg_print_cstr(pctx, "/");
cfg_print_rawuint(pctx, p->prefixlen); cfg_print_rawuint(pctx, p->prefixlen);
} }
@ -2180,11 +2222,11 @@ cfg_print_sockaddr(cfg_printer_t *pctx, const cfg_obj_t *obj) {
cfg_print_cstr(pctx, buf); cfg_print_cstr(pctx, buf);
port = isc_sockaddr_getport(&obj->value.sockaddr); port = isc_sockaddr_getport(&obj->value.sockaddr);
if (port != 0) { if (port != 0) {
cfg_print_chars(pctx, " port ", 6); cfg_print_cstr(pctx, " port ");
cfg_print_rawuint(pctx, port); cfg_print_rawuint(pctx, port);
} }
if (obj->value.sockaddrdscp.dscp != -1) { if (obj->value.sockaddrdscp.dscp != -1) {
cfg_print_chars(pctx, " dscp ", 6); cfg_print_cstr(pctx, " dscp ");
cfg_print_rawuint(pctx, obj->value.sockaddrdscp.dscp); cfg_print_rawuint(pctx, obj->value.sockaddrdscp.dscp);
} }
} }
@ -2193,25 +2235,25 @@ void
cfg_doc_sockaddr(cfg_printer_t *pctx, const cfg_type_t *type) { cfg_doc_sockaddr(cfg_printer_t *pctx, const cfg_type_t *type) {
const unsigned int *flagp = type->of; const unsigned int *flagp = type->of;
int n = 0; int n = 0;
cfg_print_chars(pctx, "( ", 2); cfg_print_cstr(pctx, "( ");
if (*flagp & CFG_ADDR_V4OK) { if (*flagp & CFG_ADDR_V4OK) {
cfg_print_cstr(pctx, "<ipv4_address>"); cfg_print_cstr(pctx, "<ipv4_address>");
n++; n++;
} }
if (*flagp & CFG_ADDR_V6OK) { if (*flagp & CFG_ADDR_V6OK) {
if (n != 0) if (n != 0)
cfg_print_chars(pctx, " | ", 3); cfg_print_cstr(pctx, " | ");
cfg_print_cstr(pctx, "<ipv6_address>"); cfg_print_cstr(pctx, "<ipv6_address>");
n++; n++;
} }
if (*flagp & CFG_ADDR_WILDOK) { if (*flagp & CFG_ADDR_WILDOK) {
if (n != 0) if (n != 0)
cfg_print_chars(pctx, " | ", 3); cfg_print_cstr(pctx, " | ");
cfg_print_chars(pctx, "*", 1); cfg_print_cstr(pctx, "*");
n++; n++;
POST(n); POST(n);
} }
cfg_print_chars(pctx, " ) ", 3); cfg_print_cstr(pctx, " ) ");
if (*flagp & CFG_ADDR_WILDOK) { if (*flagp & CFG_ADDR_WILDOK) {
cfg_print_cstr(pctx, "[ port ( <integer> | * ) ]"); cfg_print_cstr(pctx, "[ port ( <integer> | * ) ]");
} else { } else {
@ -2510,7 +2552,6 @@ map_symtabitem_destroy(char *key, unsigned int type,
cfg_obj_destroy(pctx, &obj); cfg_obj_destroy(pctx, &obj);
} }
static isc_result_t static isc_result_t
create_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { create_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
isc_result_t result; isc_result_t result;
@ -2587,9 +2628,9 @@ cfg_doc_obj(cfg_printer_t *pctx, const cfg_type_t *type) {
void void
cfg_doc_terminal(cfg_printer_t *pctx, const cfg_type_t *type) { cfg_doc_terminal(cfg_printer_t *pctx, const cfg_type_t *type) {
cfg_print_chars(pctx, "<", 1); cfg_print_cstr(pctx, "<");
cfg_print_cstr(pctx, type->name); cfg_print_cstr(pctx, type->name);
cfg_print_chars(pctx, ">", 1); cfg_print_cstr(pctx, ">");
} }
void void
@ -2604,3 +2645,72 @@ cfg_print_grammar(const cfg_type_t *type,
pctx.flags = 0; pctx.flags = 0;
cfg_doc_obj(&pctx, type); cfg_doc_obj(&pctx, type);
} }
isc_result_t
cfg_parser_mapadd(cfg_parser_t *pctx, cfg_obj_t *mapobj,
cfg_obj_t *obj, const char *clausename)
{
isc_result_t result = ISC_R_SUCCESS;
const cfg_map_t *map;
isc_symvalue_t symval;
cfg_obj_t *destobj = NULL;
cfg_listelt_t *elt = NULL;
const cfg_clausedef_t * const *clauseset;
const cfg_clausedef_t *clause;
REQUIRE(pctx != NULL);
REQUIRE(mapobj != NULL && mapobj->type->rep == &cfg_rep_map);
REQUIRE(obj != NULL);
map = &mapobj->value.map;
clause = NULL;
for (clauseset = map->clausesets; *clauseset != NULL; clauseset++) {
for (clause = *clauseset; clause->name != NULL; clause++) {
if (strcasecmp(clause->name, clausename) == 0) {
goto breakout;
}
}
}
breakout:
if (clause == NULL || clause->name == NULL)
return (ISC_R_FAILURE);
result = isc_symtab_lookup(map->symtab, clausename, 0, &symval);
if (result == ISC_R_NOTFOUND) {
if ((clause->flags & CFG_CLAUSEFLAG_MULTI) != 0) {
CHECK(cfg_create_list(pctx, &cfg_type_implicitlist,
&destobj));
CHECK(create_listelt(pctx, &elt));
cfg_obj_attach(obj, &elt->obj);
ISC_LIST_APPEND(destobj->value.list, elt, link);
symval.as_pointer = destobj;
} else
symval.as_pointer = obj;
CHECK(isc_symtab_define(map->symtab, clausename, 1, symval,
isc_symexists_reject));
} else {
cfg_obj_t *destobj2 = symval.as_pointer;
INSIST(result == ISC_R_SUCCESS);
if (destobj2->type == &cfg_type_implicitlist) {
CHECK(create_listelt(pctx, &elt));
cfg_obj_attach(obj, &elt->obj);
ISC_LIST_APPEND(destobj2->value.list, elt, link);
} else
result = ISC_R_EXISTS;
}
destobj = NULL;
elt = NULL;
cleanup:
if (elt != NULL)
free_listelt(pctx, elt);
CLEANUP_OBJ(destobj);
return (result);
}