162ac0c33Sjakob /* 262ac0c33Sjakob * namedb.c -- common namedb operations. 362ac0c33Sjakob * 4217deabeSjakob * Copyright (c) 2001-2011, NLnet Labs. All rights reserved. 562ac0c33Sjakob * 662ac0c33Sjakob * See LICENSE for the license. 762ac0c33Sjakob * 862ac0c33Sjakob */ 962ac0c33Sjakob 10*aee1b7aaSsthen #include "config.h" 1162ac0c33Sjakob 1262ac0c33Sjakob #include <sys/types.h> 1362ac0c33Sjakob 1462ac0c33Sjakob #include <assert.h> 1562ac0c33Sjakob #include <ctype.h> 1662ac0c33Sjakob #include <limits.h> 1762ac0c33Sjakob #include <stdio.h> 1862ac0c33Sjakob #include <string.h> 190c2b6c02Sjakob #include <errno.h> 2062ac0c33Sjakob 2162ac0c33Sjakob #include "namedb.h" 2262ac0c33Sjakob 2362ac0c33Sjakob 2462ac0c33Sjakob static domain_type * 2562ac0c33Sjakob allocate_domain_info(domain_table_type *table, 2662ac0c33Sjakob const dname_type *dname, 2762ac0c33Sjakob domain_type *parent) 2862ac0c33Sjakob { 2962ac0c33Sjakob domain_type *result; 3062ac0c33Sjakob 3162ac0c33Sjakob assert(table); 3262ac0c33Sjakob assert(dname); 3362ac0c33Sjakob assert(parent); 3462ac0c33Sjakob 3562ac0c33Sjakob result = (domain_type *) region_alloc(table->region, 3662ac0c33Sjakob sizeof(domain_type)); 3762ac0c33Sjakob result->node.key = dname_partial_copy( 3862ac0c33Sjakob table->region, dname, domain_dname(parent)->label_count + 1); 3962ac0c33Sjakob result->parent = parent; 40044f85deSsthen result->nextdiff = NULL; 4162ac0c33Sjakob result->wildcard_child_closest_match = result; 4262ac0c33Sjakob result->rrsets = NULL; 4362ac0c33Sjakob result->number = 0; 4462ac0c33Sjakob #ifdef NSEC3 4562ac0c33Sjakob result->nsec3_cover = NULL; 460c2b6c02Sjakob #ifdef FULL_PREHASH 4762ac0c33Sjakob result->nsec3_wcard_child_cover = NULL; 4862ac0c33Sjakob result->nsec3_ds_parent_cover = NULL; 4962ac0c33Sjakob result->nsec3_lookup = NULL; 5062ac0c33Sjakob result->nsec3_is_exact = 0; 5162ac0c33Sjakob result->nsec3_ds_parent_is_exact = 0; 520c2b6c02Sjakob #endif /* FULL_PREHASH */ 530c2b6c02Sjakob #endif /* NSEC3 */ 5462ac0c33Sjakob result->is_existing = 0; 5562ac0c33Sjakob result->is_apex = 0; 560c2b6c02Sjakob result->has_SOA = 0; 5762ac0c33Sjakob 5862ac0c33Sjakob return result; 5962ac0c33Sjakob } 6062ac0c33Sjakob 6162ac0c33Sjakob domain_table_type * 6262ac0c33Sjakob domain_table_create(region_type *region) 6362ac0c33Sjakob { 6462ac0c33Sjakob const dname_type *origin; 6562ac0c33Sjakob domain_table_type *result; 6662ac0c33Sjakob domain_type *root; 6762ac0c33Sjakob 6862ac0c33Sjakob assert(region); 6962ac0c33Sjakob 7062ac0c33Sjakob origin = dname_make(region, (uint8_t *) "", 0); 7162ac0c33Sjakob 7262ac0c33Sjakob root = (domain_type *) region_alloc(region, sizeof(domain_type)); 7362ac0c33Sjakob root->node.key = origin; 7462ac0c33Sjakob root->parent = NULL; 75044f85deSsthen root->nextdiff = NULL; 7662ac0c33Sjakob root->wildcard_child_closest_match = root; 7762ac0c33Sjakob root->rrsets = NULL; 7862ac0c33Sjakob root->number = 1; /* 0 is used for after header */ 7962ac0c33Sjakob root->is_existing = 0; 8062ac0c33Sjakob root->is_apex = 0; 810c2b6c02Sjakob root->has_SOA = 0; 8262ac0c33Sjakob #ifdef NSEC3 830c2b6c02Sjakob root->nsec3_cover = NULL; 840c2b6c02Sjakob #ifdef FULL_PREHASH 8562ac0c33Sjakob root->nsec3_is_exact = 0; 8662ac0c33Sjakob root->nsec3_ds_parent_is_exact = 0; 8762ac0c33Sjakob root->nsec3_wcard_child_cover = NULL; 8862ac0c33Sjakob root->nsec3_ds_parent_cover = NULL; 8962ac0c33Sjakob root->nsec3_lookup = NULL; 900c2b6c02Sjakob #endif /* FULL_PREHASH */ 910c2b6c02Sjakob #endif /* NSEC3 */ 9262ac0c33Sjakob 9362ac0c33Sjakob result = (domain_table_type *) region_alloc(region, 9462ac0c33Sjakob sizeof(domain_table_type)); 9562ac0c33Sjakob result->region = region; 9662ac0c33Sjakob result->names_to_domains = rbtree_create( 9762ac0c33Sjakob region, (int (*)(const void *, const void *)) dname_compare); 9862ac0c33Sjakob rbtree_insert(result->names_to_domains, (rbnode_t *) root); 9962ac0c33Sjakob 10062ac0c33Sjakob result->root = root; 10162ac0c33Sjakob 10262ac0c33Sjakob return result; 10362ac0c33Sjakob } 10462ac0c33Sjakob 10562ac0c33Sjakob int 10662ac0c33Sjakob domain_table_search(domain_table_type *table, 10762ac0c33Sjakob const dname_type *dname, 10862ac0c33Sjakob domain_type **closest_match, 10962ac0c33Sjakob domain_type **closest_encloser) 11062ac0c33Sjakob { 11162ac0c33Sjakob int exact; 11262ac0c33Sjakob uint8_t label_match_count; 11362ac0c33Sjakob 11462ac0c33Sjakob assert(table); 11562ac0c33Sjakob assert(dname); 11662ac0c33Sjakob assert(closest_match); 11762ac0c33Sjakob assert(closest_encloser); 11862ac0c33Sjakob 11962ac0c33Sjakob exact = rbtree_find_less_equal(table->names_to_domains, dname, (rbnode_t **) closest_match); 12062ac0c33Sjakob assert(*closest_match); 12162ac0c33Sjakob 12262ac0c33Sjakob *closest_encloser = *closest_match; 12362ac0c33Sjakob 12462ac0c33Sjakob if (!exact) { 12562ac0c33Sjakob label_match_count = dname_label_match_count( 12662ac0c33Sjakob domain_dname(*closest_encloser), 12762ac0c33Sjakob dname); 12862ac0c33Sjakob assert(label_match_count < dname->label_count); 12962ac0c33Sjakob while (label_match_count < domain_dname(*closest_encloser)->label_count) { 13062ac0c33Sjakob (*closest_encloser) = (*closest_encloser)->parent; 13162ac0c33Sjakob assert(*closest_encloser); 13262ac0c33Sjakob } 13362ac0c33Sjakob } 13462ac0c33Sjakob 13562ac0c33Sjakob return exact; 13662ac0c33Sjakob } 13762ac0c33Sjakob 13862ac0c33Sjakob domain_type * 13962ac0c33Sjakob domain_table_find(domain_table_type *table, 14062ac0c33Sjakob const dname_type *dname) 14162ac0c33Sjakob { 14262ac0c33Sjakob domain_type *closest_match; 14362ac0c33Sjakob domain_type *closest_encloser; 14462ac0c33Sjakob int exact; 14562ac0c33Sjakob 14662ac0c33Sjakob exact = domain_table_search( 14762ac0c33Sjakob table, dname, &closest_match, &closest_encloser); 14862ac0c33Sjakob return exact ? closest_encloser : NULL; 14962ac0c33Sjakob } 15062ac0c33Sjakob 15162ac0c33Sjakob 15262ac0c33Sjakob domain_type * 15362ac0c33Sjakob domain_table_insert(domain_table_type *table, 15462ac0c33Sjakob const dname_type *dname) 15562ac0c33Sjakob { 15662ac0c33Sjakob domain_type *closest_match; 15762ac0c33Sjakob domain_type *closest_encloser; 15862ac0c33Sjakob domain_type *result; 15962ac0c33Sjakob int exact; 16062ac0c33Sjakob 16162ac0c33Sjakob assert(table); 16262ac0c33Sjakob assert(dname); 16362ac0c33Sjakob 16462ac0c33Sjakob exact = domain_table_search( 16562ac0c33Sjakob table, dname, &closest_match, &closest_encloser); 16662ac0c33Sjakob if (exact) { 16762ac0c33Sjakob result = closest_encloser; 16862ac0c33Sjakob } else { 16962ac0c33Sjakob assert(domain_dname(closest_encloser)->label_count < dname->label_count); 17062ac0c33Sjakob 17162ac0c33Sjakob /* Insert new node(s). */ 17262ac0c33Sjakob do { 17362ac0c33Sjakob result = allocate_domain_info(table, 17462ac0c33Sjakob dname, 17562ac0c33Sjakob closest_encloser); 17662ac0c33Sjakob rbtree_insert(table->names_to_domains, (rbnode_t *) result); 17762ac0c33Sjakob result->number = table->names_to_domains->count; 17862ac0c33Sjakob 17962ac0c33Sjakob /* 18062ac0c33Sjakob * If the newly added domain name is larger 18162ac0c33Sjakob * than the parent's current 18262ac0c33Sjakob * wildcard_child_closest_match but smaller or 18362ac0c33Sjakob * equal to the wildcard domain name, update 18462ac0c33Sjakob * the parent's wildcard_child_closest_match 18562ac0c33Sjakob * field. 18662ac0c33Sjakob */ 18762ac0c33Sjakob if (label_compare(dname_name(domain_dname(result)), 18862ac0c33Sjakob (const uint8_t *) "\001*") <= 0 18962ac0c33Sjakob && dname_compare(domain_dname(result), 19062ac0c33Sjakob domain_dname(closest_encloser->wildcard_child_closest_match)) > 0) 19162ac0c33Sjakob { 19262ac0c33Sjakob closest_encloser->wildcard_child_closest_match 19362ac0c33Sjakob = result; 19462ac0c33Sjakob } 19562ac0c33Sjakob closest_encloser = result; 19662ac0c33Sjakob } while (domain_dname(closest_encloser)->label_count < dname->label_count); 19762ac0c33Sjakob } 19862ac0c33Sjakob 19962ac0c33Sjakob return result; 20062ac0c33Sjakob } 20162ac0c33Sjakob 20262ac0c33Sjakob int 20362ac0c33Sjakob domain_table_iterate(domain_table_type *table, 20462ac0c33Sjakob domain_table_iterator_type iterator, 20562ac0c33Sjakob void *user_data) 20662ac0c33Sjakob { 20762ac0c33Sjakob const void *dname; 20862ac0c33Sjakob void *node; 20962ac0c33Sjakob int error = 0; 21062ac0c33Sjakob 21162ac0c33Sjakob assert(table); 21262ac0c33Sjakob 21362ac0c33Sjakob RBTREE_WALK(table->names_to_domains, dname, node) { 21462ac0c33Sjakob error += iterator((domain_type *) node, user_data); 21562ac0c33Sjakob } 21662ac0c33Sjakob 21762ac0c33Sjakob return error; 21862ac0c33Sjakob } 21962ac0c33Sjakob 22062ac0c33Sjakob 22162ac0c33Sjakob void 22262ac0c33Sjakob domain_add_rrset(domain_type *domain, rrset_type *rrset) 22362ac0c33Sjakob { 22462ac0c33Sjakob #if 0 /* fast */ 22562ac0c33Sjakob rrset->next = domain->rrsets; 22662ac0c33Sjakob domain->rrsets = rrset; 22762ac0c33Sjakob #else 22862ac0c33Sjakob /* preserve ordering, add at end */ 22962ac0c33Sjakob rrset_type** p = &domain->rrsets; 23062ac0c33Sjakob while(*p) 23162ac0c33Sjakob p = &((*p)->next); 23262ac0c33Sjakob *p = rrset; 23362ac0c33Sjakob rrset->next = 0; 23462ac0c33Sjakob #endif 23562ac0c33Sjakob 23662ac0c33Sjakob while (domain && !domain->is_existing) { 23762ac0c33Sjakob domain->is_existing = 1; 23862ac0c33Sjakob domain = domain->parent; 23962ac0c33Sjakob } 24062ac0c33Sjakob } 24162ac0c33Sjakob 24262ac0c33Sjakob 24362ac0c33Sjakob rrset_type * 24462ac0c33Sjakob domain_find_rrset(domain_type *domain, zone_type *zone, uint16_t type) 24562ac0c33Sjakob { 24662ac0c33Sjakob rrset_type *result = domain->rrsets; 24762ac0c33Sjakob 24862ac0c33Sjakob while (result) { 24962ac0c33Sjakob if (result->zone == zone && rrset_rrtype(result) == type) { 25062ac0c33Sjakob return result; 25162ac0c33Sjakob } 25262ac0c33Sjakob result = result->next; 25362ac0c33Sjakob } 25462ac0c33Sjakob return NULL; 25562ac0c33Sjakob } 25662ac0c33Sjakob 25762ac0c33Sjakob rrset_type * 25862ac0c33Sjakob domain_find_any_rrset(domain_type *domain, zone_type *zone) 25962ac0c33Sjakob { 26062ac0c33Sjakob rrset_type *result = domain->rrsets; 26162ac0c33Sjakob 26262ac0c33Sjakob while (result) { 26362ac0c33Sjakob if (result->zone == zone) { 26462ac0c33Sjakob return result; 26562ac0c33Sjakob } 26662ac0c33Sjakob result = result->next; 26762ac0c33Sjakob } 26862ac0c33Sjakob return NULL; 26962ac0c33Sjakob } 27062ac0c33Sjakob 27162ac0c33Sjakob zone_type * 27262ac0c33Sjakob domain_find_zone(domain_type *domain) 27362ac0c33Sjakob { 27462ac0c33Sjakob rrset_type *rrset; 27562ac0c33Sjakob while (domain) { 27662ac0c33Sjakob for (rrset = domain->rrsets; rrset; rrset = rrset->next) { 27762ac0c33Sjakob if (rrset_rrtype(rrset) == TYPE_SOA) { 27862ac0c33Sjakob return rrset->zone; 27962ac0c33Sjakob } 28062ac0c33Sjakob } 28162ac0c33Sjakob domain = domain->parent; 28262ac0c33Sjakob } 28362ac0c33Sjakob return NULL; 28462ac0c33Sjakob } 28562ac0c33Sjakob 2860c2b6c02Sjakob #ifndef FULL_PREHASH 2870c2b6c02Sjakob domain_type * 2880c2b6c02Sjakob domain_find_zone_apex(domain_type *domain) { 2890c2b6c02Sjakob while (domain != NULL) { 2900c2b6c02Sjakob if (domain->has_SOA != 0) 2910c2b6c02Sjakob return domain; 2920c2b6c02Sjakob domain = domain->parent; 2930c2b6c02Sjakob } 2940c2b6c02Sjakob return NULL; 2950c2b6c02Sjakob } 2960c2b6c02Sjakob #endif /* !FULL_PREHASH */ 2970c2b6c02Sjakob 29862ac0c33Sjakob zone_type * 29962ac0c33Sjakob domain_find_parent_zone(zone_type *zone) 30062ac0c33Sjakob { 30162ac0c33Sjakob rrset_type *rrset; 30262ac0c33Sjakob 30362ac0c33Sjakob assert(zone); 30462ac0c33Sjakob 30562ac0c33Sjakob for (rrset = zone->apex->rrsets; rrset; rrset = rrset->next) { 30662ac0c33Sjakob if (rrset->zone != zone && rrset_rrtype(rrset) == TYPE_NS) { 30762ac0c33Sjakob return rrset->zone; 30862ac0c33Sjakob } 30962ac0c33Sjakob } 31062ac0c33Sjakob return NULL; 31162ac0c33Sjakob } 31262ac0c33Sjakob 31362ac0c33Sjakob domain_type * 31462ac0c33Sjakob domain_find_ns_rrsets(domain_type *domain, zone_type *zone, rrset_type **ns) 31562ac0c33Sjakob { 31662ac0c33Sjakob while (domain && domain != zone->apex) { 31762ac0c33Sjakob *ns = domain_find_rrset(domain, zone, TYPE_NS); 31862ac0c33Sjakob if (*ns) 31962ac0c33Sjakob return domain; 32062ac0c33Sjakob domain = domain->parent; 32162ac0c33Sjakob } 32262ac0c33Sjakob 32362ac0c33Sjakob *ns = NULL; 32462ac0c33Sjakob return NULL; 32562ac0c33Sjakob } 32662ac0c33Sjakob 32762ac0c33Sjakob int 32862ac0c33Sjakob domain_is_glue(domain_type *domain, zone_type *zone) 32962ac0c33Sjakob { 33062ac0c33Sjakob rrset_type *unused; 33162ac0c33Sjakob domain_type *ns_domain = domain_find_ns_rrsets(domain, zone, &unused); 33262ac0c33Sjakob return (ns_domain != NULL && 33362ac0c33Sjakob domain_find_rrset(ns_domain, zone, TYPE_SOA) == NULL); 33462ac0c33Sjakob } 33562ac0c33Sjakob 33662ac0c33Sjakob domain_type * 33762ac0c33Sjakob domain_wildcard_child(domain_type *domain) 33862ac0c33Sjakob { 33962ac0c33Sjakob domain_type *wildcard_child; 34062ac0c33Sjakob 34162ac0c33Sjakob assert(domain); 34262ac0c33Sjakob assert(domain->wildcard_child_closest_match); 34362ac0c33Sjakob 34462ac0c33Sjakob wildcard_child = domain->wildcard_child_closest_match; 34562ac0c33Sjakob if (wildcard_child != domain 34662ac0c33Sjakob && label_is_wildcard(dname_name(domain_dname(wildcard_child)))) 34762ac0c33Sjakob { 34862ac0c33Sjakob return wildcard_child; 34962ac0c33Sjakob } else { 35062ac0c33Sjakob return NULL; 35162ac0c33Sjakob } 35262ac0c33Sjakob } 35362ac0c33Sjakob 35462ac0c33Sjakob int 35562ac0c33Sjakob zone_is_secure(zone_type *zone) 35662ac0c33Sjakob { 35762ac0c33Sjakob assert(zone); 35862ac0c33Sjakob return zone->is_secure; 35962ac0c33Sjakob } 36062ac0c33Sjakob 36162ac0c33Sjakob uint16_t 36262ac0c33Sjakob rr_rrsig_type_covered(rr_type *rr) 36362ac0c33Sjakob { 36462ac0c33Sjakob assert(rr->type == TYPE_RRSIG); 36562ac0c33Sjakob assert(rr->rdata_count > 0); 36662ac0c33Sjakob assert(rdata_atom_size(rr->rdatas[0]) == sizeof(uint16_t)); 36762ac0c33Sjakob 36862ac0c33Sjakob return ntohs(* (uint16_t *) rdata_atom_data(rr->rdatas[0])); 36962ac0c33Sjakob } 37062ac0c33Sjakob 37162ac0c33Sjakob zone_type * 37262ac0c33Sjakob namedb_find_zone(namedb_type *db, domain_type *domain) 37362ac0c33Sjakob { 37462ac0c33Sjakob zone_type *zone; 37562ac0c33Sjakob 37662ac0c33Sjakob for (zone = db->zones; zone; zone = zone->next) { 37762ac0c33Sjakob if (zone->apex == domain) 37862ac0c33Sjakob break; 37962ac0c33Sjakob } 38062ac0c33Sjakob 38162ac0c33Sjakob return zone; 38262ac0c33Sjakob } 38362ac0c33Sjakob 38462ac0c33Sjakob rrset_type * 38562ac0c33Sjakob domain_find_non_cname_rrset(domain_type *domain, zone_type *zone) 38662ac0c33Sjakob { 38762ac0c33Sjakob /* find any rrset type that is not allowed next to a CNAME */ 38862ac0c33Sjakob /* nothing is allowed next to a CNAME, except RRSIG, NSEC, NSEC3 */ 38962ac0c33Sjakob rrset_type *result = domain->rrsets; 39062ac0c33Sjakob 39162ac0c33Sjakob while (result) { 39262ac0c33Sjakob if (result->zone == zone && /* here is the list of exceptions*/ 39362ac0c33Sjakob rrset_rrtype(result) != TYPE_CNAME && 39462ac0c33Sjakob rrset_rrtype(result) != TYPE_RRSIG && 39562ac0c33Sjakob rrset_rrtype(result) != TYPE_NXT && 39662ac0c33Sjakob rrset_rrtype(result) != TYPE_SIG && 39762ac0c33Sjakob rrset_rrtype(result) != TYPE_NSEC && 39862ac0c33Sjakob rrset_rrtype(result) != TYPE_NSEC3 ) { 39962ac0c33Sjakob return result; 40062ac0c33Sjakob } 40162ac0c33Sjakob result = result->next; 40262ac0c33Sjakob } 40362ac0c33Sjakob return NULL; 40462ac0c33Sjakob } 4050c2b6c02Sjakob 4060c2b6c02Sjakob /** 4070c2b6c02Sjakob * Create namedb. 4080c2b6c02Sjakob * 4090c2b6c02Sjakob */ 4100c2b6c02Sjakob struct namedb * 4110c2b6c02Sjakob namedb_create(void) 4120c2b6c02Sjakob { 4130c2b6c02Sjakob struct namedb *db = NULL; 4140c2b6c02Sjakob region_type *region = NULL; 4150c2b6c02Sjakob #ifdef NSEC3 4160c2b6c02Sjakob #ifndef FULL_PREHASH 4170c2b6c02Sjakob region_type *nsec3_region = NULL; 4180c2b6c02Sjakob region_type *nsec3_mod_region = NULL; 4190c2b6c02Sjakob #endif /* !FULL_PREHASH */ 4200c2b6c02Sjakob #endif /* NSEC3 */ 4210c2b6c02Sjakob 4220c2b6c02Sjakob #ifdef USE_MMAP_ALLOC 4230c2b6c02Sjakob region = region_create_custom(mmap_alloc, mmap_free, 4240c2b6c02Sjakob MMAP_ALLOC_CHUNK_SIZE, MMAP_ALLOC_LARGE_OBJECT_SIZE, 4250c2b6c02Sjakob MMAP_ALLOC_INITIAL_CLEANUP_SIZE, 1); 4260c2b6c02Sjakob #else /* !USE_MMAP_ALLOC */ 4270c2b6c02Sjakob region = region_create_custom(xalloc, free, 4280c2b6c02Sjakob DEFAULT_CHUNK_SIZE, DEFAULT_LARGE_OBJECT_SIZE, 4290c2b6c02Sjakob DEFAULT_INITIAL_CLEANUP_SIZE, 1); 4300c2b6c02Sjakob #endif /* !USE_MMAP_ALLOC */ 4310c2b6c02Sjakob if (region == NULL) 4320c2b6c02Sjakob return NULL; 4330c2b6c02Sjakob 4340c2b6c02Sjakob #ifdef NSEC3 4350c2b6c02Sjakob #ifndef FULL_PREHASH 4360c2b6c02Sjakob #ifdef USE_MMAP_ALLOC 4370c2b6c02Sjakob nsec3_region = region_create_custom(mmap_alloc, mmap_free, 4380c2b6c02Sjakob MMAP_ALLOC_CHUNK_SIZE, MMAP_ALLOC_LARGE_OBJECT_SIZE, 4390c2b6c02Sjakob MMAP_ALLOC_INITIAL_CLEANUP_SIZE, 1); 4400c2b6c02Sjakob #else /* !USE_MMAP_ALLOC */ 4410c2b6c02Sjakob nsec3_region = region_create_custom(xalloc, free, 4420c2b6c02Sjakob DEFAULT_CHUNK_SIZE, DEFAULT_LARGE_OBJECT_SIZE, 4430c2b6c02Sjakob DEFAULT_INITIAL_CLEANUP_SIZE, 1); 4440c2b6c02Sjakob #endif /* !USE_MMAP_ALLOC */ 4450c2b6c02Sjakob if (nsec3_region == NULL) { 4460c2b6c02Sjakob region_destroy(region); 4470c2b6c02Sjakob return NULL; 4480c2b6c02Sjakob } 4490c2b6c02Sjakob #ifdef USE_MMAP_ALLOC 4500c2b6c02Sjakob nsec3_mod_region = region_create_custom(mmap_alloc, mmap_free, 4510c2b6c02Sjakob MMAP_ALLOC_CHUNK_SIZE, MMAP_ALLOC_LARGE_OBJECT_SIZE, 4520c2b6c02Sjakob MMAP_ALLOC_INITIAL_CLEANUP_SIZE, 1); 4530c2b6c02Sjakob #else /* !USE_MMAP_ALLOC */ 4540c2b6c02Sjakob nsec3_mod_region = region_create_custom(xalloc, free, 4550c2b6c02Sjakob DEFAULT_CHUNK_SIZE, DEFAULT_LARGE_OBJECT_SIZE, 4560c2b6c02Sjakob DEFAULT_INITIAL_CLEANUP_SIZE, 1); 4570c2b6c02Sjakob #endif /* !USE_MMAP_ALLOC */ 4580c2b6c02Sjakob if (nsec3_mod_region == NULL) { 4590c2b6c02Sjakob region_destroy(region); 4600c2b6c02Sjakob region_destroy(nsec3_region); 4610c2b6c02Sjakob return NULL; 4620c2b6c02Sjakob } 4630c2b6c02Sjakob #endif /* !FULL_PREHASH */ 4640c2b6c02Sjakob #endif /* NSEC3 */ 4650c2b6c02Sjakob 4660c2b6c02Sjakob /* Make a new structure... */ 4670c2b6c02Sjakob db = (namedb_type *) region_alloc(region, sizeof(namedb_type)); 4680c2b6c02Sjakob db->region = region; 4690c2b6c02Sjakob #ifdef NSEC3 4700c2b6c02Sjakob #ifndef FULL_PREHASH 4710c2b6c02Sjakob db->nsec3_region = nsec3_region; 4720c2b6c02Sjakob db->nsec3_mod_region = nsec3_mod_region; 4730c2b6c02Sjakob db->nsec3_mod_domains = NULL; 4740c2b6c02Sjakob #endif /* !FULL_PREHASH */ 4750c2b6c02Sjakob #endif /* NSEC3 */ 4760c2b6c02Sjakob db->domains = domain_table_create(region); 4770c2b6c02Sjakob db->zones = NULL; 4780c2b6c02Sjakob db->zone_count = 0; 4790c2b6c02Sjakob db->filename = NULL; 4800c2b6c02Sjakob db->fd = NULL; 4810c2b6c02Sjakob db->crc = ~0; 4820c2b6c02Sjakob db->crc_pos = 0; 4830c2b6c02Sjakob db->diff_skip = 0; 4840c2b6c02Sjakob db->diff_pos = 0; 4850c2b6c02Sjakob return db; 4860c2b6c02Sjakob } 4870c2b6c02Sjakob 4880c2b6c02Sjakob /** 4890c2b6c02Sjakob * Destroy namedb. 4900c2b6c02Sjakob * 4910c2b6c02Sjakob */ 4920c2b6c02Sjakob void 4930c2b6c02Sjakob namedb_destroy(struct namedb *db) 4940c2b6c02Sjakob { 4950c2b6c02Sjakob #ifdef NSEC3 4960c2b6c02Sjakob #ifndef FULL_PREHASH 4970c2b6c02Sjakob region_destroy(db->nsec3_mod_region); 4980c2b6c02Sjakob db->nsec3_mod_region = NULL; 4990c2b6c02Sjakob db->nsec3_mod_domains = NULL; 5000c2b6c02Sjakob region_destroy(db->nsec3_region); 5010c2b6c02Sjakob db->nsec3_region = NULL; 5020c2b6c02Sjakob #endif /* !FULL_PREHASH */ 5030c2b6c02Sjakob #endif /* NSEC3 */ 5040c2b6c02Sjakob region_destroy(db->region); 5050c2b6c02Sjakob } 5060c2b6c02Sjakob 5070c2b6c02Sjakob 5080c2b6c02Sjakob #ifdef NSEC3 5090c2b6c02Sjakob #ifndef FULL_PREHASH 5100c2b6c02Sjakob int 5110c2b6c02Sjakob zone_nsec3_domains_create(struct namedb *db, struct zone *zone) 5120c2b6c02Sjakob { 5130c2b6c02Sjakob if ((db == NULL) || (zone == NULL)) 5140c2b6c02Sjakob return EINVAL; 5150c2b6c02Sjakob if (zone->nsec3_domains != NULL) 5160c2b6c02Sjakob return 0; 5170c2b6c02Sjakob zone->nsec3_domains = rbtree_create(db->nsec3_region, 5180c2b6c02Sjakob dname_compare); 5190c2b6c02Sjakob if (zone->nsec3_domains == NULL) 5200c2b6c02Sjakob return ENOMEM; 5210c2b6c02Sjakob return 0; 5220c2b6c02Sjakob } 5230c2b6c02Sjakob 5240c2b6c02Sjakob int 5250c2b6c02Sjakob zone_nsec3_domains_destroy(struct namedb *db, struct zone *zone) 5260c2b6c02Sjakob { 5270c2b6c02Sjakob rbnode_t *node; 5280c2b6c02Sjakob if ((db == NULL) || (zone == NULL)) 5290c2b6c02Sjakob return EINVAL; 5300c2b6c02Sjakob if (zone->nsec3_domains == NULL) 5310c2b6c02Sjakob return 0; 5320c2b6c02Sjakob 5330c2b6c02Sjakob node = rbtree_postorder_first(zone->nsec3_domains->root); 5340c2b6c02Sjakob while (node != RBTREE_NULL) { 5350c2b6c02Sjakob struct nsec3_domain *nsec3_domain = 5360c2b6c02Sjakob (struct nsec3_domain *) node; 5370c2b6c02Sjakob node = rbtree_postorder_next(node); 5380c2b6c02Sjakob 5390c2b6c02Sjakob if (nsec3_domain->covers != NULL) { 5400c2b6c02Sjakob nsec3_domain->covers->nsec3_cover = NULL; 5410c2b6c02Sjakob } 5420c2b6c02Sjakob region_recycle(db->nsec3_region, nsec3_domain, 5430c2b6c02Sjakob sizeof(*nsec3_domain)); 5440c2b6c02Sjakob } 5450c2b6c02Sjakob region_recycle(db->nsec3_region, zone->nsec3_domains, 5460c2b6c02Sjakob sizeof(*(zone->nsec3_domains))); 5470c2b6c02Sjakob zone->nsec3_domains = NULL; 5480c2b6c02Sjakob return 0; 5490c2b6c02Sjakob } 5500c2b6c02Sjakob 5510c2b6c02Sjakob 5520c2b6c02Sjakob int 5530c2b6c02Sjakob namedb_add_nsec3_domain(struct namedb *db, struct domain *domain, 5540c2b6c02Sjakob struct zone *zone) 5550c2b6c02Sjakob { 5560c2b6c02Sjakob struct nsec3_domain *nsec3_domain; 5570c2b6c02Sjakob if (zone->nsec3_domains == NULL) 5580c2b6c02Sjakob return 0; 5590c2b6c02Sjakob nsec3_domain = (struct nsec3_domain *) region_alloc(db->nsec3_region, 5600c2b6c02Sjakob sizeof(*nsec3_domain)); 5610c2b6c02Sjakob if (nsec3_domain == NULL) 5620c2b6c02Sjakob return ENOMEM; 5630c2b6c02Sjakob nsec3_domain->node.key = domain_dname(domain); 5640c2b6c02Sjakob nsec3_domain->nsec3_domain = domain; 5650c2b6c02Sjakob nsec3_domain->covers = NULL; 5660c2b6c02Sjakob if (rbtree_insert(zone->nsec3_domains, (rbnode_t *) nsec3_domain) == NULL) { 5670c2b6c02Sjakob region_recycle(db->nsec3_region, nsec3_domain, sizeof(*nsec3_domain)); 5680c2b6c02Sjakob } 5690c2b6c02Sjakob return 0; 5700c2b6c02Sjakob } 5710c2b6c02Sjakob 5720c2b6c02Sjakob 5730c2b6c02Sjakob int 5740c2b6c02Sjakob namedb_del_nsec3_domain(struct namedb *db, struct domain *domain, 5750c2b6c02Sjakob struct zone *zone) 5760c2b6c02Sjakob { 5770c2b6c02Sjakob rbnode_t *node; 5780c2b6c02Sjakob struct nsec3_domain *nsec3_domain; 5790c2b6c02Sjakob int error = 0; 5800c2b6c02Sjakob 5810c2b6c02Sjakob if (zone->nsec3_domains == NULL) 5820c2b6c02Sjakob return 0; 5830c2b6c02Sjakob 5840c2b6c02Sjakob node = rbtree_delete(zone->nsec3_domains, domain_dname(domain)); 5850c2b6c02Sjakob if (node == NULL) 5860c2b6c02Sjakob return 0; 5870c2b6c02Sjakob 5880c2b6c02Sjakob nsec3_domain = (struct nsec3_domain *) node; 5890c2b6c02Sjakob if (nsec3_domain->covers != NULL) { 5900c2b6c02Sjakob /* 5910c2b6c02Sjakob * It is possible that this NSEC3 domain was modified 5920c2b6c02Sjakob * due to the addition/deletion of another NSEC3 domain. 5930c2b6c02Sjakob * Make sure it gets added to the NSEC3 list later by 5940c2b6c02Sjakob * making sure it's covered domain is added to the 5950c2b6c02Sjakob * NSEC3 mod list. S64#3441 5960c2b6c02Sjakob */ 5970c2b6c02Sjakob error = namedb_add_nsec3_mod_domain(db, nsec3_domain->covers); 5980c2b6c02Sjakob nsec3_domain->covers->nsec3_cover = NULL; 5990c2b6c02Sjakob nsec3_domain->covers = NULL; 6000c2b6c02Sjakob } 6010c2b6c02Sjakob region_recycle(db->nsec3_region, nsec3_domain, sizeof(*nsec3_domain)); 6020c2b6c02Sjakob return error; 6030c2b6c02Sjakob } 6040c2b6c02Sjakob 6050c2b6c02Sjakob 6060c2b6c02Sjakob int 6070c2b6c02Sjakob namedb_nsec3_mod_domains_create(struct namedb *db) 6080c2b6c02Sjakob { 6090c2b6c02Sjakob if (db == NULL) 6100c2b6c02Sjakob return EINVAL; 6110c2b6c02Sjakob namedb_nsec3_mod_domains_destroy(db); 6120c2b6c02Sjakob 6130c2b6c02Sjakob db->nsec3_mod_domains = rbtree_create(db->nsec3_mod_region, dname_compare); 6140c2b6c02Sjakob if (db->nsec3_mod_domains == NULL) 6150c2b6c02Sjakob return ENOMEM; 6160c2b6c02Sjakob return 0; 6170c2b6c02Sjakob } 6180c2b6c02Sjakob 6190c2b6c02Sjakob 6200c2b6c02Sjakob int 6210c2b6c02Sjakob namedb_nsec3_mod_domains_destroy(struct namedb *db) 6220c2b6c02Sjakob { 6230c2b6c02Sjakob if (db == NULL) 6240c2b6c02Sjakob return EINVAL; 6250c2b6c02Sjakob if (db->nsec3_mod_domains == NULL) 6260c2b6c02Sjakob return 0; 6270c2b6c02Sjakob region_free_all(db->nsec3_mod_region); 6280c2b6c02Sjakob db->nsec3_mod_domains = NULL; 6290c2b6c02Sjakob return 0; 6300c2b6c02Sjakob } 6310c2b6c02Sjakob 6320c2b6c02Sjakob int 6330c2b6c02Sjakob namedb_add_nsec3_mod_domain(struct namedb *db, struct domain *domain) 6340c2b6c02Sjakob { 6350c2b6c02Sjakob struct nsec3_mod_domain *nsec3_mod_domain; 6360c2b6c02Sjakob nsec3_mod_domain = (struct nsec3_mod_domain *) 6370c2b6c02Sjakob region_alloc(db->nsec3_mod_region, sizeof(*nsec3_mod_domain)); 6380c2b6c02Sjakob if (nsec3_mod_domain == NULL) { 6390c2b6c02Sjakob log_msg(LOG_ERR, 6400c2b6c02Sjakob "memory allocation failure on modified domain"); 6410c2b6c02Sjakob return ENOMEM; 6420c2b6c02Sjakob } 6430c2b6c02Sjakob nsec3_mod_domain->node.key = domain_dname(domain); 6440c2b6c02Sjakob nsec3_mod_domain->domain = domain; 6450c2b6c02Sjakob 6460c2b6c02Sjakob if (rbtree_insert(db->nsec3_mod_domains, (rbnode_t *) nsec3_mod_domain) == NULL) { 6470c2b6c02Sjakob region_recycle(db->nsec3_mod_region, nsec3_mod_domain, 6480c2b6c02Sjakob sizeof(*nsec3_mod_domain)); 6490c2b6c02Sjakob } 6500c2b6c02Sjakob return 0; 6510c2b6c02Sjakob } 6520c2b6c02Sjakob #endif /* !FULL_PREHASH */ 6530c2b6c02Sjakob #endif /* NSEC3 */ 654