OpenDNSSEC-signer  1.3.9
zonedata.c
Go to the documentation of this file.
1 /*
2  * $Id: zonedata.c 6050 2012-01-10 11:25:28Z 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->inbound_serial = 0;
188  zd->internal_serial = 0;
189  zd->outbound_serial = 0;
190  zd->default_ttl = 3600; /* TODO: configure --default-ttl option? */
191  return zd;
192 }
193 
194 
201 {
202  const char* token = NULL;
203  const char* owner = NULL;
204  int dstatus = 0;
205  ods_status status = ODS_STATUS_OK;
206  domain_type* domain = NULL;
207  ldns_rdf* rdf = NULL;
208  ldns_rbnode_t* denial_node = LDNS_RBTREE_NULL;
209 
210  ods_log_assert(zd);
211  ods_log_assert(fd);
212 
213  while (backup_read_str(fd, &token)) {
214  /* domain part */
215  if (ods_strcmp(token, ";;Domain:") == 0) {
216  if (!backup_read_check_str(fd, "name") ||
217  !backup_read_str(fd, &owner) ||
218  !backup_read_check_str(fd, "status") ||
219  !backup_read_int(fd, &dstatus)) {
220  ods_log_error("[%s] domain in backup corrupted", zd_str);
221  goto recover_domain_error;
222  }
223  /* ok, look up domain */
224  rdf = ldns_dname_new_frm_str(owner);
225  if (rdf) {
226  domain = zonedata_lookup_domain(zd, rdf);
227  ldns_rdf_deep_free(rdf);
228  rdf = NULL;
229  }
230  if (!domain) {
231  ods_log_error("[%s] domain in backup, but not in zonedata",
232  zd_str);
233  goto recover_domain_error;
234  }
235  /* lookup success */
236  status = domain_recover(domain, fd, dstatus);
237  if (status != ODS_STATUS_OK) {
238  ods_log_error("[%s] unable to recover domain", zd_str);
239  goto recover_domain_error;
240  }
241  if (domain->denial) {
242  denial_node = denial2node(domain->denial);
243  /* insert */
244  if (!ldns_rbtree_insert(zd->denial_chain, denial_node)) {
245  ods_log_error("[%s] unable to recover denial", zd_str);
246  free((void*)denial_node);
247  goto recover_domain_error;
248  }
249  denial_node = NULL;
250  }
251 
252  /* done, next domain */
253  free((void*) owner);
254  owner = NULL;
255  domain = NULL;
256  } else if (ods_strcmp(token, ";;") == 0) {
257  /* done with all zone data */
258  free((void*) token);
259  token = NULL;
260  return ODS_STATUS_OK;
261  } else {
262  /* domain corrupted */
263  ods_log_error("[%s] domain in backup corrupted", zd_str);
264  goto recover_domain_error;
265  }
266  free((void*) token);
267  token = NULL;
268  }
269 
270  if (!backup_read_check_str(fd, ODS_SE_FILE_MAGIC)) {
271  goto recover_domain_error;
272  }
273 
274  return ODS_STATUS_OK;
275 
276 recover_domain_error:
277  free((void*) owner);
278  owner = NULL;
279 
280  free((void*) token);
281  token = NULL;
282 
283  return ODS_STATUS_ERR;
284 }
285 
286 
291 static domain_type*
292 zonedata_domain_search(ldns_rbtree_t* tree, ldns_rdf* dname)
293 {
294  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
295 
296  if (!tree || !dname) {
297  return NULL;
298  }
299  node = ldns_rbtree_search(tree, dname);
300  if (node && node != LDNS_RBTREE_NULL) {
301  return (domain_type*) node->data;
302  }
303  return NULL;
304 }
305 
306 
313 {
314  if (!zd) return NULL;
315 
316  return zonedata_domain_search(zd->domains, dname);
317 }
318 
319 
326 {
327  ldns_rbnode_t* new_node = LDNS_RBTREE_NULL;
328 
329  if (!domain) {
330  ods_log_error("[%s] unable to add domain: no domain", zd_str);
331  return NULL;
332  }
333  ods_log_assert(domain);
334 
335  if (!zd || !zd->domains) {
336  log_rdf(domain->dname, "unable to add domain, no storage", 1);
337  return NULL;
338  }
339  ods_log_assert(zd);
340  ods_log_assert(zd->domains);
341 
342  new_node = domain2node(domain);
343  if (ldns_rbtree_insert(zd->domains, new_node) == NULL) {
344  log_rdf(domain->dname, "unable to add domain, already present", 1);
345  free((void*)new_node);
346  return NULL;
347  }
348  log_rdf(domain->dname, "+DD", 6);
349  return domain;
350 }
351 
352 
357 static domain_type*
358 zonedata_del_domain_fixup(ldns_rbtree_t* tree, domain_type* domain)
359 {
360  domain_type* del_domain = NULL;
361  ldns_rbnode_t* del_node = LDNS_RBTREE_NULL;
362 
363  ods_log_assert(tree);
364  ods_log_assert(domain);
365  ods_log_assert(domain->dname);
366 
367  del_node = ldns_rbtree_search(tree, (const void*)domain->dname);
368  if (del_node) {
369  del_node = ldns_rbtree_delete(tree, (const void*)domain->dname);
370  del_domain = (domain_type*) del_node->data;
371  domain_cleanup(del_domain);
372  free((void*)del_node);
373  return NULL;
374  } else {
375  log_rdf(domain->dname, "unable to del domain, not found", 1);
376  }
377  return domain;
378 }
379 
380 
387 {
388  if (!domain) {
389  ods_log_error("[%s] unable to delete domain: no domain", zd_str);
390  return NULL;
391  }
392  ods_log_assert(domain);
393  ods_log_assert(domain->dname);
394 
395  if (!zd || !zd->domains) {
396  log_rdf(domain->dname, "unable to delete domain, no zonedata", 1);
397  return domain;
398  }
399  ods_log_assert(zd);
400  ods_log_assert(zd->domains);
401 
402  if (domain->denial && zonedata_del_denial(zd, domain->denial) != NULL) {
403  log_rdf(domain->dname, "unable to delete domain, failed to delete "
404  "denial of existence data point", 1);
405  return domain;
406  }
407  domain->denial = NULL;
408  log_rdf(domain->dname, "-DD", 6);
409  return zonedata_del_domain_fixup(zd->domains, domain);
410 }
411 
412 
417 static denial_type*
418 zonedata_denial_search(ldns_rbtree_t* tree, ldns_rdf* dname)
419 {
420  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
421 
422  if (!tree || !dname) {
423  return NULL;
424  }
425  node = ldns_rbtree_search(tree, dname);
426  if (node && node != LDNS_RBTREE_NULL) {
427  return (denial_type*) node->data;
428  }
429  return NULL;
430 }
431 
432 
439 {
440  if (!zd) return NULL;
441 
442  return zonedata_denial_search(zd->denial_chain, dname);
443 }
444 
445 
450 static ldns_rdf*
451 dname_hash(ldns_rdf* dname, ldns_rdf* apex, nsec3params_type* nsec3params)
452 {
453  ldns_rdf* hashed_ownername = NULL;
454  ldns_rdf* hashed_label = NULL;
455 
456  ods_log_assert(dname);
457  ods_log_assert(apex);
458  ods_log_assert(nsec3params);
459 
464  hashed_label = ldns_nsec3_hash_name(dname, nsec3params->algorithm,
465  nsec3params->iterations, nsec3params->salt_len,
466  nsec3params->salt_data);
467  if (!hashed_label) {
468  log_rdf(dname, "unable to hash dname, hash failed", 1);
469  return NULL;
470  }
471  hashed_ownername = ldns_dname_cat_clone((const ldns_rdf*) hashed_label,
472  (const ldns_rdf*) apex);
473  if (!hashed_ownername) {
474  log_rdf(dname, "unable to hash dname, concat apex failed", 1);
475  return NULL;
476  }
477  ldns_rdf_deep_free(hashed_label);
478  return hashed_ownername;
479 }
480 
481 
487 zonedata_add_denial(zonedata_type* zd, domain_type* domain, ldns_rdf* apex,
488  nsec3params_type* nsec3params)
489 {
490  ldns_rbnode_t* new_node = LDNS_RBTREE_NULL;
491  ldns_rbnode_t* prev_node = LDNS_RBTREE_NULL;
492  ldns_rdf* owner = NULL;
493  denial_type* denial = NULL;
494  denial_type* prev_denial = NULL;
495 
496  if (!domain) {
497  ods_log_error("[%s] unable to add denial of existence data point: "
498  "no domain", zd_str);
499  return ODS_STATUS_ASSERT_ERR;
500  }
501  ods_log_assert(domain);
502 
503  if (!zd || !zd->denial_chain) {
504  log_rdf(domain->dname, "unable to add denial of existence data "
505  "point for domain, no denial chain", 1);
506  return ODS_STATUS_ASSERT_ERR;
507  }
508  ods_log_assert(zd);
510 
511  if (!apex) {
512  log_rdf(domain->dname, "unable to add denial of existence data "
513  "point for domain, apex unknown", 1);
514  return ODS_STATUS_ASSERT_ERR;
515  }
516  ods_log_assert(apex);
517 
518  /* nsec or nsec3 */
519  if (nsec3params) {
520  owner = dname_hash(domain->dname, apex, nsec3params);
521  if (!owner) {
522  log_rdf(domain->dname, "unable to add denial of existence data "
523  "point for domain, dname hash failed", 1);
524  return ODS_STATUS_ERR;
525  }
526  } else {
527  owner = ldns_rdf_clone(domain->dname);
528  }
529  /* lookup */
530  if (zonedata_lookup_denial(zd, owner) != NULL) {
531  log_rdf(domain->dname, "unable to add denial of existence for "
532  "domain, data point exists", 1);
534  }
535  /* create */
536  denial = denial_create(owner);
537  new_node = denial2node(denial);
538  ldns_rdf_deep_free(owner);
539  /* insert */
540  if (!ldns_rbtree_insert(zd->denial_chain, new_node)) {
541  log_rdf(domain->dname, "unable to add denial of existence for "
542  "domain, insert failed", 1);
543  free((void*)new_node);
544  denial_cleanup(denial);
545  return ODS_STATUS_ERR;
546  }
547  /* denial of existence data point added */
548  denial->bitmap_changed = 1;
549  denial->nxt_changed = 1;
550  prev_node = ldns_rbtree_previous(new_node);
551  if (!prev_node || prev_node == LDNS_RBTREE_NULL) {
552  prev_node = ldns_rbtree_last(zd->denial_chain);
553  }
554  ods_log_assert(prev_node);
555  prev_denial = (denial_type*) prev_node->data;
556  ods_log_assert(prev_denial);
557  prev_denial->nxt_changed = 1;
558  domain->denial = denial;
559  domain->denial->domain = domain; /* back reference */
560  return ODS_STATUS_OK;
561 }
562 
563 
568 static denial_type*
569 zonedata_del_denial_fixup(ldns_rbtree_t* tree, denial_type* denial)
570 {
571  denial_type* del_denial = NULL;
572  denial_type* prev_denial = NULL;
573  ldns_rbnode_t* prev_node = LDNS_RBTREE_NULL;
574  ldns_rbnode_t* del_node = LDNS_RBTREE_NULL;
575  ods_status status = ODS_STATUS_OK;
576 
577  ods_log_assert(tree);
578  ods_log_assert(denial);
579  ods_log_assert(denial->owner);
580 
581  del_node = ldns_rbtree_search(tree, (const void*)denial->owner);
582  if (del_node) {
587  prev_node = ldns_rbtree_previous(del_node);
588  if (!prev_node || prev_node == LDNS_RBTREE_NULL) {
589  prev_node = ldns_rbtree_last(tree);
590  }
591  ods_log_assert(prev_node);
592  ods_log_assert(prev_node->data);
593  prev_denial = (denial_type*) prev_node->data;
594  prev_denial->nxt_changed = 1;
595 
596  /* delete old NSEC RR(s) */
597  if (denial->rrset) {
598  status = rrset_wipe_out(denial->rrset);
599  if (status != ODS_STATUS_OK) {
600  ods_log_alert("[%s] unable to del denial of existence data "
601  "point: failed to wipe out NSEC RRset", zd_str);
602  return denial;
603  }
604  status = rrset_commit(denial->rrset);
605  if (status != ODS_STATUS_OK) {
606  ods_log_alert("[%s] unable to del denial of existence data "
607  "point: failed to commit NSEC RRset", zd_str);
608  return denial;
609  }
610  }
611 
612  del_node = ldns_rbtree_delete(tree, (const void*)denial->owner);
613  del_denial = (denial_type*) del_node->data;
614  denial_cleanup(del_denial);
615  free((void*)del_node);
616  return NULL;
617  } else {
618  log_rdf(denial->owner, "unable to del denial of existence data "
619  "point, not found", 1);
620  }
621  return denial;
622 }
623 
624 
631 {
632  if (!denial) {
633  ods_log_error("[%s] unable to delete denial of existence data "
634  "point: no data point", zd_str);
635  return NULL;
636  }
637  ods_log_assert(denial);
638 
639  if (!zd || !zd->denial_chain) {
640  log_rdf(denial->owner, "unable to delete denial of existence data "
641  "point, no zone data", 1);
642  return denial;
643  }
644  ods_log_assert(zd);
646 
647  return zonedata_del_denial_fixup(zd->denial_chain, denial);
648 }
649 
650 
657 {
658  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
659  domain_type* domain = NULL;
660  ods_status status = ODS_STATUS_OK;
661 
662  if (!zd || !zd->domains) {
663  return status;
664  }
665  if (zd->domains->root != LDNS_RBTREE_NULL) {
666  node = ldns_rbtree_first(zd->domains);
667  }
668  while (node && node != LDNS_RBTREE_NULL) {
669  domain = (domain_type*) node->data;
670  status = domain_diff(domain, kl);
671  if (status != ODS_STATUS_OK) {
672  return status;
673  }
674  node = ldns_rbtree_next(node);
675  }
676  return status;
677 }
678 
679 
686 {
687  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
688  ldns_rbnode_t* nxtnode = LDNS_RBTREE_NULL;
689  ldns_rbnode_t* tmpnode = LDNS_RBTREE_NULL;
690  domain_type* domain = NULL;
691  domain_type* nxtdomain = NULL;
692  ods_status status = ODS_STATUS_OK;
693  size_t oldnum = 0;
694 
695  if (!zd || !zd->domains) {
696  return ODS_STATUS_OK;
697  }
698  if (zd->domains->root != LDNS_RBTREE_NULL) {
699  node = ldns_rbtree_last(zd->domains);
700  }
701  while (node && node != LDNS_RBTREE_NULL) {
702  domain = (domain_type*) node->data;
703  oldnum = domain_count_rrset(domain);
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 
1188 ods_status
1190 {
1191  uint32_t soa = 0;
1192  uint32_t prev = 0;
1193  uint32_t update = 0;
1194 
1195  ods_log_assert(zd);
1196  ods_log_assert(sc);
1197 
1198  prev = zd->outbound_serial;
1199  ods_log_debug("[%s] update serial: in=%u internal=%u out=%u now=%u",
1200  zd_str, zd->inbound_serial, zd->internal_serial, zd->outbound_serial,
1201  (uint32_t) time_now());
1202 
1203  if (!sc->soa_serial) {
1204  ods_log_error("[%s] no serial type given", zd_str);
1205  return ODS_STATUS_ERR;
1206  }
1207  if (ods_strcmp(sc->soa_serial, "unixtime") == 0) {
1208  soa = (uint32_t) time_now();
1209  if (!zd->initialized) {
1210  if (!DNS_SERIAL_GT(soa, zd->inbound_serial)) {
1211  ods_log_warning("[%s] unable to use unixtime %u as serial: "
1212  "not greater than inbound serial %u", zd_str, soa,
1213  zd->inbound_serial);
1214  soa = zd->inbound_serial + 1;
1215  }
1216  } else if (!DNS_SERIAL_GT(soa, prev)) {
1217  soa = prev + 1;
1218  }
1219  } else if (strncmp(sc->soa_serial, "counter", 7) == 0) {
1220  soa = zd->inbound_serial;
1221  if (!zd->initialized) {
1222  soa = zd->inbound_serial + 1;
1223  } else if (!DNS_SERIAL_GT(soa, prev)) {
1224  soa = prev + 1;
1225  }
1226  } else if (strncmp(sc->soa_serial, "datecounter", 11) == 0) {
1227  soa = (uint32_t) time_datestamp(0, "%Y%m%d", NULL) * 100;
1228  if (!zd->initialized) {
1229  if (!DNS_SERIAL_GT(soa, zd->inbound_serial)) {
1230  ods_log_warning("[%s] unable to use datecounter %u as serial: "
1231  "not greater than inbound serial %u", zd_str, soa,
1232  zd->inbound_serial);
1233  soa = zd->inbound_serial + 1;
1234  }
1235  } else if (!DNS_SERIAL_GT(soa, prev)) {
1236  soa = prev + 1;
1237  }
1238  } else if (strncmp(sc->soa_serial, "keep", 4) == 0) {
1239  soa = zd->inbound_serial;
1240  if (zd->initialized && !DNS_SERIAL_GT(soa, prev)) {
1241  ods_log_error("[%s] cannot keep SOA SERIAL from input zone "
1242  " (%u): previous output SOA SERIAL is %u", zd_str, soa, prev);
1243  return ODS_STATUS_CONFLICT_ERR;
1244  }
1245  } else {
1246  ods_log_error("[%s] unknown serial type %s", zd_str, sc->soa_serial);
1247  return ODS_STATUS_ERR;
1248  }
1249 
1250  /* serial is stored in 32 bits */
1251  update = soa - prev;
1252  if (update > 0x7FFFFFFF) {
1253  update = 0x7FFFFFFF;
1254  }
1255 
1256  if (!zd->initialized) {
1257  zd->internal_serial = soa;
1258  } else {
1259  zd->internal_serial = prev + update; /* automatically does % 2^32 */
1260  }
1261  ods_log_debug("[%s] update serial: %u + %u = %u", zd_str, prev, update,
1262  zd->internal_serial);
1263  return ODS_STATUS_OK;
1264 }
1265 
1266 
1271 ods_status
1273 {
1274  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
1275  domain_type* domain = NULL;
1276  ods_status status = ODS_STATUS_OK;
1277 
1278  if (!zd || !zd->domains) {
1279  return ODS_STATUS_OK;
1280  }
1281  if (zd->domains->root != LDNS_RBTREE_NULL) {
1282  node = ldns_rbtree_first(zd->domains);
1283  }
1284  while (node && node != LDNS_RBTREE_NULL) {
1285  domain = (domain_type*) node->data;
1286  status = domain_queue(domain, q, worker);
1287  if (status != ODS_STATUS_OK) {
1288  return status;
1289  }
1290  node = ldns_rbtree_next(node);
1291  }
1292  return status;
1293 }
1294 
1295 
1300 static int
1301 zonedata_examine_domain_is_occluded(zonedata_type* zd, domain_type* domain,
1302  ldns_rdf* apex)
1303 {
1304  ldns_rdf* parent_rdf = NULL;
1305  ldns_rdf* next_rdf = NULL;
1306  domain_type* parent_domain = NULL;
1307  char* str_name = NULL;
1308  char* str_parent = NULL;
1309 
1310  ods_log_assert(apex);
1311  ods_log_assert(domain);
1312  ods_log_assert(domain->dname);
1313  ods_log_assert(zd);
1314  ods_log_assert(zd->domains);
1315 
1316  if (ldns_dname_compare(domain->dname, apex) == 0) {
1317  return 0;
1318  }
1319 
1320  if (domain_examine_valid_zonecut(domain) != 0) {
1321  log_rdf(domain->dname, "occluded (non-glue non-DS) data at NS", 2);
1322  return 1;
1323  }
1324 
1325  parent_rdf = ldns_dname_left_chop(domain->dname);
1326  while (parent_rdf && ldns_dname_is_subdomain(parent_rdf, apex) &&
1327  ldns_dname_compare(parent_rdf, apex) != 0) {
1328 
1329  parent_domain = zonedata_lookup_domain(zd, parent_rdf);
1330  next_rdf = ldns_dname_left_chop(parent_rdf);
1331  ldns_rdf_deep_free(parent_rdf);
1332 
1333  if (parent_domain) {
1334  /* check for DNAME or NS */
1335  if (domain_examine_data_exists(parent_domain, LDNS_RR_TYPE_DNAME,
1336  0) && domain_examine_data_exists(domain, 0, 0)) {
1337  /* data below DNAME */
1338  str_name = ldns_rdf2str(domain->dname);
1339  str_parent = ldns_rdf2str(parent_domain->dname);
1340  ods_log_warning("[%s] occluded data at %s (below %s DNAME)",
1341  zd_str, str_name, str_parent);
1342  free((void*)str_name);
1343  free((void*)str_parent);
1344  return 1;
1345  } else if (domain_examine_data_exists(parent_domain,
1346  LDNS_RR_TYPE_NS, 0) &&
1347  domain_examine_data_exists(domain, 0, 1)) {
1348  /* data (non-glue) below NS */
1349  str_name = ldns_rdf2str(domain->dname);
1350  str_parent = ldns_rdf2str(parent_domain->dname);
1351  ods_log_warning("[%s] occluded (non-glue) data at %s (below "
1352  "%s NS)", zd_str, str_name, str_parent);
1353  free((void*)str_name);
1354  free((void*)str_parent);
1355  return 1;
1356 /* allow for now (root zone has it)
1357  } else if (domain_examine_data_exists(parent_domain,
1358  LDNS_RR_TYPE_NS, 0) &&
1359  domain_examine_data_exists(domain, 0, 0) &&
1360  !domain_examine_ns_rdata(parent_domain, domain->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 NS)",
1364  zd_str, str_name, str_parent);
1365  free((void*)str_name);
1366  free((void*)str_parent);
1367  return 1;
1368 */
1369  }
1370  }
1371  parent_rdf = next_rdf;
1372  }
1373  if (parent_rdf) {
1374  ldns_rdf_deep_free(parent_rdf);
1375  }
1376  return 0;
1377 }
1378 
1379 
1384 ods_status
1385 zonedata_examine(zonedata_type* zd, ldns_rdf* apex, adapter_mode mode)
1386 {
1387  int result = 0;
1388  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
1389  domain_type* domain = NULL;
1390  ods_status status = ODS_STATUS_OK;
1391 
1392  if (!zd || !zd->domains) {
1393  /* no zone data, no error */
1394  return ODS_STATUS_OK;
1395  }
1396  ods_log_assert(zd);
1397  ods_log_assert(zd->domains);
1398 
1399  if (zd->domains->root != LDNS_RBTREE_NULL) {
1400  node = ldns_rbtree_first(zd->domains);
1401  }
1402  while (node && node != LDNS_RBTREE_NULL) {
1403  domain = (domain_type*) node->data;
1404  result =
1405  /* Thou shall not have other data next to CNAME */
1406  domain_examine_rrset_is_alone(domain, LDNS_RR_TYPE_CNAME) &&
1407  /* Thou shall have at most one CNAME per name */
1408  domain_examine_rrset_is_singleton(domain, LDNS_RR_TYPE_CNAME) &&
1409  /* Thou shall have at most one DNAME per name */
1410  domain_examine_rrset_is_singleton(domain, LDNS_RR_TYPE_DNAME);
1411  if (!result) {
1412  status = ODS_STATUS_ERR;
1413  }
1414 
1415  if (mode == ADAPTER_FILE) {
1416  result =
1417  /* Thou shall not have occluded data in your zone file */
1418  zonedata_examine_domain_is_occluded(zd, domain, apex);
1419  if (result) {
1420  ; /* just warn if there is occluded data */
1421  }
1422  }
1423  node = ldns_rbtree_next(node);
1424  }
1425  return status;
1426 }
1427 
1428 
1433 void
1435 {
1436  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
1437  denial_type* denial = NULL;
1438 
1439  if (zd && zd->denial_chain) {
1440  node = ldns_rbtree_first(zd->denial_chain);
1441  while (node && node != LDNS_RBTREE_NULL) {
1442  denial = (denial_type*) node->data;
1443  if (denial->rrset) {
1444  /* [TODO] IXFR delete NSEC */
1445  rrset_cleanup(denial->rrset);
1446  denial->rrset = NULL;
1447  }
1448  node = ldns_rbtree_next(node);
1449  }
1450  }
1451  return;
1452 }
1453 
1454 
1459 static void
1460 domain_delfunc(ldns_rbnode_t* elem)
1461 {
1462  domain_type* domain = NULL;
1463 
1464  if (elem && elem != LDNS_RBTREE_NULL) {
1465  domain = (domain_type*) elem->data;
1466  domain_delfunc(elem->left);
1467  domain_delfunc(elem->right);
1468 
1469  domain_cleanup(domain);
1470  free((void*)elem);
1471  }
1472  return;
1473 }
1474 
1475 
1480 static void
1481 denial_delfunc(ldns_rbnode_t* elem)
1482 {
1483  denial_type* denial = NULL;
1484  domain_type* domain = NULL;
1485 
1486 
1487  if (elem && elem != LDNS_RBTREE_NULL) {
1488  denial = (denial_type*) elem->data;
1489  denial_delfunc(elem->left);
1490  denial_delfunc(elem->right);
1491 
1492  domain = denial->domain;
1493  if (domain) {
1494  domain->denial = NULL;
1495  }
1496  denial_cleanup(denial);
1497 
1498  free((void*)elem);
1499  }
1500  return;
1501 }
1502 
1503 
1508 static void
1509 zonedata_cleanup_domains(zonedata_type* zd)
1510 {
1511  if (zd && zd->domains) {
1512  domain_delfunc(zd->domains->root);
1513  ldns_rbtree_free(zd->domains);
1514  zd->domains = NULL;
1515  }
1516  return;
1517 }
1518 
1519 
1524 void
1526 {
1527  if (zd && zd->denial_chain) {
1528  denial_delfunc(zd->denial_chain->root);
1529  ldns_rbtree_free(zd->denial_chain);
1530  zd->denial_chain = NULL;
1531  }
1532  return;
1533 }
1534 
1535 
1540 void
1542 {
1543  allocator_type* allocator;
1544 
1545  if (!zd) {
1546  return;
1547  }
1549  zonedata_cleanup_domains(zd);
1550  allocator = zd->allocator;
1551  allocator_deallocate(allocator, (void*) zd);
1552  return;
1553 }
1554 
1555 
1560 void
1562 {
1563  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
1564  domain_type* domain = NULL;
1565 
1566  if (!fd || !zd) {
1567  return;
1568  }
1569 
1570  node = ldns_rbtree_first(zd->domains);
1571  while (node && node != LDNS_RBTREE_NULL) {
1572  domain = (domain_type*) node->data;
1573  domain_backup(fd, domain);
1574  node = ldns_rbtree_next(node);
1575  }
1576  fprintf(fd, ";;\n");
1577  return;
1578 }
1579 
1580 
1585 ods_status
1587 {
1588  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
1589  domain_type* domain = NULL;
1590 
1591  if (!fd) {
1592  ods_log_error("[%s] unable to print zone data: no file descriptor",
1593  zd_str);
1594  return ODS_STATUS_ASSERT_ERR;
1595  }
1596  ods_log_assert(fd);
1597 
1598  if (!zd || !zd->domains) {
1599  ods_log_error("[%s] unable to print zone data: no zone data",
1600  zd_str);
1601  return ODS_STATUS_ASSERT_ERR;
1602  }
1603  ods_log_assert(zd);
1604  ods_log_assert(zd->domains);
1605 
1606  node = ldns_rbtree_first(zd->domains);
1607  if (!node || node == LDNS_RBTREE_NULL) {
1608  fprintf(fd, "; empty zone\n");
1609  return ODS_STATUS_OK;
1610  }
1611  while (node && node != LDNS_RBTREE_NULL) {
1612  domain = (domain_type*) node->data;
1613  domain_print(fd, domain);
1614  node = ldns_rbtree_next(node);
1615  }
1616  return ODS_STATUS_OK;
1617 }