]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
Review comments for the fast reload feature (#1259)
authorYorgos Thessalonikefs <yorgos@nlnetlabs.nl>
Mon, 31 Mar 2025 12:02:02 +0000 (14:02 +0200)
committerGitHub <noreply@github.com>
Mon, 31 Mar 2025 12:02:02 +0000 (14:02 +0200)
* - fast-reload review, respip set can be null from a view.

* - fast-reload review, typos.

* - fast-reload review, keep clang static analyzer happy.

* - fast-reload review, don't forget to copy tag_actions.

* - fast-reload review, less indentation.

* - fast-reload review, don't leak respip_actions when reloading.

* - fast-reload review, protect NULL pointer dereference in get_mem
  functions.

* - fast-reload review, add fast_reload_most_options.tdir to test most
  options with high verbosity when fast reloading.

* - fast-reload review, don't skip new line on long error printouts.

* - fast-reload review, typo.

* - fast-reload review, use new_z for consistency.

* - fast-reload review, nit for unlock ordering to make eye comparison
  with the lock counterpart easier.

* - fast-reload review, in case of error the sockets are already closed.

* - fast-reload review, identation.

* - fast-reload review, add static keywords.

* - fast-reload review, update unbound-control usage text.

* - fast-reload review, updates to the man page.

19 files changed:
daemon/remote.c
daemon/worker.c
doc/unbound-control.8.in
respip/respip.c
services/authzone.c
services/localzone.c
services/mesh.c
services/view.c
smallapp/unbound-control.c
testdata/fast_reload_fwd.tdir/fast_reload_fwd.pre
testdata/fast_reload_most_options.tdir/auth.nlnetlabs.nl.zone [new file with mode: 0644]
testdata/fast_reload_most_options.tdir/fast_reload_most_options.conf [new file with mode: 0644]
testdata/fast_reload_most_options.tdir/fast_reload_most_options.dsc [new file with mode: 0644]
testdata/fast_reload_most_options.tdir/fast_reload_most_options.post [new file with mode: 0644]
testdata/fast_reload_most_options.tdir/fast_reload_most_options.pre [new file with mode: 0644]
testdata/fast_reload_most_options.tdir/fast_reload_most_options.test [new file with mode: 0644]
testdata/fast_reload_most_options.tdir/rpz.nlnetlabs.nl.zone [new file with mode: 0644]
util/config_file.c
validator/val_anchor.c

index d231f6eab68e61634ee3eca1a2654aaebd85db8a..76e1de8bb2e60d31b6e9ebcfeae5ebe7a1f63cbf 100644 (file)
@@ -4510,7 +4510,8 @@ fr_check_compat_cfg(struct fast_reload_thread* fr, struct config_file* newcfg)
                 * fast reload. */
                if(!fr_output_printf(fr, "The config changes items that are "
                        "not compatible with fast_reload, perhaps do reload "
-                       "or restart: %s\n", changed_str))
+                       "or restart: %s", changed_str) ||
+                       !fr_output_printf(fr, "\n"))
                        return 0;
                fr_send_notification(fr, fast_reload_notification_printout);
                return 0;
@@ -4623,7 +4624,8 @@ fr_check_nopause_cfg(struct fast_reload_thread* fr, struct config_file* newcfg)
                 * to be able to update the variables. */
                if(!fr_output_printf(fr, "The config changes items that need "
                        "the fast_reload +p option, for nopause, "
-                       "disabled to be reloaded: %s\n", changed_str))
+                       "disabled to be reloaded: %s", changed_str) ||
+                       !fr_output_printf(fr, "\n"))
                        return 0;
                fr_send_notification(fr, fast_reload_notification_printout);
                return 0;
@@ -5009,7 +5011,7 @@ xfr_masterlist_equal(struct auth_master* list1, struct auth_master* list2)
                p1 = p1->next;
                p2 = p2->next;
        }
-       if(!p2 && !p2)
+       if(!p1 && !p2)
                return 1;
        return 0;
 }
