OpenDNSSEC-signer  2.0.4
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  ldns_rr* del_rr = NULL;
247  int del_rrset = 0;
248  uint16_t i = 0;
249  if (!domain) {
250  return;
251  }
252  rrset = domain->rrsets;
253  while (rrset) {
254  if (keepsc) {
255  /* skip rollback for NSEC3PARAM and DNSKEY RRset */
256  if (rrset->rrtype == LDNS_RR_TYPE_NSEC3PARAMS ||
257  rrset->rrtype == LDNS_RR_TYPE_DNSKEY) {
258  prev_rrset = rrset;
259  rrset = rrset->next;
260  continue;
261  }
262  }
263  /* walk rrs */
264  for (i=0; i < rrset->rr_count; i++) {
265  rrset->rrs[i].is_added = 0;
266  rrset->rrs[i].is_removed = 0;
267  if (!rrset->rrs[i].exists) {
268  /* can we delete the RRset? */
269  if(rrset->rr_count == 1) {
270  del_rrset = 1;
271  }
272  del_rr = rrset->rrs[i].rr;
273  rrset_del_rr(rrset, i);
274  ldns_rr_free(del_rr);
275  del_rr = NULL;
276  i--;
277  }
278  }
279  /* next rrset */
280  if (del_rrset) {
281  /* delete entire rrset */
282  if (!prev_rrset) {
283  domain->rrsets = rrset->next;
284  } else {
285  prev_rrset->next = rrset->next;
286  }
287  rrset->next = NULL;
288  log_rrset(domain->dname, rrset->rrtype, "-RRSET", LOG_DEEEBUG);
289  rrset_cleanup(rrset);
290  if (!prev_rrset) {
291  rrset = domain->rrsets;
292  } else {
293  rrset = prev_rrset->next;
294  }
295  if (domain->denial) {
296  denial = (denial_type*) domain->denial;
297  denial->bitmap_changed = 0;
298  }
299  del_rrset = 0;
300  } else {
301  /* just go to next rrset */
302  prev_rrset = rrset;
303  rrset = rrset->next;
304  }
305  }
306 }
307 
308 
313 int
315 {
316  ldns_rbnode_t* n = LDNS_RBTREE_NULL;
317  domain_type* d = NULL;
318 
319  ods_log_assert(domain);
320  if (domain->rrsets) {
321  return 0; /* not an empty non-terminal */
322  }
323  n = ldns_rbtree_next(domain->node);
324  while (n && n != LDNS_RBTREE_NULL) {
325  d = (domain_type*) n->data;
326  if (!ldns_dname_is_subdomain(d->dname, domain->dname)) {
327  break;
328  }
329  if (d->rrsets) {
330  if (domain_is_delegpt(d) != LDNS_RR_TYPE_NS &&
331  domain_is_occluded(d) == LDNS_RR_TYPE_SOA) {
332  /* domain has signed delegation/auth */
333  return 0;
334  }
335  }
336  /* maybe there is data at the next domain */
337  n = ldns_rbtree_next(n);
338  }
339  return 1;
340 }
341 
342 
347 ldns_rr_type
349 {
350  ods_log_assert(domain);
351  if (domain->is_apex) {
352  return LDNS_RR_TYPE_SOA;
353  }
354  if (domain_lookup_rrset(domain, LDNS_RR_TYPE_NS)) {
355  if (domain_lookup_rrset(domain, LDNS_RR_TYPE_DS)) {
356  /* Signed delegation */
357  return LDNS_RR_TYPE_DS;
358  } else {
359  /* Unsigned delegation */
360  return LDNS_RR_TYPE_NS;
361  }
362  }
363  /* Authoritative */
364  return LDNS_RR_TYPE_SOA;
365 }
366 
367 
372 ldns_rr_type
374 {
375  domain_type* parent = NULL;
376  ods_log_assert(domain);
377  if (domain->is_apex) {
378  return LDNS_RR_TYPE_SOA;
379  }
380  parent = domain->parent;
381  while (parent && !parent->is_apex) {
382  if (domain_lookup_rrset(parent, LDNS_RR_TYPE_NS)) {
383  /* Glue / Empty non-terminal to Glue */
384  return LDNS_RR_TYPE_A;
385  }
386  if (domain_lookup_rrset(parent, LDNS_RR_TYPE_DNAME)) {
387  /* Occluded data / Empty non-terminal to Occluded data */
388  return LDNS_RR_TYPE_DNAME;
389  }
390  parent = parent->parent;
391  }
392  /* Authoritative or delegation */
393  return LDNS_RR_TYPE_SOA;
394 }
395 
396 
401 void
402 domain_print(FILE* fd, domain_type* domain, ods_status* status)
403 {
404  char* str = NULL;
405  rrset_type* rrset = NULL;
406  rrset_type* soa_rrset = NULL;
407  rrset_type* cname_rrset = NULL;
408  if (!domain || !fd) {
409  if (status) {
410  ods_log_crit("[%s] unable to print domain: domain or fd missing",
411  dname_str);
412  *status = ODS_STATUS_ASSERT_ERR;
413  }
414  return;
415  }
416  /* empty non-terminal? */
417  if (!domain->rrsets) {
418  str = ldns_rdf2str(domain->dname);
419  fprintf(fd, ";;Empty non-terminal %s\n", str);
420  free((void*)str);
421  /* Denial of Existence */
422  if (domain->denial) {
423  denial_print(fd, (denial_type*) domain->denial, status);
424  }
425  return;
426  }
427  /* no other data may accompany a CNAME */
428  cname_rrset = domain_lookup_rrset(domain, LDNS_RR_TYPE_CNAME);
429  if (cname_rrset) {
430  rrset_print(fd, cname_rrset, 0, status);
431  } else {
432  /* if SOA, print soa first */
433  if (domain->is_apex) {
434  soa_rrset = domain_lookup_rrset(domain, LDNS_RR_TYPE_SOA);
435  if (soa_rrset) {
436  rrset_print(fd, soa_rrset, 0, status);
437  if (status && *status != ODS_STATUS_OK) {
438  return;
439  }
440  }
441  }
442  /* print other RRsets */
443  rrset = domain->rrsets;
444  while (rrset) {
445  /* skip SOA RRset */
446  if (rrset->rrtype != LDNS_RR_TYPE_SOA) {
447  rrset_print(fd, rrset, 0, status);
448  }
449  if (status && *status != ODS_STATUS_OK) {
450  ods_log_crit("[%s] failed to print one or more RRsets: %s",
451  dname_str, ods_status2str(*status));
452  return;
453  }
454  rrset = rrset->next;
455  }
456  }
457  /* Denial of Existence */
458  if (domain->denial) {
459  denial_print(fd, (denial_type*) domain->denial, status);
460  }
461 }
462 
463 
468 void
470 {
471  if (!domain) {
472  return;
473  }
474  ldns_rdf_deep_free(domain->dname);
475  rrset_cleanup(domain->rrsets);
476  free(domain);
477 }
478 
479 
484 void
485 domain_backup2(FILE* fd, domain_type* domain, int sigs)
486 {
487  rrset_type* rrset = NULL;
488  if (!domain || !fd) {
489  return;
490  }
491  /* if SOA, print soa first */
492  if (domain->is_apex) {
493  rrset = domain_lookup_rrset(domain, LDNS_RR_TYPE_SOA);
494  if (rrset) {
495  if (sigs) {
496  rrset_backup2(fd, rrset);
497  } else {
498  rrset_print(fd, rrset, 1, NULL);
499  }
500  }
501  }
502  rrset = domain->rrsets;
503  while (rrset) {
504  /* skip SOA RRset */
505  if (rrset->rrtype != LDNS_RR_TYPE_SOA) {
506  if (sigs) {
507  rrset_backup2(fd, rrset);
508  } else {
509  rrset_print(fd, rrset, 1, NULL);
510  }
511  }
512  rrset = rrset->next;
513  }
514 }
size_t domain_count_rrset_is_added(domain_type *domain)
Definition: domain.c:118
void domain_cleanup(domain_type *domain)
Definition: domain.c:469
size_t rr_count
Definition: rrset.h:65
void domain_add_rrset(domain_type *domain, rrset_type *rrset)
Definition: domain.c:160
void rrset_cleanup(rrset_type *rrset)
Definition: rrset.c:845
void domain_backup2(FILE *fd, domain_type *domain, int sigs)
Definition: domain.c:485
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:402
size_t rrset_count_rr_is_added(rrset_type *rrset)
Definition: rrset.c:264
ldns_rr_type rrtype
Definition: rrset.h:63
rrset_type * next
Definition: rrset.h:60
void domain_diff(domain_type *domain, unsigned is_ixfr, unsigned more_coming)
Definition: domain.c:190
denial_type * denial
Definition: domain.h:52
unsigned exists
Definition: rrset.h:54
domain_type * parent
Definition: domain.h:56
int domain_ent2unsignedns(domain_type *domain)
Definition: domain.c:314
unsigned is_removed
Definition: rrset.h:56
void log_rrset(ldns_rdf *dname, ldns_rr_type type, const char *pre, int level)
Definition: rrset.c:99
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:348
ldns_rr_type domain_is_occluded(domain_type *domain)
Definition: domain.c:373
domain_type * domain_create(zone_type *zone, ldns_rdf *dname)
Definition: domain.c:88
void log_dname(ldns_rdf *rdf, const char *pre, int level)
Definition: domain.c:48
unsigned is_apex
Definition: domain.h:59
void rrset_backup2(FILE *fd, rrset_type *rrset)
Definition: rrset.c:868
unsigned is_new
Definition: domain.h:58
void rrset_del_rr(rrset_type *rrset, uint16_t rrnum)
Definition: rrset.c:320
zone_type * zone
Definition: domain.h:53
domain_type * domain
Definition: rrset.h:62
ldns_rr * rr
Definition: rrset.h:52
ldns_rbnode_t * node
Definition: domain.h:54
void domain_rollback(domain_type *domain, int keepsc)
Definition: domain.c:241
void rrset_diff(rrset_type *rrset, unsigned is_ixfr, unsigned more_coming)
Definition: rrset.c:352
rrset_type * rrsets
Definition: domain.h:57
unsigned bitmap_changed
Definition: denial.h:56
unsigned is_added
Definition: rrset.h:55
void rrset_print(FILE *fd, rrset_type *rrset, int skip_rrsigs, ods_status *status)
Definition: rrset.c:788
ldns_rdf * dname
Definition: domain.h:55
rr_type * rrs
Definition: rrset.h:64