Commit 53cb90dc authored by Marek Vavruša's avatar Marek Vavruša

lib: revert to rfc1035 basic dns query on bad reply

if the server doesn’t understand edns0, replies with
notimpl, formerr or sends bad badly formed response,
we try basic dns query (ns0.rbsov.bbc.co.uk)
parent ab06efbd
......@@ -345,6 +345,24 @@ static int begin(knot_layer_t *ctx, void *module_param)
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);
......@@ -370,23 +388,28 @@ static int prepare_query(knot_layer_t *ctx, knot_pkt_t *pkt)
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.
......@@ -403,7 +426,7 @@ static int resolve(knot_layer_t *ctx, knot_pkt_t *pkt)
/* 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;
......@@ -428,6 +451,10 @@ static int resolve(knot_layer_t *ctx, knot_pkt_t *pkt)
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);
......
......@@ -100,6 +100,7 @@ static int sendrecv(struct sockaddr *addr, int proto, const knot_pkt_t *query, k
{
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;
}
......@@ -127,11 +128,7 @@ static int sendrecv(struct sockaddr *addr, int proto, const knot_pkt_t *query, k
/* 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,
......@@ -178,7 +175,6 @@ 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);
......
......@@ -31,7 +31,8 @@ enum kr_query_flag {
QUERY_NO_MINIMIZE = 1 << 0, /**< Don't minimize QNAME. */
QUERY_TCP = 1 << 1, /**< Use TCP for this query. */
QUERY_RESOLVED = 1 << 2, /**< Query is resolved. */
QUERY_AWAIT_ADDR = 1 << 3 /**< Query is waiting for NS address. */
QUERY_AWAIT_ADDR = 1 << 3, /**< Query is waiting for NS address. */
QUERY_SAFEMODE = 1 << 4 /**< Don't use fancy stuff (EDNS...) */
};
/**
......
; 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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment