Commit 23a913b0 authored by Lubos Slovak's avatar Lubos Slovak

TTL checking rewritten and optimized.

parent a7fadcd8
......@@ -133,18 +133,24 @@ int knot_node_add_rrset_replace(knot_node_t *node, knot_rrset_t *rrset)
}
int knot_node_add_rrset(knot_node_t *node, knot_rrset_t *rrset,
knot_rrset_t **out_rrset)
bool *ttl_err)
{
if (node == NULL) {
if (node == NULL || rrset == NULL) {
return KNOT_EINVAL;
}
for (uint16_t i = 0; i < node->rrset_count; ++i) {
if (node->rrset_tree[i]->type == rrset->type) {
if (out_rrset) {
*out_rrset = node->rrset_tree[i];
}
int merged, deleted_rrs;
/* Check if the added RR has the same TTL as the first
* RR in the RRSet.
*/
if (ttl_err && knot_rrset_rr_ttl(rrset, 0)
!= knot_rrset_rr_ttl(node->rrset_tree[i], 0)) {
*ttl_err = true;
}
int ret = knot_rrset_merge_sort(node->rrset_tree[i],
rrset, &merged,
&deleted_rrs, NULL);
......@@ -158,10 +164,6 @@ int knot_node_add_rrset(knot_node_t *node, knot_rrset_t *rrset,
}
}
// New RRSet (with one RR)
if (out_rrset) {
*out_rrset = rrset;
}
return knot_node_add_rrset_no_merge(node, rrset);
}
......
......@@ -129,7 +129,7 @@ knot_node_t *knot_node_new(const knot_dname_t *owner, knot_node_t *parent,
* \retval KNOT_ERROR if the RRSet could not be inserted.
*/
int knot_node_add_rrset(knot_node_t *node, knot_rrset_t *rrset,
knot_rrset_t **out_rrset);
bool *ttl_err);
int knot_node_add_rrset_replace(knot_node_t *node, knot_rrset_t *rrset);
......
......@@ -249,43 +249,6 @@ void err_handler_log_all(err_handler_t *handler)
}
}
/* TODO: optimize */
static bool rrset_ttls_equal(const knot_rrset_t *rrset)
{
uint16_t rr_count = knot_rrset_rr_count(rrset);
if (rr_count == 0) {
return true;
}
uint32_t prev_ttl = knot_rrset_rr_ttl(rrset, 0);
for (uint16_t i = 1; i < rr_count; ++i) {
uint32_t cur_ttl = knot_rrset_rr_ttl(rrset, i);
if (cur_ttl != prev_ttl) {
return false;
}
prev_ttl = cur_ttl;
}
return true;
}
/*!
* \brief Logs a warning if merging RRs with different TTLs.
*
* \param ttl_first TTL of the first RR in the RRSet.
* \param ttl_new TTL to be inserted.
* \param rr RRSet we're adding into.
* \param zname Zone name for logging.
*/
static int rrset_ttl_check(const knot_rrset_t *rr)
{
if (rr->type != KNOT_RRTYPE_RRSIG && !rrset_ttls_equal(rr)) {
return KNOT_EMALF;
} else {
return KNOT_EOK;
}
}
/*!
* \brief Check whether DNSKEY rdata are valid.
*
......@@ -942,38 +905,6 @@ int sem_check_node_plain(const knot_zone_contents_t *zone,
}
}
int sem_check_rrset(const knot_node_t *node, const knot_rrset_t *rrset,
bool master, err_handler_t *handler)
{
if (node == NULL || rrset == NULL || handler == NULL) {
return KNOT_EINVAL;
}
int ret = rrset_ttl_check(rrset);
/* Do the check both on master and slave because of the warning,
* but fail only on master. */
if (ret != KNOT_EOK) {
/* Prepare additional info string. */
char info_str[64] = { '\0' };
char type_str[16] = { '\0' };
knot_rrtype_to_string(rr->type, type_str, sizeof(type_str));
snprintf(info_str, sizeof(info_str), "Record type: %s.", type_str);
if (master) {
/*! \todo REPLACE WITH FATAL ERROR */
err_handler_handle_error(handler, n, ZC_ERR_TTL_MISMATCH,
info_str);
return KNOT_EMALF;
} else {
err_handler_handle_error(handler, n, ZC_ERR_TTL_MISMATCH,
info_str);
}
}
return KNOT_EOK;
}
/*!
* \brief Run semantic checks for node with DNSSEC-related types.
*
......
......@@ -633,9 +633,9 @@ int knot_zone_contents_create_node(knot_zone_contents_t *contents,
/*----------------------------------------------------------------------------*/
static int insert_rr(knot_zone_contents_t *z, knot_rrset_t *rr, knot_node_t **n,
knot_rrset_t **rrset, bool nsec3)
bool nsec3, bool *ttl_err)
{
if (z == NULL || rr == NULL || n == NULL || rrset == NULL) {
if (z == NULL || rr == NULL || n == NULL || ttl_err == NULL) {
return KNOT_EINVAL;
}
......@@ -663,7 +663,7 @@ static int insert_rr(knot_zone_contents_t *z, knot_rrset_t *rr, knot_node_t **n,
}
}
return knot_node_add_rrset(*n, rr, rrset);
return knot_node_add_rrset(*n, rr, ttl_err);
}
static bool to_nsec3_tree(const knot_rrset_t *rr)
......@@ -671,11 +671,10 @@ static bool to_nsec3_tree(const knot_rrset_t *rr)
return knot_rrset_is_nsec3rel(rr);
}
int knot_zone_contents_add_rr(knot_zone_contents_t *z,
knot_rrset_t *rr, knot_node_t **n,
knot_rrset_t **rrset)
int knot_zone_contents_add_rr(knot_zone_contents_t *z, knot_rrset_t *rr,
knot_node_t **n, bool *ttl_err)
{
return insert_rr(z, rr, n, rrset, to_nsec3_tree(rr));
return insert_rr(z, rr, n, to_nsec3_tree(rr), ttl_err);
}
int knot_zone_contents_add_rrset(knot_zone_contents_t *zone,
......
......@@ -128,9 +128,8 @@ int knot_zone_contents_create_node(knot_zone_contents_t *contents,
const knot_rrset_t *rr,
knot_node_t **node);
int knot_zone_contents_add_rr(knot_zone_contents_t *z,
knot_rrset_t *rr, knot_node_t **n,
knot_rrset_t **rrset);
int knot_zone_contents_add_rr(knot_zone_contents_t *z, knot_rrset_t *rr,
knot_node_t **n, bool *ttl_err);
/*!
* \brief Adds a RRSet to the given zone.
......
......@@ -80,7 +80,9 @@ static bool handle_err(zcreator_t *zc,
int zcreator_step(zcreator_t *zc, knot_rrset_t *rr)
{
assert(zc && rr);
if (zc == NULL || rr == NULL || knot_rrset_rr_count(rr) != 1) {
return KNOT_EINVAL;
}
if (rr->type == KNOT_RRTYPE_SOA &&
knot_node_rrset(zc->z->apex, KNOT_RRTYPE_SOA)) {
......@@ -98,8 +100,10 @@ int zcreator_step(zcreator_t *zc, knot_rrset_t *rr)
// Search for node or create a new one
n = NULL;
}
knot_rrset_t *zone_rrset = NULL;
int ret = knot_zone_contents_add_rr(zc->z, rr, &n, &zone_rrset);
bool ttl_err = false;
int ret = knot_zone_contents_add_rr(zc->z, rr, &n, &ttl_err);
if (ret < 0) {
if (!handle_err(zc, rr, ret)) {
// Fatal error
......@@ -112,7 +116,6 @@ int zcreator_step(zcreator_t *zc, knot_rrset_t *rr)
knot_rrset_deep_free(&rr, true, NULL);
}
assert(n);
assert(zone_rrset);
zc->last_node = n;
// Do RRSet and node semantic checks
......@@ -120,12 +123,30 @@ int zcreator_step(zcreator_t *zc, knot_rrset_t *rr)
err_handler_t err_handler;
err_handler_init(&err_handler);
ret = sem_check_rrset(n, zone_rrset, zc->master, &err_handler);
if (ret != KNOT_EOK) {
return ret;
/* Check if TTL of the added RR is equal to the TTL of the RRSet.
* It's sufficient to compare with the first RR, because each RR in the
* RRSet already underwent this check.
*/
if (ttl_err) {
/* Prepare additional info string. */
char info_str[64] = { '\0' };
char type_str[16] = { '\0' };
knot_rrtype_to_string(rr->type, type_str, sizeof(type_str));
snprintf(info_str, sizeof(info_str), "Record type: %s.",
type_str);
if (zc->master) {
/*! \todo REPLACE WITH FATAL ERROR */
err_handler_handle_error(&err_handler, n,
ZC_ERR_TTL_MISMATCH, info_str);
return KNOT_EMALF;
} else {
err_handler_handle_error(&err_handler, n,
ZC_ERR_TTL_MISMATCH, info_str);
}
}
ret = sem_check_node_plain(zc->z, n,
&err_handler, true,
ret = sem_check_node_plain(zc->z, n, &err_handler, true,
&sem_fatal_error);
if (ret != KNOT_EOK) {
return ret;
......
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