diff --git a/src/knot/dnssec/nsec-chain.h b/src/knot/dnssec/nsec-chain.h index b9cf6a3e1a117ebcdb12941a96a877baffb6ed5e..23b6ac984b24e1103efed3f12385d3ef53a14aef 100644 --- a/src/knot/dnssec/nsec-chain.h +++ b/src/knot/dnssec/nsec-chain.h @@ -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); } /*! diff --git a/src/knot/nameserver/update.c b/src/knot/nameserver/update.c index 21ff05d8e3931f5982bc020e8d5edf1b7954d14b..c0db3fa601f95becf34d4f692c808964be60a1dd 100644 --- a/src/knot/nameserver/update.c +++ b/src/knot/nameserver/update.c @@ -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); diff --git a/src/knot/server/zones.c b/src/knot/server/zones.c index bb66ac232e55c19229221dbb6c0fc0d9d17ec5f8..4db77baabda3ca63792045d0128bb8d004a5b922 100644 --- a/src/knot/server/zones.c +++ b/src/knot/server/zones.c @@ -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); diff --git a/src/knot/updates/ddns.c b/src/knot/updates/ddns.c index 5e396e5f5328853e1510fd2f6de2c30e37f339e3..c4ea97b905f81669ac8b79b13f580e7558f6c5eb 100644 --- a/src/knot/updates/ddns.c +++ b/src/knot/updates/ddns.c @@ -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); diff --git a/src/knot/updates/xfr-in.c b/src/knot/updates/xfr-in.c index 8ff77bd8851ba01b846cf3540d91a659d32313a1..b287c500a6119d87dabb9bb4e9f39d493bcfbf69 100644 --- a/src/knot/updates/xfr-in.c +++ b/src/knot/updates/xfr-in.c @@ -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) { diff --git a/src/knot/updates/xfr-in.h b/src/knot/updates/xfr-in.h index 226c53ea3541d4d2c6c8a82dda33ec938521044a..4f2425f7eca872a4dedc513cbdc25c4782a85a48 100644 --- a/src/knot/updates/xfr-in.h +++ b/src/knot/updates/xfr-in.h @@ -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_ */ diff --git a/src/knot/zone/node.c b/src/knot/zone/node.c index fcfd66dd6462118a2ca3968ce4a1a994895ca788..9266a0b59088cce60deaa54f1ee9fa33d3119a5f 100644 --- a/src/knot/zone/node.c +++ b/src/knot/zone/node.c @@ -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); } } diff --git a/src/knot/zone/zone-contents.c b/src/knot/zone/zone-contents.c index 5e6c424db4b7bc64fc066d51225b3c24dbfeee4e..f6e169c4a124c52e4e5b5dfad3e736551b96e83a 100644 --- a/src/knot/zone/zone-contents.c +++ b/src/knot/zone/zone-contents.c @@ -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;