From 1ae8be68478b003e50109a8cf3586de6e47a414c Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Fri, 12 Sep 2025 15:38:39 +0200 Subject: [PATCH] - xfr-tsig, fast reload support for tsig keys. --- Makefile.in | 2 +- daemon/remote.c | 23 ++++++++++++++++++++++- util/tsig.c | 26 ++++++++++++++++++++++++++ util/tsig.h | 20 +++++++++++++++++++- 4 files changed, 68 insertions(+), 3 deletions(-) diff --git a/Makefile.in b/Makefile.in index 9d5c9d888..1fd4126cf 100644 --- a/Makefile.in +++ b/Makefile.in @@ -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 \ diff --git a/daemon/remote.c b/daemon/remote.c index 058517398..d94c9f7fd 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -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; } diff --git a/util/tsig.c b/util/tsig.c index 2f9889772..d5f2ff29a 100644 --- a/util/tsig.c +++ b/util/tsig.c @@ -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) diff --git a/util/tsig.h b/util/tsig.h index 6ba9c1ca6..2b5fbab6e 100644 --- a/util/tsig.h +++ b/util/tsig.h @@ -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 -- 2.47.3