From b44194968513d3285c1484e7acb148e13c906941 Mon Sep 17 00:00:00 2001
From: Jan Kadlec <jan.kadlec@nic.cz>
Date: Thu, 27 Mar 2014 15:24:12 +0100
Subject: [PATCH] new_node: Copy dnames when KNOT_PF_FREE is set.

- not perfect, but without this there'd be no way to tell whether to
  free the owner or not.
---
 src/knot/nameserver/internet.c | 24 ++++++++++++++++++------
 src/knot/updates/xfr-in.c      |  2 +-
 src/libknot/packet/pkt.c       | 12 +++++-------
 src/libknot/rr.c               |  8 --------
 src/libknot/rr.h               |  1 -
 5 files changed, 24 insertions(+), 23 deletions(-)

diff --git a/src/knot/nameserver/internet.c b/src/knot/nameserver/internet.c
index d53e78051..4e067ba4f 100644
--- a/src/knot/nameserver/internet.c
+++ b/src/knot/nameserver/internet.c
@@ -62,7 +62,10 @@ 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_t *)qname;
+	cname_rrset->owner = knot_dname_copy(qname, mm);
+	if (cname_rrset->owner == NULL) {
+		return KNOT_ENOMEM;
+	}
 	cname_rrset->type = KNOT_RRTYPE_CNAME;
 	cname_rrset->rclass = KNOT_CLASS_IN;
 	knot_rrs_init(&cname_rrset->rrs);
@@ -131,14 +134,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_t *)sig_owner;
+	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;
-	struct rrsig_info *info = mm_alloc(qdata->mm,
-	                                   sizeof(struct rrsig_info));
+	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);
 		return KNOT_ENOMEM;
 	}
@@ -244,14 +250,20 @@ static int put_authority_soa(knot_pkt_t *pkt, struct query_data *qdata,
 		if (ret != KNOT_EOK) {
 			return ret;
 		}
-
 		knot_rrset_rr_set_ttl(&soa_rrset, 0, min);
+		
+		soa_rrset.owner = knot_dname_copy(soa_rrset.owner, &pkt->mm);
+		if (soa_rrset.owner == NULL) {
+			knot_rrs_clear(&soa_rrset.rrs, &pkt->mm);
+			return KNOT_ENOMEM;
+		}
 		flags |= KNOT_PF_FREE;
 	}
 
 	ret = ns_put_rr(pkt, &soa_rrset, &rrsigs, COMPR_HINT_NONE, flags, qdata);
 	if (ret != KNOT_EOK && (flags & KNOT_PF_FREE)) {
-		knot_rrs_free(&soa_rrset.rrs, &pkt->mm);
+		knot_dname_free(&soa_rrset.owner, &pkt->mm);
+		knot_rrs_clear(&soa_rrset.rrs, &pkt->mm);
 	}
 
 	return ret;
diff --git a/src/knot/updates/xfr-in.c b/src/knot/updates/xfr-in.c
index 47d86cf90..0d30d43b1 100644
--- a/src/knot/updates/xfr-in.c
+++ b/src/knot/updates/xfr-in.c
@@ -132,7 +132,7 @@ int xfrin_create_ixfr_query(const zone_t *zone, knot_pkt_t *pkt)
 	knot_node_t *apex = zone->contents->apex;
 	knot_rrset_t soa = RRSET_INIT(apex, KNOT_RRTYPE_SOA);
 	knot_pkt_begin(pkt, KNOT_AUTHORITY);
-	ret = knot_pkt_put(pkt, COMPR_HINT_QNAME, &soa, KNOT_PF_FREE);
+	ret = knot_pkt_put(pkt, COMPR_HINT_QNAME, &soa, 0);
 	return ret;
 }
 
diff --git a/src/libknot/packet/pkt.c b/src/libknot/packet/pkt.c
index 7bcc02407..2e60fbda4 100644
--- a/src/libknot/packet/pkt.c
+++ b/src/libknot/packet/pkt.c
@@ -26,7 +26,7 @@
 #include "libknot/tsig.h"
 #include "libknot/tsig-op.h"
 
-static void free_pkt_rr(knot_rrset_t *rr, mm_ctx_t *mm)
+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);
@@ -59,7 +59,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) {
-			knot_rrs_clear(&pkt->rr[i].rrs, &pkt->mm);
+			clear_pkt_rr(&pkt->rr[i], &pkt->mm);
 		}
 	}
 
@@ -659,7 +659,7 @@ static int knot_pkt_merge_rr(knot_pkt_t *pkt, knot_rrset_t *rr, unsigned flags)
 			}
 
 			dbg_packet("%s: merged RR %p\n", __func__, rr);
-			free_pkt_rr(rr, &pkt->mm);
+			clear_pkt_rr(rr, &pkt->mm);
 			return KNOT_EOK;
 		}
 	}
@@ -706,8 +706,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__);
-		knot_dname_free(&owner, mm);
-		knot_rrs_clear(&rrset->rrs, mm);
+		clear_pkt_rr(rrset, mm);
 		return KNOT_EMALF;
 	}
 
@@ -718,8 +717,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);
-		knot_dname_free(&owner, mm);
-		knot_rrs_clear(&rrset->rrs, mm);
+		clear_pkt_rr(rrset, mm);
 		return ret;
 	}
 
diff --git a/src/libknot/rr.c b/src/libknot/rr.c
index d76eccae9..d6642e8d5 100644
--- a/src/libknot/rr.c
+++ b/src/libknot/rr.c
@@ -276,14 +276,6 @@ void knot_rrs_init(knot_rrs_t *rrs)
 	}
 }
 
-void knot_rrs_free(knot_rrs_t *rrs, mm_ctx_t *mm)
-{
-	if (rrs) {
-		mm_free(mm, rrs->data);
-		mm_free(mm, rrs);
-	}
-}
-
 void knot_rrs_clear(knot_rrs_t *rrs, mm_ctx_t *mm)
 {
 	if (rrs) {
diff --git a/src/libknot/rr.h b/src/libknot/rr.h
index cd0640e7c..4cb4cf2f7 100644
--- a/src/libknot/rr.h
+++ b/src/libknot/rr.h
@@ -43,7 +43,6 @@ uint8_t* knot_rrs_create_rr_at_pos(knot_rrs_t *rrs,
                                    size_t pos, uint16_t size,
                                    uint32_t ttl, mm_ctx_t *mm);
 int knot_rrs_remove_rr_at_pos(knot_rrs_t *rrs, size_t pos, mm_ctx_t *mm);
-void knot_rrs_free(knot_rrs_t *rrs, mm_ctx_t *mm);
 void knot_rrs_clear(knot_rrs_t *rrs, mm_ctx_t *mm);
 int knot_rr_cmp(const knot_rr_t *rr1, const knot_rr_t *rr2);
 bool knot_rrs_eq(const knot_rrs_t *rrs1, const knot_rrs_t *rrs2);
-- 
GitLab