OpenDNSSEC-signer 2.1.13
domain.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2009 NLNet Labs. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
19 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
21 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
23 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 */
26
32#include "config.h"
33#include "log.h"
34#include "signer/backup.h"
35#include "signer/denial.h"
36#include "signer/domain.h"
37#include "signer/ixfr.h"
38#include "signer/zone.h"
39
40static const char* dname_str = "domain";
41
42
47void
48log_dname(ldns_rdf *rdf, const char* pre, int level)
49{
50 char* str = NULL;
51 if (ods_log_get_level() < level) {
52 return;
53 }
54 str = ldns_rdf2str(rdf);
55 if (!str) {
56 return;
57 }
58 if (level == LOG_EMERG) {
59 ods_fatal_exit("[%s] %s: %s", dname_str, pre?pre:"", str);
60 } else if (level == LOG_ALERT) {
61 ods_log_alert("[%s] %s: %s", dname_str, pre?pre:"", str);
62 } else if (level == LOG_CRIT) {
63 ods_log_crit("[%s] %s: %s", dname_str, pre?pre:"", str);
64 } else if (level == LOG_ERR) {
65 ods_log_error("[%s] %s: %s", dname_str, pre?pre:"", str);
66 } else if (level == LOG_WARNING) {
67 ods_log_warning("[%s] %s: %s", dname_str, pre?pre:"", str);
68 } else if (level == LOG_NOTICE) {
69 ods_log_info("[%s] %s: %s", dname_str, pre?pre:"", str);
70 } else if (level == LOG_INFO) {
71 ods_log_verbose("[%s] %s: %s", dname_str, pre?pre:"", str);
72 } else if (level == LOG_DEBUG) {
73 ods_log_debug("[%s] %s: %s", dname_str, pre?pre:"", str);
74 } else if (level == LOG_DEEEBUG) {
75 ods_log_deeebug("[%s] %s: %s", dname_str, pre?pre:"", str);
76 } else {
77 ods_log_deeebug("[%s] %s: %s", dname_str, pre?pre:"", str);
78 }
79 free((void*)str);
80}
81
82
88domain_create(zone_type* zone, ldns_rdf* dname)
89{
90 domain_type* domain = NULL;
91 if (!dname || !zone) {
92 return NULL;
93 }
94 CHECKALLOC(domain = (domain_type*) malloc(sizeof(domain_type)));
95 domain->dname = ldns_rdf_clone(dname);
96 if (!domain->dname) {
97 ods_log_error("[%s] unable to create domain: ldns_rdf_clone() "
98 "failed", dname_str);
99 free(domain);
100 return NULL;
101 }
102 domain->zone = zone;
103 domain->denial = NULL; /* no reference yet */
104 domain->node = NULL; /* not in db yet */
105 domain->rrsets = NULL;
106 domain->parent = NULL;
107 domain->is_apex = 0;
108 domain->is_new = 0;
109 return domain;
110}
111
112
117size_t
119{
120 rrset_type* rrset = NULL;
121 size_t count = 0;
122 if (!domain) {
123 return 0;
124 }
125 rrset = domain->rrsets;
126 while (rrset) {
127 if (rrset_count_rr_is_added(rrset)) {
128 count++;
129 }
130 rrset = rrset->next;
131 }
132 return count;
133}
134
135
141domain_lookup_rrset(domain_type* domain, ldns_rr_type rrtype)
142{
143 rrset_type* rrset = NULL;
144 if (!domain || !domain->rrsets || !rrtype) {
145 return NULL;
146 }
147 rrset = domain->rrsets;
148 while (rrset && rrset->rrtype != rrtype) {
149 rrset = rrset->next;
150 }
151 return rrset;
152}
153
154
159void
161{
162 rrset_type** p = NULL;
163 denial_type* denial = NULL;
164 ods_log_assert(domain);
165 ods_log_assert(rrset);
166 if (!domain->rrsets) {
167 domain->rrsets = rrset;
168 } else {
169 p = &domain->rrsets;
170 while(*p) {
171 p = &((*p)->next);
172 }
173 *p = rrset;
174 rrset->next = NULL;
175 }
176 log_rrset(domain->dname, rrset->rrtype, "+RRSET", LOG_DEEEBUG);
177 rrset->domain = (void*) domain;
178 if (domain->denial) {
179 denial = (denial_type*) domain->denial;
180 denial->bitmap_changed = 1;
181 }
182}
183
184
189void
190domain_diff(domain_type* domain, unsigned is_ixfr, unsigned more_coming)
191{
192 denial_type* denial = NULL;
193 rrset_type* rrset = NULL;
194 rrset_type* prev_rrset = NULL;
195
196 if (!domain) {
197 return;
198 }
199 rrset = domain->rrsets;
200 while (rrset) {
201 if (rrset->rrtype == LDNS_RR_TYPE_NSEC3PARAMS ||
202 rrset->rrtype == LDNS_RR_TYPE_DNSKEY) {
203 /* always do full diff on NSEC3PARAMS | DNSKEY RRset */
204 rrset_diff(rrset, 0, more_coming);
205 } else {
206 rrset_diff(rrset, is_ixfr, more_coming);
207 }
208 if (rrset->rr_count <= 0) {
209 /* delete entire rrset */
210 if (!prev_rrset) {
211 domain->rrsets = rrset->next;
212 } else {
213 prev_rrset->next = rrset->next;
214 }
215 rrset->next = NULL;
216 log_rrset(domain->dname, rrset->rrtype, "-RRSET", LOG_DEEEBUG);
217 rrset_cleanup(rrset);
218 if (!prev_rrset) {
219 rrset = domain->rrsets;
220 } else {
221 rrset = prev_rrset->next;
222 }
223 if (domain->denial) {
224 denial = (denial_type*) domain->denial;
225 denial->bitmap_changed = 1;
226 }
227 } else {
228 /* just go to next rrset */
229 prev_rrset = rrset;
230 rrset = rrset->next;
231 }
232 }
233}
234
235
240void
241domain_rollback(domain_type* domain, int keepsc)
242{
243 denial_type* denial = NULL;
244 rrset_type* rrset = NULL;
245 rrset_type* prev_rrset = NULL;
246 int del_rrset = 0;
247 uint16_t i = 0;
248 if (!domain) {
249 return;
250 }
251 rrset = domain->rrsets;
252 while (rrset) {
253 if (keepsc) {
254 /* skip rollback for NSEC3PARAM and DNSKEY RRset */
255 if (rrset->rrtype == LDNS_RR_TYPE_NSEC3PARAMS ||
256 rrset->rrtype == LDNS_RR_TYPE_DNSKEY) {
257 prev_rrset = rrset;
258 rrset = rrset->next;
259 continue;
260 }
261 }
262 /* walk rrs */
263 for (i=0; i < rrset->rr_count; i++) {
264 rrset->rrs[i].is_added = 0;
265 rrset->rrs[i].is_removed = 0;
266 if (!rrset->rrs[i].exists) {
267 /* can we delete the RRset? */
268 if(rrset->rr_count == 1) {
269 del_rrset = 1;
270 }
271 rrset_del_rr(rrset, i);
272 i--;
273 }
274 }
275 /* next rrset */
276 if (del_rrset) {
277 /* delete entire rrset */
278 if (!prev_rrset) {
279 domain->rrsets = rrset->next;
280 } else {
281 prev_rrset->next = rrset->next;
282 }
283 rrset->next = NULL;
284 log_rrset(domain->dname, rrset->rrtype, "-RRSET", LOG_DEEEBUG);
285 rrset_cleanup(rrset);
286 if (!prev_rrset) {
287 rrset = domain->rrsets;
288 } else {
289 rrset = prev_rrset->next;
290 }
291 if (domain->denial) {
292 denial = (denial_type*) domain->denial;
293 denial->bitmap_changed = 0;
294 }
295 del_rrset = 0;
296 } else {
297 /* just go to next rrset */
298 prev_rrset = rrset;
299 rrset = rrset->next;
300 }
301 }
302}
303
304
309int
311{
312 ldns_rbnode_t* n = LDNS_RBTREE_NULL;
313 domain_type* d = NULL;
314
315 ods_log_assert(domain);
316 if (domain->rrsets) {
317 return 0; /* not an empty non-terminal */
318 }
319 n = ldns_rbtree_next(domain->node);
320 while (n && n != LDNS_RBTREE_NULL) {
321 d = (domain_type*) n->data;
322 if (!ldns_dname_is_subdomain(d->dname, domain->dname)) {
323 break;
324 }
325 if (d->rrsets) {
326 if (domain_is_delegpt(d) != LDNS_RR_TYPE_NS &&
327 domain_is_occluded(d) == LDNS_RR_TYPE_SOA) {
328 /* domain has signed delegation/auth */
329 return 0;
330 }
331 }
332 /* maybe there is data at the next domain */
333 n = ldns_rbtree_next(n);
334 }
335 return 1;
336}
337
338
343ldns_rr_type
345{
346 ods_log_assert(domain);
347 if (domain->is_apex) {
348 return LDNS_RR_TYPE_SOA;
349 }
350 if (domain_lookup_rrset(domain, LDNS_RR_TYPE_NS)) {
351 if (domain_lookup_rrset(domain, LDNS_RR_TYPE_DS)) {
352 /* Signed delegation */
353 return LDNS_RR_TYPE_DS;
354 } else {
355 /* Unsigned delegation */
356 return LDNS_RR_TYPE_NS;
357 }
358 }
359 /* Authoritative */
360 return LDNS_RR_TYPE_SOA;
361}
362
363
368ldns_rr_type
370{
371 domain_type* parent = NULL;
372 ods_log_assert(domain);
373 if (domain->is_apex) {
374 return LDNS_RR_TYPE_SOA;
375 }
376 parent = domain->parent;
377 while (parent && !parent->is_apex) {
378 if (domain_lookup_rrset(parent, LDNS_RR_TYPE_NS)) {
379 /* Glue / Empty non-terminal to Glue */
380 return LDNS_RR_TYPE_A;
381 }
382 if (domain_lookup_rrset(parent, LDNS_RR_TYPE_DNAME)) {
383 /* Occluded data / Empty non-terminal to Occluded data */
384 return LDNS_RR_TYPE_DNAME;
385 }
386 parent = parent->parent;
387 }
388 /* Authoritative or delegation */
389 return LDNS_RR_TYPE_SOA;
390}
391
392
397void
398domain_print(FILE* fd, domain_type* domain, ods_status* status)
399{
400 char* str = NULL;
401 rrset_type* rrset = NULL;
402 rrset_type* soa_rrset = NULL;
403 rrset_type* cname_rrset = NULL;
404 if (!domain || !fd) {
405 if (status) {
406 ods_log_crit("[%s] unable to print domain: domain or fd missing",
407 dname_str);
408 *status = ODS_STATUS_ASSERT_ERR;
409 }
410 return;
411 }
412 /* empty non-terminal? */
413 if (!domain->rrsets) {
414 str = ldns_rdf2str(domain->dname);
415 fprintf(fd, ";;Empty non-terminal %s\n", str);
416 free((void*)str);
417 /* Denial of Existence */
418 if (domain->denial) {
419 denial_print(fd, (denial_type*) domain->denial, status);
420 }
421 return;
422 }
423 /* no other data may accompany a CNAME */
424 cname_rrset = domain_lookup_rrset(domain, LDNS_RR_TYPE_CNAME);
425 if (cname_rrset) {
426 rrset_print(fd, cname_rrset, 0, status);
427 } else {
428 /* if SOA, print soa first */
429 if (domain->is_apex) {
430 soa_rrset = domain_lookup_rrset(domain, LDNS_RR_TYPE_SOA);
431 if (soa_rrset) {
432 rrset_print(fd, soa_rrset, 0, status);
433 if (status && *status != ODS_STATUS_OK) {
434 return;
435 }
436 }
437 }
438 /* print other RRsets */
439 rrset = domain->rrsets;
440 while (rrset) {
441 /* skip SOA RRset */
442 if (rrset->rrtype != LDNS_RR_TYPE_SOA) {
443 rrset_print(fd, rrset, 0, status);
444 }
445 if (status && *status != ODS_STATUS_OK) {
446 ods_log_crit("[%s] failed to print one or more RRsets: %s",
447 dname_str, ods_status2str(*status));
448 return;
449 }
450 rrset = rrset->next;
451 }
452 }
453 /* Denial of Existence */
454 if (domain->denial) {
455 denial_print(fd, (denial_type*) domain->denial, status);
456 }
457}
458
459
464void
466{
467 if (!domain) {
468 return;
469 }
470 ldns_rdf_deep_free(domain->dname);
471 rrset_cleanup(domain->rrsets);
472 free(domain);
473}
474
475
480void
481domain_backup2(FILE* fd, domain_type* domain, int sigs)
482{
483 rrset_type* rrset = NULL;
484 if (!domain || !fd) {
485 return;
486 }
487 /* if SOA, print soa first */
488 if (domain->is_apex) {
489 rrset = domain_lookup_rrset(domain, LDNS_RR_TYPE_SOA);
490 if (rrset) {
491 if (sigs) {
492 rrset_backup2(fd, rrset);
493 } else {
494 rrset_print(fd, rrset, 1, NULL);
495 }
496 }
497 }
498 rrset = domain->rrsets;
499 while (rrset) {
500 /* skip SOA RRset */
501 if (rrset->rrtype != LDNS_RR_TYPE_SOA) {
502 if (sigs) {
503 rrset_backup2(fd, rrset);
504 } else {
505 rrset_print(fd, rrset, 1, NULL);
506 }
507 }
508 rrset = rrset->next;
509 }
510}
void denial_print(FILE *fd, denial_type *denial, ods_status *status)
Definition: denial.c:331
domain_type * domain_create(zone_type *zone, ldns_rdf *dname)
Definition: domain.c:88
ldns_rr_type domain_is_delegpt(domain_type *domain)
Definition: domain.c:344
size_t domain_count_rrset_is_added(domain_type *domain)
Definition: domain.c:118
int domain_ent2unsignedns(domain_type *domain)
Definition: domain.c:310
void domain_diff(domain_type *domain, unsigned is_ixfr, unsigned more_coming)
Definition: domain.c:190
void domain_backup2(FILE *fd, domain_type *domain, int sigs)
Definition: domain.c:481
void domain_cleanup(domain_type *domain)
Definition: domain.c:465
ldns_rr_type domain_is_occluded(domain_type *domain)
Definition: domain.c:369
void log_dname(ldns_rdf *rdf, const char *pre, int level)
Definition: domain.c:48
rrset_type * domain_lookup_rrset(domain_type *domain, ldns_rr_type rrtype)
Definition: domain.c:141
void domain_print(FILE *fd, domain_type *domain, ods_status *status)
Definition: domain.c:398
void domain_add_rrset(domain_type *domain, rrset_type *rrset)
Definition: domain.c:160
void domain_rollback(domain_type *domain, int keepsc)
Definition: domain.c:241
size_t rrset_count_rr_is_added(rrset_type *rrset)
Definition: rrset.c:278
void rrset_del_rr(rrset_type *rrset, uint16_t rrnum)
Definition: rrset.c:334
void rrset_diff(rrset_type *rrset, unsigned is_ixfr, unsigned more_coming)
Definition: rrset.c:366
void rrset_cleanup(rrset_type *rrset)
Definition: rrset.c:928
void log_rrset(ldns_rdf *dname, ldns_rr_type type, const char *pre, int level)
Definition: rrset.c:99
void rrset_backup2(FILE *fd, rrset_type *rrset)
Definition: rrset.c:951
void rrset_print(FILE *fd, rrset_type *rrset, int skip_rrsigs, ods_status *status)
Definition: rrset.c:871
unsigned bitmap_changed
Definition: denial.h:56
ldns_rdf * dname
Definition: domain.h:56
unsigned is_new
Definition: domain.h:59
zone_type * zone
Definition: domain.h:54
rrset_type * rrsets
Definition: domain.h:58
denial_type * denial
Definition: domain.h:53
ldns_rbnode_t * node
Definition: domain.h:55
unsigned is_apex
Definition: domain.h:60
domain_type * parent
Definition: domain.h:57
unsigned is_removed
Definition: rrset.h:56
unsigned exists
Definition: rrset.h:54
unsigned is_added
Definition: rrset.h:55
size_t rr_count
Definition: rrset.h:65
rr_type * rrs
Definition: rrset.h:64
ldns_rr_type rrtype
Definition: rrset.h:63
rrset_type * next
Definition: rrset.h:60
domain_type * domain
Definition: rrset.h:62