@@ -5083,8 +5085,8 @@ auth_zones_check_changes(struct fast_reload_thread* fr,
                        struct auth_xfer* old_xfr, *new_xfr;
                        lock_rw_rdlock(&new_z->lock);
                        lock_rw_rdlock(&old_z->lock);
-                       new_xfr = auth_xfer_find(ct->auth_zones, old_z->name,
-                               old_z->namelen, old_z->dclass);
+                       new_xfr = auth_xfer_find(ct->auth_zones, new_z->name,
+                               new_z->namelen, new_z->dclass);
                        old_xfr = auth_xfer_find(env->auth_zones, old_z->name,
                                old_z->namelen, old_z->dclass);
                        if(new_xfr) {
@@ -6024,14 +6026,14 @@ fr_reload_config(struct fast_reload_thread* fr, struct config_file* newcfg,
        lock_rw_unlock(&env->respip_set->lock);
        lock_rw_unlock(&ct->local_zones->lock);
        lock_rw_unlock(&daemon->local_zones->lock);
-       lock_rw_unlock(&env->auth_zones->lock);
        lock_rw_unlock(&ct->auth_zones->lock);
-       lock_rw_unlock(&env->auth_zones->rpz_lock);
+       lock_rw_unlock(&env->auth_zones->lock);
        lock_rw_unlock(&ct->auth_zones->rpz_lock);
-       lock_rw_unlock(&env->fwds->lock);
+       lock_rw_unlock(&env->auth_zones->rpz_lock);
        lock_rw_unlock(&ct->fwds->lock);
-       lock_rw_unlock(&env->hints->lock);
+       lock_rw_unlock(&env->fwds->lock);
        lock_rw_unlock(&ct->hints->lock);
+       lock_rw_unlock(&env->hints->lock);
        if(ct->anchors) {
                lock_basic_unlock(&ct->anchors->lock);
                lock_basic_unlock(&env->anchors->lock);
@@ -6605,8 +6607,6 @@ fast_reload_thread_setup(struct worker* worker, int fr_verb, int fr_nopause,
        if(!create_socketpair(fr->commreload, worker->daemon->rand)) {
                sock_close(fr->commpair[0]);
                sock_close(fr->commpair[1]);
-               sock_close(fr->commreload[0]);
-               sock_close(fr->commreload[1]);
                free(fr->fr_output);
                free(fr);
                worker->daemon->fast_reload_thread = NULL;
@@ -6706,6 +6706,8 @@ fr_send_cmd_to(struct fast_reload_thread* fr,
                }
                if(!outevent)
                        continue;
+               /* keep static analyzer happy; send(-1,..) */
+               log_assert(fr->commpair[0] >= 0);
                ret = send(fr->commpair[0], ((char*)&cmd)+bcount,
                        sizeof(cmd)-bcount, 0);
                if(ret == -1) {
@@ -6808,16 +6810,16 @@ fr_read_ack_from_workers(struct fast_reload_thread* fr)
                if(ret == -1) {
                        if(
 #ifndef USE_WINSOCK
-                                errno == EINTR || errno == EAGAIN
+                               errno == EINTR || errno == EAGAIN
 #  ifdef EWOULDBLOCK
-                                || errno == EWOULDBLOCK
+                               || errno == EWOULDBLOCK
 #  endif
 #else
-                                WSAGetLastError() == WSAEINTR ||
-                                WSAGetLastError() == WSAEINPROGRESS ||
-                                WSAGetLastError() == WSAEWOULDBLOCK
+                               WSAGetLastError() == WSAEINTR ||
+                               WSAGetLastError() == WSAEINPROGRESS ||
+                               WSAGetLastError() == WSAEWOULDBLOCK
 #endif
-                                )
+                               )
                                continue; /* Try again */
                        log_err("worker reload ack: recv failed: %s",
                                sock_strerror(errno));
@@ -6884,7 +6886,7 @@ fr_poll_for_reload_start(struct fast_reload_thread* fr)
 }
 
 /** Pick up the worker mesh changes, after fast reload. */
-void
+static void
 fr_worker_pickup_mesh(struct worker* worker)
 {
        struct mesh_area* mesh = worker->env.mesh;
@@ -6904,7 +6906,7 @@ fr_worker_pickup_mesh(struct worker* worker)
  * They are only incremented when an accept is performed on a tcp comm point.
  * @param front: listening comm ports of the worker.
  */
-void
+static void
 tcl_remove_old(struct listen_dnsport* front)
 {
        struct listen_list* l;
@@ -7342,6 +7344,8 @@ fr_main_handle_cmd(struct fast_reload_thread* fr)
 {
        enum fast_reload_notification status;
        ssize_t ret;
+       /* keep static analyzer happy; recv(-1,..) */
+       log_assert(fr->commpair[0] >= 0);
        ret = recv(fr->commpair[0],
                ((char*)&fr->service_read_cmd)+fr->service_read_cmd_count,
                sizeof(fr->service_read_cmd)-fr->service_read_cmd_count, 0);
index de74cc049d5b824f6195e66ffc50051ec6b96643..9953ee657721609d45e4be9fce337a5a05c22502 100644 (file)
@@ -373,7 +373,7 @@ worker_check_request(sldns_buffer* pkt, struct worker* worker,
 
 /**
  * Send fast-reload acknowledgement to the mainthread in one byte.
- * This signals that this works has received the previous command.
+ * This signals that this worker has received the previous command.
  * The worker is waiting if that is after a reload_stop command.
  * Or the worker has briefly processed the event itself, and in doing so
  * released data pointers to old config, after a reload_poll command.
index 60cbe96a700adcf73a77e9223cb8ae8bb126e4df..5041b609dd0194d34944fd60342b5833eeced5d6 100644 (file)
@@ -94,11 +94,13 @@ dnstap-tls-client-key-file and dnstap-tls-client-cert-file. The options
 dnstap-send-identity, dnstap-send-version, dnstap-identity, and
 dnstap-version can be loaded when '+p' is not used.
 .IP
-The '+v' option makes the output verbose. With '+vv' it is more verbose.
-That includes the time it took to do the reload. And with more verbose output
-the amount of memory that was allocated temporarily to perform the reload,
-this amount of memory can be big if the config has large contents. In the
-timing output the 'reload' time is the time during which the server was paused.
+The '+v' option makes the output verbose which includes the time it took to do
+the reload.
+With '+vv' it is more verbose which includes the amount of memory that was
+allocated temporarily to perform the reload; this amount of memory can be big
+if the config has large contents.
+In the timing output the 'reload' time is the time during which the server was
+paused.
 .IP
 The '+p' option makes the reload not pause threads, they keep running.
 Locks are acquired, but items are updated in sequence, so it is possible
@@ -131,10 +133,11 @@ processed. The drop makes it so that queries during the life time of the
 query processing see only old, or only new config options.
 .IP
 When there are changes to the config tags, from \fBdefine\-tag\fR config,
-then the '+d' option is turned on with a warning printout, and queries are
-dropped. This is to stop references to the old tag information, by the old
+then the '+d' option is implicitly turned on with a warning printout, and
+queries are dropped.
+This is to stop references to the old tag information, by the old
 queries. If the number of tags is increased in the newly loaded config, by
-adding tags at the end, then the '+d' option is not needed.
+adding tags at the end, then the implicit '+d' option is not needed.
 .IP
 For response ip, that is actions associated with IP addresses, and perhaps
 intersected with access control tag and action information, those settings
index c13bc6ac9665d45895c49779110888aeb56da438..d79d5a2fdc09b671b8d4a133ba08563de7c0b9a3 100644 (file)
@@ -105,6 +105,7 @@ respip_sockaddr_find_or_create(struct respip_set* set, struct sockaddr_storage*
                socklen_t addrlen, int net, int create, const char* ipstr)
 {
        struct resp_addr* node;
+       log_assert(set);
        node = (struct resp_addr*)addr_tree_find(&set->ip_tree, addr, addrlen, net);
        if(!node && create) {
                node = regional_alloc_zero(set->region, sizeof(*node));
@@ -128,6 +129,7 @@ void
 respip_sockaddr_delete(struct respip_set* set, struct resp_addr* node)
 {
        struct resp_addr* prev;
+       log_assert(set);
        prev = (struct resp_addr*)rbtree_previous((struct rbnode_type*)node);   
        lock_rw_destroy(&node->lock);
        (void)rbtree_delete(&set->ip_tree, node);
@@ -146,6 +148,7 @@ respip_find_or_create(struct respip_set* set, const char* ipstr, int create)
        struct sockaddr_storage addr;
        int net;
        socklen_t addrlen;
+       log_assert(set);
 
        if(!netblockstrtoaddr(ipstr, 0, &addr, &addrlen, &net)) {
                log_err("cannot parse netblock: '%s'", ipstr);
@@ -160,6 +163,7 @@ respip_tag_cfg(struct respip_set* set, const char* ipstr,
        const uint8_t* taglist, size_t taglen)
 {
        struct resp_addr* node;
+       log_assert(set);
 
        if(!(node=respip_find_or_create(set, ipstr, 1)))
                return 0;
@@ -183,6 +187,7 @@ respip_action_cfg(struct respip_set* set, const char* ipstr,
 {
        struct resp_addr* node;
        enum respip_action action;
+       log_assert(set);
 
        if(!(node=respip_find_or_create(set, ipstr, 1)))
                return 0;
@@ -325,6 +330,7 @@ static int
 respip_data_cfg(struct respip_set* set, const char* ipstr, const char* rrstr)
 {
        struct resp_addr* node;
+       log_assert(set);
 
        node=respip_find_or_create(set, ipstr, 0);
        if(!node || node->action == respip_none) {
@@ -344,6 +350,7 @@ respip_set_apply_cfg(struct respip_set* set, char* const* tagname, int num_tags,
        struct config_strbytelist* p;
        struct config_str2list* pa;
        struct config_str2list* pd;
+       log_assert(set);
 
        set->tagname = tagname;
        set->num_tags = num_tags;
@@ -609,6 +616,7 @@ respip_addr_lookup(const struct reply_info *rep, struct respip_set* rs,
        struct resp_addr* ra;
        struct sockaddr_storage ss;
        socklen_t addrlen;
+       log_assert(rs);
 
        lock_rw_rdlock(&rs->lock);
        for(i=0; i<rep->an_numrrsets; i++) {
@@ -1343,7 +1351,9 @@ respip_inform_print(struct respip_action_info* respip_actinfo, uint8_t* qname,
 
 size_t respip_set_get_mem(struct respip_set* set)
 {
-       size_t m = sizeof(*set);
+       size_t m;
+       if(!set) return 0;
+       m = sizeof(*set);
        lock_rw_rdlock(&set->lock);
        m += regional_get_mem(set->region);
        lock_rw_unlock(&set->lock);
index ad9351d9e848cb69fa13e98717a76bd193d305e3..b4df102f671f28a9fa5778848fac0550750e9f22 100644 (file)
@@ -8697,7 +8697,9 @@ az_xtree_get_mem(struct auth_zones* az)
 
 size_t auth_zones_get_mem(struct auth_zones* zones)
 {
-       size_t m = sizeof(*zones);
+       size_t m;
+       if(!zones) return 0;
+       m = sizeof(*zones);
        lock_rw_rdlock(&zones->rpz_lock);
        lock_rw_rdlock(&zones->lock);
        m += az_ztree_get_mem(zones);
index e5411eebbbeb513fc8b57bdbafd76765374eaa5a..6ff1d85d4402096fe79956ba6eb469551075227d 100644 (file)
@@ -2225,7 +2225,9 @@ local_zone_get_mem(struct local_zone* z)
 size_t local_zones_get_mem(struct local_zones* zones)
 {
        struct local_zone* z;
-       size_t m = sizeof(*zones);
+       size_t m;
+       if(!zones) return 0;
+       m = sizeof(*zones);
        lock_rw_rdlock(&zones->lock);
        RBTREE_FOR(z, struct local_zone*, &zones->ztree) {
                m += local_zone_get_mem(z);
index 658ce632cc576b1ff8082e3b10198b48f6eb6a50..f46de7414fc542314b28d87d3503963f9a718d80 100644 (file)
@@ -919,6 +919,10 @@ mesh_copy_client_info(struct regional* region, struct respip_client_info* cinfo)
                cinfo->taglen);
        if(!client_info->taglist)
                return NULL;
+       client_info->tag_actions = regional_alloc_init(region, cinfo->tag_actions,
+               cinfo->tag_actions_size);
+       if(!client_info->tag_actions)
+               return NULL;
        client_info->tag_datas = regional_alloc_zero(region,
                sizeof(struct config_strlist*)*cinfo->tag_datas_size);
        if(!client_info->tag_datas)
@@ -2465,19 +2469,19 @@ void mesh_remove_callback(struct mesh_area* mesh, struct query_info* qinfo,
 {
        struct mesh_state* s = NULL;
        s = mesh_area_find(mesh, NULL, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
-       if(s) {
-               if(mesh_state_del_cb(s, cb, cb_arg)) {
-                       /* It was in the list and removed. */
-                       log_assert(mesh->num_reply_addrs > 0);
-                       mesh->num_reply_addrs--;
-                       if(!s->reply_list && !s->cb_list) {
-                               /* was a reply state, not anymore */
-                               log_assert(mesh->num_reply_states > 0);
-                               mesh->num_reply_states--;
-                       }
-                       if(!s->reply_list && !s->cb_list &&
-                               s->super_set.count == 0)
-                               mesh->num_detached_states++;
-               }
+       if(!s) return;
+       if(!mesh_state_del_cb(s, cb, cb_arg)) return;
+
+       /* It was in the list and removed. */
+       log_assert(mesh->num_reply_addrs > 0);
+       mesh->num_reply_addrs--;
+       if(!s->reply_list && !s->cb_list) {
+               /* was a reply state, not anymore */
+               log_assert(mesh->num_reply_states > 0);
+               mesh->num_reply_states--;
+       }
+       if(!s->reply_list && !s->cb_list &&
+               s->super_set.count == 0) {
+               mesh->num_detached_states++;
        }
 }
index 4ecd52d494b3a7f7af2dcc0ab5ebe7832fcfc2d7..44b07f3ed1b41dff3559836a029dfee580256723 100644 (file)
@@ -247,7 +247,9 @@ void views_print(struct views* v)
 size_t views_get_mem(struct views* vs)
 {
        struct view* v;
-       size_t m = sizeof(struct views);
+       size_t m;
+       if(!vs) return 0;
+       m = sizeof(struct views);
        lock_rw_rdlock(&vs->lock);
        RBTREE_FOR(v, struct view*, &vs->vtree) {
                m += view_get_mem(v);
index 3513b04e7ed5c0713a90e17f34ef9b06349d1973..3965deb230f1d172239bb932dd0b101f0be42733 100644 (file)
@@ -110,9 +110,15 @@ usage(void)
        printf("                                the number of threads must not\n");
        printf("                                change between reloads.\n");
        printf("  fast_reload [+dpv]            reloads the server but only briefly stops\n");
-       printf("                                server processing, keeps cache, and only\n");
-       printf("                                changes some options, like forwards\n");
-       printf("                                and stubs.\n");
+       printf("                                server processing, keeps cache, and changes\n");
+       printf("                                most options; check unbound-control(8).\n");
+       printf("                +d              drops running queries to keep consistency\n");
+       printf("                                on changed options while reloading.\n");
+       printf("                +p              does not pause threads for even faster\n");
+       printf("                                reload but less options are supported\n");
+       printf("                                ; check unbound-control(8).\n");
+       printf("                +v              verbose output, it will include duration needed.\n");
+       printf("                +vv             more verbose output, it will include memory needed.\n");
        printf("  stats                         print statistics\n");
        printf("  stats_noreset                 peek at statistics\n");
 #ifdef HAVE_SHMGET
index 67d02ca663d7808dfe8f2cf91df118ee1aae7e83..42e680d8f04196cc6c0c27800ac1358eb0adf384 100644 (file)
@@ -24,7 +24,7 @@ NS1_PORT=$(($RND_PORT + 1))
 NS2_PORT=$(($RND_PORT + 2))
 echo "UNBOUND_PORT=$UNBOUND_PORT" >> .tpkg.var.test
 echo "NS1_PORT=$NS1_PORT" >> .tpkg.var.test
-echo "NS2=$NS2_PORT" >> .tpkg.var.test
+echo "NS2_PORT=$NS2_PORT" >> .tpkg.var.test
 
 # make config files
 CONTROL_PATH=/tmp
diff --git a/testdata/fast_reload_most_options.tdir/auth.nlnetlabs.nl.zone b/testdata/fast_reload_most_options.tdir/auth.nlnetlabs.nl.zone
new file mode 100644 (file)
index 0000000..55b8d34
--- /dev/null
@@ -0,0 +1,3 @@
+$ORIGIN auth.nlnetlabs.nl.
+$TTL 60
+@ IN SOA a b 1 2 3 4 5
diff --git a/testdata/fast_reload_most_options.tdir/fast_reload_most_options.conf b/testdata/fast_reload_most_options.tdir/fast_reload_most_options.conf
new file mode 100644 (file)
index 0000000..eda3d67
--- /dev/null
@@ -0,0 +1,143 @@
+# Try to define values for options that don't have "default" options that would
+# trigger fast-reload functionality.
+server:
+       verbosity: 4
+       num-threads: 4
+       interface: 127.0.0.1
+       interface: lo
+       port: @PORT@
+       interface-action: lo allow
+       use-syslog: no
+       directory: ""
+       pidfile: "unbound.pid"
+       chroot: ""
+       username: ""
+       do-not-query-localhost: no
+
+       module-config: "respip validator iterator"
+
+       outgoing-interface: 127.0.0.1
+       outgoing-port-avoid: "3200-3208"
+
+       define-tag: "tag1 tag2 tag3"
+
+       do-nat64: yes
+       nat64-prefix: 64:ff9b::0/96
+       dns64-prefix: 64:ff9b::0/96
+       dns64-ignore-aaaa: "ignore-aaaa.nlnetlabs.nl"
+
+       edns-tcp-keepalive: yes
+
+       response-ip: 192.0.2.0 always_refuse
+       access-control: 127.0.0.0/8 allow
+       access-control: ::1 allow
+       access-control-tag: 192.0.2.0/24 "tag2 tag3"
+       interface-tag: lo "tag2 tag3"
+       access-control-tag-action: 192.0.2.0/24 tag3 always_refuse
+       interface-tag-action: lo tag3 always_refuse
+       access-control-tag-data: 192.0.2.0/24 tag2 "A 127.0.0.1"
+       interface-tag-data: lo tag2 "A 127.0.0.1"
+       access-control-view: 192.0.2.0/24 viewname
+       interface-view: lo viewname
+
+       nsid: "ascii_something"
+
+       http-user-agent: "httpuseragent"
+
+       caps-exempt: "nlnetlabs.nl"
+
+       private-address: 10.0.0.0/8
+       private-address: 172.16.0.0/12
+       private-address: 192.168.0.0/16
+       private-address: 169.254.0.0/16
+       private-address: fd00::/8
+       private-address: fe80::/10
+       private-address: ::ffff:0:0/96
+
+       private-domain: "nlnetlabs.nl"
+
+       unwanted-reply-threshold: 10000000
+
+       do-not-query-address: 1.1.1.1
+       do-not-query-address: 8.8.8.8
+       do-not-query-address: 9.9.9.9
+
+       do-not-query-localhost: no
+
+       trust-anchor: "jelte.nlnetlabs.nl. DS 42860 5 1 14D739EB566D2B1A5E216A0BA4D17FA9B038BE4A"
+
+       domain-insecure: "nlnetlabs.nl"
+
+       serve-expired: yes
+       serve-expired-client-timeout: 1800
+
+       val-log-level: 2
+
+       local-zone: refuse.nlnetlabs.nl. refuse
+       local-zone: override.nlnetlabs.nl. deny
+       local-zone: tag.nlnetlabs.nl. transparent
+       local-data: "data.nlnetlabs.nl. TXT localdata"
+       local-data-ptr: "192.0.2.3 reverse.nlnetlabs.nl."
+       local-zone-tag: "tag.nlnetlabs.nl" "tag2 tag3"
+       local-zone-override: "override.nlnetlabs.nl" 192.0.2.0/24 refuse
+
+
+       ratelimit: 100
+       ratelimit-below-domain: ratelimit.nlnetlabs.nl 1000
+       ip-ratelimit: 100
+
+       tcp-connection-limit: 192.0.2.0/24 12
+
+       answer-cookie: yes
+       cookie-secret:  "000102030405060708090a0b0c0d0e0f"
+
+       ede: yes
+       ede-serve-expired: yes
+
+remote-control:
+       control-enable: yes
+       control-interface: @CONTROL_PATH@/controlpipe.@CONTROL_PID@
+       control-use-cert: no
+
+stub-zone:
+       name: "stub.nlnetlabs.nl"
+       stub-addr: 192.0.2.68
+       stub-prime: no
+       stub-first: no
+       stub-tcp-upstream: no
+       stub-tls-upstream: no
+       stub-no-cache: no
+
+forward-zone:
+       name: "forward.nlnetlabs.nl"
+       forward-addr: 192.0.2.68
+       forward-first: no
+       forward-tcp-upstream: no
+       forward-tls-upstream: no
+       forward-no-cache: no
+
+auth-zone:
+       name: "auth.nlnetlabs.nl"
+       for-downstream: yes
+       for-upstream: yes
+       zonemd-check: no
+       zonemd-reject-absence: no
+       zonefile: "auth.nlnetlabs.nl.zone"
+
+view:
+       name: "viewname"
+       local-zone: "view.nlnetlabs.nl" redirect
+       local-data: "view.nlnetlabs.nl A 192.0.2.3"
+       local-data-ptr: "192.0.2.3 view.nlnetlabs.nl"
+       view-first: no
+
+rpz:
+       name: "rpz.nlnetlabs.nl"
+       zonefile: "rpz.nlnetlabs.nl.zone"
+       rpz-action-override: cname
+       rpz-cname-override: www.example.org
+       rpz-log: yes
+       rpz-log-name: "example policy"
+       rpz-signal-nxdomain-ra: no
+       for-downstream: no
+       tags: "tag3"
diff --git a/testdata/fast_reload_most_options.tdir/fast_reload_most_options.dsc b/testdata/fast_reload_most_options.tdir/fast_reload_most_options.dsc
new file mode 100644 (file)
index 0000000..e0e8e9f
--- /dev/null
@@ -0,0 +1,16 @@
+BaseName: fast_reload_most_options
+Version: 1.0
+Description: Test fast reload on high verbosity with most options.
+CreationDate: Fri 28 Feb 2025 15:55:15 CET
+Maintainer: Yorgos Thessalonikefs
+Category:
+Component:
+CmdDepends:
+Depends:
+Help:
+Pre: fast_reload_most_options.pre
+Post: fast_reload_most_options.post
+Test: fast_reload_most_options.test
+AuxFiles:
+Passed:
+Failure:
diff --git a/testdata/fast_reload_most_options.tdir/fast_reload_most_options.post b/testdata/fast_reload_most_options.tdir/fast_reload_most_options.post
new file mode 100644 (file)
index 0000000..7fd25e3
--- /dev/null
@@ -0,0 +1,11 @@
+# #-- fast_reload_most_options.post --#
+# source the master var file when it's there
+[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
+# source the test var file when it's there
+[ -f .tpkg.var.test ] && source .tpkg.var.test
+#
+# do your teardown here
+. ../common.sh
+kill_pid $UNBOUND_PID
+rm -f $CONTROL_PATH/controlpipe.$CONTROL_PID
+cat unbound.log
diff --git a/testdata/fast_reload_most_options.tdir/fast_reload_most_options.pre b/testdata/fast_reload_most_options.tdir/fast_reload_most_options.pre
new file mode 100644 (file)
index 0000000..47e3642
--- /dev/null
@@ -0,0 +1,33 @@
+# #-- fast_reload_most_options.pre--#
+# source the master var file when it's there
+[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
+# use .tpkg.var.test for in test variable passing
+[ -f .tpkg.var.test ] && source .tpkg.var.test
+
+PRE="../.."
+. ../common.sh
+# if no threads; exit
+if grep -e "define HAVE_PTHREAD 1" -e "define HAVE_SOLARIS_THREADS 1" -e "define HAVE_WINDOWS_THREADS 1" $PRE/config.h; then
+       echo "have threads"
+else
+       skip_test "no threads"
+fi
+
+get_random_port 1
+UNBOUND_PORT=$RND_PORT
+echo "UNBOUND_PORT=$UNBOUND_PORT" >> .tpkg.var.test
+
+# make config file
+CONTROL_PATH=/tmp
+CONTROL_PID=$$
+sed -e 's/@PORT\@/'$UNBOUND_PORT'/' -e 's?@CONTROL_PATH\@?'$CONTROL_PATH'?' -e 's/@CONTROL_PID@/'$CONTROL_PID'/' < fast_reload_most_options.conf > ub.conf
+# start unbound in the background
+PRE="../.."
+$PRE/unbound -d -c ub.conf >unbound.log 2>&1 &
+UNBOUND_PID=$!
+echo "UNBOUND_PID=$UNBOUND_PID" >> .tpkg.var.test
+echo "CONTROL_PATH=$CONTROL_PATH" >> .tpkg.var.test
+echo "CONTROL_PID=$CONTROL_PID" >> .tpkg.var.test
+
+cat .tpkg.var.test
+wait_unbound_up unbound.log
diff --git a/testdata/fast_reload_most_options.tdir/fast_reload_most_options.test b/testdata/fast_reload_most_options.tdir/fast_reload_most_options.test
new file mode 100644 (file)
index 0000000..2079998
--- /dev/null
@@ -0,0 +1,42 @@
+# #-- fast_reload_most_options.test --#
+# source the master var file when it's there
+[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
+# use .tpkg.var.test for in test variable passing
+[ -f .tpkg.var.test ] && source .tpkg.var.test
+
+PRE="../.."
+. ../common.sh
+
+echo "> unbound-control status"
+$PRE/unbound-control -c ub.conf status
+if test $? -ne 0; then
+       echo "wrong exit value."
+       exit 1
+else
+       echo "exit value: OK"
+fi
+
+for i in {1..10}
+do
+
+       echo "> unbound-control fast_reload +vvdp ($i)"
+       $PRE/unbound-control -c ub.conf fast_reload +vvdp 2>&1 | tee output
+       if test $? -ne 0; then
+               echo "wrong exit value."
+               exit 1
+       else
+               echo "exit value: OK"
+       fi
+       wait_logfile unbound.log "start fast reload thread" 60
+       wait_logfile unbound.log "stop fast reload thread" 60
+       wait_logfile unbound.log "joined with fastreload thread" 60
+
+       if grep "ok" output; then
+               echo "OK"
+       else
+               echo "output not correct"
+               exit 1
+       fi
+done
+
+exit 0
diff --git a/testdata/fast_reload_most_options.tdir/rpz.nlnetlabs.nl.zone b/testdata/fast_reload_most_options.tdir/rpz.nlnetlabs.nl.zone
new file mode 100644 (file)
index 0000000..71b3715
--- /dev/null
@@ -0,0 +1,5 @@
+$ORIGIN rpz.nlnetlabs.nl.
+$TTL 60
+@ IN SOA a b 1 2 3 4 5
+nxdomain.nlnetlabs.nl IN CNAME .
+rpzdata.nlnetlabs.nl IN A 0.0.0.0
index 0587b706246a8846a37e4486921644b839fb98d5..ce1bc1fe9c419d7051a5e23a45e4f82cdb5c9382 100644 (file)
@@ -1689,6 +1689,7 @@ config_delete(struct config_file* cfg)
        config_del_strarray(cfg->tagname, cfg->num_tags);
        config_del_strbytelist(cfg->local_zone_tags);
        config_del_strbytelist(cfg->respip_tags);
+       config_deldblstrlist(cfg->respip_actions);
        config_deldblstrlist(cfg->acl_view);
        config_del_strbytelist(cfg->acl_tags);
        config_deltrplstrlist(cfg->acl_tag_actions);
index 0c9d0c4fd63c3da36c0064f1fb689182379ea5e0..cd2df95a167e570b62f6cc3a2d6536de38a0e1f9 100644 (file)
@@ -1192,9 +1192,9 @@ anchors_get_mem(struct val_anchors* anchors)
 {
        struct trust_anchor *ta;
        struct ta_key *k;
-       size_t s = sizeof(*anchors);
-       if(!anchors)
-               return 0;
+       size_t s;
+       if(!anchors) return 0;
+       s = sizeof(*anchors);
        lock_basic_lock(&anchors->lock);
        RBTREE_FOR(ta, struct trust_anchor*, anchors->tree) {
                lock_basic_lock(&ta->lock);