From f5d1375c0ed52074fe840dcb0704b8359ce12187 Mon Sep 17 00:00:00 2001
From: Jan Kadlec <jan.kadlec@nic.cz>
Date: Mon, 7 Apr 2014 12:50:07 +0200
Subject: [PATCH] new_node: xfr/ddns simpler SOA handling + obsolete setters
 removed.

---
 src/knot/dnssec/nsec-chain.c   |  2 +-
 src/knot/dnssec/nsec-chain.h   |  2 +-
 src/knot/dnssec/nsec3-chain.c  |  2 +-
 src/knot/dnssec/zone-sign.c    |  2 +-
 src/knot/nameserver/axfr.c     |  2 +-
 src/knot/nameserver/internet.c |  2 +-
 src/knot/updates/ddns.c        | 49 +++++++++----------
 src/knot/updates/xfr-in.c      | 32 ++-----------
 src/knot/zone/node.c           |  2 +-
 src/knot/zone/node.h           | 86 ++++++++++++----------------------
 src/knot/zone/semantic-check.c |  2 +-
 src/knot/zone/zone-diff.c      |  8 ++--
 src/knot/zone/zone-dump.c      |  4 +-
 13 files changed, 70 insertions(+), 125 deletions(-)

diff --git a/src/knot/dnssec/nsec-chain.c b/src/knot/dnssec/nsec-chain.c
index 0a08b2640..8b32397de 100644
--- a/src/knot/dnssec/nsec-chain.c
+++ b/src/knot/dnssec/nsec-chain.c
@@ -278,7 +278,7 @@ bool knot_nsec_empty_nsec_and_rrsigs_in_node(const knot_node_t *n)
 {
 	assert(n);
 	for (int i = 0; i < n->rrset_count; ++i) {
-		knot_rrset_t rrset = knot_node_rrset_n(n, i);
+		knot_rrset_t rrset = knot_node_rrset_at(n, i);
 		if (rrset.type != KNOT_RRTYPE_NSEC &&
 		    rrset.type != KNOT_RRTYPE_RRSIG) {
 			return false;
diff --git a/src/knot/dnssec/nsec-chain.h b/src/knot/dnssec/nsec-chain.h
index 7aa422163..299f79350 100644
--- a/src/knot/dnssec/nsec-chain.h
+++ b/src/knot/dnssec/nsec-chain.h
@@ -63,7 +63,7 @@ inline static void bitmap_add_node_rrsets(bitmap_t *bitmap,
                                           const knot_node_t *node)
 {
 	for (int i = 0; i < node->rrset_count; i++) {
-		knot_rrset_t rr = knot_node_rrset_n(node, i);
+		knot_rrset_t rr = knot_node_rrset_at(node, i);
 		if (rr.type != KNOT_RRTYPE_NSEC &&
 		    rr.type != KNOT_RRTYPE_RRSIG) {
 			bitmap_add_type(bitmap, rr.type);
diff --git a/src/knot/dnssec/nsec3-chain.c b/src/knot/dnssec/nsec3-chain.c
index 17380fe9f..0daa397d5 100644
--- a/src/knot/dnssec/nsec3-chain.c
+++ b/src/knot/dnssec/nsec3-chain.c
@@ -89,7 +89,7 @@ static bool are_nsec3_nodes_equal(const knot_node_t *a, const knot_node_t *b)
 static bool node_should_be_signed_nsec3(const knot_node_t *n)
 {
 	for (int i = 0; i < n->rrset_count; i++) {
-		knot_rrset_t rrset = knot_node_rrset_n(n, i);
+		knot_rrset_t rrset = knot_node_rrset_at(n, i);
 		if (rrset.type == KNOT_RRTYPE_NSEC ||
 		    rrset.type == KNOT_RRTYPE_RRSIG) {
 			continue;
diff --git a/src/knot/dnssec/zone-sign.c b/src/knot/dnssec/zone-sign.c
index b93cb7bd4..f00d52117 100644
--- a/src/knot/dnssec/zone-sign.c
+++ b/src/knot/dnssec/zone-sign.c
@@ -501,7 +501,7 @@ static int sign_node_rrsets(const knot_node_t *node,
 	knot_rrset_t rrsigs = knot_node_rrset(node, KNOT_RRTYPE_RRSIG);
 
 	for (int i = 0; i < node->rrset_count; i++) {
-		knot_rrset_t rrset = knot_node_rrset_n(node, i);
+		knot_rrset_t rrset = knot_node_rrset_at(node, i);
 		if (rrset.type == KNOT_RRTYPE_RRSIG) {
 			continue;
 		}
diff --git a/src/knot/nameserver/axfr.c b/src/knot/nameserver/axfr.c
index 1f0c558b9..c52f00452 100644
--- a/src/knot/nameserver/axfr.c
+++ b/src/knot/nameserver/axfr.c
@@ -38,7 +38,7 @@ static int put_rrsets(knot_pkt_t *pkt, knot_node_t *node, struct axfr_proc *stat
 
 	/* Append all RRs. */
 	for (;i < rrset_count; ++i) {
-		knot_rrset_t rrset = knot_node_rrset_n(node, i);
+		knot_rrset_t rrset = knot_node_rrset_at(node, i);
 		if (rrset.type == KNOT_RRTYPE_SOA) {
 			continue;
 		}
diff --git a/src/knot/nameserver/internet.c b/src/knot/nameserver/internet.c
index aa1db5ae4..ebb36634a 100644
--- a/src/knot/nameserver/internet.c
+++ b/src/knot/nameserver/internet.c
@@ -166,7 +166,7 @@ static int put_answer(knot_pkt_t *pkt, uint16_t type, struct query_data *qdata)
 			return KNOT_ESPACE;
 		}
 		for (unsigned i = 0; i < knot_node_rrset_count(qdata->node); ++i) {
-			rrset = knot_node_rrset_n(qdata->node, i);
+			rrset = knot_node_rrset_at(qdata->node, i);
 			ret = ns_put_rr(pkt, &rrset, NULL, compr_hint, 0, qdata);
 			if (ret != KNOT_EOK) {
 				break;
diff --git a/src/knot/updates/ddns.c b/src/knot/updates/ddns.c
index abc05a62c..9b6c8010c 100644
--- a/src/knot/updates/ddns.c
+++ b/src/knot/updates/ddns.c
@@ -393,8 +393,7 @@ static bool should_replace(const knot_rrset_t *chg_rrset,
                            const knot_rrset_t *rrset)
 {
 	if (rrset->type != KNOT_RRTYPE_CNAME &&
-	    rrset->type != KNOT_RRTYPE_NSEC3PARAM &&
-	    rrset->type != KNOT_RRTYPE_SOA) {
+	    rrset->type != KNOT_RRTYPE_NSEC3PARAM) {
 		return false;
 	} else {
 		return chg_rrset->type == rrset->type;
@@ -416,7 +415,7 @@ static bool node_empty(const knot_node_t *node, knot_dname_t *owner,
 	}
 
 	for (uint16_t i = 0; i < node->rrset_count; ++i) {
-		knot_rrset_t node_rrset = knot_node_rrset_n(node, i);
+		knot_rrset_t node_rrset = knot_node_rrset_at(node, i);
 		knot_rrset_t node_rr;
 		knot_rrset_init(&node_rr, node->owner, node_rrset.type, KNOT_CLASS_IN);
 		for (uint16_t j = 0; j < node_rrset.rrs.rr_count; ++j) {
@@ -678,13 +677,25 @@ static int process_add_soa(const knot_node_t *node,
 		return KNOT_EOK;
 	}
 
-	/* Get the current SOA RR from the node. */
+	// Get current SOA RR.
 	knot_rrset_t removed = knot_node_rrset(node, KNOT_RRTYPE_SOA);
-	/* If they are identical, ignore. */
 	if (knot_rrset_equal(&removed, rr, KNOT_RRSET_COMPARE_WHOLE)) {
+		// If they are identical, ignore.
 		return KNOT_EOK;
 	}
-	return add_rr_to_chgset(rr, changeset, NULL);
+
+	// Store SOA copy into changeset.
+	if (changeset->soa_to != NULL) {
+		// Discard previous SOA - "There can be only one!"
+		knot_rrset_free(&changeset->soa_to, NULL);
+	}
+	knot_rrset_t *soa_cpy = knot_rrset_copy(rr, NULL);
+	if (soa_cpy == NULL) {
+		return KNOT_ENOMEM;
+	}
+
+	knot_changeset_add_soa(changeset, soa_cpy, KNOT_CHANGESET_ADD);
+	return KNOT_EOK;
 }
 
 /*!< \brief Adds normal RR, ignores when CNAME exists in node. */
@@ -821,7 +832,7 @@ static int process_rem_node(const knot_rrset_t *rr,
 
 	// Remove all RRSets from node
 	for (int i = 0; i < node->rrset_count; ++i) {
-		knot_rrset_t rrset = knot_node_rrset_n(node, i);
+		knot_rrset_t rrset = knot_node_rrset_at(node, i);
 		int ret = process_rem_rrset(&rrset, node, changeset);
 		if (ret != KNOT_EOK) {
 			return ret;
@@ -1014,7 +1025,6 @@ int knot_ddns_process_update(const knot_zone_contents_t *zone,
 	/* Process all RRs the Authority (Update) section. */
 
 	dbg_ddns("Processing UPDATE section.\n");
-	knot_rrset_t *soa_end = NULL;
 	int apex_ns_rem = 0;
 	const knot_pktsection_t *authority = knot_pkt_section(query, KNOT_AUTHORITY);
 	for (uint16_t i = 0; i < authority->count; ++i) {
@@ -1035,36 +1045,23 @@ int knot_ddns_process_update(const knot_zone_contents_t *zone,
 			*rcode = ret_to_rcode(ret);
 			return ret;
 		}
-
-		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_old) > 0);
-			soa_end = knot_rrset_copy(rr, NULL);
-			if (soa_end == NULL) {
-				return KNOT_ENOMEM;
-			}
-		}
 	}
 
-	if (soa_end == NULL) {
+	if (changeset->soa_to == NULL) {
 		// No SOA in the update, create according to current policy
 		if (knot_changeset_is_empty(changeset)) {
 			// No change, no new SOA
 			return KNOT_EOK;
 		}
 
-		soa_end = knot_rrset_copy(soa_begin, NULL);
-		if (soa_end == NULL) {
+		knot_rrset_t *soa_cpy = knot_rrset_copy(soa_begin, NULL);
+		if (soa_cpy == NULL) {
 			*rcode = KNOT_RCODE_SERVFAIL;
 			return KNOT_ENOMEM;
 		}
-		knot_rrs_soa_serial_set(&soa_end->rrs, new_serial);
+		knot_rrs_soa_serial_set(&soa_cpy->rrs, new_serial);
+		knot_changeset_add_soa(changeset, soa_cpy, KNOT_CHANGESET_ADD);
 	}
 
-	knot_changeset_add_soa(changeset, soa_end, KNOT_CHANGESET_ADD);
 	return KNOT_EOK;
 }
diff --git a/src/knot/updates/xfr-in.c b/src/knot/updates/xfr-in.c
index 1a79e7e63..e0a0be6ea 100644
--- a/src/knot/updates/xfr-in.c
+++ b/src/knot/updates/xfr-in.c
@@ -887,39 +887,15 @@ static int xfrin_apply_add(knot_zone_contents_t *contents,
 static int xfrin_apply_replace_soa(knot_zone_contents_t *contents,
                                    knot_changeset_t *chset)
 {
-	dbg_xfrin("Replacing SOA record.\n");
-	knot_node_t *node = contents->apex;
-	assert(node != NULL);
-
-	assert(node != NULL);
-	knot_rrs_t *soa_rrs = knot_node_get_rrs(node, KNOT_RRTYPE_SOA);
-	knot_rr_t *old_data = soa_rrs->data;
-	int ret = xfrin_replace_rrs_with_copy(node, KNOT_RRTYPE_SOA);
+	assert(chset->soa_from);
+	int ret = remove_rr(contents->apex, chset->soa_from, chset);
 	if (ret != KNOT_EOK) {
 		return ret;
 	}
 
-	ret = add_old_data(chset, old_data, NULL);
-	if (ret != KNOT_EOK) {
-		clear_new_rrs(node, KNOT_RRTYPE_SOA);
-		return ret;
-	}
-
-	soa_rrs = knot_node_get_rrs(node, KNOT_RRTYPE_SOA);
-	knot_rrs_clear(soa_rrs, NULL);
-	ret = knot_rrs_copy(soa_rrs, &chset->soa_to->rrs, NULL);
-	if (ret != KNOT_EOK) {
-		clear_new_rrs(node, KNOT_RRTYPE_SOA);
-		return KNOT_ENOMEM;
-	}
-
-	ret = add_new_data(chset, soa_rrs->data);
-	if (ret != KNOT_EOK) {
-		clear_new_rrs(node, KNOT_RRTYPE_SOA);
-		return ret;
-	}
+	assert(!knot_node_rrtype_exists(contents->apex, KNOT_RRTYPE_SOA));
 
-	return KNOT_EOK;
+	return add_rr(contents->apex, chset->soa_to, chset);
 }
 
 /*----------------------------------------------------------------------------*/
diff --git a/src/knot/zone/node.c b/src/knot/zone/node.c
index 6e26eee43..84e4c512e 100644
--- a/src/knot/zone/node.c
+++ b/src/knot/zone/node.c
@@ -188,7 +188,7 @@ knot_rrset_t *knot_node_create_rrset(const knot_node_t *node, uint16_t type)
 
 	for (uint16_t i = 0; i < node->rrset_count; ++i) {
 		if (node->rrs[i].type == type) {
-			knot_rrset_t rrset = knot_node_rrset_n(node, i);
+			knot_rrset_t rrset = knot_node_rrset_at(node, i);
 			return knot_rrset_copy(&rrset, NULL);
 		}
 	}
diff --git a/src/knot/zone/node.h b/src/knot/zone/node.h
index df636b274..4a3062612 100644
--- a/src/knot/zone/node.h
+++ b/src/knot/zone/node.h
@@ -384,56 +384,6 @@ bool knot_node_rrtype_is_signed(const knot_node_t *node, uint16_t type);
  */
 bool knot_node_rrtype_exists(const knot_node_t *node, uint16_t type);
 
-/*!
- * \brief Initializes given RRSet structure with data from node.
- *
- * \param node   Node containing RRSet.
- * \param type   RRSet type we want to get.
- * \param rrset  Structure to be initialized.
- */
-static void inline knot_node_fill_rrset(const knot_node_t *node, uint16_t type,
-                                        knot_rrset_t *rrset)
-{
-	if (node == NULL || rrset == NULL) {
-		knot_rrset_init_empty(rrset);
-		return;
-	}
-	for (uint i = 0; i < node->rrset_count; ++i) {
-		if (node->rrs[i].type == type) {
-			struct rr_data *rr_data = &node->rrs[i];
-			rrset->owner = node->owner;
-			rrset->type = type;
-			rrset->rclass = KNOT_CLASS_IN;
-			rrset->rrs = rr_data->rrs;
-			rrset->additional = rr_data->additional;
-			return;
-		}
-	}
-	knot_rrset_init_empty(rrset);
-}
-
-/*!
- * \brief Initializes given RRSet structure with data from node.
- *
- * \param node   Node containing RRSet.
- * \param pos    Position to use for initialization.
- * \param rrset  Structure to be initialized.
- */
-static void inline knot_node_fill_rrset_pos(const knot_node_t *node, size_t pos,
-                                            knot_rrset_t *rrset)
-{
-	if (node == NULL || pos >= node->rrset_count || rrset == NULL) {
-		knot_rrset_init_empty(rrset);
-		return;
-	}
-	struct rr_data *rr_data = &node->rrs[pos];
-	rrset->owner = node->owner;
-	rrset->type = rr_data->type;
-	rrset->rclass = KNOT_CLASS_IN;
-	rrset->rrs = rr_data->rrs;
-	rrset->additional = rr_data->additional;
-}
-
 /*!
  * \brief Returns RRSet structure initialized with data from node.
  *
@@ -444,9 +394,20 @@ static void inline knot_node_fill_rrset_pos(const knot_node_t *node, size_t pos,
  */
 static inline knot_rrset_t knot_node_rrset(const knot_node_t *node, uint16_t type)
 {
-	knot_rrset_t ret;
-	knot_node_fill_rrset(node, type, &ret);
-	return ret;
+	knot_rrset_t rrset;
+	for (uint i = 0; node && i < node->rrset_count; ++i) {
+		if (node->rrs[i].type == type) {
+			struct rr_data *rr_data = &node->rrs[i];
+			rrset.owner = node->owner;
+			rrset.type = type;
+			rrset.rclass = KNOT_CLASS_IN;
+			rrset.rrs = rr_data->rrs;
+			rrset.additional = rr_data->additional;
+			return rrset;
+		}
+	}
+	knot_rrset_init_empty(&rrset);
+	return rrset;
 }
 
 /*!
@@ -458,11 +419,22 @@ static inline knot_rrset_t knot_node_rrset(const knot_node_t *node, uint16_t typ
  *
  * \return RRSet structure with data from wanted position, or empty RRSet.
  */
-static inline knot_rrset_t knot_node_rrset_n(const knot_node_t *node, size_t pos)
+static inline knot_rrset_t knot_node_rrset_at(const knot_node_t *node, size_t pos)
 {
-	knot_rrset_t ret;
-	knot_node_fill_rrset_pos(node, pos, &ret);
-	return ret;
+	knot_rrset_t rrset;
+	if (node == NULL || pos >= node->rrset_count) {
+		knot_rrset_init_empty(&rrset);
+		return rrset;
+	}
+
+	struct rr_data *rr_data = &node->rrs[pos];
+	rrset.owner = node->owner;
+	rrset.type = rr_data->type;
+	rrset.rclass = KNOT_CLASS_IN;
+	rrset.rrs = rr_data->rrs;
+	rrset.additional = rr_data->additional;
+
+	return rrset;
 }
 
 #endif /* _KNOT_NODE_H_ */
diff --git a/src/knot/zone/semantic-check.c b/src/knot/zone/semantic-check.c
index 757da994d..87b95b6f9 100644
--- a/src/knot/zone/semantic-check.c
+++ b/src/knot/zone/semantic-check.c
@@ -935,7 +935,7 @@ static int semantic_checks_dnssec(knot_zone_contents_t *zone,
 	int ret = KNOT_EOK;
 
 	for (int i = 0; i < rrset_count; i++) {
-		knot_rrset_t rrset = knot_node_rrset_n(node, i);
+		knot_rrset_t rrset = knot_node_rrset_at(node, i);
 		if (auth && !deleg && rrset.type != KNOT_RRTYPE_RRSIG &&
 		    (ret = check_rrsig_in_rrset(handler, node,
 		                                &rrset, &dnskey_rrset)) != 0) {
diff --git a/src/knot/zone/zone-diff.c b/src/knot/zone/zone-diff.c
index 45b4061de..dc340df0e 100644
--- a/src/knot/zone/zone-diff.c
+++ b/src/knot/zone/zone-diff.c
@@ -169,7 +169,7 @@ static int knot_zone_diff_add_node(const knot_node_t *node,
 {
 	/* Add all rrsets from node. */
 	for (uint i = 0; i < knot_node_rrset_count(node); i++) {
-		knot_rrset_t rrset = knot_node_rrset_n(node, i);
+		knot_rrset_t rrset = knot_node_rrset_at(node, i);
 		int ret = knot_zone_diff_changeset_add_rrset(changeset,
 		                                             &rrset);
 		if (ret != KNOT_EOK) {
@@ -187,7 +187,7 @@ static int knot_zone_diff_remove_node(knot_changeset_t *changeset,
 {
 	/* Remove all the RRSets of the node. */
 	for (uint i = 0; i < knot_node_rrset_count(node); i++) {
-		knot_rrset_t rrset = knot_node_rrset_n(node, i);
+		knot_rrset_t rrset = knot_node_rrset_at(node, i);
 		int ret = knot_zone_diff_changeset_remove_rrset(changeset,
 		                                                &rrset);
 		if (ret != KNOT_EOK) {
@@ -405,7 +405,7 @@ static int knot_zone_diff_node(knot_node_t **node_ptr, void *data)
 
 	for (uint i = 0; i < knot_node_rrset_count(node); i++) {
 		/* Search for the RRSet in the node from the second tree. */
-		knot_rrset_t rrset = knot_node_rrset_n(node, i);
+		knot_rrset_t rrset = knot_node_rrset_at(node, i);
 
 		/* SOAs are handled explicitely. */
 		if (rrset.type == KNOT_RRTYPE_SOA) {
@@ -438,7 +438,7 @@ static int knot_zone_diff_node(knot_node_t **node_ptr, void *data)
 
 	for (uint i = 0; i < knot_node_rrset_count(node_in_second_tree); i++) {
 		/* Search for the RRSet in the node from the second tree. */
-		knot_rrset_t rrset = knot_node_rrset_n(node_in_second_tree, i);
+		knot_rrset_t rrset = knot_node_rrset_at(node_in_second_tree, i);
 
 		/* SOAs are handled explicitely. */
 		if (rrset.type == KNOT_RRTYPE_SOA) {
diff --git a/src/knot/zone/zone-dump.c b/src/knot/zone/zone-dump.c
index 33748cb82..4443ac2bc 100644
--- a/src/knot/zone/zone-dump.c
+++ b/src/knot/zone/zone-dump.c
@@ -57,7 +57,7 @@ static int apex_node_dump_text(knot_node_t *node, dump_params_t *params)
 
 	// Dump other records.
 	for (uint16_t i = 0; i < node->rrset_count; i++) {
-		knot_rrset_t rrset = knot_node_rrset_n(node, i);
+		knot_rrset_t rrset = knot_node_rrset_at(node, i);
 		switch (rrset.type) {
 		case KNOT_RRTYPE_NSEC:
 			continue;
@@ -94,7 +94,7 @@ static int node_dump_text(knot_node_t *node, void *data)
 
 	// Dump non-apex rrsets.
 	for (uint16_t i = 0; i < node->rrset_count; i++) {
-		knot_rrset_t rrset = knot_node_rrset_n(node, i);
+		knot_rrset_t rrset = knot_node_rrset_at(node, i);
 		switch (rrset.type) {
 		case KNOT_RRTYPE_RRSIG:
 			if (params->dump_rrsig) {
-- 
GitLab