OpenDNSSEC-signer  2.1.12
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 
40 static const char* dname_str = "domain";
41 
42 
47 void
48 log_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 
88 domain_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 
117 size_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 
140 rrset_type*
141 domain_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 
159 void
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 
189 void
190 domain_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 
240 void
241 domain_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 
309 int
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 
343 ldns_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 
368 ldns_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 
397 void
398 domain_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 
464 void
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 
480 void
481 domain_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
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
domain_type * domain_create(zone_type *zone, ldns_rdf *dname)
Definition: domain.c:88
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
rrset_type * domain_lookup_rrset(domain_type *domain, ldns_rr_type rrtype)
Definition: domain.c:141
void log_dname(ldns_rdf *rdf, const char *pre, int level)
Definition: domain.c:48
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