#ifndef NAMEDB_H
#define NAMEDB_H
#include <stdio.h>
#include "dname.h"
#include "dns.h"
#include "radtree.h"
#include "rbtree.h"
struct zone_options;
struct nsd_options;
struct udb_base;
struct udb_ptr;
struct nsd;
struct zone_ixfr;
typedef struct rrset rrset_type;
typedef struct rr rr_type;
typedef struct domain_table domain_table_type;
typedef struct domain domain_type;
typedef struct zone zone_type;
typedef struct namedb namedb_type;
struct domain_table
{
region_type* region;
#ifdef USE_RADIX_TREE
struct radtree *nametree;
#else
rbtree_type *names_to_domains;
#endif
domain_type* root;
domain_type *numlist_last;
#ifdef NSEC3
domain_type* prehash_list;
#endif
};
#ifdef NSEC3
typedef struct nsec3_hash_node nsec3_hash_node_type;
struct nsec3_hash_node {
uint8_t hash[NSEC3_HASH_LEN];
rbnode_type node;
} ATTR_PACKED;
typedef struct nsec3_hash_wc_node nsec3_hash_wc_node_type;
struct nsec3_hash_wc_node {
nsec3_hash_node_type hash;
nsec3_hash_node_type wc;
};
struct nsec3_domain_data {
domain_type* nsec3_cover;
domain_type* nsec3_wcard_child_cover;
domain_type* nsec3_ds_parent_cover;
domain_type* prehash_prev, *prehash_next;
rbnode_type nsec3_node;
nsec3_hash_wc_node_type* hash_wc;
nsec3_hash_node_type* ds_parent_hash;
unsigned nsec3_is_exact : 1;
unsigned nsec3_ds_parent_is_exact : 1;
} ATTR_PACKED;
#endif
struct domain
{
#ifdef USE_RADIX_TREE
struct radnode* rnode;
const dname_type* dname;
#else
rbnode_type node;
#endif
domain_type* parent;
domain_type* wildcard_child_closest_match;
rrset_type* rrsets;
#ifdef NSEC3
struct nsec3_domain_data* nsec3;
#endif
domain_type* numlist_prev, *numlist_next;
uint32_t number;
uint32_t usage;
unsigned is_existing : 1;
unsigned is_apex : 1;
} ATTR_PACKED;
struct zone
{
struct radnode *node;
domain_type* apex;
rrset_type* soa_rrset;
rrset_type* soa_nx_rrset;
rrset_type* ns_rrset;
#ifdef NSEC3
rr_type* nsec3_param;
domain_type* nsec3_last;
rbtree_type* nsec3tree;
rbtree_type* hashtree;
rbtree_type* wchashtree;
rbtree_type* dshashtree;
#endif
struct zone_options* opts;
struct zone_ixfr* ixfr;
char *filename;
struct {
size_t count;
char **paths;
} includes;
char* logstr;
struct timespec mtime;
unsigned zonestatid;
unsigned is_secure : 1;
unsigned is_ok : 1;
unsigned is_changed : 1;
unsigned is_updated : 1;
unsigned is_skipped : 1;
unsigned is_checked : 1;
unsigned is_bad : 1;
} ATTR_PACKED;
struct rr {
domain_type* owner;
uint32_t ttl;
uint16_t type;
uint16_t klass;
uint16_t rdlength;
uint8_t rdata[];
} ATTR_PACKED;
struct rrset
{
rrset_type* next;
zone_type* zone;
#ifndef PACKED_STRUCTS
rr_type** rrs;
#endif
uint16_t rr_count;
#ifdef PACKED_STRUCTS
rr_type* rrs[];
#endif
} ATTR_PACKED;
domain_table_type *domain_table_create(region_type *region);
int domain_table_search(domain_table_type* table,
const dname_type* dname,
domain_type **closest_match,
domain_type **closest_encloser);
static inline uint32_t
domain_table_count(domain_table_type* table)
{
#ifdef USE_RADIX_TREE
return table->nametree->count;
#else
return table->names_to_domains->count;
#endif
}
domain_type* domain_table_find(domain_table_type* table,
const dname_type* dname);
domain_type *domain_table_insert(domain_table_type *table,
const dname_type *dname);
void zone_add_domain_in_hash_tree(region_type* region, rbtree_type** tree,
int (*cmpf)(const void*, const void*), domain_type* domain,
rbnode_type* node);
void zone_del_domain_in_hash_tree(rbtree_type* tree, rbnode_type* node);
void hash_tree_delete(region_type* region, rbtree_type* tree);
void prehash_clear(domain_table_type* table);
void prehash_add(domain_table_type* table, domain_type* domain);
void prehash_del(domain_table_type* table, domain_type* domain);
int domain_is_prehash(domain_table_type* table, domain_type* domain);
void domain_add_rrset(domain_type* domain, rrset_type* rrset);
rrset_type* domain_find_rrset(domain_type* domain, zone_type* zone, uint16_t type);
rrset_type* domain_find_any_rrset(domain_type* domain, zone_type* zone);
rrset_type* domain_find_rrset_and_prev(domain_type* domain, zone_type* zone,
uint16_t type, rrset_type** prev);
zone_type* domain_find_zone(namedb_type* db, domain_type* domain);
zone_type* domain_find_parent_zone(namedb_type* db, zone_type* zone);
domain_type* domain_find_ns_rrsets(domain_type* domain, zone_type* zone, rrset_type **ns);
domain_type * find_dname_above(domain_type* domain, zone_type* zone);
int domain_is_glue(domain_type* domain, zone_type* zone);
rrset_type* domain_find_non_cname_rrset(domain_type* domain, zone_type* zone);
domain_type* domain_wildcard_child(domain_type* domain);
domain_type *domain_previous_existing_child(domain_type* domain);
int zone_is_secure(zone_type* zone);
static inline dname_type *
domain_dname(domain_type* domain)
{
#ifdef USE_RADIX_TREE
return (dname_type *) domain->dname;
#else
return (dname_type *) domain->node.key;
#endif
}
static inline const dname_type *
domain_dname_const(const domain_type* domain)
{
#ifdef USE_RADIX_TREE
return domain->dname;
#else
return (const dname_type *) domain->node.key;
#endif
}
static inline domain_type *
domain_previous(domain_type* domain)
{
#ifdef USE_RADIX_TREE
struct radnode* prev = radix_prev(domain->rnode);
return prev == NULL ? NULL : (domain_type*)prev->elem;
#else
rbnode_type *prev = rbtree_previous((rbnode_type *) domain);
return prev == RBTREE_NULL ? NULL : (domain_type *) prev;
#endif
}
static inline domain_type *
domain_next(domain_type* domain)
{
#ifdef USE_RADIX_TREE
struct radnode* next = radix_next(domain->rnode);
return next == NULL ? NULL : (domain_type*)next->elem;
#else
rbnode_type *next = rbtree_next((rbnode_type *) domain);
return next == RBTREE_NULL ? NULL : (domain_type *) next;
#endif
}
static inline int domain_is_subdomain(domain_type* d1, domain_type* d2)
{ return dname_is_subdomain(domain_dname(d1), domain_dname(d2)); }
static inline const char* domain_to_string(domain_type* domain)
{ return dname_to_string(domain_dname(domain), NULL); }
static inline const char* domain_to_string_buf(domain_type* domain, char *buf)
{ return dname_to_string_buf(domain_dname(domain), NULL, buf); }
uint16_t rr_rrsig_type_covered(rr_type* rr);
struct namedb
{
region_type* region;
domain_table_type* domains;
struct radtree* zonetree;
struct timeval diff_timestamp;
uint8_t diff_skip;
off_t diff_pos;
};
zone_type *namedb_find_zone(namedb_type *db, const dname_type *dname);
void domain_table_deldomain(namedb_type* db, domain_type* domain);
int print_rrs(FILE* out, struct zone* zone);
int namedb_lookup (struct namedb* db,
const dname_type* dname,
domain_type **closest_match,
domain_type **closest_encloser);
struct namedb *namedb_open(struct nsd_options* opt);
void namedb_close(struct namedb* db);
void namedb_free_ixfr(struct namedb* db);
void namedb_check_zonefiles(struct nsd* nsd, struct nsd_options* opt,
struct udb_base* taskudb, struct udb_ptr* last_task);
void namedb_check_zonefile(struct nsd* nsd, struct udb_base* taskudb,
struct udb_ptr* last_task, struct zone_options* zo);
void namedb_read_zonefile(struct nsd* nsd, struct zone* zone,
struct udb_base* taskudb, struct udb_ptr* last_task);
zone_type* namedb_zone_create(namedb_type* db, const dname_type* dname,
struct zone_options* zopt);
static inline zone_type*
namedb_find_or_create_zone(namedb_type *db, const dname_type *dname,
struct zone_options* zopt)
{ zone_type* zone = namedb_find_zone(db, dname);
return zone ? zone : namedb_zone_create(db, dname, zopt); }
void namedb_zone_free_filenames(namedb_type* db, zone_type* zone);
void namedb_zone_delete(namedb_type* db, zone_type* zone);
void namedb_write_zonefile(struct nsd* nsd, struct zone_options* zopt);
void namedb_write_zonefiles(struct nsd* nsd, struct nsd_options* options);
int create_dirs(const char* path);
int file_get_mtime(const char* file, struct timespec* mtime, int* nonexist);
void allocate_domain_nsec3(domain_table_type *table, domain_type *result);
static inline uint16_t
rrset_rrtype(rrset_type* rrset)
{
assert(rrset);
assert(rrset->rr_count > 0);
return rrset->rrs[0]->type;
}
static inline uint16_t
rrset_rrclass(rrset_type* rrset)
{
assert(rrset);
assert(rrset->rr_count > 0);
return rrset->rrs[0]->klass;
}
typedef struct zone_rr_iter zone_rr_iter_type;
struct zone_rr_iter {
zone_type *zone;
domain_type *domain;
rrset_type *rrset;
ssize_t index;
};
void zone_rr_iter_init(zone_rr_iter_type *iter, zone_type *zone);
rr_type *zone_rr_iter_next(zone_rr_iter_type *iter);
void numlist_make_last(domain_table_type* table, domain_type* domain);
domain_type* numlist_pop_last(domain_table_type* table);
#endif