summaryrefslogtreecommitdiff
path: root/src/libknot/updates/ddns.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libknot/updates/ddns.c')
-rw-r--r--src/libknot/updates/ddns.c691
1 files changed, 369 insertions, 322 deletions
diff --git a/src/libknot/updates/ddns.c b/src/libknot/updates/ddns.c
index 79b28fb..7f4f14f 100644
--- a/src/libknot/updates/ddns.c
+++ b/src/libknot/updates/ddns.c
@@ -14,16 +14,21 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <assert.h>
+#include <stdlib.h>
+#include <inttypes.h>
#include "updates/ddns.h"
#include "updates/changesets.h"
#include "util/debug.h"
#include "packet/packet.h"
+#include "common.h"
#include "consts.h"
#include "common/mempattern.h"
#include "nameserver/name-server.h" // ns_serial_compare() - TODO: extract
#include "updates/xfr-in.h"
+#include "common/descriptor.h"
/*----------------------------------------------------------------------------*/
// Copied from XFR - maybe extract somewhere else
@@ -37,7 +42,7 @@ static int knot_ddns_prereq_check_rrsets(knot_rrset_t ***rrsets,
if (ret < 0) {
return KNOT_ENOMEM;
}
-
+
*rrsets = (knot_rrset_t**)arr;
return KNOT_EOK;
@@ -55,7 +60,7 @@ static int knot_ddns_prereq_check_dnames(knot_dname_t ***dnames,
if (ret < 0) {
return KNOT_ENOMEM;
}
-
+
*dnames = (knot_dname_t**)arr;
return KNOT_EOK;
@@ -70,10 +75,9 @@ static int knot_ddns_add_prereq_rrset(const knot_rrset_t *rrset,
// check if such RRSet is not already there and merge if needed
int ret;
for (int i = 0; i < *count; ++i) {
- if (knot_rrset_match(rrset, (*rrsets)[i],
+ if (knot_rrset_equal(rrset, (*rrsets)[i],
KNOT_RRSET_COMPARE_HEADER) == 1) {
- ret = knot_rrset_merge((void **)&((*rrsets)[i]),
- (void **)&rrset);
+ ret = knot_rrset_merge((*rrsets)[i], rrset);
if (ret != KNOT_EOK) {
return ret;
} else {
@@ -132,13 +136,15 @@ static int knot_ddns_add_prereq(knot_ddns_prereq_t *prereqs,
assert(rrset != NULL);
if (knot_rrset_ttl(rrset) != 0) {
+ dbg_ddns("ddns: add_prereq: Wrong TTL.\n");
return KNOT_EMALF;
}
int ret;
if (knot_rrset_class(rrset) == KNOT_CLASS_ANY) {
- if (knot_rrset_rdata(rrset) != NULL) {
+ if (knot_rrset_rdata_rr_count(rrset)) {
+ dbg_ddns("ddns: add_prereq: Extra data\n");
return KNOT_EMALF;
}
if (knot_rrset_type(rrset) == KNOT_RRTYPE_ANY) {
@@ -153,7 +159,8 @@ static int knot_ddns_add_prereq(knot_ddns_prereq_t *prereqs,
&prereqs->exist_allocd);
}
} else if (knot_rrset_class(rrset) == KNOT_CLASS_NONE) {
- if (knot_rrset_rdata(rrset) != NULL) {
+ if (knot_rrset_rdata_rr_count(rrset)) {
+ dbg_ddns("ddns: add_prereq: Extra data\n");
return KNOT_EMALF;
}
if (knot_rrset_type(rrset) == KNOT_RRTYPE_ANY) {
@@ -173,6 +180,7 @@ static int knot_ddns_add_prereq(knot_ddns_prereq_t *prereqs,
&prereqs->exist_full_count,
&prereqs->exist_full_allocd);
} else {
+ dbg_ddns("ddns: add_prereq: Bad class.\n");
return KNOT_EMALF;
}
@@ -202,8 +210,8 @@ static int knot_ddns_check_remove_rr(knot_changeset_t *changeset,
&changeset->add_count, i);
dbg_ddns_detail("Removed RRSet from "
"chgset:\n");
- knot_rrset_dump(remove, 0);
- knot_rrset_deep_free(&remove, 1, 1, 1);
+ knot_rrset_dump(remove);
+ knot_rrset_deep_free(&remove, 1, 1);
}
} else if (knot_rrset_type(rr)
== knot_rrset_type(changeset->add[i])){
@@ -213,15 +221,14 @@ static int knot_ddns_check_remove_rr(knot_changeset_t *changeset,
assert(knot_rrset_class(rr) == KNOT_CLASS_NONE);
// Removing specific RR from a RRSet
- knot_rdata_t *rdata = knot_rrset_remove_rdata(
- changeset->add[i],
- knot_rrset_rdata(rr));
-
- dbg_ddns_detail("Removed RR from chgset: \n");
- knot_rdata_dump(rdata, knot_rrset_type(rr), 0);
+ int ret =
+ knot_rrset_remove_rr_using_rrset_del(changeset->add[i], rr);
+ if (ret != KNOT_EOK) {
+ dbg_ddns("ddns: Could not remove RDATA from RRSet (%s).\n",
+ knot_strerror(ret));
+ return ret;
+ }
- knot_rdata_deep_free(&rdata,
- knot_rrset_type(changeset->add[i]), 1);
// if the RRSet is empty, remove from changeset
if (knot_rrset_rdata_rr_count(changeset->add[i])
== 0) {
@@ -231,7 +238,7 @@ static int knot_ddns_check_remove_rr(knot_changeset_t *changeset,
&changeset->add_count, i);
dbg_ddns_detail("RRSet empty, removing."
"\n");
- knot_rrset_deep_free(&remove, 1, 1, 1);
+ knot_rrset_deep_free(&remove, 1, 1);
}
}
}
@@ -257,7 +264,7 @@ static int knot_ddns_add_update(knot_changeset_t *changeset,
* copy.
*/
*rrset_copy = NULL;
- ret = knot_rrset_deep_copy(rrset, rrset_copy, 0);
+ ret = knot_rrset_deep_copy(rrset, rrset_copy, 1);
if (ret != KNOT_EOK) {
return ret;
}
@@ -286,7 +293,7 @@ static int knot_ddns_add_update(knot_changeset_t *changeset,
ret = knot_ddns_check_remove_rr(changeset, *rrset_copy);
if (ret != KNOT_EOK) {
- knot_rrset_deep_free(rrset_copy, 1, 1, 1);
+ knot_rrset_deep_free(rrset_copy, 1, 1);
return ret;
}
@@ -307,7 +314,7 @@ static int knot_ddns_check_exist(const knot_zone_contents_t *zone,
assert(zone != NULL);
assert(rrset != NULL);
assert(rcode != NULL);
- assert(knot_rrset_rdata(rrset) == NULL);
+ assert(knot_rrset_rdata_rr_count(rrset) == 0);
assert(knot_rrset_type(rrset) != KNOT_RRTYPE_ANY);
assert(knot_rrset_ttl(rrset) == 0);
assert(knot_rrset_class(rrset) == KNOT_CLASS_ANY);
@@ -334,13 +341,13 @@ static int knot_ddns_check_exist(const knot_zone_contents_t *zone,
/*----------------------------------------------------------------------------*/
static int knot_ddns_check_exist_full(const knot_zone_contents_t *zone,
- const knot_rrset_t *rrset,
+ const knot_rrset_t *rrset,
knot_rcode_t *rcode)
{
assert(zone != NULL);
assert(rrset != NULL);
assert(rcode != NULL);
- assert(knot_rrset_rdata(rrset) == NULL);
+ assert(knot_rrset_rdata_rr_count(rrset) == 0);
assert(knot_rrset_type(rrset) != KNOT_RRTYPE_ANY);
assert(knot_rrset_ttl(rrset) == 0);
assert(knot_rrset_class(rrset) == KNOT_CLASS_ANY);
@@ -367,7 +374,7 @@ static int knot_ddns_check_exist_full(const knot_zone_contents_t *zone,
assert(knot_rrset_type(found) == knot_rrset_type(rrset));
assert(knot_dname_compare(knot_rrset_owner(found),
knot_rrset_owner(rrset)) == 0);
- if (knot_rrset_compare_rdata(found, rrset) <= 0) {
+ if (knot_rrset_rdata_equal(found, rrset) <= 0) {
*rcode = KNOT_RCODE_NXRRSET;
return KNOT_EPREREQ;
}
@@ -379,13 +386,13 @@ static int knot_ddns_check_exist_full(const knot_zone_contents_t *zone,
/*----------------------------------------------------------------------------*/
static int knot_ddns_check_not_exist(const knot_zone_contents_t *zone,
- const knot_rrset_t *rrset,
+ const knot_rrset_t *rrset,
knot_rcode_t *rcode)
{
assert(zone != NULL);
assert(rrset != NULL);
assert(rcode != NULL);
- assert(knot_rrset_rdata(rrset) == NULL);
+ assert(knot_rrset_rdata_rr_count(rrset) == 0);
assert(knot_rrset_type(rrset) != KNOT_RRTYPE_ANY);
assert(knot_rrset_ttl(rrset) == 0);
assert(knot_rrset_class(rrset) == KNOT_CLASS_NONE);
@@ -404,7 +411,7 @@ static int knot_ddns_check_not_exist(const knot_zone_contents_t *zone,
} else if (knot_node_rrset(node, knot_rrset_type(rrset)) == NULL) {
return KNOT_EOK;
}
-
+
/* RDATA is always empty for simple RRset checks. */
*rcode = KNOT_RCODE_YXRRSET;
@@ -414,7 +421,7 @@ static int knot_ddns_check_not_exist(const knot_zone_contents_t *zone,
/*----------------------------------------------------------------------------*/
static int knot_ddns_check_in_use(const knot_zone_contents_t *zone,
- const knot_dname_t *dname,
+ const knot_dname_t *dname,
knot_rcode_t *rcode)
{
assert(zone != NULL);
@@ -444,7 +451,7 @@ static int knot_ddns_check_in_use(const knot_zone_contents_t *zone,
/*----------------------------------------------------------------------------*/
static int knot_ddns_check_not_in_use(const knot_zone_contents_t *zone,
- const knot_dname_t *dname,
+ const knot_dname_t *dname,
knot_rcode_t *rcode)
{
assert(zone != NULL);
@@ -474,7 +481,7 @@ static int knot_ddns_check_not_in_use(const knot_zone_contents_t *zone,
/* API functions */
/*----------------------------------------------------------------------------*/
-int knot_ddns_check_zone(const knot_zone_contents_t *zone,
+int knot_ddns_check_zone(const knot_zone_contents_t *zone,
const knot_packet_t *query, knot_rcode_t *rcode)
{
if (zone == NULL || query == NULL || rcode == NULL) {
@@ -511,7 +518,7 @@ int knot_ddns_process_prereqs(const knot_packet_t *query,
if (query == NULL || prereqs == NULL || rcode == NULL) {
return KNOT_EINVAL;
}
-
+
dbg_ddns("Processing prerequisities.\n");
// allocate space for the prerequisities
@@ -523,6 +530,8 @@ int knot_ddns_process_prereqs(const knot_packet_t *query,
for (int i = 0; i < knot_packet_answer_rrset_count(query); ++i) {
// we must copy the RRSets, because all those stored in the
// packet will be destroyed
+ dbg_ddns_detail("Creating prereqs from following RRSet:\n");
+ knot_rrset_dump(knot_packet_answer_rrset(query, i));
ret = knot_ddns_add_prereq(*prereqs,
knot_packet_answer_rrset(query, i),
knot_packet_qclass(query));
@@ -545,7 +554,7 @@ int knot_ddns_check_prereqs(const knot_zone_contents_t *zone,
knot_ddns_prereq_t **prereqs, knot_rcode_t *rcode)
{
int i, ret;
-
+
dbg_ddns("Checking 'exist' prerequisities.\n");
for (i = 0; i < (*prereqs)->exist_count; ++i) {
@@ -599,7 +608,7 @@ int knot_ddns_check_prereqs(const knot_zone_contents_t *zone,
/*----------------------------------------------------------------------------*/
static int knot_ddns_check_update(const knot_rrset_t *rrset,
- const knot_packet_t *query,
+ const knot_packet_t *query,
knot_rcode_t *rcode)
{
/* Accept both subdomain and dname match. */
@@ -618,7 +627,7 @@ static int knot_ddns_check_update(const knot_rrset_t *rrset,
return KNOT_EMALF;
}
} else if (knot_rrset_class(rrset) == KNOT_CLASS_ANY) {
- if (knot_rrset_rdata(rrset) != NULL
+ if (knot_rrset_rdata_rr_count(rrset)
|| (knot_rrtype_is_metatype(knot_rrset_type(rrset))
&& knot_rrset_type(rrset) != KNOT_RRTYPE_ANY)) {
*rcode = KNOT_RCODE_FORMERR;
@@ -658,7 +667,7 @@ int knot_ddns_process_update(const knot_zone_contents_t *zone,
KNOT_RRTYPE_SOA);
knot_rrset_t *soa_begin = NULL;
knot_rrset_t *soa_end = NULL;
- ret = knot_rrset_deep_copy(soa, &soa_begin, 0);
+ ret = knot_rrset_deep_copy(soa, &soa_begin, 1);
if (ret == KNOT_EOK) {
knot_changeset_store_soa(&changeset->soa_from,
&changeset->serial_from, soa_begin);
@@ -668,7 +677,7 @@ int knot_ddns_process_update(const knot_zone_contents_t *zone,
}
/* Current SERIAL */
- int64_t sn = knot_rdata_soa_serial(knot_rrset_rdata(soa_begin));
+ int64_t sn = knot_rrset_rdata_soa_serial(soa_begin);
int64_t sn_new;
/* Incremented SERIAL
* We must set it now to be able to compare SERIAL from SOAs in the
@@ -721,10 +730,9 @@ int knot_ddns_process_update(const knot_zone_contents_t *zone,
* RRSet. This should be handled somehow.
*/
if (knot_rrset_type(rrset) == KNOT_RRTYPE_SOA
- && ns_serial_compare(knot_rdata_soa_serial(
- knot_rrset_rdata(rrset)),
+ && ns_serial_compare(knot_rrset_rdata_soa_serial(rrset),
sn_new) > 0) {
- sn_new = knot_rdata_soa_serial(knot_rrset_rdata(rrset));
+ sn_new = knot_rrset_rdata_soa_serial(rrset);
soa_end = (knot_rrset_t *)rrset_copy;
}
}
@@ -734,8 +742,12 @@ int knot_ddns_process_update(const knot_zone_contents_t *zone,
/* If not set */
assert(sn_new == (uint32_t)sn + 1);
ret = knot_rrset_deep_copy(soa, &soa_end, 1);
- knot_rdata_t *rd = knot_rrset_get_rdata(soa_end);
- knot_rdata_soa_serial_set(rd, sn_new);
+ if (ret != KNOT_EOK) {
+ dbg_ddns("ddns: Could not copy SOA RRSet (%s).\n ",
+ knot_strerror(ret));
+ return ret;
+ }
+ knot_rrset_rdata_soa_serial_set(soa_end, sn_new);
}
knot_changeset_store_soa(&changeset->soa_to,
@@ -754,17 +766,17 @@ void knot_ddns_prereqs_free(knot_ddns_prereq_t **prereq)
int i;
for (i = 0; i < (*prereq)->exist_count; ++i) {
- knot_rrset_deep_free(&(*prereq)->exist[i], 1, 1, 1);
+ knot_rrset_deep_free(&(*prereq)->exist[i], 1, 1);
}
free((*prereq)->exist);
for (i = 0; i < (*prereq)->exist_full_count; ++i) {
- knot_rrset_deep_free(&(*prereq)->exist_full[i], 1, 1, 1);
+ knot_rrset_deep_free(&(*prereq)->exist_full[i], 1, 1);
}
free((*prereq)->exist_full);
for (i = 0; i < (*prereq)->not_exist_count; ++i) {
- knot_rrset_deep_free(&(*prereq)->not_exist[i], 1, 1, 1);
+ knot_rrset_deep_free(&(*prereq)->not_exist[i], 1, 1);
}
free((*prereq)->not_exist);
@@ -788,7 +800,7 @@ void knot_ddns_prereqs_free(knot_ddns_prereq_t **prereq)
static int knot_ddns_check_remove_rr2(knot_changeset_t *changeset,
const knot_dname_t *owner,
- uint16_t type, const knot_rdata_t *rdata,
+ const knot_rrset_t *rr,
knot_rrset_t ***removed,
size_t *removed_count)
{
@@ -800,6 +812,7 @@ static int knot_ddns_check_remove_rr2(knot_changeset_t *changeset,
*removed = (knot_rrset_t **)malloc(changeset->add_count
* sizeof(knot_rrset_t *));
if (*removed == NULL) {
+ ERR_ALLOC_FAILED;
return KNOT_ENOMEM;
}
@@ -814,27 +827,30 @@ static int knot_ddns_check_remove_rr2(knot_changeset_t *changeset,
dbg_ddns_verb("Removing possible redundant RRs from changeset.\n");
for (int i = 0; i < changeset->add_count; ++i) {
// Removing RR(s) from this owner
- if (knot_dname_compare(knot_rrset_owner(changeset->add[i]),
- owner) == 0) {
+dbg_ddns_exec_detail(
+ char *name = knot_dname_to_str(changeset->add[i]->owner);
+ dbg_ddns_detail("ddns: remove_rr2: Removing RR of type=%u owned by %s\n",
+ knot_rrset_type(changeset->add[i]), name);
+ free(name);
+);
+ if (knot_dname_compare_non_canon(knot_rrset_owner(changeset->add[i]),
+ owner) == 0) {
// Removing one or all RRSets
- if (rdata == NULL
- && (type == knot_rrset_type(changeset->add[i])
- || type == KNOT_RRTYPE_ANY)) {
+ if ((knot_rrset_rdata_rr_count(rr) == 0)
+ && (knot_rrset_type(rr) == knot_rrset_type(changeset->add[i])
+ || knot_rrset_type(rr) == KNOT_RRTYPE_ANY)) {
dbg_ddns_detail("Removing one or all RRSets\n");
- remove = knot_changeset_remove_rr(
- changeset->add,
- &changeset->add_count, i);
- } else if (type == knot_rrset_type(changeset->add[i])) {
+ remove = knot_changeset_remove_rr(
+ changeset->add,
+ &changeset->add_count, i);
+ } else if (knot_rrset_type(rr) ==
+ knot_rrset_type(changeset->add[i])) {
// Removing specific RR
- assert(rdata != NULL);
-
- knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(type);
+ assert(knot_rrset_rdata_rr_count(rr) != 0);
// We must check if the RDATA match
- if (knot_rdata_compare(rdata,
- knot_rrset_rdata(changeset->add[i]),
- desc->wireformat)) {
+ if (knot_rrset_rdata_equal(rr,
+ changeset->add[i])) {
remove = knot_changeset_remove_rr(
changeset->add,
&changeset->add_count, i);
@@ -842,7 +858,7 @@ static int knot_ddns_check_remove_rr2(knot_changeset_t *changeset,
}
dbg_ddns_detail("Removed RRSet from chgset:\n");
- knot_rrset_dump(remove, 0);
+ knot_rrset_dump(remove);
(*removed)[(*removed_count)++] = remove;
}
}
@@ -861,19 +877,19 @@ static void knot_ddns_check_add_rr(knot_changeset_t *changeset,
assert(removed != NULL);
*removed = NULL;
-
+
dbg_ddns_verb("Removing possible redundant RRs from changeset.\n");
for (int i = 0; i < changeset->remove_count; ++i) {
- /* Just check exact match, the changeset contains only
+ /* Just check exact match, the changeset contains only
* whole RRs that have been removed.
*/
- if (knot_rrset_match(rr, changeset->remove[i],
+ if (knot_rrset_equal(rr, changeset->remove[i],
KNOT_RRSET_COMPARE_WHOLE) == 1) {
*removed = knot_changeset_remove_rr(
changeset->remove,
&changeset->remove_count, i);
dbg_ddns_detail("Removed RRSet from chgset:\n");
- knot_rrset_dump(*removed, 0);
+ knot_rrset_dump(*removed);
break;
}
}
@@ -887,8 +903,8 @@ static int knot_ddns_rr_is_nsec3(const knot_rrset_t *rr)
if ((knot_rrset_type(rr) == KNOT_RRTYPE_NSEC3)
|| (knot_rrset_type(rr) == KNOT_RRTYPE_RRSIG
- && knot_rrset_rdata(rr)
- && knot_rdata_rrsig_type_covered(knot_rrset_rdata(rr))
+ && knot_rrset_rdata_rr_count(rr)
+ && knot_rrset_rdata_rrsig_type_covered(rr)
== KNOT_RRTYPE_NSEC3))
{
dbg_ddns_detail("This is NSEC3-related RRSet.\n");
@@ -917,9 +933,9 @@ static knot_node_t *knot_ddns_add_new_node(knot_zone_contents_t *zone,
// insert the node into zone structures and create parents if
// necessary
if (is_nsec3) {
- ret = knot_zone_contents_add_nsec3_node(zone, node, 1, 0, 1);
+ ret = knot_zone_contents_add_nsec3_node(zone, node, 1, 0);
} else {
- ret = knot_zone_contents_add_node(zone, node, 1, 0, 1);
+ ret = knot_zone_contents_add_node(zone, node, 1, 0);
}
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to add new node to zone contents.\n");
@@ -961,7 +977,7 @@ static knot_node_t *knot_ddns_get_node(knot_zone_contents_t *zone,
/*----------------------------------------------------------------------------*/
-static int knot_ddns_process_add_cname(knot_node_t *node,
+static int knot_ddns_process_add_cname(knot_node_t *node,
const knot_rrset_t *rr,
knot_changeset_t *changeset,
knot_changes_t *changes)
@@ -970,29 +986,29 @@ static int knot_ddns_process_add_cname(knot_node_t *node,
assert(rr != NULL);
assert(changeset != NULL);
assert(changes != NULL);
-
+
dbg_ddns_detail("Adding CNAME RR.\n");
-
+
int ret = 0;
-
+
/* Get the current CNAME RR from the node. */
knot_rrset_t *removed = knot_node_get_rrset(node, KNOT_RRTYPE_CNAME);
-
+
if (removed != NULL) {
/* If they are identical, ignore. */
- if (knot_rrset_match(removed, rr, KNOT_RRSET_COMPARE_WHOLE)
+ if (knot_rrset_equal(removed, rr, KNOT_RRSET_COMPARE_WHOLE)
== 1) {
dbg_ddns_verb("CNAME identical to one in the node.\n");
return 1;
}
-
+
/*! \note
* Together with the removed CNAME we remove also its RRSIGs as
* they would not be valid for the new CNAME anyway.
*
* \todo Document!!
*/
-
+
/* b) Store it to 'changes', together with its RRSIGs. */
ret = knot_changes_add_old_rrsets(&removed, 1, changes, 1);
if (ret != KNOT_EOK) {
@@ -1002,41 +1018,40 @@ static int knot_ddns_process_add_cname(knot_node_t *node,
}
/* c) And remove it from the node. */
- (void)knot_node_remove_rrset(node, KNOT_RRTYPE_CNAME);
-
+ UNUSED(knot_node_remove_rrset(node, KNOT_RRTYPE_CNAME));
+
/* d) Check if this CNAME was not previously added by
- * the UPDATE. If yes, remove it from the ADD
+ * the UPDATE. If yes, remove it from the ADD
* section and do not add it to the REMOVE section.
*/
knot_rrset_t **from_chgset = NULL;
size_t from_chgset_count = 0;
ret = knot_ddns_check_remove_rr2(
changeset, knot_rrset_owner(removed),
- KNOT_RRTYPE_CNAME, knot_rrset_rdata(removed),
- &from_chgset, &from_chgset_count);
+ removed, &from_chgset, &from_chgset_count);
if (ret != KNOT_EOK) {
dbg_ddns("Failed to remove possible redundant "
- "RRs from ADD section: %s.\n",
+ "RRs from ADD section: %s.\n",
knot_strerror(ret));
free(from_chgset);
return ret;
}
-
+
assert(from_chgset_count <= 1);
-
+
if (from_chgset_count == 1) {
/* Just delete the RRSet. */
- knot_rrset_deep_free(&(from_chgset[0]), 1, 1, 1);
+ knot_rrset_deep_free(&(from_chgset[0]), 1, 1);
/* Okay, &(from_chgset[0]) is basically equal to just
* from_chgset, but it's more clear this way that we are
* deleting the first RRSet in the array ;-)
*/
} else {
- /* Otherwise copy the removed CNAME and add it
+ /* Otherwise copy the removed CNAME and add it
* to the REMOVE section.
*/
knot_rrset_t *removed_copy;
- ret = knot_rrset_deep_copy(removed,
+ ret = knot_rrset_deep_copy(removed,
&removed_copy, 1);
if (ret != KNOT_EOK) {
dbg_ddns("Failed to copy removed RRSet:"
@@ -1044,15 +1059,15 @@ static int knot_ddns_process_add_cname(knot_node_t *node,
free(from_chgset);
return ret;
}
-
+
ret = knot_changeset_add_rrset(
&changeset->remove,
&changeset->remove_count,
&changeset->remove_allocated,
removed_copy);
if (ret != KNOT_EOK) {
- knot_rrset_deep_free(&removed_copy,
- 1, 1, 1);
+ knot_rrset_deep_free(&removed_copy,
+ 1, 1);
dbg_ddns("Failed to add removed CNAME "
"to changeset: %s\n",
knot_strerror(ret));
@@ -1065,50 +1080,48 @@ static int knot_ddns_process_add_cname(knot_node_t *node,
/* 2) Other occupied node => ignore. */
return 1;
}
-
+
return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
-static int knot_ddns_process_add_soa(knot_node_t *node,
+static int knot_ddns_process_add_soa(knot_node_t *node,
const knot_rrset_t *rr,
knot_changes_t *changes)
{
assert(node != NULL);
assert(rr != NULL);
assert(changes != NULL);
-
+
dbg_ddns_detail("Adding SOA RR.\n");
-
+
int ret = 0;
-
+
/*
- * Just remove the SOA from the node, together with its RRSIGs.
+ * Just remove the SOA from the node, together with its RRSIGs.
* Adding the RR is done in the caller function. Note that only SOA
* with larger SERIAL than the current one will get to these functions,
* so we don't have to check the SERIALS again. But an assert won't
* hurt.
*/
-
+
/* Get the current SOA RR from the node. */
knot_rrset_t *removed = knot_node_get_rrset(node, KNOT_RRTYPE_SOA);
-
+
if (removed != NULL) {
dbg_ddns_detail("Found SOA in the node.\n");
/* If they are identical, ignore. */
- if (knot_rrset_match(removed, rr, KNOT_RRSET_COMPARE_WHOLE)
+ if (knot_rrset_equal(removed, rr, KNOT_RRSET_COMPARE_WHOLE)
== 1) {
dbg_ddns_detail("Old and new SOA identical.\n");
return 1;
}
-
+
/* Check that the serial is indeed larger than the current one*/
- assert(ns_serial_compare(knot_rdata_soa_serial(
- knot_rrset_rdata(removed)),
- knot_rdata_soa_serial(
- knot_rrset_rdata(rr))) < 0);
-
+ assert(ns_serial_compare(knot_rrset_rdata_soa_serial(removed),
+ knot_rrset_rdata_soa_serial(rr)) < 0);
+
/* 1) Store it to 'changes', together with its RRSIGs. */
ret = knot_changes_add_old_rrsets(
&removed, 1, changes, 1);
@@ -1119,15 +1132,15 @@ static int knot_ddns_process_add_soa(knot_node_t *node,
}
/* 2) And remove it from the node. */
- (void)knot_node_remove_rrset(node, KNOT_RRTYPE_SOA);
-
+ UNUSED(knot_node_remove_rrset(node, KNOT_RRTYPE_SOA));
+
/* No changeset processing needed in this case. */
} else {
dbg_ddns_detail("No SOA in node, ignoring.\n");
/* If there is no SOA in the node, ignore. */
return 1;
}
-
+
return KNOT_EOK;
}
@@ -1139,40 +1152,40 @@ static int knot_ddns_add_rr_new_normal(knot_node_t *node, knot_rrset_t *rr_copy,
assert(node != NULL);
assert(rr_copy != NULL);
assert(changes != NULL);
-
+
dbg_ddns_verb("Adding normal RR.\n");
-
+
/* Add the RRSet to 'changes'. */
int ret = knot_changes_add_new_rrsets(&rr_copy, 1, changes, 1);
if (ret != KNOT_EOK) {
- knot_rrset_deep_free(&rr_copy, 1, 1, 1);
+ knot_rrset_deep_free(&rr_copy, 1, 1);
dbg_ddns("Failed to store copy of the added RR: "
"%s\n", knot_strerror(ret));
return ret;
}
-
+
/* Add the RRSet to the node. */
- ret = knot_node_add_rrset(node, rr_copy, 0);
+ ret = knot_node_add_rrset_no_merge(node, rr_copy);
if (ret != KNOT_EOK) {
dbg_ddns("Failed to add RR to node: %s\n", knot_strerror(ret));
return ret;
}
-
+
return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
static int knot_ddns_add_rr_new_rrsig(knot_node_t *node, knot_rrset_t *rr_copy,
- knot_changes_t *changes,
+ knot_changes_t *changes,
uint16_t type_covered)
{
assert(node != NULL);
assert(rr_copy != NULL);
assert(changes != NULL);
-
+
dbg_ddns_verb("Adding RRSIG RR.\n");
-
+
/* Create RRSet to be covered by the RRSIG. */
knot_rrset_t *covered_rrset = knot_rrset_new(
knot_rrset_get_owner(rr_copy), type_covered,
@@ -1181,47 +1194,47 @@ static int knot_ddns_add_rr_new_rrsig(knot_node_t *node, knot_rrset_t *rr_copy,
if (covered_rrset == NULL) {
dbg_ddns("Failed to create RRSet to be covered"
" by the UPDATE RRSIG RR.\n");
- knot_rrset_deep_free(&rr_copy, 1, 1, 1);
+ knot_rrset_deep_free(&rr_copy, 1, 1);
return KNOT_ENOMEM;
}
-
+
/* Add the RRSet to the node. */
- int ret = knot_node_add_rrset(node, covered_rrset, 0);
+ int ret = knot_node_add_rrset_no_merge(node, covered_rrset);
if (ret != KNOT_EOK) {
dbg_ddns("Failed to add the RRSet to be covered to the node: %s"
".\n", knot_strerror(ret));
- knot_rrset_deep_free(&rr_copy, 1, 1, 1);
- knot_rrset_deep_free(&covered_rrset, 1, 1, 1);
+ knot_rrset_deep_free(&rr_copy, 1, 1);
+ knot_rrset_deep_free(&covered_rrset, 1, 1);
return KNOT_ENOMEM;
}
-
+
/* Add the RRSet to 'changes'. */
ret = knot_changes_add_new_rrsets(&covered_rrset, 1, changes, 0);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to add new RRSet (covered) to list: %s.\n",
knot_strerror(ret));
- knot_rrset_deep_free(&rr_copy, 1, 1, 1);
- knot_rrset_deep_free(&covered_rrset, 1, 1, 1);
+ knot_rrset_deep_free(&rr_copy, 1, 1);
+ knot_rrset_deep_free(&covered_rrset, 1, 1);
return ret;
}
/* Add the RRSIG RRSet to 'changes'. */
ret = knot_changes_add_new_rrsets(&rr_copy, 1, changes, 1);
if (ret != KNOT_EOK) {
- knot_rrset_deep_free(&rr_copy, 1, 1, 1);
+ knot_rrset_deep_free(&rr_copy, 1, 1);
dbg_ddns("Failed to store copy of the added RRSIG: %s\n",
knot_strerror(ret));
return ret;
}
-
+
/* Add the RRSIG RRSet to the covered RRSet. */
- ret = knot_rrset_add_rrsigs(covered_rrset, rr_copy,
+ ret = knot_rrset_add_rrsigs(covered_rrset, rr_copy,
KNOT_RRSET_DUPL_SKIP);
if (ret != KNOT_EOK) {
dbg_ddns("Failed to add RRSIG RR to the covered RRSet.\n");
return ret;
}
-
+
return KNOT_EOK;
}
@@ -1233,42 +1246,44 @@ static int knot_ddns_add_rr_merge_normal(knot_rrset_t *node_rrset_copy,
assert(node_rrset_copy != NULL);
assert(rr_copy != NULL);
assert(*rr_copy != NULL);
-
+
dbg_ddns_verb("Merging normal RR to existing RRSet.\n");
-
- /* In case the RRSet is empty (and only remained there because
- * of the RRSIGs) it may happen that the TTL may be different
- * than that of he new RRs. Update the TTL according to the
+
+ /* In case the RRSet is empty (and only remained there because
+ * of the RRSIGs) it may happen that the TTL may be different
+ * than that of he new RRs. Update the TTL according to the
* first RR.
- */
- if (knot_rrset_rdata(node_rrset_copy) == NULL
- && knot_rrset_ttl(node_rrset_copy)
+ */
+ if (knot_rrset_rdata_rr_count(node_rrset_copy) == 0
+ && knot_rrset_ttl(node_rrset_copy)
!= knot_rrset_ttl(*rr_copy)) {
- knot_rrset_set_ttl(node_rrset_copy,
+ knot_rrset_set_ttl(node_rrset_copy,
knot_rrset_ttl(*rr_copy));
}
int rdata_in_copy = knot_rrset_rdata_rr_count(*rr_copy);
- int ret = knot_rrset_merge_no_dupl((void **)&node_rrset_copy,
- (void **)rr_copy);
+ int merged, deleted_rrs;
+ int ret = knot_rrset_merge_no_dupl(node_rrset_copy, *rr_copy, &merged,
+ &deleted_rrs);
dbg_ddns_detail("Merge returned: %d\n", ret);
- if (ret < 0) {
+ if (ret != KNOT_EOK) {
dbg_ddns("Failed to merge UPDATE RR to node RRSet: %s."
"\n", knot_strerror(ret));
return ret;
}
- knot_rrset_free(rr_copy);
+ knot_rrset_deep_free(rr_copy, 1, 0);
+
- if (rdata_in_copy == ret) {
+ if (rdata_in_copy == deleted_rrs) {
/* All RDATA have been removed, because they were duplicates
* or there were none (0). In general this means, that no
* change was made.
*/
return 1;
}
-
+
return KNOT_EOK;
}
@@ -1282,12 +1297,12 @@ static int knot_ddns_add_rr_merge_rrsig(knot_rrset_t *node_rrset_copy,
assert(rr_copy != NULL);
assert(*rr_copy != NULL);
assert(changes != NULL);
-
+
dbg_ddns_verb("Adding RRSIG RR to existing RRSet.\n");
-
+
knot_rrset_t *rrsigs_old = knot_rrset_get_rrsigs(node_rrset_copy);
int ret = 0;
-
+
if (rrsigs_old != NULL) {
/* If there is an RRSIG RRSet already, copy it too. */
knot_rrset_t *rrsigs_copy = NULL;
@@ -1298,33 +1313,34 @@ static int knot_ddns_add_rr_merge_rrsig(knot_rrset_t *node_rrset_copy,
"%s\n", knot_strerror(ret));
return ret;
}
-
+
/* Replace the RRSIGs by the copy. */
ret = knot_rrset_set_rrsigs(node_rrset_copy, rrsigs_copy);
if (ret != KNOT_EOK) {
dbg_ddns("Failed to replace RRSIGs in "
- "the RRSet: %s\n",
+ "the RRSet: %s\n",
knot_strerror(ret));
return ret;
}
-
+
/* Merge the UPDATE RR to the copied RRSIG
* RRSet.
*/
dbg_ddns_detail("Merging RRSIG to the one in the RRSet.\n");
int rdata_in_copy = knot_rrset_rdata_rr_count(*rr_copy);
- ret = knot_rrset_merge_no_dupl(
- (void **)&rrsigs_copy, (void **)rr_copy);
+ int merged, deleted_rrs;
+ ret = knot_rrset_merge_no_dupl(rrsigs_copy, *rr_copy, &merged,
+ &deleted_rrs);
if (ret < 0) {
dbg_xfrin("Failed to merge UPDATE RRSIG to copy: %s.\n",
knot_strerror(ret));
return KNOT_ERROR;
}
-
- knot_rrset_free(rr_copy);
+ knot_rrset_deep_free(rr_copy, 1, 0);
+
- if (rdata_in_copy == ret) {
+ if (rdata_in_copy == deleted_rrs) {
/* All RDATA have been removed, because they were
* duplicates or there were none (0). In general this
* means, that no change was made.
@@ -1342,7 +1358,7 @@ static int knot_ddns_add_rr_merge_rrsig(knot_rrset_t *node_rrset_copy,
knot_strerror(ret));
return ret;
}
-
+
/* Add the RRSet to the covered RRSet. */
ret = knot_rrset_add_rrsigs(node_rrset_copy, *rr_copy,
KNOT_RRSET_DUPL_SKIP);
@@ -1352,7 +1368,7 @@ static int knot_ddns_add_rr_merge_rrsig(knot_rrset_t *node_rrset_copy,
return ret;
}
}
-
+
return KNOT_EOK;
}
@@ -1371,7 +1387,7 @@ static int knot_ddns_add_rr(knot_node_t *node, const knot_rrset_t *rr,
assert(rr != NULL);
assert(changes != NULL);
assert(rr_copy != NULL);
-
+
/* Copy the RRSet from the packet. */
//knot_rrset_t *rr_copy;
int ret = knot_rrset_deep_copy(rr, rr_copy, 1);
@@ -1379,45 +1395,46 @@ static int knot_ddns_add_rr(knot_node_t *node, const knot_rrset_t *rr,
dbg_ddns("Failed to copy RR: %s\n", knot_strerror(ret));
return ret;
}
-
+
uint16_t type = knot_rrset_type(rr);
- uint16_t type_covered = (type == KNOT_RRTYPE_RRSIG)
- ? knot_rdata_rrsig_type_covered(knot_rrset_rdata(rr))
+ uint16_t type_covered = (type == KNOT_RRTYPE_RRSIG)
+ ? knot_rrset_rdata_rrsig_type_covered(rr)
: type;
-
+
/* If the RR belongs to a RRSet already present in the node, we must
* take this RRSet from the node, copy it, and merge this RR into it.
*
* This code is more or less copied from xfr-in.c.
*/
knot_rrset_t *node_rrset_copy = NULL;
- ret = xfrin_copy_rrset(node, type_covered, &node_rrset_copy, changes,
+ ret = xfrin_copy_rrset(node, type_covered, &node_rrset_copy, changes,
0);
-
+
if (node_rrset_copy == NULL) {
/* No such RRSet in the node. Add the whole UPDATE RRSet. */
dbg_ddns_detail("Adding whole UPDATE RR to the zone.\n");
if (type_covered != type) {
/* Adding RRSIG. */
- ret = knot_ddns_add_rr_new_rrsig(node, *rr_copy,
+ ret = knot_ddns_add_rr_new_rrsig(node, *rr_copy,
changes, type_covered);
} else {
- ret = knot_ddns_add_rr_new_normal(node, *rr_copy,
+ ret = knot_ddns_add_rr_new_normal(node, *rr_copy,
changes);
}
if (ret != KNOT_EOK) {
dbg_ddns("Failed to add new RR to node.\n");
return ret;
}
+ dbg_ddns_detail("RRSet added successfully.\n");
} else {
/* We have copied the RRSet from the node. */
dbg_ddns_exec_detail(
dbg_ddns_detail("Merging RR to an existing RRSet.\n");
- knot_rrset_dump(node_rrset_copy, 1);
+ knot_rrset_dump(node_rrset_copy);
dbg_ddns_detail("New RR:\n");
- knot_rrset_dump(*rr_copy, 0);
+ knot_rrset_dump(*rr_copy);
);
-
+
if (type_covered != type) {
/* Adding RRSIG. */
ret = knot_ddns_add_rr_merge_rrsig(node_rrset_copy,
@@ -1429,27 +1446,27 @@ dbg_ddns_exec_detail(
dbg_ddns_exec_detail(
dbg_ddns_detail("After merge:\n");
- knot_rrset_dump(node_rrset_copy, 1);
+ knot_rrset_dump(node_rrset_copy);
);
if (ret < KNOT_EOK) {
dbg_ddns("Failed to merge UPDATE RR to node RRSet.\n");
- knot_rrset_deep_free(rr_copy, 1, 1, 1);
- knot_rrset_deep_free(&node_rrset_copy, 1, 1, 1);
+ knot_rrset_deep_free(rr_copy, 1, 1);
+ knot_rrset_deep_free(&node_rrset_copy, 1, 1);
return ret;
}
-
+
// save the new RRSet together with the new RDATA to 'changes'
// do not overwrite 'ret', it have to be returned
int r = knot_changes_add_new_rrsets(&node_rrset_copy, 1,
changes, 1);
if (r != KNOT_EOK) {
dbg_ddns("Failed to store RRSet copy to 'changes'\n");
- knot_rrset_deep_free(&node_rrset_copy, 1, 1, 1);
+ knot_rrset_deep_free(&node_rrset_copy, 1, 1);
return r;
}
}
-
+
assert(ret >= 0);
return ret;
}
@@ -1461,7 +1478,7 @@ static int knot_ddns_final_soa_to_chgset(const knot_rrset_t *soa,
{
assert(soa != NULL);
assert(changeset != NULL);
-
+
knot_rrset_t *soa_copy = NULL;
int ret = knot_rrset_deep_copy(soa, &soa_copy, 1);
if (ret != KNOT_EOK) {
@@ -1469,11 +1486,11 @@ static int knot_ddns_final_soa_to_chgset(const knot_rrset_t *soa,
"%s\n", knot_strerror(ret));
return ret;
}
-
+
knot_changeset_store_soa(&changeset->soa_to,
&changeset->serial_to,
soa_copy);
-
+
return KNOT_EOK;
}
@@ -1484,7 +1501,7 @@ static int knot_ddns_add_rr_to_chgset(const knot_rrset_t *rr,
{
assert(rr != NULL);
assert(changeset != NULL);
-
+
int ret = 0;
knot_rrset_t *chgset_rr = NULL;
knot_ddns_check_add_rr(changeset, rr, &chgset_rr);
@@ -1501,15 +1518,15 @@ static int knot_ddns_add_rr_to_chgset(const knot_rrset_t *rr,
&changeset->add_allocated,
chgset_rr);
if (ret != KNOT_EOK) {
- knot_rrset_deep_free(&chgset_rr, 1, 1, 1);
+ knot_rrset_deep_free(&chgset_rr, 1, 1);
dbg_ddns("Failed to add RR to changeset: %s.\n",
knot_strerror(ret));
return ret;
}
} else {
- knot_rrset_deep_free(&chgset_rr, 1, 1, 1);
+ knot_rrset_deep_free(&chgset_rr, 1, 1);
}
-
+
return KNOT_EOK;
}
@@ -1527,7 +1544,7 @@ static int knot_ddns_process_add(const knot_rrset_t *rr,
assert(changeset != NULL);
assert(changes != NULL);
assert(rr_copy != NULL);
-
+
dbg_ddns_verb("Adding RR.\n");
if (node == NULL) {
@@ -1541,11 +1558,11 @@ static int knot_ddns_process_add(const knot_rrset_t *rr,
return KNOT_ERROR;
}
}
-
+
uint16_t type = knot_rrset_type(rr);
*rr_copy = NULL;
int ret = 0;
-
+
/*
* First, rule out special cases: CNAME, SOA and adding to CNAME node.
*/
@@ -1564,7 +1581,7 @@ static int knot_ddns_process_add(const knot_rrset_t *rr,
*/
return KNOT_EOK;
}
-
+
if (ret == 1) {
dbg_ddns_detail("Ignoring the added RR.\n");
// Ignore
@@ -1573,11 +1590,11 @@ static int knot_ddns_process_add(const knot_rrset_t *rr,
dbg_ddns_detail("Adding RR failed.\n");
return ret;
}
-
+
/*
* In all other cases, the RR should just be added to the node.
*/
-
+
/* Add the RRSet to the node (RRSIGs handled in the function). */
dbg_ddns_detail("Adding RR to the node.\n");
ret = knot_ddns_add_rr(node, rr, changes, rr_copy);
@@ -1585,7 +1602,7 @@ static int knot_ddns_process_add(const knot_rrset_t *rr,
dbg_ddns("Failed to add RR to the node.\n");
return ret;
}
-
+
/*
* If adding SOA, it should not be stored in the changeset.
* (This is done in the calling function, and the SOA is stored in the
@@ -1594,9 +1611,9 @@ static int knot_ddns_process_add(const knot_rrset_t *rr,
if (type == KNOT_RRTYPE_SOA) {
return KNOT_EOK;
}
-
+
/* Add the RR to ADD section of the changeset. */
- /* If the RR was previously removed, do not add it to the
+ /* If the RR was previously removed, do not add it to the
* changeset, and remove the entry from the REMOVE section.
*
* If there was no change (i.e. all RDATA were duplicates), do not add
@@ -1655,7 +1672,7 @@ static int knot_ddns_process_rem_rr(const knot_rrset_t *rr,
assert(type != KNOT_RRTYPE_SOA);
int is_apex = knot_node_rrset(node, KNOT_RRTYPE_SOA) != NULL;
-
+
/* If removing NS from an apex and there is only one NS left, ignore
* this removal right away. We do not have to check if the RRs match:
* - if they don't match, the removal will be ignored
@@ -1670,7 +1687,7 @@ static int knot_ddns_process_rem_rr(const knot_rrset_t *rr,
* 1) Copy the RRSet.
*/
uint16_t type_to_copy = (type != KNOT_RRTYPE_RRSIG) ? type
- : knot_rdata_rrsig_type_covered(knot_rrset_rdata(rr));
+ : knot_rrset_rdata_rrsig_type_covered(rr);
knot_rrset_t *rrset_copy = NULL;
int ret = xfrin_copy_rrset(node, type_to_copy, &rrset_copy, changes, 1);
if (ret < 0) {
@@ -1683,31 +1700,29 @@ static int knot_ddns_process_rem_rr(const knot_rrset_t *rr,
dbg_ddns_verb("RRSet not found.\n");
return KNOT_EOK;
}
-
+
/*
* Set some variables needed, according to the modified RR type.
*/
-
- int rdata_count;
+
+ int rdata_count = 0;
knot_rrset_t *to_modify;
if (type == KNOT_RRTYPE_RRSIG) {
- rdata_count = knot_rrset_rdata_rr_count(
- knot_rrset_rrsigs(rrset_copy));
+ rdata_count = knot_rrset_rdata_rr_count(knot_rrset_rrsigs(rrset_copy));
to_modify = knot_rrset_get_rrsigs(rrset_copy);
} else {
rdata_count = knot_rrset_rdata_rr_count(rrset_copy);
to_modify = rrset_copy;
}
-
+
/*
* 1.5) Prepare place for the removed RDATA.
* We don't know if there are some, but if this fails, at least we
* haven't removed them yet.
*/
ret = knot_changes_rdata_reserve(&changes->old_rdata,
- &changes->old_rdata_types,
changes->old_rdata_count,
- &changes->old_rdata_allocated,
+ &changes->old_rdata_allocated,
rdata_count);
if (ret != KNOT_EOK) {
dbg_ddns("Failed to reserve place for RDATA.\n");
@@ -1717,32 +1732,39 @@ static int knot_ddns_process_rem_rr(const knot_rrset_t *rr,
/*
* 2) Remove the proper RDATA from the RRSet copy, or its RRSIGs.
*/
- knot_rdata_t *removed = knot_rrset_remove_rdata(to_modify,
- knot_rrset_rdata(rr));
+ knot_rrset_t *rr_remove = NULL;
+ ret = knot_rrset_remove_rr_using_rrset(to_modify, rr, &rr_remove, 0);
+ if (ret != KNOT_EOK) {
+ dbg_ddns("ddns: proces_rem_rr: Could not remove RDATA from"
+ " RRSet (%s).\n", knot_strerror(ret));
+ return ret;
+ }
/* No such RR in the RRSet. */
- if (removed == NULL) {
+ if (knot_rrset_rdata_rr_count(rr_remove) == 0) {
+ knot_rrset_free(&rr_remove);
dbg_ddns_detail("No such RR found to be removed.\n");
return KNOT_EOK;
}
/* If we removed NS from apex, there should be at least one more. */
- assert(!is_apex || type != KNOT_RRTYPE_NS
- || knot_rrset_rdata(rrset_copy) != NULL);
+ assert(!is_apex || type != KNOT_RRTYPE_NS
+ || knot_rrset_rdata_rr_count(rrset_copy));
/*
* 3) Store the removed RDATA in 'changes'.
*/
- knot_changes_add_rdata(changes->old_rdata, changes->old_rdata_types,
- &changes->old_rdata_count, removed, type);
+ knot_changes_add_rdata(changes->old_rdata, &changes->old_rdata_count,
+ rr_remove);
/*
* 4) If the RRSet is empty, remove it and store in 'changes'.
- * Do this also if the RRSIGs are empty.
+ * Do this also if the RRSIGs are empty.
* And if both are empty, remove both.
+ * RRSIG handling first,
*/
- if (type == KNOT_RRTYPE_RRSIG
- && knot_rrset_rdata(to_modify) == NULL) {
+ if (type == KNOT_RRTYPE_RRSIG &&
+ knot_rrset_rdata_rr_count(to_modify) == 0) {
/* Empty RRSIGs, remove the RRSIG RRSet */
ret = knot_changes_rrsets_reserve(&changes->old_rrsets,
&changes->old_rrsets_count,
@@ -1751,45 +1773,44 @@ static int knot_ddns_process_rem_rr(const knot_rrset_t *rr,
if (ret == KNOT_EOK) {
knot_rrset_t *rrsig = knot_rrset_get_rrsigs(rrset_copy);
dbg_xfrin_detail("Removed RRSIG RRSet (%p).\n", rrsig);
-
- assert(rrsig == to_modify);
+
+ assert(rrsig && rrsig == to_modify);
// add the removed RRSet to list of old RRSets
changes->old_rrsets[changes->old_rrsets_count++]
= rrsig;
-
+
// remove it from the RRSet
knot_rrset_set_rrsigs(rrset_copy, NULL);
} else {
dbg_ddns("Failed to reserve space for empty RRSet.\n");
}
}
-
- /*! \note Copied from xfr-in.c - maybe extract to some function. */
- /*! \note This is not needed as rrset is already on the old_rrsets */
-// if (knot_rrset_rdata(rrset_copy) == NULL
-// && knot_rrset_rrsigs(rrset_copy) == NULL) {
-// // The RRSet should not be empty if we were removing NSs from
-// // apex in case of DDNS
-// assert(!is_apex);
-
-// ret = knot_changes_rrsets_reserve(&changes->old_rrsets,
-// &changes->old_rrsets_count,
-// &changes->old_rrsets_allocated,
-// 1);
-// if (ret == KNOT_EOK) {
-// knot_rrset_t *tmp = knot_node_remove_rrset(node, type);
-// dbg_xfrin_detail("Removed whole RRSet (%p).\n", tmp);
-
-// assert(tmp == rrset_copy);
-
-// // add the removed RRSet to list of old RRSets
-// changes->old_rrsets[changes->old_rrsets_count++]
-// = rrset_copy;
-// } else {
-// dbg_ddns("Failed to reserve space for empty RRSet.\n");
-// }
-// }
+
+ // Remove empty RRSet from node and store to changeset
+ if (type != KNOT_RRTYPE_RRSIG &&
+ knot_rrset_rdata_rr_count(to_modify) == 0) {
+ // The RRSet should not be empty if we were removing NSs from
+ // apex in case of DDNS
+ assert(!is_apex);
+
+ ret = knot_changes_rrsets_reserve(&changes->old_rrsets,
+ &changes->old_rrsets_count,
+ &changes->old_rrsets_allocated,
+ 1);
+ if (ret == KNOT_EOK) {
+ knot_rrset_t *tmp = knot_node_remove_rrset(node, type);
+ dbg_xfrin_detail("Removed whole RRSet (%p).\n", tmp);
+
+ assert(tmp == rrset_copy);
+
+ // add the removed RRSet to list of old RRSets
+ changes->old_rrsets[changes->old_rrsets_count++]
+ = rrset_copy;
+ } else {
+ dbg_ddns("Failed to reserve space for empty RRSet.\n");
+ }
+ }
/*
* 5) Check if the RR is not in the ADD section. If yes, remove it
@@ -1798,8 +1819,7 @@ static int knot_ddns_process_rem_rr(const knot_rrset_t *rr,
knot_rrset_t **from_chgset = NULL;
size_t from_chgset_count = 0;
ret = knot_ddns_check_remove_rr2(changeset, knot_node_owner(node),
- type, knot_rrset_rdata(rr),
- &from_chgset, &from_chgset_count);
+ rr, &from_chgset, &from_chgset_count);
if (ret != KNOT_EOK) {
dbg_ddns("Failed to remove possible redundant RRs from ADD "
"section: %s.\n", knot_strerror(ret));
@@ -1811,13 +1831,13 @@ static int knot_ddns_process_rem_rr(const knot_rrset_t *rr,
if (from_chgset_count == 1) {
/* Just delete the RRSet. */
- knot_rrset_deep_free(&(from_chgset[0]), 1, 1, 1);
+ knot_rrset_deep_free(&(from_chgset[0]), 1, 1);
/* Finish processing, no adding to changeset. */
free(from_chgset);
return KNOT_EOK;
}
-
+
free(from_chgset);
/*
@@ -1841,7 +1861,7 @@ static int knot_ddns_process_rem_rr(const knot_rrset_t *rr,
if (ret != KNOT_EOK) {
dbg_ddns("Failed to store the RRSet copy to changeset: %s.\n",
knot_strerror(ret));
- knot_rrset_deep_free(&to_chgset, 1, 1, 1);
+ knot_rrset_deep_free(&to_chgset, 1, 1);
return ret;
}
@@ -1858,9 +1878,9 @@ static int knot_ddns_process_rem_rrsig(knot_node_t *node,
assert(node != NULL);
assert(rrset != NULL);
assert(changes != NULL);
-
+
knot_rrset_t *rrset_copy = NULL;
-
+
/* Copy RRSet. */
int ret = xfrin_copy_old_rrset(rrset, &rrset_copy, changes, 1);
if (ret != KNOT_EOK) {
@@ -1868,29 +1888,29 @@ static int knot_ddns_process_rem_rrsig(knot_node_t *node,
knot_strerror(ret));
return ret;
}
-
+
/* Remove RRSIGs from the copy. */
*rrsig = knot_rrset_get_rrsigs(rrset_copy);
if (*rrsig != NULL) {
knot_rrset_set_rrsigs(rrset_copy, NULL);
}
-
+
/* Put the copy to the node. */
- ret = knot_node_add_rrset(node, rrset_copy, 0);
+ ret = knot_node_add_rrset_no_merge(node, rrset_copy);
if (ret != KNOT_EOK) {
dbg_ddns("Failed to add RRSet copy to the node: %s\n",
knot_strerror(ret));
- knot_rrset_deep_free(&rrset_copy, 1, 1, 1);
+ knot_rrset_deep_free(&rrset_copy, 1, 1);
return ret;
}
-
+
return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
-static int knot_ddns_process_rem_rrsigs(knot_node_t *node,
- knot_changes_t *changes,
+static int knot_ddns_process_rem_rrsigs(knot_node_t *node,
+ knot_changes_t *changes,
knot_rrset_t ***removed,
size_t *removed_count)
{
@@ -1898,33 +1918,37 @@ static int knot_ddns_process_rem_rrsigs(knot_node_t *node,
assert(removed != NULL);
assert(removed_count != NULL);
assert(changes != NULL);
-
- /* If removing RRSIGs, we must remove them from all RRSets in
- * the node. This means to copy all RRSets and then remove the
+
+ /* If removing RRSIGs, we must remove them from all RRSets in
+ * the node. This means to copy all RRSets and then remove the
* RRSIGs from them.
*/
dbg_ddns_verb("Removing all RRSIGs from node.\n");
-
+
knot_rrset_t **rrsets = knot_node_get_rrsets(node);
if (rrsets == NULL) {
// No RRSets in the node, nothing to remove
return KNOT_EOK;
}
-
+
/* Allocate space for the removed RRSIGs. There may be as many as there
* are RRSets.
*/
short rrset_count = knot_node_rrset_count(node);
-
+
*removed = malloc(rrset_count * sizeof(knot_rrset_t *));
- CHECK_ALLOC_LOG(*removed, KNOT_ENOMEM);
+ if (*removed == NULL) {
+ ERR_ALLOC_FAILED;
+ free(rrsets);
+ return KNOT_ENOMEM;
+ }
*removed_count = 0;
-
+
/* Remove all the RRSets from the node, so that we may insert the copies
* right away.
*/
knot_node_remove_all_rrsets(node);
-
+
knot_rrset_t *rrsig = NULL;
int ret = 0;
for (int i = 0; i < rrset_count; ++i) {
@@ -1932,41 +1956,47 @@ static int knot_ddns_process_rem_rrsigs(knot_node_t *node,
&rrsig);
if (ret != KNOT_EOK) {
dbg_ddns("Failed to remove RRSIG.\n");
+ free(rrsets);
+ free(*removed);
+ *removed = NULL;
return ret;
}
/* Store the RRSIGs to the array of removed RRSets. */
(*removed)[(*removed_count)++] = rrsig;
}
-
+
free(rrsets);
-
-
+
+
return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
-static int knot_ddns_process_rem_rrset(uint16_t type,
+static int knot_ddns_process_rem_rrset(const knot_rrset_t *rrset,
knot_node_t *node,
knot_changeset_t *changeset,
knot_changes_t *changes)
{
assert(node != NULL);
+ assert(rrset != NULL);
assert(changeset != NULL);
assert(changes != NULL);
+ uint16_t type = knot_rrset_type(rrset);
+
/*! \note
* We decided to automatically remove RRSIGs together with the removed
- * RRSet as they are no longer valid or required anyway.
+ * RRSet as they are no longer valid or required anyway.
*
* Also refer to RFC3007, section 4.3:
- * 'When the contents of an RRset are updated, the server MAY delete
+ * 'When the contents of an RRset are updated, the server MAY delete
* all associated SIG records, since they will no longer be valid.'
*
* (Although we are compliant with this RFC only selectively. The next
- * section says: 'If any changes are made, the server MUST, if
- * necessary, generate a new SOA record and new NXT records, and sign
- * these with the appropriate zone keys.' and we are definitely not
+ * section says: 'If any changes are made, the server MUST, if
+ * necessary, generate a new SOA record and new NXT records, and sign
+ * these with the appropriate zone keys.' and we are definitely not
* doing this...
*
* \todo Document!!
@@ -1980,15 +2010,20 @@ static int knot_ddns_process_rem_rrset(uint16_t type,
// if removing NS from apex, ignore
return KNOT_EOK;
}
-
+
knot_rrset_t **removed = NULL;
size_t removed_count = 0;
int ret = 0;
-
+
if (type == KNOT_RRTYPE_RRSIG) {
/* Remove all RRSIGs from the node. */
ret = knot_ddns_process_rem_rrsigs(node, changes, &removed,
&removed_count);
+ if (ret != KNOT_EOK) {
+ dbg_ddns("Failed to remove RRSIGs. (%s)\n",
+ knot_strerror(ret));
+ return ret;
+ }
} else {
/* Remove the RRSet from the node. */
removed = malloc(sizeof(knot_rrset_t *));
@@ -1998,23 +2033,28 @@ static int knot_ddns_process_rem_rrset(uint16_t type,
}
dbg_ddns_detail("Removing RRSet of type: %d\n", type);
-
+
*removed = knot_node_remove_rrset(node, type);
- removed_count = 1;
+ if (*removed != NULL) {
+ removed_count = 1;
+ } else {
+ removed_count = 0;
+ }
}
- dbg_ddns_detail("Removed: %p (first item: %p), removed count: %d\n",
- removed, (removed == NULL) ? "none" : *removed,
+ dbg_ddns_detail("Removed: %p (first item: %p), removed count: %zu\n",
+ removed, (removed == NULL) ? (void *)"none" : *removed,
removed_count);
// no such RR
- if (removed_count == 0 || removed == NULL) {
+ if (removed_count == 0) {
// ignore
+ free(removed);
return KNOT_EOK;
}
/* 2) Store them to 'changes' for later deallocation, together with
- * their RRSIGs.
+ * their RRSIGs.
*/
ret = knot_changes_add_old_rrsets(removed, removed_count, changes, 1);
if (ret != KNOT_EOK) {
@@ -2025,7 +2065,7 @@ static int knot_ddns_process_rem_rrset(uint16_t type,
}
/* 3) Copy the RRSets, so that they can be stored to the changeset. */
- knot_rrset_t **to_chgset = malloc(removed_count
+ knot_rrset_t **to_chgset = malloc(removed_count
* sizeof(knot_rrset_t *));
if (to_chgset == NULL) {
dbg_ddns("Failed to allocate space for RRSets going to "
@@ -2033,21 +2073,21 @@ static int knot_ddns_process_rem_rrset(uint16_t type,
free(removed);
return KNOT_ENOMEM;
}
-
+
for (int i = 0; i < removed_count; ++i) {
ret = knot_rrset_deep_copy(removed[i], &to_chgset[i], 1);
if (ret != KNOT_EOK) {
dbg_ddns("Failed to copy the removed RRSet: %s.\n",
knot_strerror(ret));
for (int j = 0; j < i; ++j) {
- knot_rrset_deep_free(&to_chgset[j], 1, 1, 1);
+ knot_rrset_deep_free(&to_chgset[j], 1, 1);
}
free(to_chgset);
free(removed);
return ret;
}
}
-
+
free(removed);
/* 4) But we must check if some of the RRs were not previously added
@@ -2059,22 +2099,28 @@ static int knot_ddns_process_rem_rrset(uint16_t type,
size_t from_chgset_count = 0;
/* 4 a) Remove redundant RRs from the ADD section of the changeset. */
- ret = knot_ddns_check_remove_rr2(changeset, knot_node_owner(node), type,
- NULL, &from_chgset,
+ knot_rrset_t *empty_rrset =
+ knot_rrset_new(rrset->owner, type, rrset->rclass, rrset->ttl);
+ if (empty_rrset == NULL) {
+ return KNOT_ENOMEM;
+ }
+ ret = knot_ddns_check_remove_rr2(changeset, knot_node_owner(node),
+ empty_rrset, &from_chgset,
&from_chgset_count);
if (ret != KNOT_EOK) {
dbg_ddns("Failed to remove possible redundant RRs from ADD "
"section: %s.\n", knot_strerror(ret));
for (int i = 0; i < removed_count; ++i) {
- knot_rrset_deep_free(&to_chgset[i], 1, 1, 1);
+ knot_rrset_deep_free(&to_chgset[i], 1, 1);
}
free(from_chgset);
free(to_chgset);
+ knot_rrset_free(&empty_rrset);
return ret;
}
+ knot_rrset_free(&empty_rrset);
/* 4 b) Remove these RRs from the copy of the RRSets removed from zone*/
- knot_rdata_t *rem = NULL;
for (int j = 0; j < removed_count; ++j) {
/* In each RRSet removed from the node (each can have more
* RDATAs) ...
@@ -2083,18 +2129,21 @@ static int knot_ddns_process_rem_rrset(uint16_t type,
/* ...try to remove redundant RDATA. Each RRSet in
* 'from_chgset' contains only one RDATA.
*/
- rem = knot_rrset_remove_rdata(to_chgset[j],
- knot_rrset_rdata(
- from_chgset[i]));
- /* And delete it right away, no use for that. */
- knot_rdata_deep_free(&rem, knot_rrset_type(
- from_chgset[i]), 1);
+ ret = knot_rrset_remove_rr_using_rrset_del(to_chgset[j],
+ from_chgset[i]);
+ if (ret != KNOT_EOK) {
+ dbg_ddns("Failed to remove RR from RRSet"
+ "(%s).\n", knot_strerror(ret));
+ free(from_chgset);
+ free(to_chgset);
+ return ret;
+ }
}
}
-
+
/* The array is cleared, we may delete the redundant RRs. */
for (int i = 0; i < from_chgset_count; ++i) {
- knot_rrset_deep_free(&from_chgset[i], 1, 1, 1);
+ knot_rrset_deep_free(&from_chgset[i], 1, 1);
}
free(from_chgset);
@@ -2110,13 +2159,13 @@ static int knot_ddns_process_rem_rrset(uint16_t type,
dbg_ddns("Failed to store the RRSet copy to changeset: "
"%s.\n", knot_strerror(ret));
for (int j = i; j < removed_count; ++j) {
- knot_rrset_deep_free(&to_chgset[j], 1, 1, 1);
+ knot_rrset_deep_free(&to_chgset[j], 1, 1);
}
free(to_chgset);
return ret;
}
}
-
+
free(to_chgset);
return KNOT_EOK;
@@ -2139,13 +2188,13 @@ static int knot_ddns_process_rem_all(knot_node_t *node,
* In case of SOA and NS in apex, the RRSets should not be removed, but
* what about their RRSIGs??
*
- * If the zone has to remain properly signed, the UPDATE will have to
+ * If the zone has to remain properly signed, the UPDATE will have to
* contain at least new SOA and RRSIGs for it (as the auto-incremented
- * SOA would not be signed). So it should not matter if we leave the
+ * SOA would not be signed). So it should not matter if we leave the
* RRSIGs there or not. But in case of the NSs it's not that clear.
*
* For now, we will leave the RRSIGs there. It's easier to implement.
- *
+ *
* \todo Should document this!!
*/
int ret = 0;
@@ -2169,8 +2218,8 @@ static int knot_ddns_process_rem_all(knot_node_t *node,
continue;
}
- ret = knot_ddns_process_rem_rrset(knot_rrset_type(rrsets[i]),
- node, changeset, changes);
+ ret = knot_ddns_process_rem_rrset(rrsets[i], node, changeset,
+ changes);
if (ret != KNOT_EOK) {
dbg_ddns("Failed to remove RRSet: %s\n",
knot_strerror(ret));
@@ -2178,7 +2227,7 @@ static int knot_ddns_process_rem_all(knot_node_t *node,
return ret;
}
}
-
+
free(rrsets);
return KNOT_EOK;
@@ -2211,14 +2260,13 @@ static int knot_ddns_process_rr(const knot_rrset_t *rr,
return KNOT_EOK;
} else if (knot_rrset_class(rr) == KNOT_CLASS_NONE) {
return knot_ddns_process_rem_rr(rr, node, zone, changeset,
- changes, qclass);
+ changes, qclass);
} else if (knot_rrset_class(rr) == KNOT_CLASS_ANY) {
if (knot_rrset_type(rr) == KNOT_RRTYPE_ANY) {
return knot_ddns_process_rem_all(node, changeset,
changes);
} else {
- return knot_ddns_process_rem_rrset(knot_rrset_type(rr),
- node, changeset,
+ return knot_ddns_process_rem_rrset(rr, node, changeset,
changes);
}
} else {
@@ -2258,7 +2306,7 @@ int knot_ddns_process_update2(knot_zone_contents_t *zone,
KNOT_RRTYPE_SOA);
knot_rrset_t *soa_begin = NULL;
knot_rrset_t *soa_end = NULL;
- ret = knot_rrset_deep_copy(soa, &soa_begin, 0);
+ ret = knot_rrset_deep_copy(soa, &soa_begin, 1);
if (ret == KNOT_EOK) {
knot_changeset_store_soa(&changeset->soa_from,
&changeset->serial_from, soa_begin);
@@ -2268,7 +2316,7 @@ int knot_ddns_process_update2(knot_zone_contents_t *zone,
}
/* Current SERIAL */
- int64_t sn = knot_rdata_soa_serial(knot_rrset_rdata(soa_begin));
+ int64_t sn = knot_rrset_rdata_soa_serial(soa_begin);
int64_t sn_new;
/* Incremented SERIAL
@@ -2320,13 +2368,14 @@ int knot_ddns_process_update2(knot_zone_contents_t *zone,
if (knot_rrset_type(rr) == KNOT_RRTYPE_SOA
&& (knot_rrset_class(rr) == KNOT_CLASS_NONE
|| knot_rrset_class(rr) == KNOT_CLASS_ANY
- || ns_serial_compare(knot_rdata_soa_serial(
- knot_rrset_rdata(rr)), sn_new) < 0)) {
+ || ns_serial_compare(knot_rrset_rdata_soa_serial(rr),
+ sn_new) < 0)) {
// This ignores also SOA removals
dbg_ddns_verb("Ignoring SOA...\n");
continue;
}
+ dbg_ddns_verb("Processing RR %p...\n", rr);
ret = knot_ddns_process_rr(rr, zone, changeset, changes,
knot_packet_qclass(query),
&rr_copy);
@@ -2341,10 +2390,9 @@ int knot_ddns_process_update2(knot_zone_contents_t *zone,
// we need the RR copy, that's why this code is here
if (knot_rrset_type(rr) == KNOT_RRTYPE_SOA) {
- int64_t sn_rr = knot_rdata_soa_serial(
- knot_rrset_rdata(rr));
- dbg_ddns_verb("Replacing SOA. Old serial: %d, new "
- "serial: %d\n", sn_new, sn_rr);
+ int64_t sn_rr = knot_rrset_rdata_soa_serial(rr);
+ dbg_ddns_verb("Replacing SOA. Old serial: %"PRId64", "
+ "new serial: %"PRId64"\n", sn_new, sn_rr);
assert(ns_serial_compare(sn_rr, sn_new) >= 0);
assert(rr_copy != NULL);
sn_new = sn_rr;
@@ -2354,14 +2402,14 @@ int knot_ddns_process_update2(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
+ /* If the changeset is empty, do not process anything further
* and indicate this to the caller, so that the changeset is not
* saved and zone is not switched.
*/
if (knot_changeset_is_empty(changeset)) {
return 1;
}
-
+
/* If not set, create new SOA. */
assert(sn_new == (uint32_t)sn + 1);
ret = knot_rrset_deep_copy(soa, &soa_end, 1);
@@ -2371,9 +2419,8 @@ int knot_ddns_process_update2(knot_zone_contents_t *zone,
*rcode = KNOT_RCODE_SERVFAIL;
return ret;
}
- knot_rdata_t *rd = knot_rrset_get_rdata(soa_end);
- knot_rdata_soa_serial_set(rd, sn_new);
-
+ knot_rrset_rdata_soa_serial_set(soa_end, sn_new);
+
/* And replace it in the zone. */
ret = xfrin_replace_rrset_in_node(
knot_zone_contents_get_apex(zone),