summaryrefslogtreecommitdiff
path: root/iterator
diff options
context:
space:
mode:
authorDag-Erling Smørgrav <des@FreeBSD.org>2018-05-12 11:56:52 +0000
committerDag-Erling Smørgrav <des@FreeBSD.org>2018-05-12 11:56:52 +0000
commit4289761a7b61df4b64c11ada446a187df61e6a1e (patch)
treeed7ceb7a1652fb9f865fafd21fbe18d1a3b5f79d /iterator
parent197f1a0fe3e81cde0cd25a3a1f37ebedf9a99488 (diff)
Diffstat (limited to 'iterator')
-rw-r--r--iterator/iter_delegpt.c34
-rw-r--r--iterator/iter_delegpt.h8
-rw-r--r--iterator/iter_fwd.c6
-rw-r--r--iterator/iter_hints.c6
-rw-r--r--iterator/iter_utils.c25
-rw-r--r--iterator/iter_utils.h14
-rw-r--r--iterator/iterator.c44
7 files changed, 100 insertions, 37 deletions
diff --git a/iterator/iter_delegpt.c b/iterator/iter_delegpt.c
index ecf88b293da1..f88b3e115db3 100644
--- a/iterator/iter_delegpt.c
+++ b/iterator/iter_delegpt.c
@@ -84,7 +84,7 @@ struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* region)
}
for(a = dp->target_list; a; a = a->next_target) {
if(!delegpt_add_addr(copy, region, &a->addr, a->addrlen,
- a->bogus, a->lame))
+ a->bogus, a->lame, a->tls_auth_name))
return NULL;
}
return copy;
@@ -176,13 +176,13 @@ delegpt_add_target(struct delegpt* dp, struct regional* region,
if(ns->got4 && ns->got6)
ns->resolved = 1;
}
- return delegpt_add_addr(dp, region, addr, addrlen, bogus, lame);
+ return delegpt_add_addr(dp, region, addr, addrlen, bogus, lame, NULL);
}
int
delegpt_add_addr(struct delegpt* dp, struct regional* region,
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t bogus,
- uint8_t lame)
+ uint8_t lame, char* tls_auth_name)
{
struct delegpt_addr* a;
log_assert(!dp->dp_type_mlc);
@@ -210,6 +210,13 @@ delegpt_add_addr(struct delegpt* dp, struct regional* region,
a->bogus = bogus;
a->lame = lame;
a->dnsseclame = 0;
+ if(tls_auth_name) {
+ a->tls_auth_name = regional_strdup(region, tls_auth_name);
+ if(!a->tls_auth_name)
+ return 0;
+ } else {
+ a->tls_auth_name = NULL;
+ }
return 1;
}
@@ -276,11 +283,16 @@ void delegpt_log(enum verbosity_value v, struct delegpt* dp)
(ns->done_pside6?" PSIDE_AAAA":""));
}
for(a = dp->target_list; a; a = a->next_target) {
+ char s[128];
const char* str = " ";
if(a->bogus && a->lame) str = " BOGUS ADDR_LAME ";
else if(a->bogus) str = " BOGUS ";
else if(a->lame) str = " ADDR_LAME ";
- log_addr(VERB_ALGO, str, &a->addr, a->addrlen);
+ if(a->tls_auth_name)
+ snprintf(s, sizeof(s), "%s[%s]", str,
+ a->tls_auth_name);
+ else snprintf(s, sizeof(s), "%s", str);
+ log_addr(VERB_ALGO, s, &a->addr, a->addrlen);
}
}
}
@@ -539,6 +551,7 @@ void delegpt_free_mlc(struct delegpt* dp)
a = dp->target_list;
while(a) {
na = a->next_target;
+ free(a->tls_auth_name);
free(a);
a = na;
}
@@ -585,7 +598,7 @@ int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame)
}
int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr,
- socklen_t addrlen, uint8_t bogus, uint8_t lame)
+ socklen_t addrlen, uint8_t bogus, uint8_t lame, char* tls_auth_name)
{
struct delegpt_addr* a;
log_assert(dp->dp_type_mlc);
@@ -612,6 +625,15 @@ int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr,
a->bogus = bogus;
a->lame = lame;
a->dnsseclame = 0;
+ if(tls_auth_name) {
+ a->tls_auth_name = strdup(tls_auth_name);
+ if(!a->tls_auth_name) {
+ free(a);
+ return 0;
+ }
+ } else {
+ a->tls_auth_name = NULL;
+ }
return 1;
}
@@ -632,7 +654,7 @@ int delegpt_add_target_mlc(struct delegpt* dp, uint8_t* name, size_t namelen,
if(ns->got4 && ns->got6)
ns->resolved = 1;
}
- return delegpt_add_addr_mlc(dp, addr, addrlen, bogus, lame);
+ return delegpt_add_addr_mlc(dp, addr, addrlen, bogus, lame, NULL);
}
size_t delegpt_get_mem(struct delegpt* dp)
diff --git a/iterator/iter_delegpt.h b/iterator/iter_delegpt.h
index 24f0574901d9..354bd6177380 100644
--- a/iterator/iter_delegpt.h
+++ b/iterator/iter_delegpt.h
@@ -151,6 +151,8 @@ struct delegpt_addr {
* option is useful to mark the address dnsseclame.
* This value is not copied in addr-copy and dp-copy. */
uint8_t dnsseclame;
+ /** the TLS authentication name, (if not NULL) to use. */
+ char* tls_auth_name;
};
/**
@@ -259,11 +261,12 @@ int delegpt_add_rrset(struct delegpt* dp, struct regional* regional,
* @param addrlen: the length of addr.
* @param bogus: if address is bogus.
* @param lame: if address is lame.
+ * @param tls_auth_name: TLS authentication name (or NULL).
* @return false on error.
*/
int delegpt_add_addr(struct delegpt* dp, struct regional* regional,
struct sockaddr_storage* addr, socklen_t addrlen,
- uint8_t bogus, uint8_t lame);
+ uint8_t bogus, uint8_t lame, char* tls_auth_name);
/**
* Find NS record in name list of delegation point.
@@ -394,10 +397,11 @@ int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame);
* @param addrlen: the length of addr.
* @param bogus: if address is bogus.
* @param lame: if address is lame.
+ * @param tls_auth_name: TLS authentication name (or NULL).
* @return false on error.
*/
int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr,
- socklen_t addrlen, uint8_t bogus, uint8_t lame);
+ socklen_t addrlen, uint8_t bogus, uint8_t lame, char* tls_auth_name);
/**
* Add target address to the delegation point.
diff --git a/iterator/iter_fwd.c b/iterator/iter_fwd.c
index 0ba6c6ddfa9e..a44f54386dc4 100644
--- a/iterator/iter_fwd.c
+++ b/iterator/iter_fwd.c
@@ -231,14 +231,16 @@ read_fwds_addr(struct config_stub* s, struct delegpt* dp)
struct config_strlist* p;
struct sockaddr_storage addr;
socklen_t addrlen;
+ char* tls_auth_name;
for(p = s->addrs; p; p = p->next) {
log_assert(p->str);
- if(!extstrtoaddr(p->str, &addr, &addrlen)) {
+ if(!authextstrtoaddr(p->str, &addr, &addrlen, &tls_auth_name)) {
log_err("cannot parse forward %s ip address: '%s'",
s->name, p->str);
return 0;
}
- if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0)) {
+ if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0,
+ tls_auth_name)) {
log_err("out of memory");
return 0;
}
diff --git a/iterator/iter_hints.c b/iterator/iter_hints.c
index 1d4c228fabc2..e8d09338e974 100644
--- a/iterator/iter_hints.c
+++ b/iterator/iter_hints.c
@@ -244,14 +244,16 @@ read_stubs_addr(struct config_stub* s, struct delegpt* dp)
struct config_strlist* p;
struct sockaddr_storage addr;
socklen_t addrlen;
+ char* auth_name;
for(p = s->addrs; p; p = p->next) {
log_assert(p->str);
- if(!extstrtoaddr(p->str, &addr, &addrlen)) {
+ if(!authextstrtoaddr(p->str, &addr, &addrlen, &auth_name)) {
log_err("cannot parse stub %s ip address: '%s'",
s->name, p->str);
return 0;
}
- if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0)) {
+ if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0,
+ auth_name)) {
log_err("out of memory");
return 0;
}
diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c
index 70cab40faa80..752474cd8e6f 100644
--- a/iterator/iter_utils.c
+++ b/iterator/iter_utils.c
@@ -312,9 +312,9 @@ static int
iter_filter_order(struct iter_env* iter_env, struct module_env* env,
uint8_t* name, size_t namelen, uint16_t qtype, time_t now,
struct delegpt* dp, int* selected_rtt, int open_target,
- struct sock_list* blacklist)
+ struct sock_list* blacklist, time_t prefetch)
{
- int got_num = 0, low_rtt = 0, swap_to_front;
+ int got_num = 0, low_rtt = 0, swap_to_front, rtt_band = RTT_BAND;
struct delegpt_addr* a, *n, *prev=NULL;
/* fillup sel_rtt and find best rtt in the bunch */
@@ -329,6 +329,16 @@ iter_filter_order(struct iter_env* iter_env, struct module_env* env,
return 0 to force the caller to fetch more */
}
+ if(env->cfg->low_rtt_pct != 0 && prefetch == 0 &&
+ low_rtt < env->cfg->low_rtt &&
+ ub_random_max(env->rnd, 1000) < env->cfg->low_rtt_pct) {
+ /* the query is not prefetch, but for a downstream client,
+ * there is a low_rtt (fast) server. We choose that x% of the
+ * time */
+ /* pick rtt numbers from 0..LOWBAND_RTT */
+ rtt_band = env->cfg->low_rtt - low_rtt;
+ }
+
got_num = 0;
a = dp->result_list;
while(a) {
@@ -340,10 +350,10 @@ iter_filter_order(struct iter_env* iter_env, struct module_env* env,
}
/* classify the server address and determine what to do */
swap_to_front = 0;
- if(a->sel_rtt >= low_rtt && a->sel_rtt - low_rtt <= RTT_BAND) {
+ if(a->sel_rtt >= low_rtt && a->sel_rtt - low_rtt <= rtt_band) {
got_num++;
swap_to_front = 1;
- } else if(a->sel_rtt<low_rtt && low_rtt-a->sel_rtt<=RTT_BAND) {
+ } else if(a->sel_rtt<low_rtt && low_rtt-a->sel_rtt<=rtt_band) {
got_num++;
swap_to_front = 1;
}
@@ -400,13 +410,14 @@ struct delegpt_addr*
iter_server_selection(struct iter_env* iter_env,
struct module_env* env, struct delegpt* dp,
uint8_t* name, size_t namelen, uint16_t qtype, int* dnssec_lame,
- int* chase_to_rd, int open_target, struct sock_list* blacklist)
+ int* chase_to_rd, int open_target, struct sock_list* blacklist,
+ time_t prefetch)
{
int sel;
int selrtt;
struct delegpt_addr* a, *prev;
int num = iter_filter_order(iter_env, env, name, namelen, qtype,
- *env->now, dp, &selrtt, open_target, blacklist);
+ *env->now, dp, &selrtt, open_target, blacklist, prefetch);
if(num == 0)
return NULL;
@@ -625,7 +636,7 @@ iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
}
int
-iter_indicates_dnssec_fwd(struct module_env* env, struct query_info *qinfo)
+iter_qname_indicates_dnssec(struct module_env* env, struct query_info *qinfo)
{
struct trust_anchor* a;
if(!env || !env->anchors || !qinfo || !qinfo->qname)
diff --git a/iterator/iter_utils.h b/iterator/iter_utils.h
index 602fa6db3d0d..e971d930b164 100644
--- a/iterator/iter_utils.h
+++ b/iterator/iter_utils.h
@@ -87,13 +87,18 @@ int iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg);
* @param open_target: number of currently outstanding target queries.
* If we wait for these, perhaps more server addresses become available.
* @param blacklist: the IP blacklist to use.
+ * @param prefetch: if not 0, prefetch is in use for this query.
+ * This means the query can have different timing, because prefetch is
+ * not waited upon by the downstream client, and thus a good time to
+ * perform exploration of other targets.
* @return best target or NULL if no target.
* if not null, that target is removed from the result list in the dp.
*/
struct delegpt_addr* iter_server_selection(struct iter_env* iter_env,
struct module_env* env, struct delegpt* dp, uint8_t* name,
size_t namelen, uint16_t qtype, int* dnssec_lame,
- int* chase_to_rd, int open_target, struct sock_list* blacklist);
+ int* chase_to_rd, int open_target, struct sock_list* blacklist,
+ time_t prefetch);
/**
* Allocate dns_msg from parsed msg, in regional.
@@ -174,15 +179,14 @@ int iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
struct delegpt* dp);
/**
- * See if qname has DNSSEC needs in the forwarding case. This is true if
- * there is a trust anchor above it. Whether there is an insecure delegation
- * to the data is unknown, but CD-retry is needed.
+ * See if qname has DNSSEC needs. This is true if there is a trust anchor above
+ * it. Whether there is an insecure delegation to the data is unknown.
* @param env: environment with anchors.
* @param qinfo: query name and class.
* @return true if trust anchor above qname, false if no anchor or insecure
* point above qname.
*/
-int iter_indicates_dnssec_fwd(struct module_env* env,
+int iter_qname_indicates_dnssec(struct module_env* env,
struct query_info *qinfo);
/**
diff --git a/iterator/iterator.c b/iterator/iterator.c
index 7f3c65737d59..188a623a2bc7 100644
--- a/iterator/iterator.c
+++ b/iterator/iterator.c
@@ -1206,7 +1206,8 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
iq->qchase.qname_len, iq->qchase.qtype,
iq->qchase.qclass, qstate->query_flags,
qstate->region, qstate->env->scratch, 0);
- if(!msg && qstate->env->neg_cache) {
+ if(!msg && qstate->env->neg_cache &&
+ iter_qname_indicates_dnssec(qstate->env, &iq->qchase)) {
/* lookup in negative cache; may result in
* NOERROR/NODATA or NXDOMAIN answers that need validation */
msg = val_neg_getmsg(qstate->env->neg_cache, &iq->qchase,
@@ -1298,7 +1299,8 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
delnamelen = iq->qchase.qname_len;
}
if(iq->qchase.qtype == LDNS_RR_TYPE_DS || iq->refetch_glue ||
- (iq->qchase.qtype == LDNS_RR_TYPE_NS && qstate->prefetch_leeway)) {
+ (iq->qchase.qtype == LDNS_RR_TYPE_NS && qstate->prefetch_leeway
+ && can_have_last_resort(qstate->env, delname, delnamelen, iq->qchase.qclass))) {
/* remove first label from delname, root goes to hints,
* but only to fetch glue, not for qtype=DS. */
/* also when prefetching an NS record, fetch it again from
@@ -1414,6 +1416,12 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
*/
if(iter_dp_is_useless(&qstate->qinfo, qstate->query_flags,
iq->dp)) {
+ if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen, iq->qchase.qclass)) {
+ verbose(VERB_ALGO, "useless dp "
+ "but cannot go up, servfail");
+ return error_response(qstate, id,
+ LDNS_RCODE_SERVFAIL);
+ }
if(dname_is_root(iq->dp->name)) {
/* use safety belt */
verbose(VERB_QUERY, "Cache has root NS but "
@@ -1791,7 +1799,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
for(a = p->target_list; a; a=a->next_target) {
(void)delegpt_add_addr(iq->dp, qstate->region,
&a->addr, a->addrlen, a->bogus,
- a->lame);
+ a->lame, a->tls_auth_name);
}
}
iq->dp->has_parent_side_NS = 1;
@@ -2160,11 +2168,18 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
log_dns_msg("msg from auth zone",
&iq->response->qinfo, iq->response->rep);
}
- iq->num_current_queries++;
- iq->chase_to_rd = 0;
- iq->dnssec_lame_query = 0;
- iq->auth_zone_response = 1;
- return next_state(iq, QUERY_RESP_STATE);
+ if((iq->chase_flags&BIT_RD) && !(iq->response->rep->flags&BIT_AA)) {
+ verbose(VERB_ALGO, "forwarder, ignoring referral from auth zone");
+ } else {
+ lock_rw_wrlock(&qstate->env->auth_zones->lock);
+ qstate->env->auth_zones->num_query_up++;
+ lock_rw_unlock(&qstate->env->auth_zones->lock);
+ iq->num_current_queries++;
+ iq->chase_to_rd = 0;
+ iq->dnssec_lame_query = 0;
+ iq->auth_zone_response = 1;
+ return next_state(iq, QUERY_RESP_STATE);
+ }
}
iq->auth_zone_response = 0;
if(auth_fallback == 0) {
@@ -2253,7 +2268,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
target = iter_server_selection(ie, qstate->env, iq->dp,
iq->dp->name, iq->dp->namelen, iq->qchase.qtype,
&iq->dnssec_lame_query, &iq->chase_to_rd,
- iq->num_target_queries, qstate->blacklist);
+ iq->num_target_queries, qstate->blacklist,
+ qstate->prefetch_leeway);
/* If no usable target was selected... */
if(!target) {
@@ -2366,12 +2382,13 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
* (blacklist nonempty) and no trust-anchors are configured
* above the qname or on the first attempt when dnssec is on */
EDNS_DO| ((iq->chase_to_rd||(iq->chase_flags&BIT_RD)!=0)&&
- !qstate->blacklist&&(!iter_indicates_dnssec_fwd(qstate->env,
+ !qstate->blacklist&&(!iter_qname_indicates_dnssec(qstate->env,
&iq->qinfo_out)||target->attempts==1)?0:BIT_CD),
iq->dnssec_expected, iq->caps_fallback || is_caps_whitelisted(
ie, iq), &target->addr, target->addrlen,
iq->dp->name, iq->dp->namelen,
- (iq->dp->ssl_upstream || qstate->env->cfg->ssl_upstream), qstate);
+ (iq->dp->ssl_upstream || qstate->env->cfg->ssl_upstream),
+ target->tls_auth_name, qstate);
if(!outq) {
log_addr(VERB_DETAIL, "error sending query to auth server",
&target->addr, target->addrlen);
@@ -2440,9 +2457,10 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
}
type = response_type_from_server(
(int)((iq->chase_flags&BIT_RD) || iq->chase_to_rd),
- iq->response, &iq->qchase, iq->dp);
+ iq->response, &iq->qinfo_out, iq->dp);
iq->chase_to_rd = 0;
- if(type == RESPONSE_TYPE_REFERRAL && (iq->chase_flags&BIT_RD)) {
+ if(type == RESPONSE_TYPE_REFERRAL && (iq->chase_flags&BIT_RD) &&
+ !iq->auth_zone_response) {
/* When forwarding (RD bit is set), we handle referrals
* differently. No queries should be sent elsewhere */
type = RESPONSE_TYPE_ANSWER;