From 818d2955936e49339ee13078241f4536d03fe87d Mon Sep 17 00:00:00 2001
From: Jan Kadlec <jan.kadlec@nic.cz>
Date: Wed, 13 Feb 2013 14:32:37 +0100
Subject: [PATCH] Added action apllying function for DNAMEs within RRSet.

- Needed when RRs were destroyed or copied - DNAMEs insided have to be released/retained.
---
 src/libknot/rrset.c | 88 +++++++++++++++++++++++++++++++++++++++++++--
 src/libknot/rrset.h |  5 +++
 2 files changed, 90 insertions(+), 3 deletions(-)

diff --git a/src/libknot/rrset.c b/src/libknot/rrset.c
index 081df133d..355104097 100644
--- a/src/libknot/rrset.c
+++ b/src/libknot/rrset.c
@@ -35,6 +35,28 @@ static const size_t KNOT_RESPONSE_MAX_PTR = 16383;
 /* Non-API functions                                                          */
 /*----------------------------------------------------------------------------*/
 
+static int rrset_retain_dnames_in_rr(knot_dname_t *dname, void *data)
+{
+	UNUSED(data);
+	if (dname == NULL) {
+		return KNOT_EINVAL;
+	}
+	
+	knot_dname_retain(dname);
+	return KNOT_EOK;
+}
+
+static int rrset_release_dnames_in_rr(knot_dname_t *dname, void *data)
+{
+	UNUSED(data);
+	if (dname == NULL) {
+		return KNOT_EINVAL;
+	}
+	
+	knot_dname_release(dname);
+	return KNOT_EOK;
+}
+
 static uint32_t rrset_rdata_offset(const knot_rrset_t *rrset,
                                    size_t pos)
 {
@@ -2273,6 +2295,10 @@ int rrset_deserialize(uint8_t *stream, size_t *stream_size,
 	
 	/* Create new RRSet. */
 	*rrset = knot_rrset_new(owner, type, rclass, ttl);
+	if (*rrset == NULL) {
+		return KNOT_ENOMEM;
+	}
+	
 	(*rrset)->rdata_indices = rdata_indices;
 	(*rrset)->rdata_count = rdata_count;
 	(*rrset)->rdata = xmalloc(rdata_indices[rdata_count - 1]);
@@ -2290,8 +2316,8 @@ int rrset_deserialize(uint8_t *stream, size_t *stream_size,
 		rrset_deserialize_rr((*rrset), i, stream + offset, rdata_size,
 		                     &read);
 		/* TODO handle malformations. */
-		dbg_rrset_detail("rr: deserilaze: RR read size=%d, actual=%d\n",
-		                 read, rdata_size);
+		dbg_rrset_detail("rr: deserialaze: RR read size=%d,"
+		                 "actual=%d\n", read, rdata_size);
 		assert(read == rdata_size);
 		offset += read;
 	}
@@ -2385,6 +2411,15 @@ static int knot_rrset_remove_rdata_pos(knot_rrset_t *rrset, size_t pos)
 	if (rrset == NULL || pos >= rrset->rdata_count) {
 		return KNOT_EINVAL;
 	}
+	
+	/* Handle DNAMEs inside RDATA. */
+	int ret = rrset_rr_dnames_apply(rrset, pos, rrset_release_dnames_in_rr,
+	                                NULL);
+	if (ret != KNOT_EOK) {
+		dbg_rrset("rr: remove_rdata_pos: Could not release DNAMEs "
+		          "within RDATA (%s).\n", knot_strerror(ret));
+		return ret;
+	}
 
 	/* Reorganize the actual RDATA array. */
 	uint8_t *rdata_to_remove = rrset_rdata_pointer(rrset, pos);
@@ -2393,7 +2428,6 @@ static int knot_rrset_remove_rdata_pos(knot_rrset_t *rrset, size_t pos)
 		/* Not the last item in array - we need to move the data. */
 		uint8_t *next_rdata = rrset_rdata_pointer(rrset, pos + 1);
 		assert(next_rdata);
-		/* TODO free DNAMES inside. */
 		/* Get size of remaining RDATA. */ 
 		size_t last_rdata_size =
 		                rrset_rdata_item_size(rrset,
@@ -2476,6 +2510,45 @@ int knot_rrset_rdata_reset(knot_rrset_t *rrset)
 	return KNOT_EOK;
 }
 
+int rrset_rr_dnames_apply(knot_rrset_t *rrset, size_t rdata_pos,
+                          int (*func)(knot_dname_t *, void *), void *data)
+{
+	if (rrset == NULL || rdata_pos >= rrset->rdata_count || func == NULL) {
+		return KNOT_EINVAL;
+	}
+	
+	knot_dname_t **dname = NULL;
+	while ((dname = knot_rrset_rdata_get_next_dname_pointer(rrset, dname,
+	                                                        rdata_pos))) {
+		assert(dname);
+		int ret = func(*dname, data);
+		if (ret != KNOT_EOK) {
+			dbg_rrset("rr: rr_dnames_apply: Function could not be"
+			          "applied (%s).\n", knot_strerror(ret));
+			return ret;
+		}
+	}
+	
+	return KNOT_EOK;
+}
+
+int rrset_dnames_apply(knot_rrset_t *rrset, int (*func)(knot_dname_t *, void *),
+                       void *data)
+{
+	if (rrset == NULL || rrset->rdata_count == 0 || func == NULL) {
+		return KNOT_EINVAL;
+	}
+	
+	for (uint16_t i = 0; i < rrset->rdata_count; ++i) {
+		int ret = rrset_rr_dnames_apply(rrset, i, func, data);
+		if (ret != KNOT_EOK) {
+			return ret;
+		}
+	}
+	
+	return KNOT_EOK;
+}
+
 int knot_rrset_add_rr_from_rrset(knot_rrset_t *dest, const knot_rrset_t *source,
                                  size_t rdata_pos)
 {
@@ -2496,6 +2569,15 @@ int knot_rrset_add_rr_from_rrset(knot_rrset_t *dest, const knot_rrset_t *source,
 	/* Copy actual data. */
 	memcpy(rdata, rrset_rdata_pointer(source, rdata_pos), item_size);
 	
+	/* Retain DNAMEs inside RDATA. */
+	int ret = rrset_rr_dnames_apply(dest, rdata_pos,
+	                                rrset_retain_dnames_in_rr, NULL);
+	if (ret != KNOT_EOK) {
+		dbg_rrset("rr: add_rr_from_rrset: Could not retain DNAMEs"
+		          " in RR (%s).\n", knot_strerror(ret));
+		return ret;
+	}
+	
 	return KNOT_EOK;
 }
 
diff --git a/src/libknot/rrset.h b/src/libknot/rrset.h
index 4e1335410..58aa94c7d 100644
--- a/src/libknot/rrset.h
+++ b/src/libknot/rrset.h
@@ -489,6 +489,11 @@ int knot_rrset_find_rr_pos(const knot_rrset_t *rr_search,
                            const knot_rrset_t *rr_input, size_t pos,
                            size_t *pos_out);
 
+int rrset_rr_dnames_apply(knot_rrset_t *rrset, size_t rdata_pos,
+                          int (*func)(knot_dname_t *, void *), void *data);
+
+int rrset_dnames_apply(knot_rrset_t *rrset, int (*func)(knot_dname_t *, void *),
+                       void *data);
 
 #endif /* _KNOT_RRSET_H_ */
 
-- 
GitLab