OpenDNSSEC-signer  1.4.1
domain.c
Go to the documentation of this file.
1 /*
2  * $Id: domain.c 6988 2013-01-29 10:57:11Z matthijs $
3  *
4  * Copyright (c) 2009 NLNet Labs. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  */
28 
34 #include "config.h"
35 #include "shared/log.h"
36 #include "signer/backup.h"
37 #include "signer/denial.h"
38 #include "signer/domain.h"
39 #include "signer/ixfr.h"
40 #include "signer/zone.h"
41 
42 static const char* dname_str = "domain";
43 
44 
49 void
50 log_dname(ldns_rdf *rdf, const char* pre, int level)
51 {
52  char* str = NULL;
53  if (ods_log_get_level() < level) {
54  return;
55  }
56  str = ldns_rdf2str(rdf);
57  if (!str) {
58  return;
59  }
60  if (level == LOG_EMERG) {
61  ods_fatal_exit("[%s] %s: %s", dname_str, pre?pre:"", str);
62  } else if (level == LOG_ALERT) {
63  ods_log_alert("[%s] %s: %s", dname_str, pre?pre:"", str);
64  } else if (level == LOG_CRIT) {
65  ods_log_crit("[%s] %s: %s", dname_str, pre?pre:"", str);
66  } else if (level == LOG_ERR) {
67  ods_log_error("[%s] %s: %s", dname_str, pre?pre:"", str);
68  } else if (level == LOG_WARNING) {
69  ods_log_warning("[%s] %s: %s", dname_str, pre?pre:"", str);
70  } else if (level == LOG_NOTICE) {
71  ods_log_info("[%s] %s: %s", dname_str, pre?pre:"", str);
72  } else if (level == LOG_INFO) {
73  ods_log_verbose("[%s] %s: %s", dname_str, pre?pre:"", str);
74  } else if (level == LOG_DEBUG) {
75  ods_log_debug("[%s] %s: %s", dname_str, pre?pre:"", str);
76  } else if (level == LOG_DEEEBUG) {
77  ods_log_deeebug("[%s] %s: %s", dname_str, pre?pre:"", str);
78  } else {
79  ods_log_deeebug("[%s] %s: %s", dname_str, pre?pre:"", str);
80  }
81  free((void*)str);
82  return;
83 }
84 
85 
91 domain_create(void* zoneptr, ldns_rdf* dname)
92 {
93  domain_type* domain = NULL;
94  zone_type* zone = (zone_type*) zoneptr;
95  if (!dname || !zoneptr) {
96  return NULL;
97  }
98  domain = (domain_type*) allocator_alloc(
99  zone->allocator, sizeof(domain_type));
100  if (!domain) {
101  ods_log_error("[%s] unable to create domain: allocator_alloc() "
102  "failed", dname_str);
103  return NULL;
104  }
105  domain->dname = ldns_rdf_clone(dname);
106  if (!domain->dname) {
107  ods_log_error("[%s] unable to create domain: ldns_rdf_clone() "
108  "failed", dname_str);
109  allocator_deallocate(zone->allocator, domain);
110  return NULL;
111  }
112  domain->zone = zoneptr;
113  domain->denial = NULL; /* no reference yet */
114  domain->node = NULL; /* not in db yet */
115  domain->rrsets = NULL;
116  domain->parent = NULL;
117  domain->is_apex = 0;
118  domain->is_new = 0;
119  return domain;
120 }
121 
122 
127 size_t
129 {
130  rrset_type* rrset = NULL;
131  size_t count = 0;
132  if (!domain) {
133  return 0;
134  }
135  rrset = domain->rrsets;
136  while (rrset) {
137  count++; /* rr_count may be zero */
138  rrset = rrset->next;
139  }
140  return count;
141 }
142 
143 
148 size_t
150 {
151  rrset_type* rrset = NULL;
152  size_t count = 0;
153  if (!domain) {
154  return 0;
155  }
156  rrset = domain->rrsets;
157  while (rrset) {
158  if (rrset_count_rr_is_added(rrset)) {
159  count++;
160  }
161  rrset = rrset->next;
162  }
163  return count;
164 }
165 
166 
171 rrset_type*
172 domain_lookup_rrset(domain_type* domain, ldns_rr_type rrtype)
173 {
174  rrset_type* rrset = NULL;
175  if (!domain || !domain->rrsets || !rrtype) {
176  return NULL;
177  }
178  rrset = domain->rrsets;
179  while (rrset && rrset->rrtype != rrtype) {
180  rrset = rrset->next;
181  }
182  return rrset;
183 }
184 
185 
190 void
192 {
193  rrset_type** p = NULL;
194  denial_type* denial = NULL;
195  ods_log_assert(domain);
196  ods_log_assert(rrset);
197  if (!domain->rrsets) {
198  domain->rrsets = rrset;
199  } else {
200  p = &domain->rrsets;
201  while(*p) {
202  p = &((*p)->next);
203  }
204  *p = rrset;
205  rrset->next = NULL;
206  }
207  log_rrset(domain->dname, rrset->rrtype, "+RRSET", LOG_DEEEBUG);
208  rrset->domain = (void*) domain;
209  if (domain->denial) {
210  denial = (denial_type*) domain->denial;
211  denial->bitmap_changed = 1;
212  }
213  return;
214 }
215 
216 
221 rrset_type*
222 domain_del_rrset(domain_type* domain, ldns_rr_type rrtype)
223 {
224  rrset_type* cur = NULL;
225  denial_type* denial = NULL;
226  if (!domain || !rrtype) {
227  return NULL;
228  }
229  if (!domain->rrsets) {
230  ods_log_error("[%s] unable to delete RRset: RRset with RRtype %s "
231  "does not exist", dname_str, rrset_type2str(rrtype));
232  return NULL;
233  }
234  if (domain->rrsets->rrtype == rrtype) {
235  cur = domain->rrsets;
236  domain->rrsets = cur->next;
237  cur->domain = NULL;
238  cur->next = NULL;
239  log_rrset(domain->dname, rrtype, "-RRSET", LOG_DEEEBUG);
240  if (domain->denial) {
241  denial = (denial_type*) domain->denial;
242  denial->bitmap_changed = 1;
243  }
244  return cur;
245  }
246  cur = domain->rrsets;
247  while (cur) {
248  if (!cur->next) {
249  ods_log_error("[%s] unable to delete RRset: RRset with RRtype %s "
250  "does not exist", dname_str, rrset_type2str(rrtype));
251  return NULL;
252  }
253  ods_log_assert(cur->next);
254  if (cur->next->rrtype != rrtype) {
255  cur = cur->next;
256  } else {
257  ods_log_assert(cur->next->rrtype == rrtype);
258  cur->next = cur->next->next;
259  cur = cur->next;
260  cur->domain = NULL;
261  cur->next = NULL;
262  log_rrset(domain->dname, rrtype, "-RRSET", LOG_DEEEBUG);
263  if (domain->denial) {
264  denial = (denial_type*) domain->denial;
265  denial->bitmap_changed = 1;
266  }
267  return cur;
268  }
269  }
270  ods_log_error("[%s] unable to delete RRset: RRset with RRtype %s "
271  "does not exist", dname_str, rrset_type2str(rrtype));
272  return NULL;
273 }
274 
275 
280 void
281 domain_diff(domain_type* domain, unsigned is_ixfr, unsigned more_coming)
282 {
283  denial_type* denial = NULL;
284  rrset_type* rrset = NULL;
285  rrset_type* prev_rrset = NULL;
286 
287  if (!domain) {
288  return;
289  }
290  rrset = domain->rrsets;
291  while (rrset) {
292  if (rrset->rrtype == LDNS_RR_TYPE_NSEC3PARAMS ||
293  rrset->rrtype == LDNS_RR_TYPE_DNSKEY) {
294  /* always do full diff on NSEC3PARAMS | DNSKEY RRset */
295  rrset_diff(rrset, 0, more_coming);
296  } else {
297  rrset_diff(rrset, is_ixfr, more_coming);
298  }
299  if (rrset->rr_count <= 0) {
300  /* delete entire rrset */
301  if (!prev_rrset) {
302  domain->rrsets = rrset->next;
303  } else {
304  prev_rrset->next = rrset->next;
305  }
306  rrset->next = NULL;
307  log_rrset(domain->dname, rrset->rrtype, "-RRSET", LOG_DEEEBUG);
308  rrset_cleanup(rrset);
309  if (!prev_rrset) {
310  rrset = domain->rrsets;
311  } else {
312  rrset = prev_rrset->next;
313  }
314  if (domain->denial) {
315  denial = (denial_type*) domain->denial;
316  denial->bitmap_changed = 1;
317  }
318  } else {
319  /* just go to next rrset */
320  prev_rrset = rrset;
321  rrset = rrset->next;
322  }
323  }
324  return;
325 }
326 
327 
332 void
333 domain_rollback(domain_type* domain, int keepsc)
334 {
335  denial_type* denial = NULL;
336  rrset_type* rrset = NULL;
337  rrset_type* prev_rrset = NULL;
338  ldns_rr* del_rr = NULL;
339  int del_rrset = 0;
340  uint16_t i = 0;
341  if (!domain) {
342  return;
343  }
344  rrset = domain->rrsets;
345  while (rrset) {
346  if (keepsc) {
347  /* skip rollback for NSEC3PARAM and DNSKEY RRset */
348  if (rrset->rrtype == LDNS_RR_TYPE_NSEC3PARAMS ||
349  rrset->rrtype == LDNS_RR_TYPE_DNSKEY) {
350  prev_rrset = rrset;
351  rrset = rrset->next;
352  continue;
353  }
354  }
355  /* walk rrs */
356  for (i=0; i < rrset->rr_count; i++) {
357  rrset->rrs[i].is_added = 0;
358  rrset->rrs[i].is_removed = 0;
359  if (!rrset->rrs[i].exists) {
360  /* can we delete the RRset? */
361  if(rrset->rr_count == 1) {
362  del_rrset = 1;
363  }
364  del_rr = rrset->rrs[i].rr;
365  rrset_del_rr(rrset, i);
366  ldns_rr_free(del_rr);
367  del_rr = NULL;
368  i--;
369  }
370  }
371  /* next rrset */
372  if (del_rrset) {
373  /* delete entire rrset */
374  if (!prev_rrset) {
375  domain->rrsets = rrset->next;
376  } else {
377  prev_rrset->next = rrset->next;
378  }
379  rrset->next = NULL;
380  log_rrset(domain->dname, rrset->rrtype, "-RRSET", LOG_DEEEBUG);
381  rrset_cleanup(rrset);
382  if (!prev_rrset) {
383  rrset = domain->rrsets;
384  } else {
385  rrset = prev_rrset->next;
386  }
387  if (domain->denial) {
388  denial = (denial_type*) domain->denial;
389  denial->bitmap_changed = 0;
390  }
391  del_rrset = 0;
392  } else {
393  /* just go to next rrset */
394  prev_rrset = rrset;
395  rrset = rrset->next;
396  }
397  }
398  return;
399 }
400 
401 
406 int
408 {
409  ldns_rbnode_t* n = LDNS_RBTREE_NULL;
410  domain_type* d = NULL;
411 
412  ods_log_assert(domain);
413  if (domain->rrsets) {
414  return 0; /* not an empty non-terminal */
415  }
416  n = ldns_rbtree_next(domain->node);
417  while (n && n != LDNS_RBTREE_NULL) {
418  d = (domain_type*) n->data;
419  if (!ldns_dname_is_subdomain(d->dname, domain->dname)) {
420  break;
421  }
422  if (d->rrsets) {
423  if (domain_is_delegpt(d) != LDNS_RR_TYPE_NS &&
424  domain_is_occluded(d) == LDNS_RR_TYPE_SOA) {
425  /* domain has signed delegation/auth */
426  return 0;
427  }
428  }
429  /* maybe there is data at the next domain */
430  n = ldns_rbtree_next(n);
431  }
432  return 1;
433 }
434 
435 
440 ldns_rr_type
442 {
443  ods_log_assert(domain);
444  if (domain->is_apex) {
445  return LDNS_RR_TYPE_SOA;
446  }
447  if (domain_lookup_rrset(domain, LDNS_RR_TYPE_NS)) {
448  if (domain_lookup_rrset(domain, LDNS_RR_TYPE_DS)) {
449  /* Signed delegation */
450  return LDNS_RR_TYPE_DS;
451  } else {
452  /* Unsigned delegation */
453  return LDNS_RR_TYPE_NS;
454  }
455  }
456  /* Authoritative */
457  return LDNS_RR_TYPE_SOA;
458 }
459 
460 
465 ldns_rr_type
467 {
468  domain_type* parent = NULL;
469  ods_log_assert(domain);
470  if (domain->is_apex) {
471  return LDNS_RR_TYPE_SOA;
472  }
473  parent = domain->parent;
474  while (parent && !parent->is_apex) {
475  if (domain_lookup_rrset(parent, LDNS_RR_TYPE_NS)) {
476  /* Glue / Empty non-terminal to Glue */
477  return LDNS_RR_TYPE_A;
478  }
479  if (domain_lookup_rrset(parent, LDNS_RR_TYPE_DNAME)) {
480  /* Occluded data / Empty non-terminal to Occluded data */
481  return LDNS_RR_TYPE_DNAME;
482  }
483  parent = parent->parent;
484  }
485  /* Authoritative or delegation */
486  return LDNS_RR_TYPE_SOA;
487 }
488 
489 
494 void
495 domain_print(FILE* fd, domain_type* domain, ods_status* status)
496 {
497  char* str = NULL;
498  rrset_type* rrset = NULL;
499  rrset_type* soa_rrset = NULL;
500  rrset_type* cname_rrset = NULL;
501  if (!domain || !fd) {
502  if (status) {
503  ods_log_crit("[%s] unable to print domain: domain or fd missing",
504  dname_str);
505  *status = ODS_STATUS_ASSERT_ERR;
506  }
507  return;
508  }
509  /* empty non-terminal? */
510  if (!domain->rrsets) {
511  str = ldns_rdf2str(domain->dname);
512  fprintf(fd, ";;Empty non-terminal %s\n", str);
513  free((void*)str);
514  /* Denial of Existence */
515  if (domain->denial) {
516  denial_print(fd, (denial_type*) domain->denial, status);
517  }
518  return;
519  }
520  /* no other data may accompany a CNAME */
521  cname_rrset = domain_lookup_rrset(domain, LDNS_RR_TYPE_CNAME);
522  if (cname_rrset) {
523  rrset_print(fd, cname_rrset, 0, status);
524  } else {
525  /* if SOA, print soa first */
526  if (domain->is_apex) {
527  soa_rrset = domain_lookup_rrset(domain, LDNS_RR_TYPE_SOA);
528  if (soa_rrset) {
529  rrset_print(fd, soa_rrset, 0, status);
530  if (status && *status != ODS_STATUS_OK) {
531  return;
532  }
533  }
534  }
535  /* print other RRsets */
536  rrset = domain->rrsets;
537  while (rrset) {
538  /* skip SOA RRset */
539  if (rrset->rrtype != LDNS_RR_TYPE_SOA) {
540  rrset_print(fd, rrset, 0, status);
541  }
542  if (status && *status != ODS_STATUS_OK) {
543  ods_log_crit("[%s] failed to print one or more RRsets: %s",
544  dname_str, ods_status2str(*status));
545  return;
546  }
547  rrset = rrset->next;
548  }
549  }
550  /* Denial of Existence */
551  if (domain->denial) {
552  denial_print(fd, (denial_type*) domain->denial, status);
553  }
554  return;
555 }
556 
557 
562 void
564 {
565  zone_type* zone = NULL;
566  if (!domain) {
567  return;
568  }
569  zone = (zone_type*) domain->zone;
570  ldns_rdf_deep_free(domain->dname);
571  rrset_cleanup(domain->rrsets);
572  allocator_deallocate(zone->allocator, (void*)domain);
573  return;
574 }
575 
576 
581 void
582 domain_backup2(FILE* fd, domain_type* domain, int sigs)
583 {
584  rrset_type* rrset = NULL;
585  if (!domain || !fd) {
586  return;
587  }
588  /* if SOA, print soa first */
589  if (domain->is_apex) {
590  rrset = domain_lookup_rrset(domain, LDNS_RR_TYPE_SOA);
591  if (rrset) {
592  if (sigs) {
593  rrset_backup2(fd, rrset);
594  } else {
595  rrset_print(fd, rrset, 1, NULL);
596  }
597  }
598  }
599  rrset = domain->rrsets;
600  while (rrset) {
601  /* skip SOA RRset */
602  if (rrset->rrtype != LDNS_RR_TYPE_SOA) {
603  if (sigs) {
604  rrset_backup2(fd, rrset);
605  } else {
606  rrset_print(fd, rrset, 1, NULL);
607  }
608  }
609  rrset = rrset->next;
610  }
611  return;
612 }
void ods_log_alert(const char *format,...)
Definition: log.c:368
size_t domain_count_rrset_is_added(domain_type *domain)
Definition: domain.c:149
void domain_cleanup(domain_type *domain)
Definition: domain.c:563
size_t rr_count
Definition: rrset.h:81
rrset_type * domain_del_rrset(domain_type *domain, ldns_rr_type rrtype)
Definition: domain.c:222
void domain_add_rrset(domain_type *domain, rrset_type *rrset)
Definition: domain.c:191
void rrset_cleanup(rrset_type *rrset)
Definition: rrset.c:844
void domain_backup2(FILE *fd, domain_type *domain, int sigs)
Definition: domain.c:582
rrset_type * domain_lookup_rrset(domain_type *domain, ldns_rr_type rrtype)
Definition: domain.c:172
const char * rrset_type2str(ldns_rr_type type)
Definition: rrset.c:162
void ods_log_debug(const char *format,...)
Definition: log.c:272
void * allocator_alloc(allocator_type *allocator, size_t size)
Definition: allocator.c:68
void domain_print(FILE *fd, domain_type *domain, ods_status *status)
Definition: domain.c:495
#define LOG_INFO
Definition: log.h:52
size_t rrset_count_rr_is_added(rrset_type *rrset)
Definition: rrset.c:243
void ods_fatal_exit(const char *format,...)
Definition: log.c:384
void ods_log_info(const char *format,...)
Definition: log.c:304
enum ods_enum_status ods_status
Definition: status.h:89
#define LOG_EMERG
Definition: log.h:46
void ods_log_error(const char *format,...)
Definition: log.c:336
const char * ods_status2str(ods_status status)
Definition: status.c:110
#define LOG_NOTICE
Definition: log.h:51
ldns_rr_type rrtype
Definition: rrset.h:78
rrset_type * next
Definition: rrset.h:75
void domain_diff(domain_type *domain, unsigned is_ixfr, unsigned more_coming)
Definition: domain.c:281
void ods_log_crit(const char *format,...)
Definition: log.c:352
unsigned exists
Definition: rrset.h:64
#define LOG_ALERT
Definition: log.h:47
domain_type * parent
Definition: domain.h:61
int domain_ent2unsignedns(domain_type *domain)
Definition: domain.c:407
unsigned is_removed
Definition: rrset.h:66
void log_rrset(ldns_rdf *dname, ldns_rr_type type, const char *pre, int level)
Definition: rrset.c:102
void denial_print(FILE *fd, denial_type *denial, ods_status *status)
Definition: denial.c:333
ldns_rr_type domain_is_delegpt(domain_type *domain)
Definition: domain.c:441
ldns_rr_type domain_is_occluded(domain_type *domain)
Definition: domain.c:466
#define LOG_CRIT
Definition: log.h:48
void log_dname(ldns_rdf *rdf, const char *pre, int level)
Definition: domain.c:50
unsigned is_apex
Definition: domain.h:64
void rrset_backup2(FILE *fd, rrset_type *rrset)
Definition: rrset.c:877
allocator_type * allocator
Definition: zone.h:69
unsigned is_new
Definition: domain.h:63
void rrset_del_rr(rrset_type *rrset, uint16_t rrnum)
Definition: rrset.c:302
#define LOG_ERR
Definition: log.h:49
int ods_log_get_level()
Definition: log.c:209
ldns_rr * rr
Definition: rrset.h:62
void ods_log_verbose(const char *format,...)
Definition: log.c:288
#define LOG_DEEEBUG
Definition: log.h:55
size_t domain_count_rrset(domain_type *domain)
Definition: domain.c:128
void ods_log_deeebug(const char *format,...)
Definition: log.c:256
ldns_rbnode_t * node
Definition: domain.h:59
void domain_rollback(domain_type *domain, int keepsc)
Definition: domain.c:333
void allocator_deallocate(allocator_type *allocator, void *data)
Definition: allocator.c:137
#define LOG_DEBUG
Definition: log.h:53
void rrset_diff(rrset_type *rrset, unsigned is_ixfr, unsigned more_coming)
Definition: rrset.c:339
rrset_type * rrsets
Definition: domain.h:62
unsigned bitmap_changed
Definition: denial.h:57
void * domain
Definition: rrset.h:77
#define ods_log_assert(x)
Definition: log.h:156
void * denial
Definition: domain.h:58
unsigned is_added
Definition: rrset.h:65
#define LOG_WARNING
Definition: log.h:50
void ods_log_warning(const char *format,...)
Definition: log.c:320
void rrset_print(FILE *fd, rrset_type *rrset, int skip_rrsigs, ods_status *status)
Definition: rrset.c:789
ldns_rdf * dname
Definition: domain.h:60
domain_type * domain_create(void *zoneptr, ldns_rdf *dname)
Definition: domain.c:91
void * zone
Definition: domain.h:57
rr_type * rrs
Definition: rrset.h:79