]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
[master] 4754. [bug] dns_zone_setview needs a two stage commit to properly
authorEvan Hunt <each@isc.org>
Thu, 5 Oct 2017 06:44:08 +0000 (23:44 -0700)
committerEvan Hunt <each@isc.org>
Thu, 5 Oct 2017 06:44:15 +0000 (23:44 -0700)
                        handle errors. [RT #45841]

16 files changed:
CHANGES
bin/named/server.c
bin/named/unix/dlz_dlopen_driver.c
bin/tests/system/addzone/clean.sh
bin/tests/system/addzone/ns3/named1.conf [new file with mode: 0644]
bin/tests/system/addzone/ns3/named2.conf [moved from bin/tests/system/addzone/ns3/named.conf with 80% similarity]
bin/tests/system/addzone/setup.sh
bin/tests/system/addzone/tests.sh
doc/arm/notes.xml
lib/dns/include/dns/view.h
lib/dns/include/dns/zone.h
lib/dns/include/dns/zt.h
lib/dns/view.c
lib/dns/win32/libdns.def.in
lib/dns/zone.c
lib/dns/zt.c

diff --git a/CHANGES b/CHANGES
index 7f790ee078228ab1f6a5bbd77d59a00a0c097af9..6205c7c9a80332eabe61150f6c6267bc63f265a0 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+4754.  [bug]           dns_zone_setview needs a two stage commit to properly
+                       handle errors. [RT #45841]
+
 4753.  [contrib]       Software obtainable from known upstream locations
                        (i.e., zkt, nslint, query-loc) has been removed.
                        Links to these and other packages can be found at
index 1ff620434e4daa600d43d165bb2e94f0b6a18aba..d5bf21105f92be82579247e5ad8cdca77dc0e192 100644 (file)
@@ -7112,6 +7112,59 @@ setup_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
        return (result);
 }
 
+static void
+configure_zone_setviewcommit(isc_result_t result, const cfg_obj_t *zconfig,
+                            dns_view_t *view)
+{
+       const char *zname;
+       dns_fixedname_t fixorigin;
+       dns_name_t *origin;
+       isc_result_t result2;
+       dns_view_t *pview = NULL;
+       dns_zone_t *zone = NULL;
+       dns_zone_t *raw = NULL;
+
+       zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
+       dns_fixedname_init(&fixorigin);
+       origin = dns_fixedname_name(&fixorigin);
+
+       result2 = dns_name_fromstring(origin, zname, 0, NULL);
+       if (result2 != ISC_R_SUCCESS) {
+               return;
+       }
+
+       result2 = dns_viewlist_find(&named_g_server->viewlist, view->name,
+                                   view->rdclass, &pview);
+       if (result2 != ISC_R_SUCCESS) {
+               return;
+       }
+
+       result2 = dns_view_findzone(pview, origin, &zone);
+       if (result2 != ISC_R_SUCCESS) {
+               dns_view_detach(&pview);
+               return;
+       }
+
+       dns_zone_getraw(zone, &raw);
+
+       if (result == ISC_R_SUCCESS) {
+               dns_zone_setviewcommit(zone);
+               if (raw != NULL)
+                       dns_zone_setviewcommit(raw);
+       } else {
+               dns_zone_setviewrevert(zone);
+               if (raw != NULL)
+                       dns_zone_setviewrevert(raw);
+       }
+
+       if (raw != NULL) {
+               dns_zone_detach(&raw);
+       }
+
+       dns_zone_detach(&zone);
+       dns_view_detach(&pview);
+}
+
 #ifndef HAVE_LMDB
 
 static isc_result_t
@@ -7124,8 +7177,9 @@ configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
        const cfg_listelt_t *element;
 
        nzctx = view->new_zone_config;
-       if (nzctx == NULL || nzctx->nzf_config == NULL)
+       if (nzctx == NULL || nzctx->nzf_config == NULL) {
                return (ISC_R_SUCCESS);
+       }
 
        isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
                      NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
@@ -7148,6 +7202,14 @@ configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
        result = ISC_R_SUCCESS;
 
  cleanup:
+       for (element = cfg_list_first(zonelist);
+            element != NULL;
+            element = cfg_list_next(element))
+       {
+               const cfg_obj_t *zconfig = cfg_listelt_value(element);
+               configure_zone_setviewcommit(result, zconfig, view);
+       }
+
        return (result);
 }
 
