infra cache consolidated and stores per zone, IP.

git-svn-id: file:///svn/unbound/trunk@2525 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2011-10-26 15:46:23 +00:00
parent 3d5cef932e
commit 11f5e16932
20 changed files with 429 additions and 590 deletions

View file

@ -815,7 +815,8 @@ print_dp_details(SSL* ssl, struct worker* worker, struct delegpt* dp)
}
/* lookup in infra cache */
entry_ttl = infra_get_host_rto(worker->env.infra_cache,
&a->addr, a->addrlen, &ri, &delay, *worker->env.now);
&a->addr, a->addrlen, dp->name, dp->namelen,
&ri, &delay, *worker->env.now);
if(entry_ttl == -2 && ri.rto >= USEFUL_SERVER_TOP_TIMEOUT) {
if(!ssl_printf(ssl, "expired, rto %d msec.\n", ri.rto))
return;
@ -848,7 +849,8 @@ print_dp_details(SSL* ssl, struct worker* worker, struct delegpt* dp)
if(!ssl_printf(ssl, ", probedelay %d", delay))
return;
if(infra_host(worker->env.infra_cache, &a->addr, a->addrlen,
*worker->env.now, &edns_vs, &edns_lame_known, &to)) {
dp->name, dp->namelen, *worker->env.now, &edns_vs,
&edns_lame_known, &to)) {
if(edns_vs == -1) {
if(!ssl_printf(ssl, ", noEDNS%s.",
edns_lame_known?" probed":" assumed"))

View file

@ -1103,33 +1103,6 @@ do_flush_stats(SSL* ssl, struct worker* worker)
send_ok(ssl);
}
/** flush infra cache */
static void
do_flush_infra(SSL* ssl, struct worker* worker, char* arg)
{
struct sockaddr_storage addr;
socklen_t len;
if(strcmp(arg, "all") == 0) {
slabhash_clear(worker->env.infra_cache->hosts);
send_ok(ssl);
return;
}
if(!ipstrtoaddr(arg, UNBOUND_DNS_PORT, &addr, &len)) {
(void)ssl_printf(ssl, "error parsing ip addr: '%s'\n", arg);
return;
}
infra_remove_host(worker->env.infra_cache, &addr, len);
send_ok(ssl);
}
/** flush requestlist */
static void
do_flush_requestlist(SSL* ssl, struct worker* worker)
{
mesh_delete_all(worker->env.mesh);
send_ok(ssl);
}
/**
* Local info for deletion functions
*/
@ -1152,8 +1125,71 @@ struct del_info {
size_t num_msgs;
/** number of key entries removed */
size_t num_keys;
/** length of addr */
socklen_t addrlen;
/** socket address for host deletion */
struct sockaddr_storage addr;
};
/** callback to delete hosts in infra cache */
static void
infra_del_host(struct lruhash_entry* e, void* arg)
{
/* entry is locked */
struct del_info* inf = (struct del_info*)arg;
struct infra_key* k = (struct infra_key*)e->key;
if(sockaddr_cmp(&inf->addr, inf->addrlen, &k->addr, k->addrlen) == 0) {
struct infra_data* d = (struct infra_data*)e->data;
if(d->ttl >= inf->now) {
d->ttl = inf->expired;
inf->num_keys++;
}
}
}
/** flush infra cache */
static void
do_flush_infra(SSL* ssl, struct worker* worker, char* arg)
{
struct sockaddr_storage addr;
socklen_t len;
struct del_info inf;
if(strcmp(arg, "all") == 0) {
slabhash_clear(worker->env.infra_cache->hosts);
send_ok(ssl);
return;
}
if(!ipstrtoaddr(arg, UNBOUND_DNS_PORT, &addr, &len)) {
(void)ssl_printf(ssl, "error parsing ip addr: '%s'\n", arg);
return;
}
/* delete all entries from cache */
/* what we do is to set them all expired */
inf.worker = worker;
inf.name = 0;
inf.len = 0;
inf.labs = 0;
inf.now = *worker->env.now;
inf.expired = *worker->env.now;
inf.expired -= 3; /* handle 3 seconds skew between threads */
inf.num_rrsets = 0;
inf.num_msgs = 0;
inf.num_keys = 0;
inf.addrlen = len;
memmove(&inf.addr, &addr, len);
slabhash_traverse(worker->env.infra_cache->hosts, 1, &infra_del_host,
&inf);
send_ok(ssl);
}
/** flush requestlist */
static void
do_flush_requestlist(SSL* ssl, struct worker* worker)
{
mesh_delete_all(worker->env.mesh);
send_ok(ssl);
}
/** callback to delete rrsets in a zone */
static void
zone_del_rrset(struct lruhash_entry* e, void* arg)
@ -1527,68 +1563,36 @@ struct infra_arg {
SSL* ssl;
/** the time now */
uint32_t now;
/** ipstr */
char* ipstr;
};
/** callback for every lame element in the infra cache */
static void
dump_infra_lame(struct lruhash_entry* e, void* arg)
{
struct infra_arg* a = (struct infra_arg*)arg;
struct infra_lame_key* k = (struct infra_lame_key*)e->key;
struct infra_lame_data* d = (struct infra_lame_data*)e->data;
ldns_rdf* rdf;
size_t pos = 0;
char* nm;
/* skip expired */
if(d->ttl < a->now) {
return;
}
/* use ldns print for domain name */
if(ldns_wire2dname(&rdf, k->zonename, k->namelen, &pos)
!= LDNS_STATUS_OK)
return;
nm = ldns_rdf2str(rdf);
ldns_rdf_deep_free(rdf);
if(!ssl_printf(a->ssl, "%s lame %s ttl %d dnssec %d rec %d "
"A %d other %d\n", a->ipstr, nm, (int)(d->ttl - a->now),
d->isdnsseclame, d->rec_lame, d->lame_type_A, d->lame_other)) {
free(nm);
return;
}
free(nm);
}
/** callback for every host element in the infra cache */
static void
dump_infra_host(struct lruhash_entry* e, void* arg)
{
struct infra_arg* a = (struct infra_arg*)arg;
struct infra_host_key* k = (struct infra_host_key*)e->key;
struct infra_host_data* d = (struct infra_host_data*)e->data;
struct infra_key* k = (struct infra_key*)e->key;
struct infra_data* d = (struct infra_data*)e->data;
char ip_str[1024];
char name[257];
addr_to_str(&k->addr, k->addrlen, ip_str, sizeof(ip_str));
a->ipstr = ip_str;
dname_str(k->zonename, name);
/* skip expired stuff (only backed off) */
if(d->ttl < a->now) {
if(d->rtt.rto >= USEFUL_SERVER_TOP_TIMEOUT) {
if(!ssl_printf(a->ssl, "%s expired rto %d\n", ip_str,
d->rtt.rto)) return;
if(!ssl_printf(a->ssl, "%s %s expired rto %d\n", ip_str,
name, d->rtt.rto)) return;
}
if(d->lameness)
lruhash_traverse(d->lameness, 0, &dump_infra_lame, arg);
return;
}
if(!ssl_printf(a->ssl, "%s ttl %d ping %d var %d rtt %d rto %d "
"ednsknown %d edns %d delay %d\n",
ip_str, (int)(d->ttl - a->now),
if(!ssl_printf(a->ssl, "%s %s ttl %d ping %d var %d rtt %d rto %d "
"ednsknown %d edns %d delay %d lame dnssec %d rec %d A %d "
"other %d\n", ip_str, name, (int)(d->ttl - a->now),
d->rtt.srtt, d->rtt.rttvar, rtt_notimeout(&d->rtt), d->rtt.rto,
(int)d->edns_lame_known, (int)d->edns_version,
(int)(a->now<d->probedelay?d->probedelay-a->now:0)))
(int)(a->now<d->probedelay?d->probedelay-a->now:0),
(int)d->isdnsseclame, (int)d->rec_lame, (int)d->lame_type_A,
(int)d->lame_other))
return;
if(d->lameness)
lruhash_traverse(d->lameness, 0, &dump_infra_lame, arg);
}
/** do the dump_infra command */

View file

@ -1244,8 +1244,8 @@ outbound_entry_compare(void* a, void* b)
struct outbound_entry*
worker_send_query(uint8_t* qname, size_t qnamelen, uint16_t qtype,
uint16_t qclass, uint16_t flags, int dnssec, int want_dnssec,
struct sockaddr_storage* addr, socklen_t addrlen,
struct module_qstate* q)
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
size_t zonelen, struct module_qstate* q)
{
struct worker* worker = q->env->worker;
struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
@ -1255,7 +1255,7 @@ worker_send_query(uint8_t* qname, size_t qnamelen, uint16_t qtype,
e->qstate = q;
e->qsent = outnet_serviced_query(worker->back, qname,
qnamelen, qtype, qclass, flags, dnssec, want_dnssec,
q->env->cfg->tcp_upstream, addr, addrlen,
q->env->cfg->tcp_upstream, addr, addrlen, zone, zonelen,
worker_handle_service_reply, e, worker->back->udp_buff,
&outbound_entry_compare);
if(!e->qsent) {

View file

@ -175,6 +175,8 @@ void worker_sighandler(int sig, void* arg);
* @param want_dnssec: signatures needed.
* @param addr: where to.
* @param addrlen: length of addr.
* @param zone: wireformat dname of the zone.
* @param zonelen: length of zone name.
* @param q: wich query state to reactivate upon return.
* @return: false on failure (memory or socket related). no query was
* sent.
@ -182,7 +184,7 @@ void worker_sighandler(int sig, void* arg);
struct outbound_entry* worker_send_query(uint8_t* qname, size_t qnamelen,
uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
int want_dnssec, struct sockaddr_storage* addr, socklen_t addrlen,
struct module_qstate* q);
uint8_t* zone, size_t zonelen, struct module_qstate* q);
/**
* process control messages from the main thread. Frees the control

View file

@ -1,5 +1,6 @@
26 October 2011: Wouter
- iana portlist updated.
- Infra cache stores information about ping and lameness per IP, zone.
24 October 2011: Wouter
- Fix resolve of partners.extranet.microsoft.com with a fix for the

View file

@ -1723,7 +1723,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
iq->qchase.qname, iq->qchase.qname_len,
iq->qchase.qtype, iq->qchase.qclass,
iq->chase_flags | (iq->chase_to_rd?BIT_RD:0), EDNS_DO|BIT_CD,
iq->dnssec_expected, &target->addr, target->addrlen, qstate);
iq->dnssec_expected, &target->addr, target->addrlen,
iq->dp->name, iq->dp->namelen, qstate);
if(!outq) {
log_addr(VERB_DETAIL, "error sending query to auth server",
&target->addr, target->addrlen);

View file

@ -685,7 +685,7 @@ outbound_entry_compare(void* a, void* b)
struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen,
uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
int want_dnssec, struct sockaddr_storage* addr, socklen_t addrlen,
struct module_qstate* q)
uint8_t* zone, size_t zonelen, struct module_qstate* q)
{
struct libworker* w = (struct libworker*)q->env->worker;
struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
@ -695,7 +695,7 @@ struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen,
e->qstate = q;
e->qsent = outnet_serviced_query(w->back, qname,
qnamelen, qtype, qclass, flags, dnssec, want_dnssec,
q->env->cfg->tcp_upstream, addr, addrlen,
q->env->cfg->tcp_upstream, addr, addrlen, zone, zonelen,
libworker_handle_service_reply, e, w->back->udp_buff,
&outbound_entry_compare);
if(!e->qsent) {

View file

@ -118,6 +118,8 @@ void libworker_alloc_cleanup(void* arg);
* @param want_dnssec: signatures needed.
* @param addr: where to.
* @param addrlen: length of addr.
* @param zone: delegation point name.
* @param zonelen: length of zone name wireformat dname.
* @param q: wich query state to reactivate upon return.
* @return: false on failure (memory or socket related). no query was
* sent.
@ -125,7 +127,7 @@ void libworker_alloc_cleanup(void* arg);
struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen,
uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
int want_dnssec, struct sockaddr_storage* addr, socklen_t addrlen,
struct module_qstate* q);
uint8_t* zone, size_t zonelen, struct module_qstate* q);
/** process incoming replies from the network */
int libworker_handle_reply(struct comm_point* c, void* arg, int error,

515
services/cache/infra.c vendored
View file

@ -53,36 +53,44 @@
#define PROBE_MAXRTO 12000 /* in msec */
size_t
infra_host_sizefunc(void* k, void* ATTR_UNUSED(d))
infra_sizefunc(void* k, void* ATTR_UNUSED(d))
{
struct infra_host_key* key = (struct infra_host_key*)k;
return sizeof(*key) + sizeof(struct infra_host_data)
struct infra_key* key = (struct infra_key*)k;
return sizeof(*key) + sizeof(struct infra_data) + key->namelen
+ lock_get_mem(&key->entry.lock);
}
int
infra_host_compfunc(void* key1, void* key2)
infra_compfunc(void* key1, void* key2)
{
struct infra_host_key* k1 = (struct infra_host_key*)key1;
struct infra_host_key* k2 = (struct infra_host_key*)key2;
return sockaddr_cmp(&k1->addr, k1->addrlen, &k2->addr, k2->addrlen);
struct infra_key* k1 = (struct infra_key*)key1;
struct infra_key* k2 = (struct infra_key*)key2;
int r = sockaddr_cmp(&k1->addr, k1->addrlen, &k2->addr, k2->addrlen);
if(r != 0)
return 0;
if(k1->namelen != k2->namelen) {
if(k1->namelen < k2->namelen)
return -1;
return 1;
}
return query_dname_compare(k1->zonename, k2->zonename);
}
void
infra_host_delkeyfunc(void* k, void* ATTR_UNUSED(arg))
infra_delkeyfunc(void* k, void* ATTR_UNUSED(arg))
{
struct infra_host_key* key = (struct infra_host_key*)k;
struct infra_key* key = (struct infra_key*)k;
if(!key)
return;
lock_rw_destroy(&key->entry.lock);
free(key->zonename);
free(key);
}
void
infra_host_deldatafunc(void* d, void* ATTR_UNUSED(arg))
infra_deldatafunc(void* d, void* ATTR_UNUSED(arg))
{
struct infra_host_data* data = (struct infra_host_data*)d;
lruhash_delete(data->lameness);
struct infra_data* data = (struct infra_data*)d;
free(data);
}
@ -91,21 +99,16 @@ infra_create(struct config_file* cfg)
{
struct infra_cache* infra = (struct infra_cache*)calloc(1,
sizeof(struct infra_cache));
/* the size of the lameness tables are not counted */
size_t maxmem = cfg->infra_cache_numhosts *
(sizeof(struct infra_host_key)+sizeof(struct infra_host_data));
size_t maxmem = cfg->infra_cache_numhosts * (sizeof(struct infra_key)+
sizeof(struct infra_data)+INFRA_BYTES_NAME);
infra->hosts = slabhash_create(cfg->infra_cache_slabs,
INFRA_HOST_STARTSIZE, maxmem, &infra_host_sizefunc,
&infra_host_compfunc, &infra_host_delkeyfunc,
&infra_host_deldatafunc, NULL);
INFRA_HOST_STARTSIZE, maxmem, &infra_sizefunc, &infra_compfunc,
&infra_delkeyfunc, &infra_deldatafunc, NULL);
if(!infra->hosts) {
free(infra);
return NULL;
}
infra->host_ttl = cfg->host_ttl;
infra->lame_ttl = cfg->lame_ttl;
infra->max_lame_size = cfg->infra_cache_lame_size;
infra->jostle = cfg->jostle_time;
return infra;
}
@ -125,11 +128,8 @@ infra_adjust(struct infra_cache* infra, struct config_file* cfg)
if(!infra)
return infra_create(cfg);
infra->host_ttl = cfg->host_ttl;
infra->lame_ttl = cfg->lame_ttl;
infra->max_lame_size = cfg->infra_cache_lame_size;
infra->jostle = cfg->jostle_time;
maxmem = cfg->infra_cache_numhosts *
(sizeof(struct infra_host_key)+sizeof(struct infra_host_data));
maxmem = cfg->infra_cache_numhosts * (sizeof(struct infra_key)+
sizeof(struct infra_data)+INFRA_BYTES_NAME);
if(maxmem != slabhash_get_size(infra->hosts) ||
cfg->infra_cache_slabs != infra->hosts->size) {
infra_delete(infra);
@ -158,65 +158,44 @@ hash_addr(struct sockaddr_storage* addr, socklen_t addrlen)
return h;
}
void
infra_remove_host(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen)
/** calculate infra hash for a key */
static hashvalue_t
hash_infra(struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* name)
{
struct infra_host_key k;
k.addrlen = addrlen;
memcpy(&k.addr, addr, addrlen);
k.entry.hash = hash_addr(addr, addrlen);
k.entry.key = (void*)&k;
k.entry.data = NULL;
slabhash_remove(infra->hosts, k.entry.hash, &k);
return dname_query_hash(name, hash_addr(addr, addrlen));
}
/** lookup version that does not check host ttl (you check it) */
static struct lruhash_entry*
infra_lookup_host_nottl(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen, int wr)
struct lruhash_entry*
infra_lookup_nottl(struct infra_cache* infra, struct sockaddr_storage* addr,
socklen_t addrlen, uint8_t* name, size_t namelen, int wr)
{
struct infra_host_key k;
struct infra_key k;
k.addrlen = addrlen;
memcpy(&k.addr, addr, addrlen);
k.entry.hash = hash_addr(addr, addrlen);
k.namelen = namelen;
k.zonename = name;
k.entry.hash = hash_infra(addr, addrlen, name);
k.entry.key = (void*)&k;
k.entry.data = NULL;
return slabhash_lookup(infra->hosts, k.entry.hash, &k, wr);
}
struct infra_host_data*
infra_lookup_host(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen, int wr,
uint32_t timenow, struct infra_host_key** key)
{
struct infra_host_data* data;
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
addrlen, wr);
*key = NULL;
if(!e)
return NULL;
/* check TTL */
data = (struct infra_host_data*)e->data;
if(data->ttl < timenow) {
lock_rw_unlock(&e->lock);
return NULL;
}
*key = (struct infra_host_key*)e->key;
return data;
}
/** init the host elements (not lame elems) */
/** init the data elements */
static void
host_entry_init(struct infra_cache* infra, struct lruhash_entry* e,
data_entry_init(struct infra_cache* infra, struct lruhash_entry* e,
uint32_t timenow)
{
struct infra_host_data* data = (struct infra_host_data*)e->data;
struct infra_data* data = (struct infra_data*)e->data;
data->ttl = timenow + infra->host_ttl;
rtt_init(&data->rtt);
data->edns_version = 0;
data->edns_lame_known = 0;
data->probedelay = 0;
data->isdnsseclame = 0;
data->rec_lame = 0;
data->lame_type_A = 0;
data->lame_other = 0;
}
/**
@ -224,87 +203,93 @@ host_entry_init(struct infra_cache* infra, struct lruhash_entry* e,
* @param infra: infra structure with config parameters.
* @param addr: host address.
* @param addrlen: length of addr.
* @param name: name of zone
* @param namelen: length of name.
* @param tm: time now.
* @return: the new entry or NULL on malloc failure.
*/
static struct lruhash_entry*
new_host_entry(struct infra_cache* infra, struct sockaddr_storage* addr,
socklen_t addrlen, uint32_t tm)
new_entry(struct infra_cache* infra, struct sockaddr_storage* addr,
socklen_t addrlen, uint8_t* name, size_t namelen, uint32_t tm)
{
struct infra_host_data* data;
struct infra_host_key* key = (struct infra_host_key*)malloc(
sizeof(struct infra_host_key));
struct infra_data* data;
struct infra_key* key = (struct infra_key*)malloc(sizeof(*key));
if(!key)
return NULL;
data = (struct infra_host_data*)malloc(
sizeof(struct infra_host_data));
data = (struct infra_data*)malloc(sizeof(struct infra_data));
if(!data) {
free(key);
return NULL;
}
key->zonename = memdup(name, namelen);
if(!key->zonename) {
free(key);
free(data);
return NULL;
}
key->namelen = namelen;
lock_rw_init(&key->entry.lock);
key->entry.hash = hash_addr(addr, addrlen);
key->entry.hash = hash_infra(addr, addrlen, name);
key->entry.key = (void*)key;
key->entry.data = (void*)data;
key->addrlen = addrlen;
memcpy(&key->addr, addr, addrlen);
data->lameness = NULL;
host_entry_init(infra, &key->entry, tm);
data_entry_init(infra, &key->entry, tm);
return &key->entry;
}
int
infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
socklen_t addrlen, uint32_t timenow, int* edns_vs,
uint8_t* edns_lame_known, int* to)
socklen_t addrlen, uint8_t* nm, size_t nmlen, uint32_t timenow,
int* edns_vs, uint8_t* edns_lame_known, int* to)
{
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
addrlen, 0);
struct infra_host_data* data;
struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
nm, nmlen, 0);
struct infra_data* data;
int wr = 0;
if(e && ((struct infra_host_data*)e->data)->ttl < timenow) {
if(e && ((struct infra_data*)e->data)->ttl < timenow) {
/* it expired, try to reuse existing entry */
int old = ((struct infra_host_data*)e->data)->rtt.rto;
int old = ((struct infra_data*)e->data)->rtt.rto;
lock_rw_unlock(&e->lock);
e = infra_lookup_host_nottl(infra, addr, addrlen, 1);
e = infra_lookup_nottl(infra, addr, addrlen, nm, nmlen, 1);
if(e) {
/* if its still there we have a writelock, init */
/* re-initialise */
/* do not touch lameness, it may be valid still */
host_entry_init(infra, e, timenow);
data_entry_init(infra, e, timenow);
wr = 1;
/* TOP_TIMEOUT remains on reuse */
if(old >= USEFUL_SERVER_TOP_TIMEOUT)
((struct infra_host_data*)e->data)->rtt.rto
((struct infra_data*)e->data)->rtt.rto
= USEFUL_SERVER_TOP_TIMEOUT;
}
}
if(!e) {
/* insert new entry */
if(!(e = new_host_entry(infra, addr, addrlen, timenow)))
if(!(e = new_entry(infra, addr, addrlen, nm, nmlen, timenow)))
return 0;
data = (struct infra_host_data*)e->data;
*to = rtt_timeout(&data->rtt);
data = (struct infra_data*)e->data;
*edns_vs = data->edns_version;
*edns_lame_known = data->edns_lame_known;
*to = rtt_timeout(&data->rtt);
slabhash_insert(infra->hosts, e->hash, e, data, NULL);
return 1;
}
/* use existing entry */
data = (struct infra_host_data*)e->data;
*to = rtt_timeout(&data->rtt);
data = (struct infra_data*)e->data;
*edns_vs = data->edns_version;
*edns_lame_known = data->edns_lame_known;
*to = rtt_timeout(&data->rtt);
if(*to >= PROBE_MAXRTO && rtt_notimeout(&data->rtt)*4 <= *to) {
/* delay other queries, this is the probe query */
if(!wr) {
lock_rw_unlock(&e->lock);
e = infra_lookup_host_nottl(infra, addr, addrlen, 1);
e = infra_lookup_nottl(infra, addr,addrlen,nm,nmlen, 1);
if(!e) { /* flushed from cache real fast, no use to
allocate just for the probedelay */
return 1;
}
data = (struct infra_host_data*)e->data;
data = (struct infra_data*)e->data;
}
/* add 999 to round up the timeout value from msec to sec,
* then add a whole second so it is certain that this probe
@ -315,170 +300,38 @@ infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
return 1;
}
/** hash lameness key */
static hashvalue_t
hash_lameness(uint8_t* name)
{
return dname_query_hash(name, 0xab);
}
int
infra_lookup_lame(struct infra_host_data* host,
uint8_t* name, size_t namelen, uint32_t timenow,
int* dlame, int* rlame, int* alame, int* olame)
infra_set_lame(struct infra_cache* infra, struct sockaddr_storage* addr,
socklen_t addrlen, uint8_t* nm, size_t nmlen, uint32_t timenow,
int dnsseclame, int reclame, uint16_t qtype)
{
struct lruhash_entry* e;
struct infra_lame_key k;
struct infra_lame_data *d;
if(!host->lameness)
return 0;
k.entry.hash = hash_lameness(name);
k.zonename = name;
k.namelen = namelen;
k.entry.key = (void*)&k;
k.entry.data = NULL;
e = lruhash_lookup(host->lameness, k.entry.hash, &k, 0);
if(!e)
return 0;
d = (struct infra_lame_data*)e->data;
if(d->ttl < timenow) {
lock_rw_unlock(&e->lock);
return 0;
}
*dlame = d->isdnsseclame;
*rlame = d->rec_lame;
*alame = d->lame_type_A;
*olame = d->lame_other;
lock_rw_unlock(&e->lock);
return *dlame || *rlame || *alame || *olame;
}
size_t
infra_lame_sizefunc(void* k, void* ATTR_UNUSED(d))
{
struct infra_lame_key* key = (struct infra_lame_key*)k;
return sizeof(*key) + sizeof(struct infra_lame_data)
+ key->namelen + lock_get_mem(&key->entry.lock);
}
int
infra_lame_compfunc(void* key1, void* key2)
{
struct infra_lame_key* k1 = (struct infra_lame_key*)key1;
struct infra_lame_key* k2 = (struct infra_lame_key*)key2;
if(k1->namelen != k2->namelen) {
if(k1->namelen < k2->namelen)
return -1;
return 1;
}
return query_dname_compare(k1->zonename, k2->zonename);
}
void
infra_lame_delkeyfunc(void* k, void* ATTR_UNUSED(arg))
{
struct infra_lame_key* key = (struct infra_lame_key*)k;
if(!key)
return;
lock_rw_destroy(&key->entry.lock);
free(key->zonename);
free(key);
}
void
infra_lame_deldatafunc(void* d, void* ATTR_UNUSED(arg))
{
if(!d)
return;
free(d);
}
int
infra_set_lame(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* name, size_t namelen, uint32_t timenow, int dnsseclame,
int reclame, uint16_t qtype)
{
struct infra_host_data* data;
struct infra_data* data;
struct lruhash_entry* e;
int needtoinsert = 0;
struct infra_lame_key* k;
struct infra_lame_data* d;
/* allocate at start, easier cleanup (no locks held) */
k = (struct infra_lame_key*)malloc(sizeof(*k));
if(!k) {
log_err("set_lame: malloc failure");
return 0;
}
d = (struct infra_lame_data*)malloc(sizeof(*d));
if(!d) {
free(k);
log_err("set_lame: malloc failure");
return 0;
}
k->zonename = memdup(name, namelen);
if(!k->zonename) {
free(d);
free(k);
log_err("set_lame: malloc failure");
return 0;
}
lock_rw_init(&k->entry.lock);
k->entry.hash = hash_lameness(name);
k->entry.key = (void*)k;
k->entry.data = (void*)d;
d->ttl = timenow + infra->lame_ttl;
d->isdnsseclame = dnsseclame;
d->rec_lame = reclame;
d->lame_type_A = (!dnsseclame && !reclame && qtype == LDNS_RR_TYPE_A);
d->lame_other = (!dnsseclame && !reclame && qtype != LDNS_RR_TYPE_A);
k->namelen = namelen;
e = infra_lookup_host_nottl(infra, addr, addrlen, 1);
e = infra_lookup_nottl(infra, addr, addrlen, nm, nmlen, 1);
if(!e) {
/* insert it */
if(!(e = new_host_entry(infra, addr, addrlen, timenow))) {
free(k->zonename);
free(k);
free(d);
if(!(e = new_entry(infra, addr, addrlen, nm, nmlen, timenow))) {
log_err("set_lame: malloc failure");
return 0;
}
needtoinsert = 1;
} else if( ((struct infra_data*)e->data)->ttl < timenow) {
/* expired, reuse existing entry */
data_entry_init(infra, e, timenow);
}
/* got an entry, now set the zone lame */
data = (struct infra_host_data*)e->data;
if(!data->lameness) {
/* create hash table if not there already */
data->lameness = lruhash_create(INFRA_LAME_STARTSIZE,
infra->max_lame_size, infra_lame_sizefunc,
infra_lame_compfunc, infra_lame_delkeyfunc,
infra_lame_deldatafunc, NULL);
if(!data->lameness) {
log_err("set_lame: malloc failure");
if(needtoinsert) slabhash_insert(infra->hosts,
e->hash, e, e->data, NULL);
else { lock_rw_unlock(&e->lock); }
free(k->zonename);
free(k);
free(d);
return 0;
}
} else {
/* lookup existing lameness entry (if any) and merge data */
int dlame, rlame, alame, olame;
if(infra_lookup_lame(data, name, namelen, timenow,
&dlame, &rlame, &alame, &olame)) {
/* merge data into new structure */
if(dlame) d->isdnsseclame = 1;
if(rlame) d->rec_lame = 1;
if(alame) d->lame_type_A = 1;
if(olame) d->lame_other = 1;
}
}
/* inserts new entry, or updates TTL of older entry */
lruhash_insert(data->lameness, k->entry.hash, &k->entry, d, NULL);
data = (struct infra_data*)e->data;
/* merge data (if any) */
if(dnsseclame)
data->isdnsseclame = 1;
if(reclame)
data->rec_lame = 1;
if(!dnsseclame && !reclame && qtype == LDNS_RR_TYPE_A)
data->lame_type_A = 1;
if(!dnsseclame && !reclame && qtype != LDNS_RR_TYPE_A)
data->lame_other = 1;
/* done */
if(needtoinsert)
slabhash_insert(infra->hosts, e->hash, e, e->data, NULL);
else { lock_rw_unlock(&e->lock); }
@ -487,14 +340,15 @@ infra_set_lame(struct infra_cache* infra,
void
infra_update_tcp_works(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen)
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* nm,
size_t nmlen)
{
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
addrlen, 1);
struct infra_host_data* data;
struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
nm, nmlen, 1);
struct infra_data* data;
if(!e)
return; /* doesn't exist */
data = (struct infra_host_data*)e->data;
data = (struct infra_data*)e->data;
if(data->rtt.rto >= RTT_MAX_TIMEOUT)
/* do not disqualify this server altogether, it is better
* than nothing */
@ -503,24 +357,24 @@ infra_update_tcp_works(struct infra_cache* infra,
}
int
infra_rtt_update(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
int roundtrip, int orig_rtt, uint32_t timenow)
infra_rtt_update(struct infra_cache* infra, struct sockaddr_storage* addr,
socklen_t addrlen, uint8_t* nm, size_t nmlen, int roundtrip,
int orig_rtt, uint32_t timenow)
{
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
addrlen, 1);
struct infra_host_data* data;
struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
nm, nmlen, 1);
struct infra_data* data;
int needtoinsert = 0;
int rto = 1;
if(!e) {
if(!(e = new_host_entry(infra, addr, addrlen, timenow)))
if(!(e = new_entry(infra, addr, addrlen, nm, nmlen, timenow)))
return 0;
needtoinsert = 1;
} else if(((struct infra_host_data*)e->data)->ttl < timenow) {
host_entry_init(infra, e, timenow);
}
} else if(((struct infra_data*)e->data)->ttl < timenow) {
data_entry_init(infra, e, timenow);
}
/* have an entry, update the rtt */
data = (struct infra_host_data*)e->data;
data = (struct infra_data*)e->data;
if(roundtrip == -1) {
rtt_lost(&data->rtt, orig_rtt);
} else {
@ -537,15 +391,15 @@ infra_rtt_update(struct infra_cache* infra,
}
int infra_get_host_rto(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
struct rtt_info* rtt, int* delay, uint32_t timenow)
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* nm,
size_t nmlen, struct rtt_info* rtt, int* delay, uint32_t timenow)
{
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
addrlen, 0);
struct infra_host_data* data;
struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
nm, nmlen, 0);
struct infra_data* data;
int ttl = -2;
if(!e) return -1;
data = (struct infra_host_data*)e->data;
data = (struct infra_data*)e->data;
if(data->ttl >= timenow) {
ttl = (int)(data->ttl - timenow);
memmove(rtt, &data->rtt, sizeof(*rtt));
@ -558,23 +412,23 @@ int infra_get_host_rto(struct infra_cache* infra,
}
int
infra_edns_update(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
int edns_version, uint32_t timenow)
infra_edns_update(struct infra_cache* infra, struct sockaddr_storage* addr,
socklen_t addrlen, uint8_t* nm, size_t nmlen, int edns_version,
uint32_t timenow)
{
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
addrlen, 1);
struct infra_host_data* data;
struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
nm, nmlen, 1);
struct infra_data* data;
int needtoinsert = 0;
if(!e) {
if(!(e = new_host_entry(infra, addr, addrlen, timenow)))
if(!(e = new_entry(infra, addr, addrlen, nm, nmlen, timenow)))
return 0;
needtoinsert = 1;
} else if(((struct infra_host_data*)e->data)->ttl < timenow) {
host_entry_init(infra, e, timenow);
}
} else if(((struct infra_data*)e->data)->ttl < timenow) {
data_entry_init(infra, e, timenow);
}
/* have an entry, update the rtt, and the ttl */
data = (struct infra_host_data*)e->data;
data = (struct infra_data*)e->data;
/* do not update if noEDNS and stored is yesEDNS */
if(!(edns_version == -1 && (data->edns_version != -1 &&
data->edns_lame_known))) {
@ -588,57 +442,23 @@ infra_edns_update(struct infra_cache* infra,
return 1;
}
int
int
infra_get_lame_rtt(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* name, size_t namelen, uint16_t qtype,
int* lame, int* dnsseclame, int* reclame, int* rtt, uint32_t timenow)
{
struct infra_host_data* host;
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
addrlen, 0);
int dlm, rlm, alm, olm;
struct infra_data* host;
struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
name, namelen, 0);
if(!e)
return 0;
host = (struct infra_host_data*)e->data;
host = (struct infra_data*)e->data;
*rtt = rtt_unclamped(&host->rtt);
if(host->rtt.rto >= PROBE_MAXRTO && timenow < host->probedelay
&& rtt_notimeout(&host->rtt)*4 <= host->rtt.rto)
/* single probe for this domain, and we are not probing */
*rtt = USEFUL_SERVER_TOP_TIMEOUT;
/* check lameness first, if so, ttl on host does not matter anymore */
if(infra_lookup_lame(host, name, namelen, timenow,
&dlm, &rlm, &alm, &olm)) {
if(alm && qtype == LDNS_RR_TYPE_A) {
lock_rw_unlock(&e->lock);
*lame = 1;
*dnsseclame = 0;
*reclame = 0;
return 1;
} else if(olm && qtype != LDNS_RR_TYPE_A) {
lock_rw_unlock(&e->lock);
*lame = 1;
*dnsseclame = 0;
*reclame = 0;
return 1;
} else if(dlm) {
lock_rw_unlock(&e->lock);
*lame = 0;
*dnsseclame = 1;
*reclame = 0;
return 1;
} else if(rlm) {
lock_rw_unlock(&e->lock);
*lame = 0;
*dnsseclame = 0;
*reclame = 1;
return 1;
}
/* no lameness for this type of query */
}
*lame = 0;
*dnsseclame = 0;
*reclame = 0;
if(timenow > host->ttl) {
/* expired entry */
/* see if this can be a re-probe of an unresponsive server */
@ -652,43 +472,42 @@ infra_get_lame_rtt(struct infra_cache* infra,
lock_rw_unlock(&e->lock);
return 0;
}
/* check lameness first */
if(host->lame_type_A && qtype == LDNS_RR_TYPE_A) {
lock_rw_unlock(&e->lock);
*lame = 1;
*dnsseclame = 0;
*reclame = 0;
return 1;
} else if(host->lame_other && qtype != LDNS_RR_TYPE_A) {
lock_rw_unlock(&e->lock);
*lame = 1;
*dnsseclame = 0;
*reclame = 0;
return 1;
} else if(host->isdnsseclame) {
lock_rw_unlock(&e->lock);
*lame = 0;
*dnsseclame = 1;
*reclame = 0;
return 1;
} else if(host->rec_lame) {
lock_rw_unlock(&e->lock);
*lame = 0;
*dnsseclame = 0;
*reclame = 1;
return 1;
}
/* no lameness for this type of query */
lock_rw_unlock(&e->lock);
*lame = 0;
*dnsseclame = 0;
*reclame = 0;
return 1;
}
/** helper memory count for a host lame cache */
static size_t
count_host_lame(struct lruhash_entry* e)
{
struct infra_host_data* host_data = (struct infra_host_data*)e->data;
if(!host_data->lameness)
return 0;
return lruhash_get_mem(host_data->lameness);
}
size_t
infra_get_mem(struct infra_cache* infra)
{
size_t i, bin;
size_t s = sizeof(*infra) +
slabhash_get_mem(infra->hosts);
struct lruhash_entry* e;
for(i=0; i<infra->hosts->size; i++) {
lock_quick_lock(&infra->hosts->array[i]->lock);
for(bin=0; bin<infra->hosts->array[i]->size; bin++) {
lock_quick_lock(&infra->hosts->array[i]->
array[bin].lock);
/* count data size in bin items. */
for(e = infra->hosts->array[i]->array[bin].
overflow_list; e; e = e->overflow_next) {
lock_rw_rdlock(&e->lock);
s += count_host_lame(e);
lock_rw_unlock(&e->lock);
}
lock_quick_unlock(&infra->hosts->array[i]->
array[bin].lock);
}
lock_quick_unlock(&infra->hosts->array[i]->lock);
}
return s;
return sizeof(*infra) + slabhash_get_mem(infra->hosts);
}

140
services/cache/infra.h vendored
View file

@ -47,65 +47,50 @@ struct slabhash;
struct config_file;
/**
* Host information kept for every server.
* Host information kept for every server, per zone.
*/
struct infra_host_key {
struct infra_key {
/** the host address. */
struct sockaddr_storage addr;
/** length of addr. */
socklen_t addrlen;
/** hash table entry, data of type infra_host_data. */
/** zone name in wireformat */
uint8_t* zonename;
/** length of zonename */
size_t namelen;
/** hash table entry, data of type infra_data. */
struct lruhash_entry entry;
};
/**
* Host information encompasses host capabilities and retransmission timeouts.
* And lameness information (notAuthoritative, noEDNS, Recursive)
*/
struct infra_host_data {
struct infra_data {
/** TTL value for this entry. absolute time. */
uint32_t ttl;
/** time in seconds (absolute) when probing re-commences, 0 disabled */
uint32_t probedelay;
/** round trip times for timeout calculation */
struct rtt_info rtt;
/** Names of the zones that are lame. NULL=no lame zones. */
struct lruhash* lameness;
/** edns version that the host supports, -1 means no EDNS */
int edns_version;
/** if the EDNS lameness is already known or not.
* EDNS lame is when EDNS queries or replies are dropped,
* and cause a timeout */
uint8_t edns_lame_known;
};
/**
* Lameness information, per host, per zone.
*/
struct infra_lame_key {
/** key is zone name in wireformat */
uint8_t* zonename;
/** length of zonename */
size_t namelen;
/** lruhash entry */
struct lruhash_entry entry;
};
/**
* Lameness information. Expires.
* This host is lame because it is in the cache.
*/
struct infra_lame_data {
/** TTL of this entry. absolute time. */
uint32_t ttl;
/** is the host lame (does not serve the zone authoritatively),
* or is the host dnssec lame (does not serve DNSSEC data) */
int isdnsseclame;
uint8_t isdnsseclame;
/** is the host recursion lame (not AA, but RA) */
int rec_lame;
uint8_t rec_lame;
/** the host is lame (not authoritative) for A records */
int lame_type_A;
uint8_t lame_type_A;
/** the host is lame (not authoritative) for other query types */
int lame_other;
uint8_t lame_other;
};
/**
@ -116,18 +101,12 @@ struct infra_cache {
struct slabhash* hosts;
/** TTL value for host information, in seconds */
int host_ttl;
/** TTL for Lameness information, in seconds */
int lame_ttl;
/** infra lame cache max memory per host, in bytes */
size_t max_lame_size;
/** jostle timeout in msec */
size_t jostle;
};
/** infra host cache default hash lookup size */
#define INFRA_HOST_STARTSIZE 32
/** infra lame cache default hash lookup size */
#define INFRA_LAME_STARTSIZE 2
/** bytes per zonename reserved in the hostcache, dnamelen(zonename.com.) */
#define INFRA_BYTES_NAME 14
/**
* Create infra cache.
@ -142,10 +121,6 @@ struct infra_cache* infra_create(struct config_file* cfg);
*/
void infra_delete(struct infra_cache* infra);
/** explicitly delete an infra host element */
void infra_remove_host(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen);
/**
* Adjust infra cache to use updated configuration settings.
* This may clean the cache. Operates a bit like realloc.
@ -158,18 +133,18 @@ struct infra_cache* infra_adjust(struct infra_cache* infra,
struct config_file* cfg);
/**
* Lookup host data
* Plain find infra data function (used by the the other functions)
* @param infra: infrastructure cache.
* @param addr: host address.
* @param addrlen: length of addr.
* @param wr: set to true to get a writelock on the entry.
* @param timenow: what time it is now.
* @param key: the key for the host, returned so caller can unlock when done.
* @return: host data or NULL if not found or expired.
* @param name: domain name of zone.
* @param namelen: length of domain name.
* @param wr: if true, writelock, else readlock.
* @return the entry, could be expired (this is not checked) or NULL.
*/
struct infra_host_data* infra_lookup_host(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen, int wr,
uint32_t timenow, struct infra_host_key** key);
struct lruhash_entry* infra_lookup_nottl(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* name,
size_t namelen, int wr);
/**
* Find host information to send a packet. Creates new entry if not found.
@ -180,6 +155,8 @@ struct infra_host_data* infra_lookup_host(struct infra_cache* infra,
* @param infra: infrastructure cache.
* @param addr: host address.
* @param addrlen: length of addr.
* @param name: domain name of zone.
* @param namelen: length of domain name.
* @param timenow: what time it is now.
* @param edns_vs: edns version it supports, is returned.
* @param edns_lame_known: if EDNS lame (EDNS is dropped in transit) has
@ -188,25 +165,8 @@ struct infra_host_data* infra_lookup_host(struct infra_cache* infra,
* @return: 0 on error.
*/
int infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
socklen_t addrlen, uint32_t timenow, int* edns_vs,
uint8_t* edns_lame_known, int* to);
/**
* Check for lameness of this server for a particular zone.
* You must have a lock on the host structure.
* @param host: infrastructure cache data for the host. Caller holds lock.
* @param name: domain name of zone apex.
* @param namelen: length of domain name.
* @param timenow: what time it is now.
* @param dlame: if the function returns true, is set true if dnssec lame.
* @param rlame: if the function returns true, is set true if recursion lame.
* @param alame: if the function returns true, is set true if qtype A lame.
* @param olame: if the function returns true, is set true if qtype other lame.
* @return: 0 if not lame or unknown or timed out, 1 if lame
*/
int infra_lookup_lame(struct infra_host_data* host,
uint8_t* name, size_t namelen, uint32_t timenow,
int* dlame, int* rlame, int* alame, int* olame);
socklen_t addrlen, uint8_t* name, size_t namelen,
uint32_t timenow, int* edns_vs, uint8_t* edns_lame_known, int* to);
/**
* Set a host to be lame for the given zone.
@ -233,6 +193,8 @@ int infra_set_lame(struct infra_cache* infra,
* @param infra: infrastructure cache.
* @param addr: host address.
* @param addrlen: length of addr.
* @param name: zone name
* @param namelen: zone name length
* @param roundtrip: estimate of roundtrip time in milliseconds or -1 for
* timeout.
* @param orig_rtt: original rtt for the query that timed out (roundtrip==-1).
@ -240,8 +202,8 @@ int infra_set_lame(struct infra_cache* infra,
* @param timenow: what time it is now.
* @return: 0 on error. new rto otherwise.
*/
int infra_rtt_update(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
int infra_rtt_update(struct infra_cache* infra, struct sockaddr_storage* addr,
socklen_t addrlen, uint8_t* name, size_t namelen,
int roundtrip, int orig_rtt, uint32_t timenow);
/**
@ -249,15 +211,20 @@ int infra_rtt_update(struct infra_cache* infra,
* @param infra: infrastructure cache.
* @param addr: host address.
* @param addrlen: length of addr.
* @param name: name of zone
* @param namelen: length of name
*/
void infra_update_tcp_works(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen);
struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* name, size_t namelen);
/**
* Update edns information for the host.
* @param infra: infrastructure cache.
* @param addr: host address.
* @param addrlen: length of addr.
* @param name: name of zone
* @param namelen: length of name
* @param edns_version: the version that it publishes.
* If it is known to support EDNS then no-EDNS is not stored over it.
* @param timenow: what time it is now.
@ -265,7 +232,7 @@ void infra_update_tcp_works(struct infra_cache* infra,
*/
int infra_edns_update(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
int edns_version, uint32_t timenow);
uint8_t* name, size_t namelen, int edns_version, uint32_t timenow);
/**
* Get Lameness information and average RTT if host is in the cache.
@ -295,6 +262,8 @@ int infra_get_lame_rtt(struct infra_cache* infra,
* @param infra: infra cache.
* @param addr: host address.
* @param addrlen: length of addr.
* @param name: zone name
* @param namelen: zone name length
* @param rtt: the rtt_info is copied into here (caller alloced return struct).
* @param delay: probe delay (if any).
* @param timenow: what time it is now.
@ -302,8 +271,8 @@ int infra_get_lame_rtt(struct infra_cache* infra,
* TTL -2: found but expired.
*/
int infra_get_host_rto(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
struct rtt_info* rtt, int* delay, uint32_t timenow);
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* name,
size_t namelen, struct rtt_info* rtt, int* delay, uint32_t timenow);
/**
* Get memory used by the infra cache.
@ -314,28 +283,15 @@ size_t infra_get_mem(struct infra_cache* infra);
/** calculate size for the hashtable, does not count size of lameness,
* so the hashtable is a fixed number of items */
size_t infra_host_sizefunc(void* k, void* d);
size_t infra_sizefunc(void* k, void* d);
/** compare two addresses, returns -1, 0, or +1 */
int infra_host_compfunc(void* key1, void* key2);
int infra_compfunc(void* key1, void* key2);
/** delete key, and destroy the lock */
void infra_host_delkeyfunc(void* k, void* arg);
void infra_delkeyfunc(void* k, void* arg);
/** delete data and destroy the lameness hashtable */
void infra_host_deldatafunc(void* d, void* arg);
/** calculate size, which is fixed, zonename does not count so that
* a fixed number of items is stored */
size_t infra_lame_sizefunc(void* k, void* d);
/** compare zone names, returns -1, 0, +1 */
int infra_lame_compfunc(void* key1, void* key2);
/** free key, lock and zonename */
void infra_lame_delkeyfunc(void* k, void* arg);
/** free the lameness data */
void infra_lame_deldatafunc(void* d, void* arg);
void infra_deldatafunc(void* d, void* arg);
#endif /* SERVICES_CACHE_INFRA_H */

