update libunbound

This commit is contained in:
Riccardo Spagni
2015-05-31 16:36:48 +02:00
parent ce974949e2
commit 6a1190792b
59 changed files with 4449 additions and 2465 deletions

View File

@@ -65,6 +65,7 @@
#include "validator/val_utils.h"
#include "validator/val_sigcrypt.h"
#include "sldns/sbuffer.h"
#include "sldns/str2wire.h"
/** time when nameserver glue is said to be 'recent' */
#define SUSPICION_RECENT_EXPIRY 86400
@@ -105,6 +106,40 @@ read_fetch_policy(struct iter_env* ie, const char* str)
return 1;
}
/** apply config caps whitelist items to name tree */
static int
caps_white_apply_cfg(rbtree_t* ntree, struct config_file* cfg)
{
struct config_strlist* p;
for(p=cfg->caps_whitelist; p; p=p->next) {
struct name_tree_node* n;
size_t len;
uint8_t* nm = sldns_str2wire_dname(p->str, &len);
if(!nm) {
log_err("could not parse %s", p->str);
return 0;
}
n = (struct name_tree_node*)calloc(1, sizeof(*n));
if(!n) {
log_err("out of memory");
free(nm);
return 0;
}
n->node.key = n;
n->name = nm;
n->len = len;
n->labs = dname_count_labels(nm);
n->dclass = LDNS_RR_CLASS_IN;
if(!name_tree_insert(ntree, n, nm, len, n->labs, n->dclass)) {
/* duplicate element ignored, idempotent */
free(n->name);
free(n);
}
}
name_tree_init_parents(ntree);
return 1;
}
int
iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
{
@@ -128,6 +163,16 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
log_err("Could not set private addresses");
return 0;
}
if(cfg->caps_whitelist) {
if(!iter_env->caps_white)
iter_env->caps_white = rbtree_create(name_tree_compare);
if(!iter_env->caps_white || !caps_white_apply_cfg(
iter_env->caps_white, cfg)) {
log_err("Could not set capsforid whitelist");
return 0;
}
}
iter_env->supports_ipv6 = cfg->do_ip6;
iter_env->supports_ipv4 = cfg->do_ip4;
return 1;

View File

