mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
preparatory work for iterator.
git-svn-id: file:///svn/unbound/trunk@336 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
42312206c9
commit
4a2c15be58
18 changed files with 495 additions and 53 deletions
|
|
@ -76,6 +76,30 @@ worker_send_cmd(struct worker* worker, ldns_buffer* buffer,
|
|||
log_err("write socket: %s", strerror(errno));
|
||||
}
|
||||
|
||||
/** delete subrequest */
|
||||
static void
|
||||
qstate_free(struct worker* worker, struct module_qstate* qstate)
|
||||
{
|
||||
int i;
|
||||
if(!qstate)
|
||||
return;
|
||||
/* remove subqueries */
|
||||
while(qstate->subquery_first) {
|
||||
qstate_free(worker, qstate->subquery_first);
|
||||
}
|
||||
log_assert(qstate->subquery_first == NULL);
|
||||
/* call de-init while all is OK */
|
||||
for(i=0; i<worker->daemon->num_modules; i++)
|
||||
(*worker->daemon->modfunc[i]->clear)(qstate, i);
|
||||
/* cleanup this query */
|
||||
region_free_all(qstate->region);
|
||||
query_info_clear(&qstate->qinfo);
|
||||
if(qstate->parent) {
|
||||
module_subreq_remove(qstate);
|
||||
free(qstate);
|
||||
}
|
||||
}
|
||||
|
||||
/** release workrequest back to the freelist,
|
||||
* note that the w->qinfo still needs to be cleared after this.
|
||||
*/
|
||||
|
|
@ -138,33 +162,50 @@ replyerror(int r, struct work_query* w)
|
|||
/** process incoming request */
|
||||
static void
|
||||
worker_process_query(struct worker* worker, struct work_query* w,
|
||||
enum module_ev event, struct outbound_entry* entry)
|
||||
struct module_qstate* qstate, enum module_ev event,
|
||||
struct outbound_entry* entry)
|
||||
{
|
||||
int i;
|
||||
enum module_ext_state s;
|
||||
if(event == module_event_new) {
|
||||
w->state.curmod = 0;
|
||||
qstate->curmod = 0;
|
||||
for(i=0; i<worker->daemon->num_modules; i++)
|
||||
w->state.ext_state[i] = module_state_initial;
|
||||
qstate->ext_state[i] = module_state_initial;
|
||||
}
|
||||
/* allow current module to run */
|
||||
(*worker->daemon->modfunc[w->state.curmod]->operate)(&w->state, event,
|
||||
w->state.curmod, entry);
|
||||
(*worker->daemon->modfunc[qstate->curmod]->operate)(qstate, event,
|
||||
qstate->curmod, entry);
|
||||
s = qstate->ext_state[qstate->curmod];
|
||||
/* TODO examine results, start further modules, etc.
|
||||
* assume it went to sleep
|
||||
*/
|
||||
region_free_all(worker->scratchpad);
|
||||
if(w->state.ext_state[w->state.curmod] == module_error) {
|
||||
region_free_all(w->state.region);
|
||||
/* subrequest done */
|
||||
/* TODO properly delete subquery */
|
||||
if(s == module_error && qstate->parent) {
|
||||
qstate_free(worker, qstate);
|
||||
worker_process_query(worker, w, qstate->parent,
|
||||
module_event_error, NULL);
|
||||
return;
|
||||
}
|
||||
if(s == module_finished && qstate->parent) {
|
||||
qstate_free(worker, qstate);
|
||||
worker_process_query(worker, w, qstate->parent,
|
||||
module_event_subq_done, NULL);
|
||||
return;
|
||||
}
|
||||
/* request done */
|
||||
if(s == module_error) {
|
||||
qstate_free(worker, qstate);
|
||||
replyerror(LDNS_RCODE_SERVFAIL, w);
|
||||
return;
|
||||
}
|
||||
if(w->state.ext_state[w->state.curmod] == module_finished) {
|
||||
if(s == module_finished) {
|
||||
memcpy(ldns_buffer_begin(w->query_reply.c->buffer),
|
||||
&w->query_id, sizeof(w->query_id));
|
||||
comm_point_send_reply(&w->query_reply);
|
||||
region_free_all(w->state.region);
|
||||
qstate_free(worker, qstate);
|
||||
req_release(w);
|
||||
query_info_clear(&w->state.qinfo);
|
||||
return;
|
||||
}
|
||||
/* suspend, waits for wakeup callback */
|
||||
|
|
@ -180,7 +221,8 @@ worker_handle_reply(struct comm_point* c, void* arg, int error,
|
|||
|
||||
w->state.reply = reply_info;
|
||||
if(error != 0) {
|
||||
worker_process_query(worker, w, module_event_timeout, NULL);
|
||||
worker_process_query(worker, w, &w->state,
|
||||
module_event_timeout, NULL);
|
||||
w->state.reply = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -191,11 +233,12 @@ worker_handle_reply(struct comm_point* c, void* arg, int error,
|
|||
|| LDNS_QDCOUNT(ldns_buffer_begin(c->buffer)) > 1) {
|
||||
/* error becomes timeout for the module as if this reply
|
||||
* never arrived. */
|
||||
worker_process_query(worker, w, module_event_timeout, NULL);
|
||||
worker_process_query(worker, w, &w->state,
|
||||
module_event_timeout, NULL);
|
||||
w->state.reply = NULL;
|
||||
return 0;
|
||||
}
|
||||
worker_process_query(worker, w, module_event_reply, NULL);
|
||||
worker_process_query(worker, w, &w->state, module_event_reply, NULL);
|
||||
w->state.reply = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -211,7 +254,8 @@ worker_handle_service_reply(struct comm_point* c, void* arg, int error,
|
|||
|
||||
w->state.reply = reply_info;
|
||||
if(error != 0) {
|
||||
worker_process_query(worker, w, module_event_timeout, e);
|
||||
worker_process_query(worker, w, e->qstate,
|
||||
module_event_timeout, e);
|
||||
w->state.reply = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -222,11 +266,12 @@ worker_handle_service_reply(struct comm_point* c, void* arg, int error,
|
|||
|| LDNS_QDCOUNT(ldns_buffer_begin(c->buffer)) > 1) {
|
||||
/* error becomes timeout for the module as if this reply
|
||||
* never arrived. */
|
||||
worker_process_query(worker, w, module_event_timeout, e);
|
||||
worker_process_query(worker, w, e->qstate,
|
||||
module_event_timeout, e);
|
||||
w->state.reply = NULL;
|
||||
return 0;
|
||||
}
|
||||
worker_process_query(worker, w, module_event_reply, e);
|
||||
worker_process_query(worker, w, e->qstate, module_event_reply, e);
|
||||
w->state.reply = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -477,7 +522,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
|||
|
||||
/* answer it */
|
||||
w->state.buf = c->buffer;
|
||||
worker_process_query(worker, w, module_event_new, NULL);
|
||||
worker_process_query(worker, w, &w->state, module_event_new, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -582,7 +627,7 @@ reqs_delete(struct worker* worker)
|
|||
n = q->all_next;
|
||||
log_assert(q->state.env->worker == worker);
|
||||
/* comm_reply closed in outside_network_delete */
|
||||
query_info_clear(&q->state.qinfo);
|
||||
qstate_free(worker, &q->state);
|
||||
region_destroy(q->state.region);
|
||||
free(q);
|
||||
q = n;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,9 @@
|
|||
24 May 2007: Wouter
|
||||
- small changes to prepare for subqueries.
|
||||
- iterator forwarder feature separated out.
|
||||
- iterator hints stub code, config file stub code, so that first
|
||||
testing can proceed locally.
|
||||
|
||||
23 May 2007: Wouter
|
||||
- outside network does precise timers for roundtrip estimates for rtt
|
||||
and for setting timeout for UDP. Pending_udp takes milliseconds.
|
||||
|
|
|
|||
|
|
@ -98,15 +98,20 @@ delegpt_add_target(struct delegpt* dp, struct region* region,
|
|||
uint8_t* name, size_t namelen, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen)
|
||||
{
|
||||
struct delegpt_addr* a;
|
||||
struct delegpt_ns* ns = delegpt_find_ns(dp, name, namelen);
|
||||
if(!ns) {
|
||||
/* ignore it */
|
||||
return 1;
|
||||
}
|
||||
ns->resolved = 1;
|
||||
|
||||
a = (struct delegpt_addr*)region_alloc(region,
|
||||
return delegpt_add_addr(dp, region, addr, addrlen);
|
||||
}
|
||||
|
||||
int
|
||||
delegpt_add_addr(struct delegpt* dp, struct region* region,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen)
|
||||
{
|
||||
struct delegpt_addr* a = (struct delegpt_addr*)region_alloc(region,
|
||||
sizeof(struct delegpt_addr));
|
||||
if(!a)
|
||||
return 0;
|
||||
|
|
@ -118,7 +123,6 @@ delegpt_add_target(struct delegpt* dp, struct region* region,
|
|||
memcpy(&a->addr, addr, addrlen);
|
||||
a->addrlen = addrlen;
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
void delegpt_log(struct delegpt* dp)
|
||||
|
|
@ -127,6 +131,10 @@ void delegpt_log(struct delegpt* dp)
|
|||
struct delegpt_ns* ns;
|
||||
struct delegpt_addr* a;
|
||||
dname_str(dp->name, buf);
|
||||
if(dp->nslist == NULL && dp->target_list == NULL) {
|
||||
log_info("DelegationPoint<%s>: empty", buf);
|
||||
return;
|
||||
}
|
||||
log_info("DelegationPoint<%s>:", buf);
|
||||
for(ns = dp->nslist; ns; ns = ns->next) {
|
||||
dname_str(ns->name, buf);
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ int delegpt_set_name(struct delegpt* dp, struct region* region, uint8_t* name);
|
|||
int delegpt_add_ns(struct delegpt* dp, struct region* region, uint8_t* name);
|
||||
|
||||
/**
|
||||
* Add address to the delegation point.
|
||||
* Add target address to the delegation point.
|
||||
* @param dp: delegation point.
|
||||
* @param region: where to allocate the info.
|
||||
* @param name: name for which target was found (must be in nslist).
|
||||
|
|
@ -142,6 +142,17 @@ int delegpt_add_target(struct delegpt* dp, struct region* region,
|
|||
uint8_t* name, size_t namelen, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen);
|
||||
|
||||
/**
|
||||
* Add address to the delegation point. No servername is associated or checked.
|
||||
* @param dp: delegation point.
|
||||
* @param region: where to allocate the info.
|
||||
* @param addr: the address.
|
||||
* @param addrlen: the length of addr.
|
||||
* @return false on error.
|
||||
*/
|
||||
int delegpt_add_addr(struct delegpt* dp, struct region* region,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen);
|
||||
|
||||
/**
|
||||
* Print the delegation point to the log. For debugging.
|
||||
* @param dp: delegation point.
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
#include "iterator/iter_delegpt.h"
|
||||
#include "util/region-allocator.h"
|
||||
#include "util/log.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/data/dname.h"
|
||||
|
||||
|
|
@ -147,8 +148,7 @@ compile_time_root_prime(struct region* r)
|
|||
|
||||
/** insert new hint info into hint structure */
|
||||
static int
|
||||
hints_insert(struct iter_hints* hints, uint16_t c, uint8_t* name,
|
||||
size_t namelen, int namelabs, struct delegpt* dp)
|
||||
hints_insert(struct iter_hints* hints, uint16_t c, struct delegpt* dp)
|
||||
{
|
||||
struct iter_hints_stub* node = region_alloc(hints->region,
|
||||
sizeof(struct iter_hints_stub));
|
||||
|
|
@ -156,11 +156,11 @@ hints_insert(struct iter_hints* hints, uint16_t c, uint8_t* name,
|
|||
return 0;
|
||||
node->node.key = node;
|
||||
node->hint_class = c;
|
||||
node->name = region_alloc_init(hints->region, name, namelen);
|
||||
node->name = region_alloc_init(hints->region, dp->name, dp->namelen);
|
||||
if(!node->name)
|
||||
return 0;
|
||||
node->namelen = namelen;
|
||||
node->namelabs = namelabs;
|
||||
node->namelen = dp->namelen;
|
||||
node->namelabs = dp->namelabs;
|
||||
node->dp = dp;
|
||||
if(!rbtree_insert(hints->tree, &node->node)) {
|
||||
log_err("second hints ignored.");
|
||||
|
|
@ -197,24 +197,123 @@ init_parents(struct iter_hints* hints)
|
|||
}
|
||||
}
|
||||
|
||||
int
|
||||
hints_apply_cfg(struct iter_hints* hints, struct config_file* ATTR_UNUSED(cfg))
|
||||
/** set stub name */
|
||||
static int
|
||||
read_stubs_name(struct iter_hints* hints, struct config_stub* s,
|
||||
struct delegpt* dp)
|
||||
{
|
||||
ldns_rdf* rdf;
|
||||
if(!s->name) {
|
||||
log_err("stub zone without a name");
|
||||
return 0;
|
||||
}
|
||||
rdf = ldns_dname_new_frm_str(s->name);
|
||||
if(!rdf) {
|
||||
log_err("cannot parse stub zone name %s", s->name);
|
||||
return 0;
|
||||
}
|
||||
if(!delegpt_set_name(dp, hints->region, ldns_rdf_data(rdf))) {
|
||||
ldns_rdf_deep_free(rdf);
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
ldns_rdf_deep_free(rdf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** set stub host names */
|
||||
static int
|
||||
read_stubs_host(struct iter_hints* hints, struct config_stub* s,
|
||||
struct delegpt* dp)
|
||||
{
|
||||
struct config_strlist* p;
|
||||
ldns_rdf* rdf;
|
||||
for(p = s->hosts; p; p = p->next) {
|
||||
log_assert(p->str);
|
||||
rdf = ldns_dname_new_frm_str(p->str);
|
||||
if(!rdf) {
|
||||
log_err("cannot parse stub %s nameserver name: '%s'",
|
||||
s->name, p->str);
|
||||
return 0;
|
||||
}
|
||||
if(!delegpt_add_ns(dp, hints->region, ldns_rdf_data(rdf))) {
|
||||
ldns_rdf_deep_free(rdf);
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
ldns_rdf_deep_free(rdf);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** set stub server addresses */
|
||||
static int
|
||||
read_stubs_addr(struct iter_hints* hints, struct config_stub* s,
|
||||
struct delegpt* dp)
|
||||
{
|
||||
struct config_strlist* p;
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t addrlen;
|
||||
for(p = s->addrs; p; p = p->next) {
|
||||
log_assert(p->str);
|
||||
if(!ipstrtoaddr(p->str, UNBOUND_DNS_PORT, &addr, &addrlen)) {
|
||||
log_err("cannot parse stub %s ip address: '%s'",
|
||||
s->name, p->str);
|
||||
return 0;
|
||||
}
|
||||
if(!delegpt_add_addr(dp, hints->region, &addr, addrlen)) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** read stubs config */
|
||||
static int
|
||||
read_stubs(struct iter_hints* hints, struct config_file* cfg)
|
||||
{
|
||||
struct config_stub* s;
|
||||
for(s = cfg->stubs; s; s = s->next) {
|
||||
struct delegpt* dp = delegpt_create(hints->region);
|
||||
if(!dp) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
if(!read_stubs_name(hints, s, dp) ||
|
||||
!read_stubs_host(hints, s, dp) ||
|
||||
!read_stubs_addr(hints, s, dp))
|
||||
return 0;
|
||||
if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp))
|
||||
return 0;
|
||||
delegpt_log(dp);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg)
|
||||
{
|
||||
struct delegpt* dp;
|
||||
free(hints->tree);
|
||||
hints->tree = rbtree_create(stub_cmp);
|
||||
if(!hints->tree)
|
||||
return 0;
|
||||
/* TODO: read hints from file named in cfg */
|
||||
/* TODO: read root hints from file named in cfg */
|
||||
|
||||
/* read stub hints */
|
||||
if(!read_stubs(hints, cfg))
|
||||
return 0;
|
||||
|
||||
/* use fallback compiletime root hints */
|
||||
dp = compile_time_root_prime(hints->region);
|
||||
if(!dp)
|
||||
return 0;
|
||||
if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp->name, dp->namelen,
|
||||
dp->namelabs, dp))
|
||||
return 0;
|
||||
delegpt_log(dp);
|
||||
if(!hints_lookup_root(hints, LDNS_RR_CLASS_IN)) {
|
||||
struct delegpt* dp = compile_time_root_prime(hints->region);
|
||||
verbose(VERB_ALGO, "no config, using builtin root hints.");
|
||||
if(!dp)
|
||||
return 0;
|
||||
if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp))
|
||||
return 0;
|
||||
delegpt_log(dp);
|
||||
}
|
||||
|
||||
init_parents(hints);
|
||||
return 1;
|
||||
|
|
@ -235,3 +334,44 @@ hints_lookup_root(struct iter_hints* hints, uint16_t qclass)
|
|||
return NULL;
|
||||
return stub->dp;
|
||||
}
|
||||
|
||||
struct delegpt*
|
||||
hints_lookup_stub(struct iter_hints* hints, uint8_t* qname,
|
||||
uint16_t qclass, struct delegpt* cache_dp)
|
||||
{
|
||||
/* first lookup the stub */
|
||||
rbnode_t* res = NULL;
|
||||
struct iter_hints_stub *result;
|
||||
struct iter_hints_stub key;
|
||||
key.node.key = &key;
|
||||
key.hint_class = qclass;
|
||||
key.name = qname;
|
||||
key.namelabs = dname_count_size_labels(qname, &key.namelen);
|
||||
if(rbtree_find_less_equal(hints->tree, &key, &res)) {
|
||||
/* exact */
|
||||
result = (struct iter_hints_stub*)res;
|
||||
} else {
|
||||
/* smaller element (or no element) */
|
||||
int m;
|
||||
result = (struct iter_hints_stub*)res;
|
||||
if(!result || result->hint_class != qclass)
|
||||
return NULL;
|
||||
/* count number of labels matched */
|
||||
(void)dname_lab_cmp(result->name, result->namelabs, key.name,
|
||||
key.namelabs, &m);
|
||||
while(result) { /* go up until qname is subdomain of stub */
|
||||
if(result->namelabs <= m)
|
||||
break;
|
||||
result = result->parent;
|
||||
}
|
||||
if(!result)
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
* If our cached delegation point is above the hint, we need to prime.
|
||||
*/
|
||||
if(dname_strict_subdomain(result->dp->name, result->dp->namelabs,
|
||||
cache_dp->name, cache_dp->namelabs))
|
||||
return result->dp; /* need to prime this stub */
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,4 +112,18 @@ int hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg);
|
|||
*/
|
||||
struct delegpt* hints_lookup_root(struct iter_hints* hints, uint16_t qclass);
|
||||
|
||||
/**
|
||||
* Given a qname/qclass combination, and the delegation point from the cache
|
||||
* for this qname/qclass, determine if this combination indicates that a
|
||||
* stub hint exists and must be primed.
|
||||
*
|
||||
* @param qname The qname that generated the delegation point.
|
||||
* @param qclass The qclass that generated the delegation point.
|
||||
* @param dp The cache generated delegation point.
|
||||
* @return A priming delegation point if there is a stub hint that must
|
||||
* be primed, otherwise null.
|
||||
*/
|
||||
struct delegpt* hints_lookup_stub(struct iter_hints* hints,
|
||||
uint8_t* qname, uint16_t qclass, struct delegpt* dp);
|
||||
|
||||
#endif /* ITERATOR_ITER_HINTS_H */
|
||||
|
|
|
|||
|
|
@ -180,18 +180,12 @@ iter_handlereply(struct module_qstate* qstate, int id,
|
|||
return 1;
|
||||
}
|
||||
|
||||
/** iterator operate on a query */
|
||||
/** perform forwarder functionality */
|
||||
static void
|
||||
iter_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
||||
perform_forward(struct module_qstate* qstate, enum module_ev event, int id,
|
||||
struct outbound_entry* outbound)
|
||||
{
|
||||
verbose(VERB_ALGO, "iterator[module %d] operate: extstate:%s event:%s",
|
||||
id, strextstate(qstate->ext_state[id]), strmodulevent(event));
|
||||
if(event == module_event_new) {
|
||||
if(!iter_new(qstate, id))
|
||||
qstate->ext_state[id] = module_error;
|
||||
return;
|
||||
}
|
||||
verbose(VERB_ALGO, "iterator: forwarding");
|
||||
/* it must be a query reply */
|
||||
if(!outbound) {
|
||||
verbose(VERB_ALGO, "query reply was not serviced");
|
||||
|
|
@ -211,6 +205,25 @@ iter_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
|||
qstate->ext_state[id] = module_error;
|
||||
}
|
||||
|
||||
/** iterator operate on a query */
|
||||
static void
|
||||
iter_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
||||
struct outbound_entry* outbound)
|
||||
{
|
||||
struct iter_env* ie = (struct iter_env*)qstate->env->modinfo[id];
|
||||
verbose(VERB_ALGO, "iterator[module %d] operate: extstate:%s event:%s",
|
||||
id, strextstate(qstate->ext_state[id]), strmodulevent(event));
|
||||
if(event == module_event_new) {
|
||||
if(!iter_new(qstate, id))
|
||||
qstate->ext_state[id] = module_error;
|
||||
return;
|
||||
}
|
||||
if(ie->fwd_addrlen != 0) {
|
||||
perform_forward(qstate, event, id, outbound);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/** iterator cleanup query state */
|
||||
static void
|
||||
iter_clear(struct module_qstate* qstate, int id)
|
||||
|
|
|
|||
|
|
@ -138,7 +138,8 @@ enum iter_state {
|
|||
* Per query state for the iterator module.
|
||||
*/
|
||||
struct iter_qstate {
|
||||
/** state of the iterator module
|
||||
/**
|
||||
* State of the iterator module.
|
||||
* This is the state that event is in or should sent to -- all
|
||||
* requests should start with the INIT_REQUEST_STATE. All
|
||||
* responses should start with QUERY_RESP_STATE. Subsequent
|
||||
|
|
@ -146,7 +147,8 @@ struct iter_qstate {
|
|||
*/
|
||||
enum iter_state state;
|
||||
|
||||
/** final state for the iterator module
|
||||
/**
|
||||
* Final state for the iterator module.
|
||||
* This is the state that responses should be routed to once the
|
||||
* response is final. For externally initiated queries, this
|
||||
* will be FINISHED_STATE, locally initiated queries will have
|
||||
|
|
@ -159,6 +161,8 @@ struct iter_qstate {
|
|||
* ANSWER section of a response before being sent upstream.
|
||||
*/
|
||||
struct packed_rrset_list* prepend_list;
|
||||
/** Last element of the prepend list */
|
||||
struct packed_rrset_list* prepend_last;
|
||||
|
||||
/**
|
||||
* This is the current delegation point for an in-progress query. This
|
||||
|
|
@ -167,6 +171,11 @@ struct iter_qstate {
|
|||
*/
|
||||
struct delegpt* dp;
|
||||
|
||||
/**
|
||||
* Current address target.
|
||||
*/
|
||||
struct delegpt_addr* current_target;
|
||||
|
||||
/** number of outstanding target sub queries */
|
||||
int num_target_queries;
|
||||
|
||||
|
|
@ -192,6 +201,7 @@ struct iter_qstate {
|
|||
|
||||
/**
|
||||
* Get the iterator function block.
|
||||
* @return: function block with function pointers to iterator methods.
|
||||
*/
|
||||
struct module_func_block* iter_get_funcblock();
|
||||
|
||||
|
|
|
|||
|
|
@ -361,6 +361,42 @@ dname_test_dname_lab_cmp()
|
|||
unit_assert(ml == 4);
|
||||
}
|
||||
|
||||
/** test dname_strict_subdomain */
|
||||
static void
|
||||
dname_test_strict_subdomain()
|
||||
{
|
||||
unit_assert(!dname_strict_subdomain(
|
||||
(uint8_t*)"", 1,
|
||||
(uint8_t*)"", 1));
|
||||
unit_assert(dname_strict_subdomain(
|
||||
(uint8_t*)"\003com", 2,
|
||||
(uint8_t*)"", 1));
|
||||
unit_assert(!dname_strict_subdomain(
|
||||
(uint8_t*)"", 1,
|
||||
(uint8_t*)"\003com", 2));
|
||||
unit_assert(dname_strict_subdomain(
|
||||
(uint8_t*)"\007example\003com", 3,
|
||||
(uint8_t*)"\003com", 2));
|
||||
unit_assert(!dname_strict_subdomain(
|
||||
(uint8_t*)"\003com", 2,
|
||||
(uint8_t*)"\007example\003com", 3));
|
||||
unit_assert(dname_strict_subdomain(
|
||||
(uint8_t*)"\007example\003com", 3,
|
||||
(uint8_t*)"", 1));
|
||||
unit_assert(!dname_strict_subdomain(
|
||||
(uint8_t*)"\003net", 2,
|
||||
(uint8_t*)"\003com", 2));
|
||||
unit_assert(!dname_strict_subdomain(
|
||||
(uint8_t*)"\003net", 2,
|
||||
(uint8_t*)"\003org", 2));
|
||||
unit_assert(!dname_strict_subdomain(
|
||||
(uint8_t*)"\007example\003net", 3,
|
||||
(uint8_t*)"\003org", 2));
|
||||
unit_assert(!dname_strict_subdomain(
|
||||
(uint8_t*)"\003net", 2,
|
||||
(uint8_t*)"\007example\003org", 3));
|
||||
}
|
||||
|
||||
void dname_test()
|
||||
{
|
||||
ldns_buffer* buff = ldns_buffer_new(65800);
|
||||
|
|
@ -372,5 +408,6 @@ void dname_test()
|
|||
dname_test_count_size_labels();
|
||||
dname_test_dname_lab_cmp();
|
||||
dname_test_pkt_dname_len(buff);
|
||||
dname_test_strict_subdomain();
|
||||
ldns_buffer_free(buff);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ config_create()
|
|||
cfg->do_daemonize = 1;
|
||||
cfg->num_ifs = 0;
|
||||
cfg->ifs = NULL;
|
||||
cfg->stubs = NULL;
|
||||
return cfg;
|
||||
error_exit:
|
||||
config_delete(cfg);
|
||||
|
|
@ -141,6 +142,19 @@ config_read(struct config_file* cfg, const char* filename)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/** delete config strlist */
|
||||
static void
|
||||
config_delstrlist(struct config_strlist* p)
|
||||
{
|
||||
struct config_strlist *np;
|
||||
while(p) {
|
||||
np = p->next;
|
||||
free(p->str);
|
||||
free(p);
|
||||
p = np;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
config_delete(struct config_file* cfg)
|
||||
{
|
||||
|
|
@ -157,6 +171,16 @@ config_delete(struct config_file* cfg)
|
|||
free(cfg->ifs[i]);
|
||||
free(cfg->ifs);
|
||||
}
|
||||
if(cfg->stubs) {
|
||||
struct config_stub* p = cfg->stubs, *np;
|
||||
while(p) {
|
||||
np = p->next;
|
||||
free(p->name);
|
||||
config_delstrlist(p->hosts);
|
||||
config_delstrlist(p->addrs);
|
||||
p = np;
|
||||
}
|
||||
}
|
||||
free(cfg);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@
|
|||
|
||||
#ifndef UTIL_CONFIG_FILE_H
|
||||
#define UTIL_CONFIG_FILE_H
|
||||
struct config_stub;
|
||||
struct config_strlist;
|
||||
|
||||
/**
|
||||
* The configuration options.
|
||||
|
|
@ -102,6 +104,9 @@ struct config_file {
|
|||
/** interface description strings (IP addresses) */
|
||||
char **ifs;
|
||||
|
||||
/** the stub definitions, linked list */
|
||||
struct config_stub* stubs;
|
||||
|
||||
/** chrootdir, if not "" or chroot will be done */
|
||||
char* chrootdir;
|
||||
/** username to change to, if not "". */
|
||||
|
|
@ -117,6 +122,30 @@ struct config_file {
|
|||
int do_daemonize;
|
||||
};
|
||||
|
||||
/**
|
||||
* Stub config options
|
||||
*/
|
||||
struct config_stub {
|
||||
/** next in list */
|
||||
struct config_stub* next;
|
||||
/** domain name (in text) of the stub apex domain */
|
||||
char* name;
|
||||
/** list of stub nameserver hosts (domain name) */
|
||||
struct config_strlist* hosts;
|
||||
/** list of stub nameserver addresses (IP address) */
|
||||
struct config_strlist* addrs;
|
||||
};
|
||||
|
||||
/**
|
||||
* List of strings for config options
|
||||
*/
|
||||
struct config_strlist {
|
||||
/** next item in list */
|
||||
struct config_strlist* next;
|
||||
/** config option string */
|
||||
char* str;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create config file structure. Filled with default values.
|
||||
* @return: the new structure or NULL on memory error.
|
||||
|
|
|
|||
|
|
@ -127,6 +127,10 @@ infra-cache-slabs{COLON} { YDOUT; return VAR_INFRA_CACHE_SLABS;}
|
|||
infra-cache-numhosts{COLON} { YDOUT; return VAR_INFRA_CACHE_NUMHOSTS;}
|
||||
infra-cache-numlame{COLON} { YDOUT; return VAR_INFRA_CACHE_NUMLAME;}
|
||||
num-queries-per-thread{COLON} { YDOUT; return VAR_NUM_QUERIES_PER_THREAD;}
|
||||
stub-zone{COLON} { YDOUT; return VAR_STUB_ZONE;}
|
||||
name{COLON} { YDOUT; return VAR_NAME;}
|
||||
stub-addr{COLON} { YDOUT; return VAR_STUB_ADDR;}
|
||||
stub-host{COLON} { YDOUT; return VAR_STUB_HOST;}
|
||||
{NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++;}
|
||||
|
||||
/* Quoted strings. Strip leading and ending quotes */
|
||||
|
|
|
|||
|
|
@ -75,7 +75,8 @@ extern struct config_parser_state* cfg_parser;
|
|||
%token VAR_MSG_CACHE_SIZE VAR_MSG_CACHE_SLABS VAR_NUM_QUERIES_PER_THREAD
|
||||
%token VAR_RRSET_CACHE_SIZE VAR_RRSET_CACHE_SLABS VAR_OUTGOING_NUM_TCP
|
||||
%token VAR_INFRA_HOST_TTL VAR_INFRA_LAME_TTL VAR_INFRA_CACHE_SLABS
|
||||
%token VAR_INFRA_CACHE_NUMHOSTS VAR_INFRA_CACHE_NUMLAME
|
||||
%token VAR_INFRA_CACHE_NUMHOSTS VAR_INFRA_CACHE_NUMLAME VAR_NAME
|
||||
%token VAR_STUB_ZONE VAR_STUB_HOST VAR_STUB_ADDR
|
||||
|
||||
%%
|
||||
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
|
||||
|
|
@ -102,7 +103,23 @@ content_server: server_num_threads | server_verbosity | server_port |
|
|||
server_rrset_cache_slabs | server_outgoing_num_tcp |
|
||||
server_infra_host_ttl | server_infra_lame_ttl |
|
||||
server_infra_cache_slabs | server_infra_cache_numhosts |
|
||||
server_infra_cache_numlame
|
||||
server_infra_cache_numlame | stubstart contents_stub
|
||||
;
|
||||
stubstart: VAR_STUB_ZONE
|
||||
{
|
||||
struct config_stub* s;
|
||||
OUTYY(("\nP(stub_zone:)\n"));
|
||||
s = (struct config_stub*)calloc(1, sizeof(struct config_stub));
|
||||
if(s) {
|
||||
s->next = cfg_parser->cfg->stubs;
|
||||
cfg_parser->cfg->stubs = s;
|
||||
} else
|
||||
yyerror("out of memory");
|
||||
}
|
||||
;
|
||||
contents_stub: contents_stub content_stub
|
||||
| ;
|
||||
content_stub: stub_name | stub_host | stub_addr
|
||||
;
|
||||
server_num_threads: VAR_NUM_THREADS STRING
|
||||
{
|
||||
|
|
@ -360,6 +377,38 @@ server_infra_cache_slabs: VAR_INFRA_CACHE_SLABS STRING
|
|||
free($2);
|
||||
}
|
||||
;
|
||||
stub_name: VAR_NAME STRING
|
||||
{
|
||||
OUTYY(("P(name:%s)\n", $2));
|
||||
cfg_parser->cfg->stubs->name = $2;
|
||||
}
|
||||
;
|
||||
stub_host: VAR_STUB_HOST STRING
|
||||
{
|
||||
struct config_strlist *s = (struct config_strlist*)calloc(1,
|
||||
sizeof(struct config_strlist));
|
||||
OUTYY(("P(stub-host:%s)\n", $2));
|
||||
if(s) {
|
||||
s->str = $2;
|
||||
s->next = cfg_parser->cfg->stubs->hosts;
|
||||
cfg_parser->cfg->stubs->hosts = s;
|
||||
} else
|
||||
yyerror("out of memory");
|
||||
}
|
||||
;
|
||||
stub_addr: VAR_STUB_ADDR STRING
|
||||
{
|
||||
struct config_strlist *s = (struct config_strlist*)calloc(1,
|
||||
sizeof(struct config_strlist));
|
||||
OUTYY(("P(stub-addr:%s)\n", $2));
|
||||
if(s) {
|
||||
s->str = $2;
|
||||
s->next = cfg_parser->cfg->stubs->addrs;
|
||||
cfg_parser->cfg->stubs->addrs = s;
|
||||
} else
|
||||
yyerror("out of memory");
|
||||
}
|
||||
;
|
||||
%%
|
||||
|
||||
/* parse helper routines could be here */
|
||||
|
|
|
|||
|
|
@ -509,3 +509,18 @@ void dname_str(uint8_t* dname, char* str)
|
|||
}
|
||||
*s = 0;
|
||||
}
|
||||
|
||||
int
|
||||
dname_strict_subdomain(uint8_t* d1, int labs1, uint8_t* d2, int labs2)
|
||||
{
|
||||
int m;
|
||||
/* check subdomain: d1: www.example.com. and d2: example.com. */
|
||||
if(labs2 >= labs1)
|
||||
return 0;
|
||||
if(dname_lab_cmp(d1, labs1, d2, labs2, &m) > 0) {
|
||||
/* subdomain if all labels match */
|
||||
return (m == labs2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -154,6 +154,17 @@ int dname_count_size_labels(uint8_t* dname, size_t* size);
|
|||
*/
|
||||
int dname_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, int* mlabs);
|
||||
|
||||
/**
|
||||
* See if domain name d1 is a strict subdomain of d2.
|
||||
* That is a subdomain, but not equal.
|
||||
* @param d1: domain name, uncompressed wireformat
|
||||
* @param labs1: number of labels in d1, including root label.
|
||||
* @param d2: domain name, uncompressed wireformat
|
||||
* @param labs2: number of labels in d2, including root label.
|
||||
* @return true if d1 is a subdomain of d2, but not equal to d2.
|
||||
*/
|
||||
int dname_strict_subdomain(uint8_t* d1, int labs1, uint8_t* d2, int labs2);
|
||||
|
||||
/**
|
||||
* Debug helper. Print wireformat dname to output.
|
||||
* @param out: like stdout or a file.
|
||||
|
|
|
|||
|
|
@ -68,3 +68,22 @@ strmodulevent(enum module_ev e)
|
|||
}
|
||||
return "bad_event_value";
|
||||
}
|
||||
|
||||
void
|
||||
module_subreq_remove(struct module_qstate* sub)
|
||||
{
|
||||
struct module_qstate* p, *prev = NULL;
|
||||
if(!sub || !sub->parent)
|
||||
return;
|
||||
p = sub->parent->subquery_first;
|
||||
while(p) {
|
||||
if(p == sub) {
|
||||
/* snip it off */
|
||||
if(prev) prev->subquery_next = p->subquery_next;
|
||||
else sub->parent->subquery_first = p->subquery_next;
|
||||
return;
|
||||
}
|
||||
prev = p;
|
||||
p = p->subquery_next;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -268,4 +268,11 @@ const char* strextstate(enum module_ext_state s);
|
|||
*/
|
||||
const char* strmodulevent(enum module_ev e);
|
||||
|
||||
/**
|
||||
* Remove subqrequest from list.
|
||||
* @param sub: subrequest. Parent pointer used to access list.
|
||||
* It is snipped off.
|
||||
*/
|
||||
void module_subreq_remove(struct module_qstate* sub);
|
||||
|
||||
#endif /* UTIL_MODULE_H */
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ log_addr(const char* str, struct sockaddr_storage* addr, socklen_t addrlen)
|
|||
strncpy(dest, "(inet_ntop error)", sizeof(dest));
|
||||
}
|
||||
port = ntohs(((struct sockaddr_in*)addr)->sin_port);
|
||||
verbose(VERB_DETAIL, "%s %s %s:%d (len %d)",
|
||||
verbose(VERB_DETAIL, "%s %s %s %d (len %d)",
|
||||
str, family, dest, (int)port, (int)addrlen);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue