}
/* 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;
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"))
send_ok(ssl);
}
+/**
+ * Local info for deletion functions
+ */
+struct del_info {
+ /** worker */
+ struct worker* worker;
+ /** name to delete */
+ uint8_t* name;
+ /** length */
+ size_t len;
+ /** labels */
+ int labs;
+ /** now */
+ uint32_t now;
+ /** time to invalidate to */
+ uint32_t expired;
+ /** number of rrsets removed */
+ size_t num_rrsets;
+ /** number of msgs removed */
+ 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);
(void)ssl_printf(ssl, "error parsing ip addr: '%s'\n", arg);
return;
}
- infra_remove_host(worker->env.infra_cache, &addr, len);
+ /* 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);
}
send_ok(ssl);
}
-/**
- * Local info for deletion functions
- */
-struct del_info {
- /** worker */
- struct worker* worker;
- /** name to delete */
- uint8_t* name;
- /** length */
- size_t len;
- /** labels */
- int labs;
- /** now */
- uint32_t now;
- /** time to invalidate to */
- uint32_t expired;
- /** number of rrsets removed */
- size_t num_rrsets;
- /** number of msgs removed */
- size_t num_msgs;
- /** number of key entries removed */
- size_t num_keys;
-};
-
/** callback to delete rrsets in a zone */
static void
zone_del_rrset(struct lruhash_entry* e, void* 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 */
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(
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) {
* @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.
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
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
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);
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(
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) {
* @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.
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,
#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);
}
{
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;
}
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);
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;
}
/**
* @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
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)
-{
- 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)
+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 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); }
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 */
}
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 {
}
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));
}
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))) {
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 */
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);
}
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;
};
/**
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.
*/
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.
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.
* @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
* @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.
* @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).
* @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);
/**
* @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.
*/
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.
* @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.
* 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.
/** 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 */
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);
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
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;
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);
&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(
/* 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;
}
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.");
}
}
{
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;
}
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,
/* 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;
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;
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 {
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 */
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;
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;
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 */
* @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.
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*));
/**
#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"
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);
}
/**
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 */
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);
* 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
#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)
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 );
; 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
{
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;
}
{
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;
}
{
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;
}
{
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;
}
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;
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));
/**
* 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.
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.