Commit 0055ced6 authored by Lubos Slovak's avatar Lubos Slovak

Adjusting data after IXFR.

(Taken from the 'ixfr' branch.)

- Adjusting zone contents after IXFR.
  - Loading NSEC3PARAM.
  - Checking if node is empty in the first walkthrough.
  - Putting dnames into the dname table.
  - Adjusting node and RRSets (as before).
- Checking CNAME and wildcard CNAME loops after IXFR.
- zone_contents_adjust_node() and
  zone_contents_dname_from_node_to_table() made public.
- Counting zone nodes in zone_conents_add_node() instead of
  during adjusting.
- Not setting node count in constructor.

refs #1550 @1h
parent 74ec53ce
......@@ -1710,6 +1710,20 @@ static int xfrin_apply_remove_rrsigs(xfrin_changes_t *changes,
knot_strerror(ret));
return 1;
}
// connect the RDATA to the list of old RDATA
ret = xfrin_changes_check_rdata(&changes->old_rdata,
&changes->old_rdata_types,
changes->old_rdata_count,
&changes->old_rdata_allocated, 1);
if (ret != KNOT_EOK) {
return ret;
}
changes->old_rdata[changes->old_rdata_count] = rdata;
changes->old_rdata_types[changes->old_rdata_count] =
knot_rrset_type(remove);
++changes->old_rdata_count;
// if the RRSet is empty, remove from node and add to old RRSets
// check if there is no RRSIGs; if there are, leave the RRSet
......@@ -1758,20 +1772,6 @@ static int xfrin_apply_remove_rrsigs(xfrin_changes_t *changes,
}
}
// connect the RDATA to the list of old RDATA
ret = xfrin_changes_check_rdata(&changes->old_rdata,
&changes->old_rdata_types,
changes->old_rdata_count,
&changes->old_rdata_allocated, 1);
if (ret != KNOT_EOK) {
return ret;
}
changes->old_rdata[changes->old_rdata_count] = rdata;
changes->old_rdata_types[changes->old_rdata_count] =
knot_rrset_type(remove);
++changes->old_rdata_count;
return KNOT_EOK;
}
......@@ -3609,6 +3609,262 @@ static int xfrin_check_contents_copy(knot_zone_contents_t *old_contents)
/*----------------------------------------------------------------------------*/
typedef struct xfrin_adjust_data {
knot_zone_contents_t *contents;
xfrin_changes_t *changes;
int err;
} xfrin_adjust_data_t;
/*----------------------------------------------------------------------------*/
static void xfrin_adjust_node_in_tree(knot_zone_tree_node_t *tnode, void *data)
{
assert(tnode != NULL);
assert(data != NULL);
assert(tnode->node != NULL);
xfrin_adjust_data_t *adata = (xfrin_adjust_data_t *)data;
assert(adata->changes != NULL);
assert(adata->contents != NULL);
if (adata->err != KNOT_EOK) {
dbg_xfrin_detail("Error during adjusting, skipping node.\n");
return;
}
knot_node_t *node = tnode->node;
assert(knot_node_new_node(node) == NULL);
xfrin_changes_t *changes = adata->changes;
int ret;
/*
* 1) If the node is empty, mark it and continue with another node.
*/
if (knot_node_rrset_count(node) == 0) {
ret = xfrin_changes_check_nodes(&changes->old_nodes,
&changes->old_nodes_count,
&changes->old_nodes_allocated);
if (ret != KNOT_EOK) {
/*! \todo Stop on error? */
adata->err = ret;
return;
}
changes->old_nodes[changes->old_nodes_count++] = node;
return;
}
/*
* 2) If not empty, first, put dnames into dname table
*/
assert(adata->contents->dname_table != NULL);
ret = knot_zone_contents_dnames_from_node_to_table(
adata->contents->dname_table, node);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to add dnames from adjusted node to "
"table: %s\n", knot_strerror(ret));
adata->err = ret;
return;
}
/*
* Calling this function is OK, because it works only with the current
* nodes. The zone contents are marked as new, so no old data should be
* altered, nor used, in a way that would somehow influence answering.
*
* It would be however nice to test it somehow.
*/
knot_zone_contents_adjust_node(node, adata->contents, 0);
}
/*----------------------------------------------------------------------------*/
typedef struct xfrin_cname_chain {
const knot_node_t *node;
struct xfrin_cname_chain *next;
} xfrin_cname_chain_t;
/*----------------------------------------------------------------------------*/
int xfrin_cname_chain_add(xfrin_cname_chain_t *last, const knot_node_t *node)
{
xfrin_cname_chain_t *new_cname =
(xfrin_cname_chain_t *)malloc(sizeof(xfrin_cname_chain_t));
CHECK_ALLOC_LOG(new_cname, KNOT_ENOMEM);
new_cname->node = node;
new_cname->next = NULL;
last->next = new_cname;
return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
int xfrin_cname_chain_contains(xfrin_cname_chain_t *chain,
const knot_node_t *node)
{
xfrin_cname_chain_t *act = chain;
while (act != NULL) {
if (act->node == node) {
return 1;
}
act = act->next;
}
return 0;
}
/*----------------------------------------------------------------------------*/
void xfrin_cname_chain_free(xfrin_cname_chain_t *chain)
{
xfrin_cname_chain_t *act = chain;
while (act != NULL) {
chain = chain->next;
free(act);
act = chain;
}
}
/*----------------------------------------------------------------------------*/
static void xfrin_check_loops_in_tree(knot_zone_tree_node_t *tnode, void *data)
{
assert(tnode != NULL);
assert(data != NULL);
assert(tnode->node != NULL);
xfrin_adjust_data_t *adata = (xfrin_adjust_data_t *)data;
knot_node_t *node = knot_node_get_new_node(tnode->node);
assert(adata->changes != NULL);
assert(adata->contents != NULL);
if (adata->err != KNOT_EOK) {
dbg_xfrin_detail("Error during adjusting, skipping node.\n");
return;
}
// check only in new nodes
if (!knot_node_is_new(node)) {
return;
}
// if there is CNAME in the node
const knot_rrset_t *cname = knot_node_rrset(node, KNOT_RRTYPE_CNAME);
xfrin_cname_chain_t *chain = NULL;
xfrin_cname_chain_t *act_cname = chain;
int ret = 0;
while (cname != NULL && !xfrin_cname_chain_contains(chain, node)) {
ret = xfrin_cname_chain_add(act_cname, node);
if (ret != KNOT_EOK) {
xfrin_cname_chain_free(chain);
adata->err = ret;
return;
}
// follow the CNAME chain, including wildcards and
// remember the nodes passed through
const knot_dname_t *next_name = knot_rdata_cname_name(
knot_rrset_rdata(cname));
assert(next_name != NULL);
const knot_node_t *next_node = knot_dname_node(next_name, 1);
if (next_node == NULL) {
// try to find the name in the zone
const knot_node_t *ce = NULL;
ret = knot_zone_contents_find_dname_hash(
adata->contents, next_name,
&next_node, &ce);
if (ret != KNOT_ZONE_NAME_FOUND) {
// try to find wildcard child
assert(knot_dname_is_subdomain(next_name,
knot_node_owner(ce)));
next_node = knot_node_wildcard_child(ce, 1);
}
assert(next_node == NULL || knot_dname_compare(
knot_node_owner(next_node), next_name) == 0);
}
if (next_node == NULL) {
// no CNAME node to follow
cname = NULL;
} else {
cname = knot_node_rrset(node, KNOT_RRTYPE_CNAME);
}
}
if (cname != NULL) {
// this means the node is in the chain already
adata->err = KNOT_ENOIXFR;
}
xfrin_cname_chain_free(chain);
}
/*----------------------------------------------------------------------------*/
static int xfrin_adjust_contents(knot_zone_contents_t *contents,
xfrin_changes_t *changes)
{
knot_zone_tree_t *t = knot_zone_contents_get_nodes(contents);
assert(t != NULL);
// first, load the NSEC3PARAM record, if there is one
const knot_node_t *apex = knot_node_new_node(contents->apex);
assert(apex != NULL);
const knot_rrset_t *rrset = knot_node_rrset(apex,
KNOT_RRTYPE_NSEC3PARAM);
if (rrset != NULL) {
knot_nsec3_params_from_wire(&contents->nsec3_params, rrset);
} else {
memset(&contents->nsec3_params, 0, sizeof(knot_nsec3_params_t));
}
xfrin_adjust_data_t data;
data.changes = changes;
data.contents = contents;
data.err = KNOT_EOK;
/*
* Walk through the nodes in the zone and do the following:
* 1) Check node flags (authoritative / non-authoritative / deleg. pt.).
* 2) For each node without NSEC3 node, try to find the NSEC3 node.
* 3) Insert all dnames to dname table.
*
* In second walkthrough check CNAME loops, including wildcards.
*/
knot_zone_tree_forward_apply_inorder(t, xfrin_adjust_node_in_tree,
(void *)&data);
if (data.err != KNOT_EOK) {
dbg_xfrin("Failed to adjust nodes after IXFR: %s\n",
knot_strerror(data.err));
return data.err;
}
knot_zone_tree_forward_apply_inorder(t, xfrin_check_loops_in_tree,
(void *)&data);
return data.err;
}
/*----------------------------------------------------------------------------*/
int xfrin_apply_changesets(knot_zone_t *zone,
knot_changesets_t *chsets)
{
......
......@@ -341,9 +341,8 @@ static void knot_zone_contents_adjust_rrsets(knot_node_t *node,
* \param node Zone node to adjust.
* \param zone Zone the node belongs to.
*/
static void knot_zone_contents_adjust_node(knot_node_t *node,
knot_zone_contents_t *zone,
int check_ver)
void knot_zone_contents_adjust_node(knot_node_t *node,
knot_zone_contents_t *zone, int check_ver)
{
dbg_zone_exec(
......@@ -381,23 +380,18 @@ dbg_zone_exec(
knot_node_set_deleg_point(node);
}
// authorative node?
// if (!knot_node_is_non_auth(node)) {
zone->node_count++;
// }
// assure that owner has proper node
if (knot_dname_node(knot_node_owner(node), 0) == NULL) {
knot_dname_set_node(knot_node_get_owner(node), node);
knot_dname_set_node(knot_node_get_owner(node), node);
}
// NSEC3 node (only if NSEC3 tree is not empty)
const knot_node_t *prev;
const knot_node_t *nsec3;
int match = knot_zone_contents_find_nsec3_for_name(zone,
knot_node_owner(node),
&nsec3, &prev, check_ver);
knot_node_owner(node),
&nsec3, &prev,
check_ver);
if (match != KNOT_ZONE_NAME_FOUND) {
nsec3 = NULL;
}
......@@ -741,9 +735,11 @@ static int knot_zone_contents_dnames_from_rrset_to_table(
return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
/* API functions */
/*----------------------------------------------------------------------------*/
static int knot_zone_contents_dnames_from_node_to_table(
int knot_zone_contents_dnames_from_node_to_table(
knot_dname_table_t *table, knot_node_t *node)
{
/*
......@@ -788,14 +784,12 @@ static int knot_zone_contents_dnames_from_node_to_table(
return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
/* API functions */
/*----------------------------------------------------------------------------*/
knot_zone_contents_t *knot_zone_contents_new(knot_node_t *apex,
uint node_count,
int use_domain_table,
struct knot_zone *zone)
uint node_count,
int use_domain_table,
struct knot_zone *zone)
{
knot_zone_contents_t *contents = (knot_zone_contents_t *)
calloc(1, sizeof(knot_zone_contents_t));
......@@ -836,7 +830,7 @@ knot_zone_contents_t *knot_zone_contents_new(knot_node_t *apex,
contents->dname_table = NULL;
}
contents->node_count = node_count;
//contents->node_count = node_count;
/* Initialize NSEC3 params */
dbg_zone("Initializing NSEC3 parameters.\n");
......@@ -859,9 +853,9 @@ knot_zone_contents_t *knot_zone_contents_new(knot_node_t *apex,
}
#ifdef USE_HASH_TABLE
if (contents->node_count > 0) {
if (node_count > 0) {
dbg_zone("Creating hash table.\n");
contents->table = ck_create_table(contents->node_count);
contents->table = ck_create_table(node_count);
if (contents->table == NULL) {
goto cleanup;
}
......@@ -1022,6 +1016,8 @@ int knot_zone_contents_add_node(knot_zone_contents_t *zone,
knot_node_set_zone(node, zone->zone);
++zone->node_count;
if (!create_parents) {
return KNOT_EOK;
}
......@@ -1037,7 +1033,7 @@ int knot_zone_contents_add_node(knot_zone_contents_t *zone,
// check if the node is not wildcard child of the parent
if (knot_dname_is_wildcard(
knot_node_owner(node))) {
knot_node_set_wildcard_child(next_node, node);
knot_node_set_wildcard_child(zone->apex, node);
}
} else {
knot_node_t *next_node;
......@@ -1120,6 +1116,8 @@ dbg_zone_exec(
knot_node_set_wildcard_child(next_node, node);
}
++zone->node_count;
dbg_zone("Next parent.\n");
node = next_node;
knot_dname_t *chopped_last = chopped;
......
......@@ -549,6 +549,12 @@ int knot_zone_contents_shallow_copy(const knot_zone_contents_t *from,
int knot_zone_contents_shallow_copy2(const knot_zone_contents_t *from,
knot_zone_contents_t **to);
int knot_zone_contents_dnames_from_node_to_table(
knot_dname_table_t *table, knot_node_t *node);
void knot_zone_contents_adjust_node(knot_node_t *node,
knot_zone_contents_t *zone, int check_ver);
void knot_zone_contents_free(knot_zone_contents_t **contents);
void knot_zone_contents_deep_free(knot_zone_contents_t **contents,
......
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