]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- fast-reload, unshared stub hints, making the structure locked, with an rwlock.
authorW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Fri, 5 Jan 2024 12:36:41 +0000 (13:36 +0100)
committerW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Fri, 5 Jan 2024 12:36:41 +0000 (13:36 +0100)
15 files changed:
Makefile.in
daemon/cachedump.c
daemon/daemon.c
daemon/remote.c
daemon/worker.c
iterator/iter_fwd.h
iterator/iter_hints.c
iterator/iter_hints.h
iterator/iter_utils.c
iterator/iterator.c
libunbound/context.c
libunbound/libunbound.c
libunbound/libworker.c
pythonmod/interface.i
util/module.h

index 4c37a980a58bf552fa05ea441555a0e2b2ee9908..79379d8d131586cc128f42baf0fb567c6a5de8a6 100644 (file)
@@ -1278,7 +1278,8 @@ daemon.lo daemon.o: $(srcdir)/daemon/daemon.c config.h $(srcdir)/daemon/daemon.h
  $(srcdir)/util/edns.h $(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h \
  $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/services/localzone.h \
  $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h $(srcdir)/services/rpz.h $(srcdir)/respip/respip.h \
- $(srcdir)/util/random.h $(srcdir)/util/tube.h $(srcdir)/util/net_help.h $(srcdir)/sldns/keyraw.h $(srcdir)/iterator/iter_fwd.h
+ $(srcdir)/util/random.h $(srcdir)/util/tube.h $(srcdir)/util/net_help.h $(srcdir)/sldns/keyraw.h \
+ $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h
 remote.lo remote.o: $(srcdir)/daemon/remote.c config.h $(srcdir)/daemon/remote.h $(srcdir)/daemon/worker.h \
  $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h \
  $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/netevent.h \
@@ -1484,7 +1485,8 @@ context.lo context.o: $(srcdir)/libunbound/context.c config.h $(srcdir)/libunbou
  $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \
  $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h  \
  $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h $(srcdir)/services/rpz.h $(srcdir)/daemon/stats.h \
- $(srcdir)/util/timehist.h $(srcdir)/respip/respip.h $(srcdir)/util/edns.h $(srcdir)/iterator/iter_fwd.h
+ $(srcdir)/util/timehist.h $(srcdir)/respip/respip.h $(srcdir)/util/edns.h \
+ $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h
 libunbound.lo libunbound.o: $(srcdir)/libunbound/libunbound.c $(srcdir)/libunbound/unbound.h \
  $(srcdir)/libunbound/unbound-event.h config.h $(srcdir)/libunbound/context.h $(srcdir)/util/locks.h \
  $(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h \
@@ -1496,7 +1498,8 @@ libunbound.lo libunbound.o: $(srcdir)/libunbound/libunbound.c $(srcdir)/libunbou
  $(srcdir)/sldns/sbuffer.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/util/netevent.h \
  $(srcdir)/dnscrypt/dnscrypt.h  $(srcdir)/services/cache/rrset.h \
  $(srcdir)/util/storage/slabhash.h $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h \
- $(srcdir)/services/rpz.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/respip/respip.h $(srcdir)/iterator/iter_fwd.h
+ $(srcdir)/services/rpz.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/respip/respip.h \
+ $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h
 libworker.lo libworker.o: $(srcdir)/libunbound/libworker.c config.h $(srcdir)/libunbound/libworker.h \
  $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
  $(srcdir)/libunbound/context.h $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h \
@@ -1510,8 +1513,7 @@ libworker.lo libworker.o: $(srcdir)/libunbound/libworker.c config.h $(srcdir)/li
  $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/outbound_list.h \
  $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/regional.h $(srcdir)/util/random.h \
  $(srcdir)/util/storage/lookup3.h $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h \
- $(srcdir)/util/data/msgencode.h $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h \
- $(srcdir)/sldns/str2wire.h
+ $(srcdir)/util/data/msgencode.h $(srcdir)/sldns/str2wire.h
 unbound-host.lo unbound-host.o: $(srcdir)/smallapp/unbound-host.c config.h $(srcdir)/libunbound/unbound.h \
  $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/wire2str.h
 asynclook.lo asynclook.o: $(srcdir)/testcode/asynclook.c config.h $(srcdir)/libunbound/unbound.h \
index d12168008bdf4bc2e5973914ea864cbcb9e3d133..c7523497d73c70c39333acf668e48618c05639fa 100644 (file)
@@ -897,22 +897,29 @@ int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm,
                                        return 0;
                                continue;
                        }
-               } 
+               }
+               lock_rw_rdlock(&worker->env.hints->lock);
                stub = hints_lookup_stub(worker->env.hints, nm, qinfo.qclass,
                        dp);
                if(stub) {
                        if(stub->noprime) {
                                if(!ssl_printf(ssl, "The noprime stub servers "
-                                       "are used:\n"))
+                                       "are used:\n")) {
+                                       lock_rw_unlock(&worker->env.hints->lock);
                                        return 0;
+                               }
                        } else {
                                if(!ssl_printf(ssl, "The stub is primed "
-                                               "with servers:\n"))
+                                               "with servers:\n")) {
+                                       lock_rw_unlock(&worker->env.hints->lock);
                                        return 0;
+                               }
                        }
                        print_dp_main(ssl, stub->dp, NULL);
                        print_dp_details(ssl, worker, stub->dp);
