xref: /openbsd/usr.sbin/nsd/namedb.h (revision 91f110e0)
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 	struct radtree *nametree;
41 	domain_type* root;
42 	/* ptr to biggest domain.number and last in list.
43 	 * the root is the lowest and first in the list. */
44 	domain_type *numlist_last;
45 #ifdef NSEC3
46 	/* the prehash list, start of the list */
47 	domain_type* prehash_list;
48 #endif /* NSEC3 */
49 };
50 
51 #ifdef NSEC3
52 struct nsec3_domain_data {
53 	/* (if nsec3 chain complete) always the covering nsec3 record */
54 	domain_type* nsec3_cover;
55 	/* the nsec3 that covers the wildcard child of this domain. */
56 	domain_type* nsec3_wcard_child_cover;
57 	/* for the DS case we must answer on the parent side of zone cut */
58 	domain_type* nsec3_ds_parent_cover;
59 	/* NSEC3 domains to prehash, prev and next on the list or cleared */
60 	domain_type* prehash_prev, *prehash_next;
61 	/* entry in the nsec3tree (for NSEC3s in the chain in use) */
62 	rbnode_t nsec3_node;
63 	/* entry in the hashtree (for precompiled domains) */
64 	rbnode_t hash_node;
65 	/* entry in the wchashtree (the wildcard precompile) */
66 	rbnode_t wchash_node;
67 	/* entry in the dshashtree (the parent ds precompile) */
68 	rbnode_t dshash_node;
69 
70 	/* nsec3 hash */
71 	uint8_t nsec3_hash[NSEC3_HASH_LEN];
72 	/* nsec3 hash of wildcard before this name */
73 	uint8_t nsec3_wc_hash[NSEC3_HASH_LEN];
74 	/* parent-side DS hash */
75 	uint8_t nsec3_ds_parent_hash[NSEC3_HASH_LEN];
76 	/* if the nsec3 has is available */
77 	unsigned  have_nsec3_hash : 1;
78 	unsigned  have_nsec3_wc_hash : 1;
79 	unsigned  have_nsec3_ds_parent_hash : 1;
80 	/* if the domain has an NSEC3 for it, use cover ptr to get it. */
81 	unsigned     nsec3_is_exact : 1;
82 	/* same but on parent side */
83 	unsigned     nsec3_ds_parent_is_exact : 1;
84 };
85 #endif /* NSEC3 */
86 
87 struct domain
88 {
89 	struct radnode* rnode;
90 	const dname_type* dname;
91 	domain_type* parent;
92 	domain_type* wildcard_child_closest_match;
93 	rrset_type* rrsets;
94 #ifdef NSEC3
95 	struct nsec3_domain_data* nsec3;
96 #endif
97 	/* double-linked list sorted by domain.number */
98 	domain_type* numlist_prev, *numlist_next;
99 	size_t     number; /* Unique domain name number.  */
100 	size_t     usage; /* number of ptrs to this from RRs(in rdata) and
101 			     from zone-apex pointers, also the root has one
102 			     more to make sure it cannot be deleted. */
103 
104 	/*
105 	 * This domain name exists (see wildcard clarification draft).
106 	 */
107 	unsigned     is_existing : 1;
108 	unsigned     is_apex : 1;
109 };
110 
111 struct zone
112 {
113 	struct radnode *node; /* this entry in zonetree */
114 	domain_type* apex;
115 	rrset_type*  soa_rrset;
116 	rrset_type*  soa_nx_rrset; /* see bug #103 */
117 	rrset_type*  ns_rrset;
118 #ifdef NSEC3
119 	rr_type* nsec3_param; /* NSEC3PARAM RR of chain in use or NULL */
120 	domain_type* nsec3_last; /* last domain with nsec3, wraps */
121 	/* in these trees, the root contains an elem ptr to the radtree* */
122 	rbtree_t* nsec3tree; /* tree with relevant NSEC3 domains */
123 	rbtree_t* hashtree; /* tree, hashed NSEC3precompiled domains */
124 	rbtree_t* wchashtree; /* tree, wildcard hashed domains */
125 	rbtree_t* dshashtree; /* tree, ds-parent-hash domains */
126 #endif
127 	struct zone_options* opts;
128 	unsigned     is_secure : 1; /* zone uses DNSSEC */
129 	unsigned     is_ok : 1; /* zone has not expired. */
130 	unsigned     is_changed : 1; /* zone was changed by AXFR */
131 };
132 
133 /* a RR in DNS */
134 struct rr {
135 	domain_type*     owner;
136 	rdata_atom_type* rdatas;
137 	uint32_t         ttl;
138 	uint16_t         type;
139 	uint16_t         klass;
140 	uint16_t         rdata_count;
141 };
142 
143 /*
144  * An RRset consists of at least one RR.  All RRs are from the same
145  * zone.
146  */
147 struct rrset
148 {
149 	rrset_type* next;
150 	zone_type*  zone;
151 	rr_type*    rrs;
152 	uint16_t    rr_count;
153 };
154 
155 /*
156  * The field used is based on the wireformat the atom is stored in.
157  * The allowed wireformats are defined by the rdata_wireformat_type
158  * enumeration.
159  */
160 union rdata_atom
161 {
162 	/* RDATA_WF_COMPRESSED_DNAME, RDATA_WF_UNCOMPRESSED_DNAME */
163 	domain_type* domain;
164 
165 	/* Default. */
166 	uint16_t*    data;
167 };
168 
169 /*
170  * Create a new domain_table containing only the root domain.
171  */
172 domain_table_type *domain_table_create(region_type *region);
173 
174 /*
175  * Search the domain table for a match and the closest encloser.
176  */
177 int domain_table_search(domain_table_type* table,
178 			const dname_type* dname,
179 			domain_type      **closest_match,
180 			domain_type      **closest_encloser);
181 
182 /*
183  * The number of domains stored in the table (minimum is one for the
184  * root domain).
185  */
186 static inline uint32_t
187 domain_table_count(domain_table_type* table)
188 {
189 	return table->nametree->count;
190 }
191 
192 /*
193  * Find the specified dname in the domain_table.  NULL is returned if
194  * there is no exact match.
195  */
196 domain_type* domain_table_find(domain_table_type* table,
197 			       const dname_type* dname);
198 
199 /*
200  * Insert a domain name in the domain table.  If the domain name is
201  * not yet present in the table it is copied and a new dname_info node
202  * is created (as well as for the missing parent domain names, if
203  * any).  Otherwise the domain_type that is already in the
204  * domain_table is returned.
205  */
206 domain_type *domain_table_insert(domain_table_type *table,
207 				 const dname_type  *dname);
208 
209 /* put domain into nsec3 hash space tree */
210 void zone_add_domain_in_hash_tree(region_type* region, rbtree_t** tree,
211 	int (*cmpf)(const void*, const void*), domain_type* domain,
212 	rbnode_t* node);
213 void zone_del_domain_in_hash_tree(rbtree_t* tree, rbnode_t* node);
214 void hash_tree_clear(rbtree_t* tree);
215 void hash_tree_delete(region_type* region, rbtree_t* tree);
216 void prehash_clear(domain_table_type* table);
217 void prehash_add(domain_table_type* table, domain_type* domain);
218 void prehash_del(domain_table_type* table, domain_type* domain);
219 int domain_is_prehash(domain_table_type* table, domain_type* domain);
220 
221 /*
222  * Iterate over all the domain names in the domain tree.
223  */
224 typedef int (*domain_table_iterator_type)(domain_type *node,
225 					   void *user_data);
226 
227 int domain_table_iterate(domain_table_type* table,
228 			  domain_table_iterator_type iterator,
229 			  void* user_data);
230 
231 /*
232  * Add an RRset to the specified domain.  Updates the is_existing flag
233  * as required.
234  */
235 void domain_add_rrset(domain_type* domain, rrset_type* rrset);
236 
237 rrset_type* domain_find_rrset(domain_type* domain, zone_type* zone, uint16_t type);
238 rrset_type* domain_find_any_rrset(domain_type* domain, zone_type* zone);
239 
240 zone_type* domain_find_zone(namedb_type* db, domain_type* domain);
241 zone_type* domain_find_parent_zone(zone_type* zone);
242 
243 domain_type* domain_find_ns_rrsets(domain_type* domain, zone_type* zone, rrset_type **ns);
244 
245 int domain_is_glue(domain_type* domain, zone_type* zone);
246 
247 rrset_type* domain_find_non_cname_rrset(domain_type* domain, zone_type* zone);
248 
249 domain_type* domain_wildcard_child(domain_type* domain);
250 
251 int zone_is_secure(zone_type* zone);
252 
253 static inline const dname_type *
254 domain_dname(domain_type* domain)
255 {
256 	return domain->dname;
257 }
258 
259 static inline domain_type *
260 domain_previous(domain_type* domain)
261 {
262 	struct radnode* prev = radix_prev(domain->rnode);
263 	return prev == NULL ? NULL : (domain_type*)prev->elem;
264 }
265 
266 static inline domain_type *
267 domain_next(domain_type* domain)
268 {
269 	struct radnode* next = radix_next(domain->rnode);
270 	return next == NULL ? NULL : (domain_type*)next->elem;
271 }
272 
273 /* easy comparison for subdomain, true if d1 is subdomain of d2. */
274 static inline int domain_is_subdomain(domain_type* d1, domain_type* d2)
275 { return dname_is_subdomain(domain_dname(d1), domain_dname(d2)); }
276 /* easy printout, to static buffer of dname_to_string, fqdn. */
277 static inline const char* domain_to_string(domain_type* domain)
278 { return dname_to_string(domain_dname(domain), NULL); }
279 
280 /*
281  * The type covered by the signature in the specified RRSIG RR.
282  */
283 uint16_t rr_rrsig_type_covered(rr_type* rr);
284 
285 struct namedb
286 {
287 	region_type*       region;
288 	domain_table_type* domains;
289 	struct radtree*    zonetree;
290 	struct udb_base*   udb;
291 	/* the timestamp on the ixfr.db file */
292 	struct timeval	  diff_timestamp;
293 	/* if diff_skip=1, diff_pos contains the nsd.diff place to continue */
294 	uint8_t		  diff_skip;
295 	off_t		  diff_pos;
296 };
297 
298 static inline int rdata_atom_is_domain(uint16_t type, size_t index);
299 static inline int rdata_atom_is_literal_domain(uint16_t type, size_t index);
300 
301 static inline domain_type *
302 rdata_atom_domain(rdata_atom_type atom)
303 {
304 	return atom.domain;
305 }
306 
307 static inline uint16_t
308 rdata_atom_size(rdata_atom_type atom)
309 {
310 	return *atom.data;
311 }
312 
313 static inline uint8_t *
314 rdata_atom_data(rdata_atom_type atom)
315 {
316 	return (uint8_t *) (atom.data + 1);
317 }
318 
319 
320 /* Find the zone for the specified dname in DB. */
321 zone_type *namedb_find_zone(namedb_type *db, const dname_type *dname);
322 /*
323  * Delete a domain name from the domain table.  Removes dname_info node.
324  * Only deletes if usage is 0, has no rrsets and no children.  Checks parents
325  * for deletion as well.  Adjusts numberlist(domain.number), and
326  * wcard_child closest match.
327  */
328 void domain_table_deldomain(namedb_type* db, domain_type* domain);
329 
330 
331 /** dbcreate.c */
332 int udb_write_rr(struct udb_base* udb, struct udb_ptr* z, rr_type* rr);
333 void udb_del_rr(struct udb_base* udb, struct udb_ptr* z, rr_type* rr);
334 int write_zone_to_udb(struct udb_base* udb, zone_type* zone, time_t mtime,
335 	const char* file_str);
336 /** marshal rdata into buffer, must be MAX_RDLENGTH in size */
337 size_t rr_marshal_rdata(rr_type* rr, uint8_t* rdata, size_t sz);
338 /* dbaccess.c */
339 int namedb_lookup (struct namedb* db,
340 		   const dname_type* dname,
341 		   domain_type     **closest_match,
342 		   domain_type     **closest_encloser);
343 /* pass number of children (to alloc in dirty array */
344 struct namedb *namedb_open(const char *filename, struct nsd_options* opt);
345 void namedb_close_udb(struct namedb* db);
346 void namedb_close(struct namedb* db);
347 void namedb_check_zonefiles(struct nsd* nsd, struct nsd_options* opt,
348 	struct udb_base* taskudb, struct udb_ptr* last_task);
349 void namedb_check_zonefile(struct nsd* nsd, struct udb_base* taskudb,
350 	struct udb_ptr* last_task, struct zone_options* zo);
351 /** zone one zonefile into memory and revert on parse error, write to udb */
352 void namedb_read_zonefile(struct nsd* nsd, struct zone* zone,
353 	struct udb_base* taskudb, struct udb_ptr* last_task);
354 void apex_rrset_checks(struct namedb* db, rrset_type* rrset,
355 	domain_type* domain);
356 zone_type* namedb_zone_create(namedb_type* db, const dname_type* dname,
357         struct zone_options* zopt);
358 void namedb_zone_delete(namedb_type* db, zone_type* zone);
359 void namedb_write_zonefile(struct nsd* nsd, struct zone_options* zopt);
360 void namedb_write_zonefiles(struct nsd* nsd, struct nsd_options* options);
361 int create_dirs(const char* path);
362 void allocate_domain_nsec3(domain_table_type *table, domain_type *result);
363 
364 static inline int
365 rdata_atom_is_domain(uint16_t type, size_t index)
366 {
367 	const rrtype_descriptor_type *descriptor
368 		= rrtype_descriptor_by_type(type);
369 	return (index < descriptor->maximum
370 		&& (descriptor->wireformat[index] == RDATA_WF_COMPRESSED_DNAME
371 		    || descriptor->wireformat[index] == RDATA_WF_UNCOMPRESSED_DNAME));
372 }
373 
374 static inline int
375 rdata_atom_is_literal_domain(uint16_t type, size_t index)
376 {
377 	const rrtype_descriptor_type *descriptor
378 		= rrtype_descriptor_by_type(type);
379 	return (index < descriptor->maximum
380 		&& (descriptor->wireformat[index] == RDATA_WF_LITERAL_DNAME));
381 }
382 
383 static inline rdata_wireformat_type
384 rdata_atom_wireformat_type(uint16_t type, size_t index)
385 {
386 	const rrtype_descriptor_type *descriptor
387 		= rrtype_descriptor_by_type(type);
388 	assert(index < descriptor->maximum);
389 	return (rdata_wireformat_type) descriptor->wireformat[index];
390 }
391 
392 static inline uint16_t
393 rrset_rrtype(rrset_type* rrset)
394 {
395 	assert(rrset);
396 	assert(rrset->rr_count > 0);
397 	return rrset->rrs[0].type;
398 }
399 
400 static inline uint16_t
401 rrset_rrclass(rrset_type* rrset)
402 {
403 	assert(rrset);
404 	assert(rrset->rr_count > 0);
405 	return rrset->rrs[0].klass;
406 }
407 
408 #endif
409