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 #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 	char*        filename; /* set if read from file, which file */
141 	char*        logstr; /* set for zone xfer, the log string */
142 	struct timespec mtime; /* time of last modification */
143 	unsigned     zonestatid; /* array index for zone stats */
144 	unsigned     is_secure : 1; /* zone uses DNSSEC */
145 	unsigned     is_ok : 1; /* zone has not expired. */
146 	unsigned     is_changed : 1; /* zone was changed by AXFR */
147 } ATTR_PACKED;
148 
149 /* a RR in DNS */
150 struct rr {
151 	domain_type*     owner;
152 	rdata_atom_type* rdatas;
153 	uint32_t         ttl;
154 	uint16_t         type;
155 	uint16_t         klass;
156 	uint16_t         rdata_count;
157 } ATTR_PACKED;
158 
159 /*
160  * An RRset consists of at least one RR.  All RRs are from the same
161  * zone.
162  */
163 struct rrset
164 {
165 	rrset_type* next;
166 	zone_type*  zone;
167 	rr_type*    rrs;
168 	uint16_t    rr_count;
169 } ATTR_PACKED;
170 
171 /*
172  * The field used is based on the wireformat the atom is stored in.
173  * The allowed wireformats are defined by the rdata_wireformat_type
174  * enumeration.
175  */
176 union rdata_atom
177 {
178 	/* RDATA_WF_COMPRESSED_DNAME, RDATA_WF_UNCOMPRESSED_DNAME */
179 	domain_type* domain;
180 
181 	/* Default. */
182 	uint16_t*    data;
183 };
184 
185 /*
186  * Create a new domain_table containing only the root domain.
187  */
188 domain_table_type *domain_table_create(region_type *region);
189 
190 /*
191  * Search the domain table for a match and the closest encloser.
192  */
193 int domain_table_search(domain_table_type* table,
194 			const dname_type* dname,
195 			domain_type      **closest_match,
196 			domain_type      **closest_encloser);
197 
198 /*
199  * The number of domains stored in the table (minimum is one for the
200  * root domain).
201  */
202 static inline uint32_t
domain_table_count(domain_table_type * table)203 domain_table_count(domain_table_type* table)
204 {
205 #ifdef USE_RADIX_TREE
206 	return table->nametree->count;
207 #else
208 	return table->names_to_domains->count;
209 #endif
210 }
211 
212 /*
213  * Find the specified dname in the domain_table.  NULL is returned if
214  * there is no exact match.
215  */
216 domain_type* domain_table_find(domain_table_type* table,
217 			       const dname_type* dname);
218 
219 /*
220  * Insert a domain name in the domain table.  If the domain name is
221  * not yet present in the table it is copied and a new dname_info node
222  * is created (as well as for the missing parent domain names, if
223  * any).  Otherwise the domain_type that is already in the
224  * domain_table is returned.
225  */
226 domain_type *domain_table_insert(domain_table_type *table,
227 				 const dname_type  *dname);
228 
229 /* put domain into nsec3 hash space tree */
230 void zone_add_domain_in_hash_tree(region_type* region, rbtree_type** tree,
231 	int (*cmpf)(const void*, const void*), domain_type* domain,
232 	rbnode_type* node);
233 void zone_del_domain_in_hash_tree(rbtree_type* tree, rbnode_type* node);
234 void hash_tree_delete(region_type* region, rbtree_type* tree);
235 void prehash_clear(domain_table_type* table);
236 void prehash_add(domain_table_type* table, domain_type* domain);
237 void prehash_del(domain_table_type* table, domain_type* domain);
238 int domain_is_prehash(domain_table_type* table, domain_type* domain);
239 
240 /*
241  * Add an RRset to the specified domain.  Updates the is_existing flag
242  * as required.
243  */
244 void domain_add_rrset(domain_type* domain, rrset_type* rrset);
245 
246 rrset_type* domain_find_rrset(domain_type* domain, zone_type* zone, uint16_t type);
247 rrset_type* domain_find_any_rrset(domain_type* domain, zone_type* zone);
248 
249 zone_type* domain_find_zone(namedb_type* db, domain_type* domain);
250 zone_type* domain_find_parent_zone(namedb_type* db, zone_type* zone);
251 
252 domain_type* domain_find_ns_rrsets(domain_type* domain, zone_type* zone, rrset_type **ns);
253 /* find DNAME rrset in domain->parent or higher and return that domain */
254 domain_type * find_dname_above(domain_type* domain, zone_type* zone);
255 
256 int domain_is_glue(domain_type* domain, zone_type* zone);
257 
258 rrset_type* domain_find_non_cname_rrset(domain_type* domain, zone_type* zone);
259 
260 domain_type* domain_wildcard_child(domain_type* domain);
261 domain_type *domain_previous_existing_child(domain_type* domain);
262 
263 int zone_is_secure(zone_type* zone);
264 
265 static inline dname_type *
domain_dname(domain_type * domain)266 domain_dname(domain_type* domain)
267 {
268 #ifdef USE_RADIX_TREE
269 	return (dname_type *) domain->dname;
270 #else
271 	return (dname_type *) domain->node.key;
272 #endif
273 }
274 
275 static inline const dname_type *
domain_dname_const(const domain_type * domain)276 domain_dname_const(const domain_type* domain)
277 {
278 #ifdef USE_RADIX_TREE
279 	return domain->dname;
280 #else
281 	return (const dname_type *) domain->node.key;
282 #endif
283 }
284 
285 static inline domain_type *
domain_previous(domain_type * domain)286 domain_previous(domain_type* domain)
287 {
288 #ifdef USE_RADIX_TREE
289 	struct radnode* prev = radix_prev(domain->rnode);
290 	return prev == NULL ? NULL : (domain_type*)prev->elem;
291 #else
292 	rbnode_type *prev = rbtree_previous((rbnode_type *) domain);
293 	return prev == RBTREE_NULL ? NULL : (domain_type *) prev;
294 #endif
295 }
296 
297 static inline domain_type *
domain_next(domain_type * domain)298 domain_next(domain_type* domain)
299 {
300 #ifdef USE_RADIX_TREE
301 	struct radnode* next = radix_next(domain->rnode);
302 	return next == NULL ? NULL : (domain_type*)next->elem;
303 #else
304 	rbnode_type *next = rbtree_next((rbnode_type *) domain);
305 	return next == RBTREE_NULL ? NULL : (domain_type *) next;
306 #endif
307 }
308 
309 /* easy comparison for subdomain, true if d1 is subdomain of d2. */
domain_is_subdomain(domain_type * d1,domain_type * d2)310 static inline int domain_is_subdomain(domain_type* d1, domain_type* d2)
311 { return dname_is_subdomain(domain_dname(d1), domain_dname(d2)); }
312 /* easy printout, to static buffer of dname_to_string, fqdn. */
domain_to_string(domain_type * domain)313 static inline const char* domain_to_string(domain_type* domain)
314 { return dname_to_string(domain_dname(domain), NULL); }
315 
316 /*
317  * The type covered by the signature in the specified RRSIG RR.
318  */
319 uint16_t rr_rrsig_type_covered(rr_type* rr);
320 
321 struct namedb
322 {
323 	region_type*       region;
324 	domain_table_type* domains;
325 	struct radtree*    zonetree;
326 	struct udb_base*   udb;
327 	/* the timestamp on the ixfr.db file */
328 	struct timeval	  diff_timestamp;
329 	/* if diff_skip=1, diff_pos contains the nsd.diff place to continue */
330 	uint8_t		  diff_skip;
331 	off_t		  diff_pos;
332 };
333 
334 static inline int rdata_atom_is_domain(uint16_t type, size_t index);
335 static inline int rdata_atom_is_literal_domain(uint16_t type, size_t index);
336 
337 static inline domain_type *
rdata_atom_domain(rdata_atom_type atom)338 rdata_atom_domain(rdata_atom_type atom)
339 {
340 	return atom.domain;
341 }
342 
343 static inline uint16_t
rdata_atom_size(rdata_atom_type atom)344 rdata_atom_size(rdata_atom_type atom)
345 {
346 	return *atom.data;
347 }
348 
349 static inline uint8_t *
rdata_atom_data(rdata_atom_type atom)350 rdata_atom_data(rdata_atom_type atom)
351 {
352 	return (uint8_t *) (atom.data + 1);
353 }
354 
355 
356 /* Find the zone for the specified dname in DB. */
357 zone_type *namedb_find_zone(namedb_type *db, const dname_type *dname);
358 /*
359  * Delete a domain name from the domain table.  Removes dname_info node.
360  * Only deletes if usage is 0, has no rrsets and no children.  Checks parents
361  * for deletion as well.  Adjusts numberlist(domain.number), and
362  * wcard_child closest match.
363  */
364 void domain_table_deldomain(namedb_type* db, domain_type* domain);
365 
366 
367 /** dbcreate.c */
368 int udb_write_rr(struct udb_base* udb, struct udb_ptr* z, rr_type* rr);
369 void udb_del_rr(struct udb_base* udb, struct udb_ptr* z, rr_type* rr);
370 int write_zone_to_udb(struct udb_base* udb, zone_type* zone,
371 	struct timespec* mtime, const char* file_str);
372 int print_rrs(FILE* out, struct zone* zone);
373 /** marshal rdata into buffer, must be MAX_RDLENGTH in size */
374 size_t rr_marshal_rdata(rr_type* rr, uint8_t* rdata, size_t sz);
375 /* dbaccess.c */
376 int namedb_lookup (struct namedb* db,
377 		   const dname_type* dname,
378 		   domain_type     **closest_match,
379 		   domain_type     **closest_encloser);
380 /* pass number of children (to alloc in dirty array */
381 struct namedb *namedb_open(const char *filename, struct nsd_options* opt);
382 void namedb_close_udb(struct namedb* db);
383 void namedb_close(struct namedb* db);
384 void namedb_check_zonefiles(struct nsd* nsd, struct nsd_options* opt,
385 	struct udb_base* taskudb, struct udb_ptr* last_task);
386 void namedb_check_zonefile(struct nsd* nsd, struct udb_base* taskudb,
387 	struct udb_ptr* last_task, struct zone_options* zo);
388 /** zone one zonefile into memory and revert on parse error, write to udb */
389 void namedb_read_zonefile(struct nsd* nsd, struct zone* zone,
390 	struct udb_base* taskudb, struct udb_ptr* last_task);
391 void apex_rrset_checks(struct namedb* db, rrset_type* rrset,
392 	domain_type* domain);
393 zone_type* namedb_zone_create(namedb_type* db, const dname_type* dname,
394         struct zone_options* zopt);
395 void namedb_zone_delete(namedb_type* db, zone_type* zone);
396 void namedb_write_zonefile(struct nsd* nsd, struct zone_options* zopt);
397 void namedb_write_zonefiles(struct nsd* nsd, struct nsd_options* options);
398 int create_dirs(const char* path);
399 int file_get_mtime(const char* file, struct timespec* mtime, int* nonexist);
400 void allocate_domain_nsec3(domain_table_type *table, domain_type *result);
401 
402 static inline int
rdata_atom_is_domain(uint16_t type,size_t index)403 rdata_atom_is_domain(uint16_t type, size_t index)
404 {
405 	const rrtype_descriptor_type *descriptor
406 		= rrtype_descriptor_by_type(type);
407 	return (index < descriptor->maximum
408 		&& (descriptor->wireformat[index] == RDATA_WF_COMPRESSED_DNAME
409 		    || descriptor->wireformat[index] == RDATA_WF_UNCOMPRESSED_DNAME));
410 }
411 
412 static inline int
rdata_atom_is_literal_domain(uint16_t type,size_t index)413 rdata_atom_is_literal_domain(uint16_t type, size_t index)
414 {
415 	const rrtype_descriptor_type *descriptor
416 		= rrtype_descriptor_by_type(type);
417 	return (index < descriptor->maximum
418 		&& (descriptor->wireformat[index] == RDATA_WF_LITERAL_DNAME));
419 }
420 
421 static inline rdata_wireformat_type
rdata_atom_wireformat_type(uint16_t type,size_t index)422 rdata_atom_wireformat_type(uint16_t type, size_t index)
423 {
424 	const rrtype_descriptor_type *descriptor
425 		= rrtype_descriptor_by_type(type);
426 	assert(index < descriptor->maximum);
427 	return (rdata_wireformat_type) descriptor->wireformat[index];
428 }
429 
430 static inline uint16_t
rrset_rrtype(rrset_type * rrset)431 rrset_rrtype(rrset_type* rrset)
432 {
433 	assert(rrset);
434 	assert(rrset->rr_count > 0);
435 	return rrset->rrs[0].type;
436 }
437 
438 static inline uint16_t
rrset_rrclass(rrset_type * rrset)439 rrset_rrclass(rrset_type* rrset)
440 {
441 	assert(rrset);
442 	assert(rrset->rr_count > 0);
443 	return rrset->rrs[0].klass;
444 }
445 
446 /*
447  * zone_rr_iter can be used to iterate over all RRs in a given zone. the
448  * SOA RRSET is guaranteed to be returned first.
449  */
450 typedef struct zone_rr_iter zone_rr_iter_type;
451 
452 struct zone_rr_iter {
453 	zone_type *zone;
454 	domain_type *domain;
455 	rrset_type *rrset;
456 	ssize_t index;
457 };
458 
459 void zone_rr_iter_init(zone_rr_iter_type *iter, zone_type *zone);
460 
461 rr_type *zone_rr_iter_next(zone_rr_iter_type *iter);
462 
463 #endif /* _NAMEDB_H_ */
464