Skip to content
Snippets Groups Projects
Commit 194e3ac6 authored by Marek Vavruša's avatar Marek Vavruša
Browse files

lib: SOA in negative answers

parent c57d0234
No related branches found
No related tags found
No related merge requests found
......@@ -32,6 +32,14 @@
#define DEBUG_MSG(fmt, ...)
#endif
/* Packet classification. */
enum {
PKT_NOERROR = 1 << 0, /* Positive response */
PKT_NODATA = 1 << 1, /* No data response */
PKT_NXDOMAIN = 1 << 2, /* Negative response */
PKT_ERROR = 1 << 3 /* Refused or server failure */
};
/* Iterator often walks through packet section, this is an abstraction. */
typedef int (*rr_callback_t)(const knot_rrset_t *, unsigned, struct kr_layer_param *);
......@@ -72,6 +80,20 @@ static bool is_paired_to_query(const knot_pkt_t *answer, struct kr_query *query)
knot_dname_is_equal(qname, knot_pkt_qname(answer));
}
/*! \brief Return response class. */
static int response_classify(knot_pkt_t *pkt)
{
const knot_pktsection_t *an = knot_pkt_section(pkt, KNOT_ANSWER);
switch (knot_wire_get_rcode(pkt->wire)) {
case KNOT_RCODE_NOERROR:
return (an->count == 0) ? PKT_NODATA : PKT_NOERROR;
case KNOT_RCODE_NXDOMAIN:
return PKT_NXDOMAIN;
default:
return PKT_ERROR;
}
}
static void follow_cname_chain(const knot_dname_t **cname, const knot_rrset_t *rr,
struct kr_query *cur)
{
......@@ -129,8 +151,7 @@ int rr_update_answer(const knot_rrset_t *rr, unsigned hint, struct kr_layer_para
return KNOT_NS_PROC_DONE;
}
/* Update parent query as well. */
return rr_update_parent(rr, hint, param);
return KNOT_NS_PROC_DONE;
}
int rr_update_nameserver(const knot_rrset_t *rr, unsigned hint, struct kr_layer_param *param)
......@@ -157,28 +178,18 @@ int rr_update_nameserver(const knot_rrset_t *rr, unsigned hint, struct kr_layer_
static int process_authority(knot_pkt_t *pkt, struct kr_layer_param *param)
{
int state = KNOT_NS_PROC_MORE;
/* Answer declares AA, can't be referral. */
if (knot_wire_get_aa(pkt->wire)) {
return state;
}
/* Update current zone cut from NS records. */
const knot_pktsection_t *ns = knot_pkt_section(pkt, KNOT_AUTHORITY);
for (unsigned i = 0; i < ns->count; ++i) {
const knot_rrset_t *rr = knot_pkt_rr(ns, i);
if (rr->type != KNOT_RRTYPE_NS) {
continue;
}
state = rr_update_nameserver(rr, 0, param);
if (state != KNOT_NS_PROC_MORE) {
break;
if (rr->type == KNOT_RRTYPE_NS) {
int state = rr_update_nameserver(rr, 0, param);
if (state != KNOT_NS_PROC_MORE) {
return state;
}
}
}
return state;
return KNOT_NS_PROC_MORE;
}
static int process_additional(knot_pkt_t *pkt, struct kr_layer_param *param)
......@@ -211,27 +222,19 @@ static int process_answer(knot_pkt_t *pkt, struct kr_layer_param *param)
* NOERROR => found zone cut, retry
* NXDOMAIN => parent is zone cut, retry as a workaround for bad authoritatives
*/
const knot_pktsection_t *an = knot_pkt_section(pkt, KNOT_ANSWER);
bool is_minimized = (!knot_dname_is_equal(knot_pkt_qname(pkt), query->sname));
bool is_nodata = (knot_wire_get_rcode(pkt->wire) == KNOT_RCODE_NOERROR) && !an->count;
bool is_nxdomain = (knot_wire_get_rcode(pkt->wire) == KNOT_RCODE_NXDOMAIN);
if (is_minimized && (is_nodata || is_nxdomain)) {
bool is_final = (query->parent == NULL);
int pkt_class = response_classify(pkt);
if (!knot_dname_is_equal(knot_pkt_qname(pkt), query->sname) && (pkt_class & (PKT_NXDOMAIN|PKT_NODATA))) {
query->flags |= QUERY_NO_MINIMIZE;
return KNOT_NS_PROC_DONE;
}
/* Does this answer update the final response? */
rr_callback_t callback = &rr_update_parent;
if (query->parent == NULL) {
knot_wire_set_rcode(param->answer->wire, knot_wire_get_rcode(pkt->wire));
callback = &rr_update_answer;
}
/* Process answer section records. */
/* Process answer type */
const knot_pktsection_t *an = knot_pkt_section(pkt, KNOT_ANSWER);
const knot_dname_t *cname = query->sname;
for (unsigned i = 0; i < an->count; ++i) {
const knot_rrset_t *rr = knot_pkt_rr(an, i);
int state = callback(rr, 0, param);
int state = is_final ? rr_update_answer(rr, 0, param) : rr_update_parent(rr, 0, param);
if (state == KNOT_NS_PROC_FAIL) {
return state;
}
......@@ -243,12 +246,36 @@ static int process_answer(knot_pkt_t *pkt, struct kr_layer_param *param)
(void) kr_rplan_push(param->rplan, query->parent, cname, query->sclass, query->stype);
}
/* This is either declares AA or not, either way it resolves current query. */
/* Either way it resolves current query. */
kr_rplan_pop(param->rplan, query);
return KNOT_NS_PROC_DONE;
}
static void finalize_answer(knot_pkt_t *pkt, struct kr_layer_param *param)
{
knot_pkt_t *answer = param->answer;
/* Finalize header */
knot_wire_set_rcode(answer->wire, knot_wire_get_rcode(pkt->wire));
/* Finalize authority */
knot_pkt_begin(answer, KNOT_AUTHORITY);
/* Fill in SOA if negative response */
int pkt_class = response_classify(pkt);
if (pkt_class & (PKT_NXDOMAIN|PKT_NODATA)) {
const knot_pktsection_t *ns = knot_pkt_section(pkt, KNOT_AUTHORITY);
for (unsigned i = 0; i < ns->count; ++i) {
const knot_rrset_t *rr = knot_pkt_rr(ns, i);
if (rr->type == KNOT_RRTYPE_SOA) {
rr_update_answer(rr, 0, param);
break;
}
}
}
}
/*! \brief Error handling, RFC1034 5.3.3, 4d. */
static int resolve_error(knot_pkt_t *pkt, struct kr_layer_param *param, int errcode)
{
......@@ -372,6 +399,11 @@ static int resolve(knot_layer_t *ctx, knot_pkt_t *pkt)
break;
}
/* If resolved, finalize answer. */
if (kr_rplan_empty(param->rplan)) {
finalize_answer(pkt, param);
}
return state;
}
......
......@@ -290,8 +290,8 @@ REPLY QR RD RA NOERROR
SECTION QUESTION
ns.bla.nl. IN AAAA
SECTION ANSWER
;SECTION AUTHORITY
;bla.nl. IN SOA bla.nl. bla.nl. 1 2 3 4 5
SECTION AUTHORITY
bla.nl. IN SOA bla.nl. bla.nl. 1 2 3 4 5
;SECTION ADDITIONAL
ENTRY_END
......
......@@ -149,8 +149,8 @@ SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN CNAME www.next.com.
;SECTION AUTHORITY
;next.com. IN SOA next.com. next.com. 2007090400 28800 7200 604800 18000
SECTION AUTHORITY
next.com. IN SOA next.com. next.com. 2007090400 28800 7200 604800 18000
SECTION ADDITIONAL
ENTRY_END
......@@ -170,8 +170,8 @@ SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN CNAME www.next.com.
;SECTION AUTHORITY
;next.com. IN SOA next.com. next.com. 2007090400 28800 7200 604800 18000
SECTION AUTHORITY
next.com. IN SOA next.com. next.com. 2007090400 28800 7200 604800 18000
SECTION ADDITIONAL
ENTRY_END
......@@ -190,8 +190,8 @@ REPLY QR RD RA NOERROR
SECTION QUESTION
www.next.com. IN A
SECTION ANSWER
;SECTION AUTHORITY
;next.com. IN SOA next.com. next.com. 2007090400 28800 7200 604800 18000
SECTION AUTHORITY
next.com. IN SOA next.com. next.com. 2007090400 28800 7200 604800 18000
SECTION ADDITIONAL
ENTRY_END
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment