Home | History | Annotate | Line # | Download | only in dist
      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 struct zone_ixfr;
     25 
     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 #ifdef USE_RADIX_TREE
     41 	struct radtree *nametree;
     42 #else
     43 	rbtree_type      *names_to_domains;
     44 #endif
     45 	domain_type* root;
     46 	/* ptr to biggest domain.number and last in list.
     47 	 * the root is the lowest and first in the list. */
     48 	domain_type *numlist_last;
     49 #ifdef NSEC3
     50 	/* the prehash list, start of the list */
     51 	domain_type* prehash_list;
     52 #endif /* NSEC3 */
     53 };
     54 
     55 #ifdef NSEC3
     56 typedef struct nsec3_hash_node nsec3_hash_node_type;
     57 struct nsec3_hash_node {
     58 	/* hash value */
     59 	uint8_t hash[NSEC3_HASH_LEN];
     60 	/* entry in the hashtree */
     61 	rbnode_type node;
     62 } ATTR_PACKED;
     63 
     64 typedef struct nsec3_hash_wc_node nsec3_hash_wc_node_type;
     65 struct nsec3_hash_wc_node {
     66 	nsec3_hash_node_type hash;
     67 	nsec3_hash_node_type wc;
     68 };
     69 
     70 struct nsec3_domain_data {
     71 	/* (if nsec3 chain complete) always the covering nsec3 record */
     72 	domain_type* nsec3_cover;
     73 	/* the nsec3 that covers the wildcard child of this domain. */
     74 	domain_type* nsec3_wcard_child_cover;
     75 	/* for the DS case we must answer on the parent side of zone cut */
     76 	domain_type* nsec3_ds_parent_cover;
     77 	/* NSEC3 domains to prehash, prev and next on the list or cleared */
     78 	domain_type* prehash_prev, *prehash_next;
     79 	/* entry in the nsec3tree (for NSEC3s in the chain in use) */
     80 	rbnode_type nsec3_node;
     81 
     82 	/* node for the precompiled domain and the precompiled wildcard */
     83 	nsec3_hash_wc_node_type* hash_wc;
     84 
     85 	/* node for the precompiled parent ds */
     86 	nsec3_hash_node_type* ds_parent_hash;
     87 
     88 	/* if the domain has an NSEC3 for it, use cover ptr to get it. */
     89 	unsigned     nsec3_is_exact : 1;
     90 	/* same but on parent side */
     91 	unsigned     nsec3_ds_parent_is_exact : 1;
     92 } ATTR_PACKED;
     93 #endif /* NSEC3 */
     94 
     95 struct domain
     96 {
     97 #ifdef USE_RADIX_TREE
     98 	struct radnode* rnode;
     99 	const dname_type* dname;
    100 #else
    101 	rbnode_type     node;
    102 #endif
    103 	domain_type* parent;
    104 	domain_type* wildcard_child_closest_match;
    105 	rrset_type* rrsets;
    106 #ifdef NSEC3
    107 	struct nsec3_domain_data* nsec3;
    108 #endif
    109 	/* double-linked list sorted by domain.number */
    110 	domain_type* numlist_prev, *numlist_next;
    111 	uint32_t     number; /* Unique domain name number.  */
    112 	uint32_t     usage; /* number of ptrs to this from RRs(in rdata) and
    113 			     from zone-apex pointers, also the root has one
    114 			     more to make sure it cannot be deleted. */
    115 
    116 	/*
    117 	 * This domain name exists (see wildcard clarification draft).
    118 	 */
    119 	unsigned     is_existing : 1;
    120 	unsigned     is_apex : 1;
    121 } ATTR_PACKED;
    122 
    123 struct zone
    124 {
    125 	struct radnode *node; /* this entry in zonetree */
    126 	domain_type* apex;
    127 	rrset_type*  soa_rrset;
    128 	rrset_type*  soa_nx_rrset; /* see bug #103 */
    129 	rrset_type*  ns_rrset;
    130 #ifdef NSEC3
    131 	rr_type* nsec3_param; /* NSEC3PARAM RR of chain in use or NULL */
    132 	domain_type* nsec3_last; /* last domain with nsec3, wraps */
    133 	/* in these trees, the root contains an elem ptr to the radtree* */
    134 	rbtree_type* nsec3tree; /* tree with relevant NSEC3 domains */
    135 	rbtree_type* hashtree; /* tree, hashed NSEC3precompiled domains */
    136 	rbtree_type* wchashtree; /* tree, wildcard hashed domains */
    137 	rbtree_type* dshashtree; /* tree, ds-parent-hash domains */
    138 #endif
    139 	struct zone_options* opts;
    140 	struct zone_ixfr* ixfr;
    141 	char *filename; /* set if read from file, which files */
    142 	/* list of include files to monitor for changes */
    143 	struct {
    144 		size_t count;
    145 		char **paths;
    146 	} includes;
    147 	char*        logstr; /* set for zone xfer, the log string */
    148 	struct timespec mtime; /* time of last modification */
    149 	unsigned     zonestatid; /* array index for zone stats */
    150 	unsigned     is_secure : 1; /* zone uses DNSSEC */
    151 	unsigned     is_ok : 1; /* zone has not expired */
    152 	unsigned     is_changed : 1; /* zone changes must be written to disk */
    153 	unsigned     is_updated : 1; /* zone was changed by XFR */
    154 	unsigned     is_skipped : 1; /* subsequent zone updates are skipped */
    155 	unsigned     is_checked : 1; /* zone already verified */
    156 	unsigned     is_bad : 1; /* zone failed verification */
    157 } ATTR_PACKED;
    158 
    159 /* a RR in DNS.
    160  * The RDATA is directly allocated with the RR structure and pointers to
    161  * domains are directly stored (likely unaligned) in the RDATA. We do this
    162  * primarily to save memory, but as the RDATA is directly stored with the RR,
    163  * it is likely that data is cached with the RR which should have a positive
    164  * impact on performance. When paired with direct conversion routines we are
    165  * very likely to improve performance when importing zones and writing RRs out
    166  * to the wire. That is in the rr.rdata array, it contains the rdata without
    167  * the rdlength bytes. The rdlength contains the length of the rr.rdata array,
    168  * that includes the pointer size for names that are pointer references to
    169  * struct domain.
    170  */
    171 struct rr {
    172 	domain_type*     owner;
    173 	uint32_t         ttl;
    174 	uint16_t         type;
    175 	uint16_t         klass;
    176 	uint16_t         rdlength;
    177 	uint8_t          rdata[]; /* c99 flexible array */
    178 } ATTR_PACKED;
    179 
    180 /*
    181  * An RRset consists of at least one RR.  All RRs are from the same
    182  * zone.
    183  */
    184 struct rrset
    185 {
    186 	rrset_type* next;
    187 	zone_type*  zone;
    188 #ifndef PACKED_STRUCTS
    189 	/* If the storage is not packed, there is a pointer to a separate
    190 	 * array of rr_type pointers. This is then accessed in an aligned
    191 	 * manner.
    192 	 * If the storage is packed, the pointer to the array is not there.
    193 	 * The rr_type pointers for the rrs are stored after the struct rrset,
    194 	 * contiguously allocated. This is then unaligned pointers, as they
    195 	 * are after the packed structure. The region also stores items when
    196 	 * packed structs is enabled without alignment, and thus there are
    197 	 * unaligned accesses. It then has unaligned access for like struct
    198 	 * domain. So unaligned access is used then, here too. This saves
    199 	 * the space used by the rr_type** rrs array pointer.
    200 	 * The rr pointers can then be accessed through the rrs[] member and,
    201 	 * that is an unaligned access, and does not need an accessor function.
    202 	 */
    203 	rr_type**   rrs;
    204 #endif
    205 	uint16_t    rr_count;
    206 #ifdef PACKED_STRUCTS
    207 	rr_type*    rrs[]; /* c99 flexible array */
    208 #endif
    209 } ATTR_PACKED;
    210 
    211 /*
    212  * Create a new domain_table containing only the root domain.
    213  */
    214 domain_table_type *domain_table_create(region_type *region);
    215 
    216 /*
    217  * Search the domain table for a match and the closest encloser.
    218  */
    219 int domain_table_search(domain_table_type* table,
    220 			const dname_type* dname,
    221 			domain_type      **closest_match,
    222 			domain_type      **closest_encloser);
    223 
    224 /*
    225  * The number of domains stored in the table (minimum is one for the
    226  * root domain).
    227  */
    228 static inline uint32_t
    229 domain_table_count(domain_table_type* table)
    230 {
    231 #ifdef USE_RADIX_TREE
    232 	return table->nametree->count;
    233 #else
    234 	return table->names_to_domains->count;
    235 #endif
    236 }
    237 
    238 /*
    239  * Find the specified dname in the domain_table.  NULL is returned if
    240  * there is no exact match.
    241  */
    242 domain_type* domain_table_find(domain_table_type* table,
    243 			       const dname_type* dname);
    244 
    245 /*
    246  * Insert a domain name in the domain table.  If the domain name is
    247  * not yet present in the table it is copied and a new dname_info node
    248  * is created (as well as for the missing parent domain names, if
    249  * any).  Otherwise the domain_type that is already in the
    250  * domain_table is returned.
    251  */
    252 domain_type *domain_table_insert(domain_table_type *table,
    253 				 const dname_type  *dname);
    254 
    255 /* put domain into nsec3 hash space tree */
    256 void zone_add_domain_in_hash_tree(region_type* region, rbtree_type** tree,
    257 	int (*cmpf)(const void*, const void*), domain_type* domain,
    258 	rbnode_type* node);
    259 void zone_del_domain_in_hash_tree(rbtree_type* tree, rbnode_type* node);
    260 void hash_tree_delete(region_type* region, rbtree_type* tree);
    261 void prehash_clear(domain_table_type* table);
    262 void prehash_add(domain_table_type* table, domain_type* domain);
    263 void prehash_del(domain_table_type* table, domain_type* domain);
    264 int domain_is_prehash(domain_table_type* table, domain_type* domain);
    265 
    266 /*
    267  * Add an RRset to the specified domain.  Updates the is_existing flag
    268  * as required.
    269  */
    270 void domain_add_rrset(domain_type* domain, rrset_type* rrset);
    271 
    272 rrset_type* domain_find_rrset(domain_type* domain, zone_type* zone, uint16_t type);
    273 rrset_type* domain_find_any_rrset(domain_type* domain, zone_type* zone);
    274 rrset_type* domain_find_rrset_and_prev(domain_type* domain, zone_type* zone,
    275 	uint16_t type, rrset_type** prev);
    276 
    277 zone_type* domain_find_zone(namedb_type* db, domain_type* domain);
    278 zone_type* domain_find_parent_zone(namedb_type* db, zone_type* zone);
    279 
    280 domain_type* domain_find_ns_rrsets(domain_type* domain, zone_type* zone, rrset_type **ns);
    281 /* find DNAME rrset in domain->parent or higher and return that domain */
    282 domain_type * find_dname_above(domain_type* domain, zone_type* zone);
    283 
    284 int domain_is_glue(domain_type* domain, zone_type* zone);
    285 
    286 rrset_type* domain_find_non_cname_rrset(domain_type* domain, zone_type* zone);
    287 
    288 domain_type* domain_wildcard_child(domain_type* domain);
    289 domain_type *domain_previous_existing_child(domain_type* domain);
    290 
    291 int zone_is_secure(zone_type* zone);
    292 
    293 static inline dname_type *
    294 domain_dname(domain_type* domain)
    295 {
    296 #ifdef USE_RADIX_TREE
    297 	return (dname_type *) domain->dname;
    298 #else
    299 	return (dname_type *) domain->node.key;
    300 #endif
    301 }
    302 
    303 static inline const dname_type *
    304 domain_dname_const(const domain_type* domain)
    305 {
    306 #ifdef USE_RADIX_TREE
    307 	return domain->dname;
    308 #else
    309 	return (const dname_type *) domain->node.key;
    310 #endif
    311 }
    312 
    313 static inline domain_type *
    314 domain_previous(domain_type* domain)
    315 {
    316 #ifdef USE_RADIX_TREE
    317 	struct radnode* prev = radix_prev(domain->rnode);
    318 	return prev == NULL ? NULL : (domain_type*)prev->elem;
    319 #else
    320 	rbnode_type *prev = rbtree_previous((rbnode_type *) domain);
    321 	return prev == RBTREE_NULL ? NULL : (domain_type *) prev;
    322 #endif
    323 }
    324 
    325 static inline domain_type *
    326 domain_next(domain_type* domain)
    327 {
    328 #ifdef USE_RADIX_TREE
    329 	struct radnode* next = radix_next(domain->rnode);
    330 	return next == NULL ? NULL : (domain_type*)next->elem;
    331 #else
    332 	rbnode_type *next = rbtree_next((rbnode_type *) domain);
    333 	return next == RBTREE_NULL ? NULL : (domain_type *) next;
    334 #endif
    335 }
    336 
    337 /* easy comparison for subdomain, true if d1 is subdomain of d2. */
    338 static inline int domain_is_subdomain(domain_type* d1, domain_type* d2)
    339 { return dname_is_subdomain(domain_dname(d1), domain_dname(d2)); }
    340 /* easy printout, to static buffer of dname_to_string, fqdn. */
    341 static inline const char* domain_to_string(domain_type* domain)
    342 { return dname_to_string(domain_dname(domain), NULL); }
    343 /* easy printout, to given buffer of dname_to_string, fqdn. */
    344 static inline const char* domain_to_string_buf(domain_type* domain, char *buf)
    345 { return dname_to_string_buf(domain_dname(domain), NULL, buf); }
    346 
    347 
    348 /*
    349  * The type covered by the signature in the specified RRSIG RR.
    350  */
    351 uint16_t rr_rrsig_type_covered(rr_type* rr);
    352 
    353 struct namedb
    354 {
    355 	region_type*       region;
    356 	domain_table_type* domains;
    357 	struct radtree*    zonetree;
    358 	/* the timestamp on the ixfr.db file */
    359 	struct timeval	  diff_timestamp;
    360 	/* if diff_skip=1, diff_pos contains the nsd.diff place to continue */
    361 	uint8_t		  diff_skip;
    362 	off_t		  diff_pos;
    363 };
    364 
    365 /* Find the zone for the specified dname in DB. */
    366 zone_type *namedb_find_zone(namedb_type *db, const dname_type *dname);
    367 /*
    368  * Delete a domain name from the domain table.  Removes dname_info node.
    369  * Only deletes if usage is 0, has no rrsets and no children.  Checks parents
    370  * for deletion as well.  Adjusts numberlist(domain.number), and
    371  * wcard_child closest match.
    372  */
    373 void domain_table_deldomain(namedb_type* db, domain_type* domain);
    374 
    375 /** dbcreate.c */
    376 int print_rrs(FILE* out, struct zone* zone);
    377 
    378 /* dbaccess.c */
    379 int namedb_lookup (struct namedb* db,
    380 		   const dname_type* dname,
    381 		   domain_type     **closest_match,
    382 		   domain_type     **closest_encloser);
    383 /* pass number of children (to alloc in dirty array */
    384 struct namedb *namedb_open(struct nsd_options* opt);
    385 void namedb_close(struct namedb* db);
    386 /* free ixfr data stored for zones */
    387 void namedb_free_ixfr(struct namedb* db);
    388 void namedb_check_zonefiles(struct nsd* nsd, struct nsd_options* opt,
    389 	struct udb_base* taskudb, struct udb_ptr* last_task);
    390 void namedb_check_zonefile(struct nsd* nsd, struct udb_base* taskudb,
    391 	struct udb_ptr* last_task, struct zone_options* zo);
    392 /** zone one zonefile into memory and revert on parse error, write to udb */
    393 void namedb_read_zonefile(struct nsd* nsd, struct zone* zone,
    394 	struct udb_base* taskudb, struct udb_ptr* last_task);
    395 zone_type* namedb_zone_create(namedb_type* db, const dname_type* dname,
    396         struct zone_options* zopt);
    397 static inline zone_type*
    398 namedb_find_or_create_zone(namedb_type *db, const dname_type *dname,
    399 	       	struct zone_options* zopt)
    400 { zone_type* zone = namedb_find_zone(db, dname);
    401   return zone ? zone : namedb_zone_create(db, dname, zopt); }
    402 void namedb_zone_free_filenames(namedb_type* db, zone_type* zone);
    403 void namedb_zone_delete(namedb_type* db, zone_type* zone);
    404 void namedb_write_zonefile(struct nsd* nsd, struct zone_options* zopt);
    405 void namedb_write_zonefiles(struct nsd* nsd, struct nsd_options* options);
    406 int create_dirs(const char* path);
    407 int file_get_mtime(const char* file, struct timespec* mtime, int* nonexist);
    408 void allocate_domain_nsec3(domain_table_type *table, domain_type *result);
    409 
    410 static inline uint16_t
    411 rrset_rrtype(rrset_type* rrset)
    412 {
    413 	assert(rrset);
    414 	assert(rrset->rr_count > 0);
    415 	return rrset->rrs[0]->type;
    416 }
    417 
    418 static inline uint16_t
    419 rrset_rrclass(rrset_type* rrset)
    420 {
    421 	assert(rrset);
    422 	assert(rrset->rr_count > 0);
    423 	return rrset->rrs[0]->klass;
    424 }
    425 
    426 /*
    427  * zone_rr_iter can be used to iterate over all RRs in a given zone. the
    428  * SOA RRSET is guaranteed to be returned first.
    429  */
    430 typedef struct zone_rr_iter zone_rr_iter_type;
    431 
    432 struct zone_rr_iter {
    433 	zone_type *zone;
    434 	domain_type *domain;
    435 	rrset_type *rrset;
    436 	ssize_t index;
    437 };
    438 
    439 void zone_rr_iter_init(zone_rr_iter_type *iter, zone_type *zone);
    440 
    441 rr_type *zone_rr_iter_next(zone_rr_iter_type *iter);
    442 
    443 /** make the domain last in the numlist, changes numbers of domains */
    444 void numlist_make_last(domain_table_type* table, domain_type* domain);
    445 /** pop the biggest domain off the numlist */
    446 domain_type* numlist_pop_last(domain_table_type* table);
    447 
    448 #endif /* NAMEDB_H */
    449