ldns_status ldns_dnssec_zone_create_nsec3s(ldns_dnssec_zone *zone, ldns_rr_list *new_rrs, uint8_t algorithm, uint8_t flags, uint16_t iterations, uint8_t salt_length, uint8_t *salt) { ldns_rbnode_t *first_name_node; ldns_rbnode_t *current_name_node; ldns_dnssec_name *current_name; ldns_status result = LDNS_STATUS_OK; ldns_rr *nsec_rr; ldns_rr_list *nsec3_list; uint32_t nsec_ttl; ldns_dnssec_rrsets *soa; if (!zone || !new_rrs || !zone->names) { return LDNS_STATUS_ERR; } /* the TTL of NSEC rrs should be set to the minimum TTL of * the zone SOA (RFC4035 Section 2.3) */ soa = ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_SOA); /* did the caller actually set it? if not, * fall back to default ttl */ if (soa && soa->rrs && soa->rrs->rr) { nsec_ttl = ldns_rdf2native_int32(ldns_rr_rdf( soa->rrs->rr, 6)); } else { nsec_ttl = LDNS_DEFAULT_TTL; } nsec3_list = ldns_rr_list_new(); first_name_node = ldns_dnssec_name_node_next_nonglue( ldns_rbtree_first(zone->names)); current_name_node = first_name_node; while (current_name_node && current_name_node != LDNS_RBTREE_NULL) { current_name = (ldns_dnssec_name *) current_name_node->data; nsec_rr = ldns_dnssec_create_nsec3(current_name, NULL, zone->soa->name, algorithm, flags, iterations, salt_length, salt); /* by default, our nsec based generator adds rrsigs * remove the bitmap for empty nonterminals */ if (!current_name->rrsets) { ldns_rdf_deep_free(ldns_rr_pop_rdf(nsec_rr)); } ldns_rr_set_ttl(nsec_rr, nsec_ttl); ldns_dnssec_name_add_rr(current_name, nsec_rr); ldns_rr_list_push_rr(new_rrs, nsec_rr); ldns_rr_list_push_rr(nsec3_list, nsec_rr); current_name_node = ldns_dnssec_name_node_next_nonglue( ldns_rbtree_next(current_name_node)); } ldns_rr_list_sort_nsec3(nsec3_list); ldns_dnssec_chain_nsec3_list(nsec3_list); if (result != LDNS_STATUS_OK) { return result; } ldns_rr_list_free(nsec3_list); return result; }
static ldns_status ldns_dnssec_zone_create_nsec3s_mkmap(ldns_dnssec_zone *zone, ldns_rr_list *new_rrs, uint8_t algorithm, uint8_t flags, uint16_t iterations, uint8_t salt_length, uint8_t *salt, ldns_rbtree_t **map) { ldns_rbnode_t *first_name_node; ldns_rbnode_t *current_name_node; ldns_dnssec_name *current_name; ldns_status result = LDNS_STATUS_OK; ldns_rr *nsec_rr; ldns_rr_list *nsec3_list; uint32_t nsec_ttl; ldns_dnssec_rrsets *soa; ldns_rbnode_t *hashmap_node; if (!zone || !new_rrs || !zone->names) { return LDNS_STATUS_ERR; } /* the TTL of NSEC rrs should be set to the minimum TTL of * the zone SOA (RFC4035 Section 2.3) */ soa = ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_SOA); /* did the caller actually set it? if not, * fall back to default ttl */ if (soa && soa->rrs && soa->rrs->rr && ldns_rr_rdf(soa->rrs->rr, 6) != NULL) { nsec_ttl = ldns_rdf2native_int32(ldns_rr_rdf(soa->rrs->rr, 6)); } else { nsec_ttl = LDNS_DEFAULT_TTL; } if (zone->hashed_names) { ldns_traverse_postorder(zone->hashed_names, ldns_hashed_names_node_free, NULL); LDNS_FREE(zone->hashed_names); } zone->hashed_names = ldns_rbtree_create(ldns_dname_compare_v); if (zone->hashed_names && map) { *map = zone->hashed_names; } first_name_node = ldns_dnssec_name_node_next_nonglue( ldns_rbtree_first(zone->names)); current_name_node = first_name_node; while (current_name_node && current_name_node != LDNS_RBTREE_NULL && result == LDNS_STATUS_OK) { current_name = (ldns_dnssec_name *) current_name_node->data; nsec_rr = ldns_dnssec_create_nsec3(current_name, NULL, zone->soa->name, algorithm, flags, iterations, salt_length, salt); /* by default, our nsec based generator adds rrsigs * remove the bitmap for empty nonterminals */ if (!current_name->rrsets) { ldns_rdf_deep_free(ldns_rr_pop_rdf(nsec_rr)); } ldns_rr_set_ttl(nsec_rr, nsec_ttl); result = ldns_dnssec_name_add_rr(current_name, nsec_rr); ldns_rr_list_push_rr(new_rrs, nsec_rr); if (ldns_rr_owner(nsec_rr)) { hashmap_node = LDNS_MALLOC(ldns_rbnode_t); if (hashmap_node == NULL) { return LDNS_STATUS_MEM_ERR; } current_name->hashed_name = ldns_dname_label(ldns_rr_owner(nsec_rr), 0); if (current_name->hashed_name == NULL) { LDNS_FREE(hashmap_node); return LDNS_STATUS_MEM_ERR; } hashmap_node->key = current_name->hashed_name; hashmap_node->data = current_name; if (! ldns_rbtree_insert(zone->hashed_names , hashmap_node)) { LDNS_FREE(hashmap_node); } } current_name_node = ldns_dnssec_name_node_next_nonglue( ldns_rbtree_next(current_name_node)); } if (result != LDNS_STATUS_OK) { return result; } /* Make sorted list of nsec3s (via zone->hashed_names) */ nsec3_list = ldns_rr_list_new(); if (nsec3_list == NULL) { return LDNS_STATUS_MEM_ERR; } for ( hashmap_node = ldns_rbtree_first(zone->hashed_names) ; hashmap_node != LDNS_RBTREE_NULL ; hashmap_node = ldns_rbtree_next(hashmap_node) ) { current_name = (ldns_dnssec_name *) hashmap_node->data; nsec_rr = ((ldns_dnssec_name *) hashmap_node->data)->nsec; if (nsec_rr) { ldns_rr_list_push_rr(nsec3_list, nsec_rr); } } result = ldns_dnssec_chain_nsec3_list(nsec3_list); ldns_rr_list_free(nsec3_list); return result; }