xref: /dragonfly/contrib/ldns/ldns/dnssec_zone.h (revision fcf53d9b)
1 /*
2  * special zone file structures and functions for better dnssec handling
3  *
4  * A zone contains a SOA dnssec_zone_rrset, and an AVL tree of 'normal'
5  * dnssec_zone_rrsets, indexed by name and type
6  */
7 
8 #ifndef LDNS_DNSSEC_ZONE_H
9 #define LDNS_DNSSEC_ZONE_H
10 
11 #include <ldns/ldns.h>
12 #include <ldns/rbtree.h>
13 
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17 
18 /**
19  * Singly linked list of rrs
20  */
21 typedef struct ldns_struct_dnssec_rrs ldns_dnssec_rrs;
22 struct ldns_struct_dnssec_rrs
23 {
24 	ldns_rr *rr;
25 	ldns_dnssec_rrs *next;
26 };
27 
28 /**
29  * Singly linked list of RRsets
30  */
31 typedef struct ldns_struct_dnssec_rrsets ldns_dnssec_rrsets;
32 struct ldns_struct_dnssec_rrsets
33 {
34 	ldns_dnssec_rrs *rrs;
35 	ldns_rr_type type;
36 	ldns_dnssec_rrs *signatures;
37 	ldns_dnssec_rrsets *next;
38 };
39 
40 /**
41  * Structure containing all resource records for a domain name
42  * Including the derived NSEC3, if present
43  */
44 typedef struct ldns_struct_dnssec_name ldns_dnssec_name;
45 struct ldns_struct_dnssec_name
46 {
47 	/**
48 	 * pointer to a dname containing the name.
49 	 * Usually points to the owner name of the first RR of the first RRset
50 	 */
51 	ldns_rdf *name;
52 	/**
53 	 * Usually, the name is a pointer to the owner name of the first rr for
54 	 * this name, but sometimes there is no actual data to point to,
55 	 * for instance in
56 	 * names representing empty nonterminals. If so, set alloced to true to
57 	 * indicate that this data must also be freed when the name is freed
58 	 */
59 	bool name_alloced;
60 	/**
61 	 * The rrsets for this name
62 	 */
63 	ldns_dnssec_rrsets *rrsets;
64 	/**
65 	 * NSEC pointing to the next name (or NSEC3 pointing to the next NSEC3)
66 	 */
67 	ldns_rr *nsec;
68 	/**
69 	 * signatures for the NSEC record
70 	 */
71 	ldns_dnssec_rrs *nsec_signatures;
72 	/**
73 	 * Set to true if this name is glue
74 	 * (as marked by ldns_dnssec_zone_mark_glue())
75 	 */
76 	bool is_glue;
77 	/**
78 	 * pointer to store the hashed name (only used when in an NSEC3 zone
79 	 */
80 	ldns_rdf *hashed_name;
81 };
82 
83 /**
84  * Structure containing a dnssec zone
85  */
86 struct ldns_struct_dnssec_zone {
87 	/** points to the name containing the SOA RR */
88 	ldns_dnssec_name *soa;
89 	/** tree of ldns_dnssec_names */
90 	ldns_rbtree_t *names;
91 };
92 typedef struct ldns_struct_dnssec_zone ldns_dnssec_zone;
93 
94 /**
95  * Creates a new entry for 1 pointer to an rr and 1 pointer to the next rrs
96  * \return the allocated data
97  */
98 ldns_dnssec_rrs *ldns_dnssec_rrs_new();
99 
100 /**
101  * Frees the list of rrs, but *not* the individual ldns_rr records
102  * contained in the list
103  *
104  * \param[in] rrs the data structure to free
105  */
106 void ldns_dnssec_rrs_free(ldns_dnssec_rrs *rrs);
107 
108 /**
109  * Frees the list of rrs, and the individual ldns_rr records
110  * contained in the list
111  *
112  * \param[in] rrs the data structure to free
113  */
114 void ldns_dnssec_rrs_deep_free(ldns_dnssec_rrs *rrs);
115 
116 /**
117  * Adds an RR to the list of RRs. The list will remain ordered
118  *
119  * \param[in] rrs the list to add to
120  * \param[in] rr the RR to add
121  * \return LDNS_STATUS_OK on success
122  */
123 ldns_status ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr);
124 
125 /**
126  * Prints the given rrs to the file descriptor
127  *
128  * \param[in] out the file descriptor to print to
129  * \param[in] rrs the list of RRs to print
130  */
131 void ldns_dnssec_rrs_print(FILE *out, ldns_dnssec_rrs *rrs);
132 
133 /**
134  * Creates a new list (entry) of RRsets
135  * \return the newly allocated structure
136  */
137 ldns_dnssec_rrsets *ldns_dnssec_rrsets_new();
138 
139 /**
140  * Frees the list of rrsets and their rrs, but *not* the ldns_rr
141  * records in the sets
142  *
143  * \param[in] rrsets the data structure to free
144  */
145 void ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets);
146 
147 /**
148  * Frees the list of rrsets and their rrs, and the ldns_rr
149  * records in the sets
150  *
151  * \param[in] rrsets the data structure to free
152  */
153 void ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets *rrsets);
154 
155 /**
156  * Returns the rr type of the rrset (that is head of the given list)
157  *
158  * \param[in] rrsets the rrset to get the type of
159  * \return the rr type
160  */
161 ldns_rr_type ldns_dnssec_rrsets_type(ldns_dnssec_rrsets *rrsets);
162 
163 /**
164  * Sets the RR type of the rrset (that is head of the given list)
165  *
166  * \param[in] rrsets the rrset to set the type of
167  * \param[in] type the type to set
168  * \return LDNS_STATUS_OK on success
169  */
170 ldns_status ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets,
171 					   ldns_rr_type type);
172 
173 /**
174  * Add an ldns_rr to the corresponding RRset in the given list of RRsets.
175  * If it is not present, add it as a new RRset with 1 record.
176  *
177  * \param[in] rrsets the list of rrsets to add the RR to
178  * \param[in] rr the rr to add to the list of rrsets
179  * \return LDNS_STATUS_OK on success
180  */
181 ldns_status ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr);
182 
183 /**
184  * Print the given list of rrsets to the fiven file descriptor
185  *
186  * \param[in] out the file descriptor to print to
187  * \param[in] rrsets the list of RRsets to print
188  * \param[in] follow if set to false, only print the first RRset
189  */
190 void ldns_dnssec_rrsets_print(FILE *out,
191 						ldns_dnssec_rrsets *rrsets,
192 						bool follow);
193 
194 /**
195  * Create a new data structure for a dnssec name
196  * \return the allocated structure
197  */
198 ldns_dnssec_name *ldns_dnssec_name_new();
199 
200 /**
201  * Create a new data structure for a dnssec name for the given RR
202  *
203  * \param[in] rr the RR to derive properties from, and to add to the name
204  */
205 ldns_dnssec_name *ldns_dnssec_name_new_frm_rr(ldns_rr *rr);
206 
207 /**
208  * Frees the name structure and its rrs and rrsets.
209  * Individual ldns_rr records therein are not freed
210  *
211  * \param[in] name the structure to free
212  */
213 void ldns_dnssec_name_free(ldns_dnssec_name *name);
214 
215 /**
216  * Frees the name structure and its rrs and rrsets.
217  * Individual ldns_rr records contained in the name are also freed
218  *
219  * \param[in] name the structure to free
220  */
221 void ldns_dnssec_name_deep_free(ldns_dnssec_name *name);
222 
223 /**
224  * Returns the domain name of the given dnssec_name structure
225  *
226  * \param[in] name the dnssec name to get the domain name from
227  * \return the domain name
228  */
229 ldns_rdf *ldns_dnssec_name_name(ldns_dnssec_name *name);
230 
231 
232 /**
233  * Sets the domain name of the given dnssec_name structure
234  *
235  * \param[in] name the dnssec name to set the domain name of
236  * \param[in] dname the domain name to set it to. This data is *not* copied.
237  */
238 void ldns_dnssec_name_set_name(ldns_dnssec_name *name,
239 						 ldns_rdf *dname);
240 
241 /**
242  * Sets the NSEC(3) RR of the given dnssec_name structure
243  *
244  * \param[in] name the dnssec name to set the domain name of
245  * \param[in] nsec the nsec rr to set it to. This data is *not* copied.
246  */
247 void ldns_dnssec_name_set_nsec(ldns_dnssec_name *name, ldns_rr *nsec);
248 
249 /**
250  * Compares the domain names of the two arguments in their
251  * canonical ordening.
252  *
253  * \param[in] a The first dnssec_name to compare
254  * \param[in] b The second dnssec_name to compare
255  * \return -1 if the domain name of a comes before that of b in canonical
256  *            ordening, 1 if it is the other way around, and 0 if they are
257  *            equal
258  */
259 int ldns_dnssec_name_cmp(const void *a, const void *b);
260 
261 /**
262  * Inserts the given rr at the right place in the current dnssec_name
263  * No checking is done whether the name matches
264  *
265  * \param[in] name The ldns_dnssec_name to add the RR to
266  * \param[in] rr The RR to add
267  * \return LDNS_STATUS_OK on success, error code otherwise
268  */
269 ldns_status ldns_dnssec_name_add_rr(ldns_dnssec_name *name,
270 							 ldns_rr *rr);
271 
272 /**
273  * Find the RRset with the given type in within this name structure
274  *
275  * \param[in] name the name to find the RRset in
276  * \param[in] type the type of the RRset to find
277  * \return the RRset, or NULL if not present
278  */
279 ldns_dnssec_rrsets *ldns_dnssec_name_find_rrset(ldns_dnssec_name *name,
280 									   ldns_rr_type type);
281 
282 /**
283  * Find the RRset with the given name and type in the zone
284  *
285  * \param[in] zone the zone structure to find the RRset in
286  * \param[in] dname the domain name of the RRset to find
287  * \param[in] type the type of the RRset to find
288  * \return the RRset, or NULL if not present
289  */
290 ldns_dnssec_rrsets *ldns_dnssec_zone_find_rrset(ldns_dnssec_zone *zone,
291 									   ldns_rdf *dname,
292 									   ldns_rr_type type);
293 
294 /**
295  * Prints the RRs in the  dnssec name structure to the given
296  * file descriptor
297  *
298  * \param[in] out the file descriptor to print to
299  * \param[in] name the name structure to print the contents of
300  */
301 void ldns_dnssec_name_print(FILE *out, ldns_dnssec_name *name);
302 
303 /**
304  * Creates a new dnssec_zone structure
305  * \return the allocated structure
306  */
307 ldns_dnssec_zone *ldns_dnssec_zone_new();
308 
309 /**
310  * Frees the given zone structure, and its rbtree of dnssec_names
311  * Individual ldns_rr RRs within those names are *not* freed
312  * \param[in] *zone the zone to free
313  */
314 void ldns_dnssec_zone_free(ldns_dnssec_zone *zone);
315 
316 /**
317  * Frees the given zone structure, and its rbtree of dnssec_names
318  * Individual ldns_rr RRs within those names are also freed
319  * \param[in] *zone the zone to free
320  */
321 void ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone);
322 
323 /**
324  * Adds the given RR to the zone.
325  * It find whether there is a dnssec_name with that name present.
326  * If so, add it to that, if not create a new one.
327  * Special handling of NSEC and RRSIG provided
328  *
329  * \param[in] zone the zone to add the RR to
330  * \param[in] rr The RR to add
331  * \return LDNS_STATUS_OK on success, an error code otherwise
332  */
333 ldns_status ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone,
334 							 ldns_rr *rr);
335 
336 /**
337  * Prints the rbtree of ldns_dnssec_name structures to the file descriptor
338  *
339  * \param[in] out the file descriptor to print the names to
340  * \param[in] tree the tree of ldns_dnssec_name structures to print
341  * \param[in] print_soa if true, print SOA records, if false, skip them
342  */
343 void ldns_dnssec_zone_names_print(FILE *out, ldns_rbtree_t *tree, bool print_soa);
344 
345 /**
346  * Prints the complete zone to the given file descriptor
347  *
348  * \param[in] out the file descriptor to print to
349  * \param[in] zone the dnssec_zone to print
350  */
351 void ldns_dnssec_zone_print(FILE *out, ldns_dnssec_zone *zone);
352 
353 /**
354  * Adds explicit dnssec_name structures for the empty nonterminals
355  * in this zone. (this is needed for NSEC3 generation)
356  *
357  * \param[in] zone the zone to check for empty nonterminals
358  * return LDNS_STATUS_OK on success.
359  */
360 ldns_status ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone);
361 
362 #ifdef __cplusplus
363 }
364 #endif
365 
366 #endif
367