From 7989f322818ffe3be75de957dce88f46d9e05e84 Mon Sep 17 00:00:00 2001
From: Jan Kadlec <jan.kadlec@nic.cz>
Date: Fri, 15 Feb 2013 16:42:59 +0100
Subject: [PATCH] Refactored knot_rrset_get_next_dname_pointer

- No cycle
- Added some rrset helper functions
- calls of function changed
- TODO: knot_rrset_rdata_get_next_dname_pointer is now obsolete, since it does the same thing
---
 src/libknot/rrset.c                     | 201 +++++++++++++++---------
 src/libknot/rrset.h                     |  17 +-
 src/libknot/zone/zone-contents.c        |  14 +-
 src/tests/libknot/libknot/rrset_tests.c |  14 +-
 4 files changed, 162 insertions(+), 84 deletions(-)

diff --git a/src/libknot/rrset.c b/src/libknot/rrset.c
index 12bc1a034..492548b63 100644
--- a/src/libknot/rrset.c
+++ b/src/libknot/rrset.c
@@ -1169,17 +1169,15 @@ int knot_rrset_deep_copy(const knot_rrset_t *from, knot_rrset_t **to,
 		knot_dname_t *dname_from = NULL;
 		knot_dname_t **dname_to = NULL;
 		knot_dname_t *dname_copy = NULL;
-		while ((dname_from =
-		        knot_rrset_get_next_dname(from, dname_from)) != NULL) {
-dbg_rrset_exec_detail(
+		for (uint16_t i = 0; i < from->rdata_count; ++i) {
+			dname_from = knot_rrset_get_next_dname(from, dname_from, i);
 			char *name = knot_dname_to_str(dname_from);
+dbg_rrset_exec_detail(
 			dbg_rrset_detail("rrset: deep_copy: copying RDATA DNAME"
 			                 "=%s\n", name);
 			free(name);
 );
-			dname_to =
-				knot_rrset_get_next_dname_pointer(*to,
-					dname_to);
+			dname_to = knot_rrset_get_next_dname_pointer(*to, dname_to, i);
 			/* These pointers have to be the same. */
 			assert(dname_from == *dname_to);
 			dname_copy = knot_dname_deep_copy(dname_from);
@@ -1479,6 +1477,64 @@ const knot_dname_t *knot_rrset_rdata_dname_target(const knot_rrset_t *rrset)
 
 /*---------------------------------------------------------------------------*/
 
+const knot_dname_t *knot_rrset_rdata_soa_primary_ns(const knot_rrset_t *rrset)
+{
+	if (rrset == NULL) {
+		return NULL;
+	}
+	knot_dname_t *dname;
+	memcpy(&dname, rrset->rdata, sizeof(knot_dname_t *));
+	return dname;
+}
+
+const knot_dname_t *knot_rrset_rdata_soa_mailbox(const knot_rrset_t *rrset)
+{
+	if (rrset == NULL) {
+		return NULL;
+	}
+	knot_dname_t *dname;
+	memcpy(&dname, rrset->rdata + sizeof(knot_dname_t *),
+	       sizeof(knot_dname_t *));
+	return dname;
+}
+
+const knot_dname_t *knot_rrset_rdata_rp_first_dname(const knot_rrset_t *rrset,
+                                                    size_t pos)
+{
+	if (rrset == NULL || pos >= rrset->rdata_count) {
+		return NULL;
+	}
+	
+	knot_dname_t *dname;
+	memcpy(&dname, knot_rrset_get_rdata(rrset, pos), sizeof(knot_dname_t *));
+	return dname;
+}
+
+const knot_dname_t *knot_rrset_rdata_rp_second_dname(const knot_rrset_t *rrset,
+                                                     size_t pos)
+{
+	if (rrset == NULL || pos >= rrset->rdata_count) {
+		return NULL;
+	}
+	
+	knot_dname_t *dname;
+	memcpy(&dname, knot_rrset_get_rdata(rrset, pos) + sizeof(knot_dname_t *),
+	       sizeof(knot_dname_t *));
+	return dname;
+}
+
+const knot_dname_t *knot_rrset_rdata_minfo_first_dname(const knot_rrset_t *rrset,
+                                                       size_t pos)
+{
+	return knot_rrset_rdata_rp_first_dname(rrset, pos);
+}
+
+const knot_dname_t *knot_rrset_rdata_minfo_second_dname(const knot_rrset_t *rrset,
+                                                        size_t pos)
+{
+	return knot_rrset_rdata_rp_second_dname(rrset, pos);
+}
+
 int64_t knot_rrset_rdata_soa_serial(const knot_rrset_t *rrset)
 {
 	if (rrset == NULL) {
@@ -1492,6 +1548,7 @@ int64_t knot_rrset_rdata_soa_serial(const knot_rrset_t *rrset)
 }
 
 /*---------------------------------------------------------------------------*/
+
 void knot_rrset_rdata_soa_serial_set(knot_rrset_t *rrset, uint32_t serial)
 {
 	if (rrset == NULL) {
@@ -1826,6 +1883,7 @@ const uint8_t *knot_rrset_rdata_nsec3_salt(const knot_rrset_t *rrset,
 	return rrset_rdata_pointer(rrset, pos) + 4;
 }
 
+/* TODO rewrite in the same fashion as knot_rrset_get_next_dname_pointer. */
 static knot_dname_t **knot_rrset_rdata_get_next_dname_pointer(
 	const knot_rrset_t *rrset,
 	knot_dname_t **prev_dname, size_t pos)
@@ -1894,15 +1952,8 @@ static knot_dname_t **knot_rrset_rdata_get_next_dname_pointer(
 	return NULL;
 }
 
-const knot_dname_t *knot_rrset_next_dname(const knot_rrset_t *rrset,
-                                          const knot_dname_t *prev_dname)
-{
-	return (const knot_dname_t *)knot_rrset_get_next_dname(rrset,
-	                                  (knot_dname_t *)prev_dname);
-}
-
 knot_dname_t *knot_rrset_get_next_dname(const knot_rrset_t *rrset,
-                                        knot_dname_t *prev_dname)
+                                        knot_dname_t *prev_dname, size_t pos)
 {
 	if (rrset == NULL) {
 		return NULL;
@@ -1916,8 +1967,7 @@ knot_dname_t *knot_rrset_get_next_dname(const knot_rrset_t *rrset,
 	}
 	
 	knot_dname_t **dp =
-		knot_rrset_get_next_dname_pointer(rrset, pr);
-	
+		knot_rrset_get_next_dname_pointer(rrset, pr, pos);
 	
 	if (dp != NULL) {
 		return *dp;
@@ -1926,45 +1976,77 @@ knot_dname_t *knot_rrset_get_next_dname(const knot_rrset_t *rrset,
 	}
 }
 
+static int rrset_type_multiple_dnames(const knot_rrset_t *rrset)
+{
+	if (rrset->type == KNOT_RRTYPE_RP || rrset->type == KNOT_RRTYPE_MINFO) {
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
 knot_dname_t **knot_rrset_get_next_dname_pointer(const knot_rrset_t *rrset,
-                                                 knot_dname_t **prev_dname)
+                                                 knot_dname_t **prev_dname,
+                                                 size_t pos)
 {
 	if (rrset == NULL) {
 		return NULL;
 	}
-	
-	// Get descriptor
-	const rdata_descriptor_t *desc =
-		get_rdata_descriptor(rrset->type);
-	int next = 0;
-	if (prev_dname == NULL) {
-		next = 1;
-	}
 
-	for (uint16_t pos = 0; pos < rrset->rdata_count; pos++) {
-		//TODO following code needs to be in a function
+	uint8_t *rdata = rrset_rdata_pointer(rrset, pos);
+	if (rrset->type == KNOT_RRTYPE_SOA) {
+		/* SOA only has one RR. */
+		knot_dname_t *d1 = knot_rrset_rdata_soa_primary_ns(rrset);
+		if (prev_dname == NULL) {
+			/* NULL - first DNAME. */
+			dbg_rrset_detail("rr: next_dname_pointer: Returning "
+			                 "first SOA DNAME.\n");
+			return (knot_dname_t **)rdata;
+		} else if (*prev_dname == d1) {
+			/* Return second DNAME. */
+			dbg_rrset_detail("rr: next_dname_pointer: Returning "
+			                 "second SOA DNAME.\n");
+			return (knot_dname_t **)(rdata + sizeof(knot_dname_t *));
+		} else {
+			/* Second DNAME already returned. */
+			dbg_rrset_detail("rr: next_dname_pointer: Returning "
+			                 "NULL.\n");
+			assert(*prev_dname == knot_rrset_rdata_soa_mailbox(rrset));
+			return NULL;
+		}
+	} else if (rrset_type_multiple_dnames(rrset)) {
+		/* RP or MINFO - no matter, DNAMEs on same position. */
+		knot_dname_t *d1 = knot_rrset_rdata_rp_first_dname(rrset, pos);
+		if (prev_dname == NULL) {
+			dbg_rrset_detail("rr: next_dname_pointer: Returning "
+			                 "first RP/MINFO DNAME.\n");
+			assert(pos == 0);
+			/* NULL - first DNAME. */
+			return (knot_dname_t **)rdata;
+		} else if (*prev_dname == d1) {
+			/* Return second DNAME. */
+			dbg_rrset_detail("rr: next_dname_pointer: Returning "
+			                 "second RP/MINFO DNAME.\n");
+			return (knot_dname_t **)(rdata + sizeof(knot_dname_t *));
+		} else if (pos != rrset->rdata_count) {
+			dbg_rrset_detail("rr: next_dname_pointer: Returning "
+			                 "first RP/MINFO DNAME (pos != 0).\n");
+			/* Not first in first RR, but first in next one. */
+			assert(pos != 0);
+			return (knot_dname_t **)rdata;
+		} else {
+			dbg_rrset_detail("rr: next_dname_pointer: Returning "
+			                 "NULL.\n");
+			return NULL;
+		}
+	} else {
+		/* Return DNAME, if any. */
 		size_t offset = 0;
-		uint8_t *rdata = rrset_rdata_pointer(rrset, pos);
-		// Cycle through blocks and fid dnames
-		for (int i = 0; desc->block_types[i] != KNOT_RDATA_WF_END; i++) {
+		const rdata_descriptor_t *desc =
+			get_rdata_descriptor(rrset->type);
+		for (int i = 0; desc->block_types[i] != KNOT_RDATA_WF_END; ++i) {
 			if (descriptor_item_is_dname(desc->block_types[i])) {
-				if (next) {
-					assert(rdata + offset);
-					return (knot_dname_t **)(rdata + offset);
-				}
-			
-				knot_dname_t **dname =
-					(knot_dname_t **)(rdata +
-				                         offset);
-	
-				assert(prev_dname);
-			
-				if (knot_dname_compare_non_canon(*dname,
-				                                 *prev_dname) == 0) {
-					//we need to return next dname
-					next = 1;
-				}
-				offset += sizeof(knot_dname_t *);
+				return (knot_dname_t **)(rdata + offset);
 			} else if (descriptor_item_is_fixed(desc->block_types[i])) {
 				offset += desc->block_types[i];
 			} else if (descriptor_item_is_remainder(desc->block_types[i])) {
@@ -1973,32 +2055,11 @@ knot_dname_t **knot_rrset_get_next_dname_pointer(const knot_rrset_t *rrset,
 				offset += remainder_size;
 			} else {
 				assert(rrset->type == KNOT_RRTYPE_NAPTR);
-				offset += rrset_rdata_naptr_bin_chunk_size(rrset, pos);
-				if (next) {
-					return (knot_dname_t **)(rdata + offset);
-				}
-			
-				knot_dname_t *dname =
-					(knot_dname_t *)(rdata +
-				                         offset);
-			
-				assert(prev_dname);
-			
-				if (knot_dname_compare_non_canon(dname,
-				                                 *prev_dname) == 0) {
-					//we need to return next dname
-					next = 1;
-				}
-			
-				/* 
-				 * Offset does not contain dname from NAPTR yet.
-				 * It should not matter, since this block type
-				 * is the only one in the RR anyway, but to be sure...
-				 */
-				offset += sizeof(knot_dname_t *); // now it does
+				return (knot_dname_t **)(rdata + offset);
 			}
 		}
 	}
+
 	return NULL;
 }
 
diff --git a/src/libknot/rrset.h b/src/libknot/rrset.h
index cae03caa1..3314c4d35 100644
--- a/src/libknot/rrset.h
+++ b/src/libknot/rrset.h
@@ -370,6 +370,9 @@ void knot_rrset_rdata_set_cname_name(knot_rrset_t *rrset,
 void knot_rrset_rdata_set_dname_target(knot_rrset_t *rrset,
                                        const knot_dname_t *target);
 //TODO test
+const knot_dname_t *knot_rrset_rdata_soa_primary_ns(const knot_rrset_t *rrset);
+//TODO test
+const knot_dname_t *knot_rrset_rdata_soa_mailbox(const knot_rrset_t *rrset);
 int64_t knot_rrset_rdata_soa_serial(const knot_rrset_t *rrset);
 //TODO test
 void knot_rrset_rdata_soa_serial_set(knot_rrset_t *rrset, uint32_t serial);
@@ -435,11 +438,21 @@ uint8_t knot_rrset_rdata_nsec3param_salt_length(const knot_rrset_t *rrset);
 //TODO test
 const uint8_t *knot_rrset_rdata_nsec3param_salt(const knot_rrset_t *rrset);
 
+const knot_dname_t *knot_rrset_rdata_rp_first_dname(const knot_rrset_t *rrset,
+                                                    size_t pos);
+const knot_dname_t *knot_rrset_rdata_rp_second_dname(const knot_rrset_t *rrset,
+                                                     size_t pos);
+const knot_dname_t *knot_rrset_rdata_minfo_first_dname(const knot_rrset_t *rrset,
+                                                       size_t pos);
+const knot_dname_t *knot_rrset_rdata_minfo_second_dname(const knot_rrset_t *rrset,
+                                                        size_t pos);
+
 knot_dname_t *knot_rrset_get_next_dname(const knot_rrset_t *rrset,
-                                        knot_dname_t *prev_dname);
+                                        knot_dname_t *prev_dname, size_t pos);
 
 knot_dname_t **knot_rrset_get_next_dname_pointer(const knot_rrset_t *rrset,
-                                                 knot_dname_t **prev_dname);
+                                                 knot_dname_t **prev_dname,
+                                                 size_t pos);
 
 const knot_dname_t *knot_rrset_rdata_ns_name(const knot_rrset_t *rrset,
                                              size_t rdata_pos);
diff --git a/src/libknot/zone/zone-contents.c b/src/libknot/zone/zone-contents.c
index 26e4bfcb7..75e69eeac 100644
--- a/src/libknot/zone/zone-contents.c
+++ b/src/libknot/zone/zone-contents.c
@@ -285,14 +285,16 @@ static void knot_zone_contents_adjust_rdata_in_rrset(knot_rrset_t *rrset,
                                                      knot_node_t *node)
 {
 	knot_dname_t **dname = NULL;
-	while ((dname = knot_rrset_get_next_dname_pointer(rrset, dname)) != NULL) {
+	for (uint16_t i = 0; i < knot_rrset_rdata_rr_count(rrset); ++i) {
+		dname = knot_rrset_get_next_dname_pointer(rrset, dname, i);
+		if (dname == NULL) {
+			continue;
+		}
 		knot_zone_contents_adjust_rdata_dname(zone,
 		                                      lookup_tree,
 		                                      node,
 		                                      dname);
 	}
-	
-	assert(dname == NULL);
 }
 
 /*----------------------------------------------------------------------------*/
@@ -2568,7 +2570,8 @@ static void knot_zc_integrity_check_dnames_in_rrset(const knot_rrset_t *rrset,
 	                        knot_rrset_owner(rrset), name);
 	
 	knot_dname_t *dname = NULL;
-	while ((dname = knot_rrset_get_next_dname(rrset, dname)) != NULL) {
+	for (uint16_t i = 0; i < knot_rrset_rdata_rr_count(rrset); ++i) {
+		dname = knot_rrset_get_next_dname(rrset, dname, i);
 		check_data->errors += knot_zc_integrity_check_find_dname(
 		                        check_data->contents, dname, name);
 	}
@@ -2870,7 +2873,8 @@ static void find_dname_in_rdata(knot_zone_tree_node_t *node, void *data)
 	for (unsigned short i = 0; i < node->node->rrset_count; i++) {
 		knot_dname_t *dname = NULL;
 		/* For all DNAMEs in RRSet. */
-		while ((dname = knot_rrset_get_next_dname(rrsets[i], NULL))!=NULL) {
+		for (uint16_t j = 0; i < knot_rrset_rdata_rr_count(rrsets[i]); ++i) {
+			dname = knot_rrset_get_next_dname(rrsets[i], dname, i);
 			if (dname == in_data->dname) {
 				in_data->found_dname = dname;
 				in_data->stopped = 1;
diff --git a/src/tests/libknot/libknot/rrset_tests.c b/src/tests/libknot/libknot/rrset_tests.c
index 3be812107..62abe61a4 100644
--- a/src/tests/libknot/libknot/rrset_tests.c
+++ b/src/tests/libknot/libknot/rrset_tests.c
@@ -1090,18 +1090,18 @@ static int test_rrset_get_next_dname()
 	knot_dname_t *dname2 = NULL;
 	
 	knot_dname_t *dname = NULL;
-	dname = knot_rrset_get_next_dname(rrset, dname);
+	dname = knot_rrset_get_next_dname(rrset, dname, 0);
 	if (dname != dname1) {
 		diag("Failed to extract correct first DNAME from RRSet.\n");
 		return 0;
 	}
-	dname = knot_rrset_get_next_dname(rrset, dname);
+	dname = knot_rrset_get_next_dname(rrset, dname, 0);
 	if (dname != dname2) {
 		diag("Failed to extract correct second DNAME from RRSet.\n");
 		return 0;
 	}
 	
-	dname = knot_rrset_get_next_dname(rrset, dname);
+	dname = knot_rrset_get_next_dname(rrset, dname, 0);
 	if (dname != NULL) {
 		diag("Failed to return NULL after all DNAMEs "
 		     "have been extracted.\n");
@@ -1110,7 +1110,7 @@ static int test_rrset_get_next_dname()
 	
 	/* Test that RRSet with no DNAMEs in it returns NULL. */
 	dname = NULL;
-	dname = knot_rrset_get_next_dname(rrset, dname);
+	dname = knot_rrset_get_next_dname(rrset, dname, 0);
 	if (dname != NULL) {
 		diag("rrset_rdata_get_next_dname() found DNAME in RRSet with "
 		     "no DNAMEs.\n");
@@ -1131,7 +1131,7 @@ static int test_rrset_next_dname_pointer()
 	extracted_dnames[3] = test_dnames[3];
 	knot_dname_t **dname = NULL;
 	int i = 0;
-	while ((dname = knot_rrset_get_next_dname_pointer(rrset, dname))) {
+	while ((dname = knot_rrset_get_next_dname_pointer(rrset, dname, 0))) {
 		if (extracted_dnames[i] != *dname) {
 			diag("Got wrong DNAME from RDATA.");
 			return 0;
@@ -1144,7 +1144,7 @@ static int test_rrset_next_dname_pointer()
 	                     &rrset, 1);
 	dname = NULL;
 	i = 4;
-	while ((dname = knot_rrset_get_next_dname_pointer(rrset, dname))) {
+	while ((dname = knot_rrset_get_next_dname_pointer(rrset, dname, 0))) {
 		memcpy(dname, &test_dnames[i], sizeof(knot_dname_t *));
 		i++;
 	}
@@ -1152,7 +1152,7 @@ static int test_rrset_next_dname_pointer()
 	knot_dname_t *dname_read = NULL;
 	i = 4;
 	while ((dname_read = knot_rrset_get_next_dname(rrset,
-	                                               dname_read))) {
+	                                               dname_read, 0))) {
 		if (dname_read != test_dnames[i]) {
 			diag("Rewriting of DNAMEs in RDATA was "
 			     "not successful.\n");
-- 
GitLab