diff --git a/src/knot/nameserver/update.c b/src/knot/nameserver/update.c index c0db3fa601f95becf34d4f692c808964be60a1dd..0891d24421374e4d9a4b279ce12a9cf1f6b6f213 100644 --- a/src/knot/nameserver/update.c +++ b/src/knot/nameserver/update.c @@ -279,7 +279,7 @@ static int zones_process_update_auth(struct query_data *qdata) sec_chs = knot_changesets_create(); sec_ch = knot_changesets_create_changeset(sec_chs); if (sec_chs == NULL || sec_ch == NULL) { - xfrin_rollback_update(old_contents, &new_contents); + xfrin_rollback_update(zone, old_contents, &new_contents); knot_changesets_free(&chgsets); free(msg); return KNOT_ENOMEM; @@ -311,7 +311,7 @@ static int zones_process_update_auth(struct query_data *qdata) if (ret != KNOT_EOK) { log_zone_error("%s: Failed to sign incoming update (%s)" "\n", msg, knot_strerror(ret)); - xfrin_rollback_update(old_contents, &new_contents); + xfrin_rollback_update(zone, old_contents, &new_contents); knot_changesets_free(&chgsets); knot_changesets_free(&sec_chs); free(msg); @@ -326,7 +326,7 @@ static int zones_process_update_auth(struct query_data *qdata) if (ret != KNOT_EOK) { log_zone_error("%s: Failed to save new entry to journal (%s)\n", msg, knot_strerror(ret)); - xfrin_rollback_update(old_contents, &new_contents); + xfrin_rollback_update(zone, old_contents, &new_contents); zones_free_merged_changesets(chgsets, sec_chs); free(msg); return ret; @@ -335,7 +335,7 @@ static int zones_process_update_auth(struct query_data *qdata) bool new_signatures = !knot_changeset_is_empty(sec_ch); // Apply DNSSEC changeset if (new_signatures) { - ret = xfrin_apply_changesets_dnssec_ddns(old_contents, + ret = xfrin_apply_changesets_dnssec_ddns(zone, old_contents, new_contents, sec_chs, chgsets); @@ -363,7 +363,7 @@ static int zones_process_update_auth(struct query_data *qdata) if (ret != KNOT_EOK) { zones_store_changesets_rollback(transaction); zones_free_merged_changesets(chgsets, sec_chs); - xfrin_rollback_update(old_contents, &new_contents); + xfrin_rollback_update(zone, old_contents, &new_contents); free(msg); return ret; } @@ -375,7 +375,7 @@ static int zones_process_update_auth(struct query_data *qdata) if (ret != KNOT_EOK) { log_zone_error("%s: Failed to commit new journal entry " "(%s).\n", msg, knot_strerror(ret)); - xfrin_rollback_update(old_contents, &new_contents); + xfrin_rollback_update(zone, old_contents, &new_contents); zones_free_merged_changesets(chgsets, sec_chs); free(msg); return ret; @@ -391,7 +391,7 @@ static int zones_process_update_auth(struct query_data *qdata) log_zone_error("%s: Failed to replace current zone (%s)\n", msg, knot_strerror(ret)); // Cleanup old and new contents - xfrin_rollback_update(old_contents, &new_contents); + xfrin_rollback_update(zone, old_contents, &new_contents); /* Free changesets, but not the data. */ zones_free_merged_changesets(chgsets, sec_chs); @@ -401,7 +401,7 @@ static int zones_process_update_auth(struct query_data *qdata) } // Cleanup. - xfrin_cleanup_successful_update(old_contents); + xfrin_cleanup_successful_update(zone); // 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 4db77baabda3ca63792045d0128bb8d004a5b922..55ee7c0860d395415ad6ab59b8d32cebdc995102 100644 --- a/src/knot/server/zones.c +++ b/src/knot/server/zones.c @@ -1478,7 +1478,7 @@ int zones_store_and_apply_chgsets(knot_changesets_t *chs, /* Commit transaction. */ ret = zones_store_changesets_commit(transaction); if (ret != KNOT_EOK) { - xfrin_rollback_update(zone->contents, new_contents); + xfrin_rollback_update(zone, zone->contents, new_contents); log_zone_error("%s Failed to commit stored changesets.\n", msgpref); knot_changesets_free(&chs); return ret; @@ -1494,14 +1494,14 @@ int zones_store_and_apply_chgsets(knot_changesets_t *chs, if (switch_ret != KNOT_EOK) { log_zone_error("%s Failed to replace current zone.\n", msgpref); // Cleanup old and new contents - xfrin_rollback_update(zone->contents, new_contents); + xfrin_rollback_update(zone, zone->contents, new_contents); /* Free changesets, but not the data. */ knot_changesets_free(&chs); return KNOT_ERROR; } - xfrin_cleanup_successful_update(zone->contents); + xfrin_cleanup_successful_update(zone); /* Free changesets, but not the data. */ knot_changesets_free(&chs); @@ -1924,7 +1924,7 @@ int zones_journal_apply(zone_t *zone) XFR_TYPE_IIN); rcu_read_lock(); if (apply_ret == KNOT_EOK) { - xfrin_cleanup_successful_update(NULL); + xfrin_cleanup_successful_update(zone); } else { log_zone_error("Failed to apply " "changesets to '%s' - Switch failed: " @@ -1933,7 +1933,8 @@ int zones_journal_apply(zone_t *zone) ret = KNOT_ERROR; // Cleanup old and new contents - xfrin_rollback_update(zone->contents, + xfrin_rollback_update(zone, + zone->contents, &contents); } } @@ -2015,7 +2016,8 @@ static int diff_after_load(zone_t *zone, zone_t *old_zone, if (*diff_chs != NULL) { assert(!zones_changesets_empty(*diff_chs)); /* Apply DNSSEC changeset to the new zone. */ - ret = xfrin_apply_changesets_directly(zone->contents, + ret = xfrin_apply_changesets_directly(zone, + zone->contents, *diff_chs); if (ret == KNOT_EOK) { @@ -2033,7 +2035,7 @@ static int diff_after_load(zone_t *zone, zone_t *old_zone, return ret; } - xfrin_cleanup_successful_update(NULL); + xfrin_cleanup_successful_update(zone); knot_changesets_free(diff_chs); assert(zone->conf->build_diffs); } @@ -2103,7 +2105,7 @@ static int store_chgsets_after_load(zone_t *old_zone, zone_t *zone, if (zone_changed) { assert(!old_zone || old_zone->contents != zone->contents); - ret = xfrin_apply_changesets_directly(zone->contents, + ret = xfrin_apply_changesets_directly(zone, zone->contents, diff_chs); if (ret == KNOT_EOK) { ret = xfrin_finalize_updated_zone( @@ -2127,7 +2129,7 @@ static int store_chgsets_after_load(zone_t *old_zone, zone_t *zone, return ret; } - xfrin_cleanup_successful_update(NULL); + xfrin_cleanup_successful_update(zone); } /* Commit transaction. */ @@ -2156,7 +2158,7 @@ static int store_chgsets_after_load(zone_t *old_zone, zone_t *zone, "switching zone (%s).\n", zone->conf->name, knot_strerror(ret)); // Cleanup old and new contents - xfrin_rollback_update(zone->contents, &new_contents); + xfrin_rollback_update(zone, zone->contents, &new_contents); return ret; } diff --git a/src/knot/updates/ddns.c b/src/knot/updates/ddns.c index efe534e2fde1e329f34ba45757dce88314bbd962..a52336343000b3b8207b278800efa23440083887 100644 --- a/src/knot/updates/ddns.c +++ b/src/knot/updates/ddns.c @@ -433,7 +433,7 @@ static bool skip_record_addition(knot_changeset_t *changeset, knot_rrset_t *rr) { knot_rr_ln_t *rr_node = NULL; - WALK_LIST(rr_node, changeset->remove) { + WALK_LIST(rr_node, changeset->add) { knot_rrset_t *rrset = rr_node->rr; if (should_replace(rr, rrset)) { knot_rrset_free(&rrset, NULL); @@ -795,6 +795,11 @@ static int knot_ddns_process_rr(const knot_rrset_t *rr, } } +/* + * Check if the record is SOA. If yes, check the SERIAL. + * If this record should cause the SOA to be replaced in the + * zone, use it as the ending SOA. + */ static bool skip_soa(const knot_rrset_t *rr, int64_t sn) { if (rr->type == KNOT_RRTYPE_SOA @@ -828,19 +833,11 @@ int knot_ddns_process_update(knot_zone_contents_t *zone, return KNOT_EINVAL; } - int ret = KNOT_EOK; - /* Copy base SOA RR. */ - knot_rrset_t *soa_begin = knot_node_create_rrset(knot_zone_contents_apex(zone), + knot_rrset_t *soa_begin = knot_node_create_rrset(zone->apex, KNOT_RRTYPE_SOA); knot_rrset_t *soa_end = NULL; - if (ret == KNOT_EOK) { - knot_changeset_add_soa(changeset, soa_begin, - KNOT_CHANGESET_REMOVE); - } else { - *rcode = KNOT_RCODE_SERVFAIL; - return ret; - } + knot_changeset_add_soa(changeset, soa_begin, KNOT_CHANGESET_REMOVE); /* Current SERIAL */ int64_t sn = knot_rrs_soa_serial(&soa_begin->rrs); @@ -852,48 +849,39 @@ int knot_ddns_process_update(knot_zone_contents_t *zone, assert(sn_new != KNOT_EINVAL); } else { *rcode = KNOT_RCODE_SERVFAIL; - return ret; + return KNOT_EINVAL; } /* Process all RRs the Authority (Update) section. */ - const knot_rrset_t *rr = NULL; - dbg_ddns("Processing UPDATE section.\n"); size_t apex_ns_removals = 0; const knot_pktsection_t *authority = knot_pkt_section(query, KNOT_AUTHORITY); - for (int i = 0; i < authority->count; ++i) { - - rr = &authority->rr[i]; + for (uint16_t i = 0; i < authority->count; ++i) { + const knot_rrset_t *rr = &authority->rr[i]; /* Check if the entry is correct. */ - ret = knot_ddns_check_update(rr, query, rcode); + int ret = knot_ddns_check_update(rr, query, rcode); if (ret != KNOT_EOK) { return ret; } - /* Check if the record is SOA. If yes, check the SERIAL. - * If this record should cause the SOA to be replaced in the - * zone, use it as the ending SOA. - * - * Also handle cases where there are multiple SOAs to be added - * in the same UPDATE. The one with the largest SERIAL should - * be used. - */ 1 == 1; // multiple SOAs test 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) { *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) { + // Using new SOA that came in the update + if (soa_end == NULL) { + knot_rrset_free(&soa_end, NULL); + } int64_t sn_rr = knot_rrs_soa_serial(&rr->rrs); assert(knot_serial_compare(sn_rr, sn) > 0); sn_new = sn_rr; @@ -904,23 +892,20 @@ int knot_ddns_process_update(knot_zone_contents_t *zone, } } - /* Ending SOA (not in the UPDATE) */ if (soa_end == NULL) { - // If the changeset is empty, do not process anything further + // No SOA in the update, create according to current policy if (knot_changeset_is_empty(changeset)) { + // No change, no new SOA return KNOT_EOK; } - /* If not set, create new SOA. */ - ret = knot_rrset_copy(soa_begin, &soa_end, NULL); - if (ret != KNOT_EOK) { - *rcode = ret_to_rcode(ret); - return ret; + soa_end = knot_rrset_cpy(soa_begin, NULL); + if (soa_end == NULL) { + *rcode = KNOT_RCODE_SERVFAIL; + return KNOT_ENOMEM; } knot_rrs_soa_serial_set(&soa_end->rrs, sn_new); } - ret = knot_ddns_final_soa_to_chgset(soa_end, changeset); - - return ret; + return knot_ddns_final_soa_to_chgset(soa_end, changeset); } diff --git a/src/knot/updates/xfr-in.c b/src/knot/updates/xfr-in.c index b287c500a6119d87dabb9bb4e9f39d493bcfbf69..511ba5ae32bdf4a76d2619ba4f42430bfb9fc78e 100644 --- a/src/knot/updates/xfr-in.c +++ b/src/knot/updates/xfr-in.c @@ -628,7 +628,7 @@ void xfrin_zone_contents_free(knot_zone_contents_t **contents) /*----------------------------------------------------------------------------*/ -void xfrin_cleanup_successful_update(knot_zone_contents_t *zone) +void xfrin_cleanup_successful_update(zone_t *zone) { if (zone == NULL) { return; @@ -636,6 +636,8 @@ void xfrin_cleanup_successful_update(knot_zone_contents_t *zone) rrs_list_clear(&zone->old_data, NULL); ptrlist_free(&zone->new_data, NULL); + init_list(&zone->new_data); + init_list(&zone->old_data); } /*----------------------------------------------------------------------------*/ @@ -729,11 +731,14 @@ static void xfrin_cleanup_failed_update(knot_zone_contents_t *old_contents, /*----------------------------------------------------------------------------*/ -void xfrin_rollback_update(knot_zone_contents_t *old_contents, +void xfrin_rollback_update(zone_t *zone, + 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); + rrs_list_clear(&zone->new_data, NULL); + ptrlist_free(&zone->old_data, NULL); + init_list(&zone->new_data); + init_list(&zone->old_data); xfrin_cleanup_failed_update(old_contents, new_contents); } @@ -937,8 +942,6 @@ static int xfrin_apply_changeset(list_t *old_rrs, list_t *new_rrs, return KNOT_ERROR; } - init_list(new_rrs); - init_list(old_rrs); int ret = xfrin_apply_remove(contents, chset, old_rrs, new_rrs); if (ret != KNOT_EOK) { return ret; @@ -1160,7 +1163,8 @@ int xfrin_finalize_updated_zone(knot_zone_contents_t *contents_copy, /*----------------------------------------------------------------------------*/ -int xfrin_apply_changesets_directly(knot_zone_contents_t *contents, +int xfrin_apply_changesets_directly(zone_t *zone, + knot_zone_contents_t *contents, knot_changesets_t *chsets) { if (contents == NULL || chsets == NULL) { @@ -1169,8 +1173,8 @@ int xfrin_apply_changesets_directly(knot_zone_contents_t *contents, knot_changeset_t *set = NULL; WALK_LIST(set, chsets->sets) { - int ret = xfrin_apply_changeset(&contents->old_data, - &contents->new_data, + int ret = xfrin_apply_changeset(&zone->old_data, + &zone->new_data, contents, set); if (ret != KNOT_EOK) { return ret; @@ -1183,12 +1187,13 @@ int xfrin_apply_changesets_directly(knot_zone_contents_t *contents, /*----------------------------------------------------------------------------*/ /* Post-DDNS application, no need to shallow copy. */ -int xfrin_apply_changesets_dnssec_ddns(knot_zone_contents_t *z_old, +int xfrin_apply_changesets_dnssec_ddns(zone_t *zone, + knot_zone_contents_t *z_old, knot_zone_contents_t *z_new, knot_changesets_t *sec_chsets, knot_changesets_t *chsets) { - if (z_old == NULL || z_new == NULL || + if (zone == NULL || z_old == NULL || z_new == NULL || sec_chsets == NULL || chsets == NULL) { return KNOT_EINVAL; } @@ -1197,10 +1202,10 @@ int xfrin_apply_changesets_dnssec_ddns(knot_zone_contents_t *z_old, knot_zone_contents_set_gen_old(z_new); /* Apply changes. */ - int ret = xfrin_apply_changesets_directly(z_new, + int ret = xfrin_apply_changesets_directly(zone, z_new, sec_chsets); if (ret != KNOT_EOK) { - xfrin_rollback_update(z_old, &z_new); + xfrin_rollback_update(zone, z_old, &z_new); dbg_xfrin("Failed to apply changesets to zone: " "%s\n", knot_strerror(ret)); return ret; @@ -1211,7 +1216,7 @@ int xfrin_apply_changesets_dnssec_ddns(knot_zone_contents_t *z_old, if (ret != KNOT_EOK) { dbg_xfrin("Failed to finalize updated zone: %s\n", knot_strerror(ret)); - xfrin_rollback_update(z_old, &z_new); + xfrin_rollback_update(zone, z_old, &z_new); return ret; } @@ -1254,12 +1259,12 @@ int xfrin_apply_changesets(zone_t *zone, old_contents->apex, contents_copy->apex); knot_changeset_t *set = NULL; WALK_LIST(set, chsets->sets) { - ret = xfrin_apply_changeset(&zone->contents->old_data, - &zone->contents->new_data, + ret = xfrin_apply_changeset(&zone->old_data, + &zone->new_data, contents_copy, set); if (ret != KNOT_EOK) { - xfrin_rollback_update(old_contents, - &contents_copy); + xfrin_rollback_update(zone, old_contents, + &contents_copy); dbg_xfrin("Failed to apply changesets to zone: " "%s\n", knot_strerror(ret)); return ret; @@ -1276,7 +1281,7 @@ int xfrin_apply_changesets(zone_t *zone, if (ret != KNOT_EOK) { dbg_xfrin("Failed to finalize updated zone: %s\n", knot_strerror(ret)); - xfrin_rollback_update(old_contents, &contents_copy); + xfrin_rollback_update(zone, old_contents, &contents_copy); return ret; } diff --git a/src/knot/updates/xfr-in.h b/src/knot/updates/xfr-in.h index 4f2425f7eca872a4dedc513cbdc25c4782a85a48..35651e95921c28f9fc1c7f242fe5558b2ca8745c 100644 --- a/src/knot/updates/xfr-in.h +++ b/src/knot/updates/xfr-in.h @@ -165,7 +165,7 @@ int xfrin_apply_changesets(zone_t *zone, * by the UPDATE-processing function. It uses new and old zones from this * operation. */ -int xfrin_apply_changesets_dnssec_ddns(knot_zone_contents_t *z_old, +int xfrin_apply_changesets_dnssec_ddns(zone_t *zone, knot_zone_contents_t *z_old, knot_zone_contents_t *z_new, knot_changesets_t *sec_chsets, knot_changesets_t *chsets); @@ -183,7 +183,7 @@ int xfrin_apply_changesets_dnssec_ddns(knot_zone_contents_t *z_old, * \retval KNOT_EINVAL if given one of the arguments is NULL. * \return Other error code if the application went wrong. */ -int xfrin_apply_changesets_directly(knot_zone_contents_t *contents, +int xfrin_apply_changesets_directly(zone_t *zone, knot_zone_contents_t *contents, knot_changesets_t *chsets); int xfrin_prepare_zone_copy(knot_zone_contents_t *old_contents, @@ -202,7 +202,7 @@ int xfrin_switch_zone(zone_t *zone, knot_zone_contents_t *new_contents, int transfer_type); -void xfrin_rollback_update(knot_zone_contents_t *old_contents, +void xfrin_rollback_update(zone_t *zone, knot_zone_contents_t *old_contents, knot_zone_contents_t **new_contents); int xfrin_copy_rrset(knot_node_t *node, uint16_t type, @@ -215,7 +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); +void xfrin_cleanup_successful_update(zone_t *zone); #endif /* _KNOTXFR_IN_H_ */ diff --git a/src/knot/zone/zone-contents.h b/src/knot/zone/zone-contents.h index ca953bde7a7f6f86b303325dbcbe96fcaad44112..fae0bb2f4fe792baf1346442c75aa82fc4cb121c 100644 --- a/src/knot/zone/zone-contents.h +++ b/src/knot/zone/zone-contents.h @@ -70,8 +70,6 @@ typedef struct knot_zone_contents_t { * - 0xx - ANY queries enabled */ uint8_t flags; - list_t old_data; - list_t new_data; } knot_zone_contents_t; /*!< \brief Helper linked list list for CNAME loop checking */ diff --git a/src/knot/zone/zone.c b/src/knot/zone/zone.c index 09f6ffa3363a77178e1635dc4e337b37da361192..025b9b7c11edd1eba659ed91f7836422a994f61d 100644 --- a/src/knot/zone/zone.c +++ b/src/knot/zone/zone.c @@ -212,6 +212,9 @@ zone_t* zone_new(conf_zone_t *conf) } } + init_list(&zone->old_data); + init_list(&zone->new_data); + return zone; } diff --git a/src/knot/zone/zone.h b/src/knot/zone/zone.h index dac7feed11bec03937c60ff98deedbda201af876..79a6d5aa43378878dafa7d6bcc76995eb2c340bc 100644 --- a/src/knot/zone/zone.h +++ b/src/knot/zone/zone.h @@ -95,6 +95,8 @@ typedef struct zone_t { /*! \brief Zone IXFR history. */ journal_t *ixfr_db; event_t *ixfr_dbsync; /*!< Syncing IXFR db to zonefile. */ + list_t old_data; + list_t new_data; } zone_t; /*----------------------------------------------------------------------------*/