preparatory work for iterator.

git-svn-id: file:///svn/unbound/trunk@336 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2007-05-24 13:24:44 +00:00
parent 42312206c9
commit 4a2c15be58
18 changed files with 495 additions and 53 deletions

View file

@ -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;

View file

@ -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.

View file

@ -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);

View file

@ -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.

View file

@ -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;
}

View file

@ -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 */

View file

@ -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)

View file

@ -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();

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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.

View file

@ -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 */

View file

@ -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 */

View file

@ -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;
}

View file

@ -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.

View 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;
}
}

View file

@ -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 */

View file

@ -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);
}