diff options
author | Dag-Erling Smørgrav <des@FreeBSD.org> | 2018-05-12 11:56:52 +0000 |
---|---|---|
committer | Dag-Erling Smørgrav <des@FreeBSD.org> | 2018-05-12 11:56:52 +0000 |
commit | 4289761a7b61df4b64c11ada446a187df61e6a1e (patch) | |
tree | ed7ceb7a1652fb9f865fafd21fbe18d1a3b5f79d /iterator | |
parent | 197f1a0fe3e81cde0cd25a3a1f37ebedf9a99488 (diff) |
Diffstat (limited to 'iterator')
-rw-r--r-- | iterator/iter_delegpt.c | 34 | ||||
-rw-r--r-- | iterator/iter_delegpt.h | 8 | ||||
-rw-r--r-- | iterator/iter_fwd.c | 6 | ||||
-rw-r--r-- | iterator/iter_hints.c | 6 | ||||
-rw-r--r-- | iterator/iter_utils.c | 25 | ||||
-rw-r--r-- | iterator/iter_utils.h | 14 | ||||
-rw-r--r-- | iterator/iterator.c | 44 |
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; |