From cfd262045c23cadb8415f0111f56995258f17361 Mon Sep 17 00:00:00 2001 From: Evan Hunt Date: Wed, 11 Aug 2010 18:14:20 +0000 Subject: [PATCH] 2936. [func] Improved configuration syntax and multiple-view support for addzone/delzone feature (see change #2930). Removed "new-zone-file" option, replaced with "allow-new-zones (yes|no)". The new-zone-file for each view is now created automatically, with a filename generated from a hash of the view name. It is no longer necessary to "include" the new-zone-file in named.conf; this happens automatically. Zones that were not added via "rndc addzone" can no longer be removed with "rndc delzone". [RT #19447] --- CHANGES | 12 + bin/named/config.c | 4 +- bin/named/server.c | 472 +++++++----------- bin/named/zoneconf.c | 9 +- bin/tests/db/Makefile.in | 8 +- bin/tests/system/addzone/clean.sh | 23 + bin/tests/system/addzone/ns2/added.db | 31 ++ bin/tests/system/addzone/ns2/default.nzf.orig | 1 + bin/tests/system/addzone/ns2/named1.conf | 41 ++ bin/tests/system/addzone/ns2/named2.conf | 49 ++ bin/tests/system/addzone/ns2/normal.db | 31 ++ bin/tests/system/addzone/ns2/previous.db | 31 ++ bin/tests/system/addzone/setup.sh | 20 + bin/tests/system/addzone/tests.sh | 122 +++++ bin/tests/system/conf.sh.in | 8 +- doc/arm/Bv9ARM-book.xml | 74 ++- lib/bind9/check.c | 6 +- lib/dns/include/dns/view.h | 31 +- lib/dns/include/dns/zone.h | 21 +- lib/dns/view.c | 45 +- lib/dns/zone.c | 22 +- lib/isccfg/aclconf.c | 21 +- lib/isccfg/include/isccfg/aclconf.h | 12 +- lib/isccfg/include/isccfg/cfg.h | 28 +- lib/isccfg/include/isccfg/grammar.h | 6 +- lib/isccfg/include/isccfg/namedconf.h | 5 +- lib/isccfg/namedconf.c | 57 +-- lib/isccfg/parser.c | 66 ++- lib/isccfg/win32/libisccfg.def | 1 + 29 files changed, 893 insertions(+), 364 deletions(-) create mode 100644 bin/tests/system/addzone/clean.sh create mode 100644 bin/tests/system/addzone/ns2/added.db create mode 100644 bin/tests/system/addzone/ns2/default.nzf.orig create mode 100644 bin/tests/system/addzone/ns2/named1.conf create mode 100644 bin/tests/system/addzone/ns2/named2.conf create mode 100644 bin/tests/system/addzone/ns2/normal.db create mode 100644 bin/tests/system/addzone/ns2/previous.db create mode 100644 bin/tests/system/addzone/setup.sh create mode 100644 bin/tests/system/addzone/tests.sh diff --git a/CHANGES b/CHANGES index adecacce8b..21e7282d43 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,15 @@ +2936. [func] Improved configuration syntax and multiple-view + support for addzone/delzone feature (see change + #2930). Removed "new-zone-file" option, replaced + with "allow-new-zones (yes|no)". The new-zone-file + for each view is now created automatically, with + a filename generated from a hash of the view name. + It is no longer necessary to "include" the + new-zone-file in named.conf; this happens + automatically. Zones that were not added via + "rndc addzone" can no longer be removed with + "rndc delzone". [RT #19447] + 2935. [bug] nsupdate: improve 'file not found' error message. [RT #21871] diff --git a/bin/named/config.c b/bin/named/config.c index 94bedbbba1..07a74bae50 100644 --- a/bin/named/config.c +++ b/bin/named/config.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: config.c,v 1.111 2010/06/25 03:24:05 marka Exp $ */ +/* $Id: config.c,v 1.112 2010/08/11 18:14:18 each Exp $ */ /*! \file */ @@ -159,6 +159,7 @@ options {\n\ max-clients-per-query 100;\n\ zero-no-soa-ttl-cache no;\n\ nsec3-test-zone no;\n\ + allow-new-zones no;\n\ " #ifdef ALLOW_FILTER_AAAA_ON_V4 " filter-aaaa-on-v4 no;\n\ @@ -218,6 +219,7 @@ options {\n\ view \"_bind\" chaos {\n\ recursion no;\n\ notify no;\n\ + allow-new-zones no;\n\ \n\ zone \"version.bind\" chaos {\n\ type master;\n\ diff --git a/bin/named/server.c b/bin/named/server.c index 064b5a932d..5703ea3207 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: server.c,v 1.577 2010/07/20 04:52:21 marka Exp $ */ +/* $Id: server.c,v 1.578 2010/08/11 18:14:18 each Exp $ */ /*! \file */ @@ -203,6 +203,17 @@ struct zonelistentry { ISC_LINK(struct zonelistentry) link; }; +/*% + * Configuration context to retain for each view that allows + * new zones to be added at runtime + */ +struct cfg_context { + isc_mem_t * mctx; + cfg_obj_t * config; + cfg_parser_t * parser; + cfg_aclconfctx_t actx; +}; + /* * These zones should not leak onto the Internet. */ @@ -286,7 +297,7 @@ configure_alternates(const cfg_obj_t *config, dns_view_t *view, static isc_result_t configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, const cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view, - cfg_aclconfctx_t *aclconf); + cfg_aclconfctx_t *aclconf, isc_boolean_t added); static isc_result_t add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx); @@ -294,14 +305,8 @@ add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx); static void end_reserved_dispatches(ns_server_t *server, isc_boolean_t all); -/* - * Stores config for building zones after the fact - */ -static cfg_obj_t *nzf_config = NULL; -static cfg_parser_t *nzf_parser = NULL; -static const char *nzf_file = NULL; -static const cfg_obj_t *nzf_option = NULL; -static cfg_aclconfctx_t nzf_actx; +static void +cfgctx_destroy(void **cfgp); /*% * Configure a single view ACL at '*aclp'. Get its configuration from @@ -1293,10 +1298,11 @@ cache_sharable(dns_view_t *originview, dns_view_t *view, * global defaults in 'config' used exclusively. */ static isc_result_t -configure_view(dns_view_t *view, const cfg_obj_t *config, - const cfg_obj_t *vconfig, ns_cachelist_t *cachelist, - const cfg_obj_t *bindkeys, isc_mem_t *mctx, - cfg_aclconfctx_t *actx, isc_boolean_t need_hints) +configure_view(dns_view_t *view, cfg_parser_t* parser, + cfg_obj_t *config, cfg_obj_t *vconfig, + ns_cachelist_t *cachelist, const cfg_obj_t *bindkeys, + isc_mem_t *mctx, cfg_aclconfctx_t *actx, + isc_boolean_t need_hints) { const cfg_obj_t *maps[4]; const cfg_obj_t *cfgmaps[3]; @@ -1349,6 +1355,8 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, isc_boolean_t auto_dlv = ISC_FALSE; ns_cache_t *nsc; isc_boolean_t zero_no_soattl; + cfg_parser_t *newzones_parser = NULL; + cfg_obj_t *nzfconf = NULL; REQUIRE(DNS_VIEW_VALID(view)); @@ -1453,7 +1461,62 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, { const cfg_obj_t *zconfig = cfg_listelt_value(element); CHECK(configure_zone(config, zconfig, vconfig, mctx, view, - actx)); + actx, ISC_FALSE)); + } + + /* + * Are we allowing zones to be added and deleted dynamically? + */ + obj = NULL; + result = ns_config_get(maps, "allow-new-zones", &obj); + if (result == ISC_R_SUCCESS) { + isc_boolean_t allow = cfg_obj_asboolean(obj); + struct cfg_context *cfg = NULL; + if (allow) { + cfg = isc_mem_get(view->mctx, sizeof(*cfg)); + if (cfg == NULL) { + result = ISC_R_NOMEMORY; + goto cleanup; + } + memset(cfg, 0, sizeof(*cfg)); + isc_mem_attach(view->mctx, &cfg->mctx); + if (config != NULL) + cfg_obj_attach(config, &cfg->config); + cfg_parser_attach(parser, &cfg->parser); + cfg_aclconfctx_clone(actx, &cfg->actx); + } + dns_view_setnewzones(view, allow, cfg, cfgctx_destroy); + } + + /* + * If we're allowing added zones, then load zone configuration + * from the newzone file for zones that were added during previous + * runs. + */ + if (view->new_zone_file != NULL) { + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_INFO, + "loading additional zones for view '%s'", + view->name); + + CHECK(cfg_parser_create(view->mctx, ns_g_lctx, + &newzones_parser)); + result = cfg_parse_file(newzones_parser, view->new_zone_file, + &cfg_type_newzones, &nzfconf); + if (result == ISC_R_SUCCESS) { + zonelist = NULL; + cfg_map_get(nzfconf, "zone", &zonelist); + for (element = cfg_list_first(zonelist); + element != NULL; + element = cfg_list_next(element)) + { + const cfg_obj_t *zconfig = + cfg_listelt_value(element); + CHECK(configure_zone(config, zconfig, vconfig, + mctx, view, actx, + ISC_TRUE)); + } + } } #ifdef DLZ @@ -1991,8 +2054,10 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, * "allow-recursion", and "allow-recursion-on" acls if * configured in named.conf. */ - CHECK(configure_view_acl(vconfig, config, "allow-query-cache", NULL, - actx, ns_g_mctx, &view->queryacl)); + if (view->queryacl == NULL) + CHECK(configure_view_acl(vconfig, config, + "allow-query-cache", NULL, + actx, ns_g_mctx, &view->queryacl)); CHECK(configure_view_acl(vconfig, config, "allow-query-cache-on", NULL, actx, ns_g_mctx, &view->queryonacl)); if (view->queryonacl == NULL) @@ -2043,9 +2108,7 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, "allow-query-cache", NULL, actx, ns_g_mctx, &view->queryacl)); - else { - if (view->queryacl != NULL) - dns_acl_detach(&view->queryacl); + else if (view->new_zone_file == NULL) { CHECK(dns_acl_none(ns_g_mctx, &view->queryacl)); } } @@ -2465,6 +2528,12 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, if (cache != NULL) dns_cache_detach(&cache); + if (newzones_parser != NULL) { + if (nzfconf != NULL) + cfg_obj_destroy(newzones_parser, &nzfconf); + cfg_parser_destroy(&newzones_parser); + } + return (result); } @@ -2718,7 +2787,7 @@ create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist, static isc_result_t configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, const cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view, - cfg_aclconfctx_t *aclconf) + cfg_aclconfctx_t *aclconf, isc_boolean_t added) { dns_view_t *pview = NULL; /* Production view */ dns_zone_t *zone = NULL; /* New or reused zone */ @@ -2931,6 +3000,11 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, CHECK(dns_view_adddelegationonly(view, origin)); } + /* + * Mark whether the zone was originally added at runtime or not + */ + dns_zone_setadded(zone, added); + /* * Configure the zone. */ @@ -4011,17 +4085,6 @@ load_configuration(const char *filename, ns_server_t *server, } } - /* Are we preserving config for adding zones dynamically? */ - obj = NULL; - result = cfg_map_get(options, "new-zone-file", &obj); - if (obj && nzf_option == NULL) { - nzf_file = cfg_obj_asstring(obj); - if (nzf_file && *nzf_file) { - /* Remember this configuration */ - nzf_option = config; - } - } - /* * Rescan the interface list to pick up changes in the * listen-on option. It's important that we do this before we try @@ -4109,28 +4172,14 @@ load_configuration(const char *filename, ns_server_t *server, element != NULL; element = cfg_list_next(element)) { - const cfg_obj_t *vconfig = cfg_listelt_value(element); + cfg_obj_t *vconfig = cfg_listelt_value(element); view = NULL; CHECK(create_view(vconfig, &viewlist, &view)); INSIST(view != NULL); - CHECK(configure_view(view, config, vconfig, + CHECK(configure_view(view, conf_parser, config, vconfig, &cachelist, bindkeys, ns_g_mctx, &aclconfctx, ISC_TRUE)); - - if (vconfig != NULL) { - /* - * Are we preserving config for dynamically added - * zones? - */ - const cfg_obj_t *voptions; - voptions = cfg_tuple_get(vconfig, "options"); - obj = NULL; - result = cfg_map_get(voptions, "new-zone-file", &obj); - if (obj && nzf_option == NULL) - nzf_option = config; - } - dns_view_freeze(view); dns_view_detach(&view); } @@ -4147,7 +4196,7 @@ load_configuration(const char *filename, ns_server_t *server, * In either case, we need to configure and freeze it. */ CHECK(create_view(NULL, &viewlist, &view)); - CHECK(configure_view(view, config, NULL, + CHECK(configure_view(view, conf_parser, config, NULL, &cachelist, bindkeys, ns_g_mctx, &aclconfctx, ISC_TRUE)); dns_view_freeze(view); @@ -4164,10 +4213,10 @@ load_configuration(const char *filename, ns_server_t *server, element != NULL; element = cfg_list_next(element)) { - const cfg_obj_t *vconfig = cfg_listelt_value(element); + cfg_obj_t *vconfig = cfg_listelt_value(element); CHECK(create_view(vconfig, &builtin_viewlist, &view)); - CHECK(configure_view(view, config, vconfig, + CHECK(configure_view(view, conf_parser, config, vconfig, &cachelist, bindkeys, ns_g_mctx, &aclconfctx, ISC_FALSE)); dns_view_freeze(view); @@ -4452,16 +4501,7 @@ load_configuration(const char *filename, ns_server_t *server, if (v6portset != NULL) isc_portset_destroy(ns_g_mctx, &v6portset); - /* Preserve config, we'll need it when adding zones */ - if (nzf_option != NULL) { - nzf_parser = conf_parser; - conf_parser = NULL; - nzf_config = config; - config = NULL; - memcpy(&nzf_actx, &aclconfctx, sizeof(cfg_aclconfctx_t)); - } else { - cfg_aclconfctx_destroy(&aclconfctx); - } + cfg_aclconfctx_clear(&aclconfctx); if (conf_parser != NULL) { if (config != NULL) @@ -4669,12 +4709,6 @@ shutdown_server(isc_task_t *task, isc_event_t *event) { cfg_obj_destroy(ns_g_parser, &ns_g_config); cfg_parser_destroy(&ns_g_parser); - if (nzf_config) { - cfg_aclconfctx_destroy(&nzf_actx); - cfg_obj_destroy(nzf_parser, &nzf_config); - cfg_parser_destroy(&nzf_parser); - } - for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; view = view_next) { @@ -6607,14 +6641,14 @@ isc_result_t ns_server_add_zone(ns_server_t *server, char *args) { isc_result_t result; isc_buffer_t argbuf; - size_t arglen, len; + size_t arglen; cfg_parser_t *parser = NULL; cfg_obj_t *config = NULL; - const cfg_obj_t *vconfig = NULL; - const cfg_obj_t *views = NULL; - const cfg_listelt_t *element; + const cfg_obj_t *vconfig = NULL; + const cfg_obj_t *views = NULL; const cfg_obj_t *parms = NULL; const cfg_obj_t *obj = NULL; + const cfg_listelt_t *element; const char *zonename; const char *classname = NULL; const char *argp; @@ -6623,16 +6657,9 @@ ns_server_add_zone(ns_server_t *server, char *args) { dns_view_t *view = 0; isc_buffer_t buf, *nbuf = NULL; dns_name_t dnsname; - const char *filename = 0; - const char *filepart = NULL; - char fnamebuf[512]; - struct stat sb; dns_zone_t *zone = NULL; FILE *fp = NULL; - - /* Are we accepting new zones? */ - if (nzf_option == NULL) - return (ISC_R_FAILURE); + struct cfg_context *cfg = NULL; /* Try to parse the argument string */ arglen = strlen(args); @@ -6651,33 +6678,6 @@ ns_server_add_zone(ns_server_t *server, char *args) { dns_name_setbuffer(&dnsname, nbuf); CHECK(dns_name_fromtext(&dnsname, &buf, dns_rootname, ISC_FALSE, NULL)); - /* - * If new-zone-file indicates a directory rather than a file, - * then "filepart" is the filename in the directory in which to - * write the zone configuration text. - */ - obj = cfg_tuple_get(parms, "filepart"); - if (obj && cfg_obj_isstring(obj)) - filepart = cfg_obj_asstring(obj); - - if (filepart != NULL && *filepart != '\0') { - /* No hidden fles or full paths */ - if (*filepart == '.' || -#ifdef WIN32 - *filepart == '\\' || -#endif - *filepart == '/') - { - result = ISC_R_INVALIDFILE; - goto cleanup; - } - /* No crawling up the directory tree */ - if (strstr(filepart, "..") != NULL) { - result = ISC_R_INVALIDFILE; - goto cleanup; - } - } - /* Make sense of optional class argument */ obj = cfg_tuple_get(parms, "class"); CHECK(ns_config_getclass(obj, dns_rdataclass_in, &rdclass)); @@ -6692,6 +6692,18 @@ ns_server_add_zone(ns_server_t *server, char *args) { viewname = "_default"; CHECK(dns_viewlist_find(&server->viewlist, viewname, rdclass, &view)); + /* Are we accepting new zones? */ + if (view->new_zone_file == NULL) { + result = ISC_R_NOPERM; + goto cleanup; + } + + cfg = (struct cfg_context *) view->new_zone_config; + if (cfg == NULL) { + result = ISC_R_FAILURE; + goto cleanup; + } + /* Zone shouldn't already exist */ result = dns_zt_find(view->zonetable, &dnsname, 0, NULL, &zone); if (result == ISC_R_SUCCESS) { @@ -6705,66 +6717,27 @@ ns_server_add_zone(ns_server_t *server, char *args) { else if (result != ISC_R_NOTFOUND) goto cleanup; - /* Find configuration for this view */ - (void)cfg_map_get(nzf_config, "view", &views); + /* 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)) { - /* What is save file for this view? */ - if (vconfig != NULL) { - const cfg_obj_t *voptions; - voptions = cfg_tuple_get(vconfig, "options"); - if (voptions) { - obj = NULL; - result = cfg_map_get(voptions, - "new-zone-file", - &obj); - if (result == ISC_R_SUCCESS) - filename = - cfg_obj_asstring(obj); - } - } + if (vname && !strcasecmp(vname, viewname)) break; - } vconfig = NULL; } - /* Can we add and remove zones in this view? */ - if (filename == NULL || *filename == '\0') - filename = nzf_file; + /* Open save file for write configuration */ + CHECK(isc_stdio_open(view->new_zone_file, "a", &fp)); - if (filename == NULL || *filename == '\0') { - /* No adding zones in this view */ - result = ISC_R_FAILURE; - goto cleanup; - } - - /* Possibly contruct a full path */ - if (filepart != NULL && *filepart != '\0') { - snprintf(fnamebuf, 512, "%s/%s", filename, filepart); - filename = fnamebuf; - } - - /* Path must be an existing file */ - if (stat(filename, &sb) < 0) { - result = ISC_R_FILENOTFOUND; - goto cleanup; - } - if (!S_ISREG(sb.st_mode)) { - result = ISC_R_FILENOTFOUND; - goto cleanup; - } - - /* Mark zone unfrozen so that zone can be added. */ + /* Mark view unfrozen so that zone can be added */ dns_view_thaw(view); - result = configure_zone(nzf_option, parms, vconfig, - server->mctx, view, &nzf_actx); + result = configure_zone(cfg->config, parms, vconfig, + server->mctx, view, &cfg->actx, ISC_FALSE); dns_view_freeze(view); if (result != ISC_R_SUCCESS) { goto cleanup; @@ -6795,30 +6768,30 @@ ns_server_add_zone(ns_server_t *server, char *args) { goto cleanup; } - /* Write zone configuration out to our save file */ - CHECK(isc_stdio_open(filename, "a", &fp)); + /* Flag the zone as having been added at runtime */ + dns_zone_setadded(zone, ISC_TRUE); /* Emit just the zone name from args */ - CHECK(isc_stdio_write("zone ", 5, 1, fp, &len)); - CHECK(isc_stdio_write(zonename, strlen(zonename), 1, fp, &len)); - CHECK(isc_stdio_write(" ", 1, 1, fp, &len)); + CHECK(isc_stdio_write("zone ", 5, 1, fp, NULL)); + CHECK(isc_stdio_write(zonename, strlen(zonename), 1, fp, NULL)); + CHECK(isc_stdio_write(" ", 1, 1, fp, NULL)); /* Classname, if not default */ if (classname != NULL && *classname != '\0') { CHECK(isc_stdio_write(classname, strlen(classname), 1, fp, - &len)); - CHECK(isc_stdio_write(" ", 1, 1, fp, &len)); + NULL)); + CHECK(isc_stdio_write(" ", 1, 1, fp, NULL)); } /* Find beginning of option block from args */ for (argp = args; *argp; argp++, arglen--) { if (*argp == '{') { /* Assume matching '}' */ /* Add that to our file */ - CHECK(isc_stdio_write(argp, arglen, 1, fp, &len)); + CHECK(isc_stdio_write(argp, arglen, 1, fp, NULL)); /* Make sure we end with a LF */ if (argp[arglen-1] != '\n') { - CHECK(isc_stdio_write("\n", 1, 1, fp, &len)); + CHECK(isc_stdio_write("\n", 1, 1, fp, NULL)); } break; } @@ -6851,50 +6824,6 @@ ns_server_add_zone(ns_server_t *server, char *args) { return (result); } -/* - * Pull an optional quoted filepart out of an arglist, shuffling memory - * so we can hand it off to zone_from_args() later - */ -static char * -extract_optional_qstring(char **args) { - char *p = *args; - char *str, *d; - char quote; - - /* Skip past the command name */ - while (isspace((unsigned char)*p)) - p++; - while (*p && !isspace((unsigned char)*p)) - p++; - - /* Look for an open quote */ - while (isspace((unsigned char)*p)) - p++; - if (*p != '\'' && *p != '"') - return (NULL); - - /* Move that string to the front of the buf */ - quote = *p++; - str = d = *args; - while (*p && *p != quote) - *d++ = *p++; - if (!*p) - return (NULL); /* No matching close quote */ - - /* End that string */ - *d++ = 0; - *args = d; - - /* A bogus command name to placate zone_from_args() */ - *d++ = 'X'; - - /* Cover over any remainder with spaces */ - while (d <= p) - *d++ = ' '; - - return (str); -} - /* * Act on a "delzone" command from the command channel. */ @@ -6903,45 +6832,15 @@ ns_server_del_zone(ns_server_t *server, char *args) { isc_result_t result; dns_zone_t *zone = NULL; dns_view_t *view = NULL; - const cfg_obj_t *views = NULL; - const cfg_obj_t *obj = NULL; - const cfg_obj_t *vconfig = NULL; dns_db_t *dbp = NULL; const char *filename = NULL; - char *filepart = NULL; - char fnamebuf[512]; char *tmpname = NULL; - const cfg_listelt_t *element; char buf[1024]; const char *zonename = NULL; size_t znamelen = 0; FILE *ifp = NULL, *ofp = NULL; - /* Only accept removes if we're accepting adds */ - if (nzf_option == NULL) - return (ISC_R_FAILURE); - - /* Possibly a filename in quotes */ - filepart = extract_optional_qstring(&args); - if (filepart != NULL && *filepart != '\0') { - /* No hidden fles or full paths */ - if (*filepart == '.' || -#ifdef WIN32 - *filepart == '\\' || -#endif - *filepart == '/') - { - result = ISC_R_INVALIDFILE; - goto cleanup; - } - /* No crawling up the directory tree */ - if (strstr(filepart, "..") != NULL) { - result = ISC_R_INVALIDFILE; - goto cleanup; - } - } - - /* Make sense of rest of params */ + /* Parse parameters */ CHECK(zone_from_args(server, args, &zone, &zonename)); if (result != ISC_R_SUCCESS) return (result); @@ -6950,56 +6849,27 @@ ns_server_del_zone(ns_server_t *server, char *args) { goto cleanup; } - if (zonename != NULL && *zonename != '\0') + /* + * 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; + } + + if (zonename != NULL) znamelen = strlen(zonename); /* Dig out configuration for this zone */ view = dns_zone_getview(zone); - (void)cfg_map_get(nzf_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 != NULL && !strcasecmp(vname, view->name)) { - /* What is save file for this view? */ - if (vconfig != NULL) { - const cfg_obj_t *voptions; - voptions = cfg_tuple_get(vconfig, "options"); - if (voptions != NULL) { - obj = NULL; - result = cfg_map_get(voptions, - "new-zone-file", - &obj); - if (result == ISC_R_SUCCESS) - filename = - cfg_obj_asstring(obj); - } - } - break; - } - vconfig = NULL; - } - - /* Can we add and remove zones in this view? */ - if (filename == NULL || *filename == '\0') - filename = nzf_file; - - if (filename == NULL || *filename == '\0') { + filename = view->new_zone_file; + if (filename == NULL) { /* No adding zones in this view */ result = ISC_R_FAILURE; goto cleanup; } - /* Possibly contruct a full path */ - if (filepart != NULL && *filepart != '\0') { - snprintf(fnamebuf, 512, "%s/%s", filename, filepart); - filename = fnamebuf; - } - /* Rewrite zone list */ result = isc_stdio_open(filename, "r", &ifp); if (ifp != NULL && result == ISC_R_SUCCESS) { @@ -7063,14 +6933,26 @@ ns_server_del_zone(ns_server_t *server, char *args) { break; p = buf; } - } - /* Just spool the remainder of the file out */ - while ((n = fread(buf, 1, 1024, ifp)) > 0U) - fwrite(buf, 1, n, ofp); + /* Just spool the remainder of the file out */ + result = isc_stdio_read(buf, 1, 1024, ifp, &n); + while (n > 0) { + if (result == ISC_R_EOF) + result = ISC_R_SUCCESS; + CHECK(result); + isc_stdio_write(buf, 1, n, ofp, NULL); + result = isc_stdio_read(buf, 1, 1024, ifp, &n); + } - /* Move temporary into place */ - CHECK(isc_file_rename(tmpname, filename)); + /* Move temporary into place */ + CHECK(isc_file_rename(tmpname, view->new_zone_file)); + } else { + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_WARNING, + "deleted zone %s was missing from " + "new zone file", zonename); + goto cleanup; + } } /* Stop answering for this zone */ @@ -7101,3 +6983,25 @@ ns_server_del_zone(ns_server_t *server, char *args) { return (result); } + +static void +cfgctx_destroy(void **cfgp) { + struct cfg_context *cfg; + isc_mem_t *mctx; + + REQUIRE(cfgp != NULL && *cfgp != NULL); + cfg = *cfgp; + mctx = cfg->mctx; + cfg->mctx = NULL; + + if (cfg->parser != NULL) { + if (cfg->config != NULL) + cfg_obj_destroy(cfg->parser, &cfg->config); + cfg_parser_destroy(&cfg->parser); + } + cfg_aclconfctx_clear(&cfg->actx); + + isc_mem_put(mctx, cfg, sizeof(*cfg)); + isc_mem_detach(&mctx); + *cfgp = NULL; +} diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c index 2ef0f17640..277b0c78d6 100644 --- a/bin/named/zoneconf.c +++ b/bin/named/zoneconf.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zoneconf.c,v 1.163 2010/07/11 23:46:54 tbox Exp $ */ +/* $Id: zoneconf.c,v 1.164 2010/08/11 18:14:18 each Exp $ */ /*% */ @@ -135,8 +135,11 @@ configure_zone_acl(const cfg_obj_t *zconfig, const cfg_obj_t *vconfig, } /* Check for default ACLs that haven't been parsed yet */ - if (vconfig != NULL) - maps[i++] = cfg_tuple_get(vconfig, "options"); + if (vconfig != NULL) { + const cfg_obj_t *options = cfg_tuple_get(vconfig, "options"); + if (options != NULL) + maps[i++] = options; + } if (config != NULL) { const cfg_obj_t *options = NULL; (void)cfg_map_get(config, "options", &options); diff --git a/bin/tests/db/Makefile.in b/bin/tests/db/Makefile.in index 78c4a93a0c..c18a578f49 100644 --- a/bin/tests/db/Makefile.in +++ b/bin/tests/db/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.32 2009/12/05 23:31:40 each Exp $ +# $Id: Makefile.in,v 1.33 2010/08/11 18:14:18 each Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -28,13 +28,15 @@ CWARNINGS = DNSLIBS = ../../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ ISCLIBS = ../../../lib/isc/libisc.@A@ +ISCCFGLIBS = ../../../lib/isccfg/libisccfg.@A@ DNSDEPLIBS = ../../../lib/dns/libdns.@A@ ISCDEPLIBS = ../../../lib/isc/libisc.@A@ +ISCCFGDEPLIBS = ../../../lib/isccfg/libisccfg.@A@ -DEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS} +DEPLIBS = ${DNSDEPLIBS} ${ISCCFGDEPLIBS} ${ISCDEPLIBS} -LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@ +LIBS = ${DNSLIBS} ${ISCCFGLIBS} ${ISCLIBS} @LIBS@ TLIB = ../../../lib/tests/libt_api.@A@ diff --git a/bin/tests/system/addzone/clean.sh b/bin/tests/system/addzone/clean.sh new file mode 100644 index 0000000000..f6d5595de7 --- /dev/null +++ b/bin/tests/system/addzone/clean.sh @@ -0,0 +1,23 @@ +#!/bin/sh +# +# Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: clean.sh,v 1.2 2010/08/11 18:14:18 each Exp $ + +rm -f dig.out.* +rm -f ns2/named.conf +rm -f */named.memstats +rm -f ns2/*.nzf +rm -f ns2/core* diff --git a/bin/tests/system/addzone/ns2/added.db b/bin/tests/system/addzone/ns2/added.db new file mode 100644 index 0000000000..4c734cb6da --- /dev/null +++ b/bin/tests/system/addzone/ns2/added.db @@ -0,0 +1,31 @@ +; Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") +; +; Permission to use, copy, modify, and/or distribute this software for any +; purpose with or without fee is hereby granted, provided that the above +; copyright notice and this permission notice appear in all copies. +; +; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +; PERFORMANCE OF THIS SOFTWARE. + +; $Id: added.db,v 1.2 2010/08/11 18:14:18 each Exp $ + +$ORIGIN added.example. +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 +ns2 A 10.53.0.2 + MX 10 mail + +a A 10.0.0.1 +mail A 10.0.0.2 diff --git a/bin/tests/system/addzone/ns2/default.nzf.orig b/bin/tests/system/addzone/ns2/default.nzf.orig new file mode 100644 index 0000000000..099f9e4a11 --- /dev/null +++ b/bin/tests/system/addzone/ns2/default.nzf.orig @@ -0,0 +1 @@ +zone previous.example { type master; file "previous.db"; }; diff --git a/bin/tests/system/addzone/ns2/named1.conf b/bin/tests/system/addzone/ns2/named1.conf new file mode 100644 index 0000000000..7717b2a5dd --- /dev/null +++ b/bin/tests/system/addzone/ns2/named1.conf @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: named1.conf,v 1.2 2010/08/11 18:14:19 each Exp $ */ + +controls { /* empty */ }; + +options { + port 5300; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + allow-query { any; }; + recursion no; + allow-new-zones yes; +}; + +include "../../common/controls.conf"; + +zone "." { + type hint; + file "../../common/root.hint"; +}; + +zone "normal.example" { + type master; + file "normal.db"; +}; diff --git a/bin/tests/system/addzone/ns2/named2.conf b/bin/tests/system/addzone/ns2/named2.conf new file mode 100644 index 0000000000..bb4a89e717 --- /dev/null +++ b/bin/tests/system/addzone/ns2/named2.conf @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: named2.conf,v 1.2 2010/08/11 18:14:19 each Exp $ */ + +controls { /* empty */ }; + +include "../../common/controls.conf"; + +options { + port 5300; + pid-file "named.pid"; + listen-on { 10.53.0.2; 10.53.0.4; }; + listen-on-v6 { none; }; + recursion no; +}; + +view internal { + match-clients { 10.53.0.2; }; + allow-new-zones no; + + zone "." { + type hint; + file "../../common/root.hint"; + }; +}; + +view external { + match-clients { any; }; + allow-new-zones yes; + + zone "." { + type hint; + file "../../common/root.hint"; + }; +}; diff --git a/bin/tests/system/addzone/ns2/normal.db b/bin/tests/system/addzone/ns2/normal.db new file mode 100644 index 0000000000..3b52784aa8 --- /dev/null +++ b/bin/tests/system/addzone/ns2/normal.db @@ -0,0 +1,31 @@ +; Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") +; +; Permission to use, copy, modify, and/or distribute this software for any +; purpose with or without fee is hereby granted, provided that the above +; copyright notice and this permission notice appear in all copies. +; +; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +; PERFORMANCE OF THIS SOFTWARE. + +; $Id: normal.db,v 1.2 2010/08/11 18:14:19 each Exp $ + +$ORIGIN normal.example. +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 +ns2 A 10.53.0.2 + MX 10 mail + +a A 10.0.0.1 +mail A 10.0.0.2 diff --git a/bin/tests/system/addzone/ns2/previous.db b/bin/tests/system/addzone/ns2/previous.db new file mode 100644 index 0000000000..106216cb5f --- /dev/null +++ b/bin/tests/system/addzone/ns2/previous.db @@ -0,0 +1,31 @@ +; Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") +; +; Permission to use, copy, modify, and/or distribute this software for any +; purpose with or without fee is hereby granted, provided that the above +; copyright notice and this permission notice appear in all copies. +; +; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +; PERFORMANCE OF THIS SOFTWARE. + +; $Id: previous.db,v 1.2 2010/08/11 18:14:19 each Exp $ + +$ORIGIN previous.example. +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 +ns2 A 10.53.0.2 + MX 10 mail + +a A 10.0.0.1 +mail A 10.0.0.2 diff --git a/bin/tests/system/addzone/setup.sh b/bin/tests/system/addzone/setup.sh new file mode 100644 index 0000000000..b4ad73bf12 --- /dev/null +++ b/bin/tests/system/addzone/setup.sh @@ -0,0 +1,20 @@ +#!/bin/sh +# +# Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: setup.sh,v 1.2 2010/08/11 18:14:18 each Exp $ + +cp -f ns2/named1.conf ns2/named.conf +cp -f ns2/default.nzf.orig ns2/3bf305731dd26307.nzf diff --git a/bin/tests/system/addzone/tests.sh b/bin/tests/system/addzone/tests.sh new file mode 100644 index 0000000000..20aff4cb2c --- /dev/null +++ b/bin/tests/system/addzone/tests.sh @@ -0,0 +1,122 @@ +#!/bin/sh +# +# Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +# $Id: tests.sh,v 1.2 2010/08/11 18:14:18 each Exp $ + +SYSTEMTESTTOP=.. +. $SYSTEMTESTTOP/conf.sh + +DIGOPTS="+tcp +nosea +nostat +nocmd +norec +noques +noauth +noadd +nostats +dnssec -p 5300" +status=0 +n=0 + +echo "I:checking normally loaded zone ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.2 a.normal.example a > dig.out.ns2.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I:checking previously added zone ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.2 a.previous.example a > dig.out.ns2.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1 +grep '^a.previous.example' dig.out.ns2.$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I:adding new zone ($n)" +ret=0 +$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 addzone 'added.example { type master; file "added.db"; };' 2>&1 | sed 's/^/I:ns2 /' +$DIG $DIGOPTS @10.53.0.2 a.added.example a > dig.out.ns2.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1 +grep '^a.added.example' dig.out.ns2.$n > /dev/null || 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)" +ret=0 +$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 delzone previous.example 2>&1 | sed 's/^/I:ns2 /' +$DIG $DIGOPTS @10.53.0.2 a.previous.example a > dig.out.ns2.$n +grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1 +grep '^a.previous.example' dig.out.ns2.$n > /dev/null && 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)" +ret=0 +$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 delzone added.example 2>&1 | sed 's/^/I:ns2 /' +$DIG $DIGOPTS @10.53.0.2 a.added.example a > dig.out.ns2.$n +grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1 +grep '^a.added.example' dig.out.ns2.$n > /dev/null && ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I:attempt to delete a normally-loaded zone (should fail) ($n)" +ret=0 +$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 delzone normal.example 2>&1 | sed 's/^/I:ns2 /' +$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 '^a.normal.example' dig.out.ns2.$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I:reconfiguring server with multiple views" +rm -f ns2/named.conf +cp -f ns2/named2.conf ns2/named.conf +$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reconfig 2>&1 | sed 's/^/I:ns2 /' +sleep 5 + +echo "I:adding new zone to external view ($n)" +ret=0 +$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 addzone 'added.example in external { type master; file "added.db"; };' 2>&1 | sed 's/^/I:ns2 /' +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.added.example a > dig.out.ns2.int.$n || ret=1 +$DIG $DIGOPTS @10.53.0.4 -b 10.53.0.4 a.added.example a > dig.out.ns2.ext.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.int.$n > /dev/null || ret=1 +grep 'status: NOERROR' dig.out.ns2.ext.$n > /dev/null || ret=1 +grep '^a.added.example' dig.out.ns2.ext.$n > /dev/null || 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)" +ret=0 +$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 delzone 'added.example in external' 2>&1 | sed 's/^/I:ns2 /' +$DIG $DIGOPTS @10.53.0.4 -b 10.53.0.4 a.added.example a > dig.out.ns2.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1 +grep '^a.added.example' dig.out.ns2.$n > /dev/null && ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I:attempting to add zone to internal view (should fail) ($n)" +ret=0 +$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 addzone 'added.example in internal { type master; file "added.db"; };' 2>&1 | sed 's/^/I:ns2 /' +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.added.example a > dig.out.ns2.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I:exit status: $status" +exit $status diff --git a/bin/tests/system/conf.sh.in b/bin/tests/system/conf.sh.in index a431aed230..8b2899d9b6 100644 --- a/bin/tests/system/conf.sh.in +++ b/bin/tests/system/conf.sh.in @@ -15,7 +15,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: conf.sh.in,v 1.49 2010/06/11 01:57:36 marka Exp $ +# $Id: conf.sh.in,v 1.50 2010/08/11 18:14:18 each Exp $ # # Common configuration data for system tests, to be sourced into @@ -51,9 +51,9 @@ PK11DEL="$TOP/bin/pkcs11/pkcs11-destroy -s 0 -p 1234" # The "stress" test is not run by default since it creates enough # load on the machine to make it unusable to other users. # v6synth -SUBDIRS="acl autosign cacheclean checkconf checknames dlv dnssec forward glue - ixfr limits lwresd masterfile masterformat metadata notify nsupdate - pending pkcs11 resolver rrsetorder sortlist smartsign stub tkey +SUBDIRS="acl addzone autosign cacheclean checkconf checknames dlv dnssec + forward glue ixfr limits lwresd masterfile masterformat metadata notify + nsupdate pending pkcs11 resolver rrsetorder sortlist smartsign stub tkey unknown upforwd views xfer xferquota zonechecks" # PERL will be an empty string if no perl interpreter was found. diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml index 6d4fcb5e69..f689b7a4a5 100644 --- a/doc/arm/Bv9ARM-book.xml +++ b/doc/arm/Bv9ARM-book.xml @@ -18,7 +18,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> - + BIND 9 Administrator Reference Manual @@ -1431,6 +1431,65 @@ zone "eng.example.com" { + + addzone + zone + class + view + configuration + + + + Add a zone while the server is running. This + command requires the + allow-new-zones option to be set + to yes. The + configuration string + specified on the command line is the zone + configuration text that would ordinarily be + placed in named.conf. + + + The configuration is saved in a file called + hash.nzf, + where hash is a + cryptographic hash generated from the name of + the view. When named is + restarted, the file will be loaded into the view + configuration, so that zones that were added + can persist after a restart. + + + This sample addzone command + would add the zone example.com + to the default view: + + +$ rndc addzone example.com '{ type master; file "example.com.db"; };' + + + (Note the brackets and semi-colon around the zone + configuration text.) + + + + + + delzone + zone + class + view + + + + Delete a zone while the server is running. + Only zones that were originally added via + rndc addzone can be deleted + in this matter. + + + + @@ -4935,6 +4994,7 @@ badresp:1,adberr:0,findfail:0,valfail:0] check-mx-cname ( warn | fail | ignore ); check-srv-cname ( warn | fail | ignore ); check-sibling yes_or_no; + allow-new-zones { yes_or_no }; allow-notify { address_match_list }; allow-query { address_match_list }; allow-query-on { address_match_list }; @@ -5628,6 +5688,18 @@ options { + + allow-new-zones + + + If yes, then zones can be + added at runtime via rndc addzone + or deleted via rndc delzone. + The default is no. + + + + auth-nxdomain diff --git a/lib/bind9/check.c b/lib/bind9/check.c index d03b070034..a7903b34d2 100644 --- a/lib/bind9/check.c +++ b/lib/bind9/check.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: check.c,v 1.119 2010/06/26 05:30:30 marka Exp $ */ +/* $Id: check.c,v 1.120 2010/08/11 18:14:19 each Exp $ */ /*! \file */ @@ -2101,7 +2101,7 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions, if (tresult != ISC_R_SUCCESS) result = tresult; - cfg_aclconfctx_destroy(&actx); + cfg_aclconfctx_clear(&actx); return (result); } @@ -2346,7 +2346,7 @@ bind9_check_controls(const cfg_obj_t *config, isc_log_t *logctx, result = tresult; } } - cfg_aclconfctx_destroy(&actx); + cfg_aclconfctx_clear(&actx); return (result); } diff --git a/lib/dns/include/dns/view.h b/lib/dns/include/dns/view.h index e0fd7a9bf2..4adfbd2ad4 100644 --- a/lib/dns/include/dns/view.h +++ b/lib/dns/include/dns/view.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: view.h,v 1.125 2010/07/11 00:12:57 each Exp $ */ +/* $Id: view.h,v 1.126 2010/08/11 18:14:19 each Exp $ */ #ifndef DNS_VIEW_H #define DNS_VIEW_H 1 @@ -176,6 +176,14 @@ struct dns_view { dns_viewlist_t * viewlist; dns_zone_t * managed_keys; + +#ifdef BIND9 + /* File in which to store configuration for newly added zones */ + char * new_zone_file; + + void * new_zone_config; + void (*cfg_destroy)(void **); +#endif }; #define DNS_VIEW_MAGIC ISC_MAGIC('V','i','e','w') @@ -994,4 +1002,25 @@ dns_view_untrust(dns_view_t *view, dns_name_t *keyname, * \li 'dnskey' is valid. */ +void +dns_view_setnewzones(dns_view_t *view, isc_boolean_t allow, void *cfgctx, + void (*cfg_destroy)(void **)); +/*%< + * Set whether or not to allow zones to be created or deleted at runtime. + * + * If 'allow' is ISC_TRUE, determines the filename into which new zone + * configuration will be written. Preserves the configuration context + * (a pointer to which is passed in 'cfgctx') for use when parsing new + * zone configuration. 'cfg_destroy' points to a callback routine to + * destroy the configuration context when the view is destroyed. (This + * roundabout method is used in order to avoid libdns having a dependency + * on libisccfg and libbind9.) + * + * If 'allow' is ISC_FALSE, removes any existing references to + * configuration context and frees any memory. + * + * Requires: + * \li 'view' is valid. + */ + #endif /* DNS_VIEW_H */ diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h index 2994e53f0f..5357649455 100644 --- a/lib/dns/include/dns/zone.h +++ b/lib/dns/include/dns/zone.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.h,v 1.175 2009/12/29 22:20:33 marka Exp $ */ +/* $Id: zone.h,v 1.176 2010/08/11 18:14:19 each Exp $ */ #ifndef DNS_ZONE_H #define DNS_ZONE_H 1 @@ -1802,6 +1802,25 @@ dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version, * ISC_R_SUCCESS if there were no errors examining the zone contents. */ +void +dns_zone_setadded(dns_zone_t *zone, isc_boolean_t added); +/*% + * Sets the value of zone->added, which should be ISC_TRUE for + * zones that were originally added by "rndc addzone". + * + * Requires: + * \li 'zone' to be valid. + */ + +isc_boolean_t +dns_zone_getadded(dns_zone_t *zone); +/*% + * Returns ISC_TRUE if the zone was originally added at runtime + * using "rndc addzone". + * + * Requires: + * \li 'zone' to be valid. + */ ISC_LANG_ENDDECLS diff --git a/lib/dns/view.c b/lib/dns/view.c index 8b9d1e93cd..f5c8c69a7a 100644 --- a/lib/dns/view.c +++ b/lib/dns/view.c @@ -15,13 +15,14 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: view.c,v 1.166 2010/07/11 00:12:57 each Exp $ */ +/* $Id: view.c,v 1.167 2010/08/11 18:14:19 each Exp $ */ /*! \file */ #include #include +#include #include #include /* Required for HP/UX (and others?) */ #include @@ -183,8 +184,11 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, view->v4_aaaa_acl = NULL; dns_fixedname_init(&view->dlv_fixed); view->managed_keys = NULL; - #ifdef BIND9 + view->new_zone_file = NULL; + view->new_zone_config = NULL; + view->cfg_destroy = NULL; + result = dns_order_create(view->mctx, &view->order); if (result != ISC_R_SUCCESS) goto cleanup_dynkeys; @@ -366,6 +370,7 @@ destroy(dns_view_t *view) { #ifdef BIND9 if (view->managed_keys != NULL) dns_zone_detach(&view->managed_keys); + dns_view_setnewzones(view, ISC_FALSE, NULL, NULL); #endif dns_fwdtable_destroy(&view->fwdtable); dns_aclenv_destroy(&view->aclenv); @@ -1620,3 +1625,39 @@ dns_view_untrust(dns_view_t *view, dns_name_t *keyname, dst_key_free(&key); } +#define NZF ".nzf" + +void +dns_view_setnewzones(dns_view_t *view, isc_boolean_t allow, void *cfgctx, + void (*cfg_destroy)(void **)) +{ + REQUIRE(DNS_VIEW_VALID(view)); + REQUIRE((cfgctx != NULL && cfg_destroy != NULL) || !allow); + +#ifdef BIND9 + if (allow) { + char buffer[ISC_SHA256_DIGESTSTRINGLENGTH + sizeof(NZF)]; + isc_sha256_data((void *)view->name, strlen(view->name), buffer); + /* Truncate the hash at 16 chars; full length is overkill */ + isc_string_printf(buffer + 16, sizeof(NZF), "%s", NZF); + view->new_zone_file = isc_mem_strdup(view->mctx, buffer); + view->new_zone_config = cfgctx; + view->cfg_destroy = cfg_destroy; + } else { + if (view->new_zone_file != NULL) { + isc_mem_free(view->mctx, view->new_zone_file); + view->new_zone_file = NULL; + } + + if (view->new_zone_config != NULL) { + view->cfg_destroy(&view->new_zone_config); + view->cfg_destroy = NULL; + } + } +#else + UNUSED(allow); + UNUSED(parser); + UNUSED(cfgctx); + UNUSED(cfg_destroy); +#endif +} diff --git a/lib/dns/zone.c b/lib/dns/zone.c index a2cd3724a9..d8d78b84f8 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.c,v 1.569 2010/06/02 00:58:54 marka Exp $ */ +/* $Id: zone.c,v 1.570 2010/08/11 18:14:19 each Exp $ */ /*! \file */ @@ -317,6 +317,11 @@ struct dns_zone { * Autosigning/key-maintenance options */ isc_uint32_t keyopts; + + /*% + * True if added by "rndc addzone" + */ + isc_boolean_t added; }; #define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0)) @@ -827,6 +832,7 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) { zone->signatures = 10; zone->nodes = 100; zone->privatetype = (dns_rdatatype_t)0xffffU; + zone->added = ISC_FALSE; zone->magic = ZONE_MAGIC; @@ -13992,3 +13998,17 @@ dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version, dns_db_detachnode(db, &node); return (result); } + +void +dns_zone_setadded(dns_zone_t *zone, isc_boolean_t added) { + REQUIRE(DNS_ZONE_VALID(zone)); + LOCK_ZONE(zone); + zone->added = added; + UNLOCK_ZONE(zone); +} + +isc_boolean_t +dns_zone_getadded(dns_zone_t *zone) { + REQUIRE(DNS_ZONE_VALID(zone)); + return (zone->added); +} diff --git a/lib/isccfg/aclconf.c b/lib/isccfg/aclconf.c index 0a240e987c..01fd9a4145 100644 --- a/lib/isccfg/aclconf.c +++ b/lib/isccfg/aclconf.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: aclconf.c,v 1.27 2009/10/01 23:48:08 tbox Exp $ */ +/* $Id: aclconf.c,v 1.28 2010/08/11 18:14:20 each Exp $ */ #include @@ -39,7 +39,7 @@ cfg_aclconfctx_init(cfg_aclconfctx_t *ctx) { } void -cfg_aclconfctx_destroy(cfg_aclconfctx_t *ctx) { +cfg_aclconfctx_clear(cfg_aclconfctx_t *ctx) { dns_acl_t *dacl, *next; for (dacl = ISC_LIST_HEAD(ctx->named_acl_cache); @@ -51,6 +51,23 @@ cfg_aclconfctx_destroy(cfg_aclconfctx_t *ctx) { } } +void +cfg_aclconfctx_clone(cfg_aclconfctx_t *src, cfg_aclconfctx_t *dest) { + dns_acl_t *dacl, *next; + REQUIRE(src != NULL && dest != NULL); + + cfg_aclconfctx_init(dest); + for (dacl = ISC_LIST_HEAD(src->named_acl_cache); + dacl != NULL; + dacl = next) + { + dns_acl_t *copy; + next = ISC_LIST_NEXT(dacl, nextincache); + dns_acl_attach(dacl, ©); + ISC_LIST_APPEND(dest->named_acl_cache, copy, nextincache); + } +} + /* * Find the definition of the named acl whose name is "name". */ diff --git a/lib/isccfg/include/isccfg/aclconf.h b/lib/isccfg/include/isccfg/aclconf.h index 7ad4351f34..43a990888f 100644 --- a/lib/isccfg/include/isccfg/aclconf.h +++ b/lib/isccfg/include/isccfg/aclconf.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: aclconf.h,v 1.10 2007/10/12 04:17:18 each Exp $ */ +/* $Id: aclconf.h,v 1.11 2010/08/11 18:14:20 each Exp $ */ #ifndef ISCCFG_ACLCONF_H #define ISCCFG_ACLCONF_H 1 @@ -44,9 +44,15 @@ cfg_aclconfctx_init(cfg_aclconfctx_t *ctx); */ void -cfg_aclconfctx_destroy(cfg_aclconfctx_t *ctx); +cfg_aclconfctx_clone(cfg_aclconfctx_t *src, cfg_aclconfctx_t *dest); /* - * Destroy an ACL configuration context. + * Copy the contents of one ACL configuration context into another. + */ + +void +cfg_aclconfctx_clear(cfg_aclconfctx_t *ctx); +/* + * Clear the contents of an ACL configuration context. */ isc_result_t diff --git a/lib/isccfg/include/isccfg/cfg.h b/lib/isccfg/include/isccfg/cfg.h index d0ed94b8f6..91d3843bbb 100644 --- a/lib/isccfg/include/isccfg/cfg.h +++ b/lib/isccfg/include/isccfg/cfg.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: cfg.h,v 1.44 2007/10/12 04:17:18 each Exp $ */ +/* $Id: cfg.h,v 1.45 2010/08/11 18:14:20 each Exp $ */ #ifndef ISCCFG_CFG_H #define ISCCFG_CFG_H 1 @@ -35,6 +35,7 @@ #include #include +#include #include #include @@ -83,6 +84,12 @@ typedef isc_result_t ISC_LANG_BEGINDECLS +void +cfg_parser_attach(cfg_parser_t *src, cfg_parser_t **dest); +/*%< + * Reference a parser object. + */ + isc_result_t cfg_parser_create(isc_mem_t *mctx, isc_log_t *lctx, cfg_parser_t **ret); /*%< @@ -140,7 +147,8 @@ cfg_parse_buffer(cfg_parser_t *pctx, isc_buffer_t *buffer, void cfg_parser_destroy(cfg_parser_t **pctxp); /*%< - * Destroy a configuration parser. + * Remove a reference to a configuration parser; destroy it if there are no + * more references. */ isc_boolean_t @@ -355,7 +363,7 @@ cfg_list_length(const cfg_obj_t *obj, isc_boolean_t recurse); * all contained lists. */ -const cfg_obj_t * +cfg_obj_t * cfg_listelt_value(const cfg_listelt_t *elt); /*%< * Returns the configuration object associated with cfg_listelt_t. @@ -392,14 +400,22 @@ cfg_obj_istype(const cfg_obj_t *obj, const cfg_type_t *type); * Return true iff 'obj' is of type 'type'. */ -void cfg_obj_destroy(cfg_parser_t *pctx, cfg_obj_t **obj); +void +cfg_obj_attach(cfg_obj_t *src, cfg_obj_t **dest); +/*%< + * Reference a configuration object. + */ + +void +cfg_obj_destroy(cfg_parser_t *pctx, cfg_obj_t **obj); /*%< - * Destroy a configuration object. + * Delete a reference to a configuration object; destroy the object if + * there are no more references. */ void cfg_obj_log(const cfg_obj_t *obj, isc_log_t *lctx, int level, - const char *fmt, ...) + const char *fmt, ...) ISC_FORMAT_PRINTF(4, 5); /*%< * Log a message concerning configuration object 'obj' to the logging diff --git a/lib/isccfg/include/isccfg/grammar.h b/lib/isccfg/include/isccfg/grammar.h index f28ba6e72e..93ebe8dee4 100644 --- a/lib/isccfg/include/isccfg/grammar.h +++ b/lib/isccfg/include/isccfg/grammar.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: grammar.h,v 1.21 2010/06/23 23:46:58 tbox Exp $ */ +/* $Id: grammar.h,v 1.22 2010/08/11 18:14:20 each Exp $ */ #ifndef ISCCFG_GRAMMAR_H #define ISCCFG_GRAMMAR_H 1 @@ -159,6 +159,7 @@ struct cfg_obj { isc_sockaddr_t sockaddr; cfg_netprefix_t netprefix; } value; + isc_refcount_t references; /*%< reference counter */ const char * file; unsigned int line; }; @@ -218,6 +219,9 @@ struct cfg_parser { */ unsigned int flags; + /*%< Reference counter */ + isc_refcount_t references; + cfg_parsecallback_t callback; void *callbackarg; }; diff --git a/lib/isccfg/include/isccfg/namedconf.h b/lib/isccfg/include/isccfg/namedconf.h index 87fe693b4e..507da06587 100644 --- a/lib/isccfg/include/isccfg/namedconf.h +++ b/lib/isccfg/include/isccfg/namedconf.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: namedconf.h,v 1.17 2010/07/11 23:46:54 tbox Exp $ */ +/* $Id: namedconf.h,v 1.18 2010/08/11 18:14:20 each Exp $ */ #ifndef ISCCFG_NAMEDCONF_H #define ISCCFG_NAMEDCONF_H 1 @@ -36,6 +36,9 @@ LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_namedconf; LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_bindkeys; /*%< A bind.keys file. */ +LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_newzones; +/*%< A new-zones file (for zones added by 'rndc addzone'). */ + LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_addzoneconf; /*%< A single zone passed via the addzone rndc command. */ diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index 247a10f1a0..6f680bde41 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: namedconf.c,v 1.122 2010/07/11 23:46:54 tbox Exp $ */ +/* $Id: namedconf.c,v 1.123 2010/08/11 18:14:20 each Exp $ */ /*! \file */ @@ -101,7 +101,6 @@ static cfg_type_t cfg_type_negated; static cfg_type_t cfg_type_notifytype; static cfg_type_t cfg_type_optional_allow; static cfg_type_t cfg_type_optional_class; -static cfg_type_t cfg_type_optional_qstring; static cfg_type_t cfg_type_optional_facility; static cfg_type_t cfg_type_optional_keyref; static cfg_type_t cfg_type_optional_port; @@ -832,8 +831,6 @@ bindkeys_clauses[] = { */ static cfg_clausedef_t options_clauses[] = { - { "use-v4-udp-ports", &cfg_type_bracketed_portlist, 0 }, - { "use-v6-udp-ports", &cfg_type_bracketed_portlist, 0 }, { "avoid-v4-udp-ports", &cfg_type_bracketed_portlist, 0 }, { "avoid-v6-udp-ports", &cfg_type_bracketed_portlist, 0 }, { "bindkeys-file", &cfg_type_qstring, 0 }, @@ -848,6 +845,7 @@ options_clauses[] = { { "dump-file", &cfg_type_qstring, 0 }, { "fake-iquery", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE }, { "files", &cfg_type_size, 0 }, + { "flush-zones-on-shutdown", &cfg_type_boolean, 0 }, { "has-old-clients", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE }, { "heartbeat-interval", &cfg_type_uint32, 0 }, { "host-statistics", &cfg_type_boolean, CFG_CLAUSEFLAG_NOTIMP }, @@ -887,8 +885,9 @@ options_clauses[] = { { "treat-cr-as-space", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE }, { "use-id-pool", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE }, { "use-ixfr", &cfg_type_boolean, 0 }, + { "use-v4-udp-ports", &cfg_type_bracketed_portlist, 0 }, + { "use-v6-udp-ports", &cfg_type_bracketed_portlist, 0 }, { "version", &cfg_type_qstringornone, 0 }, - { "flush-zones-on-shutdown", &cfg_type_boolean, 0 }, { NULL, NULL, 0 } }; @@ -996,6 +995,7 @@ view_clauses[] = { { "acache-enable", &cfg_type_boolean, 0 }, { "additional-from-auth", &cfg_type_boolean, 0 }, { "additional-from-cache", &cfg_type_boolean, 0 }, + { "allow-new-zones", &cfg_type_boolean, 0 }, { "allow-query-cache", &cfg_type_bracketed_aml, 0 }, { "allow-query-cache-on", &cfg_type_bracketed_aml, 0 }, { "allow-recursion", &cfg_type_bracketed_aml, 0 }, @@ -1058,7 +1058,6 @@ view_clauses[] = { { "transfer-format", &cfg_type_transferformat, 0 }, { "use-queryport-pool", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE }, { "zero-no-soa-ttl-cache", &cfg_type_boolean, 0 }, - { "new-zone-file", &cfg_type_qstringornone, 0 }, #ifdef ALLOW_FILTER_AAAA_ON_V4 { "filter-aaaa", &cfg_type_bracketed_aml, 0 }, { "filter-aaaa-on-v4", &cfg_type_v4_aaaa, 0 }, @@ -1236,6 +1235,24 @@ LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_bindkeys = { &cfg_rep_map, bindkeys_clausesets }; +/*% The new-zone-file syntax (for zones added by 'rndc addzone') */ +static cfg_clausedef_t +newzones_clauses[] = { + { "zone", &cfg_type_zone, CFG_CLAUSEFLAG_MULTI }, + { NULL, NULL, 0 } +}; + +static cfg_clausedef_t * +newzones_clausesets[] = { + newzones_clauses, + NULL +}; + +LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_newzones = { + "newzones", cfg_parse_mapbody, cfg_print_mapbody, cfg_doc_mapbody, + &cfg_rep_map, newzones_clausesets +}; + /*% The "options" statement syntax. */ static cfg_clausedef_t * @@ -1402,11 +1419,7 @@ static cfg_type_t cfg_type_logging = { * For parsing an 'addzone' statement */ -/*% - * A zone statement. - */ static cfg_tuplefielddef_t addzone_fields[] = { - { "filepart", &cfg_type_optional_qstring, 0 }, { "name", &cfg_type_astring, 0 }, { "class", &cfg_type_optional_class, 0 }, { "view", &cfg_type_optional_class, 0 }, @@ -1836,30 +1849,6 @@ static cfg_type_t cfg_type_optional_class = { NULL, NULL }; -/*% - * An optional string, distinguished by being in quotes - */ -static isc_result_t -parse_optional_qstr(cfg_parser_t *pctx, const cfg_type_t *type, - cfg_obj_t **ret) -{ - isc_result_t result; - UNUSED(type); - CHECK(cfg_peektoken(pctx, CFG_LEXOPT_QSTRING)); - if (pctx->token.type == isc_tokentype_qstring) - CHECK(cfg_parse_obj(pctx, &cfg_type_qstring, ret)); - else - CHECK(cfg_parse_obj(pctx, &cfg_type_void, ret)); - cleanup: - return (result); -} - - -static cfg_type_t cfg_type_optional_qstring = { - "optional_quoted_string", parse_optional_qstr, NULL, cfg_doc_terminal, - NULL, NULL -}; - static isc_result_t parse_querysource(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { isc_result_t result; diff --git a/lib/isccfg/parser.c b/lib/isccfg/parser.c index 85f282c5dd..2c9aca1507 100644 --- a/lib/isccfg/parser.c +++ b/lib/isccfg/parser.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: parser.c,v 1.134 2010/06/23 23:46:58 tbox Exp $ */ +/* $Id: parser.c,v 1.135 2010/08/11 18:14:20 each Exp $ */ /*! \file */ @@ -387,6 +387,12 @@ cfg_parser_create(isc_mem_t *mctx, isc_log_t *lctx, cfg_parser_t **ret) { if (pctx == NULL) return (ISC_R_NOMEMORY); + result = isc_refcount_init(&pctx->references, 1); + if (result != ISC_R_SUCCESS) { + isc_mem_put(mctx, pctx, sizeof(*pctx)); + return (result); + } + pctx->mctx = mctx; pctx->lctx = lctx; pctx->lexer = NULL; @@ -526,18 +532,31 @@ cfg_parse_buffer(cfg_parser_t *pctx, isc_buffer_t *buffer, return (result); } +void +cfg_parser_attach(cfg_parser_t *src, cfg_parser_t **dest) { + REQUIRE(src != NULL); + REQUIRE(dest != NULL && *dest == NULL); + isc_refcount_increment(&src->references, NULL); + *dest = src; +} + void cfg_parser_destroy(cfg_parser_t **pctxp) { cfg_parser_t *pctx = *pctxp; - isc_lex_destroy(&pctx->lexer); - /* - * Cleaning up open_files does not - * close the files; that was already done - * by closing the lexer. - */ - CLEANUP_OBJ(pctx->open_files); - CLEANUP_OBJ(pctx->closed_files); - isc_mem_put(pctx->mctx, pctx, sizeof(*pctx)); + unsigned int refs; + + isc_refcount_decrement(&pctx->references, &refs); + if (refs == 0) { + isc_lex_destroy(&pctx->lexer); + /* + * Cleaning up open_files does not + * close the files; that was already done + * by closing the lexer. + */ + CLEANUP_OBJ(pctx->open_files); + CLEANUP_OBJ(pctx->closed_files); + isc_mem_put(pctx->mctx, pctx, sizeof(*pctx)); + } *pctxp = NULL; } @@ -1133,7 +1152,7 @@ cfg_list_length(const cfg_obj_t *obj, isc_boolean_t recurse) { return (count); } -const cfg_obj_t * +cfg_obj_t * cfg_listelt_value(const cfg_listelt_t *elt) { REQUIRE(elt != NULL); return (elt->obj); @@ -2315,6 +2334,7 @@ cfg_obj_line(const cfg_obj_t *obj) { isc_result_t cfg_create_obj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { + isc_result_t result; cfg_obj_t *obj; obj = isc_mem_get(pctx->mctx, sizeof(cfg_obj_t)); @@ -2323,10 +2343,16 @@ cfg_create_obj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { obj->type = type; obj->file = current_file(pctx); obj->line = pctx->line; + result = isc_refcount_init(&obj->references, 1); + if (result != ISC_R_SUCCESS) { + isc_mem_put(pctx->mctx, obj, sizeof(cfg_obj_t)); + return (result); + } *ret = obj; return (ISC_R_SUCCESS); } + static void map_symtabitem_destroy(char *key, unsigned int type, isc_symvalue_t symval, void *userarg) @@ -2380,11 +2406,25 @@ cfg_obj_istype(const cfg_obj_t *obj, const cfg_type_t *type) { void cfg_obj_destroy(cfg_parser_t *pctx, cfg_obj_t **objp) { cfg_obj_t *obj = *objp; - obj->type->rep->free(pctx, obj); - isc_mem_put(pctx->mctx, obj, sizeof(cfg_obj_t)); + unsigned int refs; + + isc_refcount_decrement(&obj->references, &refs); + if (refs == 0) { + obj->type->rep->free(pctx, obj); + isc_refcount_destroy(&obj->references); + isc_mem_put(pctx->mctx, obj, sizeof(cfg_obj_t)); + } *objp = NULL; } +void +cfg_obj_attach(cfg_obj_t *src, cfg_obj_t **dest) { + REQUIRE(src != NULL); + REQUIRE(dest != NULL && *dest == NULL); + isc_refcount_increment(&src->references, NULL); + *dest = src; +} + static void free_noop(cfg_parser_t *pctx, cfg_obj_t *obj) { UNUSED(pctx); diff --git a/lib/isccfg/win32/libisccfg.def b/lib/isccfg/win32/libisccfg.def index a06232b806..3afe090c48 100644 --- a/lib/isccfg/win32/libisccfg.def +++ b/lib/isccfg/win32/libisccfg.def @@ -18,6 +18,7 @@ cfg_obj_assockaddr cfg_obj_asstring cfg_obj_asuint32 cfg_obj_asuint64 +cfg_obj_attach cfg_obj_destroy cfg_obj_file cfg_obj_isboolean -- GitLab