]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Added mesh_add_sub to add detached mesh entries.
authorRalph Dolmans <ralph@nlnetlabs.nl>
Tue, 2 May 2017 13:17:56 +0000 (13:17 +0000)
committerRalph Dolmans <ralph@nlnetlabs.nl>
Tue, 2 May 2017 13:17:56 +0000 (13:17 +0000)
- Use mesh_add_sub for key tag signaling queries.

git-svn-id: file:///svn/unbound/trunk@4144 be551aaa-1e26-0410-a405-d3ace91eadb9

daemon/worker.c
doc/Changelog
services/mesh.c
services/mesh.h
util/fptr_wlist.c
util/fptr_wlist.h
util/module.h
validator/validator.c

index ff798ae7efc6c60b8651392b61ba167295af8d00..efe97d6d683a1c14ae796f397a44ac907662d04c 100644 (file)
@@ -1669,6 +1669,7 @@ worker_init(struct worker* worker, struct config_file *cfg,
        worker->env.mesh = mesh_create(&worker->daemon->mods, &worker->env);
        worker->env.detach_subs = &mesh_detach_subs;
        worker->env.attach_sub = &mesh_attach_sub;
+       worker->env.add_sub = &mesh_add_sub;
        worker->env.kill_sub = &mesh_state_delete;
        worker->env.detect_cycle = &mesh_detect_cycle;
        worker->env.scratch_buffer = sldns_buffer_new(cfg->msg_buffer_size);
index dba5b82d39a2b105f4711bd3acac61ff023f5406..d9fd9cc11a2da8d1ee68691786bece80748d2d40 100644 (file)
@@ -1,3 +1,7 @@
+2 May 2017: Ralph
+       - Added mesh_add_sub to add detached mesh entries.
+       - Use mesh_add_sub for key tag signaling query.
+
 2 May 2017: Wouter
        - Added test for leak of stub information.
        - Fix sldns wire2str printout of RR type CAA tags.
index 4b0a039392787bae57568584ba8d0a87a920e394..f04ae16ddbcb9b0585803d9d063b26a21384d1be 100644 (file)
@@ -821,26 +821,26 @@ void mesh_detach_subs(struct module_qstate* qstate)
        rbtree_init(&qstate->mesh_info->sub_set, &mesh_state_ref_compare);
 }
 