@@ -7189,8 +7251,9 @@ data_to_cfg(dns_view_t *view, MDB_val *key, MDB_val *data,
        /* zone zonename { config; }; */
        result = isc_buffer_reserve(text, 5 + zone_name_len + 1 +
                                    zone_config_len + 2);
-       if (result != ISC_R_SUCCESS)
+       if (result != ISC_R_SUCCESS) {
                goto cleanup;
+       }
 
        putstr(text, "zone ");
        putmem(text, (const void *) zone_name, zone_name_len);
@@ -7216,8 +7279,9 @@ data_to_cfg(dns_view_t *view, MDB_val *key, MDB_val *data,
        result = ISC_R_SUCCESS;
 
  cleanup:
-       if (zoneconf != NULL)
+       if (zoneconf != NULL) {
                cfg_obj_destroy(named_g_addparser, &zoneconf);
+       }
 
        return (result);
 }
@@ -7235,13 +7299,13 @@ configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
        MDB_dbi dbi;
        MDB_val key, data;
 
-       if (view->new_zone_config == NULL)
+       if (view->new_zone_config == NULL) {
                return (ISC_R_SUCCESS);
+       }
 
        result = nzd_open(view, MDB_RDONLY, &txn, &dbi);
        if (result != ISC_R_SUCCESS) {
-               result = ISC_R_SUCCESS;
-               goto cleanup;
+               return (ISC_R_SUCCESS);
        }
 
        isc_log_write(named_g_lctx,
@@ -7261,12 +7325,14 @@ configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
                const cfg_obj_t *zoneobj = NULL;
 
                result = data_to_cfg(view, &key, &data, &text, &zoneconf);
-               if (result != ISC_R_SUCCESS)
+               if (result != ISC_R_SUCCESS) {
                        goto cleanup;
+               }
 
                CHECK(cfg_map_get(zoneconf, "zone", &zlist));
-               if (!cfg_obj_islist(zlist))
+               if (!cfg_obj_islist(zlist)) {
                        CHECK(ISC_R_FAILURE);
+               }
 
                zoneobj = cfg_listelt_value(cfg_list_first(zlist));
                CHECK(configure_zone(config, zoneobj, vconfig, mctx,
@@ -7279,14 +7345,52 @@ configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
        result = ISC_R_SUCCESS;
 
  cleanup:
-       if (cursor != NULL)
-               mdb_cursor_close(cursor);
-       (void) nzd_close(&txn, ISC_FALSE);
-       if (zoneconf != NULL)
+       if (zoneconf != NULL) {
                cfg_obj_destroy(named_g_addparser, &zoneconf);
-       if (text != NULL)
-               isc_buffer_free(&text);
+       }
+       if (cursor != NULL) {
+               mdb_cursor_close(cursor);
+               cursor = NULL;
+       }
+       if (result != ISC_R_SUCCESS) {
+               status = mdb_cursor_open(txn, dbi, &cursor);
+               if (status != 0) {
+                       goto cleanup2;
+               }
+               while (mdb_cursor_get(cursor, &key, &data, MDB_NEXT) == 0) {
+                       const cfg_obj_t *zlist = NULL;
+                       const cfg_obj_t *zconfig = NULL;
+                       isc_result_t result2;
+
+                       result2 = data_to_cfg(view, &key, &data, &text,
+                                             &zoneconf);
+                       if (result2 != ISC_R_SUCCESS) {
+                               goto cleanup2;
+                       }
+
+                       result2 = cfg_map_get(zoneconf, "zone", &zlist);
+                       if (result2 != ISC_R_SUCCESS) {
+                               goto cleanup2;
+                       }
+
+                       zconfig = cfg_listelt_value(cfg_list_first(zlist));
+                       configure_zone_setviewcommit(result, zconfig, view);
+
+                       cfg_obj_destroy(named_g_addparser, &zoneconf);
+               }
+       }
 
+ cleanup2:
+       if (text != NULL) {
+               isc_buffer_free(&text);
+       }
+       if (zoneconf != NULL) {
+               cfg_obj_destroy(named_g_addparser, &zoneconf);
+       }
+       if (cursor != NULL) {
+               mdb_cursor_close(cursor);
+       }
+       (void) nzd_close(&txn, ISC_FALSE);
        return (result);
 }
 
@@ -7495,8 +7599,9 @@ load_configuration(const char *filename, named_server_t *server,
        ISC_LIST_INIT(altsecrets);
 
        /* Create the ACL configuration context */
-       if (named_g_aclconfctx != NULL)
+       if (named_g_aclconfctx != NULL) {
                cfg_aclconfctx_detach(&named_g_aclconfctx);
+       }
        CHECK(cfg_aclconfctx_create(named_g_mctx, &named_g_aclconfctx));
 
        /*
@@ -7510,10 +7615,11 @@ load_configuration(const char *filename, named_server_t *server,
        if (first_time) {
                result = named_config_parsedefaults(named_g_parser,
                                                    &named_g_config);
-               if (result != ISC_R_SUCCESS)
+               if (result != ISC_R_SUCCESS) {
                        named_main_earlyfatal("unable to load "
                                              "internal defaults: %s",
                                              isc_result_totext(result));
+               }
                RUNTIME_CHECK(cfg_map_get(named_g_config, "options",
                                          &named_g_defaults) == ISC_R_SUCCESS);
        }
@@ -7545,8 +7651,9 @@ load_configuration(const char *filename, named_server_t *server,
        i = 0;
        options = NULL;
        result = cfg_map_get(config, "options", &options);
-       if (result == ISC_R_SUCCESS)
+       if (result == ISC_R_SUCCESS) {
                maps[i++] = options;
+       }
        maps[i++] = named_g_defaults;
        maps[i] = NULL;
 
@@ -7604,8 +7711,9 @@ load_configuration(const char *filename, named_server_t *server,
         * server.
         */
        result = isc_socketmgr_getmaxsockets(named_g_socketmgr, &maxsocks);
-       if (result != ISC_R_SUCCESS)
+       if (result != ISC_R_SUCCESS) {
                maxsocks = 0;
+       }
        result = isc_resource_getcurlimit(isc_resource_openfiles, &nfiles);
        if (result == ISC_R_SUCCESS && (isc_resourcevalue_t)maxsocks > nfiles) {
                isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
@@ -7623,14 +7731,16 @@ load_configuration(const char *filename, named_server_t *server,
        INSIST(result == ISC_R_SUCCESS);
        reserved = cfg_obj_asuint32(obj);
        if (maxsocks != 0) {
-               if (maxsocks < 128U)                    /* Prevent underflow. */
+               if (maxsocks < 128U) {                  /* Prevent underflow. */
                        reserved = 0;
-               else if (reserved > maxsocks - 128U)    /* Minimum UDP space. */
+               } else if (reserved > maxsocks - 128U) { /* Minimum UDP space. */
                        reserved = maxsocks - 128;
+               }
        }
        /* Minimum TCP/stdio space. */
-       if (reserved < 128U)
+       if (reserved < 128U) {
                reserved = 128;
+       }
        if (reserved + 128U > maxsocks && maxsocks != 0) {
                isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
                              NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
@@ -7652,8 +7762,9 @@ load_configuration(const char *filename, named_server_t *server,
                char *dir;
                DE_CONST(cfg_obj_asstring(obj), dir);
                named_geoip_load(dir);
-       } else
+       } else {
                named_geoip_load(NULL);
+       }
        named_g_aclconfctx->geoip = named_g_geoip;
 
        obj = NULL;
@@ -7683,17 +7794,19 @@ load_configuration(const char *filename, named_server_t *server,
                        CHECK(ISC_R_RANGE);
                }
                softquota = server->sctx->recursionquota.max - margin;
-       } else
+       } else {
                softquota = (server->sctx->recursionquota.max * 90) / 100;
+       }
 
        isc_quota_soft(&server->sctx->recursionquota, softquota);
 
        CHECK(configure_view_acl(NULL, config, "blackhole", NULL,
                                 named_g_aclconfctx, named_g_mctx,
                                 &server->sctx->blackholeacl));
-       if (server->sctx->blackholeacl != NULL)
+       if (server->sctx->blackholeacl != NULL) {
                dns_dispatchmgr_setblackhole(named_g_dispatchmgr,
                                             server->sctx->blackholeacl);
+       }
 
        CHECK(configure_view_acl(NULL, config, "keep-response-order", NULL,
                                 named_g_aclconfctx, named_g_mctx,
@@ -7784,15 +7897,15 @@ load_configuration(const char *filename, named_server_t *server,
        avoidv6ports = NULL;
 
        (void)named_config_get(maps, "use-v4-udp-ports", &usev4ports);
-       if (usev4ports != NULL)
+       if (usev4ports != NULL) {
                portset_fromconf(v4portset, usev4ports, ISC_TRUE);
-       else {
+       else {
                CHECKM(isc_net_getudpportrange(AF_INET, &udpport_low,
                                               &udpport_high),
                       "get the default UDP/IPv4 port range");
-               if (udpport_low == udpport_high)
+               if (udpport_low == udpport_high) {
                        isc_portset_add(v4portset, udpport_low);
-               else {
+               else {
                        isc_portset_addrange(v4portset, udpport_low,
                                             udpport_high);
                }
@@ -7804,19 +7917,20 @@ load_configuration(const char *filename, named_server_t *server,
                }
        }
        (void)named_config_get(maps, "avoid-v4-udp-ports", &avoidv4ports);
-       if (avoidv4ports != NULL)
+       if (avoidv4ports != NULL) {
                portset_fromconf(v4portset, avoidv4ports, ISC_FALSE);
+       }
 
        (void)named_config_get(maps, "use-v6-udp-ports", &usev6ports);
-       if (usev6ports != NULL)
+       if (usev6ports != NULL) {
                portset_fromconf(v6portset, usev6ports, ISC_TRUE);
-       else {
+       else {
                CHECKM(isc_net_getudpportrange(AF_INET6, &udpport_low,
                                               &udpport_high),
                       "get the default UDP/IPv6 port range");
-               if (udpport_low == udpport_high)
+               if (udpport_low == udpport_high) {
                        isc_portset_add(v6portset, udpport_low);
-               else {
+               else {
                        isc_portset_addrange(v6portset, udpport_low,
                                             udpport_high);
                }
@@ -7828,8 +7942,9 @@ load_configuration(const char *filename, named_server_t *server,
                }
        }
        (void)named_config_get(maps, "avoid-v6-udp-ports", &avoidv6ports);
-       if (avoidv6ports != NULL)
+       if (avoidv6ports != NULL) {
                portset_fromconf(v6portset, avoidv6ports, ISC_FALSE);
+       }
 
        dns_dispatchmgr_setavailports(named_g_dispatchmgr, v4portset,
                                      v6portset);
@@ -7841,10 +7956,12 @@ load_configuration(const char *filename, named_server_t *server,
        result = named_config_get(maps, "edns-udp-size", &obj);
        INSIST(result == ISC_R_SUCCESS);
        udpsize = cfg_obj_asuint32(obj);
-       if (udpsize < 512)
+       if (udpsize < 512) {
                udpsize = 512;
-       if (udpsize > 4096)
+       }
+       if (udpsize > 4096) {
                udpsize = 4096;
+       }
        server->sctx->udpsize = (isc_uint16_t)udpsize;
 
        /* Set the transfer message size for TCP */
@@ -7852,10 +7969,11 @@ load_configuration(const char *filename, named_server_t *server,
        result = named_config_get(maps, "transfer-message-size", &obj);
        INSIST(result == ISC_R_SUCCESS);
        transfer_message_size = cfg_obj_asuint32(obj);
-       if (transfer_message_size < 512)
+       if (transfer_message_size < 512) {
                transfer_message_size = 512;
-       else if (transfer_message_size > 65535)
+       } else if (transfer_message_size > 65535) {
                transfer_message_size = 65535;
+       }
        server->sctx->transfer_tcp_message_size =
                (isc_uint16_t) transfer_message_size;
 
@@ -7891,10 +8009,11 @@ load_configuration(const char *filename, named_server_t *server,
        /*
         * Determine which port to use for listening for incoming connections.
         */
-       if (named_g_port != 0)
+       if (named_g_port != 0) {
                listen_port = named_g_port;
-       else
+       } else {
                CHECKM(named_config_getport(config, &listen_port), "port");
+       }
 
        /*
         * Determing the default DSCP code point.
@@ -7908,8 +8027,9 @@ load_configuration(const char *filename, named_server_t *server,
        result = named_config_get(maps, "tcp-listen-queue", &obj);
        INSIST(result == ISC_R_SUCCESS);
        backlog = cfg_obj_asuint32(obj);
-       if ((backlog > 0) && (backlog < 10))
+       if ((backlog > 0) && (backlog < 10)) {
                backlog = 10;
+       }
        ns_interfacemgr_setbacklog(server->interfacemgr, backlog);
 
        /*
@@ -7925,8 +8045,9 @@ load_configuration(const char *filename, named_server_t *server,
                 * Even though listen-on is present in the default
                 * configuration, this way is easier.
                 */
-               if (options != NULL)
+               if (options != NULL) {
                        (void)cfg_map_get(options, "listen-on", &clistenon);
+               }
                if (clistenon != NULL) {
                        /* check return code? */
                        (void)ns_listenlist_fromconfig(clistenon, config,
@@ -7953,8 +8074,9 @@ load_configuration(const char *filename, named_server_t *server,
                const cfg_obj_t *clistenon = NULL;
                ns_listenlist_t *listenon = NULL;
 
-               if (options != NULL)
+               if (options != NULL) {
                        (void)cfg_map_get(options, "listen-on-v6", &clistenon);
+               }
                if (clistenon != NULL) {
                        /* check return code? */
                        (void)ns_listenlist_fromconfig(clistenon, config,
@@ -8056,11 +8178,12 @@ load_configuration(const char *filename, named_server_t *server,
         */
        obj = NULL;
        if (named_config_get(maps, "pid-file", &obj) == ISC_R_SUCCESS) {
-               if (cfg_obj_isvoid(obj))
+               if (cfg_obj_isvoid(obj)) {
                        named_os_writepidfile(NULL, first_time);
-               else
+               } else {
                        named_os_writepidfile(cfg_obj_asstring(obj),
                                              first_time);
+               }
        } else {
                named_os_writepidfile(named_g_defaultpidfile, first_time);
        }
@@ -8200,6 +8323,17 @@ load_configuration(const char *filename, named_server_t *server,
        /* Now combine the two viewlists into one */
        ISC_LIST_APPENDLIST(viewlist, builtin_viewlist, link);
 
+       /*
+        * Commit any dns_zone_setview() calls on all zones in the new
+        * view.
+        */
+       for (view = ISC_LIST_HEAD(viewlist);
+            view != NULL;
+            view = ISC_LIST_NEXT(view, link))
+       {
+               dns_view_setviewcommit(view);
+       }
+
        /* Swap our new view list with the production one. */
        tmpviewlist = server->viewlist;
        server->viewlist = viewlist;
@@ -8223,8 +8357,9 @@ load_configuration(const char *filename, named_server_t *server,
                CHECKM(named_tkeyctx_fromconfig(options, named_g_mctx,
                                                named_g_entropy, &t),
                       "configuring TKEY");
-               if (server->sctx->tkeyctx != NULL)
+               if (server->sctx->tkeyctx != NULL) {
                        dns_tkeyctx_destroy(&server->sctx->tkeyctx);
+               }
                server->sctx->tkeyctx = t;
        }
 
@@ -8321,8 +8456,9 @@ load_configuration(const char *filename, named_server_t *server,
        /*
         * Relinquish root privileges.
         */
-       if (first_time)
+       if (first_time) {
                named_os_changeuser();
+       }
 
        /*
         * Check that the working directory is writable.
@@ -8452,18 +8588,22 @@ load_configuration(const char *filename, named_server_t *server,
        obj = NULL;
        if (options != NULL &&
            cfg_map_get(options, "memstatistics", &obj) == ISC_R_SUCCESS)
+       {
                named_g_memstatistics = cfg_obj_asboolean(obj);
-       else
+       } else {
                named_g_memstatistics =
                        ISC_TF((isc_mem_debugging & ISC_MEM_DEBUGRECORD) != 0);
+       }
 
        obj = NULL;
        if (named_config_get(maps, "memstatistics-file", &obj) == ISC_R_SUCCESS)
+       {
                named_main_setmemstats(cfg_obj_asstring(obj));
-       else if (named_g_memstatistics)
+       } else if (named_g_memstatistics) {
                named_main_setmemstats("named.memstats");
-       else
+       } else {
                named_main_setmemstats(NULL);
+       }
 
        obj = NULL;
        result = named_config_get(maps, "statistics-file", &obj);
@@ -8534,18 +8674,19 @@ load_configuration(const char *filename, named_server_t *server,
        obj = NULL;
        result = named_config_get(maps, "cookie-algorithm", &obj);
        INSIST(result == ISC_R_SUCCESS);
-       if (strcasecmp(cfg_obj_asstring(obj), "aes") == 0)
+       if (strcasecmp(cfg_obj_asstring(obj), "aes") == 0) {
 #if defined(HAVE_OPENSSL_AES) || defined(HAVE_OPENSSL_EVP_AES)
                server->sctx->cookiealg = ns_cookiealg_aes;
 #else
                INSIST(0);
 #endif
-       else if (strcasecmp(cfg_obj_asstring(obj), "sha1") == 0)
+       } else if (strcasecmp(cfg_obj_asstring(obj), "sha1") == 0) {
                server->sctx->cookiealg = ns_cookiealg_sha1;
-       else if (strcasecmp(cfg_obj_asstring(obj), "sha256") == 0)
+       } else if (strcasecmp(cfg_obj_asstring(obj), "sha256") == 0) {
                server->sctx->cookiealg = ns_cookiealg_sha256;
-       else
+       } else {
                INSIST(0);
+       }
 
        obj = NULL;
        result = named_config_get(maps, "cookie-secret", &obj);
@@ -8570,7 +8711,9 @@ load_configuration(const char *filename, named_server_t *server,
                                result = isc_hex_decodestring(str, &b);
                                if (result != ISC_R_SUCCESS &&
                                    result != ISC_R_NOSPACE)
+                               {
                                        goto cleanup;
+                               }
                                first = ISC_FALSE;
                        } else {
                                altsecret = isc_mem_get(server->sctx->mctx,
@@ -8583,7 +8726,8 @@ load_configuration(const char *filename, named_server_t *server,
                                                sizeof(altsecret->secret));
                                result = isc_hex_decodestring(str, &b);
                                if (result != ISC_R_SUCCESS &&
-                                   result != ISC_R_NOSPACE) {
+                                   result != ISC_R_NOSPACE)
+                               {
                                        isc_mem_put(server->sctx->mctx,
                                                    altsecret,
                                                    sizeof(*altsecret));
@@ -8624,8 +8768,9 @@ load_configuration(const char *filename, named_server_t *server,
                                             sizeof(server->sctx->secret),
                                             NULL,
                                             0);
-               if (result != ISC_R_SUCCESS)
+               if (result != ISC_R_SUCCESS) {
                        goto cleanup;
+               }
        }
 
        /*
@@ -8656,29 +8801,35 @@ load_configuration(const char *filename, named_server_t *server,
        result = ISC_R_SUCCESS;
 
  cleanup:
-       if (logc != NULL)
+       if (logc != NULL) {
                isc_logconfig_destroy(&logc);
+       }
 
-       if (v4portset != NULL)
+       if (v4portset != NULL) {
                isc_portset_destroy(named_g_mctx, &v4portset);
+       }
 
-       if (v6portset != NULL)
+       if (v6portset != NULL) {
                isc_portset_destroy(named_g_mctx, &v6portset);
+       }
 
        if (conf_parser != NULL) {
-               if (config != NULL)
+               if (config != NULL) {
                        cfg_obj_destroy(conf_parser, &config);
+               }
                cfg_parser_destroy(&conf_parser);
        }
 
        if (bindkeys_parser != NULL) {
-               if (bindkeys != NULL)
+               if (bindkeys != NULL) {
                        cfg_obj_destroy(bindkeys_parser, &bindkeys);
+               }
                cfg_parser_destroy(&bindkeys_parser);
        }
 
-       if (view != NULL)
+       if (view != NULL) {
                dns_view_detach(&view);
+       }
 
        ISC_LIST_APPENDLIST(viewlist, builtin_viewlist, link);
 
@@ -8694,8 +8845,11 @@ load_configuration(const char *filename, named_server_t *server,
                ISC_LIST_UNLINK(viewlist, view, link);
                if (result == ISC_R_SUCCESS &&
                    strcmp(view->name, "_bind") != 0)
+               {
+                       dns_view_setviewrevert(view);
                        (void)dns_zt_apply(view->zonetable, ISC_FALSE,
                                           removed, view);
+               }
                dns_view_detach(&view);
        }
 
@@ -8716,20 +8870,23 @@ load_configuration(const char *filename, named_server_t *server,
         * Adjust the listening interfaces in accordance with the source
         * addresses specified in views and zones.
         */
-       if (isc_net_probeipv6() == ISC_R_SUCCESS)
+       if (isc_net_probeipv6() == ISC_R_SUCCESS) {
                adjust_interfaces(server, named_g_mctx);
+       }
 
        /*
         * Record the time of most recent configuration
         */
        tresult = isc_time_now(&named_g_configtime);
-       if (tresult != ISC_R_SUCCESS)
+       if (tresult != ISC_R_SUCCESS) {
                named_main_earlyfatal("isc_time_now() failed: %s",
                                      isc_result_totext(result));
+       }
 
        /* Relinquish exclusive access to configuration data. */
-       if (exclusive)
+       if (exclusive) {
                isc_task_endexclusive(server->task);
+       }
 
        isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
                      NAMED_LOGMODULE_SERVER, ISC_LOG_DEBUG(1),
index 1039ee22b61ebf96f7ae6439f32fe343f89c8fd3..bbb93eeab61283d6100dc4a5cb5f126f2830cf5e 100644 (file)
@@ -476,7 +476,7 @@ dlopen_dlz_configure(dns_view_t *view, dns_dlzdb_t *dlzdb,
 
 
 /*
- * Check for authority to change a name
+ * Check for authority to change a name.
  */
 static isc_boolean_t
 dlopen_dlz_ssumatch(const char *signer, const char *name, const char *tcpaddr,
@@ -501,7 +501,7 @@ dlopen_dlz_ssumatch(const char *signer, const char *name, const char *tcpaddr,
 
 
 /*
- * Add an rdataset
+ * Add an rdataset.
  */
 static isc_result_t
 dlopen_dlz_addrdataset(const char *name, const char *rdatastr,
@@ -523,7 +523,7 @@ dlopen_dlz_addrdataset(const char *name, const char *rdatastr,
 }
 
 /*
- * Subtract an rdataset
+ * Subtract an rdataset.
  */
 static isc_result_t
 dlopen_dlz_subrdataset(const char *name, const char *rdatastr,
@@ -545,7 +545,7 @@ dlopen_dlz_subrdataset(const char *name, const char *rdatastr,
 }
 
 /*
-  delete a rdataset
+ * Delete a rdataset.
  */
 static isc_result_t
 dlopen_dlz_delrdataset(const char *name, const char *type,
index f47b83cffff940d3b920c4d2489c7aa73cd45d9f..074da01769ee5e02ef17d1adccb01a385b81acc9 100644 (file)
@@ -6,8 +6,6 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-# $Id: clean.sh,v 1.3 2010/09/15 03:32:34 marka Exp $
-
 rm -f dig.out.*
 rm -f rndc.out*
 rm -f showzone.out*
@@ -28,8 +26,11 @@ rm -rf ns2/new-zones
 rm -f ns*/named.lock
 rm -f ns*/named.run
 rm -f ns2/nzf-*
+rm -f ns3/named.conf
+rm -f ns3/*.nzf ns3/*.nzf~
+rm -f ns3/*.nzd ns3/*.nzd-lock
+rm -f ns3/inlineslave.db
 rm -f ns1/redirect.db
 rm -f ns2/redirect.db
 rm -f ns2/redirect.bk
 rm -f ns3/redirect.db
-
diff --git a/bin/tests/system/addzone/ns3/named1.conf b/bin/tests/system/addzone/ns3/named1.conf
new file mode 100644 (file)
index 0000000..433322b
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2013, 2016  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+key rndc_key {
+       secret "1234abcd8765";
+       algorithm hmac-sha256;
+};
+
+controls {
+       inet 10.53.0.3 port 9953 allow { any; } keys { rndc_key; };
+};
+
+options {
+       port 5300;
+       pid-file "named.pid";
+       listen-on { 10.53.0.3; };
+       listen-on-v6 { none; };
+       allow-query { any; };
+       recursion no;
+       allow-new-zones yes;
+};
+
+zone "." {
+       type master;
+       file "redirect.db";
+};
+
+masters "testmaster" {
+       192.5.5.241;
+};
similarity index 80%
rename from bin/tests/system/addzone/ns3/named.conf
rename to bin/tests/system/addzone/ns3/named2.conf
index 638ac6182840edd3136fcf57a33ad5f7962dd437..8617c282eb6e4b4e7a5ab81218d880fdf9d576de 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2013, 2016  Internet Systems Consortium, Inc. ("ISC")
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -20,10 +20,7 @@ options {
        pid-file "named.pid";
        listen-on { 10.53.0.3; };
        listen-on-v6 { none; };
+       allow-query { any; };
        recursion no;
-};
-
-zone "." {
-       type master;
-       file "redirect.db";
+       allow-new-zones yes;
 };
index a07e0788cd81866a13ed124e61a9681418074ed0..9128078fc01758ae0ddafbc600e92e9b530c5b89 100644 (file)
@@ -16,4 +16,8 @@ cp -f ns2/redirect.db.1 ns2/redirect.db
 cp -f ns3/redirect.db.1 ns3/redirect.db
 cp -f ns2/named1.conf ns2/named.conf
 cp -f ns2/default.nzf.in ns2/3bf305731dd26307.nzf
+cp -f ns3/named1.conf ns3/named.conf
+rm -f ns3/*.nzf ns3/*.nzf~
+rm -f ns3/*.nzd ns3/*.nzd-lock
+rm -f ns3/inlineslave.db
 mkdir ns2/new-zones
index b5950bc27eed76d82b09b958a0fe9256435d8115..fe14f9e3b3f2cb355a9dd2cefbb5fb392ef8fe36 100755 (executable)
@@ -661,5 +661,16 @@ n=`expr $n + 1`
 if [ $ret != 0 ]; then echo "I:failed"; fi
 status=`expr $status + $ret`
 
+echo "I:check delzone after reconfig failure ($n)"
+ret=0
+$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 addzone 'inlineslave.example. IN { type slave; file "inlineslave.db"; masterfile-format text; masters { testmaster; }; };' > /dev/null 2>&1 || ret=1
+cp -f ns3/named2.conf ns3/named.conf
+$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 reconfig > /dev/null 2>&1 && ret=1
+sleep 5
+$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 delzone inlineslave.example > /dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
 echo "I:exit status: $status"
 [ $status -eq 0 ] || exit 1
index bc7607fbf21925474673cc65ba4758ea50aa00ab..30025f9fb8345e8266f519d7d8e60cb6037d5dfd 100644 (file)
          validator messages.
        </para>
       </listitem>
+      <listitem>
+       <para>
+         When <command>named</command> was reconfigured, failure of some
+         zones to load correctly could leave the system in an inconsistent
+         state; while generally harmless, this could lead to a crash later
+         when using <command>rndc addzone</command>.  Reconfiguration changes
+         are now fully rolled back in the event of failure. [RT #45841]
+       </para>
+      </listitem>
+      <listitem>
+       <para>
+         Fixed a bug that was introduced in an earlier development
+         release which caused multi-packet AXFR and IXFR messages to fail
+         validation if not all packets contained TSIG records; this
+         caused interoperability problems with some other DNS
+         implementations. [RT #45509]
+       </para>
+      </listitem>
       <listitem>
        <para>
          Multiple <command>cookie-secret</command> clauses are now
index 7d696abdc41db3bd82b03618fd3f1333f7d05327..2a0412038aeb809c5c14cb55b08f7ceab71cfd40 100644 (file)
@@ -1320,6 +1320,27 @@ dns_view_loadnta(dns_view_t *view);
  *\li  'view' to be valid.
  */
 
+void
+dns_view_setviewcommit(dns_view_t *view);
+/*%<
+ * Commit dns_zone_setview() calls previously made for all zones in this
+ * view.
+ *
+ * Requires:
+ *\li  'view' to be valid.
+ */
+
+void
+dns_view_setviewrevert(dns_view_t *view);
+/*%<
+ * Revert dns_zone_setview() calls previously made for all zones in this
+ * view.
+ *
+ * Requires:
+ *\li  'view' to be valid.
+ */
+
+
 ISC_LANG_ENDDECLS
 
 #endif /* DNS_VIEW_H */
index 1bf291d49758a077ea9b7d50e991410d8adffc76..aa08b1f67560fde389f3f2aa2428209740673aab 100644 (file)
@@ -225,6 +225,26 @@ dns_zone_getview(dns_zone_t *zone);
  *\li  'zone' to be a valid zone.
  */
 
+void
+dns_zone_setviewcommit(dns_zone_t *zone);
+/*%<
+ *     Commit the previous view saved internally via dns_zone_setview().
+ *
+ * Require:
+ *\li  'zone' to be a valid zone.
+ */
+
+void
+dns_zone_setviewrevert(dns_zone_t *zone);
+/*%<
+ *     Revert the most recent dns_zone_setview() on this zone,
+ *     restoring the previous view.
+ *
+ * Require:
+ *\li  'zone' to be a valid zone.
+ */
+
+
 isc_result_t
 dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin);
 /*%<
index 3be1539704121a5fec90194a19c0172d588ac148..592a43f4f285e4bc6a84dcec454245fd17cd21be 100644 (file)
@@ -201,6 +201,26 @@ dns_zt_loadspending(dns_zt_t *zt);
  * \li 'zt' to be valid.
  */
 
+void
+dns_zt_setviewcommit(dns_zt_t *zt);
+/*%<
+ * Commit dns_zone_setview() calls previously made for all zones in this
+ * zone table.
+ *
+ * Requires:
+ *\li  'view' to be valid.
+ */
+
+void
+dns_zt_setviewrevert(dns_zt_t *zt);
+/*%<
+ * Revert dns_zone_setview() calls previously made for all zones in this
+ * zone table.
+ *
+ * Requires:
+ *\li  'view' to be valid.
+ */
+
 ISC_LANG_ENDDECLS
 
 #endif /* DNS_ZT_H */
index 8a7a116a8c17be0158ea21aba869d561288c48f8..87420066a69d69812fd3d2ef8a8e67262b3724da 100644 (file)
@@ -1477,7 +1477,7 @@ dns_viewlist_findzone(dns_viewlist_t *list, const dns_name_t *name,
        dns_view_t *view;
        isc_result_t result;
        dns_zone_t *zone1 = NULL, *zone2 = NULL;
-       dns_zone_t **zp = NULL;;
+       dns_zone_t **zp = NULL;
 
        REQUIRE(list != NULL);
        REQUIRE(zonep != NULL && *zonep == NULL);
@@ -2431,3 +2431,47 @@ dns_view_loadnta(dns_view_t *view) {
 
        return (result);
 }
+
+void
+dns_view_setviewcommit(dns_view_t *view) {
+       REQUIRE(DNS_VIEW_VALID(view));
+
+       LOCK(&view->lock);
+
+       if (view->redirect != NULL) {
+               dns_zone_setviewcommit(view->redirect);
+       }
+       if (view->managed_keys != NULL) {
+               dns_zone_setviewcommit(view->managed_keys);
+       }
+       if (view->zonetable != NULL) {
+               dns_zt_setviewcommit(view->zonetable);
+       }
+
+       UNLOCK(&view->lock);
+}
+
+void
+dns_view_setviewrevert(dns_view_t *view) {
+       dns_zt_t *zonetable;
+
+       REQUIRE(DNS_VIEW_VALID(view));
+
+       /*
+        * dns_zt_setviewrevert() attempts to lock this view, so we must
+        * release the lock.
+        */
+       LOCK(&view->lock);
+       if (view->redirect != NULL) {
+               dns_zone_setviewrevert(view->redirect);
+       }
+       if (view->managed_keys != NULL) {
+               dns_zone_setviewrevert(view->managed_keys);
+       }
+       zonetable = view->zonetable;
+       UNLOCK(&view->lock);
+
+       if (zonetable != NULL) {
+               dns_zt_setviewrevert(zonetable);
+       }
+}
index 40a63b539c197ef29f27707c09abc08304ce1e6b..020079569bfebd6bf263381b3f6c1ccdf4dac058 100644 (file)
@@ -1129,6 +1129,8 @@ dns_view_setnewzones
 dns_view_setresquerystats
 dns_view_setresstats
 dns_view_setrootdelonly
+dns_view_setviewcommit
+dns_view_setviewrevert
 dns_view_simplefind
 dns_view_thaw
 dns_view_untrust
@@ -1337,6 +1339,8 @@ dns_zone_settype
 dns_zone_setupdateacl
 dns_zone_setupdatedisabled
 dns_zone_setview
+dns_zone_setviewcommit
+dns_zone_setviewrevert
 dns_zone_setxfracl
 dns_zone_setxfrsource4
 dns_zone_setxfrsource4dscp
@@ -1385,6 +1389,8 @@ dns_zt_freezezones
 dns_zt_load
 dns_zt_loadnew
 dns_zt_mount
+dns_zt_setviewcommit
+dns_zt_setviewrevert
 dns_zt_unmount
 dst_algorithm_supported
 dst_context_adddata
index a769e6a809e98827f0d2af68c5fae597d6648ec4..4d80027bc1428bb79c422c570304b21e4205e1a4 100644 (file)
@@ -301,6 +301,7 @@ struct dns_zone {
        isc_uint32_t            sigvalidityinterval;
        isc_uint32_t            sigresigninginterval;
        dns_view_t              *view;
+       dns_view_t              *prev_view;
        dns_checkmxfunc_t       checkmx;
        dns_checksrvfunc_t      checksrv;
        dns_checknsfunc_t       checkns;
@@ -894,19 +895,22 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
 
        TIME_NOW(&now);
        zone = isc_mem_get(mctx, sizeof(*zone));
-       if (zone == NULL)
+       if (zone == NULL) {
                return (ISC_R_NOMEMORY);
+       }
 
        zone->mctx = NULL;
        isc_mem_attach(mctx, &zone->mctx);
 
        result = isc_mutex_init(&zone->lock);
-       if (result != ISC_R_SUCCESS)
+       if (result != ISC_R_SUCCESS) {
                goto free_zone;
+       }
 
        result = ZONEDB_INITLOCK(&zone->dblock);
-       if (result != ISC_R_SUCCESS)
+       if (result != ISC_R_SUCCESS) {
                goto free_mutex;
+       }
 
        /* XXX MPA check that all elements are initialised */
 #ifdef DNS_ZONE_CHECKLOCK
@@ -916,8 +920,9 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
        zone->zmgr = NULL;
        ISC_LINK_INIT(zone, link);
        result = isc_refcount_init(&zone->erefs, 1);    /* Implicit attach. */
-       if (result != ISC_R_SUCCESS)
+       if (result != ISC_R_SUCCESS) {
                goto free_dblock;
+       }
        zone->irefs = 0;
        dns_name_init(&zone->origin, NULL);
        zone->strnamerd = NULL;
@@ -1014,6 +1019,7 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
        zone->sigvalidityinterval = 30 * 24 * 3600;
        zone->sigresigninginterval = 7 * 24 * 3600;
        zone->view = NULL;
+       zone->prev_view = NULL;
        zone->checkmx = NULL;
        zone->checksrv = NULL;
        zone->checkns = NULL;
@@ -1060,8 +1066,9 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
 
        /* Must be after magic is set. */
        result = dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
-       if (result != ISC_R_SUCCESS)
+       if (result != ISC_R_SUCCESS) {
                goto free_erefs;
+       }
 
        ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
                       DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone,
@@ -1105,18 +1112,25 @@ zone_free(dns_zone_t *zone) {
        /*
         * Managed objects.  Order is important.
         */
-       if (zone->request != NULL)
+       if (zone->request != NULL) {
                dns_request_destroy(&zone->request); /* XXXMPA */
+       }
        INSIST(zone->readio == NULL);
        INSIST(zone->statelist == NULL);
        INSIST(zone->writeio == NULL);
 
-       if (zone->task != NULL)
+       if (zone->task != NULL) {
                isc_task_detach(&zone->task);
-       if (zone->loadtask != NULL)
+       }
+       if (zone->loadtask != NULL) {
                isc_task_detach(&zone->loadtask);
-       if (zone->view != NULL)
+       }
+       if (zone->view != NULL) {
                dns_view_weakdetach(&zone->view);
+       }
+       if (zone->prev_view != NULL) {
+               dns_view_weakdetach(&zone->prev_view);
+       }
 
        /* Unmanaged objects */
        for (signing = ISC_LIST_HEAD(zone->signing);
@@ -1149,24 +1163,31 @@ zone_free(dns_zone_t *zone) {
                isc_mem_free(zone->mctx, include->name);
                isc_mem_put(zone->mctx, include, sizeof *include);
        }
-       if (zone->masterfile != NULL)
+       if (zone->masterfile != NULL) {
                isc_mem_free(zone->mctx, zone->masterfile);
+       }
        zone->masterfile = NULL;
-       if (zone->keydirectory != NULL)
+       if (zone->keydirectory != NULL) {
                isc_mem_free(zone->mctx, zone->keydirectory);
+       }
        zone->keydirectory = NULL;
        zone->journalsize = -1;
-       if (zone->journal != NULL)
+       if (zone->journal != NULL) {
                isc_mem_free(zone->mctx, zone->journal);
+       }
        zone->journal = NULL;
-       if (zone->stats != NULL)
+       if (zone->stats != NULL) {
                isc_stats_detach(&zone->stats);
-       if (zone->requeststats != NULL)
+       }
+       if (zone->requeststats != NULL) {
                isc_stats_detach(&zone->requeststats);
-       if (zone->rcvquerystats != NULL)
+       }
+       if (zone->rcvquerystats != NULL){
                dns_stats_detach(&zone->rcvquerystats);
-       if (zone->db != NULL)
+       }
+       if (zone->db != NULL) {
                zone_detachdb(zone);
+       }
        if (zone->rpzs != NULL) {
                REQUIRE(zone->rpz_num < zone->rpzs->p.num_zones);
                dns_rpz_detach_rpzs(&zone->rpzs);
@@ -1176,35 +1197,46 @@ zone_free(dns_zone_t *zone) {
                dns_catz_catzs_detach(&zone->catzs);
        }
        zone_freedbargs(zone);
-       RUNTIME_CHECK(dns_zone_setmasterswithkeys(zone, NULL, NULL, 0)
-                     == ISC_R_SUCCESS);
-       RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0)
-                     == ISC_R_SUCCESS);
+       RUNTIME_CHECK(dns_zone_setmasterswithkeys(zone, NULL,
+                                                 NULL, 0) == ISC_R_SUCCESS);
+       RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0) == ISC_R_SUCCESS);
        zone->check_names = dns_severity_ignore;
-       if (zone->update_acl != NULL)
+       if (zone->update_acl != NULL) {
                dns_acl_detach(&zone->update_acl);
-       if (zone->forward_acl != NULL)
+       }
+       if (zone->forward_acl != NULL) {
                dns_acl_detach(&zone->forward_acl);
-       if (zone->notify_acl != NULL)
+       }
+       if (zone->notify_acl != NULL) {
                dns_acl_detach(&zone->notify_acl);
-       if (zone->query_acl != NULL)
+       }
+       if (zone->query_acl != NULL) {
                dns_acl_detach(&zone->query_acl);
-       if (zone->queryon_acl != NULL)
+       }
+       if (zone->queryon_acl != NULL) {
                dns_acl_detach(&zone->queryon_acl);
-       if (zone->xfr_acl != NULL)
+       }
+       if (zone->xfr_acl != NULL) {
                dns_acl_detach(&zone->xfr_acl);
-       if (dns_name_dynamic(&zone->origin))
+       }
+       if (dns_name_dynamic(&zone->origin)) {
                dns_name_free(&zone->origin, zone->mctx);
-       if (zone->strnamerd != NULL)
+       }
+       if (zone->strnamerd != NULL) {
                isc_mem_free(zone->mctx, zone->strnamerd);
-       if (zone->strname != NULL)
+       }
+       if (zone->strname != NULL) {
                isc_mem_free(zone->mctx, zone->strname);
-       if (zone->strrdclass != NULL)
+       }
+       if (zone->strrdclass != NULL) {
                isc_mem_free(zone->mctx, zone->strrdclass);
-       if (zone->strviewname != NULL)
+       }
+       if (zone->strviewname != NULL) {
                isc_mem_free(zone->mctx, zone->strviewname);
-       if (zone->ssutable != NULL)
+       }
+       if (zone->ssutable != NULL) {
                dns_ssutable_detach(&zone->ssutable);
+       }
 
        /* last stuff */
        ZONEDB_DESTROYLOCK(&zone->dblock);
@@ -1416,10 +1448,12 @@ dns_zone_setdbtype(dns_zone_t *zone,
 
        /* Set up a new database argument list. */
        argv = isc_mem_get(zone->mctx, dbargc * sizeof(*argv));
-       if (argv == NULL)
+       if (argv == NULL) {
                goto nomem;
-       for (i = 0; i < dbargc; i++)
+       }
+       for (i = 0; i < dbargc; i++) {
                argv[i] = NULL;
+       }
        for (i = 0; i < dbargc; i++) {
                argv[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
                if (argv[i] == NULL)
@@ -1436,9 +1470,11 @@ dns_zone_setdbtype(dns_zone_t *zone,
 
  nomem:
        if (argv != NULL) {
-               for (i = 0; i < dbargc; i++)
-                       if (argv[i] != NULL)
+               for (i = 0; i < dbargc; i++) {
+                       if (argv[i] != NULL) {
                                isc_mem_free(zone->mctx, argv[i]);
+                       }
+               }
                isc_mem_put(zone->mctx, argv, dbargc * sizeof(*argv));
        }
        result = ISC_R_NOMEMORY;
@@ -1448,30 +1484,43 @@ dns_zone_setdbtype(dns_zone_t *zone,
        return (result);
 }
 
-void
-dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
+static void
+dns_zone_setview_helper(dns_zone_t *zone, dns_view_t *view) {
        char namebuf[1024];
-       REQUIRE(DNS_ZONE_VALID(zone));
 
-       LOCK_ZONE(zone);
+       if (zone->prev_view == NULL && zone->view != NULL) {
+               dns_view_weakattach(zone->view, &zone->prev_view);
+       }
+
        INSIST(zone != zone->raw);
-       if (zone->view != NULL)
+       if (zone->view != NULL) {
                dns_view_weakdetach(&zone->view);
+       }
        dns_view_weakattach(view, &zone->view);
 
-       if (zone->strviewname != NULL)
+       if (zone->strviewname != NULL) {
                isc_mem_free(zone->mctx, zone->strviewname);
-       if (zone->strnamerd != NULL)
+       }
+       if (zone->strnamerd != NULL) {
                isc_mem_free(zone->mctx, zone->strnamerd);
+       }
 
        zone_namerd_tostr(zone, namebuf, sizeof namebuf);
        zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
        zone_viewname_tostr(zone, namebuf, sizeof namebuf);
        zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
 
-       if (inline_secure(zone))
+       if (inline_secure(zone)) {
                dns_zone_setview(zone->raw, view);
+       }
+}
+
+void
+dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
+       REQUIRE(DNS_ZONE_VALID(zone));
 
+       LOCK_ZONE(zone);
+       dns_zone_setview_helper(zone, view);
        UNLOCK_ZONE(zone);
 }
 
@@ -1482,6 +1531,27 @@ dns_zone_getview(dns_zone_t *zone) {
        return (zone->view);
 }
 
+void
+dns_zone_setviewcommit(dns_zone_t *zone) {
+       REQUIRE(DNS_ZONE_VALID(zone));
+
+       LOCK_ZONE(zone);
+       if (zone->prev_view != NULL)
+               dns_view_weakdetach(&zone->prev_view);
+       UNLOCK_ZONE(zone);
+}
+
+void
+dns_zone_setviewrevert(dns_zone_t *zone) {
+       REQUIRE(DNS_ZONE_VALID(zone));
+
+       LOCK_ZONE(zone);
+       if (zone->prev_view != NULL) {
+               dns_zone_setview_helper(zone, zone->prev_view);
+               dns_view_weakdetach(&zone->prev_view);
+       }
+       UNLOCK_ZONE(zone);
+}
 
 isc_result_t
 dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
index 58edeb2943f94c7dec091593bc16d0da3ad06db4..4c1e1918339617f5efaf812d58d5156d025c20c7 100644 (file)
@@ -423,6 +423,54 @@ freezezones(dns_zone_t *zone, void *uap) {
        return (result);
 }
 
+void
+dns_zt_setviewcommit(dns_zt_t *zt) {
+       dns_rbtnode_t *node;
+       dns_rbtnodechain_t chain;
+       isc_result_t result;
+
+       REQUIRE(VALID_ZT(zt));
+
+       dns_rbtnodechain_init(&chain, zt->mctx);
+
+       result = dns_rbtnodechain_first(&chain, zt->table, NULL, NULL);
+       while (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) {
+               result = dns_rbtnodechain_current(&chain, NULL, NULL,
+                                                 &node);
+               if (result == ISC_R_SUCCESS && node->data != NULL) {
+                       dns_zone_setviewcommit(node->data);
+               }
+
+               result = dns_rbtnodechain_next(&chain, NULL, NULL);
+       }
+
+       dns_rbtnodechain_invalidate(&chain);
+}
+
+void
+dns_zt_setviewrevert(dns_zt_t *zt) {
+       dns_rbtnode_t *node;
+       dns_rbtnodechain_t chain;
+       isc_result_t result;
+
+       REQUIRE(VALID_ZT(zt));
+
+       dns_rbtnodechain_init(&chain, zt->mctx);
+
+       result = dns_rbtnodechain_first(&chain, zt->table, NULL, NULL);
+       while (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) {
+               result = dns_rbtnodechain_current(&chain, NULL, NULL,
+                                                 &node);
+               if (result == ISC_R_SUCCESS && node->data != NULL) {
+                       dns_zone_setviewrevert(node->data);
+               }
+
+               result = dns_rbtnodechain_next(&chain, NULL, NULL);
+       }
+
+       dns_rbtnodechain_invalidate(&chain);
+}
+
 isc_result_t
 dns_zt_apply(dns_zt_t *zt, isc_boolean_t stop,
             isc_result_t (*action)(dns_zone_t *, void *), void *uap)