xref: /openbsd/usr.sbin/nsd/namedb.h (revision bf87c3c0)
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 union rdata_atom rdata_atom_type;
27 typedef struct rrset rrset_type;
28 typedef struct rr rr_type;
29 
30 /*
31  * A domain name table supporting fast insert and search operations.
32  */
33 typedef struct domain_table domain_table_type;
34 typedef struct domain domain_type;
35 typedef struct zone zone_type;
36 typedef struct namedb namedb_type;
37 
38 struct 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
57 typedef struct nsec3_hash_node nsec3_hash_node_type;
58 struct 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 
65 typedef struct nsec3_hash_wc_node nsec3_hash_wc_node_type;
66 struct nsec3_hash_wc_node {
67 	nsec3_hash_node_type hash;
68 	nsec3_hash_node_type wc;
69 };
70 
71 struct 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 
96 struct 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 
124 struct 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 */
156 struct 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  */
169 struct 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  */
182 union 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  */
194 domain_table_type *domain_table_create(region_type *region);
195 
196 /*
197  * Search the domain table for a match and the closest encloser.
198  */
199 int 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  */
208 static inline uint32_t
domain_table_count(domain_table_type * table)209 domain_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  */
222 domain_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  */
232 domain_type *domain_table_insert(domain_table_type *table,
233 				 const dname_type  *dname);
234 
235 /* put domain into nsec3 hash space tree */
236 void 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);
239 void zone_del_domain_in_hash_tree(rbtree_type* tree, rbnode_type* node);
240 void hash_tree_delete(region_type* region, rbtree_type* tree);
241 void prehash_clear(domain_table_type* table);
242 void prehash_add(domain_table_type* table, domain_type* domain);
243 void prehash_del(domain_table_type* table, domain_type* domain);
244 int 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  */
250 void domain_add_rrset(domain_type* domain, rrset_type* rrset);
251 
252 rrset_type* domain_find_rrset(domain_type* domain, zone_type* zone, uint16_t type);
253 rrset_type* domain_find_any_rrset(domain_type* domain, zone_type* zone);
254 
255 zone_type* domain_find_zone(namedb_type* db, domain_type* domain);
256 zone_type* domain_find_parent_zone(namedb_type* db, zone_type* zone);
257 
258 domain_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 */
260 domain_type * find_dname_above(domain_type* domain, zone_type* zone);
261 
262 int domain_is_glue(domain_type* domain, zone_type* zone);
263 
264 rrset_type* domain_find_non_cname_rrset(domain_type* domain, zone_type* zone);
265 
266 domain_type* domain_wildcard_child(domain_type* domain);
267 domain_type *domain_previous_existing_child(domain_type* domain);
268 
269 int zone_is_secure(zone_type* zone);
270 
271 static inline dname_type *
domain_dname(domain_type * domain)272 domain_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 
281 static inline const dname_type *
domain_dname_const(const domain_type * domain)282 domain_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 
291 static inline domain_type *
domain_previous(domain_type * domain)292 domain_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 
303 static inline domain_type *
domain_next(domain_type * domain)304 domain_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. */
domain_is_subdomain(domain_type * d1,domain_type * d2)316 static 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. */
domain_to_string(domain_type * domain)319 static 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. */
domain_to_string_buf(domain_type * domain,char * buf)322 static 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  */
329 uint16_t rr_rrsig_type_covered(rr_type* rr);
330 
331 struct 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 
343 static inline int rdata_atom_is_domain(uint16_t type, size_t index);
344 static inline int rdata_atom_is_literal_domain(uint16_t type, size_t index);
345 
346 static inline domain_type *
rdata_atom_domain(rdata_atom_type atom)347 rdata_atom_domain(rdata_atom_type atom)
348 {
349 	return atom.domain;
350 }
351 
352 static inline uint16_t
rdata_atom_size(rdata_atom_type atom)353 rdata_atom_size(rdata_atom_type atom)
354 {
355 	return *atom.data;
356 }
357 
358 static inline uint8_t *
rdata_atom_data(rdata_atom_type atom)359 rdata_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. */
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 /** marshal rdata into buffer, must be MAX_RDLENGTH in size */
378 size_t rr_marshal_rdata(rr_type* rr, uint8_t* rdata, size_t sz);
379 /* dbaccess.c */
380 int 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 */
385 struct namedb *namedb_open(struct nsd_options* opt);
386 void namedb_close(struct namedb* db);
387 /* free ixfr data stored for zones */
388 void namedb_free_ixfr(struct namedb* db);
389 void namedb_check_zonefiles(struct nsd* nsd, struct nsd_options* opt,
390 	struct udb_base* taskudb, struct udb_ptr* last_task);
391 void 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 */
394 void namedb_read_zonefile(struct nsd* nsd, struct zone* zone,
395 	struct udb_base* taskudb, struct udb_ptr* last_task);
396 zone_type* namedb_zone_create(namedb_type* db, const dname_type* dname,
397         struct zone_options* zopt);
398 static inline zone_type*
namedb_find_or_create_zone(namedb_type * db,const dname_type * dname,struct zone_options * zopt)399 namedb_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); }
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 int
rdata_atom_is_domain(uint16_t type,size_t index)411 rdata_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 
420 static inline int
rdata_atom_is_literal_domain(uint16_t type,size_t index)421 rdata_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 
429 static inline rdata_wireformat_type
rdata_atom_wireformat_type(uint16_t type,size_t index)430 rdata_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 
438 static inline uint16_t
rrset_rrtype(rrset_type * rrset)439 rrset_rrtype(rrset_type* rrset)
440 {
441 	assert(rrset);
442 	assert(rrset->rr_count > 0);
443 	return rrset->rrs[0].type;
444 }
445 
446 static inline uint16_t
rrset_rrclass(rrset_type * rrset)447 rrset_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  */
458 typedef struct zone_rr_iter zone_rr_iter_type;
459 
460 struct zone_rr_iter {
461 	zone_type *zone;
462 	domain_type *domain;
463 	rrset_type *rrset;
464 	ssize_t index;
465 };
466 
467 void zone_rr_iter_init(zone_rr_iter_type *iter, zone_type *zone);
468 
469 rr_type *zone_rr_iter_next(zone_rr_iter_type *iter);
470 
471 #endif /* NAMEDB_H */
472