+                       lock_rw_unlock(&worker->env.hints->lock);
                } else {
+                       lock_rw_unlock(&worker->env.hints->lock);
                        print_dp_main(ssl, dp, msg);
                        print_dp_details(ssl, worker, dp);
                }
index 8f672950a0418a8e284e794a37a5cfdb1df63459..75bae96baee66ed28497c9024040b1194d95e1af 100644 (file)
@@ -92,6 +92,7 @@
 #include "sldns/keyraw.h"
 #include "respip/respip.h"
 #include "iterator/iter_fwd.h"
+#include "iterator/iter_hints.h"
 #include <signal.h>
 
 #ifdef HAVE_SYSTEMD
@@ -720,6 +721,9 @@ daemon_fork(struct daemon* daemon)
        if(!(daemon->env->fwds = forwards_create()) ||
                !forwards_apply_cfg(daemon->env->fwds, daemon->cfg))
                fatal_exit("Could not set forward zones");
+       if(!(daemon->env->hints = hints_create()) ||
+               !hints_apply_cfg(daemon->env->hints, daemon->cfg))
+               fatal_exit("Could not set root or stub hints");
 
        /* process raw response-ip configuration data */
        if(!(daemon->respip_set = respip_set_create()))
@@ -838,6 +842,8 @@ daemon_cleanup(struct daemon* daemon)
        daemon->old_num = daemon->num; /* save the current num */
        forwards_delete(daemon->env->fwds);
        daemon->env->fwds = NULL;
+       hints_delete(daemon->env->hints);
+       daemon->env->hints = NULL;
        local_zones_delete(daemon->local_zones);
        daemon->local_zones = NULL;
        respip_set_delete(daemon->respip_set);
index 18cc3dbbcf98ce87851adccf994447efbc16b5d9..87246ddfef0a72ecbcf26c25e0591be2afe3c60d 100644 (file)
@@ -2244,9 +2244,12 @@ do_stub_add(RES* ssl, struct worker* worker, char* args)
        if(!parse_fs_args(ssl, args, &nm, &dp, &insecure, &prime))
                return;
        lock_rw_wrlock(&fwd->lock);
+       lock_rw_wrlock(&worker->env.hints->lock);
        if(insecure && worker->env.anchors) {
                if(!anchors_add_insecure(worker->env.anchors, LDNS_RR_CLASS_IN,
                        nm)) {
+                       lock_rw_unlock(&fwd->lock);
+                       lock_rw_unlock(&worker->env.hints->lock);
                        (void)ssl_printf(ssl, "error out of memory\n");
                        delegpt_free_mlc(dp);
                        free(nm);
@@ -2258,6 +2261,7 @@ do_stub_add(RES* ssl, struct worker* worker, char* args)
                        anchors_delete_insecure(worker->env.anchors,
                                LDNS_RR_CLASS_IN, nm);
                lock_rw_unlock(&fwd->lock);
+               lock_rw_unlock(&worker->env.hints->lock);
                (void)ssl_printf(ssl, "error out of memory\n");
                delegpt_free_mlc(dp);
                free(nm);
@@ -2270,10 +2274,12 @@ do_stub_add(RES* ssl, struct worker* worker, char* args)
                        anchors_delete_insecure(worker->env.anchors,
                                LDNS_RR_CLASS_IN, nm);
                lock_rw_unlock(&fwd->lock);
+               lock_rw_unlock(&worker->env.hints->lock);
                free(nm);
                return;
        }
        lock_rw_unlock(&fwd->lock);
+       lock_rw_unlock(&worker->env.hints->lock);
        free(nm);
        send_ok(ssl);
 }
@@ -2288,12 +2294,14 @@ do_stub_remove(RES* ssl, struct worker* worker, char* args)
        if(!parse_fs_args(ssl, args, &nm, NULL, &insecure, NULL))
                return;
        lock_rw_wrlock(&fwd->lock);
