Skip to content
Snippets Groups Projects
Commit 3c42fe04 authored by Jan Kadlec's avatar Jan Kadlec
Browse files

DNSSEC: Initial solution for chain reconnection

Refs #4
parent 807cead6
Branches
Tags v1.6.3
No related merge requests found
......@@ -31,6 +31,15 @@
#include "libknot/zone/zone-diff.h"
#include "libknot/util/debug.h"
/*!
* \brief Parameters to be used in connect_nsec_nodes callback.
*/
typedef struct {
uint32_t ttl;
knot_changeset_t *changeset;
const knot_zone_contents_t *zone;
} nsec_chain_iterate_data_t;
/* - NSEC chain iteration -------------------------------------------------- */
typedef int (*chain_iterate_cb)(knot_node_t *, knot_node_t *, void *);
......@@ -75,7 +84,14 @@ static int chain_iterate(knot_zone_tree_t *nodes, chain_iterate_cb callback,
current = (knot_node_t *)*hattrie_iter_val(it);
int result = callback(previous, current, data);
if (result != KNOT_EOK) {
if (result == NSEC_NODE_SKIP) {
// No NSEC should be created for this node, skip 2 nodes
hattrie_iter_next(it);
if (hattrie_iter_finished(it)) {
break;
}
current = (knot_node_t *)*hattrie_iter_val(it);
} else if (result != KNOT_EOK) {
hattrie_iter_free(it);
return result;
}
......@@ -89,6 +105,55 @@ static int chain_iterate(knot_zone_tree_t *nodes, chain_iterate_cb callback,
return callback(current, first, data);
}
/*!
* \brief Add entry for removed NSEC to the changeset.
*
* \param oldrr Old NSEC RR set to be removed (including RRSIG).
* \param changeset Changeset to add the old RR into.
*
* \return Error code, KNOT_EOK if successful.
*/
static int changeset_remove_nsec(const knot_rrset_t *oldrr,
knot_changeset_t *changeset)
{
assert(oldrr);
assert(changeset);
int result;
// extract copy of NSEC and RRSIG
knot_rrset_t *old_nsec = NULL;
knot_rrset_t *old_rrsigs = NULL;
result = knot_rrset_deep_copy(oldrr, &old_nsec, 1);
if (result != KNOT_EOK)
return result;
old_rrsigs = old_nsec->rrsigs;
old_nsec->rrsigs = NULL;
// update changeset
result = knot_changeset_add_rrset(changeset, old_nsec,
KNOT_CHANGESET_REMOVE);
if (result != KNOT_EOK) {
knot_rrset_deep_free(&old_nsec, 1, 1);
knot_rrset_deep_free(&old_rrsigs, 1, 1);
return result;
}
if (old_rrsigs) {
result = knot_changeset_add_rrset(changeset, old_rrsigs,
KNOT_CHANGESET_REMOVE);
if (result != KNOT_EOK) {
knot_rrset_deep_free(&old_rrsigs, 1, 1);
return result;
}
}
return KNOT_EOK;
}
/* - NSEC nodes construction ----------------------------------------------- */
......@@ -142,6 +207,7 @@ static knot_rrset_t *create_nsec_rrset(const knot_node_t *from,
return rrset;
}
<<<<<<< HEAD
/*!
* \brief Add entry for removed NSEC to the changeset..
*
......@@ -179,28 +245,57 @@ static int changeset_remove_nsec(const knot_rrset_t *oldrr,
knot_rrset_deep_free(&old_nsec, 1, 1);
knot_rrset_deep_free(&old_rrsigs, 1, 1);
return result;
=======
static int fix_nsec_chain_for(const knot_node_t *node,
const knot_node_t *to,
const nsec_chain_iterate_data_t *data)
{
assert(node);
assert(to);
assert(data);
/*!
* Previous NSEC can either be in changeset, or in
* zone (we get to it via node->prev), but never in both.
*/
const knot_rrset_t *last_rr = knot_changeset_last_rr(data->changeset,
KNOT_CHANGESET_ADD);
assert(!(knot_node_rrset(node->prev, KNOT_RRTYPE_NSEC) && last_rr &&
last_rr->type == KNOT_RRTYPE_NSEC));
const knot_rrset_t *prev_nsec = node->prev ?
knot_node_rrset(node->prev,
KNOT_RRTYPE_NSEC) :
last_rr;
assert(prev_nsec);
assert(prev_nsec->type == KNOT_RRTYPE_NSEC);
if (last_rr) {
// Force remove last NSEC from changeset (has bogus next field)
knot_changeset_remove_last_rr(data->changeset,
KNOT_CHANGESET_ADD);
} else {
// Remove last NSEC from zone (ditto)
int ret = changeset_remove_nsec(prev_nsec, data->changeset);
if (ret != KNOT_EOK) {
return ret;
}
>>>>>>> DNSSEC: Initial solution for chain reconnection
}
if (old_rrsigs) {
result = knot_changeset_add_rrset(changeset, old_rrsigs,
KNOT_CHANGESET_REMOVE);
if (result != KNOT_EOK) {
knot_rrset_deep_free(&old_rrsigs, 1, 1);
return result;
}
// Create new RR pointing to the 'to' node (node after deleted node)
const knot_node_t *prev_node =
node->prev ? node->prev :
knot_zone_contents_find_previous(data->zone, node->owner);
assert(prev_node); // This fails for apex, but it should never happen
knot_rrset_t *fixed_nsec = create_nsec_rrset(prev_node, to, data->ttl);
if (fixed_nsec == NULL) {
return KNOT_ENOMEM;
}
return KNOT_EOK;
// Add new NSEC RR to changeset
return knot_changeset_add_rrset(data->changeset, fixed_nsec,
KNOT_CHANGESET_ADD);
}
/*!
* \brief Parameters to be used in connect_nsec_nodes callback.
*/
typedef struct {
uint32_t ttl;
knot_changeset_t *changeset;
} nsec_chain_iterate_data_t;
/*!
* \brief Connect two nodes by adding a NSEC RR into the first node.
*
......@@ -215,11 +310,11 @@ typedef struct {
*/
static int connect_nsec_nodes(knot_node_t *a, knot_node_t *b, void *d)
{
nsec_chain_iterate_data_t *data = (nsec_chain_iterate_data_t *)d;
dbg_dnssec_detail("Changeset emtpy during generating NSEC chain: %d\n",
knot_changeset_is_empty(data->changeset));
if (b->rrset_count == 0 || knot_node_is_non_auth(b)) {
return NSEC_NODE_SKIP;
}
nsec_chain_iterate_data_t *data = (nsec_chain_iterate_data_t *)d;
knot_rrset_t *old_nsec = knot_node_get_rrset(a, KNOT_RRTYPE_NSEC);
int ret = 0;
......@@ -235,7 +330,11 @@ dbg_dnssec_exec_detail(
free(name);
);
ret = changeset_remove_nsec(old_nsec, data->changeset);
return ret;
if (ret != KNOT_EOK) {
return ret;
}
// Fix NSEC chain
return fix_nsec_chain_for(a, b, data);
}
// create new NSEC
......@@ -286,7 +385,7 @@ static int create_nsec_chain(const knot_zone_contents_t *zone, uint32_t ttl,
assert(zone);
assert(zone->nodes);
nsec_chain_iterate_data_t data = { ttl, changeset };
nsec_chain_iterate_data_t data = { ttl, changeset, zone };
return chain_iterate(zone->nodes, connect_nsec_nodes, &data);
}
......@@ -561,11 +660,12 @@ static int connect_nsec3_nodes(knot_node_t *a, knot_node_t *b, void *data)
uint8_t *rdata_hash = nsec3_rdata_hash(a->rrset_tree[0]->rdata);
uint8_t *b32_hash = (uint8_t *)knot_dname_to_str(b->owner);
if (!b32_hash)
if (!b32_hash) {
return KNOT_ENOMEM;
}
int written = base32hex_decode(b32_hash, KNOT_NSEC3_HASH_B32_LENGTH,
rdata_hash, KNOT_NSEC3_HASH_LENGTH);
int32_t written = base32hex_decode(b32_hash, KNOT_NSEC3_HASH_B32_LENGTH,
rdata_hash, KNOT_NSEC3_HASH_LENGTH);
free(b32_hash);
......@@ -579,7 +679,7 @@ static int connect_nsec3_nodes(knot_node_t *a, knot_node_t *b, void *data)
* \brief Get zone apex as a string.
*/
static bool get_zone_apex_str(const knot_zone_contents_t *zone,
char **apex, size_t *apex_size)
char **apex, size_t *apex_size)
{
assert(zone);
assert(zone->apex);
......@@ -672,9 +772,6 @@ static int create_nsec3_nodes(const knot_zone_contents_t *zone, uint32_t ttl,
if (result != KNOT_EOK)
break;
// Caused invalid reads after updating zone w/ changesets
//node->nsec3_node = nsec3_node;
hattrie_iter_next(it);
}
......
......@@ -122,6 +122,40 @@ knot_changeset_t *knot_changesets_get_last(const knot_changesets_t *chs)
return (knot_changeset_t *)(TAIL(chs->sets));
}
const knot_rrset_t *knot_changeset_last_rr(const knot_changeset_t *ch,
knot_changeset_part_t part)
{
if (ch == NULL) {
return NULL;
}
if (part == KNOT_CHANGESET_ADD) {
knot_rr_ln_t *n = TAIL(ch->add);
return n ? n->rr : NULL;
} else if (part == KNOT_CHANGESET_REMOVE) {
knot_rr_ln_t *n = TAIL(ch->remove);
return n ? n->rr : NULL;
}
return NULL;
}
void knot_changeset_remove_last_rr(knot_changeset_t *ch,
knot_changeset_part_t part)
{
if (ch == NULL) {
return;
}
if (part == KNOT_CHANGESET_ADD) {
knot_rr_ln_t *n = TAIL(ch->add);
rem_node((node *)n);
} else if (part == KNOT_CHANGESET_REMOVE) {
knot_rr_ln_t *n = TAIL(ch->remove);
rem_node((node *)n);
}
}
int knot_changeset_add_rrset(knot_changeset_t *chgs, knot_rrset_t *rrset,
knot_changeset_part_t part)
{
......
......@@ -59,13 +59,13 @@ typedef struct knot_changeset {
/*----------------------------------------------------------------------------*/
/*! \brief Wrapper BIRD lists. Storing: RRSet. */
/*! \brief Wrapper for BIRD lists. Storing: RRSet. */
typedef struct knot_rr_ln {
node n; /*!< List node. */
knot_rrset_t *rr; /*!< Actual usable data. */
} knot_rr_ln_t;
/*! \brief Wrapper BIRD lists. Storing: Node. */
/*! \brief Wrapper for BIRD lists. Storing: Node. */
typedef struct knot_node_ln {
node n; /*!< List node. */
knot_node_t *node; /*!< Actual usable data. */
......@@ -173,6 +173,11 @@ knot_changeset_t *knot_changesets_create_changeset(knot_changesets_t *ch);
*/
knot_changeset_t *knot_changesets_get_last(const knot_changesets_t *ch);
const knot_rrset_t *knot_changeset_last_rr(const knot_changeset_t *ch,
knot_changeset_part_t part);
void knot_changeset_remove_last_rr(knot_changeset_t *ch,
knot_changeset_part_t part);
/*!
* \brief Add RRSet to changeset. RRSet is either inserted to 'add' or to
* 'remove' list. Will *not* try to merge with previous RRSets.
......@@ -209,7 +214,7 @@ int knot_changeset_add_rr(knot_changeset_t *chgs,
* \param part To which part we store SOA (from = REMOVE, add = TO)
*/
void knot_changeset_add_soa(knot_changeset_t *changeset, knot_rrset_t *soa,
knot_changeset_part_t part);
knot_changeset_part_t part);
/*!
* \brief Checks whether changeset is empty.
......
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