Commit 3e3920b8 authored by Jan Kadlec's avatar Jan Kadlec

new_node: Basic set-like operation on knot_rrs_t.

parent bc237b81
......@@ -53,7 +53,7 @@ static int add_rr_to_list(list_t *l, const knot_rrset_t *rr)
ptrnode_t *ptr_n = (ptrnode_t *)n;
knot_rrset_t *rrset = (knot_rrset_t *)ptr_n->d;
if (knot_rrset_equal(rr, rrset, KNOT_RRSET_COMPARE_HEADER)) {
int ret = knot_rrset_merge(rrset, rr, NULL);
int ret = knot_rrs_merge(&rrset->rrs, &rr->rrs, NULL);
if (ret != KNOT_EOK) {
return ret;
}
......@@ -437,19 +437,12 @@ static bool node_empty(const knot_node_t *node, knot_dname_t *owner,
static bool node_contains_rr(const knot_node_t *node,
const knot_rrset_t *rr)
{
knot_rrset_t zone_rrset = knot_node_rrset(node, rr->type);
if (!knot_rrset_empty(&zone_rrset)) {
knot_rrset_t intersection;
const knot_rrs_t *zone_rrs = knot_node_rrs(node, rr->type);
if (zone_rrs) {
assert(rr->rrs.rr_count == 1);
const bool compare_ttls = false;
int ret = knot_rrset_intersection(&zone_rrset, rr,
&intersection, compare_ttls,
NULL);
if (ret != KNOT_EOK) {
return false;
}
const bool contains = !knot_rrset_empty(&intersection);
knot_rrs_clear(&intersection.rrs, NULL);
return contains;
return knot_rrs_member(zone_rrs, knot_rrs_rr(&rr->rrs, 0),
compare_ttls);
} else {
return false;
}
......@@ -775,9 +768,9 @@ static int process_rem_rr(const knot_rrset_t *rr,
}
knot_rrset_t intersection;
const bool compare_ttls = false;
int ret = knot_rrset_intersection(&to_modify, rr, &intersection,
compare_ttls, NULL);
knot_rrset_init(&intersection, to_modify.owner, to_modify.type, KNOT_CLASS_IN);
int ret = knot_rrs_intersect(&to_modify.rrs, &rr->rrs, &intersection.rrs,
NULL);
if (ret != KNOT_EOK) {
return ret;
}
......
......@@ -705,21 +705,19 @@ static bool can_remove(const knot_node_t *node, const knot_rrset_t *rr)
if (node == NULL) {
return false;
}
knot_rrset_t node_rrset = knot_node_rrset(node, rr->type);
if (knot_rrset_empty(&node_rrset)) {
const knot_rrs_t *node_rrs = knot_node_rrs(node, rr->type);
if (node_rrs == NULL) {
return false;
}
knot_rrset_t intersection;
const bool compare_ttls = false;
knot_rrset_intersection(&node_rrset, rr, &intersection,
compare_ttls, NULL);
if (knot_rrset_empty(&intersection)) {
return false;
for (uint16_t i = 0; i < rr->rrs.rr_count; ++i) {
knot_rr_t *rr_cmp = knot_rrs_rr(&rr->rrs, i);
if (knot_rrs_member(node_rrs, rr_cmp, compare_ttls)) {
return true;
}
}
knot_rrs_clear(&intersection.rrs, NULL);
return true;
return false;
}
static int add_old_data(knot_changeset_t *chset, knot_rr_t *old_data,
......@@ -767,23 +765,19 @@ static int remove_rr(knot_node_t *node, const knot_rrset_t *rr,
return ret;
}
knot_rrset_t changed_rrset = knot_node_rrset(node, rr->type);
ret = knot_rrset_remove_rr_using_rrset(&changed_rrset, rr, NULL);
knot_rrs_t *changed_rrs = knot_node_get_rrs(node, rr->type);
ret = knot_rrs_subtract(changed_rrs, &rr->rrs, NULL);
if (ret != KNOT_EOK) {
clear_new_rrs(node, rr->type);
return ret;
}
if (changed_rrset.rrs.rr_count > 0) {
ret = add_new_data(chset, changed_rrset.rrs.data);
if (changed_rrs->rr_count > 0) {
ret = add_new_data(chset, changed_rrs->data);
if (ret != KNOT_EOK) {
knot_rrs_clear(&changed_rrset.rrs, NULL);
knot_rrs_clear(changed_rrs, NULL);
return ret;
}
// Replace data in node with changed data
knot_rrs_t *rrs = knot_node_get_rrs(node, rr->type);
*rrs = changed_rrset.rrs;
} else {
// Removed last RR in RRSet, remove it from node.
knot_node_remove_rrset(node, rr->type);
......
......@@ -25,6 +25,7 @@
#include "knot/other/debug.h"
#include "libknot/libknot.h"
#include "libknot/dnssec/key.h"
#include "libknot/dnssec/rrset-sign.h"
#include "common/base32hex.h"
#include "common/crc.h"
#include "common/descriptor.h"
......@@ -687,10 +688,11 @@ static int check_nsec3_node_in_zone(knot_zone_contents_t *zone,
return KNOT_EOK;
}
const knot_rr_t *nsec3_rr = knot_rrs_rr(nsec3_rrs, 0);
const knot_rrs_t *soa_rrs = knot_node_rrs(zone->apex, KNOT_RRTYPE_SOA);
assert(soa_rrs);
uint32_t minimum_ttl = knot_rrs_soa_minimum(soa_rrs);
if (knot_rrs_rr_ttl(nsec3_rrs, 0) != minimum_ttl) {
if (knot_rr_ttl(nsec3_rr) != minimum_ttl) {
err_handler_handle_error(handler, node,
ZC_ERR_NSEC3_RDATA_TTL, NULL);
}
......
......@@ -204,27 +204,9 @@ static int knot_zone_diff_remove_node(knot_changeset_t *changeset,
static bool rr_exists(const knot_rrset_t *in, const knot_rrset_t *ref,
size_t ref_pos)
{
// Create RRSet with single RR fron 'ref' RRSet, position 'ref_pos'.
knot_rrset_t ref_rr;
knot_rrset_init(&ref_rr, ref->owner, ref->type, ref->rclass);
knot_rr_t *to_add = knot_rrs_rr(&ref->rrs, ref_pos);
int ret = knot_rrs_add_rr(&ref_rr.rrs, to_add, NULL);
if (ret != KNOT_EOK) {
return false;
}
// Do an intersection with 'in' rrset, if non-empty, RR exists.
knot_rrset_t int_rr;
knot_rr_t *to_check = knot_rrs_rr(&ref->rrs, ref_pos);
const bool compare_ttls = true;
ret = knot_rrset_intersection(in, &ref_rr, &int_rr, compare_ttls, NULL);
knot_rrs_clear(&ref_rr.rrs, NULL);
if (ret != KNOT_EOK) {
return false;
}
const bool exists = !knot_rrset_empty(&int_rr);
knot_rrs_clear(&int_rr.rrs, NULL);
return exists;
return knot_rrs_member(&in->rrs, to_check, compare_ttls);
}
static int knot_zone_diff_rdata_return_changes(const knot_rrset_t *rrset1,
......
......@@ -75,6 +75,19 @@ static knot_rr_t *rr_seek(knot_rr_t *d, size_t pos)
return d + offset;
}
static int find_rr_pos(const knot_rrs_t *search_in,
const knot_rr_t *rr)
{
for (uint16_t i = 0; i < search_in->rr_count; ++i) {
const knot_rr_t *search_rr = knot_rrs_rr(search_in, i);
if (knot_rr_cmp(rr, search_rr) == 0) {
return i;
}
}
return KNOT_ENOENT;
}
static int add_rr_at(knot_rrs_t *rrs, const knot_rr_t *rr, size_t pos,
mm_ctx_t *mm)
{
......@@ -127,6 +140,47 @@ static int add_rr_at(knot_rrs_t *rrs, const knot_rr_t *rr, size_t pos,
return KNOT_EOK;
}
static int remove_rr_at(knot_rrs_t *rrs, size_t pos, mm_ctx_t *mm)
{
if (rrs == NULL || pos >= rrs->rr_count) {
return KNOT_EINVAL;
}
knot_rr_t *old_rr = knot_rrs_rr(rrs, pos);
knot_rr_t *last_rr = knot_rrs_rr(rrs, rrs->rr_count - 1);
assert(old_rr);
assert(last_rr);
size_t total_size = knot_rrs_size(rrs);
uint16_t old_size = knot_rr_rdata_size(old_rr);
void *old_threshold = old_rr + knot_rr_array_size(old_size);
void *last_threshold = last_rr + knot_rr_array_size(knot_rr_rdata_size(last_rr));
// Move RDATA
memmove(old_rr, old_threshold,
last_threshold - old_threshold);
if (rrs->rr_count > 1) {
// Realloc RDATA
void *tmp = mm_realloc(mm, rrs->data,
total_size - (knot_rr_array_size(old_size)),
total_size);
if (tmp == NULL) {
ERR_ALLOC_FAILED;
return KNOT_ENOMEM;
} else {
rrs->data = tmp;
}
} else {
// Free RDATA
mm_free(mm, rrs->data);
rrs->data = NULL;
}
rrs->rr_count--;
return KNOT_EOK;
}
uint16_t knot_rr_rdata_size(const knot_rr_t *rr)
{
return ((struct rr_offsets *)rr)->size;
......@@ -215,33 +269,6 @@ knot_rr_t *knot_rrs_rr(const knot_rrs_t *rrs, size_t pos)
return rr_seek(rrs->data, pos);
}
uint8_t *knot_rrs_rr_rdata(const knot_rrs_t *rrs, size_t pos)
{
if (rrs == NULL || pos >= rrs->rr_count) {
return NULL;
}
return knot_rr_rdata(knot_rrs_rr(rrs, pos));
}
uint16_t knot_rrs_rr_size(const knot_rrs_t *rrs, size_t pos)
{
if (rrs == NULL || pos >= rrs->rr_count) {
return 0;
}
return knot_rr_rdata_size(knot_rrs_rr(rrs, pos));
}
uint32_t knot_rrs_rr_ttl(const knot_rrs_t *rrs, size_t pos)
{
if (rrs == NULL || pos >= rrs->rr_count) {
return 0;
}
return knot_rr_ttl(knot_rrs_rr(rrs, pos));
}
size_t knot_rrs_size(const knot_rrs_t *rrs)
{
if (rrs == NULL) {
......@@ -280,47 +307,6 @@ int knot_rrs_add_rr(knot_rrs_t *rrs, const knot_rr_t *rr, mm_ctx_t *mm)
return add_rr_at(rrs, rr, rrs->rr_count, mm);
}
int knot_rrs_remove_rr_at_pos(knot_rrs_t *rrs, size_t pos, mm_ctx_t *mm)
{
if (rrs == NULL || pos >= rrs->rr_count) {
return KNOT_EINVAL;
}
knot_rr_t *old_rr = knot_rrs_rr(rrs, pos);
knot_rr_t *last_rr = knot_rrs_rr(rrs, rrs->rr_count - 1);
assert(old_rr);
assert(last_rr);
size_t total_size = knot_rrs_size(rrs);
uint16_t old_size = knot_rr_rdata_size(old_rr);
void *old_threshold = old_rr + knot_rr_array_size(old_size);
void *last_threshold = last_rr + knot_rr_array_size(knot_rr_rdata_size(last_rr));
// Move RDATA
memmove(old_rr, old_threshold,
last_threshold - old_threshold);
if (rrs->rr_count > 1) {
// Realloc RDATA
void *tmp = mm_realloc(mm, rrs->data,
total_size - (knot_rr_array_size(old_size)),
total_size);
if (tmp == NULL) {
ERR_ALLOC_FAILED;
return KNOT_ENOMEM;
} else {
rrs->data = tmp;
}
} else {
// Free RDATA
mm_free(mm, rrs->data);
rrs->data = NULL;
}
rrs->rr_count--;
return KNOT_EOK;
}
bool knot_rrs_eq(const knot_rrs_t *rrs1, const knot_rrs_t *rrs2)
{
if (rrs1->rr_count != rrs2->rr_count) {
......@@ -338,6 +324,28 @@ bool knot_rrs_eq(const knot_rrs_t *rrs1, const knot_rrs_t *rrs2)
return true;
}
bool knot_rrs_member(const knot_rrs_t *rrs, const knot_rr_t *rr, bool cmp_ttl)
{
for (uint16_t i = 0; i < rrs->rr_count; ++i) {
const knot_rr_t *cmp_rr = knot_rrs_rr(rrs, i);
if (cmp_ttl) {
if (knot_rr_ttl(rr) != knot_rr_ttl(cmp_rr)) {
continue;
}
}
int cmp = knot_rr_cmp(cmp_rr, rr);
if (cmp == 0) {
// Match.
return true;
}
if (cmp > 0) {
// 'Bigger' RR present, no need to continue.
return false;
}
}
return false;
}
int knot_rrs_merge(knot_rrs_t *rrs1, const knot_rrs_t *rrs2, mm_ctx_t *mm)
{
if (rrs1 == NULL || rrs2 == NULL) {
......@@ -355,3 +363,47 @@ int knot_rrs_merge(knot_rrs_t *rrs1, const knot_rrs_t *rrs2, mm_ctx_t *mm)
return KNOT_EOK;
}
int knot_rrs_intersect(const knot_rrs_t *a, const knot_rrs_t *b,
knot_rrs_t *out, mm_ctx_t *mm)
{
if (a == NULL || b == NULL || out == NULL) {
return KNOT_EINVAL;
}
knot_rrs_init(out);
const bool compare_ttls = false;
for (uint16_t i = 0; i < a->rr_count; ++i) {
const knot_rr_t *rr = knot_rrs_rr(a, i);
if (knot_rrs_member(b, rr, compare_ttls)) {
// Add RR into output intersection RRSet.
int ret = knot_rrs_add_rr(out, rr, mm);
if (ret != KNOT_EOK) {
knot_rrs_clear(out, mm);
return ret;
}
}
}
return KNOT_EOK;
}
int knot_rrs_subtract(knot_rrs_t *from, const knot_rrs_t *what, mm_ctx_t *mm)
{
if (from == NULL || what == NULL) {
return KNOT_EINVAL;
}
for (uint16_t i = 0; i < what->rr_count; ++i) {
const knot_rr_t *to_remove = knot_rrs_rr(what, i);
int pos_to_remove = find_rr_pos(from, to_remove);
if (pos_to_remove >= 0) {
int ret = remove_rr_at(from, pos_to_remove, mm);
if (ret != KNOT_EOK) {
return ret;
}
}
}
return KNOT_EOK;
}
......@@ -86,7 +86,7 @@ uint8_t *knot_rr_rdata(const knot_rr_t *rr);
size_t knot_rr_array_size(uint16_t size);
/*!
* \brief Canonical comparison of two RRs.
* \brief Canonical comparison of two RRs. Both RRs *must* exist.
* \param rr1 First RR to compare.
* \param rr2 Second RR to compare.
* \retval 0 if rr1 == rr2.
......@@ -137,30 +137,6 @@ int knot_rrs_copy(knot_rrs_t *dst, const knot_rrs_t *src, mm_ctx_t *mm);
*/
knot_rr_t *knot_rrs_rr(const knot_rrs_t *rrs, size_t pos);
/*!
* \brief Gets RDATA from RR at \a pos position.
* \param rrs RRS to get RDATA from.
* \param pos Position to use.
* \return Pointer to RDATA of RR at \a pos position.
*/
uint8_t *knot_rrs_rr_rdata(const knot_rrs_t *rrs, size_t pos);
/*!
* \brief Gets size from RR at \a pos position.
* \param rrs RRS to get size from.
* \param pos Position to use.
* \return Size of RR at \a pos position.
*/
uint16_t knot_rrs_rr_size(const knot_rrs_t *rrs, size_t pos);
/*!
* \brief Gets TTL from RR at \a pos position.
* \param rrs RRS to get TTL from.
* \param pos Position to use.
* \return Size of TTL at \a pos position.
*/
uint32_t knot_rrs_rr_ttl(const knot_rrs_t *rrs, size_t pos);
/*!
* \brief Returns size of array with RRs.
* \param rrs RR array.
......@@ -179,16 +155,7 @@ size_t knot_rrs_size(const knot_rrs_t *rrs);
*/
int knot_rrs_add_rr(knot_rrs_t *rrs, const knot_rr_t *rr, mm_ctx_t *mm);
/*!
* \brief Removes RR at a given position from RRS structure. RR is dropped.
* \param rrs RRS structure to remove from.
* \param pos Position to use.
* \param mm Memory context.
* \return KNOT_E*
*/
int knot_rrs_remove_rr_at_pos(knot_rrs_t *rrs, size_t pos, mm_ctx_t *mm);
/* ----------------------------- RRs misc ----------------------------------- */
/* ---------------------- RRs set-like operations --------------------------- */
/*!
* \brief RRS equality check.
......@@ -199,6 +166,16 @@ int knot_rrs_remove_rr_at_pos(knot_rrs_t *rrs, size_t pos, mm_ctx_t *mm);
*/
bool knot_rrs_eq(const knot_rrs_t *rrs1, const knot_rrs_t *rrs2);
/*!
* \brief Returns true if \a rr is present in \a rrs, false otherwise.
* \param rrs RRS to search in.
* \param rr RR to compare with.
* \param cmp_ttl If set to true, TTLs will be compared as well.
* \retval true if \a rr is present in \a rrs.
* \retval false if \a rr is not present in \a rrs.
*/
bool knot_rrs_member(const knot_rrs_t *rrs, const knot_rr_t *rr, bool cmp_ttl);
/*!
* \brief Merges two RRS into the first one. Second RRS is left intact.
* Canonical order is preserved.
......@@ -208,3 +185,24 @@ bool knot_rrs_eq(const knot_rrs_t *rrs1, const knot_rrs_t *rrs2);
* \return KNOT_E*
*/
int knot_rrs_merge(knot_rrs_t *rrs1, const knot_rrs_t *rrs2, mm_ctx_t *mm);
/*!
* \brief RRS set-like intersection. Full compare is done.
* \param a First RRS to intersect.
* \param b Second RRS to intersect.
* \param out Output RRS with intersection, RDATA are created anew.
* \param mm Memory context. Will be used to create new RDATA.
* \return KNOT_E*
*/
int knot_rrs_intersect(const knot_rrs_t *a, const knot_rrs_t *b,
knot_rrs_t *out, mm_ctx_t *mm);
/*!
* \brief Does set-like RRS subtraction. \a from RRS is changed.
* \param from RRS to subtract from.
* \param what RRS to subtract.
* \param mm Memory context use to reallocated \a from data.
* \return KNOT_E*
*/
int knot_rrs_subtract(knot_rrs_t *from, const knot_rrs_t *what,
mm_ctx_t *mm);
......@@ -700,118 +700,6 @@ void knot_rrset_clear(knot_rrset_t *rrset, mm_ctx_t *mm)
}
}
int knot_rrset_merge(knot_rrset_t *rrset1, const knot_rrset_t *rrset2,
mm_ctx_t *mm)
{
if (rrset1 == NULL || rrset2 == NULL ||
!knot_rrset_equal(rrset1, rrset2, KNOT_RRSET_COMPARE_HEADER)) {
return KNOT_EINVAL;
}
return knot_rrs_merge(&rrset1->rrs, &rrset2->rrs, mm);
}
static int find_rr_pos(const knot_rrset_t *rr_search_in,
const knot_rrset_t *rr_reference, size_t pos)
{
bool found = false;
uint16_t rr_count = knot_rrset_rr_count(rr_search_in);
for (uint16_t i = 0; i < rr_count && !found; ++i) {
const knot_rr_t *in_rr = knot_rrs_rr(&rr_search_in->rrs, i);
const knot_rr_t *ref_rr = knot_rrs_rr(&rr_reference->rrs, pos);
if (knot_rr_cmp(in_rr, ref_rr) == 0) {
return i;
}
}
return KNOT_ENOENT;
}
static int knot_rrset_remove_rr(knot_rrset_t *rrset,
const knot_rrset_t *rr_from, size_t rdata_pos,
mm_ctx_t *mm)
{
/*
* Position in first and second rrset can differ, we have
* to search for position first.
*/
int pos_to_remove = find_rr_pos(rrset, rr_from, rdata_pos);
if (pos_to_remove >= 0) {
/* Position found, can be removed. */
return knot_rrs_remove_rr_at_pos(&rrset->rrs, pos_to_remove, mm);
} else {
assert(pos_to_remove == KNOT_ENOENT);
return KNOT_ENOENT;
}
}
int knot_rrset_remove_rr_using_rrset(knot_rrset_t *from,
const knot_rrset_t *what,
mm_ctx_t *mm)
{
if (from == NULL || what == NULL) {
return KNOT_EINVAL;
}
uint16_t what_rdata_count = knot_rrset_rr_count(what);
for (uint16_t i = 0; i < what_rdata_count; ++i) {
int ret = knot_rrset_remove_rr(from, what, i, mm);
if (ret != KNOT_EOK) {
if (ret != KNOT_ENOENT) {
return ret;
}
}
}
return KNOT_EOK;
}
static bool has_rr(const knot_rrset_t *rrset, const knot_rr_t *rr, bool cmp_ttl)
{
for (uint16_t i = 0; i < rrset->rrs.rr_count; ++i) {
const knot_rr_t *cmp_rr = knot_rrs_rr(&rrset->rrs, i);
if (cmp_ttl) {
if (knot_rr_ttl(rr) != knot_rr_ttl(cmp_rr)) {
continue;
}
}
int cmp = knot_rr_cmp(cmp_rr, rr);
if (cmp == 0) {
// Match.
return true;
}
if (cmp > 0) {
// 'Bigger' RR present, no need to continue.
return false;
}
}
return false;
}
int knot_rrset_intersection(const knot_rrset_t *a, const knot_rrset_t *b,
knot_rrset_t *out, bool cmp_ttl, mm_ctx_t *mm)
{
if (a == NULL || b == NULL || !knot_dname_is_equal(a->owner, b->owner) ||
a->type != b->type) {
return KNOT_EINVAL;
}
knot_rrset_init(out, a->owner, a->type, a->rclass);
for (uint16_t i = 0; i < a->rrs.rr_count; ++i) {
const knot_rr_t *rr = knot_rrs_rr(&a->rrs, i);
if (has_rr(b, rr, cmp_ttl)) {
// Add RR into output intersection RRSet.
int ret = knot_rrs_add_rr(&out->rrs, rr, mm);
if (ret != KNOT_EOK) {
knot_rrs_clear(&out->rrs, mm);
return ret;
}
}
}
return KNOT_EOK;
}
bool knot_rrset_empty(const knot_rrset_t *rrset)
{
uint16_t rr_count = knot_rrset_rr_count(rrset);
......
......@@ -202,30 +202,6 @@ void knot_rrset_clear(knot_rrset_t *rrset, mm_ctx_t *mm);
int knot_rrset_to_wire(const knot_rrset_t *rrset, uint8_t *wire, size_t *size,
size_t max_size, uint16_t *rr_count, struct knot_compr *compr);
/*!
* \brief Merges two RRSets, duplicate check is done, preserves canonical ordering.
*
* \param r1 Pointer to RRSet to be merged into.
* \param r2 Pointer to RRSet to be merged.
* \param mm Memory context.
*
* \return KNOT_E*
*/
int knot_rrset_merge(knot_rrset_t *rrset1, const knot_rrset_t *rrset2, mm_ctx_t *mm);
/*!
* \brief Removes RRs contained in 'what' RRSet from 'from' RRSet.
*
* \param from Delete from.
* \param what Delete what.
* \param mm Memory context.
*
* \return KNOT_E*
*/
int knot_rrset_remove_rr_using_rrset(knot_rrset_t *from,
const knot_rrset_t *what,
mm_ctx_t *mm);
/*!
* \brief Creates one RR from wire, stores it into 'rrset'
*
......@@ -265,21 +241,6 @@ bool knot_rrset_empty(const knot_rrset_t *rrset);
*/
knot_rrset_t *knot_rrset_copy(const knot_rrset_t *src, mm_ctx_t *mm);
/*!
* \brief RRSet intersection. Full compare is done, including RDATA.
*
* \param a First RRSet to intersect.
* \param b Second RRset to intersect.
* \param out Output RRSet with intersection, RDATA are created anew, owner is
* just a reference.
* \param cmp_ttl If set to true, TTLs will be compared as well.
* \param mm Memory context. Will be used to create new RDATA.
*
* \return KNOT_E*
*/
int knot_rrset_intersection(const knot_rrset_t *a, const knot_rrset_t *b,
knot_rrset_t *out, bool cmp_ttl, mm_ctx_t *mm);
/*!
* \brief Initializes given RRSet structure.
*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment