aboutsummaryrefslogtreecommitdiffstats
path: root/dnssec_zone.c
diff options
context:
space:
mode:
Diffstat (limited to 'dnssec_zone.c')
-rw-r--r--dnssec_zone.c185
1 files changed, 132 insertions, 53 deletions
diff --git a/dnssec_zone.c b/dnssec_zone.c
index 60d62eae09f2..f610a3cfe8fc 100644
--- a/dnssec_zone.c
+++ b/dnssec_zone.c
@@ -78,7 +78,7 @@ ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr)
void
ldns_dnssec_rrs_print_fmt(FILE *out, const ldns_output_format *fmt,
- ldns_dnssec_rrs *rrs)
+ const ldns_dnssec_rrs *rrs)
{
if (!rrs) {
if ((fmt->flags & LDNS_COMMENT_LAYOUT))
@@ -94,7 +94,7 @@ ldns_dnssec_rrs_print_fmt(FILE *out, const ldns_output_format *fmt,
}
void
-ldns_dnssec_rrs_print(FILE *out, ldns_dnssec_rrs *rrs)
+ldns_dnssec_rrs_print(FILE *out, const ldns_dnssec_rrs *rrs)
{
ldns_dnssec_rrs_print_fmt(out, ldns_output_format_default, rrs);
}
@@ -143,7 +143,7 @@ ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets *rrsets)
}
ldns_rr_type
-ldns_dnssec_rrsets_type(ldns_dnssec_rrsets *rrsets)
+ldns_dnssec_rrsets_type(const ldns_dnssec_rrsets *rrsets)
{
if (rrsets) {
return rrsets->type;
@@ -271,7 +271,7 @@ ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr)
static void
ldns_dnssec_rrsets_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
- ldns_dnssec_rrsets *rrsets,
+ const ldns_dnssec_rrsets *rrsets,
bool follow,
bool show_soa)
{
@@ -300,14 +300,14 @@ ldns_dnssec_rrsets_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
void
ldns_dnssec_rrsets_print_fmt(FILE *out, const ldns_output_format *fmt,
- ldns_dnssec_rrsets *rrsets,
+ const ldns_dnssec_rrsets *rrsets,
bool follow)
{
ldns_dnssec_rrsets_print_soa_fmt(out, fmt, rrsets, follow, true);
}
void
-ldns_dnssec_rrsets_print(FILE *out, ldns_dnssec_rrsets *rrsets, bool follow)
+ldns_dnssec_rrsets_print(FILE *out, const ldns_dnssec_rrsets *rrsets, bool follow)
{
ldns_dnssec_rrsets_print_fmt(out, ldns_output_format_default,
rrsets, follow);
@@ -391,7 +391,7 @@ ldns_dnssec_name_deep_free(ldns_dnssec_name *name)
}
ldns_rdf *
-ldns_dnssec_name_name(ldns_dnssec_name *name)
+ldns_dnssec_name_name(const ldns_dnssec_name *name)
{
if (name) {
return name->name;
@@ -400,7 +400,7 @@ ldns_dnssec_name_name(ldns_dnssec_name *name)
}
bool
-ldns_dnssec_name_is_glue(ldns_dnssec_name *name)
+ldns_dnssec_name_is_glue(const ldns_dnssec_name *name)
{
if (name) {
return name->is_glue;
@@ -489,7 +489,7 @@ ldns_dnssec_name_add_rr(ldns_dnssec_name *name,
}
ldns_dnssec_rrsets *
-ldns_dnssec_name_find_rrset(ldns_dnssec_name *name,
+ldns_dnssec_name_find_rrset(const ldns_dnssec_name *name,
ldns_rr_type type) {
ldns_dnssec_rrsets *result;
@@ -505,13 +505,13 @@ ldns_dnssec_name_find_rrset(ldns_dnssec_name *name,
}
ldns_dnssec_rrsets *
-ldns_dnssec_zone_find_rrset(ldns_dnssec_zone *zone,
- ldns_rdf *dname,
+ldns_dnssec_zone_find_rrset(const ldns_dnssec_zone *zone,
+ const ldns_rdf *dname,
ldns_rr_type type)
{
ldns_rbnode_t *node;
- if (!zone || !dname) {
+ if (!zone || !dname || !zone->names) {
return NULL;
}
@@ -526,7 +526,7 @@ ldns_dnssec_zone_find_rrset(ldns_dnssec_zone *zone,
static void
ldns_dnssec_name_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
- ldns_dnssec_name *name,
+ const ldns_dnssec_name *name,
bool show_soa)
{
if (name) {
@@ -553,13 +553,13 @@ ldns_dnssec_name_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
void
ldns_dnssec_name_print_fmt(FILE *out, const ldns_output_format *fmt,
- ldns_dnssec_name *name)
+ const ldns_dnssec_name *name)
{
ldns_dnssec_name_print_soa_fmt(out, fmt, name, true);
}
void
-ldns_dnssec_name_print(FILE *out, ldns_dnssec_name *name)
+ldns_dnssec_name_print(FILE *out, const ldns_dnssec_name *name)
{
ldns_dnssec_name_print_fmt(out, ldns_output_format_default, name);
}
@@ -593,8 +593,19 @@ rr_is_rrsig_covering(ldns_rr* rr, ldns_rr_type t)
*/
#define FASTER_DNSSEC_ZONE_NEW_FRM_FP 1 /* Because of L2 cache efficiency */
+static ldns_status
+ldns_dnssec_zone_add_empty_nonterminals_nsec3(
+ ldns_dnssec_zone *zone, ldns_rbtree_t *nsec3s);
+
+static void
+ldns_todo_nsec3_ents_node_free(ldns_rbnode_t *node, void *arg) {
+ (void) arg;
+ ldns_rdf_deep_free((ldns_rdf *)node->key);
+ LDNS_FREE(node);
+}
+
ldns_status
-ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin,
+ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, const ldns_rdf* origin,
uint32_t ttl, ldns_rr_class ATTR_UNUSED(c), int* line_nr)
{
ldns_rr* cur_rr;
@@ -604,34 +615,58 @@ ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin,
ldns_rdf *my_prev = NULL;
ldns_dnssec_zone *newzone = ldns_dnssec_zone_new();
+ /* NSEC3s may occur before the names they refer to. We must remember
+ them and add them to the name later on, after the name is read.
+ We track not yet matching NSEC3s*n the todo_nsec3s list */
+ ldns_rr_list* todo_nsec3s = ldns_rr_list_new();
/* when reading NSEC3s, there is a chance that we encounter nsecs
for empty nonterminals, whose nonterminals we cannot derive yet
- because the needed information is to be read later. in that case
- we keep a list of those nsec3's and retry to add them later */
- ldns_rr_list* todo_nsec3s = ldns_rr_list_new();
+ because the needed information is to be read later.
+
+ nsec3_ents (where ent is e.n.t.; i.e. empty non terminal) will
+ hold the NSEC3s that still didn't have a matching name in the
+ zone tree, even after all names were read. They can only match
+ after the zone is equiped with all the empty non terminals. */
+ ldns_rbtree_t todo_nsec3_ents;
+ ldns_rbnode_t *new_node;
ldns_rr_list* todo_nsec3_rrsigs = ldns_rr_list_new();
- ldns_status status = LDNS_STATUS_MEM_ERR;
+ ldns_status status;
#ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
ldns_zone* zone = NULL;
- if (ldns_zone_new_frm_fp_l(&zone, fp, origin,ttl, c, line_nr)
- != LDNS_STATUS_OK) goto error;
#else
uint32_t my_ttl = ttl;
#endif
- if (!newzone || !todo_nsec3s || !todo_nsec3_rrsigs ) goto error;
+ ldns_rbtree_init(&todo_nsec3_ents, ldns_dname_compare_v);
+#ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
+ status = ldns_zone_new_frm_fp_l(&zone, fp, origin,ttl, c, line_nr);
+ if (status != LDNS_STATUS_OK)
+ goto error;
+#endif
+ if (!newzone || !todo_nsec3s || !todo_nsec3_rrsigs ) {
+ status = LDNS_STATUS_MEM_ERR;
+ goto error;
+ }
if (origin) {
- if (!(my_origin = ldns_rdf_clone(origin))) goto error;
- if (!(my_prev = ldns_rdf_clone(origin))) goto error;
+ if (!(my_origin = ldns_rdf_clone(origin))) {
+ status = LDNS_STATUS_MEM_ERR;
+ goto error;
+ }
+ if (!(my_prev = ldns_rdf_clone(origin))) {
+ status = LDNS_STATUS_MEM_ERR;
+ goto error;
+ }
}
#ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
- if (ldns_dnssec_zone_add_rr(newzone, ldns_zone_soa(zone))
- != LDNS_STATUS_OK) goto error;
-
+ if (ldns_zone_soa(zone)) {
+ status = ldns_dnssec_zone_add_rr(newzone, ldns_zone_soa(zone));
+ if (status != LDNS_STATUS_OK)
+ goto error;
+ }
for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
cur_rr = ldns_rr_list_rr(ldns_zone_rrs(zone), i);
status = LDNS_STATUS_OK;
@@ -679,23 +714,33 @@ ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin,
}
}
- if (ldns_rr_list_rr_count(todo_nsec3s) > 0) {
- (void) ldns_dnssec_zone_add_empty_nonterminals(newzone);
- for (i = 0; status == LDNS_STATUS_OK &&
- i < ldns_rr_list_rr_count(todo_nsec3s); i++) {
- cur_rr = ldns_rr_list_rr(todo_nsec3s, i);
- status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
- }
- }
- if (ldns_rr_list_rr_count(todo_nsec3_rrsigs) > 0) {
- for (i = 0; status == LDNS_STATUS_OK &&
- i < ldns_rr_list_rr_count(todo_nsec3_rrsigs);
- i++){
- cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i);
- status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
+ for (i = 0; status == LDNS_STATUS_OK &&
+ i < ldns_rr_list_rr_count(todo_nsec3s); i++) {
+ cur_rr = ldns_rr_list_rr(todo_nsec3s, i);
+ status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
+ if (status == LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) {
+ if (!(new_node = LDNS_MALLOC(ldns_rbnode_t))) {
+ status = LDNS_STATUS_MEM_ERR;
+ break;
+ }
+ new_node->key = ldns_dname_label(ldns_rr_owner(cur_rr), 0);
+ new_node->data = cur_rr;
+ if (!ldns_rbtree_insert(&todo_nsec3_ents, new_node)) {
+ LDNS_FREE(new_node);
+ status = LDNS_STATUS_MEM_ERR;
+ break;
+ }
+ status = LDNS_STATUS_OK;
}
}
-
+ if (todo_nsec3_ents.count > 0)
+ (void) ldns_dnssec_zone_add_empty_nonterminals_nsec3(
+ newzone, &todo_nsec3_ents);
+ for (i = 0; status == LDNS_STATUS_OK &&
+ i < ldns_rr_list_rr_count(todo_nsec3_rrsigs); i++) {
+ cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i);
+ status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
+ }
if (z) {
*z = newzone;
newzone = NULL;
@@ -710,6 +755,8 @@ error:
}
#endif
ldns_rr_list_free(todo_nsec3_rrsigs);
+ ldns_traverse_postorder(&todo_nsec3_ents,
+ ldns_todo_nsec3_ents_node_free, NULL);
ldns_rr_list_free(todo_nsec3s);
if (my_origin) {
@@ -725,7 +772,7 @@ error:
}
ldns_status
-ldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin,
+ldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone** z, FILE* fp, const ldns_rdf* origin,
uint32_t ttl, ldns_rr_class ATTR_UNUSED(c))
{
return ldns_dnssec_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL);
@@ -932,7 +979,7 @@ ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr)
void
ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt,
- ldns_rbtree_t *tree,
+ const ldns_rbtree_t *tree,
bool print_soa)
{
ldns_rbnode_t *node;
@@ -949,7 +996,7 @@ ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt,
}
void
-ldns_dnssec_zone_names_print(FILE *out, ldns_rbtree_t *tree, bool print_soa)
+ldns_dnssec_zone_names_print(FILE *out, const ldns_rbtree_t *tree, bool print_soa)
{
ldns_dnssec_zone_names_print_fmt(out, ldns_output_format_default,
tree, print_soa);
@@ -957,7 +1004,7 @@ ldns_dnssec_zone_names_print(FILE *out, ldns_rbtree_t *tree, bool print_soa)
void
ldns_dnssec_zone_print_fmt(FILE *out, const ldns_output_format *fmt,
- ldns_dnssec_zone *zone)
+ const ldns_dnssec_zone *zone)
{
if (zone) {
if (zone->soa) {
@@ -984,13 +1031,14 @@ ldns_dnssec_zone_print_fmt(FILE *out, const ldns_output_format *fmt,
}
void
-ldns_dnssec_zone_print(FILE *out, ldns_dnssec_zone *zone)
+ldns_dnssec_zone_print(FILE *out, const ldns_dnssec_zone *zone)
{
ldns_dnssec_zone_print_fmt(out, ldns_output_format_default, zone);
}
-ldns_status
-ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
+static ldns_status
+ldns_dnssec_zone_add_empty_nonterminals_nsec3(
+ ldns_dnssec_zone *zone, ldns_rbtree_t *nsec3s)
{
ldns_dnssec_name *new_name;
ldns_rdf *cur_name;
@@ -1053,12 +1101,34 @@ ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
/* We have an empty nonterminal, add it to the
* tree
*/
+ ldns_rbnode_t *node = NULL;
+ ldns_rdf *ent_name;
+
+ if (!(ent_name = ldns_dname_clone_from(
+ next_name, i)))
+ return LDNS_STATUS_MEM_ERR;
+
+ if (nsec3s && zone->_nsec3params) {
+ ldns_rdf *ent_hashed_name;
+
+ if (!(ent_hashed_name =
+ ldns_nsec3_hash_name_frm_nsec3(
+ zone->_nsec3params,
+ ent_name)))
+ return LDNS_STATUS_MEM_ERR;
+ node = ldns_rbtree_search(nsec3s,
+ ent_hashed_name);
+ if (!node) {
+ ldns_rdf_deep_free(l1);
+ ldns_rdf_deep_free(l2);
+ continue;
+ }
+ }
new_name = ldns_dnssec_name_new();
if (!new_name) {
return LDNS_STATUS_MEM_ERR;
}
- new_name->name = ldns_dname_clone_from(next_name,
- i);
+ new_name->name = ent_name;
if (!new_name->name) {
ldns_dnssec_name_free(new_name);
return LDNS_STATUS_MEM_ERR;
@@ -1074,6 +1144,9 @@ ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
(void)ldns_rbtree_insert(zone->names, new_node);
ldns_dnssec_name_make_hashed_name(
zone, new_name, NULL);
+ if (node)
+ (void) ldns_dnssec_zone_add_rr(zone,
+ (ldns_rr *)node->data);
}
ldns_rdf_deep_free(l1);
ldns_rdf_deep_free(l2);
@@ -1091,8 +1164,14 @@ ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
return LDNS_STATUS_OK;
}
+ldns_status
+ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
+{
+ return ldns_dnssec_zone_add_empty_nonterminals_nsec3(zone, NULL);
+}
+
bool
-ldns_dnssec_zone_is_nsec3_optout(ldns_dnssec_zone* zone)
+ldns_dnssec_zone_is_nsec3_optout(const ldns_dnssec_zone* zone)
{
ldns_rr* nsec3;
ldns_rbnode_t* node;