OpenDNSSEC-signer  1.3.14
zonedata.c
Go to the documentation of this file.
1 /*
2  * $Id: zonedata.c 6990 2013-02-01 16:36:57Z 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 
694  if (!zd || !zd->domains) {
695  return ODS_STATUS_OK;
696  }
697  if (zd->domains->root != LDNS_RBTREE_NULL) {
698  node = ldns_rbtree_last(zd->domains);
699  }
700  while (node && node != LDNS_RBTREE_NULL) {
701  domain = (domain_type*) node->data;
702  status = domain_commit(domain);
703  if (status != ODS_STATUS_OK) {
704  return status;
705  }
706  tmpnode = node;
707  node = ldns_rbtree_previous(node);
708 
709  /* delete memory if empty leaf domain */
710  if (domain_count_rrset(domain) <= 0) {
711  /* empty domain */
712  nxtnode = ldns_rbtree_next(tmpnode);
713  nxtdomain = NULL;
714  if (nxtnode && nxtnode != LDNS_RBTREE_NULL) {
715  nxtdomain = (domain_type*) nxtnode->data;
716  }
717  if (!nxtdomain ||
718  !ldns_dname_is_subdomain(nxtdomain->dname, domain->dname)) {
719  /* leaf domain */
720  if (zonedata_del_domain(zd, domain) != NULL) {
721  ods_log_warning("[%s] unable to delete obsoleted "
722  "domain", zd_str);
723  return ODS_STATUS_ERR;
724  }
725  }
726  } /* if (domain_count_rrset(domain) <= 0) */
727  }
728  return status;
729 }
730 
731 
736 void
738 {
739  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
740  domain_type* domain = NULL;
741 
742  if (!zd || !zd->domains) {
743  return;
744  }
745  if (zd->domains->root != LDNS_RBTREE_NULL) {
746  node = ldns_rbtree_first(zd->domains);
747  }
748  while (node && node != LDNS_RBTREE_NULL) {
749  domain = (domain_type*) node->data;
750  domain_rollback(domain);
751  node = ldns_rbtree_next(node);
752  }
753  return;
754 }
755 
756 
761 static int
762 domain_ent2glue(ldns_rbnode_t* node)
763 {
764  ldns_rbnode_t* nextnode = LDNS_RBTREE_NULL;
765  domain_type* nextdomain = NULL;
766  domain_type* domain = NULL;
767  ods_log_assert(node && node != LDNS_RBTREE_NULL);
768  domain = (domain_type*) node->data;
769  if (domain->dstatus == DOMAIN_STATUS_ENT) {
770  ods_log_assert(domain_count_rrset(domain) == 0);
771  nextnode = ldns_rbtree_next(node);
772  while (nextnode && nextnode != LDNS_RBTREE_NULL) {
773  nextdomain = (domain_type*) nextnode->data;
774  if (!ldns_dname_is_subdomain(nextdomain->dname, domain->dname)) {
775  /* we are done, no non-glue found */
776  return 1;
777  }
778  if (nextdomain->dstatus != DOMAIN_STATUS_OCCLUDED &&
779  nextdomain->dstatus != DOMAIN_STATUS_ENT &&
780  nextdomain->dstatus != DOMAIN_STATUS_NONE) {
781  /* found non-glue */
782  return 0;
783  }
784  nextnode = ldns_rbtree_next(nextnode);
785  }
786  } else {
787  /* no empty non-terminal */
788  ods_log_assert(domain_count_rrset(domain) != 0);
789  return 0;
790  }
791  /* no non-glue found */
792  return 1;
793 }
794 
795 
800 static int
801 domain_ent2unsigned(ldns_rbnode_t* node)
802 {
803  ldns_rbnode_t* nextnode = LDNS_RBTREE_NULL;
804  domain_type* nextdomain = NULL;
805  domain_type* domain = NULL;
806  ods_log_assert(node && node != LDNS_RBTREE_NULL);
807  domain = (domain_type*) node->data;
808  if (domain->dstatus == DOMAIN_STATUS_ENT) {
809  ods_log_assert(domain_count_rrset(domain) == 0);
810  nextnode = ldns_rbtree_next(node);
811  while (nextnode && nextnode != LDNS_RBTREE_NULL) {
812  nextdomain = (domain_type*) nextnode->data;
813  if (!ldns_dname_is_subdomain(nextdomain->dname, domain->dname)) {
814  /* we are done, no unsigned delegation found */
815  return 1;
816  }
817  if (nextdomain->dstatus != DOMAIN_STATUS_OCCLUDED &&
818  nextdomain->dstatus != DOMAIN_STATUS_ENT &&
819  nextdomain->dstatus != DOMAIN_STATUS_NS &&
820  nextdomain->dstatus != DOMAIN_STATUS_NONE) {
821  /* found data that has to be signed */
822  return 0;
823  }
824  nextnode = ldns_rbtree_next(nextnode);
825  }
826  } else {
827  /* no empty non-terminal */
828  ods_log_assert(domain_count_rrset(domain) != 0);
829  return 0;
830  }
831  /* no unsigned delegation found */
832  return 1;
833 }
834 
835 
840 static ods_status
841 domain_entize(zonedata_type* zd, domain_type* domain, ldns_rdf* apex)
842 {
843  ldns_rdf* parent_rdf = NULL;
844  domain_type* parent_domain = NULL;
845 
846  ods_log_assert(apex);
847  ods_log_assert(domain);
848  ods_log_assert(domain->dname);
849  ods_log_assert(zd);
850  ods_log_assert(zd->domains);
851 
852  if (domain->parent) {
853  /* domain already has parent */
854  return ODS_STATUS_OK;
855  }
856 
857  while (domain && ldns_dname_is_subdomain(domain->dname, apex) &&
858  ldns_dname_compare(domain->dname, apex) != 0) {
859 
867  parent_rdf = ldns_dname_left_chop(domain->dname);
868  if (!parent_rdf) {
869  log_rdf(domain->dname, "unable to entize domain, left chop "
870  "failed", 1);
871  return ODS_STATUS_ERR;
872  }
873  ods_log_assert(parent_rdf);
874 
875  parent_domain = zonedata_lookup_domain(zd, parent_rdf);
876  if (!parent_domain) {
877  parent_domain = domain_create(parent_rdf);
878  ldns_rdf_deep_free(parent_rdf);
879  if (!parent_domain) {
880  log_rdf(domain->dname, "unable to entize domain, create "
881  "parent failed", 1);
882  return ODS_STATUS_ERR;
883  }
884  ods_log_assert(parent_domain);
885  if (zonedata_add_domain(zd, parent_domain) == NULL) {
886  log_rdf(domain->dname, "unable to entize domain, add parent "
887  "failed", 1);
888  domain_cleanup(parent_domain);
889  return ODS_STATUS_ERR;
890  }
891  parent_domain->dstatus = DOMAIN_STATUS_ENT;
892  domain->parent = parent_domain;
893  /* continue with the parent domain */
894  domain = parent_domain;
895  } else {
896  ldns_rdf_deep_free(parent_rdf);
897  domain->parent = parent_domain;
898  /* we are done with this domain */
899  domain = NULL;
900  }
901  }
902  return ODS_STATUS_OK;
903 }
904 
905 
911 zonedata_entize(zonedata_type* zd, ldns_rdf* apex)
912 {
913  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
914  ods_status status = ODS_STATUS_OK;
915  domain_type* domain = NULL;
916 
917  if (!zd || !zd->domains) {
918  ods_log_error("[%s] unable to entize zone data: no zone data",
919  zd_str);
920  return ODS_STATUS_ASSERT_ERR;
921  }
922  ods_log_assert(zd);
923  ods_log_assert(zd->domains);
924 
925  if (!apex) {
926  ods_log_error("[%s] unable to entize zone data: no zone apex",
927  zd_str);
928  return ODS_STATUS_ASSERT_ERR;
929  }
930  ods_log_assert(apex);
931 
932  node = ldns_rbtree_first(zd->domains);
933  while (node && node != LDNS_RBTREE_NULL) {
934  domain = (domain_type*) node->data;
935  status = domain_entize(zd, domain, apex);
936  if (status != ODS_STATUS_OK) {
937  ods_log_error("[%s] unable to entize zone data: entize domain "
938  "failed", zd_str);
939  return status;
940  }
941  domain_dstatus(domain);
942  node = ldns_rbtree_next(node);
943  }
944  return ODS_STATUS_OK;
945 }
946 
947 
953 zonedata_nsecify(zonedata_type* zd, ldns_rr_class klass, uint32_t ttl,
954  uint32_t* num_added)
955 {
956  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
957  ldns_rbnode_t* nxt_node = LDNS_RBTREE_NULL;
958  ods_status status = ODS_STATUS_OK;
959  domain_type* domain = NULL;
960  domain_type* apex = NULL;
961  denial_type* denial = NULL;
962  denial_type* nxt = NULL;
963  size_t nsec_added = 0;
964 
965  if (!zd || !zd->domains) {
966  return ODS_STATUS_OK;
967  }
968  ods_log_assert(zd);
969  ods_log_assert(zd->domains);
970 
971  node = ldns_rbtree_first(zd->domains);
972  while (node && node != LDNS_RBTREE_NULL) {
973  domain = (domain_type*) node->data;
974  if (domain->dstatus == DOMAIN_STATUS_APEX) {
975  apex = domain;
976  }
977  /* don't do glue-only or empty domains */
978  if (domain->dstatus == DOMAIN_STATUS_NONE ||
979  domain->dstatus == DOMAIN_STATUS_ENT ||
980  domain->dstatus == DOMAIN_STATUS_OCCLUDED ||
981  domain_count_rrset(domain) <= 0) {
982  if (domain_count_rrset(domain)) {
983  log_rdf(domain->dname, "nsecify: don't do glue domain", 6);
984  } else {
985  log_rdf(domain->dname, "nsecify: don't do empty domain", 6);
986  }
987  if (domain->denial) {
988  if (zonedata_del_denial(zd, domain->denial) != NULL) {
989  ods_log_warning("[%s] unable to nsecify: failed to "
990  "delete denial of existence data point", zd_str);
991  return ODS_STATUS_ERR;
992  }
993  domain->denial = NULL;
994  }
995  node = ldns_rbtree_next(node);
996  continue;
997  }
998  if (!apex) {
999  ods_log_alert("[%s] unable to nsecify: apex unknown", zd_str);
1000  return ODS_STATUS_ASSERT_ERR;
1001  }
1002 
1003  /* add the denial of existence */
1004  if (!domain->denial) {
1005  status = zonedata_add_denial(zd, domain, apex->dname, NULL);
1006  if (status != ODS_STATUS_OK) {
1007  log_rdf(domain->dname, "unable to nsecify: failed to add "
1008  "denial of existence for domain", 1);
1009  return status;
1010  }
1011  nsec_added++;
1012  }
1013  node = ldns_rbtree_next(node);
1014  }
1015 
1017  node = ldns_rbtree_first(zd->denial_chain);
1018  while (node && node != LDNS_RBTREE_NULL) {
1019  denial = (denial_type*) node->data;
1020  nxt_node = ldns_rbtree_next(node);
1021  if (!nxt_node || nxt_node == LDNS_RBTREE_NULL) {
1022  nxt_node = ldns_rbtree_first(zd->denial_chain);
1023  }
1024  nxt = (denial_type*) nxt_node->data;
1025 
1026  status = denial_nsecify(denial, nxt, ttl, klass);
1027  if (status != ODS_STATUS_OK) {
1028  ods_log_error("[%s] unable to nsecify: failed to add NSEC record",
1029  zd_str);
1030  return status;
1031  }
1032  node = ldns_rbtree_next(node);
1033  }
1034  if (num_added) {
1035  *num_added = nsec_added;
1036  }
1037  return ODS_STATUS_OK;
1038 }
1039 
1040 
1045 ods_status
1046 zonedata_nsecify3(zonedata_type* zd, ldns_rr_class klass,
1047  uint32_t ttl, nsec3params_type* nsec3params, uint32_t* num_added)
1048 {
1049  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
1050  ldns_rbnode_t* nxt_node = LDNS_RBTREE_NULL;
1051  ods_status status = ODS_STATUS_OK;
1052  domain_type* domain = NULL;
1053  domain_type* apex = NULL;
1054  denial_type* denial = NULL;
1055  denial_type* nxt = NULL;
1056  size_t nsec3_added = 0;
1057 
1058  if (!zd || !zd->domains) {
1059  return ODS_STATUS_OK;
1060  }
1061  ods_log_assert(zd);
1062  ods_log_assert(zd->domains);
1063 
1064  if (!nsec3params) {
1065  ods_log_error("[%s] unable to nsecify3: no nsec3 paramaters", zd_str);
1066  return ODS_STATUS_ASSERT_ERR;
1067  }
1068  ods_log_assert(nsec3params);
1069 
1070  node = ldns_rbtree_first(zd->domains);
1071  while (node && node != LDNS_RBTREE_NULL) {
1072  domain = (domain_type*) node->data;
1073  if (domain->dstatus == DOMAIN_STATUS_APEX) {
1074  apex = domain;
1075  }
1076 
1077  /* don't do glue-only domains */
1078  if (domain->dstatus == DOMAIN_STATUS_NONE ||
1079  domain->dstatus == DOMAIN_STATUS_OCCLUDED ||
1080  domain_ent2glue(node)) {
1081  log_rdf(domain->dname, "nsecify3: don't do glue domain" , 6);
1082  if (domain->denial) {
1083  if (zonedata_del_denial(zd, domain->denial) != NULL) {
1084  ods_log_error("[%s] unable to nsecify3: failed to "
1085  "delete denial of existence data point", zd_str);
1086  return ODS_STATUS_ERR;
1087  }
1088  domain->denial = NULL;
1089  }
1090  node = ldns_rbtree_next(node);
1091  continue;
1092  }
1093  /* Opt-Out? */
1094  if (nsec3params->flags) {
1095  /* If Opt-Out is being used, owner names of unsigned delegations
1096  MAY be excluded. */
1097  if (domain->dstatus == DOMAIN_STATUS_NS ||
1098  domain_ent2unsigned(node)) {
1099  if (domain->dstatus == DOMAIN_STATUS_NS) {
1100  log_rdf(domain->dname, "nsecify3: opt-out (unsigned "
1101  "delegation)", 5);
1102  } else {
1103  log_rdf(domain->dname, "nsecify3: opt-out (empty "
1104  "non-terminal (to unsigned delegation))", 5);
1105  }
1106  if (domain->denial) {
1107  if (zonedata_del_denial(zd, domain->denial) != NULL) {
1108  ods_log_error("[%s] unable to nsecify3: failed to "
1109  "delete denial of existence data point", zd_str);
1110  return ODS_STATUS_ERR;
1111  }
1112  domain->denial = NULL;
1113  }
1114  node = ldns_rbtree_next(node);
1115  continue;
1116  }
1117  }
1118  if (!apex) {
1119  ods_log_alert("[%s] unable to nsecify3: apex unknown", zd_str);
1120  return ODS_STATUS_ASSERT_ERR;
1121  }
1122 
1123  /* add the denial of existence */
1124  if (!domain->denial) {
1125  status = zonedata_add_denial(zd, domain, apex->dname,
1126  nsec3params);
1127  if (status != ODS_STATUS_OK) {
1128  log_rdf(domain->dname, "unable to nsecify3: failed to add "
1129  "denial of existence for domain", 1);
1130  return status;
1131  }
1132  nsec3_added++;
1133  }
1134 
1135  /* The Next Hashed Owner Name field is left blank for the moment. */
1136 
1144  /* [TODO] */
1154  node = ldns_rbtree_next(node);
1155  }
1156 
1158  node = ldns_rbtree_first(zd->denial_chain);
1159  while (node && node != LDNS_RBTREE_NULL) {
1160  denial = (denial_type*) node->data;
1161  nxt_node = ldns_rbtree_next(node);
1162  if (!nxt_node || nxt_node == LDNS_RBTREE_NULL) {
1163  nxt_node = ldns_rbtree_first(zd->denial_chain);
1164  }
1165  nxt = (denial_type*) nxt_node->data;
1166 
1167  status = denial_nsecify3(denial, nxt, ttl, klass, nsec3params);
1168  if (status != ODS_STATUS_OK) {
1169  ods_log_error("[%s] unable to nsecify3: failed to add NSEC3 "
1170  "record", zd_str);
1171  return status;
1172  }
1173  node = ldns_rbtree_next(node);
1174  }
1175  if (num_added) {
1176  *num_added = nsec3_added;
1177  }
1178  return ODS_STATUS_OK;
1179 }
1180 
1181 
1182 static uint32_t
1183 max(uint32_t a, uint32_t b)
1184 {
1185  return (a<b?b:a);
1186 }
1187 
1192 ods_status
1194 {
1195  uint32_t soa = 0;
1196  uint32_t prev = 0;
1197  uint32_t update = 0;
1198 
1199  ods_log_assert(zd);
1200  ods_log_assert(sc);
1201 
1202  prev = max(zd->outbound_serial, zd->inbound_serial);
1203  ods_log_debug("[%s] update serial: in=%u internal=%u out=%u now=%u",
1204  zd_str, zd->inbound_serial, zd->internal_serial, zd->outbound_serial,
1205  (uint32_t) time_now());
1206 
1207  if (!sc->soa_serial) {
1208  ods_log_error("[%s] no serial type given", zd_str);
1209  return ODS_STATUS_ERR;
1210  }
1211  if (ods_strcmp(sc->soa_serial, "unixtime") == 0) {
1212  soa = (uint32_t) time_now();
1213  if (!zd->initialized) {
1214  if (!DNS_SERIAL_GT(soa, zd->inbound_serial)) {
1215  ods_log_warning("[%s] unable to use unixtime %u as serial: "
1216  "not greater than inbound serial %u", zd_str, soa,
1217  zd->inbound_serial);
1218  soa = zd->inbound_serial + 1;
1219  }
1220  } else if (!DNS_SERIAL_GT(soa, prev)) {
1221  soa = prev + 1;
1222  }
1223  } else if (strncmp(sc->soa_serial, "counter", 7) == 0) {
1224  soa = zd->inbound_serial;
1225  if (!zd->initialized) {
1226  soa = zd->inbound_serial + 1;
1227  } else if (!DNS_SERIAL_GT(soa, prev)) {
1228  soa = prev + 1;
1229  }
1230  } else if (strncmp(sc->soa_serial, "datecounter", 11) == 0) {
1231  soa = (uint32_t) time_datestamp(0, "%Y%m%d", NULL) * 100;
1232  if (!zd->initialized) {
1233  if (!DNS_SERIAL_GT(soa, zd->inbound_serial)) {
1234  ods_log_warning("[%s] unable to use datecounter %u as serial: "
1235  "not greater than inbound serial %u", zd_str, soa,
1236  zd->inbound_serial);
1237  soa = zd->inbound_serial + 1;
1238  }
1239  } else if (!DNS_SERIAL_GT(soa, prev)) {
1240  soa = prev + 1;
1241  }
1242  } else if (strncmp(sc->soa_serial, "keep", 4) == 0) {
1243  prev = zd->outbound_serial;
1244  soa = zd->inbound_serial;
1245  if (zd->initialized && !DNS_SERIAL_GT(soa, prev)) {
1246  ods_log_error("[%s] cannot keep SOA SERIAL from input zone "
1247  " (%u): previous output SOA SERIAL is %u", zd_str, soa, prev);
1248  return ODS_STATUS_CONFLICT_ERR;
1249  }
1250  } else {
1251  ods_log_error("[%s] unknown serial type %s", zd_str, sc->soa_serial);
1252  return ODS_STATUS_ERR;
1253  }
1254 
1255  /* serial is stored in 32 bits */
1256  update = soa - prev;
1257  if (update > 0x7FFFFFFF) {
1258  update = 0x7FFFFFFF;
1259  }
1260 
1261  if (!zd->initialized) {
1262  zd->internal_serial = soa;
1263  } else {
1264  zd->internal_serial = prev + update; /* automatically does % 2^32 */
1265  }
1266  ods_log_debug("[%s] update serial: %u + %u = %u", zd_str, prev, update,
1267  zd->internal_serial);
1268  return ODS_STATUS_OK;
1269 }
1270 
1271 
1276 ods_status
1278 {
1279  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
1280  domain_type* domain = NULL;
1281  ods_status status = ODS_STATUS_OK;
1282 
1283  if (!zd || !zd->domains) {
1284  return ODS_STATUS_OK;
1285  }
1286  if (zd->domains->root != LDNS_RBTREE_NULL) {
1287  node = ldns_rbtree_first(zd->domains);
1288  }
1289  while (node && node != LDNS_RBTREE_NULL) {
1290  domain = (domain_type*) node->data;
1291  status = domain_queue(domain, q, worker);
1292  if (status != ODS_STATUS_OK) {
1293  return status;
1294  }
1295  node = ldns_rbtree_next(node);
1296  }
1297  return status;
1298 }
1299 
1300 
1305 static int
1306 zonedata_examine_domain_is_occluded(zonedata_type* zd, domain_type* domain,
1307  ldns_rdf* apex)
1308 {
1309  ldns_rdf* parent_rdf = NULL;
1310  ldns_rdf* next_rdf = NULL;
1311  domain_type* parent_domain = NULL;
1312  char* str_name = NULL;
1313  char* str_parent = NULL;
1314 
1315  ods_log_assert(apex);
1316  ods_log_assert(domain);
1317  ods_log_assert(domain->dname);
1318  ods_log_assert(zd);
1319  ods_log_assert(zd->domains);
1320 
1321  if (ldns_dname_compare(domain->dname, apex) == 0) {
1322  return 0;
1323  }
1324 
1325  if (domain_examine_valid_zonecut(domain) != 0) {
1326  log_rdf(domain->dname, "occluded (non-glue non-DS) data at NS", 2);
1327  return 1;
1328  }
1329 
1330  parent_rdf = ldns_dname_left_chop(domain->dname);
1331  while (parent_rdf && ldns_dname_is_subdomain(parent_rdf, apex) &&
1332  ldns_dname_compare(parent_rdf, apex) != 0) {
1333 
1334  parent_domain = zonedata_lookup_domain(zd, parent_rdf);
1335  next_rdf = ldns_dname_left_chop(parent_rdf);
1336  ldns_rdf_deep_free(parent_rdf);
1337 
1338  if (parent_domain) {
1339  /* check for DNAME or NS */
1340  if (domain_examine_data_exists(parent_domain, LDNS_RR_TYPE_DNAME,
1341  0) && domain_examine_data_exists(domain, 0, 0)) {
1342  /* data below DNAME */
1343  str_name = ldns_rdf2str(domain->dname);
1344  str_parent = ldns_rdf2str(parent_domain->dname);
1345  ods_log_warning("[%s] occluded data at %s (below %s DNAME)",
1346  zd_str, str_name, str_parent);
1347  free((void*)str_name);
1348  free((void*)str_parent);
1349  return 1;
1350  } else if (domain_examine_data_exists(parent_domain,
1351  LDNS_RR_TYPE_NS, 0) &&
1352  domain_examine_data_exists(domain, 0, 1)) {
1353  /* data (non-glue) below NS */
1354  str_name = ldns_rdf2str(domain->dname);
1355  str_parent = ldns_rdf2str(parent_domain->dname);
1356  ods_log_warning("[%s] occluded (non-glue) data at %s (below "
1357  "%s NS)", zd_str, str_name, str_parent);
1358  free((void*)str_name);
1359  free((void*)str_parent);
1360  return 1;
1361 /* allow for now (root zone has it)
1362  } else if (domain_examine_data_exists(parent_domain,
1363  LDNS_RR_TYPE_NS, 0) &&
1364  domain_examine_data_exists(domain, 0, 0) &&
1365  !domain_examine_ns_rdata(parent_domain, domain->dname)) {
1366  str_name = ldns_rdf2str(domain->dname);
1367  str_parent = ldns_rdf2str(parent_domain->dname);
1368  ods_log_warning("[%s] occluded data at %s (below %s NS)",
1369  zd_str, str_name, str_parent);
1370  free((void*)str_name);
1371  free((void*)str_parent);
1372  return 1;
1373 */
1374  }
1375  }
1376  parent_rdf = next_rdf;
1377  }
1378  if (parent_rdf) {
1379  ldns_rdf_deep_free(parent_rdf);
1380  }
1381  return 0;
1382 }
1383 
1384 
1389 ods_status
1390 zonedata_examine(zonedata_type* zd, ldns_rdf* apex, adapter_mode mode)
1391 {
1392  int result = 0;
1393  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
1394  domain_type* domain = NULL;
1395  ods_status status = ODS_STATUS_OK;
1396 
1397  if (!zd || !zd->domains) {
1398  /* no zone data, no error */
1399  return ODS_STATUS_OK;
1400  }
1401  ods_log_assert(zd);
1402  ods_log_assert(zd->domains);
1403 
1404  if (zd->domains->root != LDNS_RBTREE_NULL) {
1405  node = ldns_rbtree_first(zd->domains);
1406  }
1407  while (node && node != LDNS_RBTREE_NULL) {
1408  domain = (domain_type*) node->data;
1409  result =
1410  /* Thou shall not have other data next to CNAME */
1411  domain_examine_rrset_is_alone(domain, LDNS_RR_TYPE_CNAME) &&
1412  /* Thou shall have at most one CNAME per name */
1413  domain_examine_rrset_is_singleton(domain, LDNS_RR_TYPE_CNAME) &&
1414  /* Thou shall have at most one DNAME per name */
1415  domain_examine_rrset_is_singleton(domain, LDNS_RR_TYPE_DNAME);
1416  if (!result) {
1417  status = ODS_STATUS_ERR;
1418  }
1419 
1420  if (mode == ADAPTER_FILE) {
1421  result =
1422  /* Thou shall not have occluded data in your zone file */
1423  zonedata_examine_domain_is_occluded(zd, domain, apex);
1424  if (result) {
1425  ; /* just warn if there is occluded data */
1426  }
1427  }
1428  node = ldns_rbtree_next(node);
1429  }
1430  return status;
1431 }
1432 
1433 
1438 void
1440 {
1441  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
1442  denial_type* denial = NULL;
1443 
1444  if (zd && zd->denial_chain) {
1445  node = ldns_rbtree_first(zd->denial_chain);
1446  while (node && node != LDNS_RBTREE_NULL) {
1447  denial = (denial_type*) node->data;
1448  if (denial->rrset) {
1449  /* [TODO] IXFR delete NSEC */
1450  rrset_cleanup(denial->rrset);
1451  denial->rrset = NULL;
1452  }
1453  node = ldns_rbtree_next(node);
1454  }
1455  }
1456  return;
1457 }
1458 
1459 
1464 static void
1465 domain_delfunc(ldns_rbnode_t* elem)
1466 {
1467  domain_type* domain = NULL;
1468 
1469  if (elem && elem != LDNS_RBTREE_NULL) {
1470  domain = (domain_type*) elem->data;
1471  domain_delfunc(elem->left);
1472  domain_delfunc(elem->right);
1473 
1474  domain_cleanup(domain);
1475  free((void*)elem);
1476  }
1477  return;
1478 }
1479 
1480 
1485 static void
1486 denial_delfunc(ldns_rbnode_t* elem)
1487 {
1488  denial_type* denial = NULL;
1489  domain_type* domain = NULL;
1490 
1491 
1492  if (elem && elem != LDNS_RBTREE_NULL) {
1493  denial = (denial_type*) elem->data;
1494  denial_delfunc(elem->left);
1495  denial_delfunc(elem->right);
1496 
1497  domain = denial->domain;
1498  if (domain) {
1499  domain->denial = NULL;
1500  }
1501  denial_cleanup(denial);
1502 
1503  free((void*)elem);
1504  }
1505  return;
1506 }
1507 
1508 
1513 static void
1514 zonedata_cleanup_domains(zonedata_type* zd)
1515 {
1516  if (zd && zd->domains) {
1517  domain_delfunc(zd->domains->root);
1518  ldns_rbtree_free(zd->domains);
1519  zd->domains = NULL;
1520  }
1521  return;
1522 }
1523 
1524 
1529 void
1531 {
1532  if (zd && zd->denial_chain) {
1533  denial_delfunc(zd->denial_chain->root);
1534  ldns_rbtree_free(zd->denial_chain);
1535  zd->denial_chain = NULL;
1536  }
1537  return;
1538 }
1539 
1540 
1545 void
1547 {
1548  allocator_type* allocator;
1549 
1550  if (!zd) {
1551  return;
1552  }
1554  zonedata_cleanup_domains(zd);
1555  allocator = zd->allocator;
1556  allocator_deallocate(allocator, (void*) zd);
1557  return;
1558 }
1559 
1560 
1565 void
1567 {
1568  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
1569  domain_type* domain = NULL;
1570 
1571  if (!fd || !zd) {
1572  return;
1573  }
1574 
1575  node = ldns_rbtree_first(zd->domains);
1576  while (node && node != LDNS_RBTREE_NULL) {
1577  domain = (domain_type*) node->data;
1578  domain_backup(fd, domain);
1579  node = ldns_rbtree_next(node);
1580  }
1581  fprintf(fd, ";;\n");
1582  return;
1583 }
1584 
1585 
1590 ods_status
1592 {
1593  ldns_rbnode_t* node = LDNS_RBTREE_NULL;
1594  domain_type* domain = NULL;
1595 
1596  if (!fd) {
1597  ods_log_error("[%s] unable to print zone data: no file descriptor",
1598  zd_str);
1599  return ODS_STATUS_ASSERT_ERR;
1600  }
1601  ods_log_assert(fd);
1602 
1603  if (!zd || !zd->domains) {
1604  ods_log_error("[%s] unable to print zone data: no zone data",
1605  zd_str);
1606  return ODS_STATUS_ASSERT_ERR;
1607  }
1608  ods_log_assert(zd);
1609  ods_log_assert(zd->domains);
1610 
1611  node = ldns_rbtree_first(zd->domains);
1612  if (!node || node == LDNS_RBTREE_NULL) {
1613  fprintf(fd, "; empty zone\n");
1614  return ODS_STATUS_OK;
1615  }
1616  while (node && node != LDNS_RBTREE_NULL) {
1617  domain = (domain_type*) node->data;
1618  domain_print(fd, domain);
1619  node = ldns_rbtree_next(node);
1620  }
1621  return ODS_STATUS_OK;
1622 }