]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- xfr-tsig, fast reload support for tsig keys.
authorW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Fri, 12 Sep 2025 13:38:39 +0000 (15:38 +0200)
committerW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Fri, 12 Sep 2025 13:38:39 +0000 (15:38 +0200)
Makefile.in
daemon/remote.c
util/tsig.c
util/tsig.h

index 9d5c9d8882f3d1a07cf10d7bb791aca1bb81f059..1fd4126cfdbb173818e5a208c9eda91363cbc6ed 100644 (file)
@@ -1509,7 +1509,7 @@ remote.lo remote.o: $(srcdir)/daemon/remote.c config.h \
  $(srcdir)/iterator/iter_delegpt.h $(srcdir)/iterator/iter_utils.h $(srcdir)/iterator/iter_resptype.h \
  $(srcdir)/iterator/iter_donotq.h $(srcdir)/iterator/iter_priv.h $(srcdir)/services/outside_network.h \
  $(srcdir)/util/regional.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/wire2str.h \
- $(srcdir)/util/timeval_func.h $(srcdir)/util/tcp_conn_limit.h $(srcdir)/util/edns.h $(srcdir)/cachedb/cachedb.h \
+ $(srcdir)/util/timeval_func.h $(srcdir)/util/tcp_conn_limit.h $(srcdir)/util/edns.h $(srcdir)/util/tsig.h $(srcdir)/cachedb/cachedb.h \
  $(srcdir)/edns-subnet/subnetmod.h $(srcdir)/edns-subnet/addrtree.h $(srcdir)/edns-subnet/edns-subnet.h
 stats.lo stats.o: $(srcdir)/daemon/stats.c config.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
  $(srcdir)/libunbound/unbound.h $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
index 058517398a23a882d7e44259c8c9fc4172d4446e..d94c9f7fd4ab24735eb25b536506d6c78447bb41 100644 (file)
@@ -98,6 +98,7 @@
 #include "util/timeval_func.h"
 #include "util/tcp_conn_limit.h"
 #include "util/edns.h"
+#include "util/tsig.h"
 #ifdef USE_CACHEDB
 #include "cachedb/cachedb.h"
 #endif
