diff --git a/src/libknot/rrset.c b/src/libknot/rrset.c
index 492548b6314006e21aa832f3c5248b49113bc9b2..ada1029f724ddd9ddeb939d07e19950d45c00739 100644
--- a/src/libknot/rrset.c
+++ b/src/libknot/rrset.c
@@ -82,7 +82,7 @@ static uint8_t *rrset_rdata_pointer(const knot_rrset_t *rrset,
 
 void knot_rrset_rdata_dump(const knot_rrset_t *rrset, size_t rdata_pos)
 {
-	fprintf(stderr, "      ------- RDATA pos=%d -------\n", rdata_pos);
+	fprintf(stderr, "      ------- RDATA pos=%zu -------\n", rdata_pos);
 	if (rrset->rdata_count == 0) {
 		fprintf(stderr, "      There are no rdata in this RRset!\n");
 		fprintf(stderr, "      ------- RDATA -------\n");
@@ -114,7 +114,7 @@ void knot_rrset_rdata_dump(const knot_rrset_t *rrset, size_t rdata_pos)
 			hex_print((char *)(rdata + offset), item);
 			offset += item;
 		} else if (descriptor_item_is_remainder(item)) {
-			fprintf(stderr, "block=%d Remainder (size=%d):\n",
+			fprintf(stderr, "block=%d Remainder (size=%zu):\n",
 			        i, rrset_rdata_item_size(rrset,
 			                                 rdata_pos) - offset);
 			hex_print((char *)(rdata + offset),
@@ -1166,21 +1166,22 @@ int knot_rrset_deep_copy(const knot_rrset_t *from, knot_rrset_t **to,
 	       sizeof(uint32_t) * from->rdata_count);
 	/* Here comes the hard part. */
 	if (copy_rdata_dnames) {
-		knot_dname_t *dname_from = NULL;
+		unsigned blk = 0;
+		knot_dname_t **dname_from = NULL;
 		knot_dname_t **dname_to = NULL;
 		knot_dname_t *dname_copy = NULL;
-		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);
+		while ((dname_from = knot_rrset_get_next_dname(from, dname_from, &blk))) {
 dbg_rrset_exec_detail(
+			char *name = knot_dname_to_str(*dname_from);
 			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, i);
+			size_t off = (uint8_t*)dname_from - from->rdata;
+			dname_to = (knot_dname_t **)((*to)->rdata + off);
 			/* These pointers have to be the same. */
-			assert(dname_from == *dname_to);
-			dname_copy = knot_dname_deep_copy(dname_from);
+			assert(*dname_from == *dname_to);
+			dname_copy = knot_dname_deep_copy(*dname_from);
 			if (dname_copy == NULL) {
 				dbg_rrset("rrset: deep_copy: Cannot copy RDATA"
 				          " dname.\n");
@@ -1883,8 +1884,8 @@ 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(
+/* TODO rewrite in the same fashion as knot_rrset_get_next_dname. */
+static knot_dname_t **knot_rrset_rdata_get_next_dname_pointer (
 	const knot_rrset_t *rrset,
 	knot_dname_t **prev_dname, size_t pos)
 {
@@ -1952,30 +1953,6 @@ static knot_dname_t **knot_rrset_rdata_get_next_dname_pointer(
 	return NULL;
 }
 
-knot_dname_t *knot_rrset_get_next_dname(const knot_rrset_t *rrset,
-                                        knot_dname_t *prev_dname, size_t pos)
-{
-	if (rrset == NULL) {
-		return NULL;
-	}
-	
-	knot_dname_t **pr;
-	if (prev_dname == NULL) {
-		pr = NULL;
-	} else {
-		pr = &prev_dname;
-	}
-	
-	knot_dname_t **dp =
-		knot_rrset_get_next_dname_pointer(rrset, pr, pos);
-	
-	if (dp != NULL) {
-		return *dp;
-	} else {
-		return NULL;
-	}
-}
-
 static int rrset_type_multiple_dnames(const knot_rrset_t *rrset)
 {
 	if (rrset->type == KNOT_RRTYPE_RP || rrset->type == KNOT_RRTYPE_MINFO) {
@@ -1985,79 +1962,46 @@ static int rrset_type_multiple_dnames(const knot_rrset_t *rrset)
 	}
 }
 
-knot_dname_t **knot_rrset_get_next_dname_pointer(const knot_rrset_t *rrset,
-                                                 knot_dname_t **prev_dname,
-                                                 size_t pos)
+knot_dname_t **knot_rrset_get_next_dname(const knot_rrset_t *rrset,
+                                                 knot_dname_t **prev,
+                                                 unsigned *blk)
 {
-	if (rrset == NULL) {
+	if (rrset == NULL || rrset->rdata_count == 0) {
 		return NULL;
 	}
 
-	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;
-		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])) {
-				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])) {
-				uint32_t remainder_size =
-					rrset_rdata_item_size(rrset, pos) - offset;
-				offset += remainder_size;
-			} else {
-				assert(rrset->type == KNOT_RRTYPE_NAPTR);
-				return (knot_dname_t **)(rdata + offset);
+	/* Convert ptr for easier manipulation. */
+	uint8_t *p = (uint8_t *)prev;
+	if (p == NULL) { /* Check first. */
+		p = rrset->rdata;
+	} else {         /* Next block. */
+		p += sizeof(knot_dname_t **);
+		++*blk;
+	}
+	
+	/* Find next dname in rdata or EOB. */
+	const rdata_descriptor_t *desc = get_rdata_descriptor(rrset->type);
+	const uint8_t *np = rrset->rdata + rrset->rdata_indices[rrset->rdata_count - 1];
+	while(p < np) {
+		if (desc->block_types[*blk] == KNOT_RDATA_WF_END) *blk = 0;
+
+		if (descriptor_item_is_dname(desc->block_types[*blk])) {
+			return (knot_dname_t **)p;
+		} else if (descriptor_item_is_fixed(desc->block_types[*blk])) {
+			p += desc->block_types[*blk];
+		} else if (descriptor_item_is_remainder(desc->block_types[*blk])) {
+			size_t off = p - rrset->rdata;
+			for (unsigned k = 0; k < rrset->rdata_count; ++k) {
+				if (off < rrset->rdata_indices[k]) {
+					p = rrset->rdata + rrset->rdata_indices[k];
+					break;
+				}
 			}
+		} else {
+			assert(rrset->type == KNOT_RRTYPE_NAPTR);
+			return (knot_dname_t **)p;
 		}
+		++*blk; /* Didn't find dname in this block. */
 	}
 
 	return NULL;
@@ -2344,7 +2288,7 @@ static int rrset_deserialize_rr(knot_rrset_t *rrset, size_t rdata_pos,
 			memcpy(&dname_size, stream + stream_offset, 1);
 			stream_offset += 1;
 			knot_dname_t *dname =
-				knot_dname_new_from_wire((char *)(stream + stream_offset),
+				knot_dname_new_from_wire(stream + stream_offset,
 			                                 dname_size, NULL);
 			memcpy(rdata + rdata_offset, &dname,
 			       sizeof(knot_dname_t *));
diff --git a/src/libknot/rrset.h b/src/libknot/rrset.h
index 3314c4d352273b02845b768535103ef41e8d903f..c568e5833c8edd085bc809a2994619212bacf903 100644
--- a/src/libknot/rrset.h
+++ b/src/libknot/rrset.h
@@ -447,12 +447,17 @@ const knot_dname_t *knot_rrset_rdata_minfo_first_dname(const knot_rrset_t *rrset
 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, size_t pos);
-
-knot_dname_t **knot_rrset_get_next_dname_pointer(const knot_rrset_t *rrset,
-                                                 knot_dname_t **prev_dname,
-                                                 size_t pos);
+/*!
+ * \brief Find next dname in rrset relative to prev.
+ *
+ * \param rrset Inspected rrset.
+ * \param prev Pointer to previous dname.
+ * \param blk Pointer to current block id (should be initialized to 0 on start).
+ * \return next dname or NULL.
+ */
+knot_dname_t **knot_rrset_get_next_dname(const knot_rrset_t *rrset,
+                                                 knot_dname_t **prev,
+                                                 unsigned *blk);
 
 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 75e69eeacb3d7243117e3ad15117003adf78dfe4..1686847609a0faf56a57587bf3353bad668332f4 100644
--- a/src/libknot/zone/zone-contents.c
+++ b/src/libknot/zone/zone-contents.c
@@ -284,16 +284,13 @@ static void knot_zone_contents_adjust_rdata_in_rrset(knot_rrset_t *rrset,
                                                      knot_zone_contents_t *zone,
                                                      knot_node_t *node)
 {
-	knot_dname_t **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;
-		}
+	unsigned i = 0;
+	knot_dname_t **dn = NULL;
+	while((dn = knot_rrset_get_next_dname(rrset, dn, &i))) {
 		knot_zone_contents_adjust_rdata_dname(zone,
 		                                      lookup_tree,
 		                                      node,
-		                                      dname);
+		                                      dn);
 	}
 }
 
@@ -2569,11 +2566,11 @@ static void knot_zc_integrity_check_dnames_in_rrset(const knot_rrset_t *rrset,
 	                        check_data->contents,
 	                        knot_rrset_owner(rrset), name);
 	
-	knot_dname_t *dname = NULL;
-	for (uint16_t i = 0; i < knot_rrset_rdata_rr_count(rrset); ++i) {
-		dname = knot_rrset_get_next_dname(rrset, dname, i);
+	unsigned blk = 0;
+	knot_dname_t **dname = NULL;
+	while ((dname = knot_rrset_get_next_dname(rrset, dname, &blk))) {
 		check_data->errors += knot_zc_integrity_check_find_dname(
-		                        check_data->contents, dname, name);
+		                        check_data->contents, *dname, name);
 	}
 }
 
@@ -2871,17 +2868,16 @@ 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. */
-		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;
+		unsigned blk = 0;
+		knot_dname_t **dname = NULL;
+		while ((dname = knot_rrset_get_next_dname(rrsets[i], dname, &blk))) {
+			if (*dname == in_data->dname) {
+				in_data->found_dname = *dname;
 				in_data->stopped = 1;
 				return;
-			} else if (knot_dname_compare(dname,
+			} else if (knot_dname_compare(*dname,
 			                              in_data->dname) == 0) {
-				in_data->found_dname = dname;
+				in_data->found_dname = *dname;
 				in_data->stopped = 1;
 				return;
 			}
diff --git a/src/tests/libknot/libknot/rrset_tests.c b/src/tests/libknot/libknot/rrset_tests.c
index 62abe61a4d08f5a922d426f167bc3c68b3b4fa76..d2a1e131e57d4b83324ee461b028b420d9b00685 100644
--- a/src/tests/libknot/libknot/rrset_tests.c
+++ b/src/tests/libknot/libknot/rrset_tests.c
@@ -1089,19 +1089,20 @@ static int test_rrset_get_next_dname()
 	knot_dname_t *dname1 = NULL;
 	knot_dname_t *dname2 = NULL;
 	
-	knot_dname_t *dname = NULL;
-	dname = knot_rrset_get_next_dname(rrset, dname, 0);
-	if (dname != dname1) {
+	unsigned blk = 0;
+	knot_dname_t **dname = NULL;
+	dname = knot_rrset_get_next_dname(rrset, dname, &blk);
+	if (!dname || *dname != dname1) {
 		diag("Failed to extract correct first DNAME from RRSet.\n");
 		return 0;
 	}
-	dname = knot_rrset_get_next_dname(rrset, dname, 0);
-	if (dname != dname2) {
+	dname = knot_rrset_get_next_dname(rrset, dname, &blk);
+	if (!dname || *dname != dname2) {
 		diag("Failed to extract correct second DNAME from RRSet.\n");
 		return 0;
 	}
 	
-	dname = knot_rrset_get_next_dname(rrset, dname, 0);
+	dname = knot_rrset_get_next_dname(rrset, dname, &blk);
 	if (dname != NULL) {
 		diag("Failed to return NULL after all DNAMEs "
 		     "have been extracted.\n");
@@ -1109,8 +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, 0);
+	dname = knot_rrset_get_next_dname(rrset, dname, &blk);
 	if (dname != NULL) {
 		diag("rrset_rdata_get_next_dname() found DNAME in RRSet with "
 		     "no DNAMEs.\n");
@@ -1131,7 +1131,8 @@ 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, 0))) {
+	unsigned blk = 0;
+	while ((dname = knot_rrset_get_next_dname(rrset, dname, &blk))) {
 		if (extracted_dnames[i] != *dname) {
 			diag("Got wrong DNAME from RDATA.");
 			return 0;
@@ -1144,16 +1145,17 @@ static int test_rrset_next_dname_pointer()
 	                     &rrset, 1);
 	dname = NULL;
 	i = 4;
-	while ((dname = knot_rrset_get_next_dname_pointer(rrset, dname, 0))) {
+	blk = 0;
+	while ((dname = knot_rrset_get_next_dname(rrset, dname, &blk))) {
 		memcpy(dname, &test_dnames[i], sizeof(knot_dname_t *));
 		i++;
 	}
 	
-	knot_dname_t *dname_read = NULL;
 	i = 4;
-	while ((dname_read = knot_rrset_get_next_dname(rrset,
-	                                               dname_read, 0))) {
-		if (dname_read != test_dnames[i]) {
+	blk = 0;
+	dname = NULL;
+	while ((dname = knot_rrset_get_next_dname(rrset, dname, &blk))) {
+		if (!dname || *dname != test_dnames[i]) {
 			diag("Rewriting of DNAMEs in RDATA was "
 			     "not successful.\n");
 			knot_rrset_deep_free(&rrset, 1, 1);