diff options
Diffstat (limited to 'iterator')
-rw-r--r-- | iterator/iter_delegpt.c | 29 | ||||
-rw-r--r-- | iterator/iter_delegpt.h | 30 | ||||
-rw-r--r-- | iterator/iter_fwd.c | 14 | ||||
-rw-r--r-- | iterator/iter_fwd.h | 10 | ||||
-rw-r--r-- | iterator/iter_priv.c | 48 | ||||
-rw-r--r-- | iterator/iter_priv.h | 2 | ||||
-rw-r--r-- | iterator/iter_scrub.c | 16 | ||||
-rw-r--r-- | iterator/iter_utils.c | 18 | ||||
-rw-r--r-- | iterator/iter_utils.h | 2 | ||||
-rw-r--r-- | iterator/iterator.c | 66 |
10 files changed, 176 insertions, 59 deletions
diff --git a/iterator/iter_delegpt.c b/iterator/iter_delegpt.c index d2f5d73335dc..c204ddfec745 100644 --- a/iterator/iter_delegpt.c +++ b/iterator/iter_delegpt.c @@ -71,7 +71,7 @@ struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* region) copy->bogus = dp->bogus; copy->has_parent_side_NS = dp->has_parent_side_NS; for(ns = dp->nslist; ns; ns = ns->next) { - if(!delegpt_add_ns(copy, region, ns->name, (int)ns->lame)) + if(!delegpt_add_ns(copy, region, ns->name, ns->lame)) return NULL; copy->nslist->resolved = ns->resolved; copy->nslist->got4 = ns->got4; @@ -98,7 +98,7 @@ delegpt_set_name(struct delegpt* dp, struct regional* region, uint8_t* name) int delegpt_add_ns(struct delegpt* dp, struct regional* region, uint8_t* name, - int lame) + uint8_t lame) { struct delegpt_ns* ns; size_t len; @@ -119,7 +119,7 @@ delegpt_add_ns(struct delegpt* dp, struct regional* region, uint8_t* name, ns->resolved = 0; ns->got4 = 0; ns->got6 = 0; - ns->lame = (uint8_t)lame; + ns->lame = lame; ns->done_pside4 = 0; ns->done_pside6 = 0; return ns->name != 0; @@ -156,7 +156,7 @@ delegpt_find_addr(struct delegpt* dp, struct sockaddr_storage* addr, int delegpt_add_target(struct delegpt* dp, struct regional* region, uint8_t* name, size_t namelen, struct sockaddr_storage* addr, - socklen_t addrlen, int bogus, int lame) + socklen_t addrlen, uint8_t bogus, uint8_t lame) { struct delegpt_ns* ns = delegpt_find_ns(dp, name, namelen); log_assert(!dp->dp_type_mlc); @@ -176,8 +176,8 @@ delegpt_add_target(struct delegpt* dp, struct regional* region, int delegpt_add_addr(struct delegpt* dp, struct regional* region, - struct sockaddr_storage* addr, socklen_t addrlen, int bogus, - int lame) + struct sockaddr_storage* addr, socklen_t addrlen, uint8_t bogus, + uint8_t lame) { struct delegpt_addr* a; log_assert(!dp->dp_type_mlc); @@ -204,6 +204,7 @@ delegpt_add_addr(struct delegpt* dp, struct regional* region, a->attempts = 0; a->bogus = bogus; a->lame = lame; + a->dnsseclame = 0; return 1; } @@ -376,7 +377,7 @@ delegpt_from_message(struct dns_msg* msg, struct regional* region) int delegpt_rrset_add_ns(struct delegpt* dp, struct regional* region, - struct ub_packed_rrset_key* ns_rrset, int lame) + struct ub_packed_rrset_key* ns_rrset, uint8_t lame) { struct packed_rrset_data* nsdata = (struct packed_rrset_data*) ns_rrset->entry.data; @@ -398,7 +399,7 @@ delegpt_rrset_add_ns(struct delegpt* dp, struct regional* region, int delegpt_add_rrset_A(struct delegpt* dp, struct regional* region, - struct ub_packed_rrset_key* ak, int lame) + struct ub_packed_rrset_key* ak, uint8_t lame) { struct packed_rrset_data* d=(struct packed_rrset_data*)ak->entry.data; size_t i; @@ -422,7 +423,7 @@ delegpt_add_rrset_A(struct delegpt* dp, struct regional* region, int delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* region, - struct ub_packed_rrset_key* ak, int lame) + struct ub_packed_rrset_key* ak, uint8_t lame) { struct packed_rrset_data* d=(struct packed_rrset_data*)ak->entry.data; size_t i; @@ -446,7 +447,7 @@ delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* region, int delegpt_add_rrset(struct delegpt* dp, struct regional* region, - struct ub_packed_rrset_key* rrset, int lame) + struct ub_packed_rrset_key* rrset, uint8_t lame) { if(!rrset) return 1; @@ -548,7 +549,7 @@ int delegpt_set_name_mlc(struct delegpt* dp, uint8_t* name) return (dp->name != NULL); } -int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, int lame) +int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame) { struct delegpt_ns* ns; size_t len; @@ -579,7 +580,7 @@ int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, int lame) } int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr, - socklen_t addrlen, int bogus, int lame) + socklen_t addrlen, uint8_t bogus, uint8_t lame) { struct delegpt_addr* a; log_assert(dp->dp_type_mlc); @@ -605,11 +606,13 @@ int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr, a->attempts = 0; a->bogus = bogus; a->lame = lame; + a->dnsseclame = 0; return 1; } int delegpt_add_target_mlc(struct delegpt* dp, uint8_t* name, size_t namelen, - struct sockaddr_storage* addr, socklen_t addrlen, int bogus, int lame) + struct sockaddr_storage* addr, socklen_t addrlen, uint8_t bogus, + uint8_t lame) { struct delegpt_ns* ns = delegpt_find_ns(dp, name, namelen); log_assert(dp->dp_type_mlc); diff --git a/iterator/iter_delegpt.h b/iterator/iter_delegpt.h index 7728031aa999..d7e0767d62eb 100644 --- a/iterator/iter_delegpt.h +++ b/iterator/iter_delegpt.h @@ -140,9 +140,13 @@ struct delegpt_addr { int sel_rtt; /** if true, the A or AAAA RR was bogus, so this address is bad. * Also check the dp->bogus to see if everything is bogus. */ - int bogus; + uint8_t bogus; /** if true, this address is dispreferred: it is a lame IP address */ - int lame; + uint8_t lame; + /** if the address is dnsseclame, but this cannot be cached, this + * option is useful to mark the address dnsseclame. + * This value is not copied in addr-copy and dp-copy. */ + uint8_t dnsseclame; }; /** @@ -179,7 +183,7 @@ int delegpt_set_name(struct delegpt* dp, struct regional* regional, * @return false on error. */ int delegpt_add_ns(struct delegpt* dp, struct regional* regional, - uint8_t* name, int lame); + uint8_t* name, uint8_t lame); /** * Add NS rrset; calls add_ns repeatedly. @@ -190,7 +194,7 @@ int delegpt_add_ns(struct delegpt* dp, struct regional* regional, * @return 0 on alloc error. */ int delegpt_rrset_add_ns(struct delegpt* dp, struct regional* regional, - struct ub_packed_rrset_key* ns_rrset, int lame); + struct ub_packed_rrset_key* ns_rrset, uint8_t lame); /** * Add target address to the delegation point. @@ -207,7 +211,7 @@ int delegpt_rrset_add_ns(struct delegpt* dp, struct regional* regional, */ int delegpt_add_target(struct delegpt* dp, struct regional* regional, uint8_t* name, size_t namelen, struct sockaddr_storage* addr, - socklen_t addrlen, int bogus, int lame); + socklen_t addrlen, uint8_t bogus, uint8_t lame); /** * Add A RRset to delegpt. @@ -218,7 +222,7 @@ int delegpt_add_target(struct delegpt* dp, struct regional* regional, * @return 0 on alloc error. */ int delegpt_add_rrset_A(struct delegpt* dp, struct regional* regional, - struct ub_packed_rrset_key* rrset, int lame); + struct ub_packed_rrset_key* rrset, uint8_t lame); /** * Add AAAA RRset to delegpt. @@ -229,7 +233,7 @@ int delegpt_add_rrset_A(struct delegpt* dp, struct regional* regional, * @return 0 on alloc error. */ int delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* regional, - struct ub_packed_rrset_key* rrset, int lame); + struct ub_packed_rrset_key* rrset, uint8_t lame); /** * Add any RRset to delegpt. @@ -241,7 +245,7 @@ int delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* regional, * @return 0 on alloc error. */ int delegpt_add_rrset(struct delegpt* dp, struct regional* regional, - struct ub_packed_rrset_key* rrset, int lame); + struct ub_packed_rrset_key* rrset, uint8_t lame); /** * Add address to the delegation point. No servername is associated or checked. @@ -254,7 +258,8 @@ int delegpt_add_rrset(struct delegpt* dp, struct regional* regional, * @return false on error. */ int delegpt_add_addr(struct delegpt* dp, struct regional* regional, - struct sockaddr_storage* addr, socklen_t addrlen, int bogus, int lame); + struct sockaddr_storage* addr, socklen_t addrlen, + uint8_t bogus, uint8_t lame); /** * Find NS record in name list of delegation point. @@ -376,7 +381,7 @@ int delegpt_set_name_mlc(struct delegpt* dp, uint8_t* name); * @param lame: the name is lame, disprefer. * @return false on error. */ -int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, int lame); +int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame); /** * add an address to a malloced delegation point. @@ -388,7 +393,7 @@ int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, int lame); * @return false on error. */ int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr, - socklen_t addrlen, int bogus, int lame); + socklen_t addrlen, uint8_t bogus, uint8_t lame); /** * Add target address to the delegation point. @@ -403,7 +408,8 @@ int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr, * @return false on error. */ int delegpt_add_target_mlc(struct delegpt* dp, uint8_t* name, size_t namelen, - struct sockaddr_storage* addr, socklen_t addrlen, int bogus, int lame); + struct sockaddr_storage* addr, socklen_t addrlen, uint8_t bogus, + uint8_t lame); /** get memory in use by dp */ size_t delegpt_get_mem(struct delegpt* dp); diff --git a/iterator/iter_fwd.c b/iterator/iter_fwd.c index 0b3b6525c26b..b84e5eff60d0 100644 --- a/iterator/iter_fwd.c +++ b/iterator/iter_fwd.c @@ -325,6 +325,20 @@ forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg) } struct delegpt* +forwards_find(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass) +{ + rbnode_t* res = NULL; + struct iter_forward_zone key; + key.node.key = &key; + key.dclass = qclass; + key.name = qname; + key.namelabs = dname_count_size_labels(qname, &key.namelen); + res = rbtree_search(fwd->tree, &key); + if(res) return ((struct iter_forward_zone*)res)->dp; + return NULL; +} + +struct delegpt* forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass) { /* lookup the forward zone in the tree */ diff --git a/iterator/iter_fwd.h b/iterator/iter_fwd.h index dbb84f226126..62408ad52e2b 100644 --- a/iterator/iter_fwd.h +++ b/iterator/iter_fwd.h @@ -105,6 +105,16 @@ void forwards_delete(struct iter_forwards* fwd); int forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg); /** + * Find forward zone exactly by name + * @param fwd: forward storage. + * @param qname: The qname of the query. + * @param qclass: The qclass of the query. + * @return: A delegation point or null. + */ +struct delegpt* forwards_find(struct iter_forwards* fwd, uint8_t* qname, + uint16_t qclass); + +/** * Find forward zone information * For this qname/qclass find forward zone information, returns delegation * point with server names and addresses, or NULL if no forwarding is needed. diff --git a/iterator/iter_priv.c b/iterator/iter_priv.c index db7dbe5faa65..572f701f350d 100644 --- a/iterator/iter_priv.c +++ b/iterator/iter_priv.c @@ -208,6 +208,28 @@ size_t priv_get_mem(struct iter_priv* priv) return sizeof(*priv) + regional_get_mem(priv->region); } +/** remove RR from msgparse RRset, return true if rrset is entirely bad */ +static int +remove_rr(const char* str, ldns_buffer* pkt, struct rrset_parse* rrset, + struct rr_parse* prev, struct rr_parse** rr, struct sockaddr_storage* addr, socklen_t addrlen) +{ + if(verbosity >= VERB_QUERY && rrset->dname_len <= LDNS_MAX_DOMAINLEN && str) { + uint8_t buf[LDNS_MAX_DOMAINLEN+1]; + dname_pkt_copy(pkt, buf, rrset->dname); + log_name_addr(VERB_QUERY, str, buf, addr, addrlen); + } + if(prev) + prev->next = (*rr)->next; + else rrset->rr_first = (*rr)->next; + if(rrset->rr_last == *rr) + rrset->rr_last = prev; + rrset->rr_count --; + rrset->size -= (*rr)->size; + /* rr struct still exists, but is unlinked, so that in the for loop + * the rr->next works fine to continue. */ + return rrset->rr_count == 0; +} + int priv_rrset_bad(struct iter_priv* priv, ldns_buffer* pkt, struct rrset_parse* rrset) { @@ -221,7 +243,7 @@ int priv_rrset_bad(struct iter_priv* priv, ldns_buffer* pkt, } else { /* so its a public name, check the address */ socklen_t len; - struct rr_parse* rr; + struct rr_parse* rr, *prev = NULL; if(rrset->type == LDNS_RR_TYPE_A) { struct sockaddr_storage addr; struct sockaddr_in sa; @@ -232,13 +254,19 @@ int priv_rrset_bad(struct iter_priv* priv, ldns_buffer* pkt, sa.sin_port = (in_port_t)htons(UNBOUND_DNS_PORT); for(rr = rrset->rr_first; rr; rr = rr->next) { if(ldns_read_uint16(rr->ttl_data+4) - != INET_SIZE) + != INET_SIZE) { + prev = rr; continue; + } memmove(&sa.sin_addr, rr->ttl_data+4+2, INET_SIZE); memmove(&addr, &sa, len); - if(priv_lookup_addr(priv, &addr, len)) - return 1; + if(priv_lookup_addr(priv, &addr, len)) { + if(remove_rr("sanitize: removing public name with private address", pkt, rrset, prev, &rr, &addr, len)) + return 1; + continue; + } + prev = rr; } } else if(rrset->type == LDNS_RR_TYPE_AAAA) { struct sockaddr_storage addr; @@ -249,13 +277,19 @@ int priv_rrset_bad(struct iter_priv* priv, ldns_buffer* pkt, sa.sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT); for(rr = rrset->rr_first; rr; rr = rr->next) { if(ldns_read_uint16(rr->ttl_data+4) - != INET6_SIZE) + != INET6_SIZE) { + prev = rr; continue; + } memmove(&sa.sin6_addr, rr->ttl_data+4+2, INET6_SIZE); memmove(&addr, &sa, len); - if(priv_lookup_addr(priv, &addr, len)) - return 1; + if(priv_lookup_addr(priv, &addr, len)) { + if(remove_rr("sanitize: removing public name with private address", pkt, rrset, prev, &rr, &addr, len)) + return 1; + continue; + } + prev = rr; } } } diff --git a/iterator/iter_priv.h b/iterator/iter_priv.h index f6264f8d0c9b..e6e51c159b09 100644 --- a/iterator/iter_priv.h +++ b/iterator/iter_priv.h @@ -92,6 +92,8 @@ int priv_apply_cfg(struct iter_priv* priv, struct config_file* cfg); /** * See if rrset is bad. + * Will remove individual RRs that are bad (if possible) to + * sanitize the RRset without removing it completely. * @param priv: structure for private address storage. * @param pkt: packet to decompress rrset name in. * @param rrset: the rrset to examine, A or AAAA. diff --git a/iterator/iter_scrub.c b/iterator/iter_scrub.c index 6147c96a9e37..a2407c27c840 100644 --- a/iterator/iter_scrub.c +++ b/iterator/iter_scrub.c @@ -62,7 +62,7 @@ static void remove_rrset(const char* str, ldns_buffer* pkt, struct msg_parse* msg, struct rrset_parse* prev, struct rrset_parse** rrset) { - if(verbosity >= VERB_QUERY + if(verbosity >= VERB_QUERY && str && (*rrset)->dname_len <= LDNS_MAX_DOMAINLEN) { uint8_t buf[LDNS_MAX_DOMAINLEN+1]; dname_pkt_copy(pkt, buf, (*rrset)->dname); @@ -520,7 +520,7 @@ store_rrset(ldns_buffer* pkt, struct msg_parse* msg, struct module_env* env, struct ub_packed_rrset_key* k; struct packed_rrset_data* d; struct rrset_ref ref; - uint32_t now = *env->now; + time_t now = *env->now; k = alloc_special_obtain(env->alloc); if(!k) @@ -646,14 +646,16 @@ scrub_sanitize(ldns_buffer* pkt, struct msg_parse* msg, /* remove private addresses */ if( (rrset->type == LDNS_RR_TYPE_A || - rrset->type == LDNS_RR_TYPE_AAAA) && - priv_rrset_bad(ie->priv, pkt, rrset)) { + rrset->type == LDNS_RR_TYPE_AAAA)) { /* do not set servfail since this leads to too * many drops of other people using rfc1918 space */ - remove_rrset("sanitize: removing public name with " - "private address", pkt, msg, prev, &rrset); - continue; + /* also do not remove entire rrset, unless all records + * in it are bad */ + if(priv_rrset_bad(ie->priv, pkt, rrset)) { + remove_rrset(NULL, pkt, msg, prev, &rrset); + continue; + } } /* skip DNAME records -- they will always be followed by a diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c index a500c75e786a..28f7dc2415c1 100644 --- a/iterator/iter_utils.c +++ b/iterator/iter_utils.c @@ -177,7 +177,7 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg) */ static int iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env, - uint8_t* name, size_t namelen, uint16_t qtype, uint32_t now, + uint8_t* name, size_t namelen, uint16_t qtype, time_t now, struct delegpt_addr* a) { int rtt, lame, reclame, dnsseclame; @@ -217,14 +217,16 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env, /* select remainder from worst to best */ else if(reclame) return rtt+USEFUL_SERVER_TOP_TIMEOUT*3; /* nonpref */ - else if(dnsseclame ) + else if(dnsseclame || a->dnsseclame) return rtt+USEFUL_SERVER_TOP_TIMEOUT*2; /* nonpref */ else if(a->lame) return rtt+USEFUL_SERVER_TOP_TIMEOUT+1; /* nonpref */ else return rtt; } /* no server information present */ - if(a->lame) + if(a->dnsseclame) + return UNKNOWN_SERVER_NICENESS+USEFUL_SERVER_TOP_TIMEOUT*2; /* nonpref */ + else if(a->lame) return USEFUL_SERVER_TOP_TIMEOUT+1+UNKNOWN_SERVER_NICENESS; /* nonpref */ return UNKNOWN_SERVER_NICENESS; } @@ -232,7 +234,7 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env, /** lookup RTT information, and also store fastest rtt (if any) */ static int iter_fill_rtt(struct iter_env* iter_env, struct module_env* env, - uint8_t* name, size_t namelen, uint16_t qtype, uint32_t now, + uint8_t* name, size_t namelen, uint16_t qtype, time_t now, struct delegpt* dp, int* best_rtt, struct sock_list* blacklist) { int got_it = 0; @@ -261,7 +263,7 @@ iter_fill_rtt(struct iter_env* iter_env, struct module_env* env, * returns number of best targets (or 0, no suitable targets) */ static int iter_filter_order(struct iter_env* iter_env, struct module_env* env, - uint8_t* name, size_t namelen, uint16_t qtype, uint32_t now, + 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) { @@ -420,7 +422,7 @@ dns_copy_msg(struct dns_msg* from, struct regional* region) void iter_dns_store(struct module_env* env, struct query_info* msgqinf, - struct reply_info* msgrep, int is_referral, uint32_t leeway, int pside, + struct reply_info* msgrep, int is_referral, time_t leeway, int pside, struct regional* region) { if(!dns_cache_store(env, msgqinf, msgrep, is_referral, leeway, @@ -768,7 +770,7 @@ void iter_store_parentside_neg(struct module_env* env, /* TTL: NS from referral in iq->deleg_msg, * or first RR from iq->response, * or servfail5secs if !iq->response */ - uint32_t ttl = NORR_TTL; + time_t ttl = NORR_TTL; struct ub_packed_rrset_key* neg; struct packed_rrset_data* newd; if(rep) { @@ -798,7 +800,7 @@ void iter_store_parentside_neg(struct module_env* env, neg->entry.hash = rrset_key_hash(&neg->rk); newd = (struct packed_rrset_data*)regional_alloc_zero(env->scratch, sizeof(struct packed_rrset_data) + sizeof(size_t) + - sizeof(uint8_t*) + sizeof(uint32_t) + sizeof(uint16_t)); + sizeof(uint8_t*) + sizeof(time_t) + sizeof(uint16_t)); if(!newd) { log_err("out of memory in store_parentside_neg"); return; diff --git a/iterator/iter_utils.h b/iterator/iter_utils.h index 8f5a291af678..2070622d4758 100644 --- a/iterator/iter_utils.h +++ b/iterator/iter_utils.h @@ -131,7 +131,7 @@ struct dns_msg* dns_copy_msg(struct dns_msg* from, struct regional* regional); * but the query resolution can continue without cache storage. */ void iter_dns_store(struct module_env* env, struct query_info* qinf, - struct reply_info* rep, int is_referral, uint32_t leeway, int pside, + struct reply_info* rep, int is_referral, time_t leeway, int pside, struct regional* region); /** diff --git a/iterator/iterator.c b/iterator/iterator.c index e3f058fe5122..160489331703 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -1409,6 +1409,35 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq, return 1; } +/** see if last resort is possible - does config allow queries to parent */ +static int +can_have_last_resort(struct module_env* env, struct delegpt* dp, + struct iter_qstate* iq) +{ + struct delegpt* fwddp; + struct iter_hints_stub* stub; + /* do not process a last resort (the parent side) if a stub + * or forward is configured, because we do not want to go 'above' + * the configured servers */ + if(!dname_is_root(dp->name) && (stub = (struct iter_hints_stub*) + name_tree_find(&env->hints->tree, dp->name, dp->namelen, + dp->namelabs, iq->qchase.qclass)) && + /* has_parent side is turned off for stub_first, where we + * are allowed to go to the parent */ + stub->dp->has_parent_side_NS) { + verbose(VERB_QUERY, "configured stub servers failed -- returning SERVFAIL"); + return 0; + } + if((fwddp = forwards_find(env->fwds, dp->name, iq->qchase.qclass)) && + /* has_parent_side is turned off for forward_first, where + * we are allowed to go to the parent */ + fwddp->has_parent_side_NS) { + verbose(VERB_QUERY, "configured forward servers failed -- returning SERVFAIL"); + return 0; + } + return 1; +} + /** * Called by processQueryTargets when it would like extra targets to query * but it seems to be out of options. At last resort some less appealing @@ -1430,6 +1459,11 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq, verbose(VERB_ALGO, "No more query targets, attempting last resort"); log_assert(iq->dp); + if(!can_have_last_resort(qstate->env, iq->dp, iq)) { + /* fail -- no more targets, no more hope of targets, no hope + * of a response. */ + return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL); + } if(!iq->dp->has_parent_side_NS && dname_is_root(iq->dp->name)) { struct delegpt* p = hints_lookup_root(qstate->env->hints, iq->qchase.qclass); @@ -1439,7 +1473,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq, iq->chase_flags &= ~BIT_RD; /* go to authorities */ for(ns = p->nslist; ns; ns=ns->next) { (void)delegpt_add_ns(iq->dp, qstate->region, - ns->name, (int)ns->lame); + ns->name, ns->lame); } for(a = p->target_list; a; a=a->next_target) { (void)delegpt_add_addr(iq->dp, qstate->region, @@ -1880,12 +1914,23 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, && type != RESPONSE_TYPE_UNTYPED) { /* a possible answer, see if it is missing DNSSEC */ /* but not when forwarding, so we dont mark fwder lame */ - /* also make sure the answer is from the zone we expected, - * otherwise, (due to parent,child on same server), we - * might mark the server,zone lame inappropriately */ - if(!iter_msg_has_dnssec(iq->response) && - iter_msg_from_zone(iq->response, iq->dp, type, - iq->qchase.qclass)) { + if(!iter_msg_has_dnssec(iq->response)) { + /* Mark this address as dnsseclame in this dp, + * because that will make serverselection disprefer + * it, but also, once it is the only final option, + * use dnssec-lame-bypass if it needs to query there.*/ + if(qstate->reply) { + struct delegpt_addr* a = delegpt_find_addr( + iq->dp, &qstate->reply->addr, + qstate->reply->addrlen); + if(a) a->dnsseclame = 1; + } + /* test the answer is from the zone we expected, + * otherwise, (due to parent,child on same server), we + * might mark the server,zone lame inappropriately */ + if(!iter_msg_from_zone(iq->response, iq->dp, type, + iq->qchase.qclass)) + qstate->reply = NULL; type = RESPONSE_TYPE_LAME; dnsseclame = 1; } @@ -2117,8 +2162,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, *qstate->env->now, dnsseclame, 0, iq->qchase.qtype)) log_err("mark host lame: out of memory"); - } else log_err("%slame response from cache", - dnsseclame?"DNSSEC ":""); + } } else if(type == RESPONSE_TYPE_REC_LAME) { /* Cache the LAMEness. */ verbose(VERB_DETAIL, "query response REC_LAME: " @@ -2326,12 +2370,12 @@ processTargetResponse(struct module_qstate* qstate, int id, rrset->rk.dname_len)) { /* if dpns->lame then set newcname ns lame too */ if(!delegpt_add_ns(foriq->dp, forq->region, - rrset->rk.dname, (int)dpns->lame)) + rrset->rk.dname, dpns->lame)) log_err("out of memory adding cnamed-ns"); } /* if dpns->lame then set the address(es) lame too */ if(!delegpt_add_rrset(foriq->dp, forq->region, rrset, - (int)dpns->lame)) + dpns->lame)) log_err("out of memory adding targets"); verbose(VERB_ALGO, "added target response"); delegpt_log(VERB_ALGO, foriq->dp); |