aboutsummaryrefslogtreecommitdiff
path: root/external/unbound/services/cache
diff options
context:
space:
mode:
Diffstat (limited to 'external/unbound/services/cache')
-rw-r--r--external/unbound/services/cache/dns.c910
-rw-r--r--external/unbound/services/cache/dns.h211
-rw-r--r--external/unbound/services/cache/infra.c997
-rw-r--r--external/unbound/services/cache/infra.h462
-rw-r--r--external/unbound/services/cache/rrset.c419
-rw-r--r--external/unbound/services/cache/rrset.h231
6 files changed, 0 insertions, 3230 deletions
diff --git a/external/unbound/services/cache/dns.c b/external/unbound/services/cache/dns.c
deleted file mode 100644
index a8fde9f28..000000000
--- a/external/unbound/services/cache/dns.c
+++ /dev/null
@@ -1,910 +0,0 @@
-/*
- * services/cache/dns.c - Cache services for DNS using msg and rrset caches.
- *
- * Copyright (c) 2007, NLnet Labs. All rights reserved.
- *
- * This software is open source.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the NLNET LABS nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * \file
- *
- * This file contains the DNS cache.
- */
-#include "config.h"
-#include "iterator/iter_delegpt.h"
-#include "validator/val_nsec.h"
-#include "services/cache/dns.h"
-#include "services/cache/rrset.h"
-#include "util/data/msgreply.h"
-#include "util/data/packed_rrset.h"
-#include "util/data/dname.h"
-#include "util/module.h"
-#include "util/net_help.h"
-#include "util/regional.h"
-#include "util/config_file.h"
-#include "sldns/sbuffer.h"
-
-/** store rrsets in the rrset cache.
- * @param env: module environment with caches.
- * @param rep: contains list of rrsets to store.
- * @param now: current time.
- * @param leeway: during prefetch how much leeway to update TTLs.
- * This makes rrsets (other than type NS) timeout sooner so they get
- * updated with a new full TTL.
- * Type NS does not get this, because it must not be refreshed from the
- * child domain, but keep counting down properly.
- * @param pside: if from parentside discovered NS, so that its NS is okay
- * in a prefetch situation to be updated (without becoming sticky).
- * @param qrep: update rrsets here if cache is better
- * @param region: for qrep allocs.
- */
-static void
-store_rrsets(struct module_env* env, struct reply_info* rep, time_t now,
- time_t leeway, int pside, struct reply_info* qrep,
- struct regional* region)
-{
- size_t i;
- /* see if rrset already exists in cache, if not insert it. */
- for(i=0; i<rep->rrset_count; i++) {
- rep->ref[i].key = rep->rrsets[i];
- rep->ref[i].id = rep->rrsets[i]->id;
- /* update ref if it was in the cache */
- switch(rrset_cache_update(env->rrset_cache, &rep->ref[i],
- env->alloc, now + ((ntohs(rep->ref[i].key->rk.type)==
- LDNS_RR_TYPE_NS && !pside)?0:leeway))) {
- case 0: /* ref unchanged, item inserted */
- break;
- case 2: /* ref updated, cache is superior */
- if(region) {
- struct ub_packed_rrset_key* ck;
- lock_rw_rdlock(&rep->ref[i].key->entry.lock);
- /* if deleted rrset, do not copy it */
- if(rep->ref[i].key->id == 0)
- ck = NULL;
- else ck = packed_rrset_copy_region(
- rep->ref[i].key, region, now);
- lock_rw_unlock(&rep->ref[i].key->entry.lock);
- if(ck) {
- /* use cached copy if memory allows */
- qrep->rrsets[i] = ck;
- }
- }
- /* no break: also copy key item */
- case 1: /* ref updated, item inserted */
- rep->rrsets[i] = rep->ref[i].key;
- }
- }
-}
-
-void
-dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
- hashvalue_type hash, struct reply_info* rep, time_t leeway, int pside,
- struct reply_info* qrep, struct regional* region)
-{
- struct msgreply_entry* e;
- time_t ttl = rep->ttl;
- size_t i;
-
- /* store RRsets */
- for(i=0; i<rep->rrset_count; i++) {
- rep->ref[i].key = rep->rrsets[i];
- rep->ref[i].id = rep->rrsets[i]->id;
- }
-
- /* there was a reply_info_sortref(rep) here but it seems to be
- * unnecessary, because the cache gets locked per rrset. */
- reply_info_set_ttls(rep, *env->now);
- store_rrsets(env, rep, *env->now, leeway, pside, qrep, region);
- if(ttl == 0) {
- /* we do not store the message, but we did store the RRs,
- * which could be useful for delegation information */
- verbose(VERB_ALGO, "TTL 0: dropped msg from cache");
- free(rep);
- return;
- }
-
- /* store msg in the cache */
- reply_info_sortref(rep);
- if(!(e = query_info_entrysetup(qinfo, rep, hash))) {
- log_err("store_msg: malloc failed");
- return;
- }
- slabhash_insert(env->msg_cache, hash, &e->entry, rep, env->alloc);
-}
-
-/** find closest NS or DNAME and returns the rrset (locked) */
-static struct ub_packed_rrset_key*
-find_closest_of_type(struct module_env* env, uint8_t* qname, size_t qnamelen,
- uint16_t qclass, time_t now, uint16_t searchtype, int stripfront)
-{
- struct ub_packed_rrset_key *rrset;
- uint8_t lablen;
-
- if(stripfront) {
- /* strip off so that DNAMEs have strict subdomain match */
- lablen = *qname;
- qname += lablen + 1;
- qnamelen -= lablen + 1;
- }
-
- /* snip off front part of qname until the type is found */
- while(qnamelen > 0) {
- if((rrset = rrset_cache_lookup(env->rrset_cache, qname,
- qnamelen, searchtype, qclass, 0, now, 0)))
- return rrset;
-
- /* snip off front label */
- lablen = *qname;
- qname += lablen + 1;
- qnamelen -= lablen + 1;
- }
- return NULL;
-}
-
-/** add addr to additional section */
-static void
-addr_to_additional(struct ub_packed_rrset_key* rrset, struct regional* region,
- struct dns_msg* msg, time_t now)
-{
- if((msg->rep->rrsets[msg->rep->rrset_count] =
- packed_rrset_copy_region(rrset, region, now))) {
- msg->rep->ar_numrrsets++;
- msg->rep->rrset_count++;
- }
-}
-
-/** lookup message in message cache */
-static struct msgreply_entry*
-msg_cache_lookup(struct module_env* env, uint8_t* qname, size_t qnamelen,
- uint16_t qtype, uint16_t qclass, uint16_t flags, time_t now, int wr)
-{
- struct lruhash_entry* e;
- struct query_info k;
- hashvalue_type h;
-
- k.qname = qname;
- k.qname_len = qnamelen;
- k.qtype = qtype;
- k.qclass = qclass;
- k.local_alias = NULL;
- h = query_info_hash(&k, flags);
- e = slabhash_lookup(env->msg_cache, h, &k, wr);
-
- if(!e) return NULL;
- if( now > ((struct reply_info*)e->data)->ttl ) {
- lock_rw_unlock(&e->lock);
- return NULL;
- }
- return (struct msgreply_entry*)e->key;
-}
-
-/** find and add A and AAAA records for nameservers in delegpt */
-static int
-find_add_addrs(struct module_env* env, uint16_t qclass,
- struct regional* region, struct delegpt* dp, time_t now,
- struct dns_msg** msg)
-{
- struct delegpt_ns* ns;
- struct msgreply_entry* neg;
- struct ub_packed_rrset_key* akey;
- for(ns = dp->nslist; ns; ns = ns->next) {
- akey = rrset_cache_lookup(env->rrset_cache, ns->name,
- ns->namelen, LDNS_RR_TYPE_A, qclass, 0, now, 0);
- if(akey) {
- if(!delegpt_add_rrset_A(dp, region, akey, 0)) {
- lock_rw_unlock(&akey->entry.lock);
- return 0;
- }
- if(msg)
- addr_to_additional(akey, region, *msg, now);
- lock_rw_unlock(&akey->entry.lock);
- } else {
- /* BIT_CD on false because delegpt lookup does
- * not use dns64 translation */
- neg = msg_cache_lookup(env, ns->name, ns->namelen,
- LDNS_RR_TYPE_A, qclass, 0, now, 0);
- if(neg) {
- delegpt_add_neg_msg(dp, neg);
- lock_rw_unlock(&neg->entry.lock);
- }
- }
- akey = rrset_cache_lookup(env->rrset_cache, ns->name,
- ns->namelen, LDNS_RR_TYPE_AAAA, qclass, 0, now, 0);
- if(akey) {
- if(!delegpt_add_rrset_AAAA(dp, region, akey, 0)) {
- lock_rw_unlock(&akey->entry.lock);
- return 0;
- }
- if(msg)
- addr_to_additional(akey, region, *msg, now);
- lock_rw_unlock(&akey->entry.lock);
- } else {
- /* BIT_CD on false because delegpt lookup does
- * not use dns64 translation */
- neg = msg_cache_lookup(env, ns->name, ns->namelen,
- LDNS_RR_TYPE_AAAA, qclass, 0, now, 0);
- if(neg) {
- delegpt_add_neg_msg(dp, neg);
- lock_rw_unlock(&neg->entry.lock);
- }
- }
- }
- return 1;
-}
-
-/** find and add A and AAAA records for missing nameservers in delegpt */
-int
-cache_fill_missing(struct module_env* env, uint16_t qclass,
- struct regional* region, struct delegpt* dp)
-{
- struct delegpt_ns* ns;
- struct msgreply_entry* neg;
- struct ub_packed_rrset_key* akey;
- time_t now = *env->now;
- for(ns = dp->nslist; ns; ns = ns->next) {
- akey = rrset_cache_lookup(env->rrset_cache, ns->name,
- ns->namelen, LDNS_RR_TYPE_A, qclass, 0, now, 0);
- if(akey) {
- if(!delegpt_add_rrset_A(dp, region, akey, ns->lame)) {
- lock_rw_unlock(&akey->entry.lock);
- return 0;
- }
- log_nametypeclass(VERB_ALGO, "found in cache",
- ns->name, LDNS_RR_TYPE_A, qclass);
- lock_rw_unlock(&akey->entry.lock);
- } else {
- /* BIT_CD on false because delegpt lookup does
- * not use dns64 translation */
- neg = msg_cache_lookup(env, ns->name, ns->namelen,
- LDNS_RR_TYPE_A, qclass, 0, now, 0);
- if(neg) {
- delegpt_add_neg_msg(dp, neg);
- lock_rw_unlock(&neg->entry.lock);
- }
- }
- akey = rrset_cache_lookup(env->rrset_cache, ns->name,
- ns->namelen, LDNS_RR_TYPE_AAAA, qclass, 0, now, 0);
- if(akey) {
- if(!delegpt_add_rrset_AAAA(dp, region, akey, ns->lame)) {
- lock_rw_unlock(&akey->entry.lock);
- return 0;
- }
- log_nametypeclass(VERB_ALGO, "found in cache",
- ns->name, LDNS_RR_TYPE_AAAA, qclass);
- lock_rw_unlock(&akey->entry.lock);
- } else {
- /* BIT_CD on false because delegpt lookup does
- * not use dns64 translation */
- neg = msg_cache_lookup(env, ns->name, ns->namelen,
- LDNS_RR_TYPE_AAAA, qclass, 0, now, 0);
- if(neg) {
- delegpt_add_neg_msg(dp, neg);
- lock_rw_unlock(&neg->entry.lock);
- }
- }
- }
- return 1;
-}
-
-/** find and add DS or NSEC to delegation msg */
-static void
-find_add_ds(struct module_env* env, struct regional* region,
- struct dns_msg* msg, struct delegpt* dp, time_t now)
-{
- /* Lookup the DS or NSEC at the delegation point. */
- struct ub_packed_rrset_key* rrset = rrset_cache_lookup(
- env->rrset_cache, dp->name, dp->namelen, LDNS_RR_TYPE_DS,
- msg->qinfo.qclass, 0, now, 0);
- if(!rrset) {
- /* NOTE: this won't work for alternate NSEC schemes
- * (opt-in, NSEC3) */
- rrset = rrset_cache_lookup(env->rrset_cache, dp->name,
- dp->namelen, LDNS_RR_TYPE_NSEC, msg->qinfo.qclass,
- 0, now, 0);
- /* Note: the PACKED_RRSET_NSEC_AT_APEX flag is not used.
- * since this is a referral, we need the NSEC at the parent
- * side of the zone cut, not the NSEC at apex side. */
- if(rrset && nsec_has_type(rrset, LDNS_RR_TYPE_DS)) {
- lock_rw_unlock(&rrset->entry.lock);
- rrset = NULL; /* discard wrong NSEC */
- }
- }
- if(rrset) {
- /* add it to auth section. This is the second rrset. */
- if((msg->rep->rrsets[msg->rep->rrset_count] =
- packed_rrset_copy_region(rrset, region, now))) {
- msg->rep->ns_numrrsets++;
- msg->rep->rrset_count++;
- }
- lock_rw_unlock(&rrset->entry.lock);
- }
-}
-
-struct dns_msg*
-dns_msg_create(uint8_t* qname, size_t qnamelen, uint16_t qtype,
- uint16_t qclass, struct regional* region, size_t capacity)
-{
- struct dns_msg* msg = (struct dns_msg*)regional_alloc(region,
- sizeof(struct dns_msg));
- if(!msg)
- return NULL;
- msg->qinfo.qname = regional_alloc_init(region, qname, qnamelen);
- if(!msg->qinfo.qname)
- return NULL;
- msg->qinfo.qname_len = qnamelen;
- msg->qinfo.qtype = qtype;
- msg->qinfo.qclass = qclass;
- msg->qinfo.local_alias = NULL;
- /* non-packed reply_info, because it needs to grow the array */
- msg->rep = (struct reply_info*)regional_alloc_zero(region,
- sizeof(struct reply_info)-sizeof(struct rrset_ref));
- if(!msg->rep)
- return NULL;
- if(capacity > RR_COUNT_MAX)
- return NULL; /* integer overflow protection */
- msg->rep->flags = BIT_QR; /* with QR, no AA */
- msg->rep->qdcount = 1;
- msg->rep->rrsets = (struct ub_packed_rrset_key**)
- regional_alloc(region,
- capacity*sizeof(struct ub_packed_rrset_key*));
- if(!msg->rep->rrsets)
- return NULL;
- return msg;
-}
-
-int
-dns_msg_authadd(struct dns_msg* msg, struct regional* region,
- struct ub_packed_rrset_key* rrset, time_t now)
-{
- if(!(msg->rep->rrsets[msg->rep->rrset_count++] =
- packed_rrset_copy_region(rrset, region, now)))
- return 0;
- msg->rep->ns_numrrsets++;
- return 1;
-}
-
-/** add rrset to answer section */
-static int
-dns_msg_ansadd(struct dns_msg* msg, struct regional* region,
- struct ub_packed_rrset_key* rrset, time_t now)
-{
- if(!(msg->rep->rrsets[msg->rep->rrset_count++] =
- packed_rrset_copy_region(rrset, region, now)))
- return 0;
- msg->rep->an_numrrsets++;
- return 1;
-}
-
-struct delegpt*
-dns_cache_find_delegation(struct module_env* env, uint8_t* qname,
- size_t qnamelen, uint16_t qtype, uint16_t qclass,
- struct regional* region, struct dns_msg** msg, time_t now)
-{
- /* try to find closest NS rrset */
- struct ub_packed_rrset_key* nskey;
- struct packed_rrset_data* nsdata;
- struct delegpt* dp;
-
- nskey = find_closest_of_type(env, qname, qnamelen, qclass, now,
- LDNS_RR_TYPE_NS, 0);
- if(!nskey) /* hope the caller has hints to prime or something */
- return NULL;
- nsdata = (struct packed_rrset_data*)nskey->entry.data;
- /* got the NS key, create delegation point */
- dp = delegpt_create(region);
- if(!dp || !delegpt_set_name(dp, region, nskey->rk.dname)) {
- lock_rw_unlock(&nskey->entry.lock);
- log_err("find_delegation: out of memory");
- return NULL;
- }
- /* create referral message */
- if(msg) {
- /* allocate the array to as much as we could need:
- * NS rrset + DS/NSEC rrset +
- * A rrset for every NS RR
- * AAAA rrset for every NS RR
- */
- *msg = dns_msg_create(qname, qnamelen, qtype, qclass, region,
- 2 + nsdata->count*2);
- if(!*msg || !dns_msg_authadd(*msg, region, nskey, now)) {
- lock_rw_unlock(&nskey->entry.lock);
- log_err("find_delegation: out of memory");
- return NULL;
- }
- }
- if(!delegpt_rrset_add_ns(dp, region, nskey, 0))
- log_err("find_delegation: addns out of memory");
- lock_rw_unlock(&nskey->entry.lock); /* first unlock before next lookup*/
- /* find and add DS/NSEC (if any) */
- if(msg)
- find_add_ds(env, region, *msg, dp, now);
- /* find and add A entries */
- if(!find_add_addrs(env, qclass, region, dp, now, msg))
- log_err("find_delegation: addrs out of memory");
- return dp;
-}
-
-/** allocate dns_msg from query_info and reply_info */
-static struct dns_msg*
-gen_dns_msg(struct regional* region, struct query_info* q, size_t num)
-{
- struct dns_msg* msg = (struct dns_msg*)regional_alloc(region,
- sizeof(struct dns_msg));
- if(!msg)
- return NULL;
- memcpy(&msg->qinfo, q, sizeof(struct query_info));
- msg->qinfo.qname = regional_alloc_init(region, q->qname, q->qname_len);
- if(!msg->qinfo.qname)
- return NULL;
- /* allocate replyinfo struct and rrset key array separately */
- msg->rep = (struct reply_info*)regional_alloc(region,
- sizeof(struct reply_info) - sizeof(struct rrset_ref));
- if(!msg->rep)
- return NULL;
- if(num > RR_COUNT_MAX)
- return NULL; /* integer overflow protection */
- msg->rep->rrsets = (struct ub_packed_rrset_key**)
- regional_alloc(region,
- num * sizeof(struct ub_packed_rrset_key*));
- if(!msg->rep->rrsets)
- return NULL;
- return msg;
-}
-
-struct dns_msg*
-tomsg(struct module_env* env, struct query_info* q, struct reply_info* r,
- struct regional* region, time_t now, struct regional* scratch)
-{
- struct dns_msg* msg;
- size_t i;
- if(now > r->ttl)
- return NULL;
- msg = gen_dns_msg(region, q, r->rrset_count);
- if(!msg)
- return NULL;
- msg->rep->flags = r->flags;
- msg->rep->qdcount = r->qdcount;
- msg->rep->ttl = r->ttl - now;
- if(r->prefetch_ttl > now)
- msg->rep->prefetch_ttl = r->prefetch_ttl - now;
- else msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
- msg->rep->security = r->security;
- msg->rep->an_numrrsets = r->an_numrrsets;
- msg->rep->ns_numrrsets = r->ns_numrrsets;
- msg->rep->ar_numrrsets = r->ar_numrrsets;
- msg->rep->rrset_count = r->rrset_count;
- msg->rep->authoritative = r->authoritative;
- if(!rrset_array_lock(r->ref, r->rrset_count, now))
- return NULL;
- if(r->an_numrrsets > 0 && (r->rrsets[0]->rk.type == htons(
- LDNS_RR_TYPE_CNAME) || r->rrsets[0]->rk.type == htons(
- LDNS_RR_TYPE_DNAME)) && !reply_check_cname_chain(q, r)) {
- /* cname chain is now invalid, reconstruct msg */
- rrset_array_unlock(r->ref, r->rrset_count);
- return NULL;
- }
- if(r->security == sec_status_secure && !reply_all_rrsets_secure(r)) {
- /* message rrsets have changed status, revalidate */
- rrset_array_unlock(r->ref, r->rrset_count);
- return NULL;
- }
- for(i=0; i<msg->rep->rrset_count; i++) {
- msg->rep->rrsets[i] = packed_rrset_copy_region(r->rrsets[i],
- region, now);
- if(!msg->rep->rrsets[i]) {
- rrset_array_unlock(r->ref, r->rrset_count);
- return NULL;
- }
- }
- if(env)
- rrset_array_unlock_touch(env->rrset_cache, scratch, r->ref,
- r->rrset_count);
- else
- rrset_array_unlock(r->ref, r->rrset_count);
- return msg;
-}
-
-/** synthesize RRset-only response from cached RRset item */
-static struct dns_msg*
-rrset_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
- time_t now, struct query_info* q)
-{
- struct dns_msg* msg;
- struct packed_rrset_data* d = (struct packed_rrset_data*)
- rrset->entry.data;
- if(now > d->ttl)
- return NULL;
- msg = gen_dns_msg(region, q, 1); /* only the CNAME (or other) RRset */
- if(!msg)
- return NULL;
- msg->rep->flags = BIT_QR; /* reply, no AA, no error */
- msg->rep->authoritative = 0; /* reply stored in cache can't be authoritative */
- msg->rep->qdcount = 1;
- msg->rep->ttl = d->ttl - now;
- msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
- msg->rep->security = sec_status_unchecked;
- msg->rep->an_numrrsets = 1;
- msg->rep->ns_numrrsets = 0;
- msg->rep->ar_numrrsets = 0;
- msg->rep->rrset_count = 1;
- msg->rep->rrsets[0] = packed_rrset_copy_region(rrset, region, now);
- if(!msg->rep->rrsets[0]) /* copy CNAME */
- return NULL;
- return msg;
-}
-
-/** synthesize DNAME+CNAME response from cached DNAME item */
-static struct dns_msg*
-synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
- time_t now, struct query_info* q)
-{
- struct dns_msg* msg;
- struct ub_packed_rrset_key* ck;
- struct packed_rrset_data* newd, *d = (struct packed_rrset_data*)
- rrset->entry.data;
- uint8_t* newname, *dtarg = NULL;
- size_t newlen, dtarglen;
- if(now > d->ttl)
- return NULL;
- /* only allow validated (with DNSSEC) DNAMEs used from cache
- * for insecure DNAMEs, query again. */
- if(d->security != sec_status_secure)
- return NULL;
- msg = gen_dns_msg(region, q, 2); /* DNAME + CNAME RRset */
- if(!msg)
- return NULL;
- msg->rep->flags = BIT_QR; /* reply, no AA, no error */
- msg->rep->authoritative = 0; /* reply stored in cache can't be authoritative */
- msg->rep->qdcount = 1;
- msg->rep->ttl = d->ttl - now;
- msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
- msg->rep->security = sec_status_unchecked;
- msg->rep->an_numrrsets = 1;
- msg->rep->ns_numrrsets = 0;
- msg->rep->ar_numrrsets = 0;
- msg->rep->rrset_count = 1;
- msg->rep->rrsets[0] = packed_rrset_copy_region(rrset, region, now);
- if(!msg->rep->rrsets[0]) /* copy DNAME */
- return NULL;
- /* synth CNAME rrset */
- get_cname_target(rrset, &dtarg, &dtarglen);
- if(!dtarg)
- return NULL;
- newlen = q->qname_len + dtarglen - rrset->rk.dname_len;
- if(newlen > LDNS_MAX_DOMAINLEN) {
- msg->rep->flags |= LDNS_RCODE_YXDOMAIN;
- return msg;
- }
- newname = (uint8_t*)regional_alloc(region, newlen);
- if(!newname)
- return NULL;
- /* new name is concatenation of qname front (without DNAME owner)
- * and DNAME target name */
- memcpy(newname, q->qname, q->qname_len-rrset->rk.dname_len);
- memmove(newname+(q->qname_len-rrset->rk.dname_len), dtarg, dtarglen);
- /* create rest of CNAME rrset */
- ck = (struct ub_packed_rrset_key*)regional_alloc(region,
- sizeof(struct ub_packed_rrset_key));
- if(!ck)
- return NULL;
- memset(&ck->entry, 0, sizeof(ck->entry));
- msg->rep->rrsets[1] = ck;
- ck->entry.key = ck;
- ck->rk.type = htons(LDNS_RR_TYPE_CNAME);
- ck->rk.rrset_class = rrset->rk.rrset_class;
- ck->rk.flags = 0;
- ck->rk.dname = regional_alloc_init(region, q->qname, q->qname_len);
- if(!ck->rk.dname)
- return NULL;
- ck->rk.dname_len = q->qname_len;
- ck->entry.hash = rrset_key_hash(&ck->rk);
- newd = (struct packed_rrset_data*)regional_alloc_zero(region,
- sizeof(struct packed_rrset_data) + sizeof(size_t) +
- sizeof(uint8_t*) + sizeof(time_t) + sizeof(uint16_t)
- + newlen);
- if(!newd)
- return NULL;
- ck->entry.data = newd;
- newd->ttl = 0; /* 0 for synthesized CNAME TTL */
- newd->count = 1;
- newd->rrsig_count = 0;
- newd->trust = rrset_trust_ans_noAA;
- newd->rr_len = (size_t*)((uint8_t*)newd +
- sizeof(struct packed_rrset_data));
- newd->rr_len[0] = newlen + sizeof(uint16_t);
- packed_rrset_ptr_fixup(newd);
- newd->rr_ttl[0] = newd->ttl;
- msg->rep->ttl = newd->ttl;
- msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(newd->ttl);
- sldns_write_uint16(newd->rr_data[0], newlen);
- memmove(newd->rr_data[0] + sizeof(uint16_t), newname, newlen);
- msg->rep->an_numrrsets ++;
- msg->rep->rrset_count ++;
- return msg;
-}
-
-/** Fill TYPE_ANY response with some data from cache */
-static struct dns_msg*
-fill_any(struct module_env* env,
- uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
- struct regional* region)
-{
- time_t now = *env->now;
- struct dns_msg* msg = NULL;
- uint16_t lookup[] = {LDNS_RR_TYPE_A, LDNS_RR_TYPE_AAAA,
- LDNS_RR_TYPE_MX, LDNS_RR_TYPE_SOA, LDNS_RR_TYPE_NS,
- LDNS_RR_TYPE_DNAME, 0};
- int i, num=6; /* number of RR types to look up */
- log_assert(lookup[num] == 0);
-
- for(i=0; i<num; i++) {
- /* look up this RR for inclusion in type ANY response */
- struct ub_packed_rrset_key* rrset = rrset_cache_lookup(
- env->rrset_cache, qname, qnamelen, lookup[i],
- qclass, 0, now, 0);
- struct packed_rrset_data *d;
- if(!rrset)
- continue;
-
- /* only if rrset from answer section */
- d = (struct packed_rrset_data*)rrset->entry.data;
- if(d->trust == rrset_trust_add_noAA ||
- d->trust == rrset_trust_auth_noAA ||
- d->trust == rrset_trust_add_AA ||
- d->trust == rrset_trust_auth_AA) {
- lock_rw_unlock(&rrset->entry.lock);
- continue;
- }
-
- /* create msg if none */
- if(!msg) {
- msg = dns_msg_create(qname, qnamelen, qtype, qclass,
- region, (size_t)(num-i));
- if(!msg) {
- lock_rw_unlock(&rrset->entry.lock);
- return NULL;
- }
- }
-
- /* add RRset to response */
- if(!dns_msg_ansadd(msg, region, rrset, now)) {
- lock_rw_unlock(&rrset->entry.lock);
- return NULL;
- }
- lock_rw_unlock(&rrset->entry.lock);
- }
- return msg;
-}
-
-struct dns_msg*
-dns_cache_lookup(struct module_env* env,
- uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
- uint16_t flags, struct regional* region, struct regional* scratch)
-{
- struct lruhash_entry* e;
- struct query_info k;
- hashvalue_type h;
- time_t now = *env->now;
- struct ub_packed_rrset_key* rrset;
-
- /* lookup first, this has both NXdomains and ANSWER responses */
- k.qname = qname;
- k.qname_len = qnamelen;
- k.qtype = qtype;
- k.qclass = qclass;
- k.local_alias = NULL;
- h = query_info_hash(&k, flags);
- e = slabhash_lookup(env->msg_cache, h, &k, 0);
- if(e) {
- struct msgreply_entry* key = (struct msgreply_entry*)e->key;
- struct reply_info* data = (struct reply_info*)e->data;
- struct dns_msg* msg = tomsg(env, &key->key, data, region, now,
- scratch);
- if(msg) {
- lock_rw_unlock(&e->lock);
- return msg;
- }
- /* could be msg==NULL; due to TTL or not all rrsets available */
- lock_rw_unlock(&e->lock);
- }
-
- /* see if a DNAME exists. Checked for first, to enforce that DNAMEs
- * are more important, the CNAME is resynthesized and thus
- * consistent with the DNAME */
- if( (rrset=find_closest_of_type(env, qname, qnamelen, qclass, now,
- LDNS_RR_TYPE_DNAME, 1))) {
- /* synthesize a DNAME+CNAME message based on this */
- struct dns_msg* msg = synth_dname_msg(rrset, region, now, &k);
- if(msg) {
- lock_rw_unlock(&rrset->entry.lock);
- return msg;
- }
- lock_rw_unlock(&rrset->entry.lock);
- }
-
- /* see if we have CNAME for this domain,
- * but not for DS records (which are part of the parent) */
- if( qtype != LDNS_RR_TYPE_DS &&
- (rrset=rrset_cache_lookup(env->rrset_cache, qname, qnamelen,
- LDNS_RR_TYPE_CNAME, qclass, 0, now, 0))) {
- struct dns_msg* msg = rrset_msg(rrset, region, now, &k);
- if(msg) {
- lock_rw_unlock(&rrset->entry.lock);
- return msg;
- }
- lock_rw_unlock(&rrset->entry.lock);
- }
-
- /* construct DS, DNSKEY, DLV messages from rrset cache. */
- if((qtype == LDNS_RR_TYPE_DS || qtype == LDNS_RR_TYPE_DNSKEY ||
- qtype == LDNS_RR_TYPE_DLV) &&
- (rrset=rrset_cache_lookup(env->rrset_cache, qname, qnamelen,
- qtype, qclass, 0, now, 0))) {
- /* if the rrset is from the additional section, and the
- * signatures have fallen off, then do not synthesize a msg
- * instead, allow a full query for signed results to happen.
- * Forego all rrset data from additional section, because
- * some signatures may not be present and cause validation
- * failure.
- */
- struct packed_rrset_data *d = (struct packed_rrset_data*)
- rrset->entry.data;
- if(d->trust != rrset_trust_add_noAA &&
- d->trust != rrset_trust_add_AA &&
- (qtype == LDNS_RR_TYPE_DS ||
- (d->trust != rrset_trust_auth_noAA
- && d->trust != rrset_trust_auth_AA) )) {
- struct dns_msg* msg = rrset_msg(rrset, region, now, &k);
- if(msg) {
- lock_rw_unlock(&rrset->entry.lock);
- return msg;
- }
- }
- lock_rw_unlock(&rrset->entry.lock);
- }
-
- /* stop downwards cache search on NXDOMAIN.
- * Empty nonterminals are NOERROR, so an NXDOMAIN for foo
- * means bla.foo also does not exist. The DNSSEC proofs are
- * the same. We search upwards for NXDOMAINs. */
- if(env->cfg->harden_below_nxdomain)
- while(!dname_is_root(k.qname)) {
- dname_remove_label(&k.qname, &k.qname_len);
- h = query_info_hash(&k, flags);
- e = slabhash_lookup(env->msg_cache, h, &k, 0);
- if(!e && k.qtype != LDNS_RR_TYPE_A &&
- env->cfg->qname_minimisation) {
- k.qtype = LDNS_RR_TYPE_A;
- h = query_info_hash(&k, flags);
- e = slabhash_lookup(env->msg_cache, h, &k, 0);
- }
- if(e) {
- struct reply_info* data = (struct reply_info*)e->data;
- struct dns_msg* msg;
- if(FLAGS_GET_RCODE(data->flags) == LDNS_RCODE_NXDOMAIN
- && data->security == sec_status_secure
- && (msg=tomsg(env, &k, data, region, now, scratch))){
- lock_rw_unlock(&e->lock);
- msg->qinfo.qname=qname;
- msg->qinfo.qname_len=qnamelen;
- /* check that DNSSEC really works out */
- msg->rep->security = sec_status_unchecked;
- return msg;
- }
- lock_rw_unlock(&e->lock);
- }
- k.qtype = qtype;
- }
-
- /* fill common RR types for ANY response to avoid requery */
- if(qtype == LDNS_RR_TYPE_ANY) {
- return fill_any(env, qname, qnamelen, qtype, qclass, region);
- }
-
- return NULL;
-}
-
-int
-dns_cache_store(struct module_env* env, struct query_info* msgqinf,
- struct reply_info* msgrep, int is_referral, time_t leeway, int pside,
- struct regional* region, uint16_t flags)
-{
- struct reply_info* rep = NULL;
- /* alloc, malloc properly (not in region, like msg is) */
- rep = reply_info_copy(msgrep, env->alloc, NULL);
- if(!rep)
- return 0;
- /* ttl must be relative ;i.e. 0..86400 not time(0)+86400.
- * the env->now is added to message and RRsets in this routine. */
- /* the leeway is used to invalidate other rrsets earlier */
-
- if(is_referral) {
- /* store rrsets */
- struct rrset_ref ref;
- size_t i;
- for(i=0; i<rep->rrset_count; i++) {
- packed_rrset_ttl_add((struct packed_rrset_data*)
- rep->rrsets[i]->entry.data, *env->now);
- ref.key = rep->rrsets[i];
- ref.id = rep->rrsets[i]->id;
- /*ignore ret: it was in the cache, ref updated */
- /* no leeway for typeNS */
- (void)rrset_cache_update(env->rrset_cache, &ref,
- env->alloc, *env->now +
- ((ntohs(ref.key->rk.type)==LDNS_RR_TYPE_NS
- && !pside) ? 0:leeway));
- }
- free(rep);
- return 1;
- } else {
- /* store msg, and rrsets */
- struct query_info qinf;
- hashvalue_type h;
-
- qinf = *msgqinf;
- qinf.qname = memdup(msgqinf->qname, msgqinf->qname_len);
- if(!qinf.qname) {
- reply_info_parsedelete(rep, env->alloc);
- return 0;
- }
- /* fixup flags to be sensible for a reply based on the cache */
- /* this module means that RA is available. It is an answer QR.
- * Not AA from cache. Not CD in cache (depends on client bit). */
- rep->flags |= (BIT_RA | BIT_QR);
- rep->flags &= ~(BIT_AA | BIT_CD);
- h = query_info_hash(&qinf, flags);
- dns_cache_store_msg(env, &qinf, h, rep, leeway, pside, msgrep,
- region);
- /* qname is used inside query_info_entrysetup, and set to
- * NULL. If it has not been used, free it. free(0) is safe. */
- free(qinf.qname);
- }
- return 1;
-}
-
-int
-dns_cache_prefetch_adjust(struct module_env* env, struct query_info* qinfo,
- time_t adjust, uint16_t flags)
-{
- struct msgreply_entry* msg;
- msg = msg_cache_lookup(env, qinfo->qname, qinfo->qname_len,
- qinfo->qtype, qinfo->qclass, flags, *env->now, 1);
- if(msg) {
- struct reply_info* rep = (struct reply_info*)msg->entry.data;
- if(rep) {
- rep->prefetch_ttl += adjust;
- lock_rw_unlock(&msg->entry.lock);
- return 1;
- }
- lock_rw_unlock(&msg->entry.lock);
- }
- return 0;
-}
diff --git a/external/unbound/services/cache/dns.h b/external/unbound/services/cache/dns.h
deleted file mode 100644
index 0dfb68874..000000000
--- a/external/unbound/services/cache/dns.h
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * services/cache/dns.h - Cache services for DNS using msg and rrset caches.
- *
- * Copyright (c) 2007, NLnet Labs. All rights reserved.
- *
- * This software is open source.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the NLNET LABS nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * \file
- *
- * This file contains the DNS cache.
- */
-
-#ifndef SERVICES_CACHE_DNS_H
-#define SERVICES_CACHE_DNS_H
-#include "util/storage/lruhash.h"
-#include "util/data/msgreply.h"
-struct module_env;
-struct query_info;
-struct reply_info;
-struct regional;
-struct delegpt;
-
-/**
- * Region allocated message reply
- */
-struct dns_msg {
- /** query info */
- struct query_info qinfo;
- /** reply info - ptr to packed repinfo structure */
- struct reply_info *rep;
-};
-
-/**
- * Allocate a dns_msg with malloc/alloc structure and store in dns cache.
- *
- * @param env: environment, with alloc structure and dns cache.
- * @param qinf: query info, the query for which answer is stored.
- * this is allocated in a region, and will be copied to malloc area
- * before insertion.
- * @param rep: reply in dns_msg from dns_alloc_msg for example.
- * this is allocated in a region, and will be copied to malloc area
- * before insertion.
- * @param is_referral: If true, then the given message to be stored is a
- * referral. The cache implementation may use this as a hint.
- * It will store only the RRsets, not the message.
- * @param leeway: TTL value, if not 0, other rrsets are considered expired
- * that many seconds before actual TTL expiry.
- * @param pside: if true, information came from a server which was fetched
- * from the parentside of the zonecut. This means that the type NS
- * can be updated to full TTL even in prefetch situations.
- * @param region: region to allocate better entries from cache into.
- * (used when is_referral is false).
- * @param flags: flags with BIT_CD for AAAA queries in dns64 translation.
- * @return 0 on alloc error (out of memory).
- */
-int dns_cache_store(struct module_env* env, struct query_info* qinf,
- struct reply_info* rep, int is_referral, time_t leeway, int pside,
- struct regional* region, uint16_t flags);
-
-/**
- * Store message in the cache. Stores in message cache and rrset cache.
- * Both qinfo and rep should be malloced and are put in the cache.
- * They should not be used after this call, as they are then in shared cache.
- * Does not return errors, they are logged and only lead to less cache.
- *
- * @param env: module environment with the DNS cache.
- * @param qinfo: query info
- * @param hash: hash over qinfo.
- * @param rep: reply info, together with qinfo makes up the message.
- * Adjusts the reply info TTLs to absolute time.
- * @param leeway: TTL value, if not 0, other rrsets are considered expired
- * that many seconds before actual TTL expiry.
- * @param pside: if true, information came from a server which was fetched
- * from the parentside of the zonecut. This means that the type NS
- * can be updated to full TTL even in prefetch situations.
- * @param qrep: message that can be altered with better rrs from cache.
- * @param region: to allocate into for qmsg.
- */
-void dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
- hashvalue_type hash, struct reply_info* rep, time_t leeway, int pside,
- struct reply_info* qrep, struct regional* region);
-
-/**
- * Find a delegation from the cache.
- * @param env: module environment with the DNS cache.
- * @param qname: query name.
- * @param qnamelen: length of qname.
- * @param qtype: query type.
- * @param qclass: query class.
- * @param region: where to allocate result delegation.
- * @param msg: if not NULL, delegation message is returned here, synthesized
- * from the cache.
- * @param timenow: the time now, for checking if TTL on cache entries is OK.
- * @return new delegation or NULL on error or if not found in cache.
- */
-struct delegpt* dns_cache_find_delegation(struct module_env* env,
- uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
- struct regional* region, struct dns_msg** msg, time_t timenow);
-
-/**
- * generate dns_msg from cached message
- * @param env: module environment with the DNS cache. NULL if the LRU from cache
- * does not need to be touched.
- * @param q: query info, contains qname that will make up the dns message.
- * @param r: reply info that, together with qname, will make up the dns message.
- * @param region: where to allocate dns message.
- * @param now: the time now, for check if TTL on cache entry is ok.
- * @param scratch: where to allocate temporary data.
- * */
-struct dns_msg* tomsg(struct module_env* env, struct query_info* q,
- struct reply_info* r, struct regional* region, time_t now,
- struct regional* scratch);
-
-/**
- * Find cached message
- * @param env: module environment with the DNS cache.
- * @param qname: query name.
- * @param qnamelen: length of qname.
- * @param qtype: query type.
- * @param qclass: query class.
- * @param flags: flags with BIT_CD for AAAA queries in dns64 translation.
- * @param region: where to allocate result.
- * @param scratch: where to allocate temporary data.
- * @return new response message (alloced in region, rrsets do not have IDs).
- * or NULL on error or if not found in cache.
- * TTLs are made relative to the current time.
- */
-struct dns_msg* dns_cache_lookup(struct module_env* env,
- uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
- uint16_t flags, struct regional* region, struct regional* scratch);
-
-/**
- * find and add A and AAAA records for missing nameservers in delegpt
- * @param env: module environment with rrset cache
- * @param qclass: which class to look in.
- * @param region: where to store new dp info.
- * @param dp: delegation point to fill missing entries.
- * @return false on alloc failure.
- */
-int cache_fill_missing(struct module_env* env, uint16_t qclass,
- struct regional* region, struct delegpt* dp);
-
-/**
- * Utility, create new, unpacked data structure for cache response.
- * QR bit set, no AA. Query set as indicated. Space for number of rrsets.
- * @param qname: query section name
- * @param qnamelen: len of qname
- * @param qtype: query section type
- * @param qclass: query section class
- * @param region: where to alloc.
- * @param capacity: number of rrsets space to create in the array.
- * @return new dns_msg struct or NULL on mem fail.
- */
-struct dns_msg* dns_msg_create(uint8_t* qname, size_t qnamelen, uint16_t qtype,
- uint16_t qclass, struct regional* region, size_t capacity);
-
-/**
- * Add rrset to authority section in unpacked dns_msg message. Must have enough
- * space left, does not grow the array.
- * @param msg: msg to put it in.
- * @param region: region to alloc in
- * @param rrset: to add in authority section
- * @param now: now.
- * @return true if worked, false on fail
- */
-int dns_msg_authadd(struct dns_msg* msg, struct regional* region,
- struct ub_packed_rrset_key* rrset, time_t now);
-
-/**
- * Adjust the prefetch_ttl for a cached message. This adds a value to the
- * prefetch ttl - postponing the time when it will be prefetched for future
- * incoming queries.
- * @param env: module environment with caches and time.
- * @param qinfo: query info for the query that needs adjustment.
- * @param adjust: time in seconds to add to the prefetch_leeway.
- * @param flags: flags with BIT_CD for AAAA queries in dns64 translation.
- * @return false if not in cache. true if added.
- */
-int dns_cache_prefetch_adjust(struct module_env* env, struct query_info* qinfo,
- time_t adjust, uint16_t flags);
-
-#endif /* SERVICES_CACHE_DNS_H */
diff --git a/external/unbound/services/cache/infra.c b/external/unbound/services/cache/infra.c
deleted file mode 100644
index 314c85ef5..000000000
--- a/external/unbound/services/cache/infra.c
+++ /dev/null
@@ -1,997 +0,0 @@
-/*
- * services/cache/infra.c - infrastructure cache, server rtt and capabilities
- *
- * Copyright (c) 2007, NLnet Labs. All rights reserved.
- *
- * This software is open source.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the NLNET LABS nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * \file
- *
- * This file contains the infrastructure cache.
- */
-#include "config.h"
-#include "sldns/rrdef.h"
-#include "sldns/str2wire.h"
-#include "services/cache/infra.h"
-#include "util/storage/slabhash.h"
-#include "util/storage/lookup3.h"
-#include "util/data/dname.h"
-#include "util/log.h"
-#include "util/net_help.h"
-#include "util/config_file.h"
-#include "iterator/iterator.h"
-
-/** Timeout when only a single probe query per IP is allowed. */
-#define PROBE_MAXRTO 12000 /* in msec */
-
-/** number of timeouts for a type when the domain can be blocked ;
- * even if another type has completely rtt maxed it, the different type
- * can do this number of packets (until those all timeout too) */
-#define TIMEOUT_COUNT_MAX 3
-
-/** ratelimit value for delegation point */
-int infra_dp_ratelimit = 0;
-
-/** ratelimit value for client ip addresses,
- * in queries per second. */
-int infra_ip_ratelimit = 0;
-
-size_t
-infra_sizefunc(void* k, void* ATTR_UNUSED(d))
-{
- 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_compfunc(void* key1, void* key2)
-{
- 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 r;
- if(k1->namelen != k2->namelen) {
- if(k1->namelen < k2->namelen)
- return -1;
- return 1;
- }
- return query_dname_compare(k1->zonename, k2->zonename);
-}
-
-void
-infra_delkeyfunc(void* k, void* ATTR_UNUSED(arg))
-{
- struct infra_key* key = (struct infra_key*)k;
- if(!key)
- return;
- lock_rw_destroy(&key->entry.lock);
- free(key->zonename);
- free(key);
-}
-
-void
-infra_deldatafunc(void* d, void* ATTR_UNUSED(arg))
-{
- struct infra_data* data = (struct infra_data*)d;
- free(data);
-}
-
-size_t
-rate_sizefunc(void* k, void* ATTR_UNUSED(d))
-{
- struct rate_key* key = (struct rate_key*)k;
- return sizeof(*key) + sizeof(struct rate_data) + key->namelen
- + lock_get_mem(&key->entry.lock);
-}
-
-int
-rate_compfunc(void* key1, void* key2)
-{
- struct rate_key* k1 = (struct rate_key*)key1;
- struct rate_key* k2 = (struct rate_key*)key2;
- if(k1->namelen != k2->namelen) {
- if(k1->namelen < k2->namelen)
- return -1;
- return 1;
- }
- return query_dname_compare(k1->name, k2->name);
-}
-
-void
-rate_delkeyfunc(void* k, void* ATTR_UNUSED(arg))
-{
- struct rate_key* key = (struct rate_key*)k;
- if(!key)
- return;
- lock_rw_destroy(&key->entry.lock);
- free(key->name);
- free(key);
-}
-
-void
-rate_deldatafunc(void* d, void* ATTR_UNUSED(arg))
-{
- struct rate_data* data = (struct rate_data*)d;
- free(data);
-}
-
-/** find or create element in domainlimit tree */
-static struct domain_limit_data* domain_limit_findcreate(
- struct infra_cache* infra, char* name)
-{
- uint8_t* nm;
- int labs;
- size_t nmlen;
- struct domain_limit_data* d;
-
- /* parse name */
- nm = sldns_str2wire_dname(name, &nmlen);
- if(!nm) {
- log_err("could not parse %s", name);
- return NULL;
- }
- labs = dname_count_labels(nm);
-
- /* can we find it? */
- d = (struct domain_limit_data*)name_tree_find(&infra->domain_limits,
- nm, nmlen, labs, LDNS_RR_CLASS_IN);
- if(d) {
- free(nm);
- return d;
- }
-
- /* create it */
- d = (struct domain_limit_data*)calloc(1, sizeof(*d));
- if(!d) {
- free(nm);
- return NULL;
- }
- d->node.node.key = &d->node;
- d->node.name = nm;
- d->node.len = nmlen;
- d->node.labs = labs;
- d->node.dclass = LDNS_RR_CLASS_IN;
- d->lim = -1;
- d->below = -1;
- if(!name_tree_insert(&infra->domain_limits, &d->node, nm, nmlen,
- labs, LDNS_RR_CLASS_IN)) {
- log_err("duplicate element in domainlimit tree");
- free(nm);
- free(d);
- return NULL;
- }
- return d;
-}
-
-/** insert rate limit configuration into lookup tree */
-static int infra_ratelimit_cfg_insert(struct infra_cache* infra,
- struct config_file* cfg)
-{
- struct config_str2list* p;
- struct domain_limit_data* d;
- for(p = cfg->ratelimit_for_domain; p; p = p->next) {
- d = domain_limit_findcreate(infra, p->str);
- if(!d)
- return 0;
- d->lim = atoi(p->str2);
- }
- for(p = cfg->ratelimit_below_domain; p; p = p->next) {
- d = domain_limit_findcreate(infra, p->str);
- if(!d)
- return 0;
- d->below = atoi(p->str2);
- }
- return 1;
-}
-
-struct infra_cache*
-infra_create(struct config_file* cfg)
-{
- struct infra_cache* infra = (struct infra_cache*)calloc(1,
- sizeof(struct infra_cache));
- 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_sizefunc, &infra_compfunc,
- &infra_delkeyfunc, &infra_deldatafunc, NULL);
- if(!infra->hosts) {
- free(infra);
- return NULL;
- }
- infra->host_ttl = cfg->host_ttl;
- name_tree_init(&infra->domain_limits);
- infra_dp_ratelimit = cfg->ratelimit;
- if(cfg->ratelimit != 0) {
- infra->domain_rates = slabhash_create(cfg->ratelimit_slabs,
- INFRA_HOST_STARTSIZE, cfg->ratelimit_size,
- &rate_sizefunc, &rate_compfunc, &rate_delkeyfunc,
- &rate_deldatafunc, NULL);
- if(!infra->domain_rates) {
- infra_delete(infra);
- return NULL;
- }
- /* insert config data into ratelimits */
- if(!infra_ratelimit_cfg_insert(infra, cfg)) {
- infra_delete(infra);
- return NULL;
- }
- name_tree_init_parents(&infra->domain_limits);
- }
- infra_ip_ratelimit = cfg->ip_ratelimit;
- infra->client_ip_rates = slabhash_create(cfg->ratelimit_slabs,
- INFRA_HOST_STARTSIZE, cfg->ip_ratelimit_size, &ip_rate_sizefunc,
- &ip_rate_compfunc, &ip_rate_delkeyfunc, &ip_rate_deldatafunc, NULL);
- if(!infra->client_ip_rates) {
- infra_delete(infra);
- return NULL;
- }
- return infra;
-}
-
-/** delete domain_limit entries */
-static void domain_limit_free(rbnode_type* n, void* ATTR_UNUSED(arg))
-{
- if(n) {
- free(((struct domain_limit_data*)n)->node.name);
- free(n);
- }
-}
-
-void
-infra_delete(struct infra_cache* infra)
-{
- if(!infra)
- return;
- slabhash_delete(infra->hosts);
- slabhash_delete(infra->domain_rates);
- traverse_postorder(&infra->domain_limits, domain_limit_free, NULL);
- slabhash_delete(infra->client_ip_rates);
- free(infra);
-}
-
-struct infra_cache*
-infra_adjust(struct infra_cache* infra, struct config_file* cfg)
-{
- size_t maxmem;
- if(!infra)
- return infra_create(cfg);
- infra->host_ttl = cfg->host_ttl;
- 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);
- infra = infra_create(cfg);
- }
- return infra;
-}
-
-/** calculate the hash value for a host key
- * set use_port to a non-0 number to use the port in
- * the hash calculation; 0 to ignore the port.*/
-static hashvalue_type
-hash_addr(struct sockaddr_storage* addr, socklen_t addrlen,
- int use_port)
-{
- hashvalue_type h = 0xab;
- /* select the pieces to hash, some OS have changing data inside */
- if(addr_is_ip6(addr, addrlen)) {
- struct sockaddr_in6* in6 = (struct sockaddr_in6*)addr;
- h = hashlittle(&in6->sin6_family, sizeof(in6->sin6_family), h);
- if(use_port){
- h = hashlittle(&in6->sin6_port, sizeof(in6->sin6_port), h);
- }
- h = hashlittle(&in6->sin6_addr, INET6_SIZE, h);
- } else {
- struct sockaddr_in* in = (struct sockaddr_in*)addr;
- h = hashlittle(&in->sin_family, sizeof(in->sin_family), h);
- if(use_port){
- h = hashlittle(&in->sin_port, sizeof(in->sin_port), h);
- }
- h = hashlittle(&in->sin_addr, INET_SIZE, h);
- }
- return h;
-}
-
-/** calculate infra hash for a key */
-static hashvalue_type
-hash_infra(struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* name)
-{
- return dname_query_hash(name, hash_addr(addr, addrlen, 1));
-}
-
-/** lookup version that does not check host ttl (you check it) */
-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_key k;
- k.addrlen = addrlen;
- memcpy(&k.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);
-}
-
-/** init the data elements */
-static void
-data_entry_init(struct infra_cache* infra, struct lruhash_entry* e,
- time_t timenow)
-{
- 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;
- data->timeout_A = 0;
- data->timeout_AAAA = 0;
- data->timeout_other = 0;
-}
-
-/**
- * Create and init a new entry for a host
- * @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_entry(struct infra_cache* infra, struct sockaddr_storage* addr,
- socklen_t addrlen, uint8_t* name, size_t namelen, time_t tm)
-{
- struct infra_data* data;
- struct infra_key* key = (struct infra_key*)malloc(sizeof(*key));
- if(!key)
- return NULL;
- 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_infra(addr, addrlen, name);
- key->entry.key = (void*)key;
- key->entry.data = (void*)data;
- key->addrlen = addrlen;
- memcpy(&key->addr, addr, addrlen);
- data_entry_init(infra, &key->entry, tm);
- return &key->entry;
-}
-
-int
-infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
- socklen_t addrlen, uint8_t* nm, size_t nmlen, time_t timenow,
- int* edns_vs, uint8_t* edns_lame_known, int* to)
-{
- struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
- nm, nmlen, 0);
- struct infra_data* data;
- int wr = 0;
- if(e && ((struct infra_data*)e->data)->ttl < timenow) {
- /* it expired, try to reuse existing entry */
- int old = ((struct infra_data*)e->data)->rtt.rto;
- uint8_t tA = ((struct infra_data*)e->data)->timeout_A;
- uint8_t tAAAA = ((struct infra_data*)e->data)->timeout_AAAA;
- uint8_t tother = ((struct infra_data*)e->data)->timeout_other;
- lock_rw_unlock(&e->lock);
- 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 */
- data_entry_init(infra, e, timenow);
- wr = 1;
- /* TOP_TIMEOUT remains on reuse */
- if(old >= USEFUL_SERVER_TOP_TIMEOUT) {
- ((struct infra_data*)e->data)->rtt.rto
- = USEFUL_SERVER_TOP_TIMEOUT;
- ((struct infra_data*)e->data)->timeout_A = tA;
- ((struct infra_data*)e->data)->timeout_AAAA = tAAAA;
- ((struct infra_data*)e->data)->timeout_other = tother;
- }
- }
- }
- if(!e) {
- /* insert new entry */
- if(!(e = new_entry(infra, addr, addrlen, nm, nmlen, timenow)))
- return 0;
- 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_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_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_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
- * has timed out before the next is allowed */
- data->probedelay = timenow + ((*to)+1999)/1000;
- }
- lock_rw_unlock(&e->lock);
- return 1;
-}
-
-int
-infra_set_lame(struct infra_cache* infra, struct sockaddr_storage* addr,
- socklen_t addrlen, uint8_t* nm, size_t nmlen, time_t timenow,
- int dnsseclame, int reclame, uint16_t qtype)
-{
- struct infra_data* data;
- struct lruhash_entry* e;
- int needtoinsert = 0;
- e = infra_lookup_nottl(infra, addr, addrlen, nm, nmlen, 1);
- if(!e) {
- /* insert it */
- 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_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); }
- return 1;
-}
-
-void
-infra_update_tcp_works(struct infra_cache* infra,
- struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* nm,
- size_t nmlen)
-{
- 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_data*)e->data;
- if(data->rtt.rto >= RTT_MAX_TIMEOUT)
- /* do not disqualify this server altogether, it is better
- * than nothing */
- data->rtt.rto = RTT_MAX_TIMEOUT-1000;
- lock_rw_unlock(&e->lock);
-}
-
-int
-infra_rtt_update(struct infra_cache* infra, struct sockaddr_storage* addr,
- socklen_t addrlen, uint8_t* nm, size_t nmlen, int qtype,
- int roundtrip, int orig_rtt, time_t timenow)
-{
- 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_entry(infra, addr, addrlen, nm, nmlen, timenow)))
- return 0;
- needtoinsert = 1;
- } else if(((struct infra_data*)e->data)->ttl < timenow) {
- data_entry_init(infra, e, timenow);
- }
- /* have an entry, update the rtt */
- data = (struct infra_data*)e->data;
- if(roundtrip == -1) {
- rtt_lost(&data->rtt, orig_rtt);
- if(qtype == LDNS_RR_TYPE_A) {
- if(data->timeout_A < TIMEOUT_COUNT_MAX)
- data->timeout_A++;
- } else if(qtype == LDNS_RR_TYPE_AAAA) {
- if(data->timeout_AAAA < TIMEOUT_COUNT_MAX)
- data->timeout_AAAA++;
- } else {
- if(data->timeout_other < TIMEOUT_COUNT_MAX)
- data->timeout_other++;
- }
- } else {
- /* if we got a reply, but the old timeout was above server
- * selection height, delete the timeout so the server is
- * fully available again */
- if(rtt_unclamped(&data->rtt) >= USEFUL_SERVER_TOP_TIMEOUT)
- rtt_init(&data->rtt);
- rtt_update(&data->rtt, roundtrip);
- data->probedelay = 0;
- if(qtype == LDNS_RR_TYPE_A)
- data->timeout_A = 0;
- else if(qtype == LDNS_RR_TYPE_AAAA)
- data->timeout_AAAA = 0;
- else data->timeout_other = 0;
- }
- if(data->rtt.rto > 0)
- rto = data->rtt.rto;
-
- if(needtoinsert)
- slabhash_insert(infra->hosts, e->hash, e, e->data, NULL);
- else { lock_rw_unlock(&e->lock); }
- return rto;
-}
-
-long long infra_get_host_rto(struct infra_cache* infra,
- struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* nm,
- size_t nmlen, struct rtt_info* rtt, int* delay, time_t timenow,
- int* tA, int* tAAAA, int* tother)
-{
- struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
- nm, nmlen, 0);
- struct infra_data* data;
- long long ttl = -2;
- if(!e) return -1;
- data = (struct infra_data*)e->data;
- if(data->ttl >= timenow) {
- ttl = (long long)(data->ttl - timenow);
- memmove(rtt, &data->rtt, sizeof(*rtt));
- if(timenow < data->probedelay)
- *delay = (int)(data->probedelay - timenow);
- else *delay = 0;
- }
- *tA = (int)data->timeout_A;
- *tAAAA = (int)data->timeout_AAAA;
- *tother = (int)data->timeout_other;
- lock_rw_unlock(&e->lock);
- return ttl;
-}
-
-int
-infra_edns_update(struct infra_cache* infra, struct sockaddr_storage* addr,
- socklen_t addrlen, uint8_t* nm, size_t nmlen, int edns_version,
- time_t timenow)
-{
- 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_entry(infra, addr, addrlen, nm, nmlen, timenow)))
- return 0;
- needtoinsert = 1;
- } 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_data*)e->data;
- /* do not update if noEDNS and stored is yesEDNS */
- if(!(edns_version == -1 && (data->edns_version != -1 &&
- data->edns_lame_known))) {
- data->edns_version = edns_version;
- data->edns_lame_known = 1;
- }
-
- if(needtoinsert)
- slabhash_insert(infra->hosts, e->hash, e, e->data, NULL);
- else { lock_rw_unlock(&e->lock); }
- return 1;
-}
-
-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, time_t timenow)
-{
- struct infra_data* host;
- struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
- name, namelen, 0);
- if(!e)
- return 0;
- 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 */
- /* unless the query type allows a probe to happen */
- if(qtype == LDNS_RR_TYPE_A) {
- if(host->timeout_A >= TIMEOUT_COUNT_MAX)
- *rtt = USEFUL_SERVER_TOP_TIMEOUT;
- else *rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
- } else if(qtype == LDNS_RR_TYPE_AAAA) {
- if(host->timeout_AAAA >= TIMEOUT_COUNT_MAX)
- *rtt = USEFUL_SERVER_TOP_TIMEOUT;
- else *rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
- } else {
- if(host->timeout_other >= TIMEOUT_COUNT_MAX)
- *rtt = USEFUL_SERVER_TOP_TIMEOUT;
- else *rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
- }
- }
- if(timenow > host->ttl) {
- /* expired entry */
- /* see if this can be a re-probe of an unresponsive server */
- /* minus 1000 because that is outside of the RTTBAND, so
- * blacklisted servers stay blacklisted if this is chosen */
- if(host->rtt.rto >= USEFUL_SERVER_TOP_TIMEOUT) {
- lock_rw_unlock(&e->lock);
- *rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
- *lame = 0;
- *dnsseclame = 0;
- *reclame = 0;
- return 1;
- }
- 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;
-}
-
-int infra_find_ratelimit(struct infra_cache* infra, uint8_t* name,
- size_t namelen)
-{
- int labs = dname_count_labels(name);
- struct domain_limit_data* d = (struct domain_limit_data*)
- name_tree_lookup(&infra->domain_limits, name, namelen, labs,
- LDNS_RR_CLASS_IN);
- if(!d) return infra_dp_ratelimit;
-
- if(d->node.labs == labs && d->lim != -1)
- return d->lim; /* exact match */
-
- /* find 'below match' */
- if(d->node.labs == labs)
- d = (struct domain_limit_data*)d->node.parent;
- while(d) {
- if(d->below != -1)
- return d->below;
- d = (struct domain_limit_data*)d->node.parent;
- }
- return infra_dp_ratelimit;
-}
-
-size_t ip_rate_sizefunc(void* k, void* ATTR_UNUSED(d))
-{
- struct ip_rate_key* key = (struct ip_rate_key*)k;
- return sizeof(*key) + sizeof(struct ip_rate_data)
- + lock_get_mem(&key->entry.lock);
-}
-
-int ip_rate_compfunc(void* key1, void* key2)
-{
- struct ip_rate_key* k1 = (struct ip_rate_key*)key1;
- struct ip_rate_key* k2 = (struct ip_rate_key*)key2;
- return sockaddr_cmp_addr(&k1->addr, k1->addrlen,
- &k2->addr, k2->addrlen);
-}
-
-void ip_rate_delkeyfunc(void* k, void* ATTR_UNUSED(arg))
-{
- struct ip_rate_key* key = (struct ip_rate_key*)k;
- if(!key)
- return;
- lock_rw_destroy(&key->entry.lock);
- free(key);
-}
-
-/** find data item in array, for write access, caller unlocks */
-static struct lruhash_entry* infra_find_ratedata(struct infra_cache* infra,
- uint8_t* name, size_t namelen, int wr)
-{
- struct rate_key key;
- hashvalue_type h = dname_query_hash(name, 0xab);
- memset(&key, 0, sizeof(key));
- key.name = name;
- key.namelen = namelen;
- key.entry.hash = h;
- return slabhash_lookup(infra->domain_rates, h, &key, wr);
-}
-
-/** find data item in array for ip addresses */
-struct lruhash_entry* infra_find_ip_ratedata(struct infra_cache* infra,
- struct comm_reply* repinfo, int wr)
-{
- struct ip_rate_key key;
- hashvalue_type h = hash_addr(&(repinfo->addr),
- repinfo->addrlen, 0);
- memset(&key, 0, sizeof(key));
- key.addr = repinfo->addr;
- key.addrlen = repinfo->addrlen;
- key.entry.hash = h;
- return slabhash_lookup(infra->client_ip_rates, h, &key, wr);
-}
-
-/** create rate data item for name, number 1 in now */
-static void infra_create_ratedata(struct infra_cache* infra,
- uint8_t* name, size_t namelen, time_t timenow)
-{
- hashvalue_type h = dname_query_hash(name, 0xab);
- struct rate_key* k = (struct rate_key*)calloc(1, sizeof(*k));
- struct rate_data* d = (struct rate_data*)calloc(1, sizeof(*d));
- if(!k || !d) {
- free(k);
- free(d);
- return; /* alloc failure */
- }
- k->namelen = namelen;
- k->name = memdup(name, namelen);
- if(!k->name) {
- free(k);
- free(d);
- return; /* alloc failure */
- }
- lock_rw_init(&k->entry.lock);
- k->entry.hash = h;
- k->entry.key = k;
- k->entry.data = d;
- d->qps[0] = 1;
- d->timestamp[0] = timenow;
- slabhash_insert(infra->domain_rates, h, &k->entry, d, NULL);
-}
-
-/** create rate data item for ip address */
-static void infra_ip_create_ratedata(struct infra_cache* infra,
- struct comm_reply* repinfo, time_t timenow)
-{
- hashvalue_type h = hash_addr(&(repinfo->addr),
- repinfo->addrlen, 0);
- struct ip_rate_key* k = (struct ip_rate_key*)calloc(1, sizeof(*k));
- struct ip_rate_data* d = (struct ip_rate_data*)calloc(1, sizeof(*d));
- if(!k || !d) {
- free(k);
- free(d);
- return; /* alloc failure */
- }
- k->addr = repinfo->addr;
- k->addrlen = repinfo->addrlen;
- lock_rw_init(&k->entry.lock);
- k->entry.hash = h;
- k->entry.key = k;
- k->entry.data = d;
- d->qps[0] = 1;
- d->timestamp[0] = timenow;
- slabhash_insert(infra->client_ip_rates, h, &k->entry, d, NULL);
-}
-
-/** find the second and return its rate counter, if none, remove oldest */
-static int* infra_rate_find_second(void* data, time_t t)
-{
- struct rate_data* d = (struct rate_data*)data;
- int i, oldest;
- for(i=0; i<RATE_WINDOW; i++) {
- if(d->timestamp[i] == t)
- return &(d->qps[i]);
- }
- /* remove oldest timestamp, and insert it at t with 0 qps */
- oldest = 0;
- for(i=0; i<RATE_WINDOW; i++) {
- if(d->timestamp[i] < d->timestamp[oldest])
- oldest = i;
- }
- d->timestamp[oldest] = t;
- d->qps[oldest] = 0;
- return &(d->qps[oldest]);
-}
-
-int infra_rate_max(void* data, time_t now)
-{
- struct rate_data* d = (struct rate_data*)data;
- int i, max = 0;
- for(i=0; i<RATE_WINDOW; i++) {
- if(now-d->timestamp[i] <= RATE_WINDOW) {
- if(d->qps[i] > max)
- max = d->qps[i];
- }
- }
- return max;
-}
-
-int infra_ratelimit_inc(struct infra_cache* infra, uint8_t* name,
- size_t namelen, time_t timenow)
-{
- int lim, max;
- struct lruhash_entry* entry;
-
- if(!infra_dp_ratelimit)
- return 1; /* not enabled */
-
- /* find ratelimit */
- lim = infra_find_ratelimit(infra, name, namelen);
-
- /* find or insert ratedata */
- entry = infra_find_ratedata(infra, name, namelen, 1);
- if(entry) {
- int premax = infra_rate_max(entry->data, timenow);
- int* cur = infra_rate_find_second(entry->data, timenow);
- (*cur)++;
- max = infra_rate_max(entry->data, timenow);
- lock_rw_unlock(&entry->lock);
-
- if(premax < lim && max >= lim) {
- char buf[257];
- dname_str(name, buf);
- verbose(VERB_OPS, "ratelimit exceeded %s %d", buf, lim);
- }
- return (max < lim);
- }
-
- /* create */
- infra_create_ratedata(infra, name, namelen, timenow);
- return (1 < lim);
-}
-
-void infra_ratelimit_dec(struct infra_cache* infra, uint8_t* name,
- size_t namelen, time_t timenow)
-{
- struct lruhash_entry* entry;
- int* cur;
- if(!infra_dp_ratelimit)
- return; /* not enabled */
- entry = infra_find_ratedata(infra, name, namelen, 1);
- if(!entry) return; /* not cached */
- cur = infra_rate_find_second(entry->data, timenow);
- if((*cur) > 0)
- (*cur)--;
- lock_rw_unlock(&entry->lock);
-}
-
-int infra_ratelimit_exceeded(struct infra_cache* infra, uint8_t* name,
- size_t namelen, time_t timenow)
-{
- struct lruhash_entry* entry;
- int lim, max;
- if(!infra_dp_ratelimit)
- return 0; /* not enabled */
-
- /* find ratelimit */
- lim = infra_find_ratelimit(infra, name, namelen);
-
- /* find current rate */
- entry = infra_find_ratedata(infra, name, namelen, 0);
- if(!entry)
- return 0; /* not cached */
- max = infra_rate_max(entry->data, timenow);
- lock_rw_unlock(&entry->lock);
-
- return (max >= lim);
-}
-
-size_t
-infra_get_mem(struct infra_cache* infra)
-{
- size_t s = sizeof(*infra) + slabhash_get_mem(infra->hosts);
- if(infra->domain_rates) s += slabhash_get_mem(infra->domain_rates);
- if(infra->client_ip_rates) s += slabhash_get_mem(infra->client_ip_rates);
- /* ignore domain_limits because walk through tree is big */
- return s;
-}
-
-int infra_ip_ratelimit_inc(struct infra_cache* infra,
- struct comm_reply* repinfo, time_t timenow)
-{
- int max;
- struct lruhash_entry* entry;
-
- /* not enabled */
- if(!infra_ip_ratelimit) {
- return 1;
- }
- /* find or insert ratedata */
- entry = infra_find_ip_ratedata(infra, repinfo, 1);
- if(entry) {
- int premax = infra_rate_max(entry->data, timenow);
- int* cur = infra_rate_find_second(entry->data, timenow);
- (*cur)++;
- max = infra_rate_max(entry->data, timenow);
- lock_rw_unlock(&entry->lock);
-
- if(premax < infra_ip_ratelimit && max >= infra_ip_ratelimit) {
- char client_ip[128];
- addr_to_str((struct sockaddr_storage *)&repinfo->addr,
- repinfo->addrlen, client_ip, sizeof(client_ip));
- verbose(VERB_OPS, "ratelimit exceeded %s %d", client_ip,
- infra_ip_ratelimit);
- }
- return (max <= infra_ip_ratelimit);
- }
-
- /* create */
- infra_ip_create_ratedata(infra, repinfo, timenow);
- return 1;
-}
diff --git a/external/unbound/services/cache/infra.h b/external/unbound/services/cache/infra.h
deleted file mode 100644
index 6f9471a39..000000000
--- a/external/unbound/services/cache/infra.h
+++ /dev/null
@@ -1,462 +0,0 @@
-/*
- * services/cache/infra.h - infrastructure cache, server rtt and capabilities
- *
- * Copyright (c) 2007, NLnet Labs. All rights reserved.
- *
- * This software is open source.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the NLNET LABS nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * \file
- *
- * This file contains the infrastructure cache, as well as rate limiting.
- * Note that there are two sorts of rate-limiting here:
- * - Pre-cache, per-query rate limiting (query ratelimits)
- * - Post-cache, per-domain name rate limiting (infra-ratelimits)
- */
-
-#ifndef SERVICES_CACHE_INFRA_H
-#define SERVICES_CACHE_INFRA_H
-#include "util/storage/lruhash.h"
-#include "util/storage/dnstree.h"
-#include "util/rtt.h"
-#include "util/netevent.h"
-#include "util/data/msgreply.h"
-struct slabhash;
-struct config_file;
-
-/**
- * Host information kept for every server, per zone.
- */
-struct infra_key {
- /** the host address. */
- struct sockaddr_storage addr;
- /** length of addr. */
- socklen_t addrlen;
- /** 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_data {
- /** TTL value for this entry. absolute time. */
- time_t ttl;
-
- /** time in seconds (absolute) when probing re-commences, 0 disabled */
- time_t probedelay;
- /** round trip times for timeout calculation */
- struct rtt_info rtt;
-
- /** 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;
-
- /** is the host lame (does not serve the zone authoritatively),
- * or is the host dnssec lame (does not serve DNSSEC data) */
- uint8_t isdnsseclame;
- /** is the host recursion lame (not AA, but RA) */
- uint8_t rec_lame;
- /** the host is lame (not authoritative) for A records */
- uint8_t lame_type_A;
- /** the host is lame (not authoritative) for other query types */
- uint8_t lame_other;
-
- /** timeouts counter for type A */
- uint8_t timeout_A;
- /** timeouts counter for type AAAA */
- uint8_t timeout_AAAA;
- /** timeouts counter for others */
- uint8_t timeout_other;
-};
-
-/**
- * Infra cache
- */
-struct infra_cache {
- /** The hash table with hosts */
- struct slabhash* hosts;
- /** TTL value for host information, in seconds */
- int host_ttl;
- /** hash table with query rates per name: rate_key, rate_data */
- struct slabhash* domain_rates;
- /** ratelimit settings for domains, struct domain_limit_data */
- rbtree_type domain_limits;
- /** hash table with query rates per client ip: ip_rate_key, ip_rate_data */
- struct slabhash* client_ip_rates;
-};
-
-/** ratelimit, unless overridden by domain_limits, 0 is off */
-extern int infra_dp_ratelimit;
-
-/**
- * ratelimit settings for domains
- */
-struct domain_limit_data {
- /** key for rbtree, must be first in struct, name of domain */
- struct name_tree_node node;
- /** ratelimit for exact match with this name, -1 if not set */
- int lim;
- /** ratelimit for names below this name, -1 if not set */
- int below;
-};
-
-/**
- * key for ratelimit lookups, a domain name
- */
-struct rate_key {
- /** lruhash key entry */
- struct lruhash_entry entry;
- /** domain name in uncompressed wireformat */
- uint8_t* name;
- /** length of name */
- size_t namelen;
-};
-
-/** ip ratelimit, 0 is off */
-extern int infra_ip_ratelimit;
-
-/**
- * key for ip_ratelimit lookups, a source IP.
- */
-struct ip_rate_key {
- /** lruhash key entry */
- struct lruhash_entry entry;
- /** client ip information */
- struct sockaddr_storage addr;
- /** length of address */
- socklen_t addrlen;
-};
-
-/** number of seconds to track qps rate */
-#define RATE_WINDOW 2
-
-/**
- * Data for ratelimits per domain name
- * It is incremented when a non-cache-lookup happens for that domain name.
- * The name is the delegation point we have for the name.
- * If a new delegation point is found (a referral reply), the previous
- * delegation point is decremented, and the new one is charged with the query.
- */
-struct rate_data {
- /** queries counted, for that second. 0 if not in use. */
- int qps[RATE_WINDOW];
- /** what the timestamp is of the qps array members, counter is
- * valid for that timestamp. Usually now and now-1. */
- time_t timestamp[RATE_WINDOW];
-};
-
-#define ip_rate_data rate_data
-
-/** infra host cache default hash lookup size */
-#define INFRA_HOST_STARTSIZE 32
-/** bytes per zonename reserved in the hostcache, dnamelen(zonename.com.) */
-#define INFRA_BYTES_NAME 14
-
-/**
- * Create infra cache.
- * @param cfg: config parameters or NULL for defaults.
- * @return: new infra cache, or NULL.
- */
-struct infra_cache* infra_create(struct config_file* cfg);
-
-/**
- * Delete infra cache.
- * @param infra: infrastructure cache to delete.
- */
-void infra_delete(struct infra_cache* infra);
-
-/**
- * Adjust infra cache to use updated configuration settings.
- * This may clean the cache. Operates a bit like realloc.
- * There may be no threading or use by other threads.
- * @param infra: existing cache. If NULL a new infra cache is returned.
- * @param cfg: config options.
- * @return the new infra cache pointer or NULL on error.
- */
-struct infra_cache* infra_adjust(struct infra_cache* infra,
- struct config_file* cfg);
-
-/**
- * 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 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 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.
- * Lameness is empty. EDNS is 0 (try with first), and rtt is returned for
- * the first message to it.
- * Use this to send a packet only, because it also locks out others when
- * probing is restricted.
- * @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
- * already been probed, is returned.
- * @param to: timeout to use, is returned.
- * @return: 0 on error.
- */
-int infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
- socklen_t addrlen, uint8_t* name, size_t namelen,
- time_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: domain name of zone apex.
- * @param namelen: length of domain name.
- * @param timenow: what time it is now.
- * @param dnsseclame: if true the host is set dnssec lame.
- * if false, the host is marked lame (not serving the zone).
- * @param reclame: if true host is a recursor not AA server.
- * if false, dnsseclame or marked lame.
- * @param qtype: the query type for which it is lame.
- * @return: 0 on error.
- */
-int infra_set_lame(struct infra_cache* infra,
- struct sockaddr_storage* addr, socklen_t addrlen,
- uint8_t* name, size_t namelen, time_t timenow, int dnsseclame,
- int reclame, uint16_t qtype);
-
-/**
- * Update rtt information for the host.
- * @param infra: infrastructure cache.
- * @param addr: host address.
- * @param addrlen: length of addr.
- * @param name: zone name
- * @param namelen: zone name length
- * @param qtype: query type.
- * @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).
- * ignored if 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, uint8_t* name, size_t namelen, int qtype,
- int roundtrip, int orig_rtt, time_t timenow);
-
-/**
- * Update information for the host, store that a TCP transaction works.
- * @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,
- 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.
- * @return: 0 on error.
- */
-int infra_edns_update(struct infra_cache* infra,
- struct sockaddr_storage* addr, socklen_t addrlen,
- uint8_t* name, size_t namelen, int edns_version, time_t timenow);
-
-/**
- * Get Lameness information and average RTT if host is in the cache.
- * This information is to be used for server selection.
- * @param infra: infrastructure cache.
- * @param addr: host address.
- * @param addrlen: length of addr.
- * @param name: zone name.
- * @param namelen: zone name length.
- * @param qtype: the query to be made.
- * @param lame: if function returns true, this returns lameness of the zone.
- * @param dnsseclame: if function returns true, this returns if the zone
- * is dnssec-lame.
- * @param reclame: if function returns true, this is if it is recursion lame.
- * @param rtt: if function returns true, this returns avg rtt of the server.
- * The rtt value is unclamped and reflects recent timeouts.
- * @param timenow: what time it is now.
- * @return if found in cache, or false if not (or TTL bad).
- */
-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, time_t timenow);
-
-/**
- * Get additional (debug) info on timing.
- * @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.
- * @param tA: timeout counter on type A.
- * @param tAAAA: timeout counter on type AAAA.
- * @param tother: timeout counter on type other.
- * @return TTL the infra host element is valid for. If -1: not found in cache.
- * TTL -2: found but expired.
- */
-long long infra_get_host_rto(struct infra_cache* infra,
- struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* name,
- size_t namelen, struct rtt_info* rtt, int* delay, time_t timenow,
- int* tA, int* tAAAA, int* tother);
-
-/**
- * Increment the query rate counter for a delegation point.
- * @param infra: infra cache.
- * @param name: zone name
- * @param namelen: zone name length
- * @param timenow: what time it is now.
- * @return 1 if it could be incremented. 0 if the increment overshot the
- * ratelimit or if in the previous second the ratelimit was exceeded.
- * Failures like alloc failures are not returned (probably as 1).
- */
-int infra_ratelimit_inc(struct infra_cache* infra, uint8_t* name,
- size_t namelen, time_t timenow);
-
-/**
- * Decrement the query rate counter for a delegation point.
- * Because the reply received for the delegation point was pleasant,
- * we do not charge this delegation point with it (i.e. it was a referral).
- * Should call it with same second as when inc() was called.
- * @param infra: infra cache.
- * @param name: zone name
- * @param namelen: zone name length
- * @param timenow: what time it is now.
- */
-void infra_ratelimit_dec(struct infra_cache* infra, uint8_t* name,
- size_t namelen, time_t timenow);
-
-/**
- * See if the query rate counter for a delegation point is exceeded.
- * So, no queries are going to be allowed.
- * @param infra: infra cache.
- * @param name: zone name
- * @param namelen: zone name length
- * @param timenow: what time it is now.
- * @return true if exceeded.
- */
-int infra_ratelimit_exceeded(struct infra_cache* infra, uint8_t* name,
- size_t namelen, time_t timenow);
-
-/** find the maximum rate stored, not too old. 0 if no information. */
-int infra_rate_max(void* data, time_t now);
-
-/** find the ratelimit in qps for a domain */
-int infra_find_ratelimit(struct infra_cache* infra, uint8_t* name,
- size_t namelen);
-
-/** Update query ratelimit hash and decide
- * whether or not a query should be dropped.
- * @param infra: infra cache
- * @param repinfo: information about client
- * @param timenow: what time it is now.
- * @return 1 if it could be incremented. 0 if the increment overshot the
- * ratelimit and the query should be dropped. */
-int infra_ip_ratelimit_inc(struct infra_cache* infra,
- struct comm_reply* repinfo, time_t timenow);
-
-/**
- * Get memory used by the infra cache.
- * @param infra: infrastructure cache.
- * @return memory in use in bytes.
- */
-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_sizefunc(void* k, void* d);
-
-/** compare two addresses, returns -1, 0, or +1 */
-int infra_compfunc(void* key1, void* key2);
-
-/** delete key, and destroy the lock */
-void infra_delkeyfunc(void* k, void* arg);
-
-/** delete data and destroy the lameness hashtable */
-void infra_deldatafunc(void* d, void* arg);
-
-/** calculate size for the hashtable */
-size_t rate_sizefunc(void* k, void* d);
-
-/** compare two names, returns -1, 0, or +1 */
-int rate_compfunc(void* key1, void* key2);
-
-/** delete key, and destroy the lock */
-void rate_delkeyfunc(void* k, void* arg);
-
-/** delete data */
-void rate_deldatafunc(void* d, void* arg);
-
-/* calculate size for the client ip hashtable */
-size_t ip_rate_sizefunc(void* k, void* d);
-
-/* compare two addresses */
-int ip_rate_compfunc(void* key1, void* key2);
-
-/* delete key, and destroy the lock */
-void ip_rate_delkeyfunc(void* d, void* arg);
-
-/* delete data */
-#define ip_rate_deldatafunc rate_deldatafunc
-
-#endif /* SERVICES_CACHE_INFRA_H */
diff --git a/external/unbound/services/cache/rrset.c b/external/unbound/services/cache/rrset.c
deleted file mode 100644
index 7e5732b76..000000000
--- a/external/unbound/services/cache/rrset.c
+++ /dev/null
@@ -1,419 +0,0 @@
-/*
- * services/cache/rrset.c - Resource record set cache.
- *
- * Copyright (c) 2007, NLnet Labs. All rights reserved.
- *
- * This software is open source.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the NLNET LABS nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * \file
- *
- * This file contains the rrset cache.
- */
-#include "config.h"
-#include "services/cache/rrset.h"
-#include "sldns/rrdef.h"
-#include "util/storage/slabhash.h"
-#include "util/config_file.h"
-#include "util/data/packed_rrset.h"
-#include "util/data/msgreply.h"
-#include "util/regional.h"
-#include "util/alloc.h"
-
-void
-rrset_markdel(void* key)
-{
- struct ub_packed_rrset_key* r = (struct ub_packed_rrset_key*)key;
- r->id = 0;
-}
-
-struct rrset_cache* rrset_cache_create(struct config_file* cfg,
- struct alloc_cache* alloc)
-{
- size_t slabs = (cfg?cfg->rrset_cache_slabs:HASH_DEFAULT_SLABS);
- size_t startarray = HASH_DEFAULT_STARTARRAY;
- size_t maxmem = (cfg?cfg->rrset_cache_size:HASH_DEFAULT_MAXMEM);
-
- struct rrset_cache *r = (struct rrset_cache*)slabhash_create(slabs,
- startarray, maxmem, ub_rrset_sizefunc, ub_rrset_compare,
- ub_rrset_key_delete, rrset_data_delete, alloc);
- slabhash_setmarkdel(&r->table, &rrset_markdel);
- return r;
-}
-
-void rrset_cache_delete(struct rrset_cache* r)
-{
- if(!r)
- return;
- slabhash_delete(&r->table);
- /* slabhash delete also does free(r), since table is first in struct*/
-}
-
-struct rrset_cache* rrset_cache_adjust(struct rrset_cache *r,
- struct config_file* cfg, struct alloc_cache* alloc)
-{
- if(!r || !cfg || cfg->rrset_cache_slabs != r->table.size ||
- cfg->rrset_cache_size != slabhash_get_size(&r->table))
- {
- rrset_cache_delete(r);
- r = rrset_cache_create(cfg, alloc);
- }
- return r;
-}
-
-void
-rrset_cache_touch(struct rrset_cache* r, struct ub_packed_rrset_key* key,
- hashvalue_type hash, rrset_id_type id)
-{
- struct lruhash* table = slabhash_gettable(&r->table, hash);
- /*
- * This leads to locking problems, deadlocks, if the caller is
- * holding any other rrset lock.
- * Because a lookup through the hashtable does:
- * tablelock -> entrylock (for that entry caller holds)
- * And this would do
- * entrylock(already held) -> tablelock
- * And if two threads do this, it results in deadlock.
- * So, the caller must not hold entrylock.
- */
- lock_quick_lock(&table->lock);
- /* we have locked the hash table, the item can still be deleted.
- * because it could already have been reclaimed, but not yet set id=0.
- * This is because some lruhash routines have lazy deletion.
- * so, we must acquire a lock on the item to verify the id != 0.
- * also, with hash not changed, we are using the right slab.
- */
- lock_rw_rdlock(&key->entry.lock);
- if(key->id == id && key->entry.hash == hash) {
- lru_touch(table, &key->entry);
- }
- lock_rw_unlock(&key->entry.lock);
- lock_quick_unlock(&table->lock);
-}
-
-/** see if rrset needs to be updated in the cache */
-static int
-need_to_update_rrset(void* nd, void* cd, time_t timenow, int equal, int ns)
-{
- struct packed_rrset_data* newd = (struct packed_rrset_data*)nd;
- struct packed_rrset_data* cached = (struct packed_rrset_data*)cd;
- /* o store if rrset has been validated
- * everything better than bogus data
- * secure is preferred */
- if( newd->security == sec_status_secure &&
- cached->security != sec_status_secure)
- return 1;
- if( cached->security == sec_status_bogus &&
- newd->security != sec_status_bogus && !equal)
- return 1;
- /* o if current RRset is more trustworthy - insert it */
- if( newd->trust > cached->trust ) {
- /* if the cached rrset is bogus, and this one equal,
- * do not update the TTL - let it expire. */
- if(equal && cached->ttl >= timenow &&
- cached->security == sec_status_bogus)
- return 0;
- return 1;
- }
- /* o item in cache has expired */
- if( cached->ttl < timenow )
- return 1;
- /* o same trust, but different in data - insert it */
- if( newd->trust == cached->trust && !equal ) {
- /* if this is type NS, do not 'stick' to owner that changes
- * the NS RRset, but use the old TTL for the new data, and
- * update to fetch the latest data. ttl is not expired, because
- * that check was before this one. */
- if(ns) {
- size_t i;
- newd->ttl = cached->ttl;
- for(i=0; i<(newd->count+newd->rrsig_count); i++)
- if(newd->rr_ttl[i] > newd->ttl)
- newd->rr_ttl[i] = newd->ttl;
- }
- return 1;
- }
- return 0;
-}
-
-/** Update RRSet special key ID */
-static void
-rrset_update_id(struct rrset_ref* ref, struct alloc_cache* alloc)
-{
- /* this may clear the cache and invalidate lock below */
- uint64_t newid = alloc_get_id(alloc);
- /* obtain writelock */
- lock_rw_wrlock(&ref->key->entry.lock);
- /* check if it was deleted in the meantime, if so, skip update */
- if(ref->key->id == ref->id) {
- ref->key->id = newid;
- ref->id = newid;
- }
- lock_rw_unlock(&ref->key->entry.lock);
-}
-
-int
-rrset_cache_update(struct rrset_cache* r, struct rrset_ref* ref,
- struct alloc_cache* alloc, time_t timenow)
-{
- struct lruhash_entry* e;
- struct ub_packed_rrset_key* k = ref->key;
- hashvalue_type h = k->entry.hash;
- uint16_t rrset_type = ntohs(k->rk.type);
- int equal = 0;
- log_assert(ref->id != 0 && k->id != 0);
- log_assert(k->rk.dname != NULL);
- /* looks up item with a readlock - no editing! */
- if((e=slabhash_lookup(&r->table, h, k, 0)) != 0) {
- /* return id and key as they will be used in the cache
- * since the lruhash_insert, if item already exists, deallocs
- * the passed key in favor of the already stored key.
- * because of the small gap (see below) this key ptr and id
- * may prove later to be already deleted, which is no problem
- * as it only makes a cache miss.
- */
- ref->key = (struct ub_packed_rrset_key*)e->key;
- ref->id = ref->key->id;
- equal = rrsetdata_equal((struct packed_rrset_data*)k->entry.
- data, (struct packed_rrset_data*)e->data);
- if(!need_to_update_rrset(k->entry.data, e->data, timenow,
- equal, (rrset_type==LDNS_RR_TYPE_NS))) {
- /* cache is superior, return that value */
- lock_rw_unlock(&e->lock);
- ub_packed_rrset_parsedelete(k, alloc);
- if(equal) return 2;
- return 1;
- }
- lock_rw_unlock(&e->lock);
- /* Go on and insert the passed item.
- * small gap here, where entry is not locked.
- * possibly entry is updated with something else.
- * we then overwrite that with our data.
- * this is just too bad, its cache anyway. */
- /* use insert to update entry to manage lruhash
- * cache size values nicely. */
- }
- log_assert(ref->key->id != 0);
- slabhash_insert(&r->table, h, &k->entry, k->entry.data, alloc);
- if(e) {
- /* For NSEC, NSEC3, DNAME, when rdata is updated, update
- * the ID number so that proofs in message cache are
- * invalidated */
- if((rrset_type == LDNS_RR_TYPE_NSEC
- || rrset_type == LDNS_RR_TYPE_NSEC3
- || rrset_type == LDNS_RR_TYPE_DNAME) && !equal) {
- rrset_update_id(ref, alloc);
- }
- return 1;
- }
- return 0;
-}
-
-struct ub_packed_rrset_key*
-rrset_cache_lookup(struct rrset_cache* r, uint8_t* qname, size_t qnamelen,
- uint16_t qtype, uint16_t qclass, uint32_t flags, time_t timenow,
- int wr)
-{
- struct lruhash_entry* e;
- struct ub_packed_rrset_key key;
-
- key.entry.key = &key;
- key.entry.data = NULL;
- key.rk.dname = qname;
- key.rk.dname_len = qnamelen;
- key.rk.type = htons(qtype);
- key.rk.rrset_class = htons(qclass);
- key.rk.flags = flags;
-
- key.entry.hash = rrset_key_hash(&key.rk);
-
- if((e = slabhash_lookup(&r->table, key.entry.hash, &key, wr))) {
- /* check TTL */
- struct packed_rrset_data* data =
- (struct packed_rrset_data*)e->data;
- if(timenow > data->ttl) {
- lock_rw_unlock(&e->lock);
- return NULL;
- }
- /* we're done */
- return (struct ub_packed_rrset_key*)e->key;
- }
- return NULL;
-}
-
-int
-rrset_array_lock(struct rrset_ref* ref, size_t count, time_t timenow)
-{
- size_t i;
- for(i=0; i<count; i++) {
- if(i>0 && ref[i].key == ref[i-1].key)
- continue; /* only lock items once */
- lock_rw_rdlock(&ref[i].key->entry.lock);
- if(ref[i].id != ref[i].key->id || timenow >
- ((struct packed_rrset_data*)(ref[i].key->entry.data))
- ->ttl) {
- /* failure! rollback our readlocks */
- rrset_array_unlock(ref, i+1);
- return 0;
- }
- }
- return 1;
-}
-
-void
-rrset_array_unlock(struct rrset_ref* ref, size_t count)
-{
- size_t i;
- for(i=0; i<count; i++) {
- if(i>0 && ref[i].key == ref[i-1].key)
- continue; /* only unlock items once */
- lock_rw_unlock(&ref[i].key->entry.lock);
- }
-}
-
-void
-rrset_array_unlock_touch(struct rrset_cache* r, struct regional* scratch,
- struct rrset_ref* ref, size_t count)
-{
- hashvalue_type* h;
- size_t i;
- if(count > RR_COUNT_MAX || !(h = (hashvalue_type*)regional_alloc(
- scratch, sizeof(hashvalue_type)*count))) {
- log_warn("rrset LRU: memory allocation failed");
- h = NULL;
- } else /* store hash values */
- for(i=0; i<count; i++)
- h[i] = ref[i].key->entry.hash;
- /* unlock */
- for(i=0; i<count; i++) {
- if(i>0 && ref[i].key == ref[i-1].key)
- continue; /* only unlock items once */
- lock_rw_unlock(&ref[i].key->entry.lock);
- }
- if(h) {
- /* LRU touch, with no rrset locks held */
- for(i=0; i<count; i++) {
- if(i>0 && ref[i].key == ref[i-1].key)
- continue; /* only touch items once */
- rrset_cache_touch(r, ref[i].key, h[i], ref[i].id);
- }
- }
-}
-
-void
-rrset_update_sec_status(struct rrset_cache* r,
- struct ub_packed_rrset_key* rrset, time_t now)
-{
- struct packed_rrset_data* updata =
- (struct packed_rrset_data*)rrset->entry.data;
- struct lruhash_entry* e;
- struct packed_rrset_data* cachedata;
-
- /* hash it again to make sure it has a hash */
- rrset->entry.hash = rrset_key_hash(&rrset->rk);
-
- e = slabhash_lookup(&r->table, rrset->entry.hash, rrset, 1);
- if(!e)
- return; /* not in the cache anymore */
- cachedata = (struct packed_rrset_data*)e->data;
- if(!rrsetdata_equal(updata, cachedata)) {
- lock_rw_unlock(&e->lock);
- return; /* rrset has changed in the meantime */
- }
- /* update the cached rrset */
- if(updata->security > cachedata->security) {
- size_t i;
- if(updata->trust > cachedata->trust)
- cachedata->trust = updata->trust;
- cachedata->security = updata->security;
- /* for NS records only shorter TTLs, other types: update it */
- if(ntohs(rrset->rk.type) != LDNS_RR_TYPE_NS ||
- updata->ttl+now < cachedata->ttl ||
- cachedata->ttl < now ||
- updata->security == sec_status_bogus) {
- cachedata->ttl = updata->ttl + now;
- for(i=0; i<cachedata->count+cachedata->rrsig_count; i++)
- cachedata->rr_ttl[i] = updata->rr_ttl[i]+now;
- }
- }
- lock_rw_unlock(&e->lock);
-}
-
-void
-rrset_check_sec_status(struct rrset_cache* r,
- struct ub_packed_rrset_key* rrset, time_t now)
-{
- struct packed_rrset_data* updata =
- (struct packed_rrset_data*)rrset->entry.data;
- struct lruhash_entry* e;
- struct packed_rrset_data* cachedata;
-
- /* hash it again to make sure it has a hash */
- rrset->entry.hash = rrset_key_hash(&rrset->rk);
-
- e = slabhash_lookup(&r->table, rrset->entry.hash, rrset, 0);
- if(!e)
- return; /* not in the cache anymore */
- cachedata = (struct packed_rrset_data*)e->data;
- if(now > cachedata->ttl || !rrsetdata_equal(updata, cachedata)) {
- lock_rw_unlock(&e->lock);
- return; /* expired, or rrset has changed in the meantime */
- }
- if(cachedata->security > updata->security) {
- updata->security = cachedata->security;
- if(cachedata->security == sec_status_bogus) {
- size_t i;
- updata->ttl = cachedata->ttl - now;
- for(i=0; i<cachedata->count+cachedata->rrsig_count; i++)
- if(cachedata->rr_ttl[i] < now)
- updata->rr_ttl[i] = 0;
- else updata->rr_ttl[i] =
- cachedata->rr_ttl[i]-now;
- }
- if(cachedata->trust > updata->trust)
- updata->trust = cachedata->trust;
- }
- lock_rw_unlock(&e->lock);
-}
-
-void rrset_cache_remove(struct rrset_cache* r, uint8_t* nm, size_t nmlen,
- uint16_t type, uint16_t dclass, uint32_t flags)
-{
- struct ub_packed_rrset_key key;
- key.entry.key = &key;
- key.rk.dname = nm;
- key.rk.dname_len = nmlen;
- key.rk.rrset_class = htons(dclass);
- key.rk.type = htons(type);
- key.rk.flags = flags;
- key.entry.hash = rrset_key_hash(&key.rk);
- slabhash_remove(&r->table, key.entry.hash, &key);
-}
diff --git a/external/unbound/services/cache/rrset.h b/external/unbound/services/cache/rrset.h
deleted file mode 100644
index d5439ef08..000000000
--- a/external/unbound/services/cache/rrset.h
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * services/cache/rrset.h - Resource record set cache.
- *
- * Copyright (c) 2007, NLnet Labs. All rights reserved.
- *
- * This software is open source.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the NLNET LABS nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * \file
- *
- * This file contains the rrset cache.
- */
-
-#ifndef SERVICES_CACHE_RRSET_H
-#define SERVICES_CACHE_RRSET_H
-#include "util/storage/lruhash.h"
-#include "util/storage/slabhash.h"
-#include "util/data/packed_rrset.h"
-struct config_file;
-struct alloc_cache;
-struct rrset_ref;
-struct regional;
-
-/**
- * The rrset cache
- * Thin wrapper around hashtable, like a typedef.
- */
-struct rrset_cache {
- /** uses partitioned hash table */
- struct slabhash table;
-};
-
-/**
- * Create rrset cache
- * @param cfg: config settings or NULL for defaults.
- * @param alloc: initial default rrset key allocation.
- * @return: NULL on error.
- */
-struct rrset_cache* rrset_cache_create(struct config_file* cfg,
- struct alloc_cache* alloc);
-
-/**
- * Delete rrset cache
- * @param r: rrset cache to delete.
- */
-void rrset_cache_delete(struct rrset_cache* r);
-
-/**
- * Adjust settings of the cache to settings from the config file.
- * May purge the cache. May recreate the cache.
- * There may be no threading or use by other threads.
- * @param r: rrset cache to adjust (like realloc).
- * @param cfg: config settings or NULL for defaults.
- * @param alloc: initial default rrset key allocation.
- * @return 0 on error, or new rrset cache pointer on success.
- */
-struct rrset_cache* rrset_cache_adjust(struct rrset_cache* r,
- struct config_file* cfg, struct alloc_cache* alloc);
-
-/**
- * Touch rrset, with given pointer and id.
- * Caller may not hold a lock on ANY rrset, this could give deadlock.
- *
- * This routine is faster than a hashtable lookup:
- * o no bin_lock is acquired.
- * o no walk through the bin-overflow-list.
- * o no comparison of the entry key to find it.
- *
- * @param r: rrset cache.
- * @param key: rrset key. Marked recently used (if it was not deleted
- * before the lock is acquired, in that case nothing happens).
- * @param hash: hash value of the item. Please read it from the key when
- * you have it locked. Used to find slab from slabhash.
- * @param id: used to check that the item is unchanged and not deleted.
- */
-void rrset_cache_touch(struct rrset_cache* r, struct ub_packed_rrset_key* key,
- hashvalue_type hash, rrset_id_type id);
-
-/**
- * Update an rrset in the rrset cache. Stores the information for later use.
- * Will lookup if the rrset is in the cache and perform an update if necessary.
- * If the item was present, and superior, references are returned to that.
- * The passed item is then deallocated with rrset_parsedelete.
- *
- * A superior rrset is:
- * o rrset with better trust value.
- * o same trust value, different rdata, newly passed rrset is inserted.
- * If rdata is the same, TTL in the cache is updated.
- *
- * @param r: the rrset cache.
- * @param ref: reference (ptr and id) to the rrset. Pass reference setup for
- * the new rrset. The reference may be changed if the cached rrset is
- * superior.
- * Before calling the rrset is presumed newly allocated and changeable.
- * Afer calling you do not hold a lock, and the rrset is inserted in
- * the hashtable so you need a lock to change it.
- * @param alloc: how to allocate (and deallocate) the special rrset key.
- * @param timenow: current time (to see if ttl in cache is expired).
- * @return: true if the passed reference is updated, false if it is unchanged.
- * 0: reference unchanged, inserted in cache.
- * 1: reference updated, item is inserted in cache.
- * 2: reference updated, item in cache is considered superior.
- * also the rdata is equal (but other parameters in cache are superior).
- */
-int rrset_cache_update(struct rrset_cache* r, struct rrset_ref* ref,
- struct alloc_cache* alloc, time_t timenow);
-
-/**
- * Lookup rrset. You obtain read/write lock. You must unlock before lookup
- * anything of else.
- * @param r: the rrset cache.
- * @param qname: name of rrset to lookup.
- * @param qnamelen: length of name of rrset to lookup.
- * @param qtype: type of rrset to lookup (host order).
- * @param qclass: class of rrset to lookup (host order).
- * @param flags: rrset flags, or 0.
- * @param timenow: used to compare with TTL.
- * @param wr: set true to get writelock.
- * @return packed rrset key pointer. Remember to unlock the key.entry.lock.
- * or NULL if could not be found or it was timed out.
- */
-struct ub_packed_rrset_key* rrset_cache_lookup(struct rrset_cache* r,
- uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
- uint32_t flags, time_t timenow, int wr);
-
-/**
- * Obtain readlock on a (sorted) list of rrset references.
- * Checks TTLs and IDs of the rrsets and rollbacks locking if not Ok.
- * @param ref: array of rrset references (key pointer and ID value).
- * duplicate references are allowed and handled.
- * @param count: size of array.
- * @param timenow: used to compare with TTL.
- * @return true on success, false on a failure, which can be that some
- * RRsets have timed out, or that they do not exist any more, the
- * RRsets have been purged from the cache.
- * If true, you hold readlocks on all the ref items.
- */
-int rrset_array_lock(struct rrset_ref* ref, size_t count, time_t timenow);
-
-/**
- * Unlock array (sorted) of rrset references.
- * @param ref: array of rrset references (key pointer and ID value).
- * duplicate references are allowed and handled.
- * @param count: size of array.
- */
-void rrset_array_unlock(struct rrset_ref* ref, size_t count);
-
-/**
- * Unlock array (sorted) of rrset references and at the same time
- * touch LRU on the rrsets. It needs the scratch region for temporary
- * storage as it uses the initial locks to obtain hash values.
- * @param r: the rrset cache. In this cache LRU is updated.
- * @param scratch: region for temporary storage of hash values.
- * if memory allocation fails, the lru touch fails silently,
- * but locks are released. memory errors are logged.
- * @param ref: array of rrset references (key pointer and ID value).
- * duplicate references are allowed and handled.
- * @param count: size of array.
- */
-void rrset_array_unlock_touch(struct rrset_cache* r, struct regional* scratch,
- struct rrset_ref* ref, size_t count);
-
-/**
- * Update security status of an rrset. Looks up the rrset.
- * If found, checks if rdata is equal.
- * If so, it will update the security, trust and rrset-ttl values.
- * The values are only updated if security is increased (towards secure).
- * @param r: the rrset cache.
- * @param rrset: which rrset to attempt to update. This rrset is left
- * untouched. The rrset in the cache is updated in-place.
- * @param now: current time.
- */
-void rrset_update_sec_status(struct rrset_cache* r,
- struct ub_packed_rrset_key* rrset, time_t now);
-
-/**
- * Looks up security status of an rrset. Looks up the rrset.
- * If found, checks if rdata is equal, and entry did not expire.
- * If so, it will update the security, trust and rrset-ttl values.
- * @param r: the rrset cache.
- * @param rrset: This rrset may change security status due to the cache.
- * But its status will only improve, towards secure.
- * @param now: current time.
- */
-void rrset_check_sec_status(struct rrset_cache* r,
- struct ub_packed_rrset_key* rrset, time_t now);
-
-/**
- * Remove an rrset from the cache, by name and type and flags
- * @param r: rrset cache
- * @param nm: name of rrset
- * @param nmlen: length of name
- * @param type: type of rrset
- * @param dclass: class of rrset, host order
- * @param flags: flags of rrset, host order
- */
-void rrset_cache_remove(struct rrset_cache* r, uint8_t* nm, size_t nmlen,
- uint16_t type, uint16_t dclass, uint32_t flags);
-
-/** mark rrset to be deleted, set id=0 */
-void rrset_markdel(void* key);
-
-#endif /* SERVICES_CACHE_RRSET_H */