Commit 345c6f75 authored by Jan Kadlec's avatar Jan Kadlec

new_node: xfr and DDNS improvements.

- removing and adding already existing record
- leak solved, but need to move old a new data lists from
  zone_contents_t
parent 2f167e3b
......@@ -63,15 +63,13 @@ typedef int (*chain_iterate_create_cb)(knot_node_t *, knot_node_t *,
inline static void bitmap_add_node_rrsets(bitmap_t *bitmap,
const knot_node_t *node)
{
knot_rrset_t **node_rrsets = knot_node_create_rrsets(node);
for (int i = 0; i < node->rrset_count; i++) {
const knot_rrset_t *rr = node_rrsets[i];
if (rr->type != KNOT_RRTYPE_NSEC &&
rr->type != KNOT_RRTYPE_RRSIG) {
bitmap_add_type(bitmap, rr->type);
knot_rrset_t rr = RRSET_INIT_N(node, i);
if (rr.type != KNOT_RRTYPE_NSEC &&
rr.type != KNOT_RRTYPE_RRSIG) {
bitmap_add_type(bitmap, rr.type);
}
}
knot_node_free_created_rrsets(node, node_rrsets);
}
/*!
......
......@@ -401,10 +401,7 @@ static int zones_process_update_auth(struct query_data *qdata)
}
// Cleanup.
xfrin_cleanup_successful_update(NULL);
if (sec_chs) {
xfrin_cleanup_successful_update(NULL);
}
xfrin_cleanup_successful_update(old_contents);
// Free changesets, but not the data.
zones_free_merged_changesets(chgsets, sec_chs);
......
......@@ -1501,7 +1501,7 @@ int zones_store_and_apply_chgsets(knot_changesets_t *chs,
return KNOT_ERROR;
}
xfrin_cleanup_successful_update(NULL);
xfrin_cleanup_successful_update(zone->contents);
/* Free changesets, but not the data. */
knot_changesets_free(&chs);
......
......@@ -458,8 +458,7 @@ static int add_rr_to_chgset(const knot_rrset_t *rr, knot_changeset_t *changeset)
return knot_ddns_check_add_rr(changeset, rr_copy);
}
static int knot_ddns_check_remove_rr(knot_changeset_t *changeset,
knot_rrset_t *rr, size_t *apex_ns_rem)
static bool skip_record_removal(knot_changeset_t *changeset, knot_rrset_t *rr)
{
knot_rr_ln_t *rr_node = NULL;
WALK_LIST(rr_node, changeset->remove) {
......@@ -467,7 +466,7 @@ static int knot_ddns_check_remove_rr(knot_changeset_t *changeset,
if (knot_rrset_equal(rr, rrset, KNOT_RRSET_COMPARE_WHOLE)) {
// Removing the same RR, drop.
knot_rrset_free(&rr, NULL);
return KNOT_EOK;
return true;
}
}
......@@ -479,14 +478,11 @@ static int knot_ddns_check_remove_rr(knot_changeset_t *changeset,
knot_rrset_free(&rrset, NULL);
knot_rrset_free(&rr, NULL);
rem_node((node_t *)rr_node);
return KNOT_EOK;
return true;
}
}
if (apex_ns_rem) {
(*apex_ns_rem)++;
}
return knot_changeset_add_rrset(changeset, rr, KNOT_CHANGESET_REMOVE);
return false;
}
static int rem_rr_to_chgset(const knot_rrset_t *rr, knot_changeset_t *changeset,
......@@ -497,7 +493,14 @@ static int rem_rr_to_chgset(const knot_rrset_t *rr, knot_changeset_t *changeset,
return KNOT_ENOMEM;
}
return knot_ddns_check_remove_rr(changeset, rr_copy, apex_ns_rem);
if (skip_record_removal(changeset, rr_copy)) {
return KNOT_EOK;
}
if (apex_ns_rem) {
(*apex_ns_rem)++;
}
return knot_changeset_add_rrset(changeset, rr_copy, KNOT_CHANGESET_REMOVE);
}
static int rem_rrset_to_chgset(const knot_rrset_t *rrset,
......@@ -671,6 +674,40 @@ static int process_add_soa(const knot_node_t *node,
return add_rr_to_chgset(rr, changeset);
}
static bool node_contains_rr(const knot_node_t *node,
const knot_rrset_t *rr)
{
knot_rrset_t zone_rrset = RRSET_INIT(node, rr->type);
if (!knot_rrset_empty(&zone_rrset)) {
knot_rrset_t intersection;
int ret = knot_rrset_intersection(&zone_rrset, rr,
&intersection, NULL);
if (ret != KNOT_EOK) {
return false;
}
const bool contains = !knot_rrset_empty(&intersection);
knot_rrs_clear(&intersection.rrs, NULL);
return contains;
} else {
return false;
}
}
static void remove_rr_from_changeset(knot_changeset_t *changeset,
const knot_rrset_t *rr)
{
knot_rr_ln_t *rr_node = NULL;
node_t *nxt = NULL;
WALK_LIST_DELSAFE(rr_node, nxt, changeset->remove) {
knot_rrset_t *rrset = rr_node->rr;
if (knot_rrset_equal(rrset, rr, KNOT_RRSET_COMPARE_WHOLE)) {
knot_rrset_free(&rrset, NULL);
rem_node((node_t *)rr_node);
return;
}
}
}
static int process_add_normal(const knot_node_t *node,
const knot_rrset_t *rr,
knot_changeset_t *changeset)
......@@ -680,6 +717,11 @@ static int process_add_normal(const knot_node_t *node,
return KNOT_EOK;
}
if (node && node_contains_rr(node, rr)) {
remove_rr_from_changeset(changeset, rr);
return KNOT_EOK;
}
return add_rr_to_chgset(rr, changeset);
}
......@@ -719,16 +761,10 @@ static int process_remove(const knot_rrset_t *rr,
}
}
static int knot_ddns_final_soa_to_chgset(const knot_rrset_t *soa,
static int knot_ddns_final_soa_to_chgset(knot_rrset_t *soa,
knot_changeset_t *changeset)
{
knot_rrset_t *soa_copy = NULL;
int ret = knot_rrset_copy(soa, &soa_copy, NULL);
if (ret != KNOT_EOK) {
return ret;
}
knot_changeset_add_soa(changeset, soa_copy, KNOT_CHANGESET_ADD);
knot_changeset_add_soa(changeset, soa, KNOT_CHANGESET_ADD);
return KNOT_EOK;
}
......@@ -754,6 +790,30 @@ static int knot_ddns_process_rr(const knot_rrset_t *rr,
}
}
static bool skip_soa(const knot_rrset_t *rr, int64_t sn)
{
if (rr->type == KNOT_RRTYPE_SOA
&& (rr->rclass == KNOT_CLASS_NONE
|| rr->rclass == KNOT_CLASS_ANY
|| knot_serial_compare(knot_rrs_soa_serial(&rr->rrs),
sn) <= 0)) {
return true;
}
return false;
}
static uint16_t ret_to_rcode(int ret)
{
if (ret == KNOT_EMALF) {
return KNOT_RCODE_FORMERR;
} else if (ret == KNOT_EDENIED) {
return KNOT_RCODE_REFUSED;
} else {
return KNOT_RCODE_SERVFAIL;
}
}
int knot_ddns_process_update(knot_zone_contents_t *zone,
const knot_pkt_t *query,
knot_changeset_t *changeset,
......@@ -804,8 +864,6 @@ int knot_ddns_process_update(knot_zone_contents_t *zone,
/* Check if the entry is correct. */
ret = knot_ddns_check_update(rr, query, rcode);
if (ret != KNOT_EOK) {
dbg_ddns("Failed to check update RRSet:%s\n",
knot_strerror(ret));
return ret;
}
......@@ -818,36 +876,20 @@ int knot_ddns_process_update(knot_zone_contents_t *zone,
* be used.
*/
1 == 1; // multiple SOAs test
if (rr->type == KNOT_RRTYPE_SOA
&& (rr->rclass == KNOT_CLASS_NONE
|| rr->rclass == KNOT_CLASS_ANY
|| knot_serial_compare(knot_rrs_soa_serial(&rr->rrs),
sn) <= 0)) {
// This ignores also SOA removals
dbg_ddns_verb("Ignoring SOA...\n");
if (skip_soa(rr, sn)) {
continue;
}
dbg_ddns_verb("Processing RR %p...\n", rr);
ret = knot_ddns_process_rr(rr, zone, changeset, &apex_ns_removals);
if (ret != KNOT_EOK) {
dbg_ddns("Failed to process update RR:%s\n",
knot_strerror(ret));
if (ret == KNOT_EMALF) {
*rcode = KNOT_RCODE_FORMERR;
} else if (ret == KNOT_EDENIED) {
*rcode = KNOT_RCODE_REFUSED;
} else {
*rcode = KNOT_RCODE_SERVFAIL;
}
*rcode = ret_to_rcode(ret);
return ret;
}
// we need the RR copy, that's why this code is here
if (rr->type == KNOT_RRTYPE_SOA) {
int64_t sn_rr = knot_rrs_soa_serial(&rr->rrs);
dbg_ddns_verb("Replacing SOA. Old serial: %"PRId64", "
"new serial: %"PRId64"\n", sn_new, sn_rr);
assert(knot_serial_compare(sn_rr, sn) > 0);
sn_new = sn_rr;
soa_end = knot_rrset_cpy(rr, NULL);
......@@ -867,9 +909,7 @@ int knot_ddns_process_update(knot_zone_contents_t *zone,
/* If not set, create new SOA. */
ret = knot_rrset_copy(soa_begin, &soa_end, NULL);
if (ret != KNOT_EOK) {
dbg_ddns("Failed to copy ending SOA: %s\n",
knot_strerror(ret));
*rcode = KNOT_RCODE_SERVFAIL;
*rcode = ret_to_rcode(ret);
return ret;
}
knot_rrs_soa_serial_set(&soa_end->rrs, sn_new);
......
......@@ -635,6 +635,7 @@ void xfrin_cleanup_successful_update(knot_zone_contents_t *zone)
}
rrs_list_clear(&zone->old_data, NULL);
ptrlist_free(&zone->new_data, NULL);
}
/*----------------------------------------------------------------------------*/
......@@ -732,6 +733,7 @@ void xfrin_rollback_update(knot_zone_contents_t *old_contents,
knot_zone_contents_t **new_contents)
{
rrs_list_clear(&old_contents->new_data, NULL);
ptrlist_free(&old_contents->old_data, NULL);
xfrin_cleanup_failed_update(old_contents, new_contents);
}
......@@ -754,8 +756,8 @@ static int xfrin_replace_rrs_with_copy(knot_node_t *node,
// Add copied RRSet
ret = knot_node_add_rrset(node, &new_rr);
knot_rrs_clear(&new_rr.rrs, mm);
if (ret != KNOT_EOK) {
knot_rrs_clear(&new_rr.rrs, mm);
return ret;
}
......@@ -821,6 +823,7 @@ static int xfrin_apply_remove(knot_zone_contents_t *contents,
clear_new_rrs(node, rr->type);
return ret;
}
assert(removed->rrs.rr_count > 0);
knot_rrset_free(&removed, NULL);
if (rrset.rrs.rr_count > 0) {
......
......@@ -215,6 +215,7 @@ int xfrin_replace_rrset_in_node(knot_node_t *node,
knot_zone_contents_t *contents);
void xfrin_zone_contents_free(knot_zone_contents_t **contents);
void xfrin_cleanup_successful_update(knot_zone_contents_t *zone);
#endif /* _KNOTXFR_IN_H_ */
......
......@@ -678,8 +678,7 @@ void knot_node_free_rrsets(knot_node_t *node)
}
for (uint16_t i = 0; i < node->rrset_count; ++i) {
knot_rrs_clear(&node->rrs[i].rrs, NULL);
mm_free(NULL, node->rrs[i].additional);
rr_data_clear(&node->rrs[i], NULL);
}
}
......
......@@ -161,6 +161,9 @@ static int discover_additionals(struct rr_data *rr_data,
/* Create new additional nodes. */
uint16_t rdcount = rrs->rr_count;
if (rr_data->additional) {
free(rr_data->additional);
}
rr_data->additional = malloc(rdcount * sizeof(knot_node_t *));
if (rr_data->additional == NULL) {
ERR_ALLOC_FAILED;
......
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