@@ -61,6 +61,7 @@
#include "util/data/msgencode.h"
#include "util/fptr_wlist.h"
#include "util/config_file.h"
#include "util/random.h"
#include "sldns/rrdef.h"
#include "sldns/wire2str.h"
#include "sldns/parseutil.h"
@@ -83,6 +84,16 @@ iter_init(struct module_env* env, int id)
return 1;
}
/** delete caps_whitelist element */
static void
caps_free(struct rbnode_t* n, void* ATTR_UNUSED(d))
{
if(n) {
free(((struct name_tree_node*)n)->name);
free(n);
}
}
void
iter_deinit(struct module_env* env, int id)
{
@@ -93,6 +104,10 @@ iter_deinit(struct module_env* env, int id)
free(iter_env->target_fetch_policy);
priv_delete(iter_env->priv);
donotq_delete(iter_env->donotq);
if(iter_env->caps_white) {
traverse_postorder(iter_env->caps_white, caps_free, NULL);
free(iter_env->caps_white);
}
free(iter_env);
env->modinfo[id] = NULL;
}
@@ -120,6 +135,7 @@ iter_new(struct module_qstate* qstate, int id)
iq->query_restart_count = 0;
iq->referral_count = 0;
iq->sent_count = 0;
iq->ratelimit_ok = 0;
iq->target_count = NULL;
iq->wait_priming_stub = 0;
iq->refetch_glue = 0;
@@ -457,6 +473,16 @@ handle_cname_response(struct module_qstate* qstate, struct iter_qstate* iq,
return 1;
}
/** see if target name is caps-for-id whitelisted */
static int
is_caps_whitelisted(struct iter_env* ie, struct iter_qstate* iq)
{
if(!ie->caps_white) return 0; /* no whitelist, or no capsforid */
return name_tree_lookup(ie->caps_white, iq->qchase.qname,
iq->qchase.qname_len, dname_count_labels(iq->qchase.qname),
iq->qchase.qclass) != NULL;
}
/** create target count structure for this query */
static void
target_count_create(struct iter_qstate* iq)
@@ -1125,6 +1151,32 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
* results of priming. */
return 0;
}
if(!iq->ratelimit_ok && qstate->prefetch_leeway)
iq->ratelimit_ok = 1; /* allow prefetches, this keeps
otherwise valid data in the cache */
if(!iq->ratelimit_ok && infra_ratelimit_exceeded(
qstate->env->infra_cache, iq->dp->name,
iq->dp->namelen, *qstate->env->now)) {
/* and increment the rate, so that the rate for time
* now will also exceed the rate, keeping cache fresh */
(void)infra_ratelimit_inc(qstate->env->infra_cache,
iq->dp->name, iq->dp->namelen,
*qstate->env->now);
/* see if we are passed through with slip factor */
if(qstate->env->cfg->ratelimit_factor != 0 &&
ub_random_max(qstate->env->rnd,
qstate->env->cfg->ratelimit_factor) == 1) {
iq->ratelimit_ok = 1;
log_nametypeclass(VERB_ALGO, "ratelimit allowed through for "
"delegation point", iq->dp->name,
LDNS_RR_TYPE_NS, LDNS_RR_CLASS_IN);
} else {
log_nametypeclass(VERB_ALGO, "ratelimit exceeded with "
"delegation point", iq->dp->name,
LDNS_RR_TYPE_NS, LDNS_RR_CLASS_IN);
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
}
}
/* see if this dp not useless.
* It is useless if:
@@ -1914,6 +1966,15 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
return 0;
}
/* if not forwarding, check ratelimits per delegationpoint name */
if(!(iq->chase_flags & BIT_RD) && !iq->ratelimit_ok) {
if(!infra_ratelimit_inc(qstate->env->infra_cache, iq->dp->name,
iq->dp->namelen, *qstate->env->now)) {
verbose(VERB_ALGO, "query exceeded ratelimits");
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
}
}
/* We have a valid target. */
if(verbosity >= VERB_QUERY) {
log_query_info(VERB_QUERY, "sending query:", &iq->qchase);
@@ -1928,11 +1989,15 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
iq->qchase.qname, iq->qchase.qname_len,
iq->qchase.qtype, iq->qchase.qclass,
iq->chase_flags | (iq->chase_to_rd?BIT_RD:0), EDNS_DO|BIT_CD,
iq->dnssec_expected, iq->caps_fallback, &target->addr,
target->addrlen, iq->dp->name, iq->dp->namelen, qstate);
iq->dnssec_expected, iq->caps_fallback || is_caps_whitelisted(
ie, iq), &target->addr, target->addrlen, iq->dp->name,
iq->dp->namelen, qstate);
if(!outq) {
log_addr(VERB_DETAIL, "error sending query to auth server",
&target->addr, target->addrlen);
if(!(iq->chase_flags & BIT_RD) && !iq->ratelimit_ok)
infra_ratelimit_dec(qstate->env->infra_cache, iq->dp->name,
iq->dp->namelen, *qstate->env->now);
return next_state(iq, QUERYTARGETS_STATE);
}
outbound_list_insert(&iq->outlist, outq);
@@ -2083,6 +2148,14 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
* delegation point, and back to the QUERYTARGETS_STATE. */
verbose(VERB_DETAIL, "query response was REFERRAL");
if(!(iq->chase_flags & BIT_RD) && !iq->ratelimit_ok) {
/* we have a referral, no ratelimit, we can send
* our queries to the given name */
infra_ratelimit_dec(qstate->env->infra_cache,
iq->dp->name, iq->dp->namelen,
*qstate->env->now);
}
/* if hardened, only store referral if we asked for it */
if(!qstate->env->cfg->harden_referral_path ||
( qstate->qinfo.qtype == LDNS_RR_TYPE_NS

View File

@@ -51,6 +51,7 @@ struct iter_forwards;
struct iter_donotq;
struct iter_prep_list;
struct iter_priv;
struct rbtree_t;
/** max number of targets spawned for a query and its subqueries */
#define MAX_TARGET_COUNT 32
@@ -96,6 +97,9 @@ struct iter_env {
/** private address space and private domains */
struct iter_priv* priv;
/** whitelist for capsforid names */
struct rbtree_t* caps_white;
/** The maximum dependency depth that this resolver will pursue. */
int max_dependency_depth;
@@ -259,6 +263,9 @@ struct iter_qstate {
* subqueries, the malloced-array is shared, [0] refcount. */
int* target_count;
/** if true, already tested for ratelimiting and passed the test */
int ratelimit_ok;
/**
* The query must store NS records from referrals as parentside RRs
* Enabled once it hits resolution problems, to throttle retries.