Commit ab6aecc4 authored by Dominik Taborsky's avatar Dominik Taborsky Committed by Daniel Salzman

zone_update: add node and rrset-by-type removal, apply change to SOA as well,...

zone_update: add node and rrset-by-type removal, apply change to SOA as well, unittest it and cleanup DDNS a bit
parent 5f5e629d
......@@ -344,35 +344,6 @@ static int add_rr_to_chgset(const knot_rrset_t *rr,
return zone_update_add(update, rr);
}
/*!< \brief Adds RR into remove section of changeset if it is deemed worthy. */
static int rem_rr_to_chgset(const knot_rrset_t *rr,
zone_update_t *update)
{
return zone_update_remove(update, rr);
}
/*!< \brief Adds all RRs from RRSet into remove section of changeset. */
static int rem_rrset_to_chgset(const knot_rrset_t *rrset,
zone_update_t *update)
{
knot_rrset_t rr;
knot_rrset_init(&rr, rrset->owner, rrset->type, rrset->rclass);
for (uint16_t i = 0; i < rrset->rrs.rr_count; ++i) {
knot_rdata_t *rr_add = knot_rdataset_at(&rrset->rrs, i);
int ret = knot_rdataset_add(&rr.rrs, rr_add, NULL);
if (ret != KNOT_EOK) {
return ret;
}
ret = rem_rr_to_chgset(&rr, update);
knot_rdataset_clear(&rr.rrs, NULL);
if (ret != KNOT_EOK) {
return ret;
}
}
return KNOT_EOK;
}
/* ------------------------ RR processing logic ----------------------------- */
/* --------------------------- RR additions --------------------------------- */
......@@ -389,7 +360,7 @@ static int process_add_cname(const zone_node_t *node,
return KNOT_EOK;
}
int ret = rem_rr_to_chgset(&cname, update);
int ret = zone_update_remove(update, &cname);
if (ret != KNOT_EOK) {
return ret;
}
......@@ -526,7 +497,7 @@ static int process_rem_rr(const knot_rrset_t *rr,
return KNOT_EOK;
}
return rem_rr_to_chgset(rr, update);
return zone_update_remove(update, rr);
}
/*!< \brief Removes RRSet from zone. */
......@@ -556,7 +527,7 @@ static int process_rem_rrset(const knot_rrset_t *rrset,
}
knot_rrset_t to_remove = node_rrset(node, rrset->type);
return rem_rrset_to_chgset(&to_remove, update);
return zone_update_remove(update, &to_remove);
}
/*!< \brief Removes node from zone. */
......
......@@ -162,6 +162,35 @@ static const zone_node_t *get_synth_node(zone_update_t *update, const knot_dname
{
const zone_node_t *old_node =
zone_contents_find_node(update->zone->contents, dname);
if (old_node == update->zone->contents->apex && update->change.soa_to != NULL) {
/* We have an apex and a SOA change, make a copy and apply the change. */
zone_node_t *synth_node = node_deep_copy(old_node, &update->mm);
if (synth_node == NULL) {
return NULL;
}
/* Remove the old SOA */
knot_rdataset_t *from = node_rdataset(synth_node, KNOT_RRTYPE_SOA);
knot_rdataset_t *what = node_rdataset(old_node, KNOT_RRTYPE_SOA);
int ret = knot_rdataset_subtract(from, what, &update->mm);
if (ret != KNOT_EOK) {
node_free_rrsets(synth_node, &update->mm);
node_free(&synth_node, &update->mm);
return NULL;
}
/* Add the new SOA */
ret = node_add_rrset(synth_node, update->change.soa_to, &update->mm);
if (ret != KNOT_EOK) {
node_free_rrsets(synth_node, &update->mm);
node_free(&synth_node, &update->mm);
return NULL;
}
old_node = synth_node;
}
const zone_node_t *add_node =
zone_contents_find_node(update->change.add, dname);
const zone_node_t *rem_node =
......@@ -294,17 +323,19 @@ const knot_rdataset_t *zone_update_to(zone_update_t *update)
void zone_update_clear(zone_update_t *update)
{
if (update != NULL) {
if (update->flags & UPDATE_INCREMENTAL) {
/* Revert any changes on error, do nothing on success. */
update_rollback(&update->a_ctx);
changeset_clear(&update->change);
} else if (update->flags & UPDATE_FULL) {
zone_contents_deep_free(&update->new_cont);
}
mp_delete(update->mm.ctx);
memset(update, 0, sizeof(*update));
if (update == NULL) {
return;
}
if (update->flags & UPDATE_INCREMENTAL) {
/* Revert any changes on error, do nothing on success. */
update_rollback(&update->a_ctx);
changeset_clear(&update->change);
} else if (update->flags & UPDATE_FULL) {
zone_contents_deep_free(&update->new_cont);
}
mp_delete(update->mm.ctx);
memset(update, 0, sizeof(*update));
}
int zone_update_add(zone_update_t *update, const knot_rrset_t *rrset)
......@@ -333,12 +364,118 @@ int zone_update_remove(zone_update_t *update, const knot_rrset_t *rrset)
return changeset_rem_rrset(&update->change, rrset, CHANGESET_CHECK);
} else if (update->flags & UPDATE_FULL) {
zone_node_t *n = NULL;
return zone_contents_remove_rr(update->new_cont, rrset, &n);
knot_rrset_t *rrs_copy = knot_rrset_copy(rrset, &update->mm);
int ret = zone_contents_remove_rr(update->new_cont, rrs_copy, &n);
knot_rrset_free(&rrs_copy, &update->mm);
return ret;
} else {
return KNOT_EINVAL;
}
}
int zone_update_remove_rrset(zone_update_t *update, knot_dname_t *owner, uint16_t type)
{
if (update == NULL || owner == NULL) {
return KNOT_EINVAL;
}
if (update->flags & UPDATE_INCREMENTAL) {
/* Remove the RRSet from the original node */
const zone_node_t *node = zone_contents_find_node(update->zone->contents, owner);
if (node != NULL) {
knot_rrset_t rrset = node_rrset(node, type);
int ret = changeset_rem_rrset(&update->change, &rrset, CHANGESET_CHECK);
if (ret != KNOT_EOK) {
return ret;
}
}
/* Remove the RRSet from the additions in the changeset */
const zone_node_t *additions = zone_contents_find_node(update->change.add, owner);
if (additions != NULL) {
knot_rrset_t rrset = node_rrset(additions, type);
int ret = changeset_rem_rrset(&update->change, &rrset, CHANGESET_CHECK);
if (ret != KNOT_EOK) {
return ret;
}
}
if (node == NULL && additions == NULL) {
return KNOT_ENONODE;
}
} else if (update->flags & UPDATE_FULL) {
/* Remove the RRSet from the non-synthesized new node */
const zone_node_t *node = zone_contents_find_node(update->new_cont, owner);
if (node == NULL) {
return KNOT_ENONODE;
}
knot_rrset_t rrset = node_rrset(node, type);
int ret = zone_update_remove(update, &rrset);
if (ret != KNOT_EOK) {
return ret;
}
}
return KNOT_EOK;
}
int zone_update_remove_node(zone_update_t *update, const knot_dname_t *owner)
{
if (update == NULL || owner == NULL) {
return KNOT_EINVAL;
}
if (update->flags & UPDATE_INCREMENTAL) {
/* Remove all RRSets from the original node */
const zone_node_t *node = zone_contents_find_node(update->zone->contents, owner);
if (node != NULL) {
size_t rrset_count = node->rrset_count;
for (int i = 0; i < rrset_count; ++i) {
knot_rrset_t rrset = node_rrset_at(node, rrset_count - 1 - i);
int ret = changeset_rem_rrset(&update->change, &rrset, CHANGESET_CHECK);
if (ret != KNOT_EOK) {
return ret;
}
}
}
/* Remove all RRSets from the additions in the changeset */
const zone_node_t *additions = zone_contents_find_node(update->change.add, owner);
if (additions != NULL) {
size_t rrset_count = additions->rrset_count;
for (int i = 0; i < rrset_count; ++i) {
knot_rrset_t rrset = node_rrset_at(additions, rrset_count - 1 - i);
int ret = changeset_rem_rrset(&update->change, &rrset, CHANGESET_CHECK);
if (ret != KNOT_EOK) {
return ret;
}
}
}
if (node == NULL && additions == NULL) {
return KNOT_ENONODE;
}
} else if (update->flags & UPDATE_FULL) {
/* Remove all RRSets from the non-synthesized new node */
const zone_node_t *node = zone_contents_find_node(update->new_cont, owner);
if (node == NULL) {
return KNOT_ENONODE;
}
size_t rrset_count = node->rrset_count;
for (int i = 0; i < rrset_count; ++i) {
knot_rrset_t rrset = node_rrset_at(node, rrset_count - 1 - i);
int ret = zone_update_remove(update, &rrset);
if (ret != KNOT_EOK) {
return ret;
}
}
}
return KNOT_EOK;
}
static bool apex_rr_changed(const zone_node_t *old_apex,
const zone_node_t *new_apex,
uint16_t type)
......
......@@ -137,6 +137,7 @@ void zone_update_clear(zone_update_t *update);
* in the zone_update iterator(s).
*
* \param update Zone update.
* \param rrset RRSet to add.
*
* \return KNOT_E*
*/
......@@ -150,11 +151,41 @@ int zone_update_add(zone_update_t *update, const knot_rrset_t *rrset);
* in the zone_update iterator(s).
*
* \param update Zone update.
* \param rrset RRSet to remove.
*
* \return KNOT_E*
*/
int zone_update_remove(zone_update_t *update, const knot_rrset_t *rrset);
/*!
* \brief Removes a whole RRSet of specified type from the zone.
*
* \warning Do not edit the zone_update when any iterator is active. Any
* zone_update modifications will invalidate the trie iterators
* in the zone_update iterator(s).
*
* \param update Zone update.
* \param owner Node name to remove.
* \param type RRSet type to remove.
*
* \return KNOT_E*
*/
int zone_update_remove_rrset(zone_update_t *update, knot_dname_t *owner, uint16_t type);
/*!
* \brief Removes a whole node from the zone.
*
* \warning Do not edit the zone_update when any iterator is active. Any
* zone_update modifications will invalidate the trie iterators
* in the zone_update iterator(s).
*
* \param update Zone update.
* \param owner Node name to remove.
*
* \return KNOT_E*
*/
int zone_update_remove_node(zone_update_t *update, const knot_dname_t *owner);
/*!
* \brief Commits all changes to the zone, signs it, saves changes to journal.
*
......
......@@ -28,8 +28,10 @@
static const char *zone_str1 = "test. 600 IN SOA ns.test. m.test. 1 900 300 4800 900 \n";
static const char *zone_str2 = "test. IN TXT \"test\"\n";
static const char *add_str = "test. IN TXT \"test2\"\n";
static const char *del_str = "test. IN TXT \"test\"\n";
static const char *add_str = "test. IN TXT \"test2\"\n";
static const char *del_str = "test. IN TXT \"test\"\n";
static const char *node_str1 = "node.test. IN TXT \"abc\"\n";
static const char *node_str2 = "node.test. IN TXT \"def\"\n";
knot_rrset_t rrset;
......@@ -37,16 +39,18 @@ knot_rrset_t rrset;
static bool node_contains_rr(const zone_node_t *node,
const knot_rrset_t *rr)
{
const knot_rdataset_t *zone_rrs = node_rdataset(node, rr->type);
if (zone_rrs) {
assert(rr->rrs.rr_count == 1);
const bool compare_ttls = false;
return knot_rdataset_member(zone_rrs,
knot_rdataset_at(&rr->rrs, 0),
compare_ttls);
} else {
return false;
}
const knot_rdataset_t *zone_rrs = node_rdataset(node, rr->type);
if (zone_rrs) {
for (size_t i = 0; i < rr->rrs.rr_count; ++i) {
if (!knot_rdataset_member(zone_rrs, knot_rdataset_at(&rr->rrs, i), false)) {
return false;
}
}
return true;
} else {
return false;
}
}
static void process_rr(zs_scanner_t *scanner)
......@@ -62,6 +66,7 @@ static void process_rr(zs_scanner_t *scanner)
void test_full(zone_t *zone, zs_scanner_t *sc)
{
zone_update_t update;
/* Init update */
int ret = zone_update_init(&update, zone, UPDATE_FULL);
ok(ret == KNOT_EOK, "zone update: init full");
......@@ -70,6 +75,7 @@ void test_full(zone_t *zone, zs_scanner_t *sc)
assert(0);
}
/* First addition */
ret = zone_update_add(&update, &rrset);
knot_rdataset_clear(&rrset.rrs, NULL);
ok(ret == KNOT_EOK, "full zone update: first addition");
......@@ -79,23 +85,52 @@ void test_full(zone_t *zone, zs_scanner_t *sc)
assert(0);
}
/* Second addition */
ret = zone_update_add(&update, &rrset);
zone_node_t *node = zone_contents_find_node_for_rr(update.new_cont, &rrset);
zone_node_t *node = (zone_node_t *) zone_update_get_node(&update, rrset.owner);
bool rrset_present = node_contains_rr(node, &rrset);
ok(ret == KNOT_EOK && rrset_present, "full zone update: second addition");
/* Removal */
ret = zone_update_remove(&update, &rrset);
node = zone_contents_find_node_for_rr(update.new_cont, &rrset);
node = (zone_node_t *) zone_update_get_node(&update, rrset.owner);
rrset_present = node_contains_rr(node, &rrset);
ok(ret == KNOT_EOK && !rrset_present, "full zone update: removal");
/* Last addition */
ret = zone_update_add(&update, &rrset);
node = zone_contents_find_node_for_rr(update.new_cont, &rrset);
node = (zone_node_t *) zone_update_get_node(&update, rrset.owner);
rrset_present = node_contains_rr(node, &rrset);
ok(ret == KNOT_EOK && rrset_present, "full zone update: last addition");
knot_rdataset_clear(&rrset.rrs, NULL);
/* Prepare node removal */
if (zs_set_input_string(sc, node_str1, strlen(node_str1)) != 0 ||
zs_parse_all(sc) != 0) {
assert(0);
}
ret = zone_update_add(&update, &rrset);
assert(ret == KNOT_EOK);
knot_rdataset_clear(&rrset.rrs, NULL);
if (zs_set_input_string(sc, node_str2, strlen(node_str2)) != 0 ||
zs_parse_all(sc) != 0) {
assert(0);
}
ret = zone_update_add(&update, &rrset);
assert(ret == KNOT_EOK);
knot_rdataset_clear(&rrset.rrs, NULL);
knot_dname_t *rem_node_name = knot_dname_from_str_alloc("node.test");
node = (zone_node_t *) zone_update_get_node(&update, rem_node_name);
assert(node && node_rdataset(node, KNOT_RRTYPE_TXT)->rr_count == 2);
/* Node removal */
ret = zone_update_remove_node(&update, rem_node_name);
node = (zone_node_t *) zone_update_get_node(&update, rem_node_name);
ok(ret == KNOT_EOK && !node, "full zone update: node removal");
knot_dname_free(&rem_node_name, NULL);
/* Test iteration */
zone_update_iter_t it;
ret = zone_update_iter(&it, &update);
ok(ret == KNOT_EOK, "full zone update: init iter");
......@@ -108,7 +143,6 @@ void test_full(zone_t *zone, zs_scanner_t *sc)
}
rrset_present = node_contains_rr(iter_node, &rrset);
ok(rrset_present, "full zone update: first iter value check");
knot_rdataset_clear(&rrset.rrs, NULL);
if (zs_set_input_string(sc, zone_str2, strlen(zone_str2)) != 0 ||
......@@ -117,6 +151,7 @@ void test_full(zone_t *zone, zs_scanner_t *sc)
}
rrset_present = node_contains_rr(iter_node, &rrset);
ok(rrset_present, "full zone update: second iter value check");
knot_rdataset_clear(&rrset.rrs, NULL);
ret = zone_update_iter_next(&it);
ok(ret == KNOT_EOK, "full zone update: iter next");
......@@ -126,6 +161,16 @@ void test_full(zone_t *zone, zs_scanner_t *sc)
zone_update_iter_finish(&it);
/* Re-add a node for later incremental functionality test */
if (zs_set_input_string(sc, node_str1, strlen(node_str1)) != 0 ||
zs_parse_all(sc) != 0) {
assert(0);
}
ret = zone_update_add(&update, &rrset);
assert(ret == KNOT_EOK);
knot_rdataset_clear(&rrset.rrs, NULL);
/* Commit */
ret = zone_update_commit(conf(), &update);
node = zone_contents_find_node_for_rr(zone->contents, &rrset);
rrset_present = node_contains_rr(node, &rrset);
......@@ -138,6 +183,7 @@ void test_incremental(zone_t *zone, zs_scanner_t *sc)
{
int ret = KNOT_EOK;
/* Init update */
zone_update_t update;
zone_update_init(&update, zone, UPDATE_INCREMENTAL);
ok(update.zone == zone && changeset_empty(&update.change) && update.mm.alloc,
......@@ -152,6 +198,7 @@ void test_incremental(zone_t *zone, zs_scanner_t *sc)
assert(0);
}
/* Addition */
ret = zone_update_add(&update, &rrset);
knot_rdataset_clear(&rrset.rrs, NULL);
ok(ret == KNOT_EOK, "incremental zone update: addition");
......@@ -164,17 +211,43 @@ void test_incremental(zone_t *zone, zs_scanner_t *sc)
zs_parse_all(sc) != 0) {
assert(0);
}
/* Removal */
ret = zone_update_remove(&update, &rrset);
ok(ret == KNOT_EOK, "incremental zone update: removal");
knot_rdataset_clear(&rrset.rrs, NULL);
synth_node = zone_update_get_apex(&update);
ok(synth_node && node_rdataset(synth_node, KNOT_RRTYPE_TXT)->rr_count == 1,
"incremental zone update: del change");
/* Prepare node removal */
if (zs_set_input_string(sc, node_str2, strlen(node_str2)) != 0 ||
zs_parse_all(sc) != 0) {
assert(0);
}
ret = zone_update_add(&update, &rrset);
assert(ret == KNOT_EOK);
knot_rdataset_clear(&rrset.rrs, NULL);
knot_dname_t *rem_node_name = knot_dname_from_str_alloc("node.test");
synth_node = zone_update_get_node(&update, rem_node_name);
assert(synth_node && node_rdataset(synth_node, KNOT_RRTYPE_TXT)->rr_count == 2);
/* Node Removal */
ret = zone_update_remove_node(&update, rem_node_name);
synth_node = zone_update_get_node(&update, rem_node_name);
ok(ret == KNOT_EOK && synth_node && node_empty(synth_node),
"incremental zone update: node removal");
knot_dname_free(&rem_node_name, NULL);
/* Test iteration */
zone_update_iter_t it;
ret = zone_update_iter(&it, &update);
ok(ret == KNOT_EOK, "incremental zone update: init iter");
if (zs_set_input_string(sc, del_str, strlen(del_str)) != 0 ||
zs_parse_all(sc) != 0) {
assert(0);
}
const zone_node_t *iter_node = zone_update_iter_val(&it);
assert(iter_node);
......@@ -189,7 +262,10 @@ void test_incremental(zone_t *zone, zs_scanner_t *sc)
}
rrset_present = node_contains_rr(iter_node, &rrset);
ok(rrset_present, "incremental zone update: second iter value check");
knot_rdataset_clear(&rrset.rrs, NULL);
ret = zone_update_iter_next(&it);
ok(ret == KNOT_EOK, "incremental zone update: iter next");
ret = zone_update_iter_next(&it);
ok(ret == KNOT_EOK, "incremental zone update: iter next");
......@@ -198,6 +274,7 @@ void test_incremental(zone_t *zone, zs_scanner_t *sc)
zone_update_iter_finish(&it);
/* Commit */
ret = zone_update_commit(conf(), &update);
iter_node = zone_contents_find_node_for_rr(zone->contents, &rrset);
rrset_present = node_contains_rr(iter_node, &rrset);
......@@ -226,7 +303,7 @@ int main(int argc, char *argv[])
assert(apex);
zone_t *zone = zone_new(apex);
/* Parse initial node */
/* Setup zscanner */
zs_scanner_t sc;
if (zs_init(&sc, "test.", KNOT_CLASS_IN, 3600) != 0 ||
zs_set_processing(&sc, process_rr, NULL, NULL) != 0) {
......
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