Commit 0868ee64 authored by Lubos Slovak's avatar Lubos Slovak

Fixed RCODE-processing.

Extended RCODE is one 12-bit number. Until now it was not only
handled separately for old and new RCODEs, but it was also
interpreted wrong.

Unified RCODE processing - it's represented by only one number and
writing into the packet takes place at the end of query processing.

refs #300
parent 362dc8fb
......@@ -121,7 +121,7 @@ static bool dname_cname_cannot_synth(const knot_rrset_t *rrset, const knot_dname
static bool have_dnssec(struct query_data *qdata)
{
return knot_pkt_has_dnssec(qdata->query) &&
qdata->rcode_ext != KNOT_RCODE_BADVERS &&
qdata->rcode != KNOT_RCODE_BADVERS &&
zone_contents_is_signed(qdata->zone->contents);
}
......
......@@ -230,7 +230,7 @@ static int answer_edns_init(const knot_pkt_t *query, knot_pkt_t *resp,
/* Check supported version. */
if (knot_edns_get_version(query->opt_rr) != KNOT_EDNS_VERSION) {
qdata->rcode_ext = KNOT_RCODE_BADVERS;
qdata->rcode = KNOT_RCODE_BADVERS;
}
/* Set DO bit if set (DNSSEC requested). */
......@@ -257,21 +257,23 @@ static int answer_edns_put(knot_pkt_t *resp, struct query_data *qdata)
return KNOT_EOK;
}
/* Write back extended RCODE. */
if (qdata->rcode_ext != 0) {
knot_wire_set_rcode(resp->wire, KNOT_EDNS_RCODE_LO(qdata->rcode_ext));
knot_edns_set_ext_rcode(&qdata->opt_rr, KNOT_EDNS_RCODE_HI(qdata->rcode_ext));
}
/* Reclaim reserved size. */
int ret = knot_pkt_reclaim(resp, knot_edns_wire_size(&qdata->opt_rr));
if (ret != KNOT_EOK) {
return ret;
}
uint8_t *wire_end = resp->wire + resp->size;
/* Write to packet. */
assert(resp->current == KNOT_ADDITIONAL);
return knot_pkt_put(resp, COMPR_HINT_NONE, &qdata->opt_rr, 0);
ret = knot_pkt_put(resp, COMPR_HINT_NONE, &qdata->opt_rr, 0);
if (ret == KNOT_EOK) {
/* Save position of the Ext RCODE field. */
qdata->ext_rcode = wire_end + KNOT_EDNS_EXT_RCODE_POS;
}
return ret;
}
/*! \brief Initialize response, sizes and find zone from which we're going to answer. */
......@@ -309,12 +311,7 @@ static int prepare_answer(const knot_pkt_t *query, knot_pkt_t *resp, knot_proces
/* Setup EDNS. */
ret = answer_edns_init(query, resp, qdata);
if (ret != KNOT_EOK) {
return ret;
}
/* If Extended RCODE is set, do not continue with query processing. */
if (qdata->rcode_ext != 0) {
if (ret != KNOT_EOK || qdata->rcode != 0) {
return KNOT_ERROR;
}
......@@ -335,6 +332,27 @@ static int prepare_answer(const knot_pkt_t *query, knot_pkt_t *resp, knot_proces
return ret;
}
static int set_rcode_to_packet(knot_pkt_t *pkt, struct query_data *qdata)
{
int ret = KNOT_EOK;
uint8_t ext_rcode = KNOT_EDNS_RCODE_HI(qdata->rcode);
if (ext_rcode != 0) {
/* If there is no OPT RR and Ext RCODE is set, result in
* SERVFAIL. This should not happen!
*/
if (qdata->ext_rcode == NULL) {
return KNOT_ERROR;
} else {
*qdata->ext_rcode = ext_rcode;
}
}
knot_wire_set_rcode(pkt->wire, KNOT_EDNS_RCODE_LO(qdata->rcode));
return ret;
}
static int process_query_err(knot_pkt_t *pkt, knot_process_t *ctx)
{
assert(pkt && ctx);
......@@ -349,8 +367,8 @@ static int process_query_err(knot_pkt_t *pkt, knot_process_t *ctx)
/* Restore original QNAME. */
process_query_qname_case_restore(qdata, pkt);
/* Set RCODE. */
knot_wire_set_rcode(pkt->wire, qdata->rcode);
/* Set final RCODE to packet. */
(void) set_rcode_to_packet(pkt, qdata);
/* Add OPT and TSIG (best effort, send reply anyway if fails). */
if (pkt->current != KNOT_ADDITIONAL) {
......@@ -489,11 +507,19 @@ static int process_query_out(knot_pkt_t *pkt, knot_process_t *ctx)
finish:
/* Default RCODE is SERVFAIL if not specified otherwise. */
if (next_state == NS_PROC_FAIL && qdata->rcode == KNOT_RCODE_NOERROR
&& qdata->rcode_ext == 0) {
if (next_state == NS_PROC_FAIL && qdata->rcode == KNOT_RCODE_NOERROR) {
qdata->rcode = KNOT_RCODE_SERVFAIL;
}
/* Store Extended RCODE - divide between header and OPT if possible. */
if (next_state != NS_PROC_FAIL) {
if (set_rcode_to_packet(pkt, qdata) != KNOT_EOK) {
qdata->rcode = KNOT_RCODE_SERVFAIL;
next_state = NS_PROC_FAIL;
}
}
/* In case of NS_PROC_FAIL, RCODE is set in the error-processing function. */
/* Rate limits (if applicable). */
if (qdata->param->proc_flags & NS_QUERY_LIMIT_RATE) {
next_state = ratelimit_apply(next_state, pkt, ctx);
......
......@@ -68,9 +68,9 @@ struct process_query_param {
/*! \brief Query processing intermediate data. */
struct query_data {
uint16_t rcode; /*!< Resulting RCODE. */
uint16_t rcode; /*!< Resulting RCODE (Whole extended RCODE). */
uint8_t *ext_rcode; /*!< Place of the Ext RCODE field of OPT RR in wire. */
uint16_t rcode_tsig; /*!< Resulting TSIG RCODE. */
uint8_t rcode_ext; /*!< Extended RCODE. */
uint16_t packet_type; /*!< Resolved packet type. */
knot_pkt_t *query; /*!< Query to be solved. */
const zone_t *zone; /*!< Zone from which is answered. */
......
......@@ -85,6 +85,12 @@ typedef enum {
KNOT_RCODE_BADVERS = 16 /*!< Bad OPT Version. */
} knot_rcode_t;
/*!
* \brief TSIG error codes to be set in the TSIG RR's RDATA.
*
* Defined in RFC 2845 and RFC 4635.
* See also https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml
*/
typedef enum {
KNOT_TSIG_ERR_BADSIG = 16, /*!< TSIG signature failed. */
KNOT_TSIG_ERR_BADKEY = 17, /*!< Key is not supported. */
......@@ -92,6 +98,9 @@ typedef enum {
KNOT_TSIG_ERR_BADTRUNC = 22 /*!< Bad truncation. */
} knot_tsig_error_t;
/*!
* \brief TKEY error codes. (Defined in RFC 2930.)
*/
typedef enum {
KNOT_TKEY_ERR_BADMODE = 19, /*!< Bad TKEY mode. */
KNOT_TKEY_ERR_BADNAME = 20, /*!< Duplicate key name. */
......
......@@ -48,7 +48,9 @@ enum knot_edns_const {
/*! \brief Minimum size of EDNS OPT RR in wire format. */
KNOT_EDNS_MIN_SIZE = 11,
/*! \brief EDNS OPT header size. */
/*! \brief Position of the Ext RCODE field in wire format of OPT RR. */
KNOT_EDNS_EXT_RCODE_POS = 5,
/*! \brief EDNS OPTION header size. */
KNOT_EDNS_OPTION_HDRLEN = 4,
/*! \brief Maximal edns client subnet data size (IPv6). */
KNOT_EDNS_MAX_OPTION_CLIENT_SUBNET = 20,
......@@ -62,7 +64,7 @@ enum knot_edns_const {
};
/* Helpers for splitting extended RCODE. */
#define KNOT_EDNS_RCODE_HI(rc) (rc >> 4)
#define KNOT_EDNS_RCODE_HI(rc) ((rc >> 4) & 0x00ff)
#define KNOT_EDNS_RCODE_LO(rc) (rc & 0x000f)
/*!
......
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