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