return 1;
}
+/** fill fail address for later recovery */
+static void
+fill_fail_addr(struct iter_qstate* iq, struct sockaddr_storage* addr,
+ socklen_t addrlen)
+{
+ if(addrlen == 0) {
+ iq->fail_addr_type = 0;
+ return;
+ }
+ if(((struct sockaddr_in*)addr)->sin_family == AF_INET) {
+ iq->fail_addr_type = 4;
+ memcpy(&iq->fail_addr.in,
+ &((struct sockaddr_in*)addr)->sin_addr,
+ sizeof(iq->fail_addr.in));
+ }
+#ifdef AF_INET6
+ else if(((struct sockaddr_in*)addr)->sin_family == AF_INET6) {
+ iq->fail_addr_type = 6;
+ memcpy(&iq->fail_addr.in6,
+ &((struct sockaddr_in6*)addr)->sin6_addr,
+ sizeof(iq->fail_addr.in6));
+ }
+#endif
+ else {
+ iq->fail_addr_type = 0;
+ }
+}
+
+/** print fail addr to string */
+static void
+print_fail_addr(struct iter_qstate* iq, char* buf, size_t len)
+{
+ if(iq->fail_addr_type == 4) {
+ if(inet_ntop(AF_INET, &iq->fail_addr.in, buf,
+ (socklen_t)len) == 0)
+ (void)strlcpy(buf, "(inet_ntop error)", len);
+ }
+#ifdef AF_INET6
+ else if(iq->fail_addr_type == 6) {
+ if(inet_ntop(AF_INET6, &iq->fail_addr.in6, buf,
+ (socklen_t)len) == 0)
+ (void)strlcpy(buf, "(inet_ntop error)", len);
+ }
+#endif
+ else
+ (void)strlcpy(buf, "", len);
+}
+
/** add response specific error information for log servfail */
static void
errinf_reply(struct module_qstate* qstate, struct iter_qstate* iq)
if(qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail)
return;
if((qstate->reply && qstate->reply->remote_addrlen != 0) ||
- (iq->fail_reply && iq->fail_reply->remote_addrlen != 0)) {
+ (iq->fail_addr_type != 0)) {
char from[256], frm[512];
if(qstate->reply && qstate->reply->remote_addrlen != 0)
addr_to_str(&qstate->reply->remote_addr,
qstate->reply->remote_addrlen, from,
sizeof(from));
else
- addr_to_str(&iq->fail_reply->remote_addr,
- iq->fail_reply->remote_addrlen, from,
- sizeof(from));
+ print_fail_addr(iq, from, sizeof(from));
snprintf(frm, sizeof(frm), "from %s", from);
errinf(qstate, frm);
}
(*qstate->env->detach_subs)(qstate);
iq->num_target_queries = 0;
iq->response = NULL;
- iq->fail_reply = NULL;
+ iq->fail_addr_type = 0;
verbose(VERB_ALGO, "cleared outbound list for next round");
return next_state(iq, QUERYTARGETS_STATE);
} else if(type == RESPONSE_TYPE_CNAME) {
}
/* parse message */
- iq->fail_reply = qstate->reply;
+ fill_fail_addr(iq, &qstate->reply->remote_addr,
+ qstate->reply->remote_addrlen);
prs = (struct msg_parse*)regional_alloc(qstate->env->scratch,
sizeof(struct msg_parse));
if(!prs) {
--- /dev/null
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+ qname-minimisation: "no"
+ minimal-responses: no
+ log-servfail: yes
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test iterator fail_reply report
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. IN NS ns2.example.net.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. IN AAAA ::1
+ns2.example.net. IN AAAA ::1
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns2.example.net. IN A
+SECTION ANSWER
+ns2.example.net. IN A 1.2.3.5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns2.example.net. IN AAAA
+SECTION ANSWER
+ns2.example.net. IN AAAA ::1
+ENTRY_END
+
+RANGE_END
+
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR SERVFAIL
+SECTION QUESTION
+ns.example.com. IN A
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR SERVFAIL
+SECTION QUESTION
+ns.example.com. IN AAAA
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+STEP 20 CHECK_OUT_QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+STEP 21 TIMEOUT
+STEP 22 TIMEOUT
+STEP 23 TIMEOUT
+STEP 24 TIMEOUT
+STEP 25 TIMEOUT
+
+STEP 31 TIMEOUT
+STEP 32 TIMEOUT
+STEP 33 TIMEOUT
+STEP 34 TIMEOUT
+
+; recursion happens here.
+STEP 50 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+ENTRY_END
+
+SCENARIO_END