dnssec_zone.c
Go to the documentation of this file.
1 /*
2  * special zone file structures and functions for better dnssec handling
3  */
4 
5 #include <ldns/config.h>
6 
7 #include <ldns/ldns.h>
8 
11 {
12  ldns_dnssec_rrs *new_rrs;
13  new_rrs = LDNS_MALLOC(ldns_dnssec_rrs);
14  if(!new_rrs) return NULL;
15  new_rrs->rr = NULL;
16  new_rrs->next = NULL;
17  return new_rrs;
18 }
19 
20 INLINE void
21 ldns_dnssec_rrs_free_internal(ldns_dnssec_rrs *rrs, int deep)
22 {
23  ldns_dnssec_rrs *next;
24  while (rrs) {
25  next = rrs->next;
26  if (deep) {
27  ldns_rr_free(rrs->rr);
28  }
29  LDNS_FREE(rrs);
30  rrs = next;
31  }
32 }
33 
34 void
36 {
37  ldns_dnssec_rrs_free_internal(rrs, 0);
38 }
39 
40 void
42 {
43  ldns_dnssec_rrs_free_internal(rrs, 1);
44 }
45 
48 {
49  int cmp;
50  ldns_dnssec_rrs *new_rrs;
51  if (!rrs || !rr) {
52  return LDNS_STATUS_ERR;
53  }
54 
55  /* this could be done more efficiently; name and type should already
56  be equal */
57  cmp = ldns_rr_compare(rrs->rr,
58  rr);
59  /* should we error on equal? */
60  if (cmp <= 0) {
61  if (rrs->next) {
62  return ldns_dnssec_rrs_add_rr(rrs->next, rr);
63  } else {
64  new_rrs = ldns_dnssec_rrs_new();
65  new_rrs->rr = rr;
66  rrs->next = new_rrs;
67  }
68  } else if (cmp > 0) {
69  /* put the current old rr in the new next, put the new
70  rr in the current container */
71  new_rrs = ldns_dnssec_rrs_new();
72  new_rrs->rr = rrs->rr;
73  new_rrs->next = rrs->next;
74  rrs->rr = rr;
75  rrs->next = new_rrs;
76  }
77  return LDNS_STATUS_OK;
78 }
79 
80 void
82  ldns_dnssec_rrs *rrs)
83 {
84  if (!rrs) {
85  if ((fmt->flags & LDNS_COMMENT_LAYOUT))
86  fprintf(out, "; <void>");
87  } else {
88  if (rrs->rr) {
89  ldns_rr_print_fmt(out, fmt, rrs->rr);
90  }
91  if (rrs->next) {
92  ldns_dnssec_rrs_print_fmt(out, fmt, rrs->next);
93  }
94  }
95 }
96 
97 void
99 {
101 }
102 
103 
106 {
107  ldns_dnssec_rrsets *new_rrsets;
108  new_rrsets = LDNS_MALLOC(ldns_dnssec_rrsets);
109  if(!new_rrsets) return NULL;
110  new_rrsets->rrs = NULL;
111  new_rrsets->type = 0;
112  new_rrsets->signatures = NULL;
113  new_rrsets->next = NULL;
114  return new_rrsets;
115 }
116 
117 INLINE void
118 ldns_dnssec_rrsets_free_internal(ldns_dnssec_rrsets *rrsets, int deep)
119 {
120  if (rrsets) {
121  if (rrsets->rrs) {
122  ldns_dnssec_rrs_free_internal(rrsets->rrs, deep);
123  }
124  if (rrsets->next) {
125  ldns_dnssec_rrsets_free_internal(rrsets->next, deep);
126  }
127  if (rrsets->signatures) {
128  ldns_dnssec_rrs_free_internal(rrsets->signatures, deep);
129  }
130  LDNS_FREE(rrsets);
131  }
132 }
133 
134 void
136 {
137  ldns_dnssec_rrsets_free_internal(rrsets, 0);
138 }
139 
140 void
142 {
143  ldns_dnssec_rrsets_free_internal(rrsets, 1);
144 }
145 
148 {
149  if (rrsets) {
150  return rrsets->type;
151  } else {
152  return 0;
153  }
154 }
155 
158  ldns_rr_type type)
159 {
160  if (rrsets) {
161  rrsets->type = type;
162  return LDNS_STATUS_OK;
163  }
164  return LDNS_STATUS_ERR;
165 }
166 
169 {
170  ldns_dnssec_rrsets *new_rrsets;
171  ldns_rr_type rr_type;
172  bool rrsig;
173 
174  new_rrsets = ldns_dnssec_rrsets_new();
175  rr_type = ldns_rr_get_type(rr);
176  if (rr_type == LDNS_RR_TYPE_RRSIG) {
177  rrsig = true;
179  } else {
180  rrsig = false;
181  }
182  if (!rrsig) {
183  new_rrsets->rrs = ldns_dnssec_rrs_new();
184  new_rrsets->rrs->rr = rr;
185  } else {
186  new_rrsets->signatures = ldns_dnssec_rrs_new();
187  new_rrsets->signatures->rr = rr;
188  }
189  new_rrsets->type = rr_type;
190  return new_rrsets;
191 }
192 
195 {
196  ldns_dnssec_rrsets *new_rrsets;
197  ldns_rr_type rr_type;
198  bool rrsig = false;
199  ldns_status result = LDNS_STATUS_OK;
200 
201  if (!rrsets || !rr) {
202  return LDNS_STATUS_ERR;
203  }
204 
205  rr_type = ldns_rr_get_type(rr);
206 
207  if (rr_type == LDNS_RR_TYPE_RRSIG) {
208  rrsig = true;
210  }
211 
212  if (!rrsets->rrs && rrsets->type == 0 && !rrsets->signatures) {
213  if (!rrsig) {
214  rrsets->rrs = ldns_dnssec_rrs_new();
215  rrsets->rrs->rr = rr;
216  rrsets->type = rr_type;
217  } else {
218  rrsets->signatures = ldns_dnssec_rrs_new();
219  rrsets->signatures->rr = rr;
220  rrsets->type = rr_type;
221  }
222  return LDNS_STATUS_OK;
223  }
224 
225  if (rr_type > ldns_dnssec_rrsets_type(rrsets)) {
226  if (rrsets->next) {
227  result = ldns_dnssec_rrsets_add_rr(rrsets->next, rr);
228  } else {
229  new_rrsets = ldns_dnssec_rrsets_new_frm_rr(rr);
230  rrsets->next = new_rrsets;
231  }
232  } else if (rr_type < ldns_dnssec_rrsets_type(rrsets)) {
233  /* move the current one into the new next,
234  replace field of current with data from new rr */
235  new_rrsets = ldns_dnssec_rrsets_new();
236  new_rrsets->rrs = rrsets->rrs;
237  new_rrsets->type = rrsets->type;
238  new_rrsets->signatures = rrsets->signatures;
239  new_rrsets->next = rrsets->next;
240  if (!rrsig) {
241  rrsets->rrs = ldns_dnssec_rrs_new();
242  rrsets->rrs->rr = rr;
243  rrsets->signatures = NULL;
244  } else {
245  rrsets->rrs = NULL;
246  rrsets->signatures = ldns_dnssec_rrs_new();
247  rrsets->signatures->rr = rr;
248  }
249  rrsets->type = rr_type;
250  rrsets->next = new_rrsets;
251  } else {
252  /* equal, add to current rrsets */
253  if (rrsig) {
254  if (rrsets->signatures) {
255  result = ldns_dnssec_rrs_add_rr(rrsets->signatures, rr);
256  } else {
257  rrsets->signatures = ldns_dnssec_rrs_new();
258  rrsets->signatures->rr = rr;
259  }
260  } else {
261  if (rrsets->rrs) {
262  result = ldns_dnssec_rrs_add_rr(rrsets->rrs, rr);
263  } else {
264  rrsets->rrs = ldns_dnssec_rrs_new();
265  rrsets->rrs->rr = rr;
266  }
267  }
268  }
269 
270  return result;
271 }
272 
273 void
275  ldns_dnssec_rrsets *rrsets,
276  bool follow,
277  bool show_soa)
278 {
279  if (!rrsets) {
280  if ((fmt->flags & LDNS_COMMENT_LAYOUT))
281  fprintf(out, "; <void>\n");
282  } else {
283  if (rrsets->rrs &&
284  (show_soa ||
286  )
287  ) {
288  ldns_dnssec_rrs_print_fmt(out, fmt, rrsets->rrs);
289  if (rrsets->signatures) {
290  ldns_dnssec_rrs_print_fmt(out, fmt,
291  rrsets->signatures);
292  }
293  }
294  if (follow && rrsets->next) {
296  rrsets->next, follow, show_soa);
297  }
298  }
299 }
300 
301 void
303  ldns_dnssec_rrsets *rrsets,
304  bool follow,
305  bool show_soa)
306 {
308  rrsets, follow, show_soa);
309 }
310 
311 
312 void
314  ldns_dnssec_rrsets *rrsets,
315  bool follow)
316 {
317  ldns_dnssec_rrsets_print_soa_fmt(out, fmt, rrsets, follow, true);
318 }
319 
320 void
321 ldns_dnssec_rrsets_print(FILE *out, ldns_dnssec_rrsets *rrsets, bool follow)
322 {
324  rrsets, follow);
325 }
326 
329 {
330  ldns_dnssec_name *new_name;
331 
332  new_name = LDNS_CALLOC(ldns_dnssec_name, 1);
333  if (!new_name) {
334  return NULL;
335  }
336  /*
337  * not needed anymore because CALLOC initalizes everything to zero.
338 
339  new_name->name = NULL;
340  new_name->rrsets = NULL;
341  new_name->name_alloced = false;
342  new_name->nsec = NULL;
343  new_name->nsec_signatures = NULL;
344 
345  new_name->is_glue = false;
346  new_name->hashed_name = NULL;
347 
348  */
349  return new_name;
350 }
351 
354 {
356 
357  new_name->name = ldns_rr_owner(rr);
358  if(ldns_dnssec_name_add_rr(new_name, rr) != LDNS_STATUS_OK) {
359  ldns_dnssec_name_free(new_name);
360  return NULL;
361  }
362 
363  return new_name;
364 }
365 
366 INLINE void
367 ldns_dnssec_name_free_internal(ldns_dnssec_name *name,
368  int deep)
369 {
370  if (name) {
371  if (name->name_alloced) {
372  ldns_rdf_deep_free(name->name);
373  }
374  if (name->rrsets) {
375  ldns_dnssec_rrsets_free_internal(name->rrsets, deep);
376  }
377  if (name->nsec && deep) {
378  ldns_rr_free(name->nsec);
379  }
380  if (name->nsec_signatures) {
381  ldns_dnssec_rrs_free_internal(name->nsec_signatures, deep);
382  }
383  if (name->hashed_name) {
384  if (deep) {
386  }
387  }
388  LDNS_FREE(name);
389  }
390 }
391 
392 void
394 {
395  ldns_dnssec_name_free_internal(name, 0);
396 }
397 
398 void
400 {
401  ldns_dnssec_name_free_internal(name, 1);
402 }
403 
404 ldns_rdf *
406 {
407  if (name) {
408  return name->name;
409  }
410  return NULL;
411 }
412 
413 bool
415 {
416  if (name) {
417  return name->is_glue;
418  }
419  return false;
420 }
421 
422 void
424  ldns_rdf *dname)
425 {
426  if (rrset && dname) {
427  rrset->name = dname;
428  }
429 }
430 
431 ldns_rr *
433 {
434  if (rrset) {
435  return rrset->nsec;
436  }
437  return NULL;
438 }
439 
440 void
442 {
443  if (rrset && nsec) {
444  rrset->nsec = nsec;
445  }
446 }
447 
448 int
449 ldns_dnssec_name_cmp(const void *a, const void *b)
450 {
453 
454  if (na && nb) {
457  } else if (na) {
458  return 1;
459  } else if (nb) {
460  return -1;
461  } else {
462  return 0;
463  }
464 }
465 
468  ldns_rr *rr)
469 {
470  ldns_status result = LDNS_STATUS_OK;
471  ldns_rdf *name_name;
472  bool hashed_name = false;
473  ldns_rr_type rr_type;
474  ldns_rr_type typecovered = 0;
475 
476  /* special handling for NSEC3 and NSECX covering RRSIGS */
477 
478  if (!name || !rr) {
479  return LDNS_STATUS_ERR;
480  }
481 
482  rr_type = ldns_rr_get_type(rr);
483 
484  if (rr_type == LDNS_RR_TYPE_RRSIG) {
485  typecovered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
486  }
487 
488 #ifdef HAVE_SSL
489  if (rr_type == LDNS_RR_TYPE_NSEC3 ||
490  typecovered == LDNS_RR_TYPE_NSEC3) {
491  name_name = ldns_nsec3_hash_name_frm_nsec3(rr,
492  ldns_dnssec_name_name(name));
493  hashed_name = true;
494  } else {
495  name_name = ldns_dnssec_name_name(name);
496  }
497 #else
498  name_name = ldns_dnssec_name_name(name);
499 #endif /* HAVE_SSL */
500 
501  if (rr_type == LDNS_RR_TYPE_NSEC ||
502  rr_type == LDNS_RR_TYPE_NSEC3) {
503  /* XX check if is already set (and error?) */
504  name->nsec = rr;
505  } else if (typecovered == LDNS_RR_TYPE_NSEC ||
506  typecovered == LDNS_RR_TYPE_NSEC3) {
507  if (name->nsec_signatures) {
508  result = ldns_dnssec_rrs_add_rr(name->nsec_signatures, rr);
509  } else {
511  name->nsec_signatures->rr = rr;
512  }
513  } else {
514  /* it's a 'normal' RR, add it to the right rrset */
515  if (name->rrsets) {
516  result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
517  } else {
518  name->rrsets = ldns_dnssec_rrsets_new();
519  result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
520  }
521  }
522 
523  if (hashed_name) {
524  ldns_rdf_deep_free(name_name);
525  }
526 
527  return result;
528 }
529 
532  ldns_rr_type type) {
533  ldns_dnssec_rrsets *result;
534 
535  result = name->rrsets;
536  while (result) {
537  if (result->type == type) {
538  return result;
539  } else {
540  result = result->next;
541  }
542  }
543  return NULL;
544 }
545 
548  ldns_rdf *dname,
549  ldns_rr_type type)
550 {
551  ldns_rbnode_t *node;
552 
553  if (!zone || !dname) {
554  return NULL;
555  }
556 
557  node = ldns_rbtree_search(zone->names, dname);
558  if (node) {
560  type);
561  } else {
562  return NULL;
563  }
564 }
565 
566 void
568  ldns_dnssec_name *name,
569  bool show_soa)
570 {
571  if (name) {
572  if(name->rrsets) {
574  name->rrsets, true, show_soa);
575  } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
576  fprintf(out, ";; Empty nonterminal: ");
577  ldns_rdf_print(out, name->name);
578  fprintf(out, "\n");
579  }
580  if(name->nsec) {
581  ldns_rr_print_fmt(out, fmt, name->nsec);
582  }
583  if (name->nsec_signatures) {
584  ldns_dnssec_rrs_print_fmt(out, fmt,
585  name->nsec_signatures);
586  }
587  } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
588  fprintf(out, "; <void>\n");
589  }
590 }
591 
592 void
593 ldns_dnssec_name_print_soa(FILE *out, ldns_dnssec_name *name, bool show_soa)
594 {
596  name, show_soa);
597 }
598 
599 void
601  ldns_dnssec_name *name)
602 {
603  ldns_dnssec_name_print_soa_fmt(out, fmt, name, true);
604 }
605 
606 void
608 {
610 }
611 
612 
615 {
617  if(!zone) return NULL;
618  zone->soa = NULL;
619  zone->names = NULL;
620 
621  return zone;
622 }
623 
624 static bool
625 rr_is_rrsig_covering(ldns_rr* rr, ldns_rr_type t)
626 {
629 }
630 
631 /* When the zone is first read into an list and then inserted into an
632  * ldns_dnssec_zone (rbtree) the nodes of the rbtree are allocated close (next)
633  * to each other. Because ldns-verify-zone (the only program that uses this
634  * function) uses the rbtree mostly for sequentual walking, this results
635  * in a speed increase (of 15% on linux) because we have less CPU-cache misses.
636  */
637 #define FASTER_DNSSEC_ZONE_NEW_FRM_FP 1 /* Because of L2 cache efficiency */
638 
641  uint32_t ttl, ldns_rr_class ATTR_UNUSED(c), int* line_nr)
642 {
643  ldns_rr* cur_rr;
644  size_t i;
645 
646  ldns_rdf *my_origin = NULL;
647  ldns_rdf *my_prev = NULL;
648 
650  /* when reading NSEC3s, there is a chance that we encounter nsecs
651  for empty nonterminals, whose nonterminals we cannot derive yet
652  because the needed information is to be read later. in that case
653  we keep a list of those nsec3's and retry to add them later */
654  ldns_rr_list* todo_nsec3s = ldns_rr_list_new();
655  ldns_rr_list* todo_nsec3_rrsigs = ldns_rr_list_new();
656 
658 
659 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
660  ldns_zone* zone = NULL;
661  if (ldns_zone_new_frm_fp_l(&zone, fp, origin,ttl, c, line_nr)
662  != LDNS_STATUS_OK) goto error;
663 #else
664  uint32_t my_ttl = ttl;
665 #endif
666 
667  if (!newzone || !todo_nsec3s || !todo_nsec3_rrsigs ) goto error;
668 
669  if (origin) {
670  if (!(my_origin = ldns_rdf_clone(origin))) goto error;
671  if (!(my_prev = ldns_rdf_clone(origin))) goto error;
672  }
673 
674 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
675  if (ldns_dnssec_zone_add_rr(newzone, ldns_zone_soa(zone))
676  != LDNS_STATUS_OK) goto error;
677 
678  for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
679  cur_rr = ldns_rr_list_rr(ldns_zone_rrs(zone), i);
680  status = LDNS_STATUS_OK;
681 #else
682  while (!feof(fp)) {
683  status = ldns_rr_new_frm_fp_l(&cur_rr, fp, &my_ttl, &my_origin,
684  &my_prev, line_nr);
685 
686 #endif
687  switch (status) {
688  case LDNS_STATUS_OK:
689 
690  status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
691  if (status ==
693 
694  if (rr_is_rrsig_covering(cur_rr,
696  ldns_rr_list_push_rr(todo_nsec3_rrsigs,
697  cur_rr);
698  } else {
699  ldns_rr_list_push_rr(todo_nsec3s,
700  cur_rr);
701  }
702  } else if (status != LDNS_STATUS_OK)
703  goto error;
704 
705  break;
706 
707 
708  case LDNS_STATUS_SYNTAX_EMPTY: /* empty line was seen */
709  case LDNS_STATUS_SYNTAX_TTL: /* the ttl was set*/
710  case LDNS_STATUS_SYNTAX_ORIGIN: /* the origin was set*/
711  status = LDNS_STATUS_OK;
712  break;
713 
714  case LDNS_STATUS_SYNTAX_INCLUDE:/* $include not implemented */
716  break;
717 
718  default:
719  goto error;
720  }
721  }
722 
723  if (ldns_rr_list_rr_count(todo_nsec3s) > 0) {
725  for (i = 0; status == LDNS_STATUS_OK &&
726  i < ldns_rr_list_rr_count(todo_nsec3s); i++) {
727  cur_rr = ldns_rr_list_rr(todo_nsec3s, i);
728  status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
729  }
730  for (i = 0; status == LDNS_STATUS_OK &&
731  i < ldns_rr_list_rr_count(todo_nsec3_rrsigs);
732  i++){
733  cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i);
734  status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
735  }
736  } else if (ldns_rr_list_rr_count(todo_nsec3_rrsigs) > 0) {
737  for (i = 0; status == LDNS_STATUS_OK &&
738  i < ldns_rr_list_rr_count(todo_nsec3_rrsigs);
739  i++){
740  cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i);
741  status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
742  }
743  }
744 
745  if (z) {
746  *z = newzone;
747  newzone = NULL;
748  } else {
749  ldns_dnssec_zone_free(newzone);
750  }
751 
752 error:
753 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
754  if (zone) {
755  ldns_zone_free(zone);
756  }
757 #endif
758  ldns_rr_list_free(todo_nsec3_rrsigs);
759  ldns_rr_list_free(todo_nsec3s);
760 
761  if (my_origin) {
762  ldns_rdf_deep_free(my_origin);
763  }
764  if (my_prev) {
765  ldns_rdf_deep_free(my_prev);
766  }
767  if (newzone) {
768  ldns_dnssec_zone_free(newzone);
769  }
770  return status;
771 }
772 
775  uint32_t ttl, ldns_rr_class ATTR_UNUSED(c))
776 {
777  return ldns_dnssec_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL);
778 }
779 
780 void
782  (void) arg;
784  LDNS_FREE(node);
785 }
786 
787 void
789  (void) arg;
791  LDNS_FREE(node);
792 }
793 
794 void
796 {
797  if (zone) {
798  if (zone->names) {
799  /* destroy all name structures within the tree */
802  NULL);
803  LDNS_FREE(zone->names);
804  }
805  LDNS_FREE(zone);
806  }
807 }
808 
809 void
811 {
812  if (zone) {
813  if (zone->names) {
814  /* destroy all name structures within the tree */
817  NULL);
818  LDNS_FREE(zone->names);
819  }
820  LDNS_FREE(zone);
821  }
822 }
823 
824 /* use for dname comparison in tree */
825 int
826 ldns_dname_compare_v(const void *a, const void *b) {
827  return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b);
828 }
829 
832  ldns_rr *rr) {
833  ldns_rbnode_t *current_node = ldns_rbtree_first(zone->names);
834  ldns_dnssec_name *current_name;
835  ldns_rdf *hashed_name;
836 
837  hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0);
838 
839  while (current_node != LDNS_RBTREE_NULL) {
840  current_name = (ldns_dnssec_name *) current_node->data;
841  if (!current_name->hashed_name) {
842  current_name->hashed_name =
843  ldns_nsec3_hash_name_frm_nsec3(rr, current_name->name);
844  }
845  if (ldns_dname_compare(hashed_name,
846  current_name->hashed_name)
847  == 0) {
848  ldns_rdf_deep_free(hashed_name);
849  return current_node;
850  }
851  current_node = ldns_rbtree_next(current_node);
852  }
853  ldns_rdf_deep_free(hashed_name);
854  return NULL;
855 }
856 
859 {
860  ldns_status result = LDNS_STATUS_OK;
861  ldns_dnssec_name *cur_name;
862  ldns_rbnode_t *cur_node;
863  ldns_rr_type type_covered = 0;
864 
865  if (!zone || !rr) {
866  return LDNS_STATUS_ERR;
867  }
868 
869  if (!zone->names) {
871  if(!zone->names) return LDNS_STATUS_MEM_ERR;
872  }
873 
874  /* we need the original of the hashed name if this is
875  an NSEC3, or an RRSIG that covers an NSEC3 */
877  type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
878  }
880  type_covered == LDNS_RR_TYPE_NSEC3) {
881  cur_node = ldns_dnssec_zone_find_nsec3_original(zone,
882  rr);
883  if (!cur_node) {
885  }
886  } else {
887  cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr));
888  }
889 
890  if (!cur_node) {
891  /* add */
892  cur_name = ldns_dnssec_name_new_frm_rr(rr);
893  if(!cur_name) return LDNS_STATUS_MEM_ERR;
894  cur_node = LDNS_MALLOC(ldns_rbnode_t);
895  if(!cur_node) {
896  ldns_dnssec_name_free(cur_name);
897  return LDNS_STATUS_MEM_ERR;
898  }
899  cur_node->key = ldns_rr_owner(rr);
900  cur_node->data = cur_name;
901  (void)ldns_rbtree_insert(zone->names, cur_node);
902  } else {
903  cur_name = (ldns_dnssec_name *) cur_node->data;
904  result = ldns_dnssec_name_add_rr(cur_name, rr);
905  }
906 
907  if (result != LDNS_STATUS_OK) {
908  fprintf(stderr, "error adding rr: ");
909  ldns_rr_print(stderr, rr);
910  }
911 
912  /*TODO ldns_dnssec_name_print_names(stdout, zone->names, 0);*/
913  if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
914  zone->soa = cur_name;
915  }
916 
917  return result;
918 }
919 
920 void
922  ldns_rbtree_t *tree,
923  bool print_soa)
924 {
925  ldns_rbnode_t *node;
926  ldns_dnssec_name *name;
927 
928  node = ldns_rbtree_first(tree);
929  while (node != LDNS_RBTREE_NULL) {
930  name = (ldns_dnssec_name *) node->data;
931  ldns_dnssec_name_print_soa_fmt(out, fmt, name, print_soa);
932  if ((fmt->flags & LDNS_COMMENT_LAYOUT))
933  fprintf(out, ";\n");
934  node = ldns_rbtree_next(node);
935  }
936 }
937 
938 void
939 ldns_dnssec_zone_names_print(FILE *out, ldns_rbtree_t *tree, bool print_soa)
940 {
942  tree, print_soa);
943 }
944 
945 void
947  ldns_dnssec_zone *zone)
948 {
949  if (zone) {
950  if (zone->soa) {
951  if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
952  fprintf(out, ";; Zone: ");
954  zone->soa));
955  fprintf(out, "\n;\n");
956  }
959  zone->soa,
961  false);
962  if ((fmt->flags & LDNS_COMMENT_LAYOUT))
963  fprintf(out, ";\n");
964  }
965 
966  if (zone->names) {
968  zone->names, false);
969  }
970  }
971 }
972 
973 void
975 {
977 }
978 
981 {
982  ldns_dnssec_name *new_name;
983  ldns_rdf *cur_name;
984  ldns_rdf *next_name;
985  ldns_rbnode_t *cur_node, *next_node, *new_node;
986 
987  /* for the detection */
988  uint16_t i, cur_label_count, next_label_count;
989  uint16_t soa_label_count = 0;
990  ldns_rdf *l1, *l2;
991  int lpos;
992 
993  if (!zone) {
994  return LDNS_STATUS_ERR;
995  }
996  if (zone->soa && zone->soa->name) {
997  soa_label_count = ldns_dname_label_count(zone->soa->name);
998  }
999 
1000  cur_node = ldns_rbtree_first(zone->names);
1001  while (cur_node != LDNS_RBTREE_NULL) {
1002  next_node = ldns_rbtree_next(cur_node);
1003 
1004  /* skip glue */
1005  while (next_node != LDNS_RBTREE_NULL &&
1006  next_node->data &&
1007  ((ldns_dnssec_name *)next_node->data)->is_glue
1008  ) {
1009  next_node = ldns_rbtree_next(next_node);
1010  }
1011 
1012  if (next_node == LDNS_RBTREE_NULL) {
1013  next_node = ldns_rbtree_first(zone->names);
1014  }
1015  if (! cur_node->data || ! next_node->data) {
1016  return LDNS_STATUS_ERR;
1017  }
1018  cur_name = ((ldns_dnssec_name *)cur_node->data)->name;
1019  next_name = ((ldns_dnssec_name *)next_node->data)->name;
1020  cur_label_count = ldns_dname_label_count(cur_name);
1021  next_label_count = ldns_dname_label_count(next_name);
1022 
1023  /* Since the names are in canonical order, we can
1024  * recognize empty non-terminals by their labels;
1025  * every label after the first one on the next owner
1026  * name is a non-terminal if it either does not exist
1027  * in the current name or is different from the same
1028  * label in the current name (counting from the end)
1029  */
1030  for (i = 1; i < next_label_count - soa_label_count; i++) {
1031  lpos = (int)cur_label_count - (int)next_label_count + (int)i;
1032  if (lpos >= 0) {
1033  l1 = ldns_dname_clone_from(cur_name, (uint8_t)lpos);
1034  } else {
1035  l1 = NULL;
1036  }
1037  l2 = ldns_dname_clone_from(next_name, i);
1038 
1039  if (!l1 || ldns_dname_compare(l1, l2) != 0) {
1040  /* We have an empty nonterminal, add it to the
1041  * tree
1042  */
1043  new_name = ldns_dnssec_name_new();
1044  if (!new_name) {
1045  return LDNS_STATUS_MEM_ERR;
1046  }
1047  new_name->name = ldns_dname_clone_from(next_name,
1048  i);
1049  if (!new_name->name) {
1050  ldns_dnssec_name_free(new_name);
1051  return LDNS_STATUS_MEM_ERR;
1052  }
1053  new_name->name_alloced = true;
1054  new_node = LDNS_MALLOC(ldns_rbnode_t);
1055  if (!new_node) {
1056  ldns_dnssec_name_free(new_name);
1057  return LDNS_STATUS_MEM_ERR;
1058  }
1059  new_node->key = new_name->name;
1060  new_node->data = new_name;
1061  (void)ldns_rbtree_insert(zone->names, new_node);
1062  }
1063  ldns_rdf_deep_free(l1);
1064  ldns_rdf_deep_free(l2);
1065  }
1066 
1067  /* we might have inserted a new node after
1068  * the current one so we can't just use next()
1069  */
1070  if (next_node != ldns_rbtree_first(zone->names)) {
1071  cur_node = next_node;
1072  } else {
1073  cur_node = LDNS_RBTREE_NULL;
1074  }
1075  }
1076  return LDNS_STATUS_OK;
1077 }
1078 
1079 bool
1081 {
1082  ldns_rr* nsec3;
1083  ldns_rbnode_t* node;
1084 
1086  node = ldns_rbtree_first(zone->names);
1087  while (node != LDNS_RBTREE_NULL) {
1088  nsec3 = ((ldns_dnssec_name*)node->data)->nsec;
1089  if (nsec3 &&ldns_rr_get_type(nsec3)
1090  == LDNS_RR_TYPE_NSEC3 &&
1091  ldns_nsec3_optout(nsec3)) {
1092  return true;
1093  }
1094  node = ldns_rbtree_next(node);
1095  }
1096  }
1097  return false;
1098 }
ldns_dnssec_rrs * rrs
Definition: dnssec_zone.h:34
ldns_rr_list * ldns_rr_list_new()
creates a new rr_list structure.
Definition: rr.c:939
void ldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg)
Definition: dnssec_zone.c:781
void ldns_dnssec_rrs_deep_free(ldns_dnssec_rrs *rrs)
Frees the list of rrs, and the individual ldns_rr records contained in the list.
Definition: dnssec_zone.c:41
ldns_rr * ldns_zone_soa(const ldns_zone *z)
Return the soa record of a zone.
Definition: zone.c:17
ldns_dnssec_zone * ldns_dnssec_zone_new()
Creates a new dnssec_zone structure.
Definition: dnssec_zone.c:614
void ldns_rdf_deep_free(ldns_rdf *rd)
frees a rdf structure and frees the data.
Definition: rdata.c:230
void ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone)
Frees the given zone structure, and its rbtree of dnssec_names Individual ldns_rr RRs within those na...
Definition: dnssec_zone.c:810
uint8_t ldns_dname_label_count(const ldns_rdf *r)
count the number of labels inside a LDNS_RDF_DNAME type rdf.
Definition: dname.c:214
ldns_rr_type ldns_rdf2rr_type(const ldns_rdf *rd)
convert an rdf of type LDNS_RDF_TYPE_TYPE to an actual LDNS_RR_TYPE.
Definition: rr.c:2410
DNSSEC.
Definition: rr.h:173
ldns_status ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone **z, FILE *fp, ldns_rdf *origin, uint32_t ttl, ldns_rr_class c __attribute__((unused)), int *line_nr)
Definition: dnssec_zone.c:640
void ldns_dnssec_rrsets_print_fmt(FILE *out, const ldns_output_format *fmt, ldns_dnssec_rrsets *rrsets, bool follow)
Definition: dnssec_zone.c:313
int ldns_dname_compare(const ldns_rdf *dname1, const ldns_rdf *dname2)
Compares the two dname rdf&#39;s according to the algorithm for ordering in RFC4034 Section 6...
Definition: dname.c:356
ldns_rbnode_t * ldns_rbtree_insert(ldns_rbtree_t *rbtree, ldns_rbnode_t *data)
Insert data into the tree.
Definition: rbtree.c:242
ldns_rr * ldns_dnssec_name_nsec(ldns_dnssec_name *rrset)
Definition: dnssec_zone.c:432
enum ldns_enum_rr_class ldns_rr_class
Definition: rr.h:64
bool ldns_rr_list_push_rr(ldns_rr_list *rr_list, const ldns_rr *rr)
pushes an rr to an rrlist.
Definition: rr.c:1071
List or Set of Resource Records.
Definition: rr.h:306
Output format specifier.
Definition: host2str.h:80
signed char name_alloced
Usually, the name is a pointer to the owner name of the first rr for this name, but sometimes there i...
Definition: dnssec_zone.h:59
bool ldns_dnssec_name_is_glue(ldns_dnssec_name *name)
Returns if dnssec_name structure is marked as glue.
Definition: dnssec_zone.c:414
ldns_dnssec_rrsets * rrsets
The rrsets for this name.
Definition: dnssec_zone.h:63
ldns_status ldns_zone_new_frm_fp_l(ldns_zone **z, FILE *fp, ldns_rdf *origin, uint32_t ttl, ldns_rr_class c __attribute__((unused)), int *line_nr)
Definition: zone.c:292
#define LDNS_CALLOC(type, count)
Definition: util.h:53
DNS Zone.
Definition: zone.h:42
ldns_rdf * ldns_rdf_clone(const ldns_rdf *rd)
clones a rdf structure.
Definition: rdata.c:222
void ldns_dnssec_zone_print_fmt(FILE *out, const ldns_output_format *fmt, ldns_dnssec_zone *zone)
Prints the complete zone to the given file descriptor.
Definition: dnssec_zone.c:946
ldns_rdf * ldns_nsec3_hash_name_frm_nsec3(const ldns_rr *nsec, ldns_rdf *name)
Calculates the hashed name using the parameters of the given NSEC3 RR.
Definition: dnssec.c:1316
ldns_dnssec_name * ldns_dnssec_name_new()
Create a new data structure for a dnssec name.
Definition: dnssec_zone.c:328
void ldns_rr_free(ldns_rr *rr)
frees an RR structure
Definition: rr.c:75
void ldns_dnssec_name_set_nsec(ldns_dnssec_name *rrset, ldns_rr *nsec)
Sets the NSEC(3) RR of the given dnssec_name structure.
Definition: dnssec_zone.c:441
ldns_rbnode_t * ldns_dnssec_zone_find_nsec3_original(ldns_dnssec_zone *zone, ldns_rr *rr)
Definition: dnssec_zone.c:831
Structure containing a dnssec zone.
Definition: dnssec_zone.h:91
void ldns_rr_list_free(ldns_rr_list *rr_list)
frees an rr_list structure.
Definition: rr.c:950
ldns_rr_type ldns_dnssec_rrsets_type(ldns_dnssec_rrsets *rrsets)
Returns the rr type of the rrset (that is head of the given list)
Definition: dnssec_zone.c:147
ldns_status ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets, ldns_rr_type type)
Sets the RR type of the rrset (that is head of the given list)
Definition: dnssec_zone.c:157
const ldns_output_format * ldns_output_format_default
The default output format record.
Definition: host2str.c:125
Resource Record.
Definition: rr.h:278
#define INLINE
splint static inline workaround
Definition: util.h:42
const void * data
pointer to data
Definition: rbtree.h:70
ldns_status ldns_dnssec_name_add_rr(ldns_dnssec_name *name, ldns_rr *rr)
Inserts the given rr at the right place in the current dnssec_name No checking is done whether the na...
Definition: dnssec_zone.c:467
ldns_rbtree_t * names
tree of ldns_dnssec_names
Definition: dnssec_zone.h:95
Including this file will include all ldns files, and define some lookup tables.
marks the start of a zone of authority
Definition: rr.h:93
void ldns_dnssec_name_free(ldns_dnssec_name *name)
Frees the name structure and its rrs and rrsets.
Definition: dnssec_zone.c:393
ldns_dnssec_rrsets * ldns_dnssec_rrsets_new()
Creates a new list (entry) of RRsets.
Definition: dnssec_zone.c:105
void ldns_dnssec_name_set_name(ldns_dnssec_name *rrset, ldns_rdf *dname)
Sets the domain name of the given dnssec_name structure.
Definition: dnssec_zone.c:423
ldns_rdf * ldns_dname_clone_from(const ldns_rdf *d, uint16_t n)
Clones the given dname from the nth label on.
Definition: dname.c:160
ldns_rr * ldns_rr_list_rr(const ldns_rr_list *rr_list, size_t nr)
returns a specific rr of an rrlist.
Definition: rr.c:929
void ldns_rr_print_fmt(FILE *output, const ldns_output_format *fmt, const ldns_rr *rr)
Prints the data in the resource record to the given file stream (in presentation format) ...
Definition: host2str.c:2228
ldns_status ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr)
Adds the given RR to the zone.
Definition: dnssec_zone.c:858
#define ATTR_UNUSED(x)
Definition: common.h:64
void ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt, ldns_rbtree_t *tree, bool print_soa)
Definition: dnssec_zone.c:921
The rbnode_t struct definition.
Definition: rbtree.h:60
void ldns_dnssec_name_print_fmt(FILE *out, const ldns_output_format *fmt, ldns_dnssec_name *name)
Prints the RRs in the dnssec name structure to the given file descriptor.
Definition: dnssec_zone.c:600
ldns_rbtree_t * ldns_rbtree_create(int(*cmpf)(const void *, const void *))
Create new tree (malloced) with given key compare function.
Definition: rbtree.c:80
bool ldns_dnssec_zone_is_nsec3_optout(ldns_dnssec_zone *zone)
If a NSEC3PARAM is available in the apex, walks the zone and returns true on the first optout nsec3...
Definition: dnssec_zone.c:1080
signed char is_glue
Unlike what the name is_glue suggests, this field is set to true by ldns_dnssec_zone_mark_glue() or l...
Definition: dnssec_zone.h:81
void ldns_dnssec_rrs_print_fmt(FILE *out, const ldns_output_format *fmt, ldns_dnssec_rrs *rrs)
Prints the given rrs to the file descriptor.
Definition: dnssec_zone.c:81
void ldns_dnssec_name_print_soa(FILE *out, ldns_dnssec_name *name, bool show_soa)
Definition: dnssec_zone.c:593
ldns_dnssec_rrs * signatures
Definition: dnssec_zone.h:36
int flags
Specification of how RR&#39;s should be formatted in text.
Definition: host2str.h:83
return NULL
Definition: keys.c:738
int ldns_dname_compare_v(const void *a, const void *b)
Definition: dnssec_zone.c:826
void ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets *rrsets)
Frees the list of rrsets and their rrs, and the ldns_rr records in the sets.
Definition: dnssec_zone.c:141
bool ldns_nsec3_optout(const ldns_rr *nsec3_rr)
Returns true if the opt-out flag has been set in the given NSEC3 RR.
Definition: dnssec.c:1236
int ldns_rr_compare(const ldns_rr *rr1, const ldns_rr *rr2)
compares two rrs.
Definition: rr.c:1594
ldns_rbnode_t * ldns_rbtree_search(ldns_rbtree_t *rbtree, const void *key)
Find key in tree.
Definition: rbtree.c:294
definition for tree struct
Definition: rbtree.h:83
void ldns_rdf_print(FILE *output, const ldns_rdf *rdf)
Prints the data in the rdata field to the given file stream (in presentation format) ...
Definition: host2str.c:2216
ldns_rr_type ldns_rr_get_type(const ldns_rr *rr)
returns the type of the rr.
Definition: rr.c:882
ldns_rdf * ldns_rr_rrsig_typecovered(const ldns_rr *r)
returns the type covered of a LDNS_RR_TYPE_RRSIG rr
Definition: rr_functions.c:111
ldns_status ldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone **z, FILE *fp, ldns_rdf *origin, uint32_t ttl, ldns_rr_class c __attribute__((unused)))
Definition: dnssec_zone.c:774
ldns_dnssec_name * soa
points to the name containing the SOA RR
Definition: dnssec_zone.h:93
void ldns_dnssec_rrs_print(FILE *out, ldns_dnssec_rrs *rrs)
Prints the given rrs to the file descriptor.
Definition: dnssec_zone.c:98
enum ldns_enum_status ldns_status
Definition: error.h:122
ldns_dnssec_rrs * next
Definition: dnssec_zone.h:25
#define LDNS_MALLOC(type)
Memory management macros.
Definition: util.h:49
ldns_dnssec_rrsets * ldns_dnssec_name_find_rrset(ldns_dnssec_name *name, ldns_rr_type type)
Find the RRset with the given type in within this name structure.
Definition: dnssec_zone.c:531
ldns_dnssec_rrs * ldns_dnssec_rrs_new()
Creates a new entry for 1 pointer to an rr and 1 pointer to the next rrs.
Definition: dnssec_zone.c:10
ldns_rdf * hashed_name
pointer to store the hashed name (only used when in an NSEC3 zone
Definition: dnssec_zone.h:85
void ldns_dnssec_name_print(FILE *out, ldns_dnssec_name *name)
Prints the RRs in the dnssec name structure to the given file descriptor.
Definition: dnssec_zone.c:607
void ldns_dnssec_zone_free(ldns_dnssec_zone *zone)
Frees the given zone structure, and its rbtree of dnssec_names Individual ldns_rr RRs within those na...
Definition: dnssec_zone.c:795
void ldns_dnssec_rrs_free(ldns_dnssec_rrs *rrs)
Frees the list of rrs, but not the individual ldns_rr records contained in the list.
Definition: dnssec_zone.c:35
ldns_status ldns_rr_new_frm_fp_l(ldns_rr **newrr, FILE *fp, uint32_t *default_ttl, ldns_rdf **origin, ldns_rdf **prev, int *line_nr)
creates a new rr from a file containing a string.
Definition: rr.c:655
void ldns_rr_print(FILE *output, const ldns_rr *rr)
Prints the data in the resource record to the given file stream (in presentation format) ...
Definition: host2str.c:2241
void ldns_dnssec_rrsets_print_soa(FILE *out, ldns_dnssec_rrsets *rrsets, bool follow, bool show_soa)
Definition: dnssec_zone.c:302
void ldns_dnssec_rrsets_print_soa_fmt(FILE *out, const ldns_output_format *fmt, ldns_dnssec_rrsets *rrsets, bool follow, bool show_soa)
Definition: dnssec_zone.c:274
void ldns_dnssec_rrsets_print(FILE *out, ldns_dnssec_rrsets *rrsets, bool follow)
Definition: dnssec_zone.c:321
#define LDNS_RBTREE_NULL
The nullpointer, points to empty node.
Definition: rbtree.h:76
ldns_rr_list * ldns_zone_rrs(const ldns_zone *z)
Get a list of a zone&#39;s content.
Definition: zone.c:35
ldns_dnssec_name * ldns_dnssec_name_new_frm_rr(ldns_rr *rr)
Create a new data structure for a dnssec name for the given RR.
Definition: dnssec_zone.c:353
const void * key
pointer to sorting key
Definition: rbtree.h:68
void ldns_dnssec_zone_print(FILE *out, ldns_dnssec_zone *zone)
Prints the complete zone to the given file descriptor.
Definition: dnssec_zone.c:974
ldns_status ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr)
Add an ldns_rr to the corresponding RRset in the given list of RRsets.
Definition: dnssec_zone.c:194
Resource record data field.
Definition: rdata.h:138
void ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets)
Frees the list of rrsets and their rrs, but not the ldns_rr records in the sets.
Definition: dnssec_zone.c:135
ldns_dnssec_rrsets * next
Definition: dnssec_zone.h:37
void ldns_dnssec_name_node_deep_free(ldns_rbnode_t *node, void *arg)
Definition: dnssec_zone.c:788
void ldns_traverse_postorder(ldns_rbtree_t *tree, void(*func)(ldns_rbnode_t *, void *), void *arg)
Call function for all elements in the redblack tree, such that leaf elements are called before parent...
Definition: rbtree.c:666
ldns_rdf * ldns_rr_owner(const ldns_rr *rr)
returns the owner name of an rr structure.
Definition: rr.c:858
size_t ldns_rr_list_rr_count(const ldns_rr_list *rr_list)
returns the number of rr&#39;s in an rr_list.
Definition: rr.c:896
enum ldns_enum_rr_type ldns_rr_type
Definition: rr.h:215
#define LDNS_FREE(ptr)
Definition: util.h:60
#define LDNS_COMMENT_LAYOUT
Print mark up.
Definition: host2str.h:64
void ldns_dnssec_name_deep_free(ldns_dnssec_name *name)
Frees the name structure and its rrs and rrsets.
Definition: dnssec_zone.c:399
ldns_rbnode_t * ldns_rbtree_first(ldns_rbtree_t *rbtree)
Returns first (smallest) node in the tree.
Definition: rbtree.c:548
void ldns_dnssec_zone_names_print(FILE *out, ldns_rbtree_t *tree, bool print_soa)
Definition: dnssec_zone.c:939
ldns_rdf * ldns_dname_label(const ldns_rdf *rdf, uint8_t labelpos)
look inside the rdf and if it is an LDNS_RDF_TYPE_DNAME try and retrieve a specific label...
Definition: dname.c:556
ldns_dnssec_rrsets * ldns_dnssec_zone_find_rrset(ldns_dnssec_zone *zone, ldns_rdf *dname, ldns_rr_type type)
Find the RRset with the given name and type in the zone.
Definition: dnssec_zone.c:547
void ldns_zone_free(ldns_zone *zone)
Frees the allocated memory for the zone, and the rr_list structure in it.
Definition: zone.c:419
ldns_dnssec_rrs * nsec_signatures
signatures for the NSEC record
Definition: dnssec_zone.h:71
ldns_rbnode_t * ldns_rbtree_next(ldns_rbnode_t *node)
Returns next larger node in the tree.
Definition: rbtree.c:574
ldns_rdf * ldns_dnssec_name_name(ldns_dnssec_name *name)
Returns the domain name of the given dnssec_name structure.
Definition: dnssec_zone.c:405
ldns_status ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
Adds explicit dnssec_name structures for the empty nonterminals in this zone.
Definition: dnssec_zone.c:980
int ldns_dnssec_name_cmp(const void *a, const void *b)
Compares the domain names of the two arguments in their canonical ordening.
Definition: dnssec_zone.c:449
if(!d||!dsa||!buf)
Definition: keys.c:671
ldns_status ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr)
Adds an RR to the list of RRs.
Definition: dnssec_zone.c:47
void ldns_dnssec_name_print_soa_fmt(FILE *out, const ldns_output_format *fmt, ldns_dnssec_name *name, bool show_soa)
Definition: dnssec_zone.c:567
ldns_dnssec_rrsets * ldns_dnssec_rrsets_new_frm_rr(ldns_rr *rr)
Definition: dnssec_zone.c:168
ldns_rr * nsec
NSEC pointing to the next name (or NSEC3 pointing to the next NSEC3)
Definition: dnssec_zone.h:67
int
Definition: dnssec.c:1575
i
Definition: keys.c:681
ldns_rdf * name
pointer to a dname containing the name.
Definition: dnssec_zone.h:51