]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
3129. [bug] Named could crash on 'rndc reconfig' when
authorEvan Hunt <each@isc.org>
Fri, 17 Jun 2011 07:05:02 +0000 (07:05 +0000)
committerEvan Hunt <each@isc.org>
Fri, 17 Jun 2011 07:05:02 +0000 (07:05 +0000)
allow-new-zones was set to yes and named ACLs
were used, [RT #22739]

CHANGES
bin/named/include/named/globals.h
bin/named/server.c
bin/tests/system/addzone/ns2/named2.conf
bin/tests/system/addzone/tests.sh
lib/bind9/check.c
lib/dns/acl.c
lib/dns/include/dns/acl.h
lib/isccfg/aclconf.c
lib/isccfg/include/isccfg/aclconf.h

diff --git a/CHANGES b/CHANGES
index c54c181be0d9b81452544c45a0187bddc57081b7..75d57c6a3d653452f720cbfcc4b7e2499d57b641 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,7 @@
+3129.  [bug]           Named could crash on 'rndc reconfig' when
+                       allow-new-zones was set to yes and named ACLs
+                       were used, [RT #22739]
+
 3128.  [func]          Inserting an NSEC3PARAM via dynamic update in an
                        auto-dnssec zone that has not been signed yet
                        will cause it to be signed with the specified NSEC3
index 96341c2c26ee75080cea7d4475063904835689ac..e72920181c8ba67babdfc38a80e1028ab047c6a0 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: globals.h,v 1.89 2010/09/15 12:07:55 marka Exp $ */
+/* $Id: globals.h,v 1.90 2011/06/17 07:05:01 each Exp $ */
 
 #ifndef NAMED_GLOBALS_H
 #define NAMED_GLOBALS_H 1
@@ -26,6 +26,7 @@
 #include <isc/log.h>
 #include <isc/net.h>
 
+#include <isccfg/aclconf.h>
 #include <isccfg/cfg.h>
 
 #include <dns/zone.h>
@@ -102,6 +103,7 @@ EXTERN const char *         lwresd_g_resolvconffile INIT("/etc"
 EXTERN isc_boolean_t           ns_g_conffileset        INIT(ISC_FALSE);
 EXTERN isc_boolean_t           lwresd_g_useresolvconf  INIT(ISC_FALSE);
 EXTERN isc_uint16_t            ns_g_udpsize            INIT(4096);
+EXTERN cfg_aclconfctx_t *      ns_g_aclconfctx         INIT(NULL);
 
 /*
  * Initial resource limits.
index 1006ca16824db9bd3e108d0103baf66d614cf494..b17f4e707f070fe014b7ba185d3927c654937a32 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: server.c,v 1.611 2011/03/21 18:38:39 each Exp $ */
+/* $Id: server.c,v 1.612 2011/06/17 07:05:01 each Exp $ */
 
 /*! \file */
 
@@ -210,7 +210,7 @@ struct cfg_context {
        isc_mem_t *                     mctx;
        cfg_obj_t *                     config;
        cfg_parser_t *                  parser;
-       cfg_aclconfctx_t                actx;
+       cfg_aclconfctx_t *              actx;
 };
 
 /*
@@ -302,7 +302,7 @@ static void
 end_reserved_dispatches(ns_server_t *server, isc_boolean_t all);
 
 static void
-cfgctx_destroy(void **cfgp);
+newzone_cfgctx_destroy(void **cfgp);
 
 /*%
  * Configure a single view ACL at '*aclp'.  Get its configuration from
@@ -1738,9 +1738,9 @@ configure_view(dns_view_t *view, cfg_parser_t* parser,
                        if (config != NULL)
                                cfg_obj_attach(config, &cfg->config);
                        cfg_parser_attach(parser, &cfg->parser);
-                       cfg_aclconfctx_clone(actx, &cfg->actx);
+                       cfg_aclconfctx_attach(actx, &cfg->actx);
                }
-               dns_view_setnewzones(view, allow, cfg, cfgctx_destroy);
+               dns_view_setnewzones(view, allow, cfg, newzone_cfgctx_destroy);
        }
 
        /*
@@ -4179,7 +4179,6 @@ static isc_result_t
 load_configuration(const char *filename, ns_server_t *server,
                   isc_boolean_t first_time)
 {
-       cfg_aclconfctx_t aclconfctx;
        cfg_obj_t *config = NULL, *bindkeys = NULL;
        cfg_parser_t *conf_parser = NULL, *bindkeys_parser = NULL;
        const cfg_listelt_t *element;
@@ -4208,7 +4207,6 @@ load_configuration(const char *filename, ns_server_t *server,
        unsigned int maxsocks;
        ns_cache_t *nsc;
 
-       cfg_aclconfctx_init(&aclconfctx);
        ISC_LIST_INIT(viewlist);
        ISC_LIST_INIT(builtin_viewlist);
        ISC_LIST_INIT(cachelist);
@@ -4217,6 +4215,11 @@ load_configuration(const char *filename, ns_server_t *server,
        result = isc_task_beginexclusive(server->task);
        RUNTIME_CHECK(result == ISC_R_SUCCESS);
 
+       /* Create the ACL configuration context */
+       if (ns_g_aclconfctx != NULL)
+               cfg_aclconfctx_detach(&ns_g_aclconfctx);
+       CHECK(cfg_aclconfctx_create(ns_g_mctx, &ns_g_aclconfctx));
+
        /*
         * Parse the global default pseudo-config file.
         */
@@ -4367,8 +4370,9 @@ load_configuration(const char *filename, ns_server_t *server,
        else
                isc_quota_soft(&server->recursionquota, 0);
 
-       CHECK(configure_view_acl(NULL, config, "blackhole", NULL, &aclconfctx,
-                                ns_g_mctx, &server->blackholeacl));
+       CHECK(configure_view_acl(NULL, config, "blackhole", NULL,
+                                ns_g_aclconfctx, ns_g_mctx,
+                                &server->blackholeacl));
        if (server->blackholeacl != NULL)
                dns_dispatchmgr_setblackhole(ns_g_dispatchmgr,
                                             server->blackholeacl);
@@ -4378,7 +4382,7 @@ load_configuration(const char *filename, ns_server_t *server,
        INSIST(result == ISC_R_SUCCESS);
        server->aclenv.match_mapped = cfg_obj_asboolean(obj);
 
-       CHECKM(ns_statschannels_configure(ns_g_server, config, &aclconfctx),
+       CHECKM(ns_statschannels_configure(ns_g_server, config, ns_g_aclconfctx),
               "configuring statistics server(s)");
 
        /*
@@ -4508,8 +4512,8 @@ load_configuration(const char *filename, ns_server_t *server,
                if (clistenon != NULL) {
                        /* check return code? */
                        (void)ns_listenlist_fromconfig(clistenon, config,
-                                                      &aclconfctx, ns_g_mctx,
-                                                      &listenon);
+                                                      ns_g_aclconfctx,
+                                                      ns_g_mctx, &listenon);
                } else if (!ns_g_lwresdonly) {
                        /*
                         * Not specified, use default.
@@ -4535,8 +4539,8 @@ load_configuration(const char *filename, ns_server_t *server,
                if (clistenon != NULL) {
                        /* check return code? */
                        (void)ns_listenlist_fromconfig(clistenon, config,
-                                                      &aclconfctx, ns_g_mctx,
-                                                      &listenon);
+                                                      ns_g_aclconfctx,
+                                                      ns_g_mctx, &listenon);
                } else if (!ns_g_lwresdonly) {
                        isc_boolean_t enable;
                        /*
@@ -4647,7 +4651,7 @@ load_configuration(const char *filename, ns_server_t *server,
                INSIST(view != NULL);
                CHECK(configure_view(view, conf_parser, config, vconfig,
                                     &cachelist, bindkeys,
-                                    ns_g_mctx, &aclconfctx, ISC_TRUE));
+                                    ns_g_mctx, ns_g_aclconfctx, ISC_TRUE));
                dns_view_freeze(view);
                dns_view_detach(&view);
        }
@@ -4666,7 +4670,7 @@ load_configuration(const char *filename, ns_server_t *server,
                CHECK(create_view(NULL, &viewlist, &view));
                CHECK(configure_view(view, conf_parser, config, NULL,
                                     &cachelist, bindkeys,
-                                    ns_g_mctx, &aclconfctx, ISC_TRUE));
+                                    ns_g_mctx, ns_g_aclconfctx, ISC_TRUE));
                dns_view_freeze(view);
                dns_view_detach(&view);
        }
@@ -4686,7 +4690,7 @@ load_configuration(const char *filename, ns_server_t *server,
                CHECK(create_view(vconfig, &builtin_viewlist, &view));
                CHECK(configure_view(view, conf_parser, config, vconfig,
                                     &cachelist, bindkeys,
-                                    ns_g_mctx, &aclconfctx, ISC_FALSE));
+                                    ns_g_mctx, ns_g_aclconfctx, ISC_FALSE));
                dns_view_freeze(view);
                dns_view_detach(&view);
                view = NULL;
@@ -4727,7 +4731,7 @@ load_configuration(const char *filename, ns_server_t *server,
         * Bind the control port(s).
         */
        CHECKM(ns_controls_configure(ns_g_server->controls, config,
-                                    &aclconfctx),
+                                    ns_g_aclconfctx),
               "binding control channel(s)");
 
        /*
@@ -4969,8 +4973,6 @@ load_configuration(const char *filename, ns_server_t *server,
        if (v6portset != NULL)
                isc_portset_destroy(ns_g_mctx, &v6portset);
 
-       cfg_aclconfctx_clear(&aclconfctx);
-
        if (conf_parser != NULL) {
                if (config != NULL)
                        cfg_obj_destroy(conf_parser, &config);
@@ -5181,6 +5183,9 @@ shutdown_server(isc_task_t *task, isc_event_t *event) {
        end_reserved_dispatches(server, ISC_TRUE);
        cleanup_session_key(server, server->mctx);
 
+       if (ns_g_aclconfctx != NULL)
+               cfg_aclconfctx_detach(&ns_g_aclconfctx);
+
        cfg_obj_destroy(ns_g_parser, &ns_g_config);
        cfg_parser_destroy(&ns_g_parser);
 
@@ -7320,7 +7325,7 @@ ns_server_add_zone(ns_server_t *server, char *args) {
        /* Mark view unfrozen so that zone can be added */
        dns_view_thaw(view);
        result = configure_zone(cfg->config, parms, vconfig,
-                               server->mctx, view, &cfg->actx, ISC_FALSE);
+                               server->mctx, view, cfg->actx, ISC_FALSE);
        dns_view_freeze(view);
        if (result != ISC_R_SUCCESS) {
                goto cleanup;
@@ -7569,23 +7574,22 @@ ns_server_del_zone(ns_server_t *server, char *args) {
 }
 
 static void
-cfgctx_destroy(void **cfgp) {
+newzone_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->actx != NULL)
+               cfg_aclconfctx_detach(&cfg->actx);
 
        if (cfg->parser != NULL) {
                if (cfg->config != NULL)
                        cfg_obj_destroy(cfg->parser, &cfg->config);
                cfg_parser_destroy(&cfg->parser);
        }
-       cfg_aclconfctx_clear(&cfg->actx);
 
-       isc_mem_put(mctx, cfg, sizeof(*cfg));
-       isc_mem_detach(&mctx);
+       isc_mem_putanddetach(&cfg->mctx, cfg, sizeof(*cfg));
        *cfgp = NULL;
 }
index 0ae37d93898eb71e487b0a1dc461ce3e7c335683..2c13e60bfdb69c0e5f6741cbf85f485c7da78ea2 100644 (file)
@@ -14,7 +14,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: named2.conf,v 1.3 2010/09/24 05:09:03 marka Exp $ */
+/* $Id: named2.conf,v 1.4 2011/06/17 07:05:01 each Exp $ */
 
 controls { /* empty */ };
 
@@ -48,3 +48,15 @@ view external {
                file "../../common/root.hint";
        };
 };
+
+# This view is only here to test that configuration context is cleaned
+# up correctly when using multiple named ACLs (regression test for RT #22739)
+acl match { none; };
+acl nobody { none; };
+view extra {
+        match-clients { match; };
+        allow-new-zones yes;
+        allow-transfer { nobody; };
+        allow-query { nobody; };
+        allow-recursion { nobody; };
+};
index ccf9d906a9bc84a6e59c95ff74b15f281c1eb74f..51fdecb9bde91138047085795a7e0b8b92412433 100644 (file)
@@ -14,7 +14,7 @@
 # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 # PERFORMANCE OF THIS SOFTWARE.
 
-# $Id: tests.sh,v 1.4 2010/09/24 05:09:03 marka Exp $
+# $Id: tests.sh,v 1.5 2011/06/17 07:05:01 each Exp $
 
 SYSTEMTESTTOP=..
 . $SYSTEMTESTTOP/conf.sh
@@ -147,5 +147,14 @@ n=`expr $n + 1`
 if [ $ret != 0 ]; then echo "I:failed"; fi
 status=`expr $status + $ret`
 
+echo "I:ensure the configuration context is cleaned up correctly ($n)"
+ret=0
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reconfig > /dev/null 2>&1 || ret=1
+sleep 5
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 status > /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"
 exit $status
index c56e230afb48561fb31f2e64ce6adf8b05205ea2..1a9174828f4b3c136ee265ae2f556aa53f3cae8a 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: check.c,v 1.132 2011/05/07 05:55:17 each Exp $ */
+/* $Id: check.c,v 1.133 2011/06/17 07:05:02 each Exp $ */
 
 /*! \file */
 
@@ -2098,7 +2098,7 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
        isc_symtab_t *symtab = NULL;
        isc_result_t result = ISC_R_SUCCESS;
        isc_result_t tresult = ISC_R_SUCCESS;
-       cfg_aclconfctx_t actx;
+       cfg_aclconfctx_t *actx = NULL;
        const cfg_obj_t *obj;
        const cfg_obj_t *options = NULL;
        isc_boolean_t enablednssec, enablevalidation;
@@ -2118,7 +2118,7 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
        if (tresult != ISC_R_SUCCESS)
                return (ISC_R_NOMEMORY);
 
-       cfg_aclconfctx_init(&actx);
+       cfg_aclconfctx_create(mctx, &actx);
 
        if (voptions != NULL)
                (void)cfg_map_get(voptions, "zone", &zones);
@@ -2133,7 +2133,7 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
                const cfg_obj_t *zone = cfg_listelt_value(element);
 
                tresult = check_zoneconf(zone, voptions, config, symtab,
-                                        vclass, &actx, logctx, mctx);
+                                        vclass, actx, logctx, mctx);
                if (tresult != ISC_R_SUCCESS)
                        result = ISC_R_FAILURE;
        }