@@ -4645,6 +4646,8 @@ struct fast_reload_construct {
        struct acl_list* acl_interface;
        /** construct for tcp connection limit */
        struct tcl_list* tcl;
+       /** tsig key table */
+       struct tsig_key_table* tsig_key_table;
        /** construct for local zones */
        struct local_zones* local_zones;
        /** if there is response ip configuration in use */
@@ -5031,6 +5034,7 @@ fr_construct_clear(struct fast_reload_construct* ct)
        acl_list_delete(ct->acl);
        acl_list_delete(ct->acl_interface);
        tcl_list_delete(ct->tcl);
+       tsig_key_table_delete(ct->tsig_key_table);
        edns_strings_delete(ct->edns_strings);
        anchors_delete(ct->anchors);
        views_delete(ct->views);
@@ -5298,6 +5302,7 @@ fr_printmem(struct fast_reload_thread* fr,
        mem += auth_zones_get_mem(ct->auth_zones);
        mem += forwards_get_mem(ct->fwds);
        mem += hints_get_mem(ct->hints);
+       mem += tsig_key_table_get_mem(ct->tsig_key_table);
        mem += local_zones_get_mem(ct->local_zones);
        mem += acl_list_get_mem(ct->acl);
        mem += acl_list_get_mem(ct->acl_interface);
@@ -5591,13 +5596,24 @@ fr_construct_from_config(struct fast_reload_thread* fr,
        if(fr_poll_for_quit(fr))
                return 1;
 
+       if(!(ct->tsig_key_table = tsig_key_table_create())) {
+               fr_construct_clear(ct);
+               return 0;
+       }
+       if(!tsig_key_table_apply_cfg(ct->tsig_key_table, newcfg)) {
+               fr_construct_clear(ct);
+               return 0;
+       }
+       if(fr_poll_for_quit(fr))
+               return 1;
+
        if(!(ct->auth_zones = auth_zones_create())) {
                fr_construct_clear(ct);
                return 0;
        }
        if(!auth_zones_apply_cfg(ct->auth_zones, newcfg, 1, &ct->use_rpz,
                fr->worker->daemon->env, &fr->worker->daemon->mods,
-               fr->worker->daemon->env->tsig_key_table)) {
+               ct->tsig_key_table)) {
                fr_construct_clear(ct);
                return 0;
        }
@@ -5926,6 +5942,7 @@ fr_atomic_copy_cfg(struct config_file* oldcfg, struct config_file* cfg,
        COPY_VAR_ptr(forwards);
        COPY_VAR_ptr(auths);
        COPY_VAR_ptr(views);
+       COPY_VAR_ptr(tsig_keys);
        COPY_VAR_ptr(donotqueryaddrs);
 #ifdef CLIENT_SUBNET
        COPY_VAR_ptr(client_subnet);
@@ -6363,6 +6380,7 @@ fr_reload_config(struct fast_reload_thread* fr, struct config_file* newcfg,
                lock_basic_lock(&ct->anchors->lock);
                lock_basic_lock(&env->anchors->lock);
        }
+       lock_rw_wrlock(&env->tsig_key_table->lock);
 
 #if defined(ATOMIC_POINTER_LOCK_FREE) && defined(HAVE_LINK_ATOMIC_STORE)
        if(fr->fr_nopause) {
@@ -6399,6 +6417,8 @@ fr_reload_config(struct fast_reload_thread* fr, struct config_file* newcfg,
        acl_list_swap_tree(daemon->acl, ct->acl);
        acl_list_swap_tree(daemon->acl_interface, ct->acl_interface);
        tcl_list_swap_tree(daemon->tcl, ct->tcl);
+       tsig_key_table_swap_tree(daemon->env->tsig_key_table,
+               ct->tsig_key_table);
        local_zones_swap_tree(daemon->local_zones, ct->local_zones);
        respip_set_swap_tree(env->respip_set, ct->respip_set);
        daemon->use_response_ip = ct->use_response_ip;
@@ -6445,6 +6465,7 @@ fr_reload_config(struct fast_reload_thread* fr, struct config_file* newcfg,
                lock_basic_unlock(&ct->anchors->lock);
                lock_basic_unlock(&env->anchors->lock);
        }
+       lock_rw_unlock(&env->tsig_key_table->lock);
 
        return 1;
 }
index 2f98897725b22a8d7bcec776938d1131eb16d475..d5f2ff29a1eeb7100b740b51680aab0e1f96ab1b 100644 (file)
@@ -271,6 +271,32 @@ tsig_key_table_search_fromstr(struct tsig_key_table* key_table, char* name)
        return tsig_key_table_search(key_table, buf, len);
 }
 
+size_t
+tsig_key_table_get_mem(struct tsig_key_table* tsig_key_table)
+{
+       size_t s;
+       struct tsig_key* p;
+       if(!tsig_key_table)
+               return 0;
+       lock_rw_rdlock(&tsig_key_table->lock);
+       s = sizeof(*tsig_key_table) + sizeof(rbtree_type);
+       RBTREE_FOR(p, struct tsig_key*, tsig_key_table->tree) {
+               s += sizeof(*p) + strlen(p->name_str)+1
+                       + p->name_len + p->data_len;
+       }
+       lock_rw_unlock(&tsig_key_table->lock);
+       return s;
+}
+
+void
+tsig_key_table_swap_tree(struct tsig_key_table* tsig_key_table,
+       struct tsig_key_table* data)
+{
+       rbtree_type* oldtree = tsig_key_table->tree;
+       tsig_key_table->tree = data->tree;
+       data->tree = oldtree;
+}
+
 void tsig_key_delete(struct tsig_key* key)
 {
        if(!key)
index 6ba9c1ca6d508263e9524f7fb3192ae6571ae08c..2b5fbab6efba4bd931b02d8a4c8abfb8ef9a8fcb 100644 (file)
@@ -183,7 +183,8 @@ struct tsig_key {
  * They are read from config.
  */
 struct tsig_key_table {
-       /* Lock on the tsig key table and all keys. */
+       /* Lock on the tsig key table and all keys.
+        * This lock is after the forwards, hints and anchor locks. */
        lock_rw_type lock;
        /* Tree of tsig keys, by wireformat name. */
        struct rbtree_type* tree;
@@ -239,6 +240,23 @@ struct tsig_key* tsig_key_table_search(struct tsig_key_table* key_table,
 struct tsig_key* tsig_key_table_search_fromstr(
        struct tsig_key_table* key_table, char* name);
 
+/**
+ * Get memory usage of tsig key table.
+ * @param tsig_key_table: the tsig key table.
+ * @return memory use.
+ */
+size_t tsig_key_table_get_mem(struct tsig_key_table* tsig_key_table);
+
+/**
+ * Swap internal tree with preallocated entries. Caller should manage
+ * the locks.
+ * @param tsig_key_table: the tsig_key_table data structure.
+ * @param data: the data structure used to take elements from. This contains
+ *     the old elements on return.
+ */
+void tsig_key_table_swap_tree(struct tsig_key_table* tsig_key_table,
+       struct tsig_key_table* data);
+
 /**
  * Delete TSIG key.
  * @param key: to delete