From daf7f4d36a19ea5bb2296f87936fdd9460d47587 Mon Sep 17 00:00:00 2001 From: Marek Vavrusa <marek.vavrusa@nic.cz> Date: Fri, 15 Feb 2013 19:22:03 +0100 Subject: [PATCH] Refactored knot_rrset_get_next_dname() for incremental lookup. --- src/libknot/rrset.c | 150 ++++++++---------------- src/libknot/rrset.h | 17 ++- src/libknot/zone/zone-contents.c | 34 +++--- src/tests/libknot/libknot/rrset_tests.c | 30 ++--- 4 files changed, 89 insertions(+), 142 deletions(-) diff --git a/src/libknot/rrset.c b/src/libknot/rrset.c index 492548b63..ada1029f7 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 3314c4d35..c568e5833 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 75e69eeac..168684760 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 62abe61a4..d2a1e131e 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); -- GitLab