OpenDNSSEC-signer  1.3.15
zonedata.c
Go to the documentation of this file.
1 /*
2  * $Id: zonedata.c 7161 2013-06-18 09:59:05Z 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 "adapter/adapter.h"
36 #include "shared/allocator.h"
37 #include "shared/log.h"
38 #include "shared/util.h"
39 #include "signer/backup.h"
40 #include "signer/domain.h"
41 #include "signer/nsec3params.h"
42 #include "signer/zonedata.h"
43 
44 #include <ldns/ldns.h> /* ldns_dname_*(), ldns_rbtree_*() */
45 
46 static const char* zd_str = "data";
47 
48 static ldns_rbnode_t* domain2node(domain_type* domain);
49 
54 void
55 log_rdf(ldns_rdf *rdf, const char* pre, int level)
56 {
57  char* str = NULL;
58 
59  if (ods_log_get_level() < level + 2) return;
60 
61  str = ldns_rdf2str(rdf);
62 
63  if (level == 1) {
64  ods_log_error("[%s] %s : %s", zd_str, pre?pre:"", str?str:"(null)");
65  } else if (level == 2) {
66  ods_log_warning("[%s] %s : %s", zd_str, pre?pre:"", str?str:"(null)");
67  } else if (level == 3) {
68  ods_log_info("[%s] %s : %s", zd_str, pre?pre:"", str?str:"(null)");
69  } else if (level == 4) {
70  ods_log_verbose("[%s] %s : %s", zd_str, pre?pre:"", str?str:"(null)");
71  } else if (level == 5) {
72  ods_log_debug("[%s] %s : %s", zd_str, pre?pre:"", str?str:"(null)");
73  } else if (level == 6) {
74  ods_log_deeebug("[%s] %s : %s", zd_str, pre?pre:"", str?str:"(null)");
75  } else {
76  ods_log_deeebug("[%s] %s : %s", zd_str, pre?pre:"", str?str:"(null)");
77  }
78 
79  free((void*)str);
80 
81  return;
82 }
83 
84 
89 static ldns_rbnode_t*
90 domain2node(domain_type* domain)
91 {
92  ldns_rbnode_t* node = (ldns_rbnode_t*) malloc(sizeof(ldns_rbnode_t));
93  if (!node) {
94  return NULL;
95  }
96  node->key = domain->dname;
97  node->data = domain;
98  return node;
99 }
100 
101 
106 static ldns_rbnode_t*
107 denial2node(denial_type* denial)
108 {
109  ldns_rbnode_t* node = (ldns_rbnode_t*) malloc(sizeof(ldns_rbnode_t));
110  if (!node) {
111  return NULL;
112  }
113  node->key = denial->owner;
114  node->data = denial;
115  return node;
116 }
117 
118 
123 static int
124 domain_compare(const void* a, const void* b)
125 {
126  ldns_rdf* x = (ldns_rdf*)a;
127  ldns_rdf* y = (ldns_rdf*)b;
128  return ldns_dname_compare(x, y);
129 }
130 
131 
136 void
138 {
139  if (zd) {
140  zd->denial_chain = ldns_rbtree_create(domain_compare);
141  }
142  return;
143 }
144 
145 
150 static void
151 zonedata_init_domains(zonedata_type* zd)
152 {
153  if (zd) {
154  zd->domains = ldns_rbtree_create(domain_compare);
155  }
156  return;
157 }
158 
159 
166 {
167  zonedata_type* zd = NULL;
168 
169  if (!allocator) {
170  ods_log_error("[%s] cannot create zonedata: no allocator", zd_str);
171  return NULL;
172  }
173  ods_log_assert(allocator);
174 
175  zd = (zonedata_type*) allocator_alloc(allocator, sizeof(zonedata_type));
176  if (!zd) {
177  ods_log_error("[%s] cannot create zonedata: allocator failed",
178  zd_str);
179  return NULL;
180  }
181  ods_log_assert(zd);
182 
183  zd->allocator = allocator;
184  zonedata_init_domains(zd);
186  zd->initialized = 0;
187  zd->force_serial = 0;
188  zd->inbound_serial = 0;
189  zd->internal_serial = 0;
190  zd->outbound_serial = 0;
191  zd->enforced_serial = 0;
192  zd->default_ttl = 3600; /* TODO: configure --default-ttl option? */
193  return zd;
194 }
195 
196 
203 {
204  const char* token = NULL;
205  const char* owner = NULL;
206  int dstatus = 0;
207  ods_status status = ODS_STATUS_OK;
208  domain_type* domain = NULL;
209  ldns_rdf* rdf = NULL;
210  ldns_rbnode_t* denial_node = LDNS_RBTREE_NULL;
211 
212  ods_log_assert(zd);
213  ods_log_assert(fd);
214 
215  while (backup_read_str(fd, &token)) {
216  /* domain part */
217  if (ods_strcmp(token, ";;Domain:") == 0) {
218  if (!backup_read_check_str(fd, "name") ||
219  !backup_read_str(fd, &owner) ||
220  !backup_read_check_str(fd, "status") ||
221  !backup_read_int(fd, &dstatus)) {
222  ods_log_error("[%s] domain in backup corrupted", zd_str);
223  goto recover_domain_error;
224  }
225  /* ok, look up domain */
226  rdf = ldns_dname_new_frm_str(owner);
227  if (rdf) {
228  domain = zonedata_lookup_domain(zd, rdf);
229  ldns_rdf_deep_free(rdf);
230  rdf = NULL;
231  }
232  if (!domain) {
233  ods_log_error("[%s] domain in backup, but not in zonedata",
234  zd_str);
235  goto recover_domain_error;
236  }
237  /* lookup success */
238  status = domain_recover(domain, fd, dstatus);
239  if (status != ODS_STATUS_OK) {
240  ods_log_error("[%s] unable to recover domain", zd_str);
241  goto recover_domain_error;
242  }
243  if (domain->denial) {
244  denial_node = denial2node(domain->denial);
245  /* insert */
246  if (!ldns_rbtree_insert(zd->denial_chain, denial_node)) {
247  ods_log_error("[%s] unable to recover denial", zd_str);
248  free((void*)denial_node);
249  goto recover_domain_error;
250  }
251  denial_node = NULL;
252  }
253 
254  /* done, next domain */
255  free((void*) owner);
256  owner = NULL;
257  domain = NULL;
258  } else if (ods_strcmp(token, ";;") == 0) {
259  /* done with all zone data */
260  free((void*) token);
261  token = NULL;
262  return ODS_STATUS_OK;
263  } else {
264  /* domain corrupted */
265  ods_log_error("[%s] domain in backup corrupted", zd_str);
266  goto recover_domain_error;
267  }
268  free((void*) token);
269  token = NULL;
270  }
271 
272  if (!backup_read_check_str(fd, ODS_SE_FILE_MAGIC)) {
273  goto recover_domain_error;
274  }
275 
276  return ODS_STATUS_OK;
277 
278 recover_domain_error:
279  free((void*) owner);
280  owner = NULL;
281 
282  free((void*) token);
283  token = NULL;
284 
285  return ODS_STATUS_ERR;
286 }
287 
288 
293 static domain_type*
294 zonedata_domain_search(ldns_rbtree_t* tree, ldns_rdf* dname)
295 {
296  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
297 
298  if (!tree || !dname) {
299  return NULL;
300  }
301  node = ldns_rbtree_search(tree, dname);
302  if (node && node != LDNS_RBTREE_NULL) {
303  return (domain_type*) node->data;
304  }
305  return NULL;
306 }
307 
308 
315 {
316  if (!zd) return NULL;
317 
318  return zonedata_domain_search(zd->domains, dname);
319 }
320 
321 
328 {
329  ldns_rbnode_t* new_node = LDNS_RBTREE_NULL;
330 
331  if (!domain) {
332  ods_log_error("[%s] unable to add domain: no domain", zd_str);
333  return NULL;
334  }
335  ods_log_assert(domain);
336 
337  if (!zd || !zd->domains) {
338  log_rdf(domain->dname, "unable to add domain, no storage", 1);
339  return NULL;
340  }
341  ods_log_assert(zd);
342  ods_log_assert(zd->domains);
343 
344  new_node = domain2node(domain);
345  if (ldns_rbtree_insert(zd->domains, new_node) == NULL) {
346  log_rdf(domain->dname, "unable to add domain, already present", 1);
347  free((void*)new_node);
348  return NULL;
349  }
350  log_rdf(domain->dname, "+DD", 6);
351  return domain;
352 }
353 
354 
359 static domain_type*
360 zonedata_del_domain_fixup(ldns_rbtree_t* tree, domain_type* domain)
361 {
362  domain_type* del_domain = NULL;
363  ldns_rbnode_t* del_node = LDNS_RBTREE_NULL;
364 
365  ods_log_assert(tree);
366  ods_log_assert(domain);
367  ods_log_assert(domain->dname);
368 
369  del_node = ldns_rbtree_search(tree, (const void*)domain->dname);
370  if (del_node) {
371  del_node = ldns_rbtree_delete(tree, (const void*)domain->dname);
372  del_domain = (domain_type*) del_node->data;
373  domain_cleanup(del_domain);
374  free((void*)del_node);
375  return NULL;
376  } else {
377  log_rdf(domain->dname, "unable to del domain, not found", 1);
378  }
379  return domain;
380 }
381 
382 
389 {
390  if (!domain) {
391  ods_log_error("[%s] unable to delete domain: no domain", zd_str);
392  return NULL;
393  }
394  ods_log_assert(domain);
395  ods_log_assert(domain->dname);
396 
397  if (!zd || !zd->domains) {
398  log_rdf(domain->dname, "unable to delete domain, no zonedata", 1);
399  return domain;
400  }
401  ods_log_assert(zd);
402  ods_log_assert(zd->domains);
403 
404  if (domain->denial && zonedata_del_denial(zd, domain->denial) != NULL) {
405  log_rdf(domain->dname, "unable to delete domain, failed to delete "
406  "denial of existence data point", 1);
407  return domain;
408  }
409  domain->denial = NULL;
410  log_rdf(domain->dname, "-DD", 6);
411  return zonedata_del_domain_fixup(zd->domains, domain);
412 }
413 
414 
419 static denial_type*
420 zonedata_denial_search(ldns_rbtree_t* tree, ldns_rdf* dname)
421 {
422  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
423 
424  if (!tree || !dname) {
425  return NULL;
426  }
427  node = ldns_rbtree_search(tree, dname);
428  if (node && node != LDNS_RBTREE_NULL) {
429  return (denial_type*) node->data;
430  }
431  return NULL;
432 }
433 
434 
441 {
442  if (!zd) return NULL;
443 
444  return zonedata_denial_search(zd->denial_chain, dname);
445 }
446 
447 
452 static ldns_rdf*
453 dname_hash(ldns_rdf* dname, ldns_rdf* apex, nsec3params_type* nsec3params)
454 {
455  ldns_rdf* hashed_ownername = NULL;
456  ldns_rdf* hashed_label = NULL;
457 
458  ods_log_assert(dname);
459  ods_log_assert(apex);
460  ods_log_assert(nsec3params);
461 
466  hashed_label = ldns_nsec3_hash_name(dname, nsec3params->algorithm,
467  nsec3params->iterations, nsec3params->salt_len,
468  nsec3params->salt_data);
469  if (!hashed_label) {
470  log_rdf(dname, "unable to hash dname, hash failed", 1);
471  return NULL;
472  }
473  hashed_ownername = ldns_dname_cat_clone((const ldns_rdf*) hashed_label,
474  (const ldns_rdf*) apex);
475  if (!hashed_ownername) {
476  log_rdf(dname, "unable to hash dname, concat apex failed", 1);
477  return NULL;
478  }
479  ldns_rdf_deep_free(hashed_label);
480  return hashed_ownername;
481 }
482 
483 
489 zonedata_add_denial(zonedata_type* zd, domain_type* domain, ldns_rdf* apex,
490  nsec3params_type* nsec3params)
491 {
492  ldns_rbnode_t* new_node = LDNS_RBTREE_NULL;
493  ldns_rbnode_t* prev_node = LDNS_RBTREE_NULL;
494  ldns_rdf* owner = NULL;
495  denial_type* denial = NULL;
496  denial_type* prev_denial = NULL;
497 
498  if (!domain) {
499  ods_log_error("[%s] unable to add denial of existence data point: "
500  "no domain", zd_str);
501  return ODS_STATUS_ASSERT_ERR;
502  }
503  ods_log_assert(domain);
504 
505  if (!zd || !zd->denial_chain) {
506  log_rdf(domain->dname, "unable to add denial of existence data "
507  "point for domain, no denial chain", 1);
508  return ODS_STATUS_ASSERT_ERR;
509  }
510  ods_log_assert(zd);
512 
513  if (!apex) {
514  log_rdf(domain->dname, "unable to add denial of existence data "
515  "point for domain, apex unknown", 1);
516  return ODS_STATUS_ASSERT_ERR;
517  }
518  ods_log_assert(apex);
519 
520  /* nsec or nsec3 */
521  if (nsec3params) {
522  owner = dname_hash(domain->dname, apex, nsec3params);
523  if (!owner) {
524  log_rdf(domain->dname, "unable to add denial of existence data "
525  "point for domain, dname hash failed", 1);
526  return ODS_STATUS_ERR;
527  }
528  } else {
529  owner = ldns_rdf_clone(domain->dname);
530  }
531  /* lookup */
532  if (zonedata_lookup_denial(zd, owner) != NULL) {
533  log_rdf(domain->dname, "unable to add denial of existence for "
534  "domain, data point exists", 1);
536  }
537  /* create */
538  denial = denial_create(owner);
539  new_node = denial2node(denial);
540  ldns_rdf_deep_free(owner);
541  /* insert */
542  if (!ldns_rbtree_insert(zd->denial_chain, new_node)) {
543  log_rdf(domain->dname, "unable to add denial of existence for "
544  "domain, insert failed", 1);
545  free((void*)new_node);
546  denial_cleanup(denial);
547  return ODS_STATUS_ERR;
548  }
549  /* denial of existence data point added */
550  denial->bitmap_changed = 1;
551  denial->nxt_changed = 1;
552  prev_node = ldns_rbtree_previous(new_node);
553  if (!prev_node || prev_node == LDNS_RBTREE_NULL) {
554  prev_node = ldns_rbtree_last(zd->denial_chain);
555  }
556  ods_log_assert(prev_node);
557  prev_denial = (denial_type*) prev_node->data;
558  ods_log_assert(prev_denial);
559  prev_denial->nxt_changed = 1;
560  domain->denial = denial;
561  domain->denial->domain = domain; /* back reference */
562  return ODS_STATUS_OK;
563 }
564 
565 
570 static denial_type*
571 zonedata_del_denial_fixup(ldns_rbtree_t* tree, denial_type* denial)
572 {
573  denial_type* del_denial = NULL;
574  denial_type* prev_denial = NULL;
575  ldns_rbnode_t* prev_node = LDNS_RBTREE_NULL;
576  ldns_rbnode_t* del_node = LDNS_RBTREE_NULL;
577  ods_status status = ODS_STATUS_OK;
578 
579  ods_log_assert(tree);
580  ods_log_assert(denial);
581  ods_log_assert(denial->owner);
582 
583  del_node = ldns_rbtree_search(tree, (const void*)denial->owner);
584  if (del_node) {
589  prev_node = ldns_rbtree_previous(del_node);
590  if (!prev_node || prev_node == LDNS_RBTREE_NULL) {
591  prev_node = ldns_rbtree_last(tree);
592  }
593  ods_log_assert(prev_node);
594  ods_log_assert(prev_node->data);
595  prev_denial = (denial_type*) prev_node->data;
596  prev_denial->nxt_changed = 1;
597 
598  /* delete old NSEC RR(s) */
599  if (denial->rrset) {
600  status = rrset_wipe_out(denial->rrset);
601  if (status != ODS_STATUS_OK) {
602  ods_log_alert("[%s] unable to del denial of existence data "
603  "point: failed to wipe out NSEC RRset", zd_str);
604  return denial;
605  }
606  status = rrset_commit(denial->rrset);
607  if (status != ODS_STATUS_OK) {
608  ods_log_alert("[%s] unable to del denial of existence data "
609  "point: failed to commit NSEC RRset", zd_str);
610  return denial;
611  }
612  }
613 
614  del_node = ldns_rbtree_delete(tree, (const void*)denial->owner);
615  del_denial = (denial_type*) del_node->data;
616  denial_cleanup(del_denial);
617  free((void*)del_node);
618  return NULL;
619  } else {
620  log_rdf(denial->owner, "unable to del denial of existence data "
621  "point, not found", 1);
622  }
623  return denial;
624 }
625 
626 
633 {
634  if (!denial) {
635  ods_log_error("[%s] unable to delete denial of existence data "
636  "point: no data point", zd_str);
637  return NULL;
638  }
639  ods_log_assert(denial);
640 
641  if (!zd || !zd->denial_chain) {
642  log_rdf(denial->owner, "unable to delete denial of existence data "
643  "point, no zone data", 1);
644  return denial;
645  }
646  ods_log_assert(zd);
648 
649  return zonedata_del_denial_fixup(zd->denial_chain, denial);
650 }
651 
652 
659 {
660  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
661  domain_type* domain = NULL;
662  ods_status status = ODS_STATUS_OK;
663 
664  if (!zd || !zd->domains) {
665  return status;
666  }
667  if (zd->domains->root != LDNS_RBTREE_NULL) {
668  node = ldns_rbtree_first(zd->domains);
669  }
670  while (node && node != LDNS_RBTREE_NULL) {
671  domain = (domain_type*) node->data;
672  status = domain_diff(domain, kl);
673  if (status != ODS_STATUS_OK) {
674  return status;
675  }
676  node = ldns_rbtree_next(node);
677  }
678  return status;
679 }
680 
681 
688 {
689  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
690  ldns_rbnode_t* nxtnode = LDNS_RBTREE_NULL;
691  ldns_rbnode_t* tmpnode = LDNS_RBTREE_NULL;
692  domain_type* domain = NULL;
693  domain_type* nxtdomain = NULL;
694  ods_status status = ODS_STATUS_OK;
695 
696  if (!zd || !zd->domains) {
697  return ODS_STATUS_OK;
698  }
699  if (zd->domains->root != LDNS_RBTREE_NULL) {
700  node = ldns_rbtree_last(zd->domains);
701  }
702  while (node && node != LDNS_RBTREE_NULL) {
703  domain = (domain_type*) node->data;
704  status = domain_commit(domain);
705  if (status != ODS_STATUS_OK) {
706  return status;
707  }
708  tmpnode = node;
709  node = ldns_rbtree_previous(node);
710 
711  /* delete memory if empty leaf domain */
712  if (domain_count_rrset(domain) <= 0) {
713  /* empty domain */
714  nxtnode = ldns_rbtree_next(tmpnode);
715  nxtdomain = NULL;
716  if (nxtnode && nxtnode != LDNS_RBTREE_NULL) {
717  nxtdomain = (domain_type*) nxtnode->data;
718  }
719  if (!nxtdomain ||
720  !ldns_dname_is_subdomain(nxtdomain->dname, domain->dname)) {
721  /* leaf domain */
722  if (zonedata_del_domain(zd, domain) != NULL) {
723  ods_log_warning("[%s] unable to delete obsoleted "
724  "domain", zd_str);
725  return ODS_STATUS_ERR;
726  }
727  }
728  } /* if (domain_count_rrset(domain) <= 0) */
729  }
730  return status;
731 }
732 
733 
738 void
740 {
741  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
742  domain_type* domain = NULL;
743 
744  if (!zd || !zd->domains) {
745  return;
746  }
747  if (zd->domains->root != LDNS_RBTREE_NULL) {
748  node = ldns_rbtree_first(zd->domains);
749  }
750  while (node && node != LDNS_RBTREE_NULL) {
751  domain = (domain_type*) node->data;
752  domain_rollback(domain);
753  node = ldns_rbtree_next(node);
754  }
755  return;
756 }
757 
758 
763 static int
764 domain_ent2glue(ldns_rbnode_t* node)
765 {
766  ldns_rbnode_t* nextnode = LDNS_RBTREE_NULL;
767  domain_type* nextdomain = NULL;
768  domain_type* domain = NULL;
769  ods_log_assert(node && node != LDNS_RBTREE_NULL);
770  domain = (domain_type*) node->data;
771  if (domain->dstatus == DOMAIN_STATUS_ENT) {
772  ods_log_assert(domain_count_rrset(domain) == 0);
773  nextnode = ldns_rbtree_next(node);
774  while (nextnode && nextnode != LDNS_RBTREE_NULL) {
775  nextdomain = (domain_type*) nextnode->data;
776  if (!ldns_dname_is_subdomain(nextdomain->dname, domain->dname)) {
777  /* we are done, no non-glue found */
778  return 1;
779  }
780  if (nextdomain->dstatus != DOMAIN_STATUS_OCCLUDED &&
781  nextdomain->dstatus != DOMAIN_STATUS_ENT &&
782  nextdomain->dstatus != DOMAIN_STATUS_NONE) {
783  /* found non-glue */
784  return 0;
785  }
786  nextnode = ldns_rbtree_next(nextnode);
787  }
788  } else {
789  /* no empty non-terminal */
790  ods_log_assert(domain_count_rrset(domain) != 0);
791  return 0;
792  }
793  /* no non-glue found */
794  return 1;
795 }
796 
797 
802 static int
803 domain_ent2unsigned(ldns_rbnode_t* node)
804 {
805  ldns_rbnode_t* nextnode = LDNS_RBTREE_NULL;
806  domain_type* nextdomain = NULL;
807  domain_type* domain = NULL;
808  ods_log_assert(node && node != LDNS_RBTREE_NULL);
809  domain = (domain_type*) node->data;
810  if (domain->dstatus == DOMAIN_STATUS_ENT) {
811  ods_log_assert(domain_count_rrset(domain) == 0);
812  nextnode = ldns_rbtree_next(node);
813  while (nextnode && nextnode != LDNS_RBTREE_NULL) {
814  nextdomain = (domain_type*) nextnode->data;
815  if (!ldns_dname_is_subdomain(nextdomain->dname, domain->dname)) {
816  /* we are done, no unsigned delegation found */
817  return 1;
818  }
819  if (nextdomain->dstatus != DOMAIN_STATUS_OCCLUDED &&
820  nextdomain->dstatus != DOMAIN_STATUS_ENT &&
821  nextdomain->dstatus != DOMAIN_STATUS_NS &&
822  nextdomain->dstatus != DOMAIN_STATUS_NONE) {
823  /* found data that has to be signed */
824  return 0;
825  }
826  nextnode = ldns_rbtree_next(nextnode);
827  }
828  } else {
829  /* no empty non-terminal */
830  ods_log_assert(domain_count_rrset(domain) != 0);
831  return 0;
832  }
833  /* no unsigned delegation found */
834  return 1;
835 }
836 
837 
842 static ods_status
843 domain_entize(zonedata_type* zd, domain_type* domain, ldns_rdf* apex)
844 {
845  ldns_rdf* parent_rdf = NULL;
846  domain_type* parent_domain = NULL;
847 
848  ods_log_assert(apex);
849  ods_log_assert(domain);
850  ods_log_assert(domain->dname);
851  ods_log_assert(zd);
852  ods_log_assert(zd->domains);
853 
854  if (domain->parent) {
855  /* domain already has parent */
856  return ODS_STATUS_OK;
857  }
858 
859  while (domain && ldns_dname_is_subdomain(domain->dname, apex) &&
860  ldns_dname_compare(domain->dname, apex) != 0) {
861 
869  parent_rdf = ldns_dname_left_chop(domain->dname);
870  if (!parent_rdf) {
871  log_rdf(domain->dname, "unable to entize domain, left chop "
872  "failed", 1);
873  return ODS_STATUS_ERR;
874  }
875  ods_log_assert(parent_rdf);
876 
877  parent_domain = zonedata_lookup_domain(zd, parent_rdf);
878  if (!parent_domain) {
879  parent_domain = domain_create(parent_rdf);
880  ldns_rdf_deep_free(parent_rdf);
881  if (!parent_domain) {
882  log_rdf(domain->dname, "unable to entize domain, create "
883  "parent failed", 1);
884  return ODS_STATUS_ERR;
885  }
886  ods_log_assert(parent_domain);
887  if (zonedata_add_domain(zd, parent_domain) == NULL) {
888  log_rdf(domain->dname, "unable to entize domain, add parent "
889  "failed", 1);
890  domain_cleanup(parent_domain);
891  return ODS_STATUS_ERR;
892  }
893  parent_domain->dstatus = DOMAIN_STATUS_ENT;
894  domain->parent = parent_domain;
895  /* continue with the parent domain */
896  domain = parent_domain;
897  } else {
898  ldns_rdf_deep_free(parent_rdf);
899  domain->parent = parent_domain;
900  /* we are done with this domain */
901  domain = NULL;
902  }
903  }
904  return ODS_STATUS_OK;
905 }
906 
907 
913 zonedata_entize(zonedata_type* zd, ldns_rdf* apex)
914 {
915  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
916  ods_status status = ODS_STATUS_OK;
917  domain_type* domain = NULL;
918 
919  if (!zd || !zd->domains) {
920  ods_log_error("[%s] unable to entize zone data: no zone data",
921  zd_str);
922  return ODS_STATUS_ASSERT_ERR;
923  }
924  ods_log_assert(zd);
925  ods_log_assert(zd->domains);
926 
927  if (!apex) {
928  ods_log_error("[%s] unable to entize zone data: no zone apex",
929  zd_str);
930  return ODS_STATUS_ASSERT_ERR;
931  }
932  ods_log_assert(apex);
933 
934  node = ldns_rbtree_first(zd->domains);
935  while (node && node != LDNS_RBTREE_NULL) {
936  domain = (domain_type*) node->data;
937  status = domain_entize(zd, domain, apex);
938  if (status != ODS_STATUS_OK) {
939  ods_log_error("[%s] unable to entize zone data: entize domain "
940  "failed", zd_str);
941  return status;
942  }
943  domain_dstatus(domain);
944  node = ldns_rbtree_next(node);
945  }
946  return ODS_STATUS_OK;
947 }
948 
949 
955 zonedata_nsecify(zonedata_type* zd, ldns_rr_class klass, uint32_t ttl,
956  uint32_t* num_added)
957 {
958  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
959  ldns_rbnode_t* nxt_node = LDNS_RBTREE_NULL;
960  ods_status status = ODS_STATUS_OK;
961  domain_type* domain = NULL;
962  domain_type* apex = NULL;
963  denial_type* denial = NULL;
964  denial_type* nxt = NULL;
965  size_t nsec_added = 0;
966 
967  if (!zd || !zd->domains) {
968  return ODS_STATUS_OK;
969  }
970  ods_log_assert(zd);
971  ods_log_assert(zd->domains);
972 
973  node = ldns_rbtree_first(zd->domains);
974  while (node && node != LDNS_RBTREE_NULL) {
975  domain = (domain_type*) node->data;
976  if (domain->dstatus == DOMAIN_STATUS_APEX) {
977  apex = domain;
978  }
979  /* don't do glue-only or empty domains */
980  if (domain->dstatus == DOMAIN_STATUS_NONE ||
981  domain->dstatus == DOMAIN_STATUS_ENT ||
982  domain->dstatus == DOMAIN_STATUS_OCCLUDED ||
983  domain_count_rrset(domain) <= 0) {
984  if (domain_count_rrset(domain)) {
985  log_rdf(domain->dname, "nsecify: don't do glue domain", 6);
986  } else {
987  log_rdf(domain->dname, "nsecify: don't do empty domain", 6);
988  }
989  if (domain->denial) {
990  if (zonedata_del_denial(zd, domain->denial) != NULL) {
991  ods_log_warning("[%s] unable to nsecify: failed to "
992  "delete denial of existence data point", zd_str);
993  return ODS_STATUS_ERR;
994  }
995  domain->denial = NULL;
996  }
997  node = ldns_rbtree_next(node);
998  continue;
999  }
1000  if (!apex) {
1001  ods_log_alert("[%s] unable to nsecify: apex unknown", zd_str);
1002  return ODS_STATUS_ASSERT_ERR;
1003  }
1004 
1005  /* add the denial of existence */
1006  if (!domain->denial) {
1007  status = zonedata_add_denial(zd, domain, apex->dname, NULL);
1008  if (status != ODS_STATUS_OK) {
1009  log_rdf(domain->dname, "unable to nsecify: failed to add "
1010  "denial of existence for domain", 1);
1011  return status;
1012  }
1013  nsec_added++;
1014  }
1015  node = ldns_rbtree_next(node);
1016  }
1017 
1019  node = ldns_rbtree_first(zd->denial_chain);
1020  while (node && node != LDNS_RBTREE_NULL) {
1021  denial = (denial_type*) node->data;
1022  nxt_node = ldns_rbtree_next(node);
1023  if (!nxt_node || nxt_node == LDNS_RBTREE_NULL) {
1024  nxt_node = ldns_rbtree_first(zd->denial_chain);
1025  }
1026  nxt = (denial_type*) nxt_node->data;
1027 
1028  status = denial_nsecify(denial, nxt, ttl, klass);
1029  if (status != ODS_STATUS_OK) {
1030  ods_log_error("[%s] unable to nsecify: failed to add NSEC record",
1031  zd_str);
1032  return status;
1033  }
1034  node = ldns_rbtree_next(node);
1035  }
1036  if (num_added) {
1037  *num_added = nsec_added;
1038  }
1039  return ODS_STATUS_OK;
1040 }
1041 
1042 
1047 ods_status
1048 zonedata_nsecify3(zonedata_type* zd, ldns_rr_class klass,
1049  uint32_t ttl, nsec3params_type* nsec3params, uint32_t* num_added)
1050 {
1051  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
1052  ldns_rbnode_t* nxt_node = LDNS_RBTREE_NULL;
1053  ods_status status = ODS_STATUS_OK;
1054  domain_type* domain = NULL;
1055  domain_type* apex = NULL;
1056  denial_type* denial = NULL;
1057  denial_type* nxt = NULL;
1058  size_t nsec3_added = 0;
1059 
1060  if (!zd || !zd->domains) {
1061  return ODS_STATUS_OK;
1062  }
1063  ods_log_assert(zd);
1064  ods_log_assert(zd->domains);
1065 
1066  if (!nsec3params) {
1067  ods_log_error("[%s] unable to nsecify3: no nsec3 paramaters", zd_str);
1068  return ODS_STATUS_ASSERT_ERR;
1069  }
1070  ods_log_assert(nsec3params);
1071 
1072  node = ldns_rbtree_first(zd->domains);
1073  while (node && node != LDNS_RBTREE_NULL) {
1074  domain = (domain_type*) node->data;
1075  if (domain->dstatus == DOMAIN_STATUS_APEX) {
1076  apex = domain;
1077  }
1078 
1079  /* don't do glue-only domains */
1080  if (domain->dstatus == DOMAIN_STATUS_NONE ||
1081  domain->dstatus == DOMAIN_STATUS_OCCLUDED ||
1082  domain_ent2glue(node)) {
1083  log_rdf(domain->dname, "nsecify3: don't do glue domain" , 6);
1084  if (domain->denial) {
1085  if (zonedata_del_denial(zd, domain->denial) != NULL) {
1086  ods_log_error("[%s] unable to nsecify3: failed to "
1087  "delete denial of existence data point", zd_str);
1088  return ODS_STATUS_ERR;
1089  }
1090  domain->denial = NULL;
1091  }
1092  node = ldns_rbtree_next(node);
1093  continue;
1094  }
1095  /* Opt-Out? */
1096  if (nsec3params->flags) {
1097  /* If Opt-Out is being used, owner names of unsigned delegations
1098  MAY be excluded. */
1099  if (domain->dstatus == DOMAIN_STATUS_NS ||
1100  domain_ent2unsigned(node)) {
1101  if (domain->dstatus == DOMAIN_STATUS_NS) {
1102  log_rdf(domain->dname, "nsecify3: opt-out (unsigned "
1103  "delegation)", 5);
1104  } else {
1105  log_rdf(domain->dname, "nsecify3: opt-out (empty "
1106  "non-terminal (to unsigned delegation))", 5);
1107  }
1108  if (domain->denial) {
1109  if (zonedata_del_denial(zd, domain->denial) != NULL) {
1110  ods_log_error("[%s] unable to nsecify3: failed to "
1111  "delete denial of existence data point", zd_str);
1112  return ODS_STATUS_ERR;
1113  }
1114  domain->denial = NULL;
1115  }
1116  node = ldns_rbtree_next(node);
1117  continue;
1118  }
1119  }
1120  if (!apex) {
1121  ods_log_alert("[%s] unable to nsecify3: apex unknown", zd_str);
1122  return ODS_STATUS_ASSERT_ERR;
1123  }
1124 
1125  /* add the denial of existence */
1126  if (!domain->denial) {
1127  status = zonedata_add_denial(zd, domain, apex->dname,
1128  nsec3params);
1129  if (status != ODS_STATUS_OK) {
1130  log_rdf(domain->dname, "unable to nsecify3: failed to add "
1131  "denial of existence for domain", 1);
1132  return status;
1133  }
1134  nsec3_added++;
1135  }
1136 
1137  /* The Next Hashed Owner Name field is left blank for the moment. */
1138 
1146  /* [TODO] */
1156  node = ldns_rbtree_next(node);
1157  }
1158 
1160  node = ldns_rbtree_first(zd->denial_chain);
1161  while (node && node != LDNS_RBTREE_NULL) {
1162  denial = (denial_type*) node->data;
1163  nxt_node = ldns_rbtree_next(node);
1164  if (!nxt_node || nxt_node == LDNS_RBTREE_NULL) {
1165  nxt_node = ldns_rbtree_first(zd->denial_chain);
1166  }
1167  nxt = (denial_type*) nxt_node->data;
1168 
1169  status = denial_nsecify3(denial, nxt, ttl, klass, nsec3params);
1170  if (status != ODS_STATUS_OK) {
1171  ods_log_error("[%s] unable to nsecify3: failed to add NSEC3 "
1172  "record", zd_str);
1173  return status;
1174  }
1175  node = ldns_rbtree_next(node);
1176  }
1177  if (num_added) {
1178  *num_added = nsec3_added;
1179  }
1180  return ODS_STATUS_OK;
1181 }
1182 
1183 
1184 static uint32_t
1185 max(uint32_t a, uint32_t b)
1186 {
1187  return (a<b?b:a);
1188 }
1189 
1190 
1195 ods_status
1197  const char* zone_name)
1198 {
1199  uint32_t soa = 0;
1200  uint32_t prev = 0;
1201  uint32_t update = 0;
1202 
1203  ods_log_assert(zd);
1204  ods_log_assert(sc);
1205  ods_log_assert(zone_name);
1206 
1207  prev = max(zd->outbound_serial, zd->inbound_serial);
1208  ods_log_debug("[%s] zone %s update serial: in=%u internal=%u out=%u now=%u",
1209  zd_str, zone_name, zd->inbound_serial, zd->internal_serial,
1210  zd->outbound_serial, (uint32_t) time_now());
1211 
1212  if (!sc->soa_serial) {
1213  ods_log_error("[%s] no serial type given", zd_str);
1214  return ODS_STATUS_ERR;
1215  }
1216  if (zd->force_serial) {
1217  soa = zd->enforced_serial;
1218  if (!DNS_SERIAL_GT(soa, prev)) {
1219  ods_log_warning("[%s] zone %s unable to enforce serial: %u does not "
1220  " increase %u", zd_str, zone_name, soa, prev);
1221  soa = prev + 1;
1222  } else {
1223  ods_log_info("[%s] zone %s enforcing serial %u", zd_str, zone_name,
1224  soa);
1225  }
1226  zd->force_serial = 0;
1227  } else if (ods_strcmp(sc->soa_serial, "unixtime") == 0) {
1228  soa = (uint32_t) time_now();
1229  if (!zd->initialized) {
1230  if (!DNS_SERIAL_GT(soa, zd->inbound_serial)) {
1231  ods_log_warning("[%s] zone %s unable to use unixtime %u as "
1232  "serial: not greater than inbound serial %u", zd_str,
1233  zone_name, soa, zd->inbound_serial);
1234  soa = zd->inbound_serial + 1;
1235  }
1236  } else if (!DNS_SERIAL_GT(soa, prev)) {
1237  soa = prev + 1;
1238  }
1239  } else if (strncmp(sc->soa_serial, "counter", 7) == 0) {
1240  soa = zd->inbound_serial;
1241  if (!zd->initialized) {
1242  soa = zd->inbound_serial + 1;
1243  } else if (!DNS_SERIAL_GT(soa, prev)) {
1244  soa = prev + 1;
1245  }
1246  } else if (strncmp(sc->soa_serial, "datecounter", 11) == 0) {
1247  soa = (uint32_t) time_datestamp(0, "%Y%m%d", NULL) * 100;
1248  if (!zd->initialized) {
1249  if (!DNS_SERIAL_GT(soa, zd->inbound_serial)) {
1250  ods_log_warning("[%s] zone %s unable to use datecounter %u as "
1251  "serial: not greater than inbound serial %u", zd_str,
1252  zone_name, soa, zd->inbound_serial);
1253  soa = zd->inbound_serial + 1;
1254  }
1255  } else if (!DNS_SERIAL_GT(soa, prev)) {
1256  soa = prev + 1;
1257  }
1258  } else if (strncmp(sc->soa_serial, "keep", 4) == 0) {
1259  prev = zd->outbound_serial;
1260  soa = zd->inbound_serial;
1261  if (zd->initialized && !DNS_SERIAL_GT(soa, prev)) {
1262  ods_log_error("[%s] zone %s cannot keep SOA SERIAL from input zone "
1263  "(%u): previous output SOA SERIAL is %u", zd_str, zone_name,
1264  soa, prev);
1265  return ODS_STATUS_CONFLICT_ERR;
1266  }
1267  } else {
1268  ods_log_error("[%s] zone %s unknown serial type %s", zd_str, zone_name,
1269  sc->soa_serial);
1270  return ODS_STATUS_ERR;
1271  }
1272 
1273  /* serial is stored in 32 bits */
1274  update = soa - prev;
1275  if (update > 0x7FFFFFFF) {
1276  update = 0x7FFFFFFF;
1277  }
1278 
1279  if (!zd->initialized) {
1280  zd->internal_serial = soa;
1281  } else {
1282  zd->internal_serial = prev + update; /* automatically does % 2^32 */
1283  }
1284  ods_log_debug("[%s] zone %s update serial: %u + %u = %u", zd_str, zone_name,
1285  prev, update, zd->internal_serial);
1286  return ODS_STATUS_OK;
1287 }
1288 
1289 
1294 ods_status
1296 {
1297  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
1298  domain_type* domain = NULL;
1299  ods_status status = ODS_STATUS_OK;
1300 
1301  if (!zd || !zd->domains) {
1302  return ODS_STATUS_OK;
1303  }
1304  if (zd->domains->root != LDNS_RBTREE_NULL) {
1305  node = ldns_rbtree_first(zd->domains);
1306  }
1307  while (node && node != LDNS_RBTREE_NULL) {
1308  domain = (domain_type*) node->data;
1309  status = domain_queue(domain, q, worker);
1310  if (status != ODS_STATUS_OK) {
1311  return status;
1312  }
1313  node = ldns_rbtree_next(node);
1314  }
1315  return status;
1316 }
1317 
1318 
1323 static int
1324 zonedata_examine_domain_is_occluded(zonedata_type* zd, domain_type* domain,
1325  ldns_rdf* apex)
1326 {
1327  ldns_rdf* parent_rdf = NULL;
1328  ldns_rdf* next_rdf = NULL;
1329  domain_type* parent_domain = NULL;
1330  char* str_name = NULL;
1331  char* str_parent = NULL;
1332 
1333  ods_log_assert(apex);
1334  ods_log_assert(domain);
1335  ods_log_assert(domain->dname);
1336  ods_log_assert(zd);
1337  ods_log_assert(zd->domains);
1338 
1339  if (ldns_dname_compare(domain->dname, apex) == 0) {
1340  return 0;
1341  }
1342 
1343  if (domain_examine_valid_zonecut(domain) != 0) {
1344  log_rdf(domain->dname, "occluded (non-glue non-DS) data at NS", 2);
1345  return 1;
1346  }
1347 
1348  parent_rdf = ldns_dname_left_chop(domain->dname);
1349  while (parent_rdf && ldns_dname_is_subdomain(parent_rdf, apex) &&
1350  ldns_dname_compare(parent_rdf, apex) != 0) {
1351 
1352  parent_domain = zonedata_lookup_domain(zd, parent_rdf);
1353  next_rdf = ldns_dname_left_chop(parent_rdf);
1354  ldns_rdf_deep_free(parent_rdf);
1355 
1356  if (parent_domain) {
1357  /* check for DNAME or NS */
1358  if (domain_examine_data_exists(parent_domain, LDNS_RR_TYPE_DNAME,
1359  0) && domain_examine_data_exists(domain, 0, 0)) {
1360  /* data below DNAME */
1361  str_name = ldns_rdf2str(domain->dname);
1362  str_parent = ldns_rdf2str(parent_domain->dname);
1363  ods_log_warning("[%s] occluded data at %s (below %s DNAME)",
1364  zd_str, str_name, str_parent);
1365  free((void*)str_name);
1366  free((void*)str_parent);
1367  return 1;
1368  } else if (domain_examine_data_exists(parent_domain,
1369  LDNS_RR_TYPE_NS, 0) &&
1370  domain_examine_data_exists(domain, 0, 1)) {
1371  /* data (non-glue) below NS */
1372  str_name = ldns_rdf2str(domain->dname);
1373  str_parent = ldns_rdf2str(parent_domain->dname);
1374  ods_log_warning("[%s] occluded (non-glue) data at %s (below "
1375  "%s NS)", zd_str, str_name, str_parent);
1376  free((void*)str_name);
1377  free((void*)str_parent);
1378  return 1;
1379 /* allow for now (root zone has it)
1380  } else if (domain_examine_data_exists(parent_domain,
1381  LDNS_RR_TYPE_NS, 0) &&
1382  domain_examine_data_exists(domain, 0, 0) &&
1383  !domain_examine_ns_rdata(parent_domain, domain->dname)) {
1384  str_name = ldns_rdf2str(domain->dname);
1385  str_parent = ldns_rdf2str(parent_domain->dname);
1386  ods_log_warning("[%s] occluded data at %s (below %s NS)",
1387  zd_str, str_name, str_parent);
1388  free((void*)str_name);
1389  free((void*)str_parent);
1390  return 1;
1391 */
1392  }
1393  }
1394  parent_rdf = next_rdf;
1395  }
1396  if (parent_rdf) {
1397  ldns_rdf_deep_free(parent_rdf);
1398  }
1399  return 0;
1400 }
1401 
1402 
1407 ods_status
1408 zonedata_examine(zonedata_type* zd, ldns_rdf* apex, adapter_mode mode)
1409 {
1410  int result = 0;
1411  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
1412  domain_type* domain = NULL;
1413  ods_status status = ODS_STATUS_OK;
1414 
1415  if (!zd || !zd->domains) {
1416  /* no zone data, no error */
1417  return ODS_STATUS_OK;
1418  }
1419  ods_log_assert(zd);
1420  ods_log_assert(zd->domains);
1421 
1422  if (zd->domains->root != LDNS_RBTREE_NULL) {
1423  node = ldns_rbtree_first(zd->domains);
1424  }
1425  while (node && node != LDNS_RBTREE_NULL) {
1426  domain = (domain_type*) node->data;
1427  result =
1428  /* Thou shall not have other data next to CNAME */
1429  domain_examine_rrset_is_alone(domain, LDNS_RR_TYPE_CNAME) &&
1430  /* Thou shall have at most one CNAME per name */
1431  domain_examine_rrset_is_singleton(domain, LDNS_RR_TYPE_CNAME) &&
1432  /* Thou shall have at most one DNAME per name */
1433  domain_examine_rrset_is_singleton(domain, LDNS_RR_TYPE_DNAME);
1434  if (!result) {
1435  status = ODS_STATUS_ERR;
1436  }
1437 
1438  if (mode == ADAPTER_FILE) {
1439  result =
1440  /* Thou shall not have occluded data in your zone file */
1441  zonedata_examine_domain_is_occluded(zd, domain, apex);
1442  if (result) {
1443  ; /* just warn if there is occluded data */
1444  }
1445  }
1446  node = ldns_rbtree_next(node);
1447  }
1448  return status;
1449 }
1450 
1451 
1456 void
1458 {
1459  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
1460  denial_type* denial = NULL;
1461 
1462  if (zd && zd->denial_chain) {
1463  node = ldns_rbtree_first(zd->denial_chain);
1464  while (node && node != LDNS_RBTREE_NULL) {
1465  denial = (denial_type*) node->data;
1466  if (denial->rrset) {
1467  /* [TODO] IXFR delete NSEC */
1468  rrset_cleanup(denial->rrset);
1469  denial->rrset = NULL;
1470  }
1471  node = ldns_rbtree_next(node);
1472  }
1473  }
1474  return;
1475 }
1476 
1477 
1482 static void
1483 domain_delfunc(ldns_rbnode_t* elem)
1484 {
1485  domain_type* domain = NULL;
1486 
1487  if (elem && elem != LDNS_RBTREE_NULL) {
1488  domain = (domain_type*) elem->data;
1489  domain_delfunc(elem->left);
1490  domain_delfunc(elem->right);
1491 
1492  domain_cleanup(domain);
1493  free((void*)elem);
1494  }
1495  return;
1496 }
1497 
1498 
1503 static void
1504 denial_delfunc(ldns_rbnode_t* elem)
1505 {
1506  denial_type* denial = NULL;
1507  domain_type* domain = NULL;
1508 
1509 
1510  if (elem && elem != LDNS_RBTREE_NULL) {
1511  denial = (denial_type*) elem->data;
1512  denial_delfunc(elem->left);
1513  denial_delfunc(elem->right);
1514 
1515  domain = denial->domain;
1516  if (domain) {
1517  domain->denial = NULL;
1518  }
1519  denial_cleanup(denial);
1520 
1521  free((void*)elem);
1522  }
1523  return;
1524 }
1525 
1526 
1531 static void
1532 zonedata_cleanup_domains(zonedata_type* zd)
1533 {
1534  if (zd && zd->domains) {
1535  domain_delfunc(zd->domains->root);
1536  ldns_rbtree_free(zd->domains);
1537  zd->domains = NULL;
1538  }
1539  return;
1540 }
1541 
1542 
1547 void
1549 {
1550  if (zd && zd->denial_chain) {
1551  denial_delfunc(zd->denial_chain->root);
1552  ldns_rbtree_free(zd->denial_chain);
1553  zd->denial_chain = NULL;
1554  }
1555  return;
1556 }
1557 
1558 
1563 void
1565 {
1566  allocator_type* allocator;
1567 
1568  if (!zd) {
1569  return;
1570  }
1572  zonedata_cleanup_domains(zd);
1573  allocator = zd->allocator;
1574  allocator_deallocate(allocator, (void*) zd);
1575  return;
1576 }
1577 
1578 
1583 void
1585 {
1586  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
1587  domain_type* domain = NULL;
1588 
1589  if (!fd || !zd) {
1590  return;
1591  }
1592 
1593  node = ldns_rbtree_first(zd->domains);
1594  while (node && node != LDNS_RBTREE_NULL) {
1595  domain = (domain_type*) node->data;
1596  domain_backup(fd, domain);
1597  node = ldns_rbtree_next(node);
1598  }
1599  fprintf(fd, ";;\n");
1600  return;
1601 }
1602 
1603 
1608 ods_status
1610 {
1611  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
1612  domain_type* domain = NULL;
1613 
1614  if (!fd) {
1615  ods_log_error("[%s] unable to print zone data: no file descriptor",
1616  zd_str);
1617  return ODS_STATUS_ASSERT_ERR;
1618  }
1619  ods_log_assert(fd);
1620 
1621  if (!zd || !zd->domains) {
1622  ods_log_error("[%s] unable to print zone data: no zone data",
1623  zd_str);
1624  return ODS_STATUS_ASSERT_ERR;
1625  }
1626  ods_log_assert(zd);
1627  ods_log_assert(zd->domains);
1628 
1629  node = ldns_rbtree_first(zd->domains);
1630  if (!node || node == LDNS_RBTREE_NULL) {
1631  fprintf(fd, "; empty zone\n");
1632  return ODS_STATUS_OK;
1633  }
1634  while (node && node != LDNS_RBTREE_NULL) {
1635  domain = (domain_type*) node->data;
1636  domain_print(fd, domain);
1637  node = ldns_rbtree_next(node);
1638  }
1639  return ODS_STATUS_OK;
1640 }