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, rr);
58  if (cmp < 0) {
59  if (rrs->next) {
60  return ldns_dnssec_rrs_add_rr(rrs->next, rr);
61  } else {
62  new_rrs = ldns_dnssec_rrs_new();
63  new_rrs->rr = rr;
64  rrs->next = new_rrs;
65  }
66  } else if (cmp > 0) {
67  /* put the current old rr in the new next, put the new
68  rr in the current container */
69  new_rrs = ldns_dnssec_rrs_new();
70  new_rrs->rr = rrs->rr;
71  new_rrs->next = rrs->next;
72  rrs->rr = rr;
73  rrs->next = new_rrs;
74  }
75  /* Silently ignore equal rr's */
76  return LDNS_STATUS_OK;
77 }
78 
79 void
81  ldns_dnssec_rrs *rrs)
82 {
83  if (!rrs) {
84  if ((fmt->flags & LDNS_COMMENT_LAYOUT))
85  fprintf(out, "; <void>");
86  } else {
87  if (rrs->rr) {
88  ldns_rr_print_fmt(out, fmt, rrs->rr);
89  }
90  if (rrs->next) {
91  ldns_dnssec_rrs_print_fmt(out, fmt, rrs->next);
92  }
93  }
94 }
95 
96 void
98 {
100 }
101 
102 
105 {
106  ldns_dnssec_rrsets *new_rrsets;
107  new_rrsets = LDNS_MALLOC(ldns_dnssec_rrsets);
108  if(!new_rrsets) return NULL;
109  new_rrsets->rrs = NULL;
110  new_rrsets->type = 0;
111  new_rrsets->signatures = NULL;
112  new_rrsets->next = NULL;
113  return new_rrsets;
114 }
115 
116 INLINE void
117 ldns_dnssec_rrsets_free_internal(ldns_dnssec_rrsets *rrsets, int deep)
118 {
119  if (rrsets) {
120  if (rrsets->rrs) {
121  ldns_dnssec_rrs_free_internal(rrsets->rrs, deep);
122  }
123  if (rrsets->next) {
124  ldns_dnssec_rrsets_free_internal(rrsets->next, deep);
125  }
126  if (rrsets->signatures) {
127  ldns_dnssec_rrs_free_internal(rrsets->signatures, deep);
128  }
129  LDNS_FREE(rrsets);
130  }
131 }
132 
133 void
135 {
136  ldns_dnssec_rrsets_free_internal(rrsets, 0);
137 }
138 
139 void
141 {
142  ldns_dnssec_rrsets_free_internal(rrsets, 1);
143 }
144 
147 {
148  if (rrsets) {
149  return rrsets->type;
150  } else {
151  return 0;
152  }
153 }
154 
157  ldns_rr_type type)
158 {
159  if (rrsets) {
160  rrsets->type = type;
161  return LDNS_STATUS_OK;
162  }
163  return LDNS_STATUS_ERR;
164 }
165 
166 static ldns_dnssec_rrsets *
167 ldns_dnssec_rrsets_new_frm_rr(ldns_rr *rr)
168 {
169  ldns_dnssec_rrsets *new_rrsets;
170  ldns_rr_type rr_type;
171  bool rrsig;
172 
173  new_rrsets = ldns_dnssec_rrsets_new();
174  rr_type = ldns_rr_get_type(rr);
175  if (rr_type == LDNS_RR_TYPE_RRSIG) {
176  rrsig = true;
178  } else {
179  rrsig = false;
180  }
181  if (!rrsig) {
182  new_rrsets->rrs = ldns_dnssec_rrs_new();
183  new_rrsets->rrs->rr = rr;
184  } else {
185  new_rrsets->signatures = ldns_dnssec_rrs_new();
186  new_rrsets->signatures->rr = rr;
187  }
188  new_rrsets->type = rr_type;
189  return new_rrsets;
190 }
191 
194 {
195  ldns_dnssec_rrsets *new_rrsets;
196  ldns_rr_type rr_type;
197  bool rrsig = false;
198  ldns_status result = LDNS_STATUS_OK;
199 
200  if (!rrsets || !rr) {
201  return LDNS_STATUS_ERR;
202  }
203 
204  rr_type = ldns_rr_get_type(rr);
205 
206  if (rr_type == LDNS_RR_TYPE_RRSIG) {
207  rrsig = true;
209  }
210 
211  if (!rrsets->rrs && rrsets->type == 0 && !rrsets->signatures) {
212  if (!rrsig) {
213  rrsets->rrs = ldns_dnssec_rrs_new();
214  rrsets->rrs->rr = rr;
215  rrsets->type = rr_type;
216  } else {
217  rrsets->signatures = ldns_dnssec_rrs_new();
218  rrsets->signatures->rr = rr;
219  rrsets->type = rr_type;
220  }
221  return LDNS_STATUS_OK;
222  }
223 
224  if (rr_type > ldns_dnssec_rrsets_type(rrsets)) {
225  if (rrsets->next) {
226  result = ldns_dnssec_rrsets_add_rr(rrsets->next, rr);
227  } else {
228  new_rrsets = ldns_dnssec_rrsets_new_frm_rr(rr);
229  rrsets->next = new_rrsets;
230  }
231  } else if (rr_type < ldns_dnssec_rrsets_type(rrsets)) {
232  /* move the current one into the new next,
233  replace field of current with data from new rr */
234  new_rrsets = ldns_dnssec_rrsets_new();
235  new_rrsets->rrs = rrsets->rrs;
236  new_rrsets->type = rrsets->type;
237  new_rrsets->signatures = rrsets->signatures;
238  new_rrsets->next = rrsets->next;
239  if (!rrsig) {
240  rrsets->rrs = ldns_dnssec_rrs_new();
241  rrsets->rrs->rr = rr;
242  rrsets->signatures = NULL;
243  } else {
244  rrsets->rrs = NULL;
245  rrsets->signatures = ldns_dnssec_rrs_new();
246  rrsets->signatures->rr = rr;
247  }
248  rrsets->type = rr_type;
249  rrsets->next = new_rrsets;
250  } else {
251  /* equal, add to current rrsets */
252  if (rrsig) {
253  if (rrsets->signatures) {
254  result = ldns_dnssec_rrs_add_rr(rrsets->signatures, rr);
255  } else {
256  rrsets->signatures = ldns_dnssec_rrs_new();
257  rrsets->signatures->rr = rr;
258  }
259  } else {
260  if (rrsets->rrs) {
261  result = ldns_dnssec_rrs_add_rr(rrsets->rrs, rr);
262  } else {
263  rrsets->rrs = ldns_dnssec_rrs_new();
264  rrsets->rrs->rr = rr;
265  }
266  }
267  }
268 
269  return result;
270 }
271 
272 static void
273 ldns_dnssec_rrsets_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
274  ldns_dnssec_rrsets *rrsets,
275  bool follow,
276  bool show_soa)
277 {
278  if (!rrsets) {
279  if ((fmt->flags & LDNS_COMMENT_LAYOUT))
280  fprintf(out, "; <void>\n");
281  } else {
282  if (rrsets->rrs &&
283  (show_soa ||
285  )
286  ) {
287  ldns_dnssec_rrs_print_fmt(out, fmt, rrsets->rrs);
288  if (rrsets->signatures) {
289  ldns_dnssec_rrs_print_fmt(out, fmt,
290  rrsets->signatures);
291  }
292  }
293  if (follow && rrsets->next) {
294  ldns_dnssec_rrsets_print_soa_fmt(out, fmt,
295  rrsets->next, follow, show_soa);
296  }
297  }
298 }
299 
300 
301 void
303  ldns_dnssec_rrsets *rrsets,
304  bool follow)
305 {
306  ldns_dnssec_rrsets_print_soa_fmt(out, fmt, rrsets, follow, true);
307 }
308 
309 void
310 ldns_dnssec_rrsets_print(FILE *out, ldns_dnssec_rrsets *rrsets, bool follow)
311 {
313  rrsets, follow);
314 }
315 
318 {
319  ldns_dnssec_name *new_name;
320 
321  new_name = LDNS_CALLOC(ldns_dnssec_name, 1);
322  if (!new_name) {
323  return NULL;
324  }
325  /*
326  * not needed anymore because CALLOC initalizes everything to zero.
327 
328  new_name->name = NULL;
329  new_name->rrsets = NULL;
330  new_name->name_alloced = false;
331  new_name->nsec = NULL;
332  new_name->nsec_signatures = NULL;
333 
334  new_name->is_glue = false;
335  new_name->hashed_name = NULL;
336 
337  */
338  return new_name;
339 }
340 
343 {
345 
346  new_name->name = ldns_rr_owner(rr);
347  if(ldns_dnssec_name_add_rr(new_name, rr) != LDNS_STATUS_OK) {
348  ldns_dnssec_name_free(new_name);
349  return NULL;
350  }
351 
352  return new_name;
353 }
354 
355 INLINE void
356 ldns_dnssec_name_free_internal(ldns_dnssec_name *name,
357  int deep)
358 {
359  if (name) {
360  if (name->name_alloced) {
361  ldns_rdf_deep_free(name->name);
362  }
363  if (name->rrsets) {
364  ldns_dnssec_rrsets_free_internal(name->rrsets, deep);
365  }
366  if (name->nsec && deep) {
367  ldns_rr_free(name->nsec);
368  }
369  if (name->nsec_signatures) {
370  ldns_dnssec_rrs_free_internal(name->nsec_signatures, deep);
371  }
372  if (name->hashed_name) {
373  if (deep) {
375  }
376  }
377  LDNS_FREE(name);
378  }
379 }
380 
381 void
383 {
384  ldns_dnssec_name_free_internal(name, 0);
385 }
386 
387 void
389 {
390  ldns_dnssec_name_free_internal(name, 1);
391 }
392 
393 ldns_rdf *
395 {
396  if (name) {
397  return name->name;
398  }
399  return NULL;
400 }
401 
402 bool
404 {
405  if (name) {
406  return name->is_glue;
407  }
408  return false;
409 }
410 
411 void
413  ldns_rdf *dname)
414 {
415  if (rrset && dname) {
416  rrset->name = dname;
417  }
418 }
419 
420 
421 void
423 {
424  if (rrset && nsec) {
425  rrset->nsec = nsec;
426  }
427 }
428 
429 int
430 ldns_dnssec_name_cmp(const void *a, const void *b)
431 {
434 
435  if (na && nb) {
438  } else if (na) {
439  return 1;
440  } else if (nb) {
441  return -1;
442  } else {
443  return 0;
444  }
445 }
446 
449  ldns_rr *rr)
450 {
451  ldns_status result = LDNS_STATUS_OK;
452  ldns_rr_type rr_type;
453  ldns_rr_type typecovered = 0;
454 
455  /* special handling for NSEC3 and NSECX covering RRSIGS */
456 
457  if (!name || !rr) {
458  return LDNS_STATUS_ERR;
459  }
460 
461  rr_type = ldns_rr_get_type(rr);
462 
463  if (rr_type == LDNS_RR_TYPE_RRSIG) {
464  typecovered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
465  }
466 
467  if (rr_type == LDNS_RR_TYPE_NSEC ||
468  rr_type == LDNS_RR_TYPE_NSEC3) {
469  /* XX check if is already set (and error?) */
470  name->nsec = rr;
471  } else if (typecovered == LDNS_RR_TYPE_NSEC ||
472  typecovered == LDNS_RR_TYPE_NSEC3) {
473  if (name->nsec_signatures) {
474  result = ldns_dnssec_rrs_add_rr(name->nsec_signatures, rr);
475  } else {
477  name->nsec_signatures->rr = rr;
478  }
479  } else {
480  /* it's a 'normal' RR, add it to the right rrset */
481  if (name->rrsets) {
482  result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
483  } else {
484  name->rrsets = ldns_dnssec_rrsets_new();
485  result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
486  }
487  }
488  return result;
489 }
490 
493  ldns_rr_type type) {
494  ldns_dnssec_rrsets *result;
495 
496  result = name->rrsets;
497  while (result) {
498  if (result->type == type) {
499  return result;
500  } else {
501  result = result->next;
502  }
503  }
504  return NULL;
505 }
506 
509  ldns_rdf *dname,
510  ldns_rr_type type)
511 {
512  ldns_rbnode_t *node;
513 
514  if (!zone || !dname) {
515  return NULL;
516  }
517 
518  node = ldns_rbtree_search(zone->names, dname);
519  if (node) {
521  type);
522  } else {
523  return NULL;
524  }
525 }
526 
527 static void
528 ldns_dnssec_name_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
529  ldns_dnssec_name *name,
530  bool show_soa)
531 {
532  if (name) {
533  if(name->rrsets) {
534  ldns_dnssec_rrsets_print_soa_fmt(out, fmt,
535  name->rrsets, true, show_soa);
536  } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
537  fprintf(out, ";; Empty nonterminal: ");
538  ldns_rdf_print(out, name->name);
539  fprintf(out, "\n");
540  }
541  if(name->nsec) {
542  ldns_rr_print_fmt(out, fmt, name->nsec);
543  }
544  if (name->nsec_signatures) {
545  ldns_dnssec_rrs_print_fmt(out, fmt,
546  name->nsec_signatures);
547  }
548  } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
549  fprintf(out, "; <void>\n");
550  }
551 }
552 
553 
554 void
556  ldns_dnssec_name *name)
557 {
558  ldns_dnssec_name_print_soa_fmt(out, fmt, name, true);
559 }
560 
561 void
563 {
565 }
566 
567 
570 {
572  if(!zone) return NULL;
573  zone->soa = NULL;
574  zone->names = NULL;
575  zone->hashed_names = NULL;
576  zone->_nsec3params = NULL;
577 
578  return zone;
579 }
580 
581 static bool
582 rr_is_rrsig_covering(ldns_rr* rr, ldns_rr_type t)
583 {
586 }
587 
588 /* When the zone is first read into an list and then inserted into an
589  * ldns_dnssec_zone (rbtree) the nodes of the rbtree are allocated close (next)
590  * to each other. Because ldns-verify-zone (the only program that uses this
591  * function) uses the rbtree mostly for sequentual walking, this results
592  * in a speed increase (of 15% on linux) because we have less CPU-cache misses.
593  */
594 #define FASTER_DNSSEC_ZONE_NEW_FRM_FP 1 /* Because of L2 cache efficiency */
595 
598  uint32_t ttl, ldns_rr_class ATTR_UNUSED(c), int* line_nr)
599 {
600  ldns_rr* cur_rr;
601  size_t i;
602 
603  ldns_rdf *my_origin = NULL;
604  ldns_rdf *my_prev = NULL;
605 
607  /* when reading NSEC3s, there is a chance that we encounter nsecs
608  for empty nonterminals, whose nonterminals we cannot derive yet
609  because the needed information is to be read later. in that case
610  we keep a list of those nsec3's and retry to add them later */
611  ldns_rr_list* todo_nsec3s = ldns_rr_list_new();
612  ldns_rr_list* todo_nsec3_rrsigs = ldns_rr_list_new();
613 
615 
616 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
617  ldns_zone* zone = NULL;
618  if (ldns_zone_new_frm_fp_l(&zone, fp, origin,ttl, c, line_nr)
619  != LDNS_STATUS_OK) goto error;
620 #else
621  uint32_t my_ttl = ttl;
622 #endif
623 
624  if (!newzone || !todo_nsec3s || !todo_nsec3_rrsigs ) goto error;
625 
626  if (origin) {
627  if (!(my_origin = ldns_rdf_clone(origin))) goto error;
628  if (!(my_prev = ldns_rdf_clone(origin))) goto error;
629  }
630 
631 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
632  if (ldns_dnssec_zone_add_rr(newzone, ldns_zone_soa(zone))
633  != LDNS_STATUS_OK) goto error;
634 
635  for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
636  cur_rr = ldns_rr_list_rr(ldns_zone_rrs(zone), i);
637  status = LDNS_STATUS_OK;
638 #else
639  while (!feof(fp)) {
640  status = ldns_rr_new_frm_fp_l(&cur_rr, fp, &my_ttl, &my_origin,
641  &my_prev, line_nr);
642 
643 #endif
644  switch (status) {
645  case LDNS_STATUS_OK:
646 
647  status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
648  if (status ==
650 
651  if (rr_is_rrsig_covering(cur_rr,
653  ldns_rr_list_push_rr(todo_nsec3_rrsigs,
654  cur_rr);
655  } else {
656  ldns_rr_list_push_rr(todo_nsec3s,
657  cur_rr);
658  }
659  status = LDNS_STATUS_OK;
660 
661  } else if (status != LDNS_STATUS_OK)
662  goto error;
663 
664  break;
665 
666 
667  case LDNS_STATUS_SYNTAX_EMPTY: /* empty line was seen */
668  case LDNS_STATUS_SYNTAX_TTL: /* the ttl was set*/
669  case LDNS_STATUS_SYNTAX_ORIGIN: /* the origin was set*/
670  status = LDNS_STATUS_OK;
671  break;
672 
673  case LDNS_STATUS_SYNTAX_INCLUDE:/* $include not implemented */
675  break;
676 
677  default:
678  goto error;
679  }
680  }
681 
682  if (ldns_rr_list_rr_count(todo_nsec3s) > 0) {
684  for (i = 0; status == LDNS_STATUS_OK &&
685  i < ldns_rr_list_rr_count(todo_nsec3s); i++) {
686  cur_rr = ldns_rr_list_rr(todo_nsec3s, i);
687  status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
688  }
689  }
690  if (ldns_rr_list_rr_count(todo_nsec3_rrsigs) > 0) {
691  for (i = 0; status == LDNS_STATUS_OK &&
692  i < ldns_rr_list_rr_count(todo_nsec3_rrsigs);
693  i++){
694  cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i);
695  status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
696  }
697  }
698 
699  if (z) {
700  *z = newzone;
701  newzone = NULL;
702  } else {
703  ldns_dnssec_zone_free(newzone);
704  }
705 
706 error:
707 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
708  if (zone) {
709  ldns_zone_free(zone);
710  }
711 #endif
712  ldns_rr_list_free(todo_nsec3_rrsigs);
713  ldns_rr_list_free(todo_nsec3s);
714 
715  if (my_origin) {
716  ldns_rdf_deep_free(my_origin);
717  }
718  if (my_prev) {
719  ldns_rdf_deep_free(my_prev);
720  }
721  if (newzone) {
722  ldns_dnssec_zone_free(newzone);
723  }
724  return status;
725 }
726 
729  uint32_t ttl, ldns_rr_class ATTR_UNUSED(c))
730 {
731  return ldns_dnssec_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL);
732 }
733 
734 static void
735 ldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg) {
736  (void) arg;
738  LDNS_FREE(node);
739 }
740 
741 static void
742 ldns_dnssec_name_node_deep_free(ldns_rbnode_t *node, void *arg) {
743  (void) arg;
745  LDNS_FREE(node);
746 }
747 
748 void
750 {
751  if (zone) {
752  if (zone->names) {
753  /* destroy all name structures within the tree */
755  ldns_dnssec_name_node_free,
756  NULL);
757  LDNS_FREE(zone->names);
758  }
759  LDNS_FREE(zone);
760  }
761 }
762 
763 void
765 {
766  if (zone) {
767  if (zone->names) {
768  /* destroy all name structures within the tree */
770  ldns_dnssec_name_node_deep_free,
771  NULL);
772  LDNS_FREE(zone->names);
773  }
774  LDNS_FREE(zone);
775  }
776 }
777 
778 /* use for dname comparison in tree */
779 int
780 ldns_dname_compare_v(const void *a, const void *b) {
781  return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b);
782 }
783 
784 static void
785 ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone,
786  ldns_dnssec_name* name, ldns_rr* nsec3rr);
787 
788 static void
789 ldns_hashed_names_node_free(ldns_rbnode_t *node, void *arg) {
790  (void) arg;
791  LDNS_FREE(node);
792 }
793 
794 static void
795 ldns_dnssec_zone_hashed_names_from_nsec3(
796  ldns_dnssec_zone* zone, ldns_rr* nsec3rr)
797 {
798  ldns_rbnode_t* current_node;
799  ldns_dnssec_name* current_name;
800 
801  assert(zone != NULL);
802  assert(nsec3rr != NULL);
803 
804  if (zone->hashed_names) {
806  ldns_hashed_names_node_free, NULL);
807  LDNS_FREE(zone->hashed_names);
808  }
809  zone->_nsec3params = nsec3rr;
810 
811  /* So this is a NSEC3 zone.
812  * Calculate hashes for all names already in the zone
813  */
815  if (zone->hashed_names == NULL) {
816  return;
817  }
818  for ( current_node = ldns_rbtree_first(zone->names)
819  ; current_node != LDNS_RBTREE_NULL
820  ; current_node = ldns_rbtree_next(current_node)
821  ) {
822  current_name = (ldns_dnssec_name *) current_node->data;
823  ldns_dnssec_name_make_hashed_name(zone, current_name, nsec3rr);
824 
825  }
826 }
827 
828 static void
829 ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone,
830  ldns_dnssec_name* name, ldns_rr* nsec3rr)
831 {
832  ldns_rbnode_t* new_node;
833 
834  assert(name != NULL);
835  if (! zone->_nsec3params) {
836  if (! nsec3rr) {
837  return;
838  }
839  ldns_dnssec_zone_hashed_names_from_nsec3(zone, nsec3rr);
840 
841  } else if (! nsec3rr) {
842  nsec3rr = zone->_nsec3params;
843  }
844  name->hashed_name = ldns_nsec3_hash_name_frm_nsec3(nsec3rr, name->name);
845 
846  /* Also store in zone->hashed_names */
847  if ((new_node = LDNS_MALLOC(ldns_rbnode_t))) {
848 
849  new_node->key = name->hashed_name;
850  new_node->data = name;
851 
852  if (ldns_rbtree_insert(zone->hashed_names, new_node) == NULL) {
853 
854  LDNS_FREE(new_node);
855  }
856  }
857 }
858 
859 
860 static ldns_rbnode_t *
861 ldns_dnssec_zone_find_nsec3_original(ldns_dnssec_zone *zone, ldns_rr *rr) {
862  ldns_rdf *hashed_name;
863 
864  hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0);
865  if (hashed_name == NULL) {
866  return NULL;
867  }
868  if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 && ! zone->_nsec3params){
869 
870  ldns_dnssec_zone_hashed_names_from_nsec3(zone, rr);
871  }
872  if (zone->hashed_names == NULL) {
873  ldns_rdf_deep_free(hashed_name);
874  return NULL;
875  }
876  return ldns_rbtree_search(zone->hashed_names, hashed_name);
877 }
878 
881 {
882  ldns_status result = LDNS_STATUS_OK;
883  ldns_dnssec_name *cur_name;
884  ldns_rbnode_t *cur_node;
885  ldns_rr_type type_covered = 0;
886 
887  if (!zone || !rr) {
888  return LDNS_STATUS_ERR;
889  }
890 
891  if (!zone->names) {
893  if(!zone->names) return LDNS_STATUS_MEM_ERR;
894  }
895 
896  /* we need the original of the hashed name if this is
897  an NSEC3, or an RRSIG that covers an NSEC3 */
899  type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
900  }
902  type_covered == LDNS_RR_TYPE_NSEC3) {
903  cur_node = ldns_dnssec_zone_find_nsec3_original(zone, rr);
904  if (!cur_node) {
906  }
907  } else {
908  cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr));
909  }
910  if (!cur_node) {
911  /* add */
912  cur_name = ldns_dnssec_name_new_frm_rr(rr);
913  if(!cur_name) return LDNS_STATUS_MEM_ERR;
914  cur_node = LDNS_MALLOC(ldns_rbnode_t);
915  if(!cur_node) {
916  ldns_dnssec_name_free(cur_name);
917  return LDNS_STATUS_MEM_ERR;
918  }
919  cur_node->key = ldns_rr_owner(rr);
920  cur_node->data = cur_name;
921  (void)ldns_rbtree_insert(zone->names, cur_node);
922  ldns_dnssec_name_make_hashed_name(zone, cur_name, NULL);
923  } else {
924  cur_name = (ldns_dnssec_name *) cur_node->data;
925  result = ldns_dnssec_name_add_rr(cur_name, rr);
926  }
927  if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
928  zone->soa = cur_name;
929  }
930  return result;
931 }
932 
933 void
935  ldns_rbtree_t *tree,
936  bool print_soa)
937 {
938  ldns_rbnode_t *node;
939  ldns_dnssec_name *name;
940 
941  node = ldns_rbtree_first(tree);
942  while (node != LDNS_RBTREE_NULL) {
943  name = (ldns_dnssec_name *) node->data;
944  ldns_dnssec_name_print_soa_fmt(out, fmt, name, print_soa);
945  if ((fmt->flags & LDNS_COMMENT_LAYOUT))
946  fprintf(out, ";\n");
947  node = ldns_rbtree_next(node);
948  }
949 }
950 
951 void
952 ldns_dnssec_zone_names_print(FILE *out, ldns_rbtree_t *tree, bool print_soa)
953 {
955  tree, print_soa);
956 }
957 
958 void
960  ldns_dnssec_zone *zone)
961 {
962  if (zone) {
963  if (zone->soa) {
964  if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
965  fprintf(out, ";; Zone: ");
967  zone->soa));
968  fprintf(out, "\n;\n");
969  }
972  zone->soa,
974  false);
975  if ((fmt->flags & LDNS_COMMENT_LAYOUT))
976  fprintf(out, ";\n");
977  }
978 
979  if (zone->names) {
981  zone->names, false);
982  }
983  }
984 }
985 
986 void
988 {
990 }
991 
994 {
995  ldns_dnssec_name *new_name;
996  ldns_rdf *cur_name;
997  ldns_rdf *next_name;
998  ldns_rbnode_t *cur_node, *next_node, *new_node;
999 
1000  /* for the detection */
1001  uint16_t i, cur_label_count, next_label_count;
1002  uint16_t soa_label_count = 0;
1003  ldns_rdf *l1, *l2;
1004  int lpos;
1005 
1006  if (!zone) {
1007  return LDNS_STATUS_ERR;
1008  }
1009  if (zone->soa && zone->soa->name) {
1010  soa_label_count = ldns_dname_label_count(zone->soa->name);
1011  }
1012 
1013  cur_node = ldns_rbtree_first(zone->names);
1014  while (cur_node != LDNS_RBTREE_NULL) {
1015  next_node = ldns_rbtree_next(cur_node);
1016 
1017  /* skip glue */
1018  while (next_node != LDNS_RBTREE_NULL &&
1019  next_node->data &&
1020  ((ldns_dnssec_name *)next_node->data)->is_glue
1021  ) {
1022  next_node = ldns_rbtree_next(next_node);
1023  }
1024 
1025  if (next_node == LDNS_RBTREE_NULL) {
1026  next_node = ldns_rbtree_first(zone->names);
1027  }
1028  if (! cur_node->data || ! next_node->data) {
1029  return LDNS_STATUS_ERR;
1030  }
1031  cur_name = ((ldns_dnssec_name *)cur_node->data)->name;
1032  next_name = ((ldns_dnssec_name *)next_node->data)->name;
1033  cur_label_count = ldns_dname_label_count(cur_name);
1034  next_label_count = ldns_dname_label_count(next_name);
1035 
1036  /* Since the names are in canonical order, we can
1037  * recognize empty non-terminals by their labels;
1038  * every label after the first one on the next owner
1039  * name is a non-terminal if it either does not exist
1040  * in the current name or is different from the same
1041  * label in the current name (counting from the end)
1042  */
1043  for (i = 1; i < next_label_count - soa_label_count; i++) {
1044  lpos = (int)cur_label_count - (int)next_label_count + (int)i;
1045  if (lpos >= 0) {
1046  l1 = ldns_dname_clone_from(cur_name, (uint8_t)lpos);
1047  } else {
1048  l1 = NULL;
1049  }
1050  l2 = ldns_dname_clone_from(next_name, i);
1051 
1052  if (!l1 || ldns_dname_compare(l1, l2) != 0) {
1053  /* We have an empty nonterminal, add it to the
1054  * tree
1055  */
1056  new_name = ldns_dnssec_name_new();
1057  if (!new_name) {
1058  return LDNS_STATUS_MEM_ERR;
1059  }
1060  new_name->name = ldns_dname_clone_from(next_name,
1061  i);
1062  if (!new_name->name) {
1063  ldns_dnssec_name_free(new_name);
1064  return LDNS_STATUS_MEM_ERR;
1065  }
1066  new_name->name_alloced = true;
1067  new_node = LDNS_MALLOC(ldns_rbnode_t);
1068  if (!new_node) {
1069  ldns_dnssec_name_free(new_name);
1070  return LDNS_STATUS_MEM_ERR;
1071  }
1072  new_node->key = new_name->name;
1073  new_node->data = new_name;
1074  (void)ldns_rbtree_insert(zone->names, new_node);
1075  ldns_dnssec_name_make_hashed_name(
1076  zone, new_name, NULL);
1077  }
1078  ldns_rdf_deep_free(l1);
1079  ldns_rdf_deep_free(l2);
1080  }
1081 
1082  /* we might have inserted a new node after
1083  * the current one so we can't just use next()
1084  */
1085  if (next_node != ldns_rbtree_first(zone->names)) {
1086  cur_node = next_node;
1087  } else {
1088  cur_node = LDNS_RBTREE_NULL;
1089  }
1090  }
1091  return LDNS_STATUS_OK;
1092 }
1093 
1094 bool
1096 {
1097  ldns_rr* nsec3;
1098  ldns_rbnode_t* node;
1099 
1101  node = ldns_rbtree_first(zone->names);
1102  while (node != LDNS_RBTREE_NULL) {
1103  nsec3 = ((ldns_dnssec_name*)node->data)->nsec;
1104  if (nsec3 &&ldns_rr_get_type(nsec3)
1105  == LDNS_RR_TYPE_NSEC3 &&
1106  ldns_nsec3_optout(nsec3)) {
1107  return true;
1108  }
1109  node = ldns_rbtree_next(node);
1110  }
1111  }
1112  return false;
1113 }
ldns_dnssec_rrs * rrs
Definition: dnssec_zone.h:34
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
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:764
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:2653
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:597
void ldns_dnssec_rrsets_print_fmt(FILE *out, const ldns_output_format *fmt, ldns_dnssec_rrsets *rrsets, bool follow)
Definition: dnssec_zone.c:302
int ldns_dname_compare(const ldns_rdf *dname1, const ldns_rdf *dname2)
Compares the two dname rdf'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
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:1096
List or Set of Resource Records.
Definition: rr.h:327
Output format specifier.
Definition: host2str.h:86
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:403
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:195
#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:959
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:1332
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:422
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:975
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:146
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:156
const ldns_output_format * ldns_output_format_default
The default output format record.
Definition: host2str.c:125
Resource Record.
Definition: rr.h:299
#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:448
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:382
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:412
int ldns_dname_compare_v(const void *a, const void *b)
Given in dnssec_zone.c, also used in dnssec_sign.c:w.
Definition: dnssec_zone.c:780
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:954
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:2501
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:880
ldns_dnssec_rrs * ldns_dnssec_rrs_new(void)
Creates a new entry for 1 pointer to an rr and 1 pointer to the next rrs.
Definition: dnssec_zone.c:10
#define ATTR_UNUSED(x)
Definition: common.h:67
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:934
The rbnode_t struct definition.
Definition: rbtree.h:60
ldns_dnssec_name * ldns_dnssec_name_new(void)
Create a new data structure for a dnssec name.
Definition: dnssec_zone.c:317
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:555
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:1095
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:80
ldns_rr_list * ldns_rr_list_new(void)
creates a new rr_list structure.
Definition: rr.c:964
ldns_dnssec_rrs * signatures
Definition: dnssec_zone.h:36
int flags
Specification of how RR's should be formatted in text.
Definition: host2str.h:89
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:140
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:1252
ldns_dnssec_rrsets * ldns_dnssec_rrsets_new(void)
Creates a new list (entry) of RRsets.
Definition: dnssec_zone.c:104
int ldns_rr_compare(const ldns_rr *rr1, const ldns_rr *rr2)
compares two rrs.
Definition: rr.c:1601
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:2489
ldns_rr_type ldns_rr_get_type(const ldns_rr *rr)
returns the type of the rr.
Definition: rr.c:907
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:728
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:97
enum ldns_enum_status ldns_status
Definition: error.h:131
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:492
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:562
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:749
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_rr * _nsec3params
points to the first added NSEC3 rr whose parameters will be assumed for all subsequent NSEC3 rr's and...
Definition: dnssec_zone.h:102
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:680
void ldns_dnssec_rrsets_print(FILE *out, ldns_dnssec_rrsets *rrsets, bool follow)
Definition: dnssec_zone.c:310
#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'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:342
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:987
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:193
Resource record data field.
Definition: rdata.h:166
ldns_dnssec_zone * ldns_dnssec_zone_new(void)
Creates a new dnssec_zone structure.
Definition: dnssec_zone.c:569
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:134
ldns_dnssec_rrsets * next
Definition: dnssec_zone.h:37
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:883
size_t ldns_rr_list_rr_count(const ldns_rr_list *rr_list)
returns the number of rr's in an rr_list.
Definition: rr.c:921
enum ldns_enum_rr_type ldns_rr_type
Definition: rr.h:236
#define LDNS_FREE(ptr)
Definition: util.h:60
#define LDNS_COMMENT_LAYOUT
Print mark up.
Definition: host2str.h:62
void ldns_dnssec_name_deep_free(ldns_dnssec_name *name)
Frees the name structure and its rrs and rrsets.
Definition: dnssec_zone.c:388
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:952
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:508
void ldns_zone_free(ldns_zone *zone)
Frees the allocated memory for the zone, and the rr_list structure in it.
Definition: zone.c:306
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_rbtree_t * hashed_names
tree of ldns_dnssec_names by nsec3 hashes (when applicible)
Definition: dnssec_zone.h:97
ldns_rdf * ldns_dnssec_name_name(ldns_dnssec_name *name)
Returns the domain name of the given dnssec_name structure.
Definition: dnssec_zone.c:394
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:993
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:430
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
ldns_rr * nsec
NSEC pointing to the next name (or NSEC3 pointing to the next NSEC3)
Definition: dnssec_zone.h:67
ldns_rdf * name
pointer to a dname containing the name.
Definition: dnssec_zone.h:51