View file

@ -669,6 +669,7 @@ serviced_node_del(rbnode_t* node, void* ATTR_UNUSED(arg))
struct serviced_query* sq = (struct serviced_query*)node;
struct service_callback* p = sq->cblist, *np;
free(sq->qbuf);
free(sq->zone);
while(p) {
np = p->next;
free(p);
@ -1143,7 +1144,7 @@ lookup_serviced(struct outside_network* outnet, ldns_buffer* buff, int dnssec,
static struct serviced_query*
serviced_create(struct outside_network* outnet, ldns_buffer* buff, int dnssec,
int want_dnssec, int tcp_upstream, struct sockaddr_storage* addr,
socklen_t addrlen)
socklen_t addrlen, uint8_t* zone, size_t zonelen)
{
struct serviced_query* sq = (struct serviced_query*)malloc(sizeof(*sq));
#ifdef UNBOUND_DEBUG
@ -1158,6 +1159,13 @@ serviced_create(struct outside_network* outnet, ldns_buffer* buff, int dnssec,
return NULL;
}
sq->qbuflen = ldns_buffer_limit(buff);
sq->zone = memdup(zone, zonelen);
if(!sq->zone) {
free(sq->qbuf);
free(sq);
return NULL;
}
sq->zonelen = zonelen;
sq->dnssec = dnssec;
sq->want_dnssec = want_dnssec;
sq->tcp_upstream = tcp_upstream;
@ -1324,8 +1332,8 @@ serviced_udp_send(struct serviced_query* sq, ldns_buffer* buff)
uint8_t edns_lame_known;
uint32_t now = *sq->outnet->now_secs;
if(!infra_host(sq->outnet->infra, &sq->addr, sq->addrlen, now, &vs,
&edns_lame_known, &rtt))
if(!infra_host(sq->outnet->infra, &sq->addr, sq->addrlen, sq->zone,
sq->zonelen, now, &vs, &edns_lame_known, &rtt))
return 0;
sq->last_rtt = rtt;
verbose(VERB_ALGO, "EDNS lookup known=%d vs=%d", edns_lame_known, vs);
@ -1495,7 +1503,7 @@ serviced_tcp_callback(struct comm_point* c, void* arg, int error,
&sq->addr, sq->addrlen);
if(error==NETEVENT_NOERROR)
infra_update_tcp_works(sq->outnet->infra, &sq->addr,
sq->addrlen);
sq->addrlen, sq->zone, sq->zonelen);
if(error==NETEVENT_NOERROR && sq->status == serviced_query_TCP_EDNS &&
(LDNS_RCODE_WIRE(ldns_buffer_begin(c->buffer)) ==
LDNS_RCODE_FORMERR || LDNS_RCODE_WIRE(ldns_buffer_begin(
@ -1516,7 +1524,8 @@ serviced_tcp_callback(struct comm_point* c, void* arg, int error,
/* only store noEDNS in cache if domain is noDNSSEC */
if(!sq->want_dnssec)
if(!infra_edns_update(sq->outnet->infra, &sq->addr,
sq->addrlen, -1, *sq->outnet->now_secs))
sq->addrlen, sq->zone, sq->zonelen, -1,
*sq->outnet->now_secs))
log_err("Out of memory caching no edns for host");
sq->status = serviced_query_TCP;
}
@ -1531,7 +1540,8 @@ serviced_tcp_callback(struct comm_point* c, void* arg, int error,
verbose(VERB_ALGO, "measured TCP-time at %d msec", roundtime);
log_assert(roundtime >= 0);
if(!infra_rtt_update(sq->outnet->infra, &sq->addr, sq->addrlen,
roundtime, sq->last_rtt, (uint32_t)now.tv_sec))
sq->zone, sq->zonelen, roundtime, sq->last_rtt,
(uint32_t)now.tv_sec))
log_err("out of memory noting rtt.");
}
}
@ -1572,8 +1582,9 @@ serviced_tcp_send(struct serviced_query* sq, ldns_buffer* buff)
{
int vs, rtt;
uint8_t edns_lame_known;
if(!infra_host(sq->outnet->infra, &sq->addr, sq->addrlen,
*sq->outnet->now_secs, &vs, &edns_lame_known, &rtt))
if(!infra_host(sq->outnet->infra, &sq->addr, sq->addrlen, sq->zone,
sq->zonelen, *sq->outnet->now_secs, &vs, &edns_lame_known,
&rtt))
return 0;
if(vs != -1)
sq->status = serviced_query_TCP_EDNS;
@ -1620,7 +1631,8 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
}
sq->retry++;
if(!(rto=infra_rtt_update(outnet->infra, &sq->addr, sq->addrlen,
-1, sq->last_rtt, (uint32_t)now.tv_sec)))
sq->zone, sq->zonelen, -1, sq->last_rtt,
(uint32_t)now.tv_sec)))
log_err("out of memory in UDP exponential backoff");
if(sq->retry < OUTBOUND_UDP_RETRY) {
log_name_addr(VERB_ALGO, "retry query", sq->qbuf+10,
@ -1664,7 +1676,7 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
/* only store noEDNS in cache if domain is noDNSSEC */
if(!sq->want_dnssec)
if(!infra_edns_update(outnet->infra, &sq->addr, sq->addrlen,
-1, (uint32_t)now.tv_sec)) {
sq->zone, sq->zonelen, -1, (uint32_t)now.tv_sec)) {
log_err("Out of memory caching no edns for host");
}
sq->status = serviced_query_UDP;
@ -1674,7 +1686,7 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
log_addr(VERB_ALGO, "serviced query: EDNS works for",
&sq->addr, sq->addrlen);
if(!infra_edns_update(outnet->infra, &sq->addr, sq->addrlen,
0, (uint32_t)now.tv_sec)) {
sq->zone, sq->zonelen, 0, (uint32_t)now.tv_sec)) {
log_err("Out of memory caching edns works");
}
sq->edns_lame_known = 1;
@ -1691,7 +1703,7 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
log_addr(VERB_ALGO, "serviced query: EDNS fails for",
&sq->addr, sq->addrlen);
if(!infra_edns_update(outnet->infra, &sq->addr, sq->addrlen,
-1, (uint32_t)now.tv_sec)) {
sq->zone, sq->zonelen, -1, (uint32_t)now.tv_sec)) {
log_err("Out of memory caching no edns for host");
}
} else {
@ -1710,7 +1722,8 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
verbose(VERB_ALGO, "measured roundtrip at %d msec", roundtime);
log_assert(roundtime >= 0);
if(!infra_rtt_update(outnet->infra, &sq->addr, sq->addrlen,
roundtime, sq->last_rtt, (uint32_t)now.tv_sec))
sq->zone, sq->zonelen, roundtime, sq->last_rtt,
(uint32_t)now.tv_sec))
log_err("out of memory noting rtt.");
}
} /* end of if_!fallback_tcp */
@ -1750,8 +1763,8 @@ struct serviced_query*
outnet_serviced_query(struct outside_network* outnet,
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
uint16_t flags, int dnssec, int want_dnssec, int tcp_upstream,
struct sockaddr_storage* addr, socklen_t addrlen,
comm_point_callback_t* callback, void* callback_arg,
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
size_t zonelen, comm_point_callback_t* callback, void* callback_arg,
ldns_buffer* buff, int (*arg_compare)(void*,void*))
{
struct serviced_query* sq;
@ -1769,7 +1782,7 @@ outnet_serviced_query(struct outside_network* outnet,
if(!sq) {
/* make new serviced query entry */
sq = serviced_create(outnet, buff, dnssec, want_dnssec,
tcp_upstream, addr, addrlen);
tcp_upstream, addr, addrlen, zone, zonelen);
if(!sq) {
free(cb);
return NULL;

View file

@ -304,6 +304,10 @@ struct serviced_query {
struct sockaddr_storage addr;
/** length of addr field in use. */
socklen_t addrlen;
/** zone name, uncompressed domain name in wireformat */
uint8_t* zone;
/** length of zone name */
size_t zonelen;
/** current status */
enum serviced_query_status {
/** initial status */
@ -449,6 +453,10 @@ void pending_delete(struct outside_network* outnet, struct pending* p);
* @param callback_arg: user argument to callback function.
* @param addr: to which server to send the query.
* @param addrlen: length of addr.
* @param zone: name of the zone of the delegation point. wireformat dname.
This is the delegation point name for which the server is deemed
authoritative.
* @param zonelen: length of zone.
* @param buff: scratch buffer to create query contents in. Empty on exit.
* @param arg_compare: function to compare callback args, return true if
* identical. It is given the callback_arg and args that are listed.
@ -458,8 +466,8 @@ void pending_delete(struct outside_network* outnet, struct pending* p);
struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
uint16_t flags, int dnssec, int want_dnssec, int tcp_upstream,
struct sockaddr_storage* addr, socklen_t addrlen,
comm_point_callback_t* callback, void* callback_arg,
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
size_t zonelen, comm_point_callback_t* callback, void* callback_arg,
ldns_buffer* buff, int (*arg_compare)(void*,void*));
/**

View file

@ -51,6 +51,7 @@
#include "util/data/msgparse.h"
#include "util/data/msgreply.h"
#include "util/data/msgencode.h"
#include "util/data/dname.h"
#include "util/config_file.h"
#include "services/listen_dnsport.h"
#include "services/outside_network.h"
@ -548,11 +549,17 @@ static void
do_infra_rtt(struct replay_runtime* runtime)
{
struct replay_moment* now = runtime->now;
int rto = infra_rtt_update(runtime->infra, &now->addr,
now->addrlen, atoi(now->string), -1, runtime->now_secs);
int rto;
ldns_rdf* dp = ldns_dname_new_frm_str(now->variable);
if(!dp) fatal_exit("cannot parse %s", now->variable);
rto = infra_rtt_update(runtime->infra, &now->addr,
now->addrlen, ldns_rdf_data(dp), ldns_rdf_size(dp),
atoi(now->string), -1, runtime->now_secs);
log_addr(0, "INFRA_RTT for", &now->addr, now->addrlen);
log_info("INFRA_RTT(roundtrip %d): rto of %d", atoi(now->string), rto);
log_info("INFRA_RTT(%s roundtrip %d): rto of %d", now->variable,
atoi(now->string), rto);
if(rto == 0) fatal_exit("infra_rtt_update failed");
ldns_rdf_deep_free(dp);
}
/**
@ -1008,19 +1015,22 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
uint16_t flags, int dnssec, int ATTR_UNUSED(want_dnssec),
int ATTR_UNUSED(tcp_upstream), struct sockaddr_storage* addr,
socklen_t addrlen, comm_point_callback_t* callback, void* callback_arg,
socklen_t addrlen, uint8_t* zone, size_t ATTR_UNUSED(zonelen),
comm_point_callback_t* callback, void* callback_arg,
ldns_buffer* ATTR_UNUSED(buff), int (*arg_compare)(void*,void*))
{
struct replay_runtime* runtime = (struct replay_runtime*)outnet->base;
struct fake_pending* pend = (struct fake_pending*)calloc(1,
sizeof(struct fake_pending));
char z[256];
ldns_status status;
(void)arg_compare;
log_assert(pend);
log_nametypeclass(VERB_OPS, "pending serviced query",
qname, qtype, qclass);
verbose(VERB_OPS, "pending serviced query flags%s%s%s%s",
(flags&BIT_RD)?" RD":"", (flags&BIT_CD)?" CD":"",
dname_str(zone, z);
verbose(VERB_OPS, "pending serviced query zone %s flags%s%s%s%s",
z, (flags&BIT_RD)?" RD":"", (flags&BIT_CD)?" CD":"",
(flags&~(BIT_RD|BIT_CD))?" MORE":"", (dnssec)?" DO":"");
/* create packet with EDNS */

View file

@ -331,23 +331,31 @@ replay_moment_read(char* remain, FILE* in, const char* name, int* lineno,
mom->evt_type = repevt_assign;
read_assign_step(remain, mom);
} else if(parse_keyword(&remain, "INFRA_RTT")) {
char *s;
char *s, *m;
mom->evt_type = repevt_infra_rtt;
while(isspace((int)*remain))
remain++;
s = remain;
remain = strchr(s, ' ');
if(!remain) fatal_exit("expected two args for INFRA_RTT");
if(!remain) fatal_exit("expected three args for INFRA_RTT");
remain[0] = 0;
remain++;
while(isspace((int)*remain))
remain++;
m = strchr(remain, ' ');
if(!m) fatal_exit("expected three args for INFRA_RTT");
m[0] = 0;
m++;
while(isspace((int)*m))
m++;
if(!extstrtoaddr(s, &mom->addr, &mom->addrlen))
fatal_exit("bad infra_rtt address %s", s);
if(strlen(remain)>0 && remain[strlen(remain)-1]=='\n')
remain[strlen(remain)-1] = 0;
mom->string = strdup(remain);
if(strlen(m)>0 && m[strlen(m)-1]=='\n')
m[strlen(m)-1] = 0;
mom->variable = strdup(remain);
mom->string = strdup(m);
if(!mom->string) fatal_exit("out of memory");
if(!mom->variable) fatal_exit("out of memory");
} else {
log_err("%d: unknown event type %s", *lineno, remain);
free(mom);

View file

@ -75,7 +75,7 @@
* the step waits for traffic to stop.
* o CHECK_AUTOTRUST [id] - followed by FILE_BEGIN [to match] FILE_END.
* The file contents is macro expanded before match.
* o INFRA_RTT [ip] [rtt] - update infra cache entry with rtt.
* o INFRA_RTT [ip] [dp] [rtt] - update infra cache entry with rtt.
* o ERROR
* ; following entry starts on the next line, ENTRY_BEGIN.
* ; more STEP items

View file

@ -401,6 +401,25 @@ rtt_test(void)
#include "services/cache/infra.h"
#include "util/config_file.h"
/* lookup and get key and data structs easily */
static struct infra_data* infra_lookup_host(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
size_t zonelen, int wr, uint32_t now, struct infra_key** k)
{
struct infra_data* d;
struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
zone, zonelen, wr);
if(!e) return NULL;
d = (struct infra_data*)e->data;
if(d->ttl < now) {
lock_rw_unlock(&e->lock);
return NULL;
}
*k = (struct infra_key*)e->key;
return d;
}
/** test host cache */
static void
infra_test(void)
@ -414,70 +433,63 @@ infra_test(void)
uint32_t now = 0;
uint8_t edns_lame;
int vs, to;
struct infra_host_key* k;
struct infra_host_data* d;
struct infra_key* k;
struct infra_data* d;
int init = 376;
int dlame, rlame, alame, olame;
unit_show_feature("infra cache");
unit_assert(ipstrtoaddr("127.0.0.1", 53, &one, &onelen));
slab = infra_create(cfg);
unit_assert( infra_host(slab, (struct sockaddr_storage*)&one,
(socklen_t)sizeof(int), now, &vs, &edns_lame, &to) );
unit_assert( infra_host(slab, &one, onelen, zone, zonelen, now,
&vs, &edns_lame, &to) );
unit_assert( vs == 0 && to == init && edns_lame == 0 );
unit_assert( infra_rtt_update(slab, &one, onelen, -1, init, now) );
unit_assert( infra_host(slab, &one, onelen,
unit_assert( infra_rtt_update(slab, &one, onelen, zone, zonelen, -1, init, now) );
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
now, &vs, &edns_lame, &to) );
unit_assert( vs == 0 && to == init*2 && edns_lame == 0 );
unit_assert( infra_edns_update(slab, &one, onelen, -1, now) );
unit_assert( infra_host(slab, &one, onelen,
unit_assert( infra_edns_update(slab, &one, onelen, zone, zonelen, -1, now) );
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
now, &vs, &edns_lame, &to) );
unit_assert( vs == -1 && to == init*2 && edns_lame == 1);
now += cfg->host_ttl + 10;
unit_assert( infra_host(slab, &one, onelen,
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
now, &vs, &edns_lame, &to) );
unit_assert( vs == 0 && to == init && edns_lame == 0 );
unit_assert( infra_set_lame(slab, &one, onelen,
unit_assert( infra_set_lame(slab, &one, onelen,
zone, zonelen, now, 0, 0, LDNS_RR_TYPE_A) );
unit_assert( (d=infra_lookup_host(slab, &one, onelen, 0, now, &k)) );
unit_assert( (d=infra_lookup_host(slab, &one, onelen, zone, zonelen, 0, now, &k)) );
unit_assert( d->ttl == now+cfg->host_ttl );
unit_assert( d->edns_version == 0 );
unit_assert( infra_lookup_lame(d, zone, zonelen, now,
&dlame, &rlame, &alame, &olame) );
unit_assert(!dlame && !rlame && alame && !olame);
unit_assert( !infra_lookup_lame(d, zone, zonelen,
now+cfg->lame_ttl+10, &dlame, &rlame, &alame, &olame) );
unit_assert( !infra_lookup_lame(d, (uint8_t*)"\000", 1, now,
&dlame, &rlame, &alame, &olame) );
unit_assert(!d->isdnsseclame && !d->rec_lame && d->lame_type_A &&
!d->lame_other);
lock_rw_unlock(&k->entry.lock);
/* test merge of data */
unit_assert( infra_set_lame(slab, &one, onelen,
unit_assert( infra_set_lame(slab, &one, onelen,
zone, zonelen, now, 0, 0, LDNS_RR_TYPE_AAAA) );
unit_assert( (d=infra_lookup_host(slab, &one, onelen, 0, now, &k)) );
unit_assert( infra_lookup_lame(d, zone, zonelen, now,
&dlame, &rlame, &alame, &olame) );
unit_assert(!dlame && !rlame && alame && olame);
unit_assert( (d=infra_lookup_host(slab, &one, onelen, zone, zonelen, 0, now, &k)) );
unit_assert(!d->isdnsseclame && !d->rec_lame && d->lame_type_A &&
d->lame_other);
lock_rw_unlock(&k->entry.lock);
/* test that noEDNS cannot overwrite known-yesEDNS */
now += cfg->host_ttl + 10;
unit_assert( infra_host(slab, &one, onelen,
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
now, &vs, &edns_lame, &to) );
unit_assert( vs == 0 && to == init && edns_lame == 0 );
unit_assert( infra_edns_update(slab, &one, onelen, 0, now) );
unit_assert( infra_host(slab, &one, onelen,
unit_assert( infra_edns_update(slab, &one, onelen, zone, zonelen, 0, now) );
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
now, &vs, &edns_lame, &to) );
unit_assert( vs == 0 && to == init && edns_lame == 1 );
unit_assert( infra_edns_update(slab, &one, onelen, -1, now) );
unit_assert( infra_host(slab, &one, onelen,
unit_assert( infra_edns_update(slab, &one, onelen, zone, zonelen, -1, now) );
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
now, &vs, &edns_lame, &to) );
unit_assert( vs == 0 && to == init && edns_lame == 1 );

View file

@ -238,7 +238,7 @@ RANGE_END
; store bad timing for one server to influence server selection
; 1.2.3.44 (ns.example.net) gets 900 msec.
; so the 376 ns.example.com is preferred.
STEP 1 INFRA_RTT 1.2.3.44 900
STEP 1 INFRA_RTT 1.2.3.44 example.net. 900
STEP 10 QUERY
ENTRY_BEGIN

View file

@ -194,9 +194,8 @@ fptr_whitelist_hash_sizefunc(lruhash_sizefunc_t fptr)
{
if(fptr == &msgreply_sizefunc) return 1;
else if(fptr == &ub_rrset_sizefunc) return 1;
else if(fptr == &infra_host_sizefunc) return 1;
else if(fptr == &infra_sizefunc) return 1;
else if(fptr == &key_entry_sizefunc) return 1;
else if(fptr == &infra_lame_sizefunc) return 1;
else if(fptr == &test_slabhash_sizefunc) return 1;
return 0;
}
@ -206,9 +205,8 @@ fptr_whitelist_hash_compfunc(lruhash_compfunc_t fptr)
{
if(fptr == &query_info_compare) return 1;
else if(fptr == &ub_rrset_compare) return 1;
else if(fptr == &infra_host_compfunc) return 1;
else if(fptr == &infra_compfunc) return 1;
else if(fptr == &key_entry_compfunc) return 1;
else if(fptr == &infra_lame_compfunc) return 1;
else if(fptr == &test_slabhash_compfunc) return 1;
return 0;
}
@ -218,9 +216,8 @@ fptr_whitelist_hash_delkeyfunc(lruhash_delkeyfunc_t fptr)
{
if(fptr == &query_entry_delete) return 1;
else if(fptr == &ub_rrset_key_delete) return 1;
else if(fptr == &infra_host_delkeyfunc) return 1;
else if(fptr == &infra_delkeyfunc) return 1;
else if(fptr == &key_entry_delkeyfunc) return 1;
else if(fptr == &infra_lame_delkeyfunc) return 1;
else if(fptr == &test_slabhash_delkey) return 1;
return 0;
}
@ -230,9 +227,8 @@ fptr_whitelist_hash_deldatafunc(lruhash_deldatafunc_t fptr)
{
if(fptr == &reply_info_delete) return 1;
else if(fptr == &rrset_data_delete) return 1;
else if(fptr == &infra_host_deldatafunc) return 1;
else if(fptr == &infra_deldatafunc) return 1;
else if(fptr == &key_entry_deldatafunc) return 1;
else if(fptr == &infra_lame_deldatafunc) return 1;
else if(fptr == &test_slabhash_deldata) return 1;
return 0;
}
@ -251,6 +247,7 @@ fptr_whitelist_modenv_send_query(struct outbound_entry* (*fptr)(
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
uint16_t flags, int dnssec, int want_dnssec,
struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* zone, size_t zonelen,
struct module_qstate* q))
{
if(fptr == &worker_send_query) return 1;

View file

@ -197,6 +197,7 @@ int fptr_whitelist_modenv_send_query(struct outbound_entry* (*fptr)(
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
uint16_t flags, int dnssec, int want_dnssec,
struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* zone, size_t zonelen,
struct module_qstate* q));
/**

View file

@ -100,6 +100,8 @@ struct module_env {
* EDNS, the answer is likely to be useless for this domain.
* @param addr: where to.
* @param addrlen: length of addr.
* @param zone: delegation point name.
* @param zonelen: length of zone name.
* @param q: wich query state to reactivate upon return.
* @return: false on failure (memory or socket related). no query was
* sent. Or returns an outbound entry with qsent and qstate set.
@ -109,7 +111,8 @@ struct module_env {
struct outbound_entry* (*send_query)(uint8_t* qname, size_t qnamelen,
uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
int want_dnssec, struct sockaddr_storage* addr,
socklen_t addrlen, struct module_qstate* q);
socklen_t addrlen, uint8_t* zone, size_t zonelen,
struct module_qstate* q);
/**
* Detach-subqueries.