From 3ef4852261d66cf4304e0d230c3a1ccf87dfddf7 Mon Sep 17 00:00:00 2001
From: Jan Kadlec <jan.kadlec@nic.cz>
Date: Tue, 8 Apr 2014 21:35:41 +0200
Subject: [PATCH] new_node: Reuse RRSet code in internet.c/pkt.c + fixes.

- ns_put_rr function now accepts consts rrsets only
- fixed wrong TTL set in SOA copy
- removed a function move_rrset, to be replaced with RRSet function
  later.
---
 src/knot/nameserver/internet.c | 90 +++++++++++++++-------------------
 src/knot/nameserver/internet.h |  4 +-
 src/libknot/packet/pkt.c       | 12 ++---
 3 files changed, 44 insertions(+), 62 deletions(-)

diff --git a/src/knot/nameserver/internet.c b/src/knot/nameserver/internet.c
index 2c3df52fa..000d97c3a 100644
--- a/src/knot/nameserver/internet.c
+++ b/src/knot/nameserver/internet.c
@@ -40,28 +40,26 @@ static int wildcard_visit(struct query_data *qdata, const knot_node_t *node, con
 	return KNOT_EOK;
 }
 
-/*! \brief Moves data from 'src' to 'dst', owner and RRs are deep copied. */
 int move_rrset(knot_rrset_t *dst, const knot_rrset_t *src, mm_ctx_t *mm)
 {
 	if (dst == NULL || src == NULL) {
 		return KNOT_EINVAL;
 	}
 
-	dst->type = src->type;
-	dst->additional = src->additional;
-	dst->rclass = src->rclass;
-
-	dst->owner = knot_dname_copy(src->owner, mm);
-	if (dst->owner == NULL) {
+	knot_dname_t *owner_cpy = knot_dname_copy(src->owner, mm);
+	if (owner_cpy == NULL) {
 		return KNOT_ENOMEM;
 	}
-	knot_rrs_init(&dst->rrs);
+
+	knot_rrset_init(dst, owner_cpy, src->type, src->rclass);
 	int ret = knot_rrs_copy(&dst->rrs, &src->rrs, mm);
 	if (ret != KNOT_EOK) {
 		knot_dname_free(&dst->owner, mm);
 		return ret;
 	}
 
+	dst->additional = src->additional;
+
 	return KNOT_EOK;
 }
 
@@ -76,13 +74,11 @@ static int dname_cname_synth(const knot_rrset_t *dname_rr,
 	}
 	dbg_ns("%s(%p, %p)\n", __func__, dname_rr, qname);
 
-	cname_rrset->owner = knot_dname_copy(qname, mm);
-	if (cname_rrset->owner == NULL) {
+	knot_dname_t *owner_copy = knot_dname_copy(qname, mm);
+	if (owner_copy == NULL) {
 		return KNOT_ENOMEM;
 	}
-	cname_rrset->type = KNOT_RRTYPE_CNAME;
-	cname_rrset->rclass = KNOT_CLASS_IN;
-	knot_rrs_init(&cname_rrset->rrs);
+	knot_rrset_init(cname_rrset, owner_copy, KNOT_RRTYPE_CNAME, dname_rr->type);
 
 	/* Replace last labels of qname with DNAME. */
 	const knot_dname_t *dname_wire = dname_rr->owner;
@@ -132,9 +128,9 @@ static int put_rrsig(const knot_dname_t *sig_owner, uint16_t type,
                      knot_rrinfo_t *rrinfo,
                      struct query_data *qdata)
 {
-	knot_rrset_t synth_sig;
-	knot_rrs_init(&synth_sig.rrs);
-	int ret = knot_synth_rrsig(type, &rrsigs->rrs, &synth_sig.rrs, qdata->mm);
+	knot_rrs_t synth_rrs;
+	knot_rrs_init(&synth_rrs);
+	int ret = knot_synth_rrsig(type, &rrsigs->rrs, &synth_rrs, qdata->mm);
 	if (ret == KNOT_ENOENT) {
 		// No signature
 		return KNOT_EOK;
@@ -142,21 +138,17 @@ static int put_rrsig(const knot_dname_t *sig_owner, uint16_t type,
 	if (ret != KNOT_EOK) {
 		return ret;
 	}
-	synth_sig.owner = knot_dname_copy(sig_owner, qdata->mm);
-	if (synth_sig.owner == NULL) {
-		knot_rrs_clear(&synth_sig.rrs, qdata->mm);
-	}
-	synth_sig.type = KNOT_RRTYPE_RRSIG;
-	synth_sig.rclass = KNOT_CLASS_IN;
-	synth_sig.additional = NULL;
+	knot_dname_t *owner_copy = knot_dname_copy(sig_owner, qdata->mm);
+	knot_rrset_t synth_rrsig;
+	knot_rrset_init(&synth_rrsig, owner_copy, rrsigs->type, rrsigs->rclass);
+	synth_rrsig.rrs = synth_rrs;
 	struct rrsig_info *info = mm_alloc(qdata->mm, sizeof(struct rrsig_info));
 	if (info == NULL) {
 		ERR_ALLOC_FAILED;
-		knot_dname_free(&synth_sig.owner, qdata->mm);
-		knot_rrs_clear(&synth_sig.rrs, qdata->mm);
+		knot_rrset_clear(&synth_rrsig, qdata->mm);
 		return KNOT_ENOMEM;
 	}
-	info->synth_rrsig = synth_sig;
+	info->synth_rrsig = synth_rrsig;
 	info->rrinfo = rrinfo;
 	add_tail(&qdata->rrsigs, &info->n);
 
@@ -168,7 +160,8 @@ static int put_rrsig(const knot_dname_t *sig_owner, uint16_t type,
  */
 static int put_answer(knot_pkt_t *pkt, uint16_t type, struct query_data *qdata)
 {
-	knot_rrset_t rrset = { 0 };
+	knot_rrset_t rrset;
+	knot_rrset_init_empty(&rrset);
 
 	/* Wildcard expansion or exact match, either way RRSet owner is
 	 * is QNAME. We can fake name synthesis by setting compression hint to
@@ -255,11 +248,10 @@ static int put_authority_soa(knot_pkt_t *pkt, struct query_data *qdata,
 	uint32_t min = knot_rrs_soa_minimum(&soa_rrset.rrs);
 	if (min < knot_rrset_rr_ttl(&soa_rrset, 0)) {
 		knot_rrset_t copy;
-		ret = move_rrset(&copy, &soa_rrset, &pkt->mm);
-		if (ret != KNOT_EOK) {
-			return ret;
-		}
-		knot_rrset_rr_set_ttl(&soa_rrset, 0, min);
+		knot_dname_t *dname_cpy = knot_dname_copy(soa_rrset.owner, &pkt->mm);
+		knot_rrset_init(&copy, dname_cpy, soa_rrset.type, soa_rrset.rclass);
+		knot_rrs_copy(&copy.rrs, &soa_rrset.rrs, &pkt->mm);
+		knot_rrset_rr_set_ttl(&copy, 0, min);
 
 		flags |= KNOT_PF_FREE;
 		soa_rrset = copy;
@@ -267,8 +259,7 @@ static int put_authority_soa(knot_pkt_t *pkt, struct query_data *qdata,
 
 	ret = ns_put_rr(pkt, &soa_rrset, &rrsigs, COMPR_HINT_NONE, flags, qdata);
 	if (ret != KNOT_EOK && (flags & KNOT_PF_FREE)) {
-		knot_dname_free(&soa_rrset.owner, &pkt->mm);
-		knot_rrs_clear(&soa_rrset.rrs, &pkt->mm);
+		knot_rrset_clear(&soa_rrset, &pkt->mm);
 	}
 
 	return ret;
@@ -675,13 +666,11 @@ static int solve_additional_dnssec(int state, knot_pkt_t *pkt, struct query_data
 	}
 }
 
-int ns_put_rr(knot_pkt_t *pkt, knot_rrset_t *rr,
-              knot_rrset_t *rrsigs, uint16_t compr_hint,
+int ns_put_rr(knot_pkt_t *pkt, const knot_rrset_t *rr,
+              const knot_rrset_t *rrsigs, uint16_t compr_hint,
               uint32_t flags, struct query_data *qdata)
 {
-	/* RFC3123 s.6 - empty APL is valid, ignore other empty RRs. */
-	if (knot_rrset_rr_count(rr) < 1 &&
-	    rr->type != KNOT_RRTYPE_APL) {
+	if (knot_rrset_rr_count(rr) < 1) {
 		dbg_ns("%s: refusing to put empty RR of type %u\n", __func__, rr->type);
 		return KNOT_EMALF;
 	}
@@ -697,26 +686,25 @@ int ns_put_rr(knot_pkt_t *pkt, knot_rrset_t *rr,
 	 * we can just insert RRSet and fake synthesis by using compression
 	 * hint. */
 	int ret = KNOT_EOK;
+	knot_rrset_t to_add;
 	if (compr_hint == COMPR_HINT_NONE && expand) {
-		rr->owner = (knot_dname_t *)qdata->name;
-		knot_rrset_t copy;
-		int ret = move_rrset(&copy, rr, &pkt->mm);
-		if (ret != KNOT_EOK) {
-			return ret;
-		}
+		knot_dname_t *qname_cpy = knot_dname_copy(qdata->name, &pkt->mm);
+		knot_rrset_init(&to_add, qname_cpy, rr->type, rr->rclass);
+		knot_rrs_copy(&to_add.rrs, &rr->rrs, &pkt->mm);
+		to_add.additional = rr->additional;
 		flags |= KNOT_PF_FREE;
-		*rr = copy;
+	} else {
+		to_add = *rr;
 	}
 
 	uint16_t prev_count = pkt->rrset_count;
-	ret = knot_pkt_put(pkt, compr_hint, rr, flags);
-	if (ret != KNOT_EOK) {
-		knot_dname_free(&rr->owner, &pkt->mm);
-		knot_rrs_clear(&rr->rrs, &pkt->mm);
+	ret = knot_pkt_put(pkt, compr_hint, &to_add, flags);
+	if (ret != KNOT_EOK && (flags & KNOT_PF_FREE)) {
+		knot_rrset_clear(&to_add, &pkt->mm);
 		return ret;
 	}
 
-	bool inserted = (prev_count != pkt->rrset_count);
+	const bool inserted = (prev_count != pkt->rrset_count);
 	if (inserted &&
 	    !knot_rrset_empty(rrsigs) && rr->type != KNOT_RRTYPE_RRSIG) {
 		// Get rrinfo of just inserted RR.
diff --git a/src/knot/nameserver/internet.h b/src/knot/nameserver/internet.h
index 5bf5354d3..1969f7f68 100644
--- a/src/knot/nameserver/internet.h
+++ b/src/knot/nameserver/internet.h
@@ -74,8 +74,8 @@ int internet_query_plan(struct query_plan *plan);
  *
  * \return KNOT_E*
  */
-int ns_put_rr(knot_pkt_t *pkt, knot_rrset_t *rr,
-              knot_rrset_t *rrsigs, uint16_t compr_hint,
+int ns_put_rr(knot_pkt_t *pkt, const knot_rrset_t *rr,
+              const knot_rrset_t *rrsigs, uint16_t compr_hint,
               uint32_t flags, struct query_data *qdata);
 
 /*! \brief Require given QUERY TYPE or return error code. */
diff --git a/src/libknot/packet/pkt.c b/src/libknot/packet/pkt.c
index 6620dbfb8..9e5acbb04 100644
--- a/src/libknot/packet/pkt.c
+++ b/src/libknot/packet/pkt.c
@@ -26,12 +26,6 @@
 #include "libknot/tsig.h"
 #include "libknot/tsig-op.h"
 
-static void clear_pkt_rr(knot_rrset_t *rr, mm_ctx_t *mm)
-{
-	knot_dname_free(&rr->owner, mm);
-	knot_rrs_clear(&rr->rrs, mm);
-}
-
 /*! \brief Scan packet for RRSet existence. */
 static bool pkt_contains(const knot_pkt_t *packet,
 			 const knot_rrset_t *rrset)
@@ -58,7 +52,7 @@ static void pkt_free_data(knot_pkt_t *pkt)
 	/* Free RRSets if applicable. */
 	for (uint16_t i = 0; i < pkt->rrset_count; ++i) {
 		if (pkt->rr_info[i].flags & KNOT_PF_FREE) {
-			clear_pkt_rr(&pkt->rr[i], &pkt->mm);
+			knot_rrset_clear(&pkt->rr[i], &pkt->mm);
 		}
 	}
 
@@ -673,7 +667,7 @@ static int knot_pkt_rr_from_wire(const uint8_t *wire, size_t *pos,
 
 	if (size - *pos < rdlength) {
 		dbg_packet("%s: not enough data to parse RDATA\n", __func__);
-		clear_pkt_rr(rrset, mm);
+		knot_rrset_clear(rrset, mm);
 		return KNOT_EMALF;
 	}
 
@@ -685,7 +679,7 @@ static int knot_pkt_rr_from_wire(const uint8_t *wire, size_t *pos,
 	                                         rdlength, mm);
 	if (ret != KNOT_EOK) {
 		dbg_packet("%s: couldn't parse RDATA (%d)\n", __func__, ret);
-		clear_pkt_rr(rrset, mm);
+		knot_rrset_clear(rrset, mm);
 		return ret;
 	}
 
-- 
GitLab