1 /* 2 * namedb.h -- nsd(8) internal namespace database definitions 3 * 4 * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. 5 * 6 * See LICENSE for the license. 7 * 8 */ 9 10 #ifndef _NAMEDB_H_ 11 #define _NAMEDB_H_ 12 13 #include <stdio.h> 14 15 #include "dname.h" 16 #include "dns.h" 17 #include "radtree.h" 18 #include "rbtree.h" 19 struct zone_options; 20 struct nsd_options; 21 struct udb_base; 22 struct udb_ptr; 23 struct nsd; 24 25 typedef union rdata_atom rdata_atom_type; 26 typedef struct rrset rrset_type; 27 typedef struct rr rr_type; 28 29 /* 30 * A domain name table supporting fast insert and search operations. 31 */ 32 typedef struct domain_table domain_table_type; 33 typedef struct domain domain_type; 34 typedef struct zone zone_type; 35 typedef struct namedb namedb_type; 36 37 struct domain_table 38 { 39 region_type* region; 40 struct radtree *nametree; 41 domain_type* root; 42 /* ptr to biggest domain.number and last in list. 43 * the root is the lowest and first in the list. */ 44 domain_type *numlist_last; 45 #ifdef NSEC3 46 /* the prehash list, start of the list */ 47 domain_type* prehash_list; 48 #endif /* NSEC3 */ 49 }; 50 51 #ifdef NSEC3 52 struct nsec3_domain_data { 53 /* (if nsec3 chain complete) always the covering nsec3 record */ 54 domain_type* nsec3_cover; 55 /* the nsec3 that covers the wildcard child of this domain. */ 56 domain_type* nsec3_wcard_child_cover; 57 /* for the DS case we must answer on the parent side of zone cut */ 58 domain_type* nsec3_ds_parent_cover; 59 /* NSEC3 domains to prehash, prev and next on the list or cleared */ 60 domain_type* prehash_prev, *prehash_next; 61 /* entry in the nsec3tree (for NSEC3s in the chain in use) */ 62 rbnode_t nsec3_node; 63 /* entry in the hashtree (for precompiled domains) */ 64 rbnode_t hash_node; 65 /* entry in the wchashtree (the wildcard precompile) */ 66 rbnode_t wchash_node; 67 /* entry in the dshashtree (the parent ds precompile) */ 68 rbnode_t dshash_node; 69 70 /* nsec3 hash */ 71 uint8_t nsec3_hash[NSEC3_HASH_LEN]; 72 /* nsec3 hash of wildcard before this name */ 73 uint8_t nsec3_wc_hash[NSEC3_HASH_LEN]; 74 /* parent-side DS hash */ 75 uint8_t nsec3_ds_parent_hash[NSEC3_HASH_LEN]; 76 /* if the nsec3 has is available */ 77 unsigned have_nsec3_hash : 1; 78 unsigned have_nsec3_wc_hash : 1; 79 unsigned have_nsec3_ds_parent_hash : 1; 80 /* if the domain has an NSEC3 for it, use cover ptr to get it. */ 81 unsigned nsec3_is_exact : 1; 82 /* same but on parent side */ 83 unsigned nsec3_ds_parent_is_exact : 1; 84 }; 85 #endif /* NSEC3 */ 86 87 struct domain 88 { 89 struct radnode* rnode; 90 const dname_type* dname; 91 domain_type* parent; 92 domain_type* wildcard_child_closest_match; 93 rrset_type* rrsets; 94 #ifdef NSEC3 95 struct nsec3_domain_data* nsec3; 96 #endif 97 /* double-linked list sorted by domain.number */ 98 domain_type* numlist_prev, *numlist_next; 99 size_t number; /* Unique domain name number. */ 100 size_t usage; /* number of ptrs to this from RRs(in rdata) and 101 from zone-apex pointers, also the root has one 102 more to make sure it cannot be deleted. */ 103 104 /* 105 * This domain name exists (see wildcard clarification draft). 106 */ 107 unsigned is_existing : 1; 108 unsigned is_apex : 1; 109 }; 110 111 struct zone 112 { 113 struct radnode *node; /* this entry in zonetree */ 114 domain_type* apex; 115 rrset_type* soa_rrset; 116 rrset_type* soa_nx_rrset; /* see bug #103 */ 117 rrset_type* ns_rrset; 118 #ifdef NSEC3 119 rr_type* nsec3_param; /* NSEC3PARAM RR of chain in use or NULL */ 120 domain_type* nsec3_last; /* last domain with nsec3, wraps */ 121 /* in these trees, the root contains an elem ptr to the radtree* */ 122 rbtree_t* nsec3tree; /* tree with relevant NSEC3 domains */ 123 rbtree_t* hashtree; /* tree, hashed NSEC3precompiled domains */ 124 rbtree_t* wchashtree; /* tree, wildcard hashed domains */ 125 rbtree_t* dshashtree; /* tree, ds-parent-hash domains */ 126 #endif 127 struct zone_options* opts; 128 char* filename; /* set if read from file, which file */ 129 char* logstr; /* set for zone xfer, the log string */ 130 time_t mtime; /* time of last modification */ 131 unsigned zonestatid; /* array index for zone stats */ 132 unsigned is_secure : 1; /* zone uses DNSSEC */ 133 unsigned is_ok : 1; /* zone has not expired. */ 134 unsigned is_changed : 1; /* zone was changed by AXFR */ 135 }; 136 137 /* a RR in DNS */ 138 struct rr { 139 domain_type* owner; 140 rdata_atom_type* rdatas; 141 uint32_t ttl; 142 uint16_t type; 143 uint16_t klass; 144 uint16_t rdata_count; 145 }; 146 147 /* 148 * An RRset consists of at least one RR. All RRs are from the same 149 * zone. 150 */ 151 struct rrset 152 { 153 rrset_type* next; 154 zone_type* zone; 155 rr_type* rrs; 156 uint16_t rr_count; 157 }; 158 159 /* 160 * The field used is based on the wireformat the atom is stored in. 161 * The allowed wireformats are defined by the rdata_wireformat_type 162 * enumeration. 163 */ 164 union rdata_atom 165 { 166 /* RDATA_WF_COMPRESSED_DNAME, RDATA_WF_UNCOMPRESSED_DNAME */ 167 domain_type* domain; 168 169 /* Default. */ 170 uint16_t* data; 171 }; 172 173 /* 174 * Create a new domain_table containing only the root domain. 175 */ 176 domain_table_type *domain_table_create(region_type *region); 177 178 /* 179 * Search the domain table for a match and the closest encloser. 180 */ 181 int domain_table_search(domain_table_type* table, 182 const dname_type* dname, 183 domain_type **closest_match, 184 domain_type **closest_encloser); 185 186 /* 187 * The number of domains stored in the table (minimum is one for the 188 * root domain). 189 */ 190 static inline uint32_t 191 domain_table_count(domain_table_type* table) 192 { 193 return table->nametree->count; 194 } 195 196 /* 197 * Find the specified dname in the domain_table. NULL is returned if 198 * there is no exact match. 199 */ 200 domain_type* domain_table_find(domain_table_type* table, 201 const dname_type* dname); 202 203 /* 204 * Insert a domain name in the domain table. If the domain name is 205 * not yet present in the table it is copied and a new dname_info node 206 * is created (as well as for the missing parent domain names, if 207 * any). Otherwise the domain_type that is already in the 208 * domain_table is returned. 209 */ 210 domain_type *domain_table_insert(domain_table_type *table, 211 const dname_type *dname); 212 213 /* put domain into nsec3 hash space tree */ 214 void zone_add_domain_in_hash_tree(region_type* region, rbtree_t** tree, 215 int (*cmpf)(const void*, const void*), domain_type* domain, 216 rbnode_t* node); 217 void zone_del_domain_in_hash_tree(rbtree_t* tree, rbnode_t* node); 218 void hash_tree_clear(rbtree_t* tree); 219 void hash_tree_delete(region_type* region, rbtree_t* tree); 220 void prehash_clear(domain_table_type* table); 221 void prehash_add(domain_table_type* table, domain_type* domain); 222 void prehash_del(domain_table_type* table, domain_type* domain); 223 int domain_is_prehash(domain_table_type* table, domain_type* domain); 224 225 /* 226 * Iterate over all the domain names in the domain tree. 227 */ 228 typedef int (*domain_table_iterator_type)(domain_type *node, 229 void *user_data); 230 231 int domain_table_iterate(domain_table_type* table, 232 domain_table_iterator_type iterator, 233 void* user_data); 234 235 /* 236 * Add an RRset to the specified domain. Updates the is_existing flag 237 * as required. 238 */ 239 void domain_add_rrset(domain_type* domain, rrset_type* rrset); 240 241 rrset_type* domain_find_rrset(domain_type* domain, zone_type* zone, uint16_t type); 242 rrset_type* domain_find_any_rrset(domain_type* domain, zone_type* zone); 243 244 zone_type* domain_find_zone(namedb_type* db, domain_type* domain); 245 zone_type* domain_find_parent_zone(zone_type* zone); 246 247 domain_type* domain_find_ns_rrsets(domain_type* domain, zone_type* zone, rrset_type **ns); 248 249 int domain_is_glue(domain_type* domain, zone_type* zone); 250 251 rrset_type* domain_find_non_cname_rrset(domain_type* domain, zone_type* zone); 252 253 domain_type* domain_wildcard_child(domain_type* domain); 254 domain_type *domain_previous_existing_child(domain_type* domain); 255 256 int zone_is_secure(zone_type* zone); 257 258 static inline const dname_type * 259 domain_dname(domain_type* domain) 260 { 261 return domain->dname; 262 } 263 264 static inline domain_type * 265 domain_previous(domain_type* domain) 266 { 267 struct radnode* prev = radix_prev(domain->rnode); 268 return prev == NULL ? NULL : (domain_type*)prev->elem; 269 } 270 271 static inline domain_type * 272 domain_next(domain_type* domain) 273 { 274 struct radnode* next = radix_next(domain->rnode); 275 return next == NULL ? NULL : (domain_type*)next->elem; 276 } 277 278 /* easy comparison for subdomain, true if d1 is subdomain of d2. */ 279 static inline int domain_is_subdomain(domain_type* d1, domain_type* d2) 280 { return dname_is_subdomain(domain_dname(d1), domain_dname(d2)); } 281 /* easy printout, to static buffer of dname_to_string, fqdn. */ 282 static inline const char* domain_to_string(domain_type* domain) 283 { return dname_to_string(domain_dname(domain), NULL); } 284 285 /* 286 * The type covered by the signature in the specified RRSIG RR. 287 */ 288 uint16_t rr_rrsig_type_covered(rr_type* rr); 289 290 struct namedb 291 { 292 region_type* region; 293 domain_table_type* domains; 294 struct radtree* zonetree; 295 struct udb_base* udb; 296 /* the timestamp on the ixfr.db file */ 297 struct timeval diff_timestamp; 298 /* if diff_skip=1, diff_pos contains the nsd.diff place to continue */ 299 uint8_t diff_skip; 300 off_t diff_pos; 301 }; 302 303 static inline int rdata_atom_is_domain(uint16_t type, size_t index); 304 static inline int rdata_atom_is_literal_domain(uint16_t type, size_t index); 305 306 static inline domain_type * 307 rdata_atom_domain(rdata_atom_type atom) 308 { 309 return atom.domain; 310 } 311 312 static inline uint16_t 313 rdata_atom_size(rdata_atom_type atom) 314 { 315 return *atom.data; 316 } 317 318 static inline uint8_t * 319 rdata_atom_data(rdata_atom_type atom) 320 { 321 return (uint8_t *) (atom.data + 1); 322 } 323 324 325 /* Find the zone for the specified dname in DB. */ 326 zone_type *namedb_find_zone(namedb_type *db, const dname_type *dname); 327 /* 328 * Delete a domain name from the domain table. Removes dname_info node. 329 * Only deletes if usage is 0, has no rrsets and no children. Checks parents 330 * for deletion as well. Adjusts numberlist(domain.number), and 331 * wcard_child closest match. 332 */ 333 void domain_table_deldomain(namedb_type* db, domain_type* domain); 334 335 336 /** dbcreate.c */ 337 int udb_write_rr(struct udb_base* udb, struct udb_ptr* z, rr_type* rr); 338 void udb_del_rr(struct udb_base* udb, struct udb_ptr* z, rr_type* rr); 339 int write_zone_to_udb(struct udb_base* udb, zone_type* zone, time_t mtime, 340 const char* file_str); 341 /** marshal rdata into buffer, must be MAX_RDLENGTH in size */ 342 size_t rr_marshal_rdata(rr_type* rr, uint8_t* rdata, size_t sz); 343 /* dbaccess.c */ 344 int namedb_lookup (struct namedb* db, 345 const dname_type* dname, 346 domain_type **closest_match, 347 domain_type **closest_encloser); 348 /* pass number of children (to alloc in dirty array */ 349 struct namedb *namedb_open(const char *filename, struct nsd_options* opt); 350 void namedb_close_udb(struct namedb* db); 351 void namedb_close(struct namedb* db); 352 void namedb_check_zonefiles(struct nsd* nsd, struct nsd_options* opt, 353 struct udb_base* taskudb, struct udb_ptr* last_task); 354 void namedb_check_zonefile(struct nsd* nsd, struct udb_base* taskudb, 355 struct udb_ptr* last_task, struct zone_options* zo); 356 /** zone one zonefile into memory and revert on parse error, write to udb */ 357 void namedb_read_zonefile(struct nsd* nsd, struct zone* zone, 358 struct udb_base* taskudb, struct udb_ptr* last_task); 359 void apex_rrset_checks(struct namedb* db, rrset_type* rrset, 360 domain_type* domain); 361 zone_type* namedb_zone_create(namedb_type* db, const dname_type* dname, 362 struct zone_options* zopt); 363 void namedb_zone_delete(namedb_type* db, zone_type* zone); 364 void namedb_write_zonefile(struct nsd* nsd, struct zone_options* zopt); 365 void namedb_write_zonefiles(struct nsd* nsd, struct nsd_options* options); 366 int create_dirs(const char* path); 367 void allocate_domain_nsec3(domain_table_type *table, domain_type *result); 368 369 static inline int 370 rdata_atom_is_domain(uint16_t type, size_t index) 371 { 372 const rrtype_descriptor_type *descriptor 373 = rrtype_descriptor_by_type(type); 374 return (index < descriptor->maximum 375 && (descriptor->wireformat[index] == RDATA_WF_COMPRESSED_DNAME 376 || descriptor->wireformat[index] == RDATA_WF_UNCOMPRESSED_DNAME)); 377 } 378 379 static inline int 380 rdata_atom_is_literal_domain(uint16_t type, size_t index) 381 { 382 const rrtype_descriptor_type *descriptor 383 = rrtype_descriptor_by_type(type); 384 return (index < descriptor->maximum 385 && (descriptor->wireformat[index] == RDATA_WF_LITERAL_DNAME)); 386 } 387 388 static inline rdata_wireformat_type 389 rdata_atom_wireformat_type(uint16_t type, size_t index) 390 { 391 const rrtype_descriptor_type *descriptor 392 = rrtype_descriptor_by_type(type); 393 assert(index < descriptor->maximum); 394 return (rdata_wireformat_type) descriptor->wireformat[index]; 395 } 396 397 static inline uint16_t 398 rrset_rrtype(rrset_type* rrset) 399 { 400 assert(rrset); 401 assert(rrset->rr_count > 0); 402 return rrset->rrs[0].type; 403 } 404 405 static inline uint16_t 406 rrset_rrclass(rrset_type* rrset) 407 { 408 assert(rrset); 409 assert(rrset->rr_count > 0); 410 return rrset->rrs[0].klass; 411 } 412 413 #endif 414