-int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo,
-        uint16_t qflags, int prime, int valrec, struct module_qstate** newq)
+int mesh_add_sub(struct module_qstate* qstate, struct query_info* qinfo,
+        uint16_t qflags, int prime, int valrec, struct module_qstate** newq,
+       struct mesh_state** sub)
 {
        /* find it, if not, create it */
        struct mesh_area* mesh = qstate->env->mesh;
-       struct mesh_state* sub = mesh_area_find(mesh, NULL, qinfo, qflags,
+       *sub = mesh_area_find(mesh, NULL, qinfo, qflags,
                prime, valrec);
-       int was_detached;
-       if(mesh_detect_cycle_found(qstate, sub)) {
+       if(mesh_detect_cycle_found(qstate, *sub)) {
                verbose(VERB_ALGO, "attach failed, cycle detected");
                return 0;
        }
-       if(!sub) {
+       if(!*sub) {
 #ifdef UNBOUND_DEBUG
                struct rbnode_type* n;
 #endif
                /* create a new one */
-               sub = mesh_state_create(qstate->env, qinfo, NULL, qflags, prime,
+               *sub = mesh_state_create(qstate->env, qinfo, NULL, qflags, prime,
                        valrec);
-               if(!sub) {
+               if(!*sub) {
                        log_err("mesh_attach_sub: out of memory");
                        return 0;
                }
@@ -849,7 +849,7 @@ int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo,
 #else
                (void)
 #endif
-               rbtree_insert(&mesh->all, &sub->node);
+               rbtree_insert(&mesh->all, &(*sub)->node);
                log_assert(n != NULL);
                /* set detached (it is now) */
                mesh->num_detached_states++;
@@ -859,11 +859,22 @@ int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo,
 #else
                (void)
 #endif
-               rbtree_insert(&mesh->run, &sub->run_node);
+               rbtree_insert(&mesh->run, &(*sub)->run_node);
                log_assert(n != NULL);
-               *newq = &sub->s;
+               *newq = &(*sub)->s;
        } else
                *newq = NULL;
+       return 1;
+}
+
+int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo,
+        uint16_t qflags, int prime, int valrec, struct module_qstate** newq)
+{
+       struct mesh_area* mesh = qstate->env->mesh;
+       struct mesh_state* sub = NULL;
+       int was_detached;
+       if(!mesh_add_sub(qstate, qinfo, qflags, prime, valrec, newq, &sub))
+               return 0;
        was_detached = (sub->super_set.count == 0);
        if(!mesh_state_attachment(qstate->mesh_info, sub))
                return 0;
index 1c77945320e31f97e59aaef6190c459c314e4219..67749accb35af2e227bc593305ae9d73ca5ebcc5 100644 (file)
@@ -370,6 +370,35 @@ void mesh_detach_subs(struct module_qstate* qstate);
 int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo,
        uint16_t qflags, int prime, int valrec, struct module_qstate** newq);
 
+/**
+ * Add detached query.
+ * Creates it if it does not exist already.
+ * Does not make super/sub references.
+ * Performs a cycle detection - for double check - and fails if there is one.
+ * Updates stat items in mesh_area structure.
+ * Pass if it is priming query or not.
+ * return:
+ *     o if error (malloc) happened.
+ *     o need to initialise the new state (module init; it is a new state).
+ *       so that the next run of the query with this module is successful.
+ *     o no init needed, attachment successful.
+ *     o added subquery, created if it did not exist already.
+ *
+ * @param qstate: the state to find mesh state, and that wants to receive
+ *     the results from the new subquery.
+ * @param qinfo: what to query for (copied).
+ * @param qflags: what flags to use (RD / CD flag or not).
+ * @param prime: if it is a (stub) priming query.
+ * @param valrec: if it is a validation recursion query (lookup of key, DS).
+ * @param newq: If the new subquery needs initialisation, it is returned,
+ *     otherwise NULL is returned.
+ * @param sub: The added mesh state, created if it did not exist already.
+ * @return: false on error, true if success (and init may be needed).
+ */
+int mesh_add_sub(struct module_qstate* qstate, struct query_info* qinfo,
+        uint16_t qflags, int prime, int valrec, struct module_qstate** newq,
+       struct mesh_state** sub);
+
 /**
  * Query state is done, send messages to reply entries.
  * Encode messages using reply entry values and the querystate (with original
index 03244a123d69f086186840dffe37b18822434b17..7c0b0bfcde7f8ab1518e01e7fdc3d51b48eaf664 100644 (file)
@@ -306,6 +306,16 @@ fptr_whitelist_modenv_attach_sub(int (*fptr)(
        return 0;
 }
 
+int 
+fptr_whitelist_modenv_add_sub(int (*fptr)(
+        struct module_qstate* qstate, struct query_info* qinfo,
+        uint16_t qflags, int prime, int valrec, struct module_qstate** newq,
+       struct mesh_state** sub))
+{
+       if(fptr == &mesh_add_sub) return 1;
+       return 0;
+}
+
 int 
 fptr_whitelist_modenv_kill_sub(void (*fptr)(struct module_qstate* newq))
 {
index 653f8f0e75d4f1aa9f7a04cfe67f8ab2ebf6e44c..39e3f2d7f21b48a0a493c1e6555126e89f5a1755 100644 (file)
@@ -233,6 +233,15 @@ int fptr_whitelist_modenv_attach_sub(int (*fptr)(
        struct module_qstate* qstate, struct query_info* qinfo, 
        uint16_t qflags, int prime, int valrec, struct module_qstate** newq));
 
+/**
+ * Check function pointer whitelist for module_env add_sub callback values.
+ *
+ * @param fptr: function pointer to check.
+ * @return false if not in whitelist.
+ */
+int fptr_whitelist_modenv_add_sub(int (*fptr)(struct module_qstate* qstate,
+       struct query_info* qinfo, uint16_t qflags, int prime, int valrec,
+       struct module_qstate** newq, struct mesh_state** sub));
 /**
  * Check function pointer whitelist for module_env kill_sub callback values.
  *
index 82b50ccd7d06dfb2711a2716ded7d5089b6a6433..6e75539d9169ccca5e2eafa12d7eae436431739e 100644 (file)
@@ -382,6 +382,37 @@ struct module_env {
                struct query_info* qinfo, uint16_t qflags, int prime, 
                int valrec, struct module_qstate** newq);
 
+       /**
+        * Add detached query.
+        * Creates it if it does not exist already.
+        * Does not make super/sub references.
+        * Performs a cycle detection - for double check - and fails if there is
+        *      one.
+        * Updates stat items in mesh_area structure.
+        * Pass if it is priming query or not.
+        * return:
+        *      o if error (malloc) happened.
+        *      o need to initialise the new state (module init; it is a new state).
+        *        so that the next run of the query with this module is successful.
+        *      o no init needed, attachment successful.
+        *      o added subquery, created if it did not exist already.
+        *
+        * @param qstate: the state to find mesh state, and that wants to receive
+        *      the results from the new subquery.
+        * @param qinfo: what to query for (copied).
+        * @param qflags: what flags to use (RD / CD flag or not).
+        * @param prime: if it is a (stub) priming query.
+        * @param valrec: if it is a validation recursion query (lookup of key, DS).
+        * @param newq: If the new subquery needs initialisation, it is returned,
+        *      otherwise NULL is returned.
+        * @param sub: The added mesh state, created if it did not exist already.
+        * @return: false on error, true if success (and init may be needed).
+        */
+       int (*add_sub)(struct module_qstate* qstate, 
+               struct query_info* qinfo, uint16_t qflags, int prime, 
+               int valrec, struct module_qstate** newq,
+               struct mesh_state** sub);
+
        /**
         * Kill newly attached sub. If attach_sub returns newq for 
         * initialisation, but that fails, then this routine will cleanup and
index 6501660463944c5b1d9e64b67e50708426bdc7fd..e8b6317f6e6b8a85445fc9b581e3f3561a8d60cd 100644 (file)
@@ -365,14 +365,17 @@ already_validated(struct dns_msg* ret_msg)
  * @param qtype: query type.
  * @param qclass: query class.
  * @param flags: additional flags, such as the CD bit (BIT_CD), or 0.
+ * @param newq: If the subquery is newly created, it is returned,
+ *     otherwise NULL is returned
+ * @param detached: true if this qstate should not attach to the subquery
  * @return false on alloc failure.
  */
 static int
 generate_request(struct module_qstate* qstate, int id, uint8_t* name, 
-       size_t namelen, uint16_t qtype, uint16_t qclass, uint16_t flags)
+       size_t namelen, uint16_t qtype, uint16_t qclass, uint16_t flags, 
+       struct module_qstate** newq, int detached)
 {
        struct val_qstate* vq = (struct val_qstate*)qstate->minfo[id];
-       struct module_qstate* newq;
        struct query_info ask;
        int valrec;
        ask.qname = name;
@@ -381,65 +384,41 @@ generate_request(struct module_qstate* qstate, int id, uint8_t* name,
        ask.qclass = qclass;
        ask.local_alias = NULL;
        log_query_info(VERB_ALGO, "generate request", &ask);
-       fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
        /* enable valrec flag to avoid recursion to the same validation
         * routine, this lookup is simply a lookup. DLVs need validation */
        if(qtype == LDNS_RR_TYPE_DLV)
                valrec = 0;
        else valrec = 1;
-       if(!(*qstate->env->attach_sub)(qstate, &ask, 
-               (uint16_t)(BIT_RD|flags), 0, valrec, &newq)){
-               log_err("Could not generate request: out of memory");
-               return 0;
+       if(detached) {
+               struct mesh_state* sub = NULL;
+               fptr_ok(fptr_whitelist_modenv_add_sub(
+                       qstate->env->add_sub));
+               if(!(*qstate->env->add_sub)(qstate, &ask, 
+                       (uint16_t)(BIT_RD|flags), 0, valrec, newq, &sub)){
+                       log_err("Could not generate request: out of memory");
+                       return 0;
+               }
+       }
+       else {
+               fptr_ok(fptr_whitelist_modenv_attach_sub(
+                       qstate->env->attach_sub));
+               if(!(*qstate->env->attach_sub)(qstate, &ask, 
+                       (uint16_t)(BIT_RD|flags), 0, valrec, newq)){
+                       log_err("Could not generate request: out of memory");
+                       return 0;
+               }
        }
        /* newq; validator does not need state created for that
         * query, and its a 'normal' for iterator as well */
-       if(newq) {
+       if(*newq) {
                /* add our blacklist to the query blacklist */
-               sock_list_merge(&newq->blacklist, newq->region,
+               sock_list_merge(&(*newq)->blacklist, (*newq)->region,
                        vq->chain_blacklist);
        }
        qstate->ext_state[id] = module_wait_subquery;
        return 1;
 }
 
-/**
- * Prime trust anchor for use.
- * Generate and dispatch a priming query for the given trust anchor.
- * The trust anchor can be DNSKEY or DS and does not have to be signed.
- *
- * @param qstate: query state.
- * @param vq: validator query state.
- * @param id: module id.
- * @param toprime: what to prime.
- * @return false on a processing error.
- */
-static int
-prime_trust_anchor(struct module_qstate* qstate, struct val_qstate* vq,
-       int id, struct trust_anchor* toprime)
-{
-       int ret = generate_request(qstate, id, toprime->name, toprime->namelen,
-               LDNS_RR_TYPE_DNSKEY, toprime->dclass, BIT_CD);
-       if(!ret) {
-               log_err("Could not prime trust anchor: out of memory");
-               return 0;
-       }
-       /* ignore newq; validator does not need state created for that
-        * query, and its a 'normal' for iterator as well */
-       vq->wait_prime_ta = 1; /* to elicit PRIME_RESP_STATE processing 
-               from the validator inform_super() routine */
-       /* store trust anchor name for later lookup when prime returns */
-       vq->trust_anchor_name = regional_alloc_init(qstate->region,
-               toprime->name, toprime->namelen);
-       vq->trust_anchor_len = toprime->namelen;
-       vq->trust_anchor_labs = toprime->namelabs;
-       if(!vq->trust_anchor_name) {
-               log_err("Could not prime trust anchor: out of memory");
-               return 0;
-       }
-       return 1;
-}
-
 /**
  * Generate, send and detach key tag signaling query.
  *
@@ -462,6 +441,8 @@ generate_keytag_query(struct module_qstate* qstate, int id,
        uint8_t dnamebuf[LDNS_MAX_DOMAINLEN+1]; /* +1 for label length byte */
        size_t dnamebuf_len = sizeof(dnamebuf);
        uint8_t* keytagdname;
+       struct module_qstate* newq = NULL;
+       enum module_ext_state ext_state = qstate->ext_state[id];
 
        numtag = anchor_list_keytags(ta, tags, MAX_LABEL_TAGS);
        if(numtag == 0)
@@ -486,19 +467,63 @@ generate_keytag_query(struct module_qstate* qstate, int id,
        log_nametypeclass(VERB_ALGO, "keytag query", keytagdname,
                LDNS_RR_TYPE_NULL, ta->dclass);
        if(!generate_request(qstate, id, keytagdname, dnamebuf_len,
-               LDNS_RR_TYPE_NULL, ta->dclass, 0)) {
+               LDNS_RR_TYPE_NULL, ta->dclass, 0, &newq, 1)) {
                log_err("failed to generate key tag signaling request");
                return 0;
        }
 
-       /* We are not interrested in the response, detach this (and all other!)
-        * subqueries. */
-       fptr_ok(fptr_whitelist_modenv_detach_subs(qstate->env->detach_subs));
-       (*qstate->env->detach_subs)(qstate);
+       /* Not interrested in subquery response. Restore the ext_state,
+        * that might be changed by generate_request() */
+       qstate->ext_state[id] = ext_state;
 
        return 1;
 }
 
+/**
+ * Prime trust anchor for use.
+ * Generate and dispatch a priming query for the given trust anchor.
+ * The trust anchor can be DNSKEY or DS and does not have to be signed.
+ *
+ * @param qstate: query state.
+ * @param vq: validator query state.
+ * @param id: module id.
+ * @param toprime: what to prime.
+ * @return false on a processing error.
+ */
+static int
+prime_trust_anchor(struct module_qstate* qstate, struct val_qstate* vq,
+       int id, struct trust_anchor* toprime)
+{
+       struct module_qstate* newq = NULL;
+       int ret = generate_request(qstate, id, toprime->name, toprime->namelen,
+               LDNS_RR_TYPE_DNSKEY, toprime->dclass, BIT_CD, &newq, 0);
+
+       if(newq && qstate->env->cfg->trust_anchor_signaling &&
+               !generate_keytag_query(qstate, id, toprime)) {
+               log_err("keytag signaling query failed");
+               return 0;
+       }
+
+       if(!ret) {
+               log_err("Could not prime trust anchor: out of memory");
+               return 0;
+       }
+       /* ignore newq; validator does not need state created for that
+        * query, and its a 'normal' for iterator as well */
+       vq->wait_prime_ta = 1; /* to elicit PRIME_RESP_STATE processing 
+               from the validator inform_super() routine */
+       /* store trust anchor name for later lookup when prime returns */
+       vq->trust_anchor_name = regional_alloc_init(qstate->region,
+               toprime->name, toprime->namelen);
+       vq->trust_anchor_len = toprime->namelen;
+       vq->trust_anchor_labs = toprime->namelabs;
+       if(!vq->trust_anchor_name) {
+               log_err("Could not prime trust anchor: out of memory");
+               return 0;
+       }
+       return 1;
+}
+
 /**
  * Validate if the ANSWER and AUTHORITY sections contain valid rrsets.
  * They must be validly signed with the given key.
@@ -1570,6 +1595,7 @@ processFindKey(struct module_qstate* qstate, struct val_qstate* vq, int id)
        uint8_t* target_key_name, *current_key_name;
        size_t target_key_len;
        int strip_lab;
+       struct module_qstate* newq = NULL;
 
        log_query_info(VERB_ALGO, "validator: FindKey", &vq->qchase);
        /* We know that state.key_entry is not 0 or bad key -- if it were,
@@ -1582,7 +1608,7 @@ processFindKey(struct module_qstate* qstate, struct val_qstate* vq, int id)
        if(key_entry_isnull(vq->key_entry)) {
                if(!generate_request(qstate, id, vq->ds_rrset->rk.dname, 
                        vq->ds_rrset->rk.dname_len, LDNS_RR_TYPE_DNSKEY, 
-                       vq->qchase.qclass, BIT_CD)) {
+                       vq->qchase.qclass, BIT_CD, &newq, 0)) {
                        log_err("mem error generating DNSKEY request");
                        return val_error(qstate, id);
                }
@@ -1654,7 +1680,7 @@ processFindKey(struct module_qstate* qstate, struct val_qstate* vq, int id)
                vq->key_entry->name) != 0) {
                if(!generate_request(qstate, id, vq->ds_rrset->rk.dname, 
                        vq->ds_rrset->rk.dname_len, LDNS_RR_TYPE_DNSKEY, 
-                       vq->qchase.qclass, BIT_CD)) {
+                       vq->qchase.qclass, BIT_CD, &newq, 0)) {
                        log_err("mem error generating DNSKEY request");
                        return val_error(qstate, id);
                }
@@ -1683,7 +1709,7 @@ processFindKey(struct module_qstate* qstate, struct val_qstate* vq, int id)
                }
                if(!generate_request(qstate, id, target_key_name, 
                        target_key_len, LDNS_RR_TYPE_DS, vq->qchase.qclass,
-                       BIT_CD)) {
+                       BIT_CD, &newq, 0)) {
                        log_err("mem error generating DS request");
                        return val_error(qstate, id);
                }
@@ -1693,7 +1719,7 @@ processFindKey(struct module_qstate* qstate, struct val_qstate* vq, int id)
        /* Otherwise, it is time to query for the DNSKEY */
        if(!generate_request(qstate, id, vq->ds_rrset->rk.dname, 
                vq->ds_rrset->rk.dname_len, LDNS_RR_TYPE_DNSKEY, 
-               vq->qchase.qclass, BIT_CD)) {
+               vq->qchase.qclass, BIT_CD, &newq, 0)) {
                log_err("mem error generating DNSKEY request");
                return val_error(qstate, id);
        }
@@ -1907,6 +1933,7 @@ val_dlv_init(struct module_qstate* qstate, struct val_qstate* vq,
 {
        uint8_t* nm;
        size_t nm_len;
+       struct module_qstate* newq = NULL;
        /* there must be a DLV configured */
        log_assert(qstate->env->anchors->dlv_anchor);
        /* this bool is true to avoid looping in the DLV checks */
@@ -2008,7 +2035,7 @@ val_dlv_init(struct module_qstate* qstate, struct val_qstate* vq,
        vq->state = VAL_DLVLOOKUP_STATE;
        if(!generate_request(qstate, id, vq->dlv_lookup_name, 
                vq->dlv_lookup_name_len, LDNS_RR_TYPE_DLV,
-               vq->qchase.qclass, 0)) {
+               vq->qchase.qclass, 0, &newq, 0)) {
                return val_error(qstate, id);
        }
 
@@ -2188,6 +2215,7 @@ static int
 processDLVLookup(struct module_qstate* qstate, struct val_qstate* vq, 
        struct val_env* ve, int id)
 {
+       struct module_qstate* newq = NULL;
        /* see if this we are ready to continue normal resolution */
        /* we may need more DLV lookups */
        if(vq->dlv_status==dlv_error)
@@ -2236,7 +2264,7 @@ processDLVLookup(struct module_qstate* qstate, struct val_qstate* vq,
 
                if(!generate_request(qstate, id, vq->ds_rrset->rk.dname, 
                        vq->ds_rrset->rk.dname_len, LDNS_RR_TYPE_DNSKEY, 
-                       vq->qchase.qclass, BIT_CD)) {
+                       vq->qchase.qclass, BIT_CD, &newq, 0)) {
                        log_err("mem error generating DNSKEY request");
                        return val_error(qstate, id);
                }
@@ -2278,7 +2306,7 @@ processDLVLookup(struct module_qstate* qstate, struct val_qstate* vq,
 
        if(!generate_request(qstate, id, vq->dlv_lookup_name,
                vq->dlv_lookup_name_len, LDNS_RR_TYPE_DLV, 
-               vq->qchase.qclass, 0)) {
+               vq->qchase.qclass, 0, &newq, 0)) {
                return val_error(qstate, id);
        }
 
@@ -2918,12 +2946,6 @@ process_prime_response(struct module_qstate* qstate, struct val_qstate* vq,
                        ta->dclass);
        }
 
-       if(qstate->env->cfg->trust_anchor_signaling &&
-               !generate_keytag_query(qstate, id, ta)) {
-               log_err("keytag signaling query failed");
-               return;
-       }
-
        if(ta->autr) {
                if(!autr_process_prime(qstate->env, ve, ta, dnskey_rrset)) {
                        /* trust anchor revoked, restart with less anchors */