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