+       lock_rw_wrlock(&worker->env.hints->lock);
        if(insecure && worker->env.anchors)
                anchors_delete_insecure(worker->env.anchors, LDNS_RR_CLASS_IN,
                        nm);
        forwards_delete_stub_hole(fwd, LDNS_RR_CLASS_IN, nm);
        hints_delete_stub(worker->env.hints, LDNS_RR_CLASS_IN, nm);
        lock_rw_unlock(&fwd->lock);
+       lock_rw_unlock(&worker->env.hints->lock);
        free(nm);
        send_ok(ssl);
 }
@@ -2753,6 +2761,7 @@ do_list_stubs(RES* ssl, struct worker* worker)
        struct trust_anchor* a;
        int insecure;
        char str[32];
+       lock_rw_rdlock(&worker->env.hints->lock);
        RBTREE_FOR(z, struct iter_hints_stub*, &worker->env.hints->tree) {
 
                /* see if it is insecure */
@@ -2768,9 +2777,12 @@ do_list_stubs(RES* ssl, struct worker* worker)
                snprintf(str, sizeof(str), "stub %sprime%s",
                        (z->noprime?"no":""), (insecure?" +i":""));
                if(!ssl_print_name_dp(ssl, str, z->node.name,
-                       z->node.dclass, z->dp))
+                       z->node.dclass, z->dp)) {
+                       lock_rw_unlock(&worker->env.hints->lock);
                        return;
+               }
        }
+       lock_rw_unlock(&worker->env.hints->lock);
 }
 
 /** do the list_auth_zones command */
@@ -3133,16 +3145,6 @@ execute_cmd(struct daemon_remote* rc, struct rc_state* s, RES* ssl, char* cmd,
        } else if(cmdcmp(p, "auth_zone_transfer", 18)) {
                do_auth_zone_transfer(ssl, worker, skipwhite(p+18));
                return;
-       } else if(cmdcmp(p, "stub_add", 8)) {
-               /* must always distribute this cmd */
-               if(rc) distribute_cmd(rc, ssl, cmd);
-               do_stub_add(ssl, worker, skipwhite(p+8));
-               return;
-       } else if(cmdcmp(p, "stub_remove", 11)) {
-               /* must always distribute this cmd */
-               if(rc) distribute_cmd(rc, ssl, cmd);
-               do_stub_remove(ssl, worker, skipwhite(p+11));
-               return;
        } else if(cmdcmp(p, "insecure_add", 12)) {
                /* must always distribute this cmd */
                if(rc) distribute_cmd(rc, ssl, cmd);
@@ -3200,6 +3202,10 @@ execute_cmd(struct daemon_remote* rc, struct rc_state* s, RES* ssl, char* cmd,
                do_forward_remove(ssl, worker, skipwhite(p+14));
        } else if(cmdcmp(p, "forward", 7)) {
                do_forward(ssl, worker, skipwhite(p+7));
+       } else if(cmdcmp(p, "stub_add", 8)) {
+               do_stub_add(ssl, worker, skipwhite(p+8));
+       } else if(cmdcmp(p, "stub_remove", 11)) {
+               do_stub_remove(ssl, worker, skipwhite(p+11));
        } else if(cmdcmp(p, "view_local_zone_remove", 22)) {
                do_view_zone_remove(ssl, worker, skipwhite(p+22));
        } else if(cmdcmp(p, "view_local_zone", 15)) {
index 8ac28ba19629becb178317d235c86765ed7a15fe..c4ae79352b93e07c8e9140005e7941d5b4d08323 100644 (file)
@@ -2268,12 +2268,6 @@ worker_init(struct worker* worker, struct config_file *cfg,
                worker_delete(worker);
                return 0;
        }
-       if(!(worker->env.hints = hints_create()) ||
-               !hints_apply_cfg(worker->env.hints, cfg)) {
-               log_err("Could not set root or stub hints");
-               worker_delete(worker);
-               return 0;
-       }
        /* one probe timer per process -- if we have 5011 anchors */
        if(autr_get_num_anchors(worker->env.anchors) > 0
 #ifndef THREADS_DISABLED
@@ -2346,7 +2340,6 @@ worker_delete(struct worker* worker)
        outside_network_quit_prepare(worker->back);
        mesh_delete(worker->env.mesh);
        sldns_buffer_free(worker->env.scratch_buffer);
-       hints_delete(worker->env.hints);
        listen_delete(worker->front);
        outside_network_delete(worker->back);
        comm_signal_delete(worker->comsig);
index 75ac597bd6e7d7a8d03c0cb6e536f8d090c13517..c1160b8533097f1e274c53293b56f117b413c270 100644 (file)
@@ -53,7 +53,8 @@ struct delegpt;
 struct iter_forwards {
        /** lock on the forwards tree.
         * When grabbing both this lock and the anchors.lock, this lock
-        * is grabbed first. */
+        * is grabbed first. When grabbing both this lock and the hints.lock
+        * this lock is grabbed first. */
        lock_rw_type lock;
        /** 
         * Zones are stored in this tree. Sort order is specially chosen.
index 4f86f3676a29db321b6a0e61140f2dcc7bc30f88..a56aa8e409264da94fc280fa767433d1413332aa 100644 (file)
@@ -57,6 +57,8 @@ hints_create(void)
                sizeof(struct iter_hints));
        if(!hints)
                return NULL;
+       lock_rw_init(&hints->lock);
+       lock_protect(&hints->lock, &hints->tree, sizeof(hints->tree));
        return hints;
 }
 
@@ -83,6 +85,7 @@ hints_delete(struct iter_hints* hints)
 {
        if(!hints) 
                return;
+       lock_rw_destroy(&hints->lock);
        hints_del_tree(hints);
        free(hints);
 }
@@ -438,29 +441,39 @@ read_root_hints_list(struct iter_hints* hints, struct config_file* cfg)
 int 
 hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg)
 {
+       lock_rw_wrlock(&hints->lock);
        hints_del_tree(hints);
        name_tree_init(&hints->tree);
-       
+
        /* read root hints */
-       if(!read_root_hints_list(hints, cfg))
+       if(!read_root_hints_list(hints, cfg)) {
+               lock_rw_unlock(&hints->lock);
                return 0;
+       }
 
        /* read stub hints */
-       if(!read_stubs(hints, cfg))
+       if(!read_stubs(hints, cfg)) {
+               lock_rw_unlock(&hints->lock);
                return 0;
+       }
 
        /* use fallback compiletime root hints */
        if(!hints_lookup_root(hints, LDNS_RR_CLASS_IN)) {
                struct delegpt* dp = compile_time_root_prime(cfg->do_ip4,
                        cfg->do_ip6);
                verbose(VERB_ALGO, "no config, using builtin root hints.");
-               if(!dp) 
+               if(!dp) {
+                       lock_rw_unlock(&hints->lock);
                        return 0;
-               if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp, 0))
+               }
+               if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp, 0)) {
+                       lock_rw_unlock(&hints->lock);
                        return 0;
+               }
        }
 
        name_tree_init_parents(&hints->tree);