@@ -2299,25 +2299,25 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
        if (tresult != ISC_R_SUCCESS)
                result = tresult;
 
-       tresult = check_viewacls(&actx, voptions, config, logctx, mctx);
+       tresult = check_viewacls(actx, voptions, config, logctx, mctx);
        if (tresult != ISC_R_SUCCESS)
                result = tresult;
 
-       tresult = check_recursionacls(&actx, voptions, viewname,
+       tresult = check_recursionacls(actx, voptions, viewname,
                                      config, logctx, mctx);
        if (tresult != ISC_R_SUCCESS)
                result = tresult;
 
-       tresult = check_filteraaaa(&actx, voptions, viewname, config,
+       tresult = check_filteraaaa(actx, voptions, viewname, config,
                                   logctx, mctx);
        if (tresult != ISC_R_SUCCESS)
                result = tresult;
 
-       tresult = check_dns64(&actx, voptions, config, logctx, mctx);
+       tresult = check_dns64(actx, voptions, config, logctx, mctx);
        if (tresult != ISC_R_SUCCESS)
                result = tresult;
 
-       cfg_aclconfctx_clear(&actx);
+       cfg_aclconfctx_detach(&actx);
 
        return (result);
 }
@@ -2474,7 +2474,7 @@ bind9_check_controls(const cfg_obj_t *config, isc_log_t *logctx,
                     isc_mem_t *mctx)
 {
        isc_result_t result = ISC_R_SUCCESS, tresult;
-       cfg_aclconfctx_t actx;
+       cfg_aclconfctx_t *actx = NULL;
        const cfg_listelt_t *element, *element2;
        const cfg_obj_t *allow;
        const cfg_obj_t *control;
@@ -2495,7 +2495,7 @@ bind9_check_controls(const cfg_obj_t *config, isc_log_t *logctx,
 
        (void)cfg_map_get(config, "key", &keylist);
 
-       cfg_aclconfctx_init(&actx);
+       cfg_aclconfctx_create(mctx, &actx);
 
        /*
         * INET: Check allow clause.
@@ -2515,7 +2515,7 @@ bind9_check_controls(const cfg_obj_t *config, isc_log_t *logctx,
                        control = cfg_listelt_value(element2);
                        allow = cfg_tuple_get(control, "allow");
                        tresult = cfg_acl_fromconfig(allow, config, logctx,
-                                                    &actx, mctx, 0, &acl);
+                                                    actx, mctx, 0, &acl);
                        if (acl != NULL)
                                dns_acl_detach(&acl);
                        if (tresult != ISC_R_SUCCESS)
@@ -2562,7 +2562,7 @@ bind9_check_controls(const cfg_obj_t *config, isc_log_t *logctx,
                                result = tresult;
                }
        }
-       cfg_aclconfctx_clear(&actx);
+       cfg_aclconfctx_detach(&actx);
        return (result);
 }
 
index 838356a7cc2b24448d4bf3f407eb9f8bb12a19fd..4d3424585b2c5b83db94f8aff8d087c1057e17de 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: acl.c,v 1.53 2009/01/17 23:47:42 tbox Exp $ */
+/* $Id: acl.c,v 1.54 2011/06/17 07:05:02 each Exp $ */
 
 /*! \file */
 
@@ -99,6 +99,7 @@ static isc_result_t
 dns_acl_anyornone(isc_mem_t *mctx, isc_boolean_t neg, dns_acl_t **target) {
        isc_result_t result;
        dns_acl_t *acl = NULL;
+
        result = dns_acl_create(mctx, 0, &acl);
        if (result != ISC_R_SUCCESS)
                return (result);
@@ -341,7 +342,6 @@ dns_acl_merge(dns_acl_t *dest, dns_acl_t *source, isc_boolean_t pos)
                }
        }
 
-
        /*
         * Merge the iptables.  Make sure the destination ACL's
         * node_count value is set correctly afterward.
@@ -439,6 +439,7 @@ dns_aclelement_match(const isc_netaddr_t *reqaddr,
 void
 dns_acl_attach(dns_acl_t *source, dns_acl_t **target) {
        REQUIRE(DNS_ACL_VALID(source));
+
        isc_refcount_increment(&source->refcount, NULL);
        *target = source;
 }
@@ -446,6 +447,9 @@ dns_acl_attach(dns_acl_t *source, dns_acl_t **target) {
 static void
 destroy(dns_acl_t *dacl) {
        unsigned int i;
+
+       INSIST(!ISC_LINK_LINKED(dacl, nextincache));
+
        for (i = 0; i < dacl->length; i++) {
                dns_aclelement_t *de = &dacl->elements[i];
                if (de->type == dns_aclelementtype_keyname) {
@@ -470,7 +474,9 @@ void
 dns_acl_detach(dns_acl_t **aclp) {
        dns_acl_t *acl = *aclp;
        unsigned int refs;
+
        REQUIRE(DNS_ACL_VALID(acl));
+
        isc_refcount_decrement(&acl->refcount, &refs);
        if (refs == 0)
                destroy(acl);
@@ -590,6 +596,7 @@ dns_acl_isinsecure(const dns_acl_t *a) {
 isc_result_t
 dns_aclenv_init(isc_mem_t *mctx, dns_aclenv_t *env) {
        isc_result_t result;
+
        env->localhost = NULL;
        env->localnets = NULL;
        result = dns_acl_create(mctx, 0, &env->localhost);
index 37bd4c911069b416214b793690c7b71a4f02f51a..7de24abb1b17dc424b55a016273c2fe10dd6f6a2 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: acl.h,v 1.33 2009/01/17 23:47:43 tbox Exp $ */
+/* $Id: acl.h,v 1.34 2011/06/17 07:05:02 each Exp $ */
 
 #ifndef DNS_ACL_H
 #define DNS_ACL_H 1
@@ -145,9 +145,26 @@ dns_acl_merge(dns_acl_t *dest, dns_acl_t *source, isc_boolean_t pos);
 
 void
 dns_acl_attach(dns_acl_t *source, dns_acl_t **target);
+/*%<
+ * Attach to acl 'source'.
+ *
+ * Requires:
+ *\li  'source' to be a valid acl.
+ *\li  'target' to be non NULL and '*target' to be NULL.
+ */
 
 void
 dns_acl_detach(dns_acl_t **aclp);
+/*%<
+ * Detach the acl. On final detach the acl must not be linked on any
+ * list.
+ *
+ * Requires:
+ *\li  '*aclp' to be a valid acl.
+ *
+ * Insists:
+ *\li  '*aclp' is not linked on final detach.
+ */
 
 isc_boolean_t
 dns_acl_isinsecure(const dns_acl_t *a);
index 5372b66be48b3f049a1553be86ed81e03ca5a5fc..7a5261cbe980a83abbf7abd99a04b51d893a13db 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: aclconf.c,v 1.29 2010/08/13 23:47:03 tbox Exp $ */
+/* $Id: aclconf.c,v 1.30 2011/06/17 07:05:02 each Exp $ */
 
 #include <config.h>
 
 
 #define LOOP_MAGIC ISC_MAGIC('L','O','O','P')
 
-void
-cfg_aclconfctx_init(cfg_aclconfctx_t *ctx) {
-       ISC_LIST_INIT(ctx->named_acl_cache);
+isc_result_t
+cfg_aclconfctx_create(isc_mem_t *mctx, cfg_aclconfctx_t **ret) {
+       isc_result_t result;
+       cfg_aclconfctx_t *actx;
+
+       REQUIRE(mctx != NULL);
+       REQUIRE(ret != NULL && *ret == NULL);
+
+       actx = isc_mem_get(mctx, sizeof(*actx));
+       if (actx == NULL)
+               return (ISC_R_NOMEMORY);
+
+       result = isc_refcount_init(&actx->references, 1);
+       if (result != ISC_R_SUCCESS)
+               goto cleanup;
+
+       actx->mctx = NULL;
+       isc_mem_attach(mctx, &actx->mctx);
+       ISC_LIST_INIT(actx->named_acl_cache);
+
+       *ret = actx;
+       return (ISC_R_SUCCESS);
+
+ cleanup:
+       isc_mem_put(mctx, actx, sizeof(*actx));
+       return (result);
 }
 
 void
-cfg_aclconfctx_clear(cfg_aclconfctx_t *ctx) {
-       dns_acl_t *dacl, *next;
+cfg_aclconfctx_attach(cfg_aclconfctx_t *src, cfg_aclconfctx_t **dest) {
+       REQUIRE(src != NULL);
+       REQUIRE(dest != NULL && *dest == NULL);
 
-       for (dacl = ISC_LIST_HEAD(ctx->named_acl_cache);
-            dacl != NULL;
-            dacl = next)
-       {
-               next = ISC_LIST_NEXT(dacl, nextincache);
-               dns_acl_detach(&dacl);
-       }
+       isc_refcount_increment(&src->references, NULL);
+       *dest = src;
 }
 
 void
-cfg_aclconfctx_clone(cfg_aclconfctx_t *src, cfg_aclconfctx_t *dest) {
+cfg_aclconfctx_detach(cfg_aclconfctx_t **actxp) {
+       cfg_aclconfctx_t *actx;
        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, &copy);
-               ISC_LIST_APPEND(dest->named_acl_cache, copy, nextincache);
+       isc_mem_t *mctx;
+       unsigned int refs;
+
+       REQUIRE(actxp != NULL && *actxp != NULL);
+
+       actx = *actxp;
+       mctx = actx->mctx;
+
+       isc_refcount_decrement(&actx->references, &refs);
+       if (refs == 0) {
+               for (dacl = ISC_LIST_HEAD(actx->named_acl_cache);
+                    dacl != NULL;
+                    dacl = next)
+               {
+                       next = ISC_LIST_NEXT(dacl, nextincache);
+                       ISC_LIST_UNLINK(actx->named_acl_cache, dacl,
+                                       nextincache);
+                       dns_acl_detach(&dacl);
+               }
+               isc_mem_putanddetach(&actx->mctx, actx, sizeof(*actx));
        }
+
+       *actxp = NULL;
 }
 
 /*
index 9f1f9dc0eb3707adbade83cfa3422d5c82cc30f7..32f81570f6f252890d24127a3d0de91bd712fa76 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: aclconf.h,v 1.12 2010/08/13 23:47:04 tbox Exp $ */
+/* $Id: aclconf.h,v 1.13 2011/06/17 07:05:02 each Exp $ */
 
 #ifndef ISCCFG_ACLCONF_H
 #define ISCCFG_ACLCONF_H 1
@@ -28,7 +28,8 @@
 
 typedef struct cfg_aclconfctx {
        ISC_LIST(dns_acl_t) named_acl_cache;
-       ISC_LIST(dns_iptable_t) named_iptable_cache;
+       isc_mem_t *mctx;
+       isc_refcount_t references;
 } cfg_aclconfctx_t;
 
 /***
@@ -37,22 +38,23 @@ typedef struct cfg_aclconfctx {
 
 ISC_LANG_BEGINDECLS
 
-void
-cfg_aclconfctx_init(cfg_aclconfctx_t *ctx);
+isc_result_t
+cfg_aclconfctx_create(isc_mem_t *mctx, cfg_aclconfctx_t **ret);
 /*
- * Initialize an ACL configuration context.
+ * Creates and initializes an ACL configuration context.
  */
 
 void
-cfg_aclconfctx_clone(cfg_aclconfctx_t *src, cfg_aclconfctx_t *dest);
+cfg_aclconfctx_detach(cfg_aclconfctx_t **actxp);
 /*
- * Copy the contents of one ACL configuration context into another.
+ * Removes a reference to an ACL configuration context; when references
+ * reaches zero, clears the contents and deallocate the structure.
  */
 
 void
-cfg_aclconfctx_clear(cfg_aclconfctx_t *ctx);
+cfg_aclconfctx_attach(cfg_aclconfctx_t *src, cfg_aclconfctx_t **dest);
 /*
- * Clear the contents of an ACL configuration context.
+ * Attaches a pointer to an existing ACL configuration context.
  */
 
 isc_result_t