/** 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)
+can_have_last_resort(struct module_env* env, uint8_t* nm, size_t nmlen,
+ uint16_t qclass)
{
struct delegpt* fwddp;
struct iter_hints_stub* stub;
+ int labs = dname_count_labels(nm);
/* 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)) &&
+ if(!dname_is_root(nm) && (stub = (struct iter_hints_stub*)
+ name_tree_find(&env->hints->tree, nm, nmlen, labs, 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)) &&
+ if((fwddp = forwards_find(env->fwds, nm, 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;
verbose(VERB_ALGO, "No more query targets, attempting last resort");
log_assert(iq->dp);
- if(!can_have_last_resort(qstate->env, iq->dp, iq)) {
+ if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen,
+ iq->qchase.qclass)) {
/* fail -- no more targets, no more hope of targets, no hope
* of a response. */
+ verbose(VERB_QUERY, "configured stub or forward servers failed -- returning SERVFAIL");
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
}
if(!iq->dp->has_parent_side_NS && dname_is_root(iq->dp->name)) {
/* see if we can issue queries to get nameserver addresses */
/* this lookup is not randomized, but sequential. */
for(ns = iq->dp->nslist; ns; ns = ns->next) {
+ /* if this nameserver is at a delegation point, but that
+ * delegation point is a stub and we cannot go higher, skip*/
+ if( ((ie->supports_ipv6 && !ns->done_pside6) ||
+ (ie->supports_ipv4 && !ns->done_pside4)) &&
+ !can_have_last_resort(qstate->env, ns->name, ns->namelen,
+ iq->qchase.qclass)) {
+ log_nametypeclass(VERB_ALGO, "cannot pside lookup ns "
+ "because it is also a stub/forward,",
+ ns->name, LDNS_RR_TYPE_NS, iq->qchase.qclass);
+ if(ie->supports_ipv6) ns->done_pside6 = 1;
+ if(ie->supports_ipv4) ns->done_pside4 = 1;
+ continue;
+ }
/* query for parent-side A and AAAA for nameservers */
if(ie->supports_ipv6 && !ns->done_pside6) {
/* Send the AAAA request. */
stub-zone:
name: "example.com"
stub-addr: 10.0.1.1
+stub-zone:
+ name: "example.net"
+ stub-addr: 10.0.5.1
CONFIG_END
SCENARIO_BEGIN Test stub zone leaking to the internet on last resort fallback
; root prime
ENTRY_BEGIN
-MATCH
+MATCH qname qtype
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
SECTION AUTHORITY
subzone.example.com. IN NS sub-ns1.example.com.
subzone.example.com. IN NS sub-ns2.example.com.
+subzone.example.com. IN NS example.net.
SECTION ADDITIONAL
sub-ns1.example.com. IN A 10.0.2.3
sub-ns2.example.com. IN A 10.0.2.4
RANGE_END
+; stub server for example.net
+RANGE_BEGIN 0 100
+ ADDRESS 10.0.5.1
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id copy_query
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 10.0.5.1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id copy_query
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.net. IN A
+SECTION ANSWER
+example.net. IN A 10.0.5.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode question
+ADJUST copy_id copy_query
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.net. IN AAAA
+SECTION AUTHORITY
+example.net. 300 SOA master.example.net etc 1 2 3 4 300
+ENTRY_END
+
+RANGE_END
+
; stub server for subzone.example.com
RANGE_BEGIN 0 100
ADDRESS 10.0.2.3
ENTRY_END
RANGE_END
+; stub server for subzone.example.com
+RANGE_BEGIN 0 100
+ ADDRESS 10.0.5.4
+; match anything, servfail
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR SERVFAIL
+SECTION QUESTION
+subzone.example.com. IN A
+SECTION ANSWER
+ENTRY_END
+RANGE_END
+
+
+; fetch the delegation point for example.net in cache.
STEP 1 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
+example.net. IN NS
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 10.0.5.1
+ENTRY_END
+
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
whatever.subzone.example.com. IN A
ENTRY_END
; recursion happens here.
; the query should not leak subzone ns queries to the internet
-STEP 10 CHECK_ANSWER
+STEP 30 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA SERVFAIL