return reset(ctx);
}
+static int prepare_additionals(knot_pkt_t *pkt)
+{
+ knot_rrset_t opt_rr;
+ int ret = knot_edns_init(&opt_rr, KR_EDNS_PAYLOAD, 0, KR_EDNS_VERSION, &pkt->mm);
+ if (ret != KNOT_EOK) {
+ return ret;
+ }
+
+ knot_pkt_begin(pkt, KNOT_ADDITIONAL);
+ ret = knot_pkt_put(pkt, KNOT_COMPR_HINT_NONE, &opt_rr, KNOT_PF_FREE);
+ if (ret != KNOT_EOK) {
+ knot_rrset_clear(&opt_rr, &pkt->mm);
+ return ret;
+ }
+
+ return kr_ok();
+}
+
static int prepare_query(knot_layer_t *ctx, knot_pkt_t *pkt)
{
assert(pkt && ctx);
knot_wire_set_id(pkt->wire, query->id);
/* Declare EDNS0 support. */
- knot_rrset_t opt_rr;
- ret = knot_edns_init(&opt_rr, KR_EDNS_PAYLOAD, 0, KR_EDNS_VERSION, &pkt->mm);
- if (ret != KNOT_EOK) {
- return KNOT_STATE_FAIL;
- }
-
- knot_pkt_begin(pkt, KNOT_ADDITIONAL);
- ret = knot_pkt_put(pkt, KNOT_COMPR_HINT_NONE, &opt_rr, KNOT_PF_FREE);
- if (ret != KNOT_EOK) {
- knot_rrset_clear(&opt_rr, &pkt->mm);
- return KNOT_STATE_FAIL;
+ if (!(query->flags & QUERY_SAFEMODE)) {
+ ret = prepare_additionals(pkt);
+ if (ret != 0) {
+ return KNOT_STATE_FAIL;
+ }
}
/* Query built, expect answer. */
return KNOT_STATE_CONSUME;
}
+static int resolve_badmsg(knot_pkt_t *pkt, struct kr_request *req, struct kr_query *query)
+{
+ /* Work around broken auths/load balancers */
+ if (query->flags & QUERY_SAFEMODE) {
+ return resolve_error(pkt, req);
+ } else {
+ query->flags |= QUERY_SAFEMODE;
+ return KNOT_STATE_DONE;
+ }
+}
+
/** Resolve input query or continue resolution with followups.
*
* This roughly corresponds to RFC1034, 5.3.3 4a-d.
/* Check for packet processing errors first. */
if (pkt->parsed < pkt->size) {
DEBUG_MSG("<= malformed response\n");
- return resolve_error(pkt, req);
+ return resolve_badmsg(pkt, req, query);
} else if (!is_paired_to_query(pkt, query)) {
DEBUG_MSG("<= ignoring mismatching response\n");
return KNOT_STATE_CONSUME;
case KNOT_RCODE_NOERROR:
case KNOT_RCODE_NXDOMAIN:
break; /* OK */
+ case KNOT_RCODE_FORMERR:
+ case KNOT_RCODE_NOTIMPL:
+ DEBUG_MSG("<= rcode: %s\n", rcode ? rcode->name : "??");
+ return resolve_badmsg(pkt, req, query);
default:
DEBUG_MSG("<= rcode: %s\n", rcode ? rcode->name : "??");
return resolve_error(pkt, req);
{
struct timeval timeout = { KR_CONN_RTT_MAX / 1000, 0 };
auto_close int fd = connected(addr, proto, &timeout);
+ resp->size = 0;
if (fd < 0) {
return fd;
}
/* Parse and return */
resp->size = ret;
- if (knot_pkt_parse(resp, 0) != 0) {
- return kr_error(EBADMSG);
- }
-
- return kr_ok();
+ return knot_pkt_parse(resp, 0);
}
int kr_resolve(struct kr_context* ctx, knot_pkt_t *answer,
int ret = sendrecv(addr, proto, query, resp);
if (ret != 0) {
DEBUG_MSG("sendrecv: %s\n", kr_strerror(ret));
- resp->size = 0;
}
state = kr_resolve_consume(&request, resp);
knot_pkt_clear(resp);
--- /dev/null
+; config options
+server:
+ harden-referral-path: no
+ target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Disable EDNS0 and fancy stuff when the server replies with FORMERR.
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+cz. IN A
+ENTRY_END
+
+; root prime
+STEP 30 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA 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
+
+; query sent to root server
+STEP 50 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+cz. IN A
+SECTION AUTHORITY
+cz. IN NS ns1.cz.
+SECTION ADDITIONAL
+ns1.cz. IN A 168.192.2.2
+ENTRY_END
+
+; this is the formerr answer
+STEP 60 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA FORMERR
+SECTION QUESTION
+cz. IN A
+SECTION ANSWER
+ENTRY_END
+
+; this is the correct answer
+STEP 60 REPLY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+cz. IN A
+SECTION ANSWER
+cz. IN A 10.20.30.40
+SECTION AUTHORITY
+cz. IN NS ns1.cz.
+SECTION ADDITIONAL
+ns1.cz. IN A 168.192.2.2
+ENTRY_END
+
+; is the final answer correct?
+STEP 100 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA
+SECTION QUESTION
+cz. IN A
+SECTION ANSWER
+cz. IN A 10.20.30.40
+ENTRY_END
+
+SCENARIO_END