+       lock_rw_unlock(&hints->lock);
        return 1;
 }
 
@@ -524,10 +537,12 @@ hints_get_mem(struct iter_hints* hints)
        size_t s;
        struct iter_hints_stub* p;
        if(!hints) return 0;
+       lock_rw_rdlock(&hints->lock);
        s = sizeof(*hints);
        RBTREE_FOR(p, struct iter_hints_stub*, &hints->tree) {
                s += sizeof(*p) + delegpt_get_mem(p->dp);
        }
+       lock_rw_unlock(&hints->lock);
        return s;
 }
 
index 06b4b9667d13569914770e8ed36c5a5fac1abfc3..23af751eff54e6b1a16e55b525431582f5d6fd27 100644 (file)
@@ -43,6 +43,7 @@
 #ifndef ITERATOR_ITER_HINTS_H
 #define ITERATOR_ITER_HINTS_H
 #include "util/storage/dnstree.h"
+#include "util/locks.h"
 struct iter_env;
 struct config_file;
 struct delegpt;
@@ -51,6 +52,10 @@ struct delegpt;
  * Iterator hints structure
  */
 struct iter_hints {
+       /** lock on the forwards tree.
+        * When grabbing both this lock and the anchors.lock, this lock
+        * is grabbed first. */
+       lock_rw_type lock;
        /** 
         * Hints are stored in this tree. Sort order is specially chosen.
         * first sorted on qclass. Then on dname in nsec-like order, so that
@@ -131,6 +136,7 @@ struct iter_hints_stub* hints_lookup_stub(struct iter_hints* hints,
 
 /**
  * Get memory in use by hints
+ * Locks and unlocks the structure.
  * @param hints: hint storage.
  * @return bytes in use
  */
index c1c4999ad47205a0863ee522ecf5d31b48d5a392..79a6e3cb02be23f0cd7afddd6860045f104419ba 100644 (file)
@@ -1284,12 +1284,14 @@ iter_get_next_root(struct iter_hints* hints, struct iter_forwards* fwd,
        uint16_t* c)
 {
        uint16_t c1 = *c, c2 = *c;
-       int r1 = hints_next_root(hints, &c1);
-       int r2;
+       int r1, r2;
 
        lock_rw_rdlock(&fwd->lock);
+       lock_rw_rdlock(&hints->lock);
+       r1 = hints_next_root(hints, &c1);
        r2 = forwards_next_root(fwd, &c2);
        lock_rw_unlock(&fwd->lock);
+       lock_rw_unlock(&hints->lock);
 
        if(!r1 && !r2) /* got none, end of list */
                return 0;
@@ -1462,9 +1464,10 @@ iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf,
        struct delegpt *dp;
 
        /* Check for stub. */
+       lock_rw_rdlock(&qstate->env->fwds->lock);
+       lock_rw_rdlock(&qstate->env->hints->lock);
        stub = hints_lookup_stub(qstate->env->hints, qinf->qname,
            qinf->qclass, NULL);
-       lock_rw_rdlock(&qstate->env->fwds->lock);
        dp = forwards_lookup(qstate->env->fwds, qinf->qname, qinf->qclass);
 
        /* see if forward or stub is more pertinent */
@@ -1479,8 +1482,9 @@ iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf,
 
        /* check stub */
        if (stub != NULL && stub->dp != NULL) {
+               int stub_no_cache = stub->dp->no_cache;
                lock_rw_unlock(&qstate->env->fwds->lock);
-               if(stub->dp->no_cache) {
+               if(stub_no_cache) {
                        char qname[255+1];
                        char dpname[255+1];
                        dname_str(qinf->qname, qname);
@@ -1488,15 +1492,26 @@ iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf,
                        verbose(VERB_ALGO, "stub for %s %s has no_cache", qname, dpname);
                }
                if(retdpname) {
-                       *retdpname = stub->dp->name;
+                       if(stub->dp->namelen > dpname_storage_len) {
+                               verbose(VERB_ALGO, "no cache stub dpname too long");
+                               lock_rw_unlock(&qstate->env->hints->lock);
+                               *retdpname = NULL;
+                               *retdpnamelen = 0;
+                               return stub_no_cache;
+                       }
+                       memmove(dpname_storage, stub->dp->name,
+                               stub->dp->namelen);
+                       *retdpname = dpname_storage;
                        *retdpnamelen = stub->dp->namelen;
                }
-               return (stub->dp->no_cache);
+               lock_rw_unlock(&qstate->env->hints->lock);
+               return stub_no_cache;
        }
 
        /* Check for forward. */
        if (dp) {
                int dp_no_cache = dp->no_cache;
+               lock_rw_unlock(&qstate->env->hints->lock);
                if(dp_no_cache) {
                        char qname[255+1];
                        char dpname[255+1];
@@ -1508,16 +1523,19 @@ iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf,
                        if(dp->namelen > dpname_storage_len) {
                                verbose(VERB_ALGO, "no cache dpname too long");
                                lock_rw_unlock(&qstate->env->fwds->lock);
-                               return (dp_no_cache);
+                               *retdpname = NULL;
+                               *retdpnamelen = 0;
+                               return dp_no_cache;
                        }
                        memmove(dpname_storage, dp->name, dp->namelen);
                        *retdpname = dpname_storage;
                        *retdpnamelen = dp->namelen;
                }
                lock_rw_unlock(&qstate->env->fwds->lock);
-               return (dp_no_cache);
+               return dp_no_cache;
        }
        lock_rw_unlock(&qstate->env->fwds->lock);
+       lock_rw_unlock(&qstate->env->hints->lock);
        if(retdpname) {
                *retdpname = NULL;
                *retdpnamelen = 0;
index 45d27825466760a33ed28e23ab484d5a33f46047..e0716e96787e1ce2e6c1c4df8bf62dc3174ac59d 100644 (file)
@@ -688,15 +688,18 @@ can_have_last_resort(struct module_env* env, uint8_t* nm, size_t nmlen,
        /* do not process a last resort (the parent side) if a stub
         * or forward is configured, because we do not want to go 'above'
         * the configured servers */
+       lock_rw_rdlock(&env->hints->lock);
        if(!dname_is_root(nm) && (stub = (struct iter_hints_stub*)
                name_tree_find(&env->hints->tree, nm, nmlen, labs, qclass)) &&
                /* has_parent side is turned off for stub_first, where we
                 * are allowed to go to the parent */
                stub->dp->has_parent_side_NS) {
-               if(retdp) *retdp = stub->dp;
+               if(retdp) *retdp = delegpt_copy(stub->dp, region);
+               lock_rw_unlock(&env->hints->lock);
                if(have_dp) *have_dp = 1;
                return 0;
        }
+       lock_rw_unlock(&env->hints->lock);
        lock_rw_rdlock(&env->fwds->lock);
        if((fwddp = forwards_find(env->fwds, nm, qclass)) &&
                /* has_parent_side is turned off for forward_first, where
@@ -886,8 +889,10 @@ prime_root(struct module_qstate* qstate, struct iter_qstate* iq, int id,
        verbose(VERB_DETAIL, "priming . %s NS", 
                sldns_lookup_by_id(sldns_rr_classes, (int)qclass)?
                sldns_lookup_by_id(sldns_rr_classes, (int)qclass)->name:"??");
+       lock_rw_rdlock(&qstate->env->hints->lock);
        dp = hints_lookup_root(qstate->env->hints, qclass);
        if(!dp) {
+               lock_rw_unlock(&qstate->env->hints->lock);
                verbose(VERB_ALGO, "Cannot prime due to lack of hints");
                return 0;
        }
@@ -896,6 +901,7 @@ prime_root(struct module_qstate* qstate, struct iter_qstate* iq, int id,
        if(!generate_sub_request((uint8_t*)"\000", 1, LDNS_RR_TYPE_NS, 
                qclass, qstate, id, iq, QUERYTARGETS_STATE, PRIME_RESP_STATE,
                &subq, 0, 0)) {
+               lock_rw_unlock(&qstate->env->hints->lock);
                verbose(VERB_ALGO, "could not prime root");
                return 0;
        }
@@ -906,6 +912,7 @@ prime_root(struct module_qstate* qstate, struct iter_qstate* iq, int id,
                 * copy dp, it is now part of the root prime query. 
                 * dp was part of in the fixed hints structure. */
                subiq->dp = delegpt_copy(dp, subq->region);
+               lock_rw_unlock(&qstate->env->hints->lock);
                if(!subiq->dp) {
                        log_err("out of memory priming root, copydp");
                        fptr_ok(fptr_whitelist_modenv_kill_sub(
@@ -917,6 +924,8 @@ prime_root(struct module_qstate* qstate, struct iter_qstate* iq, int id,
                subiq->num_target_queries = 0; 
                subiq->dnssec_expected = iter_indicates_dnssec(
                        qstate->env, subiq->dp, NULL, subq->qinfo.qclass);
+       } else {
+               lock_rw_unlock(&qstate->env->hints->lock);
        }
        
        /* this module stops, our submodule starts, and does the query. */
@@ -949,16 +958,21 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, int id,
        struct module_qstate* subq;
 
        if(!qname) return 0;
+       lock_rw_rdlock(&qstate->env->hints->lock);
        stub = hints_lookup_stub(qstate->env->hints, qname, qclass, iq->dp);
        /* The stub (if there is one) does not need priming. */
-       if(!stub)
+       if(!stub) {
+               lock_rw_unlock(&qstate->env->hints->lock);
                return 0;
+       }
        stub_dp = stub->dp;
        /* if we have an auth_zone dp, and stub is equal, don't prime stub
         * yet, unless we want to fallback and avoid the auth_zone */
        if(!iq->auth_zone_avoid && iq->dp && iq->dp->auth_dp && 
-               query_dname_compare(iq->dp->name, stub_dp->name) == 0)
+               query_dname_compare(iq->dp->name, stub_dp->name) == 0) {
+               lock_rw_unlock(&qstate->env->hints->lock);
                return 0;
+       }
 
        /* is it a noprime stub (always use) */
        if(stub->noprime) {
@@ -967,13 +981,14 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, int id,
                /* copy the dp out of the fixed hints structure, so that
                 * it can be changed when servicing this query */
                iq->dp = delegpt_copy(stub_dp, qstate->region);
+               lock_rw_unlock(&qstate->env->hints->lock);
                if(!iq->dp) {
                        log_err("out of memory priming stub");
                        errinf(qstate, "malloc failure, priming stub");
                        (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
                        return 1; /* return 1 to make module stop, with error */
                }
-               log_nametypeclass(VERB_DETAIL, "use stub", stub_dp->name, 
+               log_nametypeclass(VERB_DETAIL, "use stub", iq->dp->name,
                        LDNS_RR_TYPE_NS, qclass);
                return r;
        }
@@ -987,6 +1002,7 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, int id,
        if(!generate_sub_request(stub_dp->name, stub_dp->namelen, 
                LDNS_RR_TYPE_NS, qclass, qstate, id, iq,
                QUERYTARGETS_STATE, PRIME_RESP_STATE, &subq, 0, 0)) {
+               lock_rw_unlock(&qstate->env->hints->lock);
                verbose(VERB_ALGO, "could not prime stub");
                errinf(qstate, "could not generate lookup for stub prime");
                (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
@@ -999,6 +1015,7 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, int id,
                /* Set the initial delegation point to the hint. */
                /* make copy to avoid use of stub dp by different qs/threads */
                subiq->dp = delegpt_copy(stub_dp, subq->region);
+               lock_rw_unlock(&qstate->env->hints->lock);
                if(!subiq->dp) {
                        log_err("out of memory priming stub, copydp");
                        fptr_ok(fptr_whitelist_modenv_kill_sub(
@@ -1015,6 +1032,8 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, int id,
                subiq->wait_priming_stub = 1;
                subiq->dnssec_expected = iter_indicates_dnssec(
                        qstate->env, subiq->dp, NULL, subq->qinfo.qclass);
+       } else {
+               lock_rw_unlock(&qstate->env->hints->lock);
        }
        
        /* this module stops, our submodule starts, and does the query. */
@@ -1615,15 +1634,18 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
                                lock_rw_unlock(&qstate->env->fwds->lock);
                                /* forward zone root, no root prime needed */
                                /* fill in some dp - safety belt */
+                               lock_rw_rdlock(&qstate->env->hints->lock);
                                iq->dp = hints_lookup_root(qstate->env->hints, 
                                        iq->qchase.qclass);
                                if(!iq->dp) {
+                                       lock_rw_unlock(&qstate->env->hints->lock);
                                        log_err("internal error: no hints dp");
                                        errinf(qstate, "no hints for this class");
                                        return error_response(qstate, id, 
                                                LDNS_RCODE_SERVFAIL);
                                }
                                iq->dp = delegpt_copy(iq->dp, qstate->region);
+                               lock_rw_unlock(&qstate->env->hints->lock);
                                if(!iq->dp) {
                                        log_err("out of memory in safety belt");
                                        errinf(qstate, "malloc failure, in safety belt");
@@ -1692,16 +1714,19 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
                                /* use safety belt */
                                verbose(VERB_QUERY, "Cache has root NS but "
                                "no addresses. Fallback to the safety belt.");
+                               lock_rw_rdlock(&qstate->env->hints->lock);
                                iq->dp = hints_lookup_root(qstate->env->hints, 
                                        iq->qchase.qclass);
                                /* note deleg_msg is from previous lookup,
                                 * but RD is on, so it is not used */
                                if(!iq->dp) {
+                                       lock_rw_unlock(&qstate->env->hints->lock);
                                        log_err("internal error: no hints dp");
                                        return error_response(qstate, id, 
                                                LDNS_RCODE_REFUSED);
                                }
                                iq->dp = delegpt_copy(iq->dp, qstate->region);
+                               lock_rw_unlock(&qstate->env->hints->lock);
                                if(!iq->dp) {
                                        log_err("out of memory in safety belt");
                                        errinf(qstate, "malloc failure, in safety belt, for root");
@@ -1764,6 +1789,7 @@ processInitRequest2(struct module_qstate* qstate, struct iter_qstate* iq,
                }
                /* Do not send queries above stub, do not set delname to dp if
                 * this is above stub without stub-first. */
+               lock_rw_rdlock(&qstate->env->hints->lock);
                stub = hints_lookup_stub(
                        qstate->env->hints, iq->qchase.qname, iq->qchase.qclass,
                        iq->dp);
@@ -1772,6 +1798,7 @@ processInitRequest2(struct module_qstate* qstate, struct iter_qstate* iq,
                        delname = iq->dp->name;
                        delnamelen = iq->dp->namelen;
                }
+               lock_rw_unlock(&qstate->env->hints->lock);
        }
        if(iq->qchase.qtype == LDNS_RR_TYPE_DS || iq->refetch_glue) {
                if(!dname_is_root(delname))
@@ -2085,8 +2112,9 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
                return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
        }
        if(!iq->dp->has_parent_side_NS && dname_is_root(iq->dp->name)) {
-               struct delegpt* p = hints_lookup_root(qstate->env->hints,
-                       iq->qchase.qclass);
+               struct delegpt* p;
+               lock_rw_rdlock(&qstate->env->hints->lock);
+               p = hints_lookup_root(qstate->env->hints, iq->qchase.qclass);
                if(p) {
                        struct delegpt_addr* a;
                        iq->chase_flags &= ~BIT_RD; /* go to authorities */
@@ -2101,6 +2129,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
                                        a->lame, a->tls_auth_name, -1, NULL);
                        }
                }
+               lock_rw_unlock(&qstate->env->hints->lock);
                iq->dp->has_parent_side_NS = 1;
        } else if(!iq->dp->has_parent_side_NS) {
                if(!iter_lookup_parent_NS_from_cache(qstate->env, iq->dp,
index f3a57d43d1b3219ff84d994271ac0e8b01825571..a319f59cdea83578c534a747b3771d890df88f3d 100644 (file)
@@ -54,6 +54,7 @@
 #include "util/edns.h"
 #include "sldns/sbuffer.h"
 #include "iterator/iter_fwd.h"
+#include "iterator/iter_hints.h"
 
 int 
 context_finalize(struct ub_ctx* ctx)
@@ -89,6 +90,9 @@ context_finalize(struct ub_ctx* ctx)
        if(!(ctx->env->fwds = forwards_create()) ||
                !forwards_apply_cfg(ctx->env->fwds, cfg))
                return UB_INITFAIL;
+       if(!(ctx->env->hints = hints_create()) ||
+               !hints_apply_cfg(ctx->env->hints, cfg))
+               return UB_INITFAIL;
        if(!edns_strings_apply_cfg(ctx->env->edns_strings, cfg))
                return UB_INITFAIL;
        if(!slabhash_is_size(ctx->env->msg_cache, cfg->msg_cache_size,
index 68e1990bc6985a87b7840c372013c3df4abfa88f..e7636d6418f1d7f05a2825b6b8c735121caa8ba5 100644 (file)
@@ -67,6 +67,7 @@
 #include "services/listen_dnsport.h"
 #include "sldns/sbuffer.h"
 #include "iterator/iter_fwd.h"
+#include "iterator/iter_hints.h"
 #ifdef HAVE_PTHREAD
 #include <signal.h>
 #endif
@@ -381,6 +382,7 @@ ub_ctx_delete(struct ub_ctx* ctx)
                edns_known_options_delete(ctx->env);
                edns_strings_delete(ctx->env->edns_strings);
                forwards_delete(ctx->env->fwds);
+               hints_delete(ctx->env->hints);
                auth_zones_delete(ctx->env->auth_zones);
                free(ctx->env);
        }
index 9149365c839b217752a9e04284b26992ea99dfc9..7880678524c4c91b7a06571952009dc2478b8c40 100644 (file)
@@ -70,8 +70,6 @@
 #include "util/data/msgreply.h"
 #include "util/data/msgencode.h"
 #include "util/tube.h"
-#include "iterator/iter_fwd.h"
-#include "iterator/iter_hints.h"
 #include "sldns/sbuffer.h"
 #include "sldns/str2wire.h"
 #ifdef USE_DNSTAP
@@ -100,7 +98,6 @@ libworker_delete_env(struct libworker* w)
                        !w->is_bg || w->is_bg_thread);
                sldns_buffer_free(w->env->scratch_buffer);
                regional_destroy(w->env->scratch);
-               hints_delete(w->env->hints);
                ub_randfree(w->env->rnd);
                free(w->env);
        }
@@ -158,24 +155,19 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
        }
        w->env->scratch = regional_create_custom(cfg->msg_buffer_size);
        w->env->scratch_buffer = sldns_buffer_new(cfg->msg_buffer_size);
-       w->env->hints = hints_create();
-       if(w->env->hints && !hints_apply_cfg(w->env->hints, cfg)) { 
-               hints_delete(w->env->hints);
-               w->env->hints = NULL;
-       }
 #ifdef HAVE_SSL
        w->sslctx = connect_sslctx_create(NULL, NULL,
                cfg->tls_cert_bundle, cfg->tls_win_cert);
        if(!w->sslctx) {
                /* to make the setup fail after unlock */
-               hints_delete(w->env->hints);
-               w->env->hints = NULL;
+               sldns_buffer_free(w->env->scratch_buffer);
+               w->env->scratch_buffer = NULL;
        }
 #endif
        if(!w->is_bg || w->is_bg_thread) {
                lock_basic_unlock(&ctx->cfglock);
        }
-       if(!w->env->scratch || !w->env->scratch_buffer || !w->env->hints) {
+       if(!w->env->scratch || !w->env->scratch_buffer) {
                libworker_delete(w);
                return NULL;
        }
index d9839fc3866c2d7c4382ff272ac6dc09ae41b136..5bc7e8492b01d7d7ff74e2080a4e411903f94d37 100644 (file)
@@ -1455,10 +1455,14 @@ struct delegpt* find_delegation(struct module_qstate* qstate, char *nm, size_t n
             dname_str((uint8_t*)nm, b);
             continue;
         }
+        lock_rw_rdlock(&qstate->env->hints->lock);
         stub = hints_lookup_stub(qstate->env->hints, qinfo.qname, qinfo.qclass, dp);
         if (stub) {
-            return stub->dp;
+            struct delegpt* stubdp = delegpt_copy(stub->dp, region);
+            lock_rw_unlock(&qstate->env->hints->lock);
+            return stubdp;
         } else {
+            lock_rw_unlock(&qstate->env->hints->lock);
             return dp;
         }
     }
index 65b82b59cba317733dcdb722ac3e710e5ddb5a3a..8e7aca635d00c753655f402ff0a7f77e915721d4 100644 (file)
@@ -514,7 +514,7 @@ struct module_env {
         * iterator forwarder information. */
        struct iter_forwards* fwds;
        /** 
-        * iterator forwarder information. per-thread, created by worker.
+        * iterator stub information.
         * The hints -- these aren't stored in the cache because they don't 
         * expire. The hints are always used to "prime" the cache. Note 
         * that both root hints and stub zone "hints" are stored in this