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;
14 if(!new_rrs) return NULL;
15 new_rrs->rr = NULL;
16 new_rrs->next = NULL;
17 return new_rrs;
18}
19
20INLINE void
21ldns_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
34void
36{
37 ldns_dnssec_rrs_free_internal(rrs, 0);
38}
39
40void
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
79void
81 const 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
96void
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
116INLINE void
117ldns_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
133void
135{
136 ldns_dnssec_rrsets_free_internal(rrsets, 0);
137}
138
139void
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
166static ldns_dnssec_rrsets *
167ldns_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;
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 {
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;
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 {
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
272static void
273ldns_dnssec_rrsets_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
274 const 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) {
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
301void
303 const ldns_dnssec_rrsets *rrsets,
304 bool follow)
305{
306 ldns_dnssec_rrsets_print_soa_fmt(out, fmt, rrsets, follow, true);
307}
308
309void
310ldns_dnssec_rrsets_print(FILE *out, const 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 initializes 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
355INLINE void
356ldns_dnssec_name_free_internal(ldns_dnssec_name *name,
357 int deep)
358{
359 if (name) {
360 if (name->name_alloced) {
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 /* Hashed name is always allocated when signing,
374 * so always deep free
375 */
377 }
378 LDNS_FREE(name);
379 }
380}
381
382void
384{
385 ldns_dnssec_name_free_internal(name, 0);
386}
387
388void
390{
391 ldns_dnssec_name_free_internal(name, 1);
392}
393
394ldns_rdf *
396{
397 if (name) {
398 return name->name;
399 }
400 return NULL;
401}
402
403bool
405{
406 if (name) {
407 return name->is_glue;
408 }
409 return false;
410}
411
412void
414 ldns_rdf *dname)
415{
416 if (rrset && dname) {
417 rrset->name = dname;
418 }
419}
420
421
422void
424{
425 if (rrset && nsec) {
426 rrset->nsec = nsec;
427 }
428}
429
430int
431ldns_dnssec_name_cmp(const void *a, const void *b)
432{
435
436 if (na && nb) {
439 } else if (na) {
440 return 1;
441 } else if (nb) {
442 return -1;
443 } else {
444 return 0;
445 }
446}
447
450 ldns_rr *rr)
451{
453 ldns_rr_type rr_type;
454 ldns_rr_type typecovered = 0;
455
456 /* special handling for NSEC3 and NSECX covering RRSIGS */
457
458 if (!name || !rr) {
459 return LDNS_STATUS_ERR;
460 }
461
462 rr_type = ldns_rr_get_type(rr);
463
464 if (rr_type == LDNS_RR_TYPE_RRSIG) {
466 }
467
468 if (rr_type == LDNS_RR_TYPE_NSEC ||
469 rr_type == LDNS_RR_TYPE_NSEC3) {
470 /* XX check if is already set (and error?) */
471 name->nsec = rr;
472 } else if (typecovered == LDNS_RR_TYPE_NSEC ||
473 typecovered == LDNS_RR_TYPE_NSEC3) {
474 if (name->nsec_signatures) {
475 result = ldns_dnssec_rrs_add_rr(name->nsec_signatures, rr);
476 } else {
478 name->nsec_signatures->rr = rr;
479 }
480 } else {
481 /* it's a 'normal' RR, add it to the right rrset */
482 if (name->rrsets) {
483 result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
484 } else {
486 result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
487 }
488 }
489 return result;
490}
491
494 ldns_rr_type type) {
495 ldns_dnssec_rrsets *result;
496
497 result = name->rrsets;
498 while (result) {
499 if (result->type == type) {
500 return result;
501 } else {
502 result = result->next;
503 }
504 }
505 return NULL;
506}
507
510 const ldns_rdf *dname,
511 ldns_rr_type type)
512{
513 ldns_rbnode_t *node;
514
515 if (!zone || !dname || !zone->names) {
516 return NULL;
517 }
518
519 node = ldns_rbtree_search(zone->names, dname);
520 if (node) {
522 type);
523 } else {
524 return NULL;
525 }
526}
527
528static void
529ldns_dnssec_name_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
530 const ldns_dnssec_name *name,
531 bool show_soa)
532{
533 if (name) {
534 if(name->rrsets) {
535 ldns_dnssec_rrsets_print_soa_fmt(out, fmt,
536 name->rrsets, true, show_soa);
537 } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
538 fprintf(out, ";; Empty nonterminal: ");
539 ldns_rdf_print(out, name->name);
540 fprintf(out, "\n");
541 }
542 if(name->nsec) {
543 ldns_rr_print_fmt(out, fmt, name->nsec);
544 }
545 if (name->nsec_signatures) {
547 name->nsec_signatures);
548 }
549 } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
550 fprintf(out, "; <void>\n");
551 }
552}
553
554
555void
557 const ldns_dnssec_name *name)
558{
559 ldns_dnssec_name_print_soa_fmt(out, fmt, name, true);
560}
561
562void
567
568
571{
573 if(!zone) return NULL;
574 zone->soa = NULL;
575 zone->names = NULL;
576 zone->hashed_names = NULL;
577 zone->_nsec3params = NULL;
578
579 return zone;
580}
581
582static bool
583rr_is_rrsig_covering(ldns_rr* rr, ldns_rr_type t)
584{
587}
588
589/* When the zone is first read into an list and then inserted into an
590 * ldns_dnssec_zone (rbtree) the nodes of the rbtree are allocated close (next)
591 * to each other. Because ldns-verify-zone (the only program that uses this
592 * function) uses the rbtree mostly for sequential walking, this results
593 * in a speed increase (of 15% on linux) because we have less CPU-cache misses.
594 */
595#define FASTER_DNSSEC_ZONE_NEW_FRM_FP 1 /* Because of L2 cache efficiency */
596
597static ldns_status
598ldns_dnssec_zone_add_empty_nonterminals_nsec3(
599 ldns_dnssec_zone *zone, ldns_rbtree_t *nsec3s);
600
601static void
602ldns_todo_nsec3_ents_node_free(ldns_rbnode_t *node, void *arg) {
603 (void) arg;
605 LDNS_FREE(node);
606}
607
610 uint32_t default_ttl, ldns_rr_class ATTR_UNUSED(c), int* line_nr)
611{
612 ldns_rr* cur_rr;
613 size_t i;
614
615 ldns_rdf *my_origin = NULL;
616 ldns_rdf *my_prev = NULL;
617
619 /* NSEC3s may occur before the names they refer to. We must remember
620 them and add them to the name later on, after the name is read.
621 We track not yet matching NSEC3s*n the todo_nsec3s list */
622 ldns_rr_list* todo_nsec3s = ldns_rr_list_new();
623 /* when reading NSEC3s, there is a chance that we encounter nsecs
624 for empty nonterminals, whose nonterminals we cannot derive yet
625 because the needed information is to be read later.
626
627 nsec3_ents (where ent is e.n.t.; i.e. empty non terminal) will
628 hold the NSEC3s that still didn't have a matching name in the
629 zone tree, even after all names were read. They can only match
630 after the zone is equipped with all the empty non terminals. */
631 ldns_rbtree_t todo_nsec3_ents;
632 ldns_rbnode_t *new_node;
633 ldns_rr_list* todo_nsec3_rrsigs = ldns_rr_list_new();
634
635 ldns_status status;
636
637#ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
638 ldns_zone* zone = NULL;
639#else
640 ldns_rr *prev_rr = NULL;
641 uint32_t my_ttl = default_ttl;
642 /* RFC 1035 Section 5.1, says 'Omitted class and TTL values are default
643 * to the last explicitly stated values.'
644 */
645 bool ttl_from_TTL = false;
646 bool explicit_ttl = false;
647#endif
648
649 ldns_rbtree_init(&todo_nsec3_ents, ldns_dname_compare_v);
650
651#ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
652 status = ldns_zone_new_frm_fp_l(&zone, fp, origin, default_ttl, c, line_nr);
653 if (status != LDNS_STATUS_OK)
654 goto error;
655#endif
656 if (!newzone || !todo_nsec3s || !todo_nsec3_rrsigs ) {
657 status = LDNS_STATUS_MEM_ERR;
658 goto error;
659 }
660 if (origin) {
661 if (!(my_origin = ldns_rdf_clone(origin))) {
662 status = LDNS_STATUS_MEM_ERR;
663 goto error;
664 }
665 if (!(my_prev = ldns_rdf_clone(origin))) {
666 status = LDNS_STATUS_MEM_ERR;
667 goto error;
668 }
669 }
670
671#ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
672 if (ldns_zone_soa(zone)) {
673 status = ldns_dnssec_zone_add_rr(newzone, ldns_zone_soa(zone));
674 if (status != LDNS_STATUS_OK)
675 goto error;
676 }
677 for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
678 cur_rr = ldns_rr_list_rr(ldns_zone_rrs(zone), i);
679 status = LDNS_STATUS_OK;
680#else
681 while (!feof(fp)) {
682 /* If ttl came from $TTL line, then it should be the default.
683 * (RFC 2308 Section 4)
684 * Otherwise it "defaults to the last explicitly stated value"
685 * (RFC 1035 Section 5.1)
686 */
687 if (ttl_from_TTL)
688 my_ttl = default_ttl;
689 status = ldns_rr_new_frm_fp_l(&cur_rr, fp, &my_ttl, &my_origin,
690 &my_prev, line_nr, &explicit_ttl);
691#endif
692 switch (status) {
693 case LDNS_STATUS_OK:
694#ifndef FASTER_DNSSEC_ZONE_NEW_FRM_FP
695 if (explicit_ttl) {
696 if (!ttl_from_TTL) {
697 /* No $TTL, so ttl "defaults to the
698 * last explicitly stated value"
699 * (RFC 1035 Section 5.1)
700 */
701 my_ttl = ldns_rr_ttl(cur_rr);
702 }
703 /* When ttl is implicit, try to adhere to the rules as
704 * much as possible. (also for compatibility with bind)
705 * This was changed when fixing an issue with ZONEMD
706 * which hashes the TTL too.
707 */
708 } else if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SIG
709 || ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_RRSIG) {
710 if (ldns_rr_rd_count(cur_rr) >= 4
712
713 /* SIG without explicit ttl get ttl
714 * from the original_ttl field
715 * (RFC 2535 Section 7.2)
716 *
717 * Similarly for RRSIG, but stated less
718 * specifically in the spec.
719 * (RFC 4034 Section 3)
720 */
721 ldns_rr_set_ttl(cur_rr,
723 ldns_rr_rdf(rr, 3)));
724
725 } else if (prev_rr
726 && ldns_rr_get_type(prev_rr) == ldns_rr_get_type(cur_rr)
728 , ldns_rr_owner(cur_rr)) == 0)
729
730 /* "TTLs of all RRs in an RRSet must be the same"
731 * (RFC 2881 Section 5.2)
732 */
733 ldns_rr_set_ttl(cur_rr, ldns_rr_ttl(prev_rr));
734
735 prev_rr = cur_rr;
736#endif
737 status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
738 if (status ==
740
741 if (rr_is_rrsig_covering(cur_rr,
743 ldns_rr_list_push_rr(todo_nsec3_rrsigs,
744 cur_rr);
745 } else {
746 ldns_rr_list_push_rr(todo_nsec3s,
747 cur_rr);
748 }
749 status = LDNS_STATUS_OK;
750
751 } else if (status != LDNS_STATUS_OK)
752 goto error;
753
754 break;
755
756 case LDNS_STATUS_SYNTAX_TTL: /* the ttl was set*/
757#ifndef FASTER_DNSSEC_ZONE_NEW_FRM_FP
758 default_ttl = my_ttl;
759 ttl_from_TTL = true;
760#endif
761 status = LDNS_STATUS_OK;
762 break;
763
764
765 case LDNS_STATUS_SYNTAX_EMPTY: /* empty line was seen */
766 case LDNS_STATUS_SYNTAX_ORIGIN: /* the origin was set*/
767 status = LDNS_STATUS_OK;
768 break;
769
770 case LDNS_STATUS_SYNTAX_INCLUDE:/* $include not implemented */
772 break;
773
774 default:
775 goto error;
776 }
777 }
778
779 for (i = 0; status == LDNS_STATUS_OK &&
780 i < ldns_rr_list_rr_count(todo_nsec3s); i++) {
781 cur_rr = ldns_rr_list_rr(todo_nsec3s, i);
782 status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
784 if (!(new_node = LDNS_MALLOC(ldns_rbnode_t))) {
785 status = LDNS_STATUS_MEM_ERR;
786 break;
787 }
788 new_node->key = ldns_dname_label(ldns_rr_owner(cur_rr), 0);
789 new_node->data = cur_rr;
790 if (!ldns_rbtree_insert(&todo_nsec3_ents, new_node)) {
791 LDNS_FREE(new_node);
792 status = LDNS_STATUS_MEM_ERR;
793 break;
794 }
795 status = LDNS_STATUS_OK;
796 }
797 }
798 if (todo_nsec3_ents.count > 0)
799 (void) ldns_dnssec_zone_add_empty_nonterminals_nsec3(
800 newzone, &todo_nsec3_ents);
801 for (i = 0; status == LDNS_STATUS_OK &&
802 i < ldns_rr_list_rr_count(todo_nsec3_rrsigs); i++) {
803 cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i);
804 status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
805 }
806 if (z) {
807 *z = newzone;
808 newzone = NULL;
809 } else {
810 ldns_dnssec_zone_free(newzone);
811 newzone = NULL;
812 }
813
814error:
815#ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
816 if (zone) {
817 ldns_zone_free(zone);
818 }
819#endif
820 ldns_rr_list_free(todo_nsec3_rrsigs);
821 ldns_traverse_postorder(&todo_nsec3_ents,
822 ldns_todo_nsec3_ents_node_free, NULL);
823 ldns_rr_list_free(todo_nsec3s);
824
825 if (my_origin) {
826 ldns_rdf_deep_free(my_origin);
827 }
828 if (my_prev) {
829 ldns_rdf_deep_free(my_prev);
830 }
831 if (newzone) {
832 ldns_dnssec_zone_free(newzone);
833 }
834 return status;
835}
836
839 uint32_t ttl, ldns_rr_class ATTR_UNUSED(c))
840{
841 return ldns_dnssec_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL);
842}
843
844static void
845ldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg) {
846 (void) arg;
848 LDNS_FREE(node);
849}
850
851static void
852ldns_dnssec_name_node_deep_free(ldns_rbnode_t *node, void *arg) {
853 (void) arg;
855 LDNS_FREE(node);
856}
857
858static void
859ldns_hashed_names_node_free(ldns_rbnode_t *node, void *arg) {
860 (void) arg;
861 LDNS_FREE(node);
862}
863
864void
866{
867 if (zone) {
868 if (zone->hashed_names) {
870 ldns_hashed_names_node_free, NULL);
871 LDNS_FREE(zone->hashed_names);
872 }
873 if (zone->names) {
874 /* destroy all name structures within the tree */
876 ldns_dnssec_name_node_free,
877 NULL);
878 LDNS_FREE(zone->names);
879 }
880 LDNS_FREE(zone);
881 }
882}
883
884void
886{
887 if (zone) {
888 if (zone->hashed_names) {
890 ldns_hashed_names_node_free, NULL);
891 LDNS_FREE(zone->hashed_names);
892 }
893 if (zone->names) {
894 /* destroy all name structures within the tree */
896 ldns_dnssec_name_node_deep_free,
897 NULL);
898 LDNS_FREE(zone->names);
899 }
900 LDNS_FREE(zone);
901 }
902}
903
904/* use for dname comparison in tree */
905int
906ldns_dname_compare_v(const void *a, const void *b) {
907 return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b);
908}
909
910static void
911ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone,
912 ldns_dnssec_name* name, ldns_rr* nsec3rr);
913
914static void
915ldns_dnssec_zone_hashed_names_from_nsec3(
916 ldns_dnssec_zone* zone, ldns_rr* nsec3rr)
917{
918 ldns_rbnode_t* current_node;
919 ldns_dnssec_name* current_name;
920
921 assert(zone != NULL);
922 assert(nsec3rr != NULL);
923
924 if (zone->hashed_names) {
926 ldns_hashed_names_node_free, NULL);
927 LDNS_FREE(zone->hashed_names);
928 }
929 zone->_nsec3params = nsec3rr;
930
931 /* So this is a NSEC3 zone.
932 * Calculate hashes for all names already in the zone
933 */
935 if (zone->hashed_names == NULL) {
936 return;
937 }
938 for ( current_node = ldns_rbtree_first(zone->names)
939 ; current_node != LDNS_RBTREE_NULL
940 ; current_node = ldns_rbtree_next(current_node)
941 ) {
942 current_name = (ldns_dnssec_name *) current_node->data;
943 ldns_dnssec_name_make_hashed_name(zone, current_name, nsec3rr);
944
945 }
946}
947
948static void
949ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone,
950 ldns_dnssec_name* name, ldns_rr* nsec3rr)
951{
952 ldns_rbnode_t* new_node;
953
954 assert(name != NULL);
955 if (! zone->_nsec3params) {
956 if (! nsec3rr) {
957 return;
958 }
959 ldns_dnssec_zone_hashed_names_from_nsec3(zone, nsec3rr);
960
961 } else if (! nsec3rr) {
962 nsec3rr = zone->_nsec3params;
963 }
964 name->hashed_name = ldns_nsec3_hash_name_frm_nsec3(nsec3rr, name->name);
965
966 /* Also store in zone->hashed_names */
967 if ((new_node = LDNS_MALLOC(ldns_rbnode_t))) {
968
969 new_node->key = name->hashed_name;
970 new_node->data = name;
971
972 if (ldns_rbtree_insert(zone->hashed_names, new_node) == NULL) {
973
974 LDNS_FREE(new_node);
975 }
976 }
977}
978
979
980static ldns_rbnode_t *
981ldns_dnssec_zone_find_nsec3_original(ldns_dnssec_zone *zone, ldns_rr *rr) {
982 ldns_rdf *hashed_name;
983 ldns_rbnode_t *to_return;
984
985 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 && ! zone->_nsec3params){
986
987 ldns_dnssec_zone_hashed_names_from_nsec3(zone, rr);
988 }
989 if (zone->hashed_names == NULL) {
990 return NULL;
991 }
992 hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0);
993 if (hashed_name == NULL) {
994 return NULL;
995 }
996 to_return = ldns_rbtree_search(zone->hashed_names, hashed_name);
997 ldns_rdf_deep_free(hashed_name);
998 return to_return;
999}
1000
1003{
1004 ldns_status result = LDNS_STATUS_OK;
1005 ldns_dnssec_name *cur_name;
1006 ldns_rbnode_t *cur_node;
1007 ldns_rr_type type_covered = 0;
1008
1009 if (!zone || !rr) {
1010 return LDNS_STATUS_ERR;
1011 }
1012
1013 if (!zone->names) {
1015 if(!zone->names) return LDNS_STATUS_MEM_ERR;
1016 }
1017
1018 /* we need the original of the hashed name if this is
1019 an NSEC3, or an RRSIG that covers an NSEC3 */
1021 type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
1022 }
1024 type_covered == LDNS_RR_TYPE_NSEC3) {
1025 cur_node = ldns_dnssec_zone_find_nsec3_original(zone, rr);
1026 if (!cur_node) {
1028 }
1029 } else {
1030 cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr));
1031 }
1032 if (!cur_node) {
1033 /* add */
1034 cur_name = ldns_dnssec_name_new_frm_rr(rr);
1035 if(!cur_name) return LDNS_STATUS_MEM_ERR;
1036 cur_node = LDNS_MALLOC(ldns_rbnode_t);
1037 if(!cur_node) {
1038 ldns_dnssec_name_free(cur_name);
1039 return LDNS_STATUS_MEM_ERR;
1040 }
1041 cur_node->key = ldns_rr_owner(rr);
1042 cur_node->data = cur_name;
1043 (void)ldns_rbtree_insert(zone->names, cur_node);
1044 ldns_dnssec_name_make_hashed_name(zone, cur_name, NULL);
1045 } else {
1046 cur_name = (ldns_dnssec_name *) cur_node->data;
1047 result = ldns_dnssec_name_add_rr(cur_name, rr);
1048 }
1050 zone->soa = cur_name;
1051 }
1052 return result;
1053}
1054
1055void
1057 const ldns_rbtree_t *tree,
1058 bool print_soa)
1059{
1060 ldns_rbnode_t *node;
1061 ldns_dnssec_name *name;
1062
1063 node = ldns_rbtree_first(tree);
1064 while (node != LDNS_RBTREE_NULL) {
1065 name = (ldns_dnssec_name *) node->data;
1066 ldns_dnssec_name_print_soa_fmt(out, fmt, name, print_soa);
1067 if ((fmt->flags & LDNS_COMMENT_LAYOUT))
1068 fprintf(out, ";\n");
1069 node = ldns_rbtree_next(node);
1070 }
1071}
1072
1073void
1074ldns_dnssec_zone_names_print(FILE *out, const ldns_rbtree_t *tree, bool print_soa)
1075{
1077 tree, print_soa);
1078}
1079
1080void
1082 const ldns_dnssec_zone *zone)
1083{
1084 if (zone) {
1085 if (zone->soa) {
1086 if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
1087 fprintf(out, ";; Zone: ");
1089 zone->soa));
1090 fprintf(out, "\n;\n");
1091 }
1094 zone->soa,
1096 false);
1097 if ((fmt->flags & LDNS_COMMENT_LAYOUT))
1098 fprintf(out, ";\n");
1099 }
1100
1101 if (zone->names) {
1103 zone->names, false);
1104 }
1105 }
1106}
1107
1108void
1113
1114static ldns_status
1115ldns_dnssec_zone_add_empty_nonterminals_nsec3(
1116 ldns_dnssec_zone *zone, ldns_rbtree_t *nsec3s)
1117{
1118 ldns_dnssec_name *new_name;
1119 ldns_rdf *cur_name;
1120 ldns_rdf *next_name;
1121 ldns_rbnode_t *cur_node, *next_node, *new_node;
1122
1123 /* for the detection */
1124 uint16_t i, cur_label_count, next_label_count;
1125 uint16_t soa_label_count = 0;
1126 ldns_rdf *l1, *l2;
1127 int lpos;
1128
1129 if (!zone) {
1130 return LDNS_STATUS_ERR;
1131 }
1132 if (zone->soa && zone->soa->name) {
1133 soa_label_count = ldns_dname_label_count(zone->soa->name);
1134 }
1135
1136 cur_node = ldns_rbtree_first(zone->names);
1137 while (cur_node != LDNS_RBTREE_NULL) {
1138 next_node = ldns_rbtree_next(cur_node);
1139
1140 /* skip glue */
1141 while (next_node != LDNS_RBTREE_NULL &&
1142 next_node->data &&
1143 ((ldns_dnssec_name *)next_node->data)->is_glue
1144 ) {
1145 next_node = ldns_rbtree_next(next_node);
1146 }
1147
1148 if (next_node == LDNS_RBTREE_NULL) {
1149 next_node = ldns_rbtree_first(zone->names);
1150 }
1151 if (! cur_node->data || ! next_node->data) {
1152 return LDNS_STATUS_ERR;
1153 }
1154 cur_name = ((ldns_dnssec_name *)cur_node->data)->name;
1155 next_name = ((ldns_dnssec_name *)next_node->data)->name;
1156 cur_label_count = ldns_dname_label_count(cur_name);
1157 next_label_count = ldns_dname_label_count(next_name);
1158
1159 /* Since the names are in canonical order, we can
1160 * recognize empty non-terminals by their labels;
1161 * every label after the first one on the next owner
1162 * name is a non-terminal if it either does not exist
1163 * in the current name or is different from the same
1164 * label in the current name (counting from the end)
1165 */
1166 for (i = 1; i < next_label_count - soa_label_count; i++) {
1167 lpos = (int)cur_label_count - (int)next_label_count + (int)i;
1168 if (lpos >= 0) {
1169 l1 = ldns_dname_clone_from(cur_name, (uint8_t)lpos);
1170 } else {
1171 l1 = NULL;
1172 }
1173 l2 = ldns_dname_clone_from(next_name, i);
1174
1175 if (!l1 || ldns_dname_compare(l1, l2) != 0) {
1176 /* We have an empty nonterminal, add it to the
1177 * tree
1178 */
1179 ldns_rbnode_t *node = NULL;
1180 ldns_rdf *ent_name;
1181
1182 if (!(ent_name = ldns_dname_clone_from(
1183 next_name, i))) {
1184
1187 return LDNS_STATUS_MEM_ERR;
1188 }
1189
1190 if (nsec3s && zone->_nsec3params) {
1191 ldns_rdf *ent_hashed_name;
1192
1193 if (!(ent_hashed_name =
1195 zone->_nsec3params,
1196 ent_name))) {
1199 ldns_rdf_deep_free(ent_name);
1200 return LDNS_STATUS_MEM_ERR;
1201 }
1202 node = ldns_rbtree_search(nsec3s,
1203 ent_hashed_name);
1204 ldns_rdf_deep_free(ent_hashed_name);
1205 if (!node) {
1208 ldns_rdf_deep_free(ent_name);
1209 continue;
1210 }
1211 }
1212 new_name = ldns_dnssec_name_new();
1213 if (!new_name) {
1216 ldns_rdf_deep_free(ent_name);
1217 return LDNS_STATUS_MEM_ERR;
1218 }
1219 new_name->name = ent_name;
1220 new_name->name_alloced = true;
1221 new_node = LDNS_MALLOC(ldns_rbnode_t);
1222 if (!new_node) {
1225 ldns_dnssec_name_free(new_name);
1226 return LDNS_STATUS_MEM_ERR;
1227 }
1228 new_node->key = new_name->name;
1229 new_node->data = new_name;
1230 (void)ldns_rbtree_insert(zone->names, new_node);
1231 ldns_dnssec_name_make_hashed_name(
1232 zone, new_name, NULL);
1233 if (node)
1234 (void) ldns_dnssec_zone_add_rr(zone,
1235 (ldns_rr *)node->data);
1236 }
1239 }
1240
1241 /* we might have inserted a new node after
1242 * the current one so we can't just use next()
1243 */
1244 if (next_node != ldns_rbtree_first(zone->names)) {
1245 cur_node = next_node;
1246 } else {
1247 cur_node = LDNS_RBTREE_NULL;
1248 }
1249 }
1250 return LDNS_STATUS_OK;
1251}
1252
1255{
1256 return ldns_dnssec_zone_add_empty_nonterminals_nsec3(zone, NULL);
1257}
1258
1259bool
1261{
1262 ldns_rr* nsec3;
1263 ldns_rbnode_t* node;
1264
1266 node = ldns_rbtree_first(zone->names);
1267 while (node != LDNS_RBTREE_NULL) {
1268 nsec3 = ((ldns_dnssec_name*)node->data)->nsec;
1269 if (nsec3 &&ldns_rr_get_type(nsec3)
1270 == LDNS_RR_TYPE_NSEC3 &&
1271 ldns_nsec3_optout(nsec3)) {
1272 return true;
1273 }
1274 node = ldns_rbtree_next(node);
1275 }
1276 }
1277 return false;
1278}
1279
1280/*
1281 * Stuff for calculating and verifying zone digests
1282 */
1292
1306
1307INLINE void
1308dnssec_zone_rr_iter_set_state_for_next_name(dnssec_zone_rr_iter *i)
1309{
1310 /* Make sure the i->name is "in zone" (i.e. below the apex) */
1311 if (i->apex_name) {
1312 ldns_rdf *name = (ldns_rdf *)i->node->key;
1313
1314 while (i->name && name != i->apex_name /* not apex */
1315
1316 && ( ldns_dname_label_count(name) != i->apex_labs
1317 || ldns_dname_compare(name, i->apex_name)) /* not apex */
1318
1319 && !ldns_dname_is_subdomain(name, i->apex_name) /* no sub */) {
1320
1321 /* next name */
1322 i->node = ldns_rbtree_next(i->node);
1323 if (i->node == LDNS_RBTREE_NULL)
1324 i->name = NULL;
1325 else {
1326 i->name = (ldns_dnssec_name *)i->node->data;
1327 name = (ldns_rdf *)i->node->key;
1328 }
1329 }
1330 }
1331 /* determine state */
1332 if (!i->name) {
1333 if (!i->nsec3_name)
1335 else {
1338 }
1339 } else if (!i->nsec3_name) {
1340 i->rrsets = i->name->rrsets;
1342
1344 , (ldns_rdf *)i->node->key) < 0) {
1347 } else {
1348 i->rrsets = i->name->rrsets;
1350 }
1351}
1352
1394static ldns_rr *
1395dnssec_zone_rr_iter_next(dnssec_zone_rr_iter *i)
1396{
1397 ldns_rr *nsec3;
1398
1399 for (;;) {
1400 if (i->rrs) {
1401 ldns_rr *rr = i->rrs->rr;
1402 i->rrs = i->rrs->next;
1403 return rr;
1404 }
1405 switch (i->state) {
1407 if (i->rrsets
1408 && i->rrsets->type < LDNS_RR_TYPE_RRSIG) {
1409
1410 i->rrs = i->rrsets->rrs;
1411 i->rrsets = i->rrsets->next;
1412 break;
1413 }
1414 i->rrsets4rrsigs = i->name->rrsets;
1415 if (i->name->nsec && ldns_rr_get_type(i->name->nsec)
1416 == LDNS_RR_TYPE_NSEC) {
1417
1419 break;
1420 }
1422 /* fallthrough */
1423
1425 if (i->rrsets4rrsigs) {
1426 i->rrs = i->rrsets4rrsigs->signatures;
1428 break;
1429 }
1431 /* fallthrough */
1432
1434 if (i->rrsets) {
1435 i->rrs = i->rrsets->rrs;
1436 i->rrsets = i->rrsets->next;
1437 break;
1438 }
1439 /* next name */
1440 i->node = ldns_rbtree_next(i->node);
1441 i->name = i->node == LDNS_RBTREE_NULL ? NULL
1442 : (ldns_dnssec_name *)i->node->data;
1443
1444 dnssec_zone_rr_iter_set_state_for_next_name(i);
1445 break;
1446
1448 if (i->rrsets4rrsigs
1450
1451 i->rrs = i->rrsets4rrsigs->signatures;
1453 break;
1454 }
1456 i->rrs = i->name->nsec_signatures;
1457 break;
1458
1460 if (i->rrsets4rrsigs) {
1461 i->rrs = i->rrsets4rrsigs->signatures;
1463 break;
1464 }
1466 return i->name->nsec;
1467
1469 nsec3 = i->nsec3_name->nsec;
1470
1471 /* next nsec3 */
1472 do {
1473 i->nsec3_node
1475 i->nsec3_name
1476 = i->nsec3_node == LDNS_RBTREE_NULL ? NULL
1478
1479 /* names for glue can be in the hashed_names
1480 * tree, but will not have a NSEC3
1481 */
1482 } while (i->nsec3_name && !i->nsec3_name->nsec);
1483
1484 dnssec_zone_rr_iter_set_state_for_next_name(i);
1485 return nsec3;
1486
1488 return NULL;
1489 }
1490 }
1491}
1492
1493static ldns_rr *
1494dnssec_zone_rr_iter_first(dnssec_zone_rr_iter *i, ldns_dnssec_zone *zone)
1495{
1496 if (!i || !zone)
1497 return NULL;
1498
1499 memset(i, 0, sizeof(*i));
1500 i->zone = zone;
1501 if (zone->soa && zone->soa->name) {
1502 i->apex_name = zone->soa->name;
1504 } else
1505 i->apex_name = NULL;
1506
1507
1508 i->node = ldns_rbtree_first(zone->names);
1509 i->name = i->node == LDNS_RBTREE_NULL ? NULL
1510 : (ldns_dnssec_name *)i->node->data;
1511
1512 if (zone->hashed_names) {
1513 do {
1515 i->nsec3_name = i->nsec3_node == LDNS_RBTREE_NULL ?NULL
1517 } while (i->nsec3_name && !i->nsec3_name->nsec);
1518 }
1519 dnssec_zone_rr_iter_set_state_for_next_name(i);
1520 return dnssec_zone_rr_iter_next(i);
1521}
1522
1529
1537
1547
1548INLINE bool zone_digester_set(zone_digester *zd)
1549{ return zd && (zd->simple_sha384 || zd->simple_sha512); }
1550
1551INLINE void zone_digester_init(zone_digester *zd)
1552{ memset(zd, 0, sizeof(*zd)); }
1553
1554static ldns_status
1555zone_digester_add(zone_digester *zd, zonemd_scheme scheme, zonemd_hash hash)
1556{
1557 if (!zd)
1558 return LDNS_STATUS_NULL;
1559
1560 switch (scheme) {
1562 switch (hash) {
1563 case ZONEMD_HASH_SHA384:
1564 if (zd->double_sha384)
1566
1567 else if (zd->simple_sha384) {
1568 zd->simple_sha384 = 0;
1569 zd->double_sha384 = 1;
1571 }
1573 zd->simple_sha384 = 1;
1574 break;
1575
1576 case ZONEMD_HASH_SHA512:
1577 if (zd->double_sha512)
1579
1580 else if (zd->simple_sha512) {
1581 zd->simple_sha512 = 0;
1582 zd->double_sha512 = 1;
1584 }
1586 zd->simple_sha512 = 1;
1587 break;
1588 default:
1590 }
1591 break;
1592 default:
1594 }
1595 return LDNS_STATUS_OK;
1596}
1597
1598static ldns_status
1599zone_digester_update(zone_digester *zd, ldns_rr *rr)
1600{
1601 uint8_t data[65536];
1602 ldns_buffer buf;
1603 ldns_status st;
1604
1605 buf._data = data;
1606 buf._position = 0;
1607 buf._limit = sizeof(data);
1608 buf._capacity = sizeof(data);
1609 buf._fixed = 1;
1610 buf._status = LDNS_STATUS_OK;
1611
1613 return st;
1614
1615 if (zd->simple_sha384)
1616 ldns_sha384_update(&zd->sha384_CTX, data, buf._position);
1617
1618 if (zd->simple_sha512)
1619 ldns_sha512_update(&zd->sha512_CTX, data, buf._position);
1620
1621 return LDNS_STATUS_OK;
1622}
1623
1625new_zonemd(ldns_rr *soa, zonemd_hash hash)
1626{
1627 ldns_rr *rr = NULL;
1628 uint8_t *data = NULL;
1629 ldns_rdf *rdf;
1630 size_t md_len = hash == ZONEMD_HASH_SHA384
1633
1635 return NULL;
1636
1637 if (!(rdf = ldns_rdf_clone(ldns_rr_owner(soa))))
1638 goto error;
1639
1640 ldns_rr_set_owner(rr, rdf);
1642 ldns_rr_set_ttl(rr, ldns_rr_ttl(soa));
1643
1644 if (!(rdf = ldns_rdf_clone(ldns_rr_rdf(soa, 2))))
1645 goto error;
1646 ldns_rr_set_rdf(rr, rdf, 0);
1647
1649 goto error;
1650 ldns_rr_set_rdf(rr, rdf, 1);
1651
1652 if (!(rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, hash)))
1653 goto error;
1654 ldns_rr_set_rdf(rr, rdf, 2);
1655
1656 if (!(data = LDNS_XMALLOC(uint8_t, md_len)))
1657 goto error;
1658
1659 if (!(rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, md_len, data)))
1660 goto error;
1661 ldns_rr_set_rdf(rr, rdf, 3);
1662
1663 return rr;
1664error:
1665 if (data)
1666 LDNS_FREE(data);
1667 ldns_rr_free(rr);
1668 return NULL;
1669}
1670
1671static ldns_rr_list *
1672zone_digester_export(
1673 zone_digester *zd, ldns_rr *soa, ldns_status *ret_st)
1674{
1676 ldns_rr_list *rr_list = NULL;
1677 ldns_rr *sha384 = NULL;
1678 ldns_rr *sha512 = NULL;
1679
1680 if (!zd || !soa)
1681 st = LDNS_STATUS_NULL;
1682
1683 else if (ldns_rr_get_type(soa) != LDNS_RR_TYPE_SOA
1684 || ldns_rr_rd_count(soa) < 3)
1686
1687 else if (!(rr_list = ldns_rr_list_new()))
1689
1690 else if (zd->simple_sha384
1691 && !(sha384 = new_zonemd(soa, ZONEMD_HASH_SHA384)))
1693
1694 else if (zd->simple_sha512
1695 && !(sha512 = new_zonemd(soa, ZONEMD_HASH_SHA512)))
1697
1698 else if (zd->simple_sha384
1699 && !ldns_rr_list_push_rr(rr_list, sha384))
1701
1702 else if (zd->simple_sha512
1703 && !ldns_rr_list_push_rr(rr_list, sha512)) {
1704 if (zd->simple_sha384)
1705 sha384 = NULL; /* deleted by ldns_rr_list_deep_free */
1707
1708 } else {
1709 if (sha384)
1711 , &zd->sha384_CTX);
1712 if (sha512)
1714 , &zd->sha512_CTX);
1715 return rr_list;
1716 }
1717 if (ret_st)
1718 *ret_st = st;
1719 if (sha384)
1720 ldns_rr_free(sha384);
1721 if (sha512)
1722 ldns_rr_free(sha512);
1723 if (rr_list)
1724 ldns_rr_list_deep_free(rr_list);
1725 return NULL;
1726}
1727
1728static ldns_status
1729ldns_digest_zone(ldns_dnssec_zone *zone, zone_digester *zd)
1730{
1732 dnssec_zone_rr_iter rr_iter;
1733 ldns_rr *rr;
1734 ldns_rdf *apex_name; /* name of zone apex */
1735
1736 if (!zone || !zd || !zone->soa || !zone->soa->name)
1737 return LDNS_STATUS_NULL;
1738
1739 apex_name = zone->soa->name;
1740 for ( rr = dnssec_zone_rr_iter_first(&rr_iter, zone)
1741 ; rr && !st
1742 ; rr = dnssec_zone_rr_iter_next(&rr_iter)) {
1743 /* Skip apex ZONEMD RRs */
1745 && !ldns_dname_compare(ldns_rr_owner(rr), apex_name))
1746 continue;
1747 /* Skip RRSIGs for apex ZONEMD RRs */
1751 && !ldns_dname_compare(ldns_rr_owner(rr), apex_name))
1752 continue;
1753 st = zone_digester_update(zd, rr);
1754 }
1755 return st;
1756}
1757
1760{
1761 ldns_dnssec_rrsets *zonemd, *soa;
1762 zone_digester zd;
1763 ldns_dnssec_rrs *rrs;
1764 ldns_rr *soa_rr;
1765 ldns_status st;
1768 size_t valid_zonemds;
1769
1770 if (!zone)
1771 return LDNS_STATUS_NULL;
1772
1774 zone, zone->soa->name, LDNS_RR_TYPE_ZONEMD);
1775 if (!zonemd) {
1776 ldns_rbnode_t *nsec3_node;
1777
1778 /* we need proof of non-existence for ZONEMD at the apex */
1779 if (zone->soa->nsec) {
1781 zone->soa->nsec),
1783 return LDNS_STATUS_NO_ZONEMD;
1784
1785 } else if (!zone->soa->hashed_name || !zone->hashed_names)
1786 return LDNS_STATUS_NO_ZONEMD;
1787
1788 else if (LDNS_RBTREE_NULL ==
1789 (nsec3_node = ldns_rbtree_search( zone->hashed_names
1790 , zone->soa->hashed_name)))
1791 return LDNS_STATUS_NO_ZONEMD;
1792 else {
1793 ldns_dnssec_name *nsec3
1794 = (ldns_dnssec_name *)nsec3_node->data;
1796 nsec3->nsec),
1798 return LDNS_STATUS_NO_ZONEMD;
1799 }
1800 /* ZONEMD at apex does really not exist */
1801 return LDNS_STATUS_OK;
1802 }
1804 zone, zone->soa->name, LDNS_RR_TYPE_SOA);
1805 if (!soa || !soa->rrs || !soa->rrs->rr)
1807
1808 soa_rr = soa->rrs->rr;
1809 if (ldns_rr_get_type(soa_rr) != LDNS_RR_TYPE_SOA
1810 || ldns_rr_rd_count(soa_rr) < 3)
1812
1813 zone_digester_init(&zd);
1814 for (rrs = zonemd->rrs; rrs; rrs = rrs->next) {
1815 if (!rrs->rr
1817 || ldns_rr_rd_count(rrs->rr) < 4)
1818 continue;
1819
1820 /* serial should match SOA's serial */
1821 if (ldns_rdf2native_int32(ldns_rr_rdf(soa_rr, 2))
1823 continue;
1824
1825 /* Add (scheme, hash) to digester */
1826 zone_digester_add(&zd,
1829 }
1830 if (!zone_digester_set(&zd))
1832
1833 if ((st = ldns_digest_zone(zone, &zd)))
1834 return st;
1835
1836 if (zd.simple_sha384)
1838 if (zd.simple_sha512)
1840
1841 valid_zonemds = 0;
1842 for (rrs = zonemd->rrs; rrs; rrs = rrs->next) {
1843 if (!rrs->rr
1845 || ldns_rr_rd_count(rrs->rr) < 4)
1846 continue;
1847
1848 /* serial should match SOA's serial */
1849 if (ldns_rdf2native_int32(ldns_rr_rdf(soa_rr, 2))
1851 continue;
1852
1855 continue;
1856
1860 == ldns_rdf_size(ldns_rr_rdf(rrs->rr, 3))
1861 && memcmp( simple_sha384
1862 , ldns_rdf_data(ldns_rr_rdf(rrs->rr, 3))
1864
1865 valid_zonemds += 1;
1866
1870 == ldns_rdf_size(ldns_rr_rdf(rrs->rr, 3))
1871 && memcmp( simple_sha512
1872 , ldns_rdf_data(ldns_rr_rdf(rrs->rr, 3))
1874
1875 valid_zonemds += 1;
1876 }
1877 return valid_zonemds ? LDNS_STATUS_OK : LDNS_STATUS_NO_VALID_ZONEMD;
1878}
1879
1880#ifdef HAVE_SSL
1881static ldns_status
1882rr_list2dnssec_rrs(ldns_rr_list *rr_list, ldns_dnssec_rrs **rrs,
1883 ldns_rr_list *new_rrs)
1884{
1885 ldns_rr *rr = NULL;
1886
1887 if (!rr_list || !rrs)
1888 return LDNS_STATUS_NULL;
1889
1890 if (ldns_rr_list_rr_count(rr_list) == 0)
1891 return LDNS_STATUS_OK;
1892
1893 if (!*rrs) {
1894 if (!(*rrs = ldns_dnssec_rrs_new()))
1895 return LDNS_STATUS_MEM_ERR;
1896 (*rrs)->rr = ldns_rr_list_pop_rr(rr_list);
1897 if (new_rrs)
1898 ldns_rr_list_push_rr(new_rrs, (*rrs)->rr);
1899 }
1900 while ((rr = ldns_rr_list_pop_rr(rr_list))) {
1901 ldns_status st;
1902
1903 if ((st = ldns_dnssec_rrs_add_rr(*rrs, rr))) {
1904 ldns_rr_list_push_rr(rr_list, rr);
1905 return st;
1906 } else if (new_rrs)
1907 ldns_rr_list_push_rr(new_rrs, rr);
1908 }
1909 return LDNS_STATUS_OK;
1910}
1911
1912
1915 ldns_rr_list *new_rrs, ldns_key_list *key_list, int signflags);
1918 ldns_rr_list *new_rrs, ldns_key_list *key_list, int signflags)
1919{
1921 zone_digester zd;
1922 ldns_rr_list *zonemd_rr_list = NULL;
1923 ldns_rr_list *zonemd_rrsigs = NULL;
1924 ldns_dnssec_rrsets *soa_rrset;
1925 ldns_rr *soa_rr = NULL;
1926 ldns_dnssec_rrsets **rrset_ref;
1927 ldns_dnssec_rrsets *zonemd_rrset;
1928
1929 zone_digester_init(&zd);
1931 zone_digester_add(&zd, ZONEMD_SCHEME_SIMPLE
1933
1935 zone_digester_add(&zd, ZONEMD_SCHEME_SIMPLE
1937
1938 if ((st = ldns_digest_zone(zone, &zd)))
1939 return st;
1940
1941 soa_rrset = ldns_dnssec_zone_find_rrset(
1942 zone, zone->soa->name, LDNS_RR_TYPE_SOA);
1943 if (!soa_rrset || !soa_rrset->rrs || !soa_rrset->rrs->rr)
1945 soa_rr = soa_rrset->rrs->rr;
1946
1947 if (!(zonemd_rr_list = zone_digester_export(&zd, soa_rr, &st)))
1948 return st;
1949
1950 /* - replace or add ZONEMD rrset */
1951 rrset_ref = &zone->soa->rrsets; /* scan rrsets at apex */
1952 while (*rrset_ref && (*rrset_ref)->type < LDNS_RR_TYPE_ZONEMD)
1953 rrset_ref = &(*rrset_ref)->next;
1954 if (*rrset_ref && (*rrset_ref)->type == LDNS_RR_TYPE_ZONEMD) {
1955 /* reuse zonemd rrset */
1956 zonemd_rrset = *rrset_ref;
1957 ldns_dnssec_rrs_free(zonemd_rrset->rrs);
1958 zonemd_rrset->rrs = NULL;
1959 ldns_dnssec_rrs_free(zonemd_rrset->signatures);
1960 zonemd_rrset->signatures = NULL;
1961 } else {
1962 /* insert zonemd rrset */
1963 zonemd_rrset = ldns_dnssec_rrsets_new();
1964 if (!zonemd_rrset) {
1965 ldns_rr_list_deep_free(zonemd_rr_list);
1966 return LDNS_STATUS_MEM_ERR;
1967 }
1968 zonemd_rrset->type = LDNS_RR_TYPE_ZONEMD;
1969 zonemd_rrset->next = *rrset_ref;
1970 *rrset_ref = zonemd_rrset;
1971 }
1972 if ((zonemd_rrsigs = ldns_sign_public(zonemd_rr_list, key_list)))
1973 st = rr_list2dnssec_rrs( zonemd_rrsigs
1974 , &zonemd_rrset->signatures, new_rrs);
1975 if (!st)
1976 st = rr_list2dnssec_rrs( zonemd_rr_list
1977 , &zonemd_rrset->rrs, new_rrs);
1978 ldns_rr_list_deep_free(zonemd_rr_list);
1979 ldns_rr_list_deep_free(zonemd_rrsigs);
1980 return st;
1981}
1982
1983#endif /* HAVE_SSL */
1984
#define ATTR_UNUSED(x)
Definition common.h:72
signed char ldns_dname_is_subdomain(const ldns_rdf *sub, const ldns_rdf *parent)
test whether the name sub falls under parent (i.e.
Definition dname.c:296
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:359
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_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:560
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
signed char ldns_nsec_bitmap_covers_type(const ldns_rdf *bitmap, ldns_rr_type type)
Check if RR type t is enumerated and set in the RR type bitmap rdf.
Definition dnssec.c:1393
ldns_rdf * ldns_nsec_get_bitmap(const ldns_rr *nsec)
Returns the rdata field that contains the bitmap of the covered types of the given NSEC record.
Definition dnssec.c:89
ldns_rdf * ldns_nsec3_hash_name_frm_nsec3(const ldns_rr *nsec, const ldns_rdf *name)
Calculates the hashed name using the parameters of the given NSEC3 RR.
Definition dnssec.c:1368
signed char 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:1286
ldns_rr_list * ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys)
Sign an rrset.
#define LDNS_SIGN_WITH_ZONEMD_SIMPLE_SHA384
Definition dnssec_sign.h:18
#define LDNS_SIGN_WITH_ZONEMD_SIMPLE_SHA512
Definition dnssec_sign.h:19
ldns_status ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone **z, FILE *fp, const ldns_rdf *origin, uint32_t default_ttl, ldns_rr_class c __attribute__((unused)), int *line_nr)
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.
void ldns_dnssec_zone_print_fmt(FILE *out, const ldns_output_format *fmt, const ldns_dnssec_zone *zone)
Prints the complete zone to the given file descriptor.
void ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt, const ldns_rbtree_t *tree, signed char print_soa)
Prints the rbtree of ldns_dnssec_name structures to the file descriptor.
ldns_status ldns_dnssec_zone_verify_zonemd(ldns_dnssec_zone *zone)
enum_zonemd_scheme
@ ZONEMD_SCHEME_SIMPLE
@ ZONEMD_SCHEME_FIRST
@ ZONEMD_SCHEME_LAST
void ldns_dnssec_name_set_nsec(ldns_dnssec_name *rrset, ldns_rr *nsec)
Sets the NSEC(3) RR of the given dnssec_name structure.
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_dnssec_zone * ldns_dnssec_zone_new(void)
Creates a new dnssec_zone structure.
ldns_rdf * ldns_dnssec_name_name(const ldns_dnssec_name *name)
Returns the domain name of the given dnssec_name structure.
void ldns_dnssec_name_set_name(ldns_dnssec_name *rrset, ldns_rdf *dname)
Sets the domain name of the given dnssec_name structure.
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
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_dnssec_rrsets * ldns_dnssec_zone_find_rrset(const ldns_dnssec_zone *zone, const ldns_rdf *dname, ldns_rr_type type)
Find the RRset with the given name and type in the zone.
ldns_status dnssec_zone_equip_zonemd(ldns_dnssec_zone *zone, ldns_rr_list *new_rrs, ldns_key_list *key_list, int signflags)
void ldns_dnssec_zone_print(FILE *out, const ldns_dnssec_zone *zone)
Prints the complete zone to the given file descriptor.
void ldns_dnssec_name_deep_free(ldns_dnssec_name *name)
Frees the name structure and its rrs and rrsets.
void ldns_dnssec_rrsets_print(FILE *out, const ldns_dnssec_rrsets *rrsets, signed char follow)
Print the given list of rrsets to the given file descriptor.
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.
void ldns_dnssec_name_free(ldns_dnssec_name *name)
Frees the name structure and its rrs and rrsets.
ldns_dnssec_rrsets * ldns_dnssec_name_find_rrset(const ldns_dnssec_name *name, ldns_rr_type type)
Find the RRset with the given type in within this name structure.
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...
void ldns_dnssec_zone_names_print(FILE *out, const ldns_rbtree_t *tree, signed char print_soa)
Prints the rbtree of ldns_dnssec_name structures to the file descriptor.
void ldns_dnssec_rrs_print_fmt(FILE *out, const ldns_output_format *fmt, const ldns_dnssec_rrs *rrs)
Prints the given rrs to the file descriptor.
Definition dnssec_zone.c:80
ldns_status ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr)
Adds the given RR to the zone.
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.
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_dnssec_zone_new_frm_fp(ldns_dnssec_zone **z, FILE *fp, const ldns_rdf *origin, uint32_t ttl, ldns_rr_class c __attribute__((unused)))
ldns_status ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
Adds explicit dnssec_name structures for the empty nonterminals in this zone.
signed char ldns_dnssec_name_is_glue(const ldns_dnssec_name *name)
Returns if dnssec_name structure is marked as glue.
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...
signed char ldns_dnssec_zone_is_nsec3_optout(const ldns_dnssec_zone *zone)
If a NSEC3PARAM is available in the apex, walks the zone and returns true on the first optout nsec3.
void ldns_dnssec_rrs_print(FILE *out, const ldns_dnssec_rrs *rrs)
Prints the given rrs to the file descriptor.
Definition dnssec_zone.c:97
enum enum_zonemd_hash zonemd_hash
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.
void ldns_dnssec_name_print_fmt(FILE *out, const ldns_output_format *fmt, const ldns_dnssec_name *name)
Prints the RRs in the dnssec name structure to the given file descriptor.
enum_zonemd_hash
@ ZONEMD_HASH_SHA512
@ ZONEMD_HASH_LAST
@ ZONEMD_HASH_SHA384
@ ZONEMD_HASH_FIRST
enum enum_zonemd_scheme zonemd_scheme
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...
void ldns_dnssec_rrsets_print_fmt(FILE *out, const ldns_output_format *fmt, const ldns_dnssec_rrsets *rrsets, signed char follow)
Print the given list of rrsets to the given file descriptor.
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)
void ldns_dnssec_name_print(FILE *out, const ldns_dnssec_name *name)
Prints the RRs in the dnssec name structure to the given file descriptor.
ldns_dnssec_rrsets * ldns_dnssec_rrsets_new(void)
Creates a new list (entry) of RRsets.
int ldns_dname_compare_v(const void *a, const void *b)
Given in dnssec_zone.c, also used in dnssec_sign.c:w.
int ldns_dnssec_name_cmp(const void *a, const void *b)
Compares the domain names of the two arguments in their canonical ordering.
dnssec_zone_rr_iter_state
@ DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC
@ DNSSEC_ZONE_RR_ITER_LT_RRSIG
@ DNSSEC_ZONE_RR_ITER_REST
@ DNSSEC_ZONE_RR_ITER_FINI
@ DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC_REST
@ DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC
@ DNSSEC_ZONE_RR_ITER_NSEC3
ldns_rr_type ldns_dnssec_rrsets_type(const ldns_dnssec_rrsets *rrsets)
Returns the rr type of the rrset (that is head of the given list)
ldns_dnssec_name * ldns_dnssec_name_new(void)
Create a new data structure for a dnssec name.
@ LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND
Definition error.h:101
@ LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL
Definition error.h:82
@ LDNS_STATUS_ZONEMD_UNKNOWN_SCHEME
Definition error.h:134
@ LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE
Definition error.h:133
@ LDNS_STATUS_NULL
Definition error.h:51
@ LDNS_STATUS_ERR
Definition error.h:37
@ LDNS_STATUS_MEM_ERR
Definition error.h:34
@ LDNS_STATUS_SYNTAX_TTL
Definition error.h:88
@ LDNS_STATUS_NO_ZONEMD
Definition error.h:137
@ LDNS_STATUS_ZONEMD_UNKNOWN_HASH
Definition error.h:135
@ LDNS_STATUS_OK
Definition error.h:26
@ LDNS_STATUS_SYNTAX_EMPTY
Definition error.h:91
@ LDNS_STATUS_ZONEMD_INVALID_SOA
Definition error.h:136
@ LDNS_STATUS_NO_VALID_ZONEMD
Definition error.h:138
@ LDNS_STATUS_SYNTAX_INCLUDE
Definition error.h:90
@ LDNS_STATUS_SYNTAX_ORIGIN
Definition error.h:89
enum ldns_enum_status ldns_status
Definition error.h:148
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:3394
const ldns_output_format * ldns_output_format_default
The default output format record.
Definition host2str.c:142
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:3406
#define LDNS_COMMENT_LAYOUT
Print mark up.
Definition host2str.h:62
ldns_status ldns_rr2buffer_wire_canonical(ldns_buffer *output, const ldns_rr *rr, int section)
Copies the rr data to the buffer in wire format, in canonical format according to RFC3597 (every dnam...
Definition host2wire.c:171
Including this file will include all ldns files, and define some lookup tables.
@ LDNS_SECTION_ANSWER
Definition packet.h:279
ldns_rbnode_t * ldns_rbtree_search(ldns_rbtree_t *rbtree, const void *key)
Find key in tree.
Definition rbtree.c:294
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_rbnode_t * ldns_rbtree_first(const ldns_rbtree_t *rbtree)
Returns first (smallest) node in the tree.
Definition rbtree.c:548
ldns_rbnode_t * ldns_rbtree_next(ldns_rbnode_t *rbtree)
Returns next larger node in the tree.
Definition rbtree.c:574
ldns_rbnode_t * ldns_rbtree_insert(ldns_rbtree_t *rbtree, ldns_rbnode_t *data)
Insert data into the tree.
Definition rbtree.c:242
#define LDNS_RBTREE_NULL
The nullpointer, points to empty node.
Definition rbtree.h:76
void ldns_rbtree_init(ldns_rbtree_t *rbtree, int(*cmpf)(const void *, const void *))
Init a new tree (malloced by caller) with given key compare function.
Definition rbtree.c:97
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
uint8_t * ldns_rdf_data(const ldns_rdf *rd)
returns the data of the rdf.
Definition rdata.c:38
ldns_rdf * ldns_rdf_clone(const ldns_rdf *rd)
clones a rdf structure.
Definition rdata.c:222
ldns_rdf_type ldns_rdf_get_type(const ldns_rdf *rd)
returns the type of the rdf.
Definition rdata.c:31
void ldns_rdf_deep_free(ldns_rdf *rd)
frees a rdf structure and frees the data.
Definition rdata.c:230
uint32_t ldns_rdf2native_int32(const ldns_rdf *rd)
returns the native uint32_t representation from the rdf.
Definition rdata.c:98
ldns_rdf * ldns_native2rdf_int8(ldns_rdf_type type, uint8_t value)
returns the rdf containing the native uint8_t repr.
Definition rdata.c:126
uint8_t ldns_rdf2native_int8(const ldns_rdf *rd)
returns the native uint8_t representation from the rdf.
Definition rdata.c:70
@ LDNS_RDF_TYPE_INT32
32 bits
Definition rdata.h:56
@ LDNS_RDF_TYPE_HEX
hex string
Definition rdata.h:70
@ LDNS_RDF_TYPE_INT8
8 bits
Definition rdata.h:52
size_t ldns_rdf_size(const ldns_rdf *rd)
returns the size of the rdf.
Definition rdata.c:24
ldns_rdf * ldns_rdf_new(ldns_rdf_type type, size_t size, void *data)
allocates a new rdf structure and fills it.
Definition rdata.c:179
void ldns_rr_list_free(ldns_rr_list *rr_list)
frees an rr_list structure.
Definition rr.c:1015
uint32_t ldns_rr_ttl(const ldns_rr *rr)
returns the ttl of an rr structure.
Definition rr.c:935
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:2762
void ldns_rr_list_deep_free(ldns_rr_list *rr_list)
frees an rr_list structure and all rrs contained therein.
Definition rr.c:1024
void ldns_rr_free(ldns_rr *rr)
frees an RR structure
Definition rr.c:81
void ldns_rr_set_owner(ldns_rr *rr, ldns_rdf *owner)
sets the owner in the rr structure.
Definition rr.c:808
ldns_rr_list * ldns_rr_list_new(void)
creates a new rr_list structure.
Definition rr.c:1004
ldns_rr * ldns_rr_list_pop_rr(ldns_rr_list *rr_list)
pops the last rr from an rrlist.
Definition rr.c:1181
enum ldns_enum_rr_type ldns_rr_type
Definition rr.h:251
ldns_rr * ldns_rr_new_frm_type(ldns_rr_type t)
creates a new rr structure, based on the given type.
Definition rr.c:48
@ LDNS_RR_TYPE_RRSIG
DNSSEC.
Definition rr.h:170
@ LDNS_RR_TYPE_ZONEMD
Definition rr.h:194
@ LDNS_RR_TYPE_SOA
marks the start of a zone of authority
Definition rr.h:90
@ LDNS_RR_TYPE_NSEC
Definition rr.h:171
@ LDNS_RR_TYPE_NSEC3PARAM
Definition rr.h:177
@ LDNS_RR_TYPE_SIG
2535typecode
Definition rr.h:126
@ LDNS_RR_TYPE_NSEC3
Definition rr.h:176
signed char ldns_rr_list_push_rr(ldns_rr_list *rr_list, const ldns_rr *rr)
pushes an rr to an rrlist.
Definition rr.c:1136
size_t ldns_rr_rd_count(const ldns_rr *rr)
returns the rd_count of an rr structure.
Definition rr.c:941
ldns_rdf * ldns_rr_rdf(const ldns_rr *rr, size_t nr)
returns the rdata field member counter.
Definition rr.c:913
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:961
ldns_rr_type ldns_rr_get_type(const ldns_rr *rr)
returns the type of the rr.
Definition rr.c:947
void ldns_rr_set_ttl(ldns_rr *rr, uint32_t ttl)
sets the ttl in the rr structure.
Definition rr.c:820
ldns_rdf * ldns_rr_set_rdf(ldns_rr *rr, const ldns_rdf *f, size_t position)
sets a rdf member, it will be set on the position given.
Definition rr.c:844
ldns_rr_class ldns_rr_get_class(const ldns_rr *rr)
returns the class of the rr.
Definition rr.c:953
enum ldns_enum_rr_class ldns_rr_class
Definition rr.h:61
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:994
void ldns_rr_set_class(ldns_rr *rr, ldns_rr_class rr_class)
sets the class in the rr.
Definition rr.c:838
ldns_status ldns_rr_new_frm_fp_l(ldns_rr **rr, 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:800
ldns_rdf * ldns_rr_owner(const ldns_rr *rr)
returns the owner name of an rr structure.
Definition rr.c:923
int ldns_rr_compare(const ldns_rr *rr1, const ldns_rr *rr2)
compares two rrs.
Definition rr.c:1642
ldns_rdf * ldns_rr_rrsig_typecovered(const ldns_rr *r)
returns the type covered of a LDNS_RR_TYPE_RRSIG rr
void ldns_sha512_update(ldns_sha512_CTX *, const uint8_t *, size_t)
Definition sha2.c:815
void ldns_sha384_init(ldns_sha384_CTX *)
Definition sha2.c:948
void ldns_sha512_init(ldns_sha512_CTX *)
Definition sha2.c:634
#define LDNS_SHA512_DIGEST_LENGTH
Definition sha2.h:69
void ldns_sha512_final(uint8_t[64], ldns_sha512_CTX *)
Definition sha2.c:908
#define LDNS_SHA384_DIGEST_LENGTH
Definition sha2.h:66
void ldns_sha384_update(ldns_sha384_CTX *, const uint8_t *, size_t)
Definition sha2.c:957
void ldns_sha384_final(uint8_t[48], ldns_sha384_CTX *)
Definition sha2.c:961
ldns_dnssec_name * nsec3_name
dnssec_zone_rr_iter_state state
ldns_dnssec_name * name
ldns_dnssec_rrsets * rrsets4rrsigs
ldns_dnssec_zone * zone
ldns_rbnode_t * nsec3_node
ldns_rbnode_t * node
ldns_dnssec_rrs * rrs
ldns_dnssec_rrsets * rrsets
The rbnode_t struct definition.
Definition rbtree.h:60
const void * data
pointer to data
Definition rbtree.h:70
const void * key
pointer to sorting key
Definition rbtree.h:68
definition for tree struct
Definition rbtree.h:83
size_t count
The number of the nodes in the tree.
Definition rbtree.h:88
implementation of buffers to ease operations
Definition buffer.h:51
size_t _capacity
The amount of data the buffer can contain.
Definition buffer.h:59
unsigned _fixed
If the buffer is fixed it cannot be resized.
Definition buffer.h:65
size_t _position
The current position used for reading/writing.
Definition buffer.h:53
ldns_status _status
The current state of the buffer.
Definition buffer.h:70
uint8_t * _data
The data contained in the buffer.
Definition buffer.h:62
size_t _limit
The read/write limit.
Definition buffer.h:56
ldns_dnssec_rrs * nsec_signatures
signatures for the NSEC record
Definition dnssec_zone.h:71
ldns_rr * nsec
NSEC pointing to the next name (or NSEC3 pointing to the next NSEC3)
Definition dnssec_zone.h:67
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
ldns_rdf * hashed_name
pointer to store the hashed name (only used when in an NSEC3 zone
Definition dnssec_zone.h:85
ldns_dnssec_rrsets * rrsets
The rrsets for this name.
Definition dnssec_zone.h:63
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
ldns_rdf * name
pointer to a dname containing the name.
Definition dnssec_zone.h:51
ldns_dnssec_rrs * next
Definition dnssec_zone.h:25
ldns_dnssec_rrs * rrs
Definition dnssec_zone.h:34
ldns_dnssec_rrs * signatures
Definition dnssec_zone.h:36
ldns_dnssec_rrsets * next
Definition dnssec_zone.h:37
Structure containing a dnssec zone.
Definition dnssec_zone.h:91
ldns_rbtree_t * hashed_names
tree of ldns_dnssec_names by nsec3 hashes (when applicable)
Definition dnssec_zone.h:97
ldns_rbtree_t * names
tree of ldns_dnssec_names
Definition dnssec_zone.h:95
ldns_rr * _nsec3params
points to the first added NSEC3 rr whose parameters will be assumed for all subsequent NSEC3 rr's and...
ldns_dnssec_name * soa
points to the name containing the SOA RR
Definition dnssec_zone.h:93
Same as rr_list, but now for keys.
Definition keys.h:173
Output format specifier.
Definition host2str.h:89
int flags
Specification of how RR's should be formatted in text.
Definition host2str.h:91
Resource record data field.
Definition rdata.h:197
List or Set of Resource Records.
Definition rr.h:346
Resource Record.
Definition rr.h:318
DNS Zone.
Definition zone.h:43
ldns_sha512_CTX sha512_CTX
ldns_sha384_CTX sha384_CTX
#define INLINE
splint static inline workaround
Definition util.h:42
#define LDNS_FREE(ptr)
Definition util.h:60
#define LDNS_CALLOC(type, count)
Definition util.h:53
#define LDNS_MALLOC(type)
Memory management macros.
Definition util.h:49
#define LDNS_XMALLOC(type, count)
Definition util.h:51
ldns_rr * ldns_zone_soa(const ldns_zone *z)
Return the soa record of a zone.
Definition zone.c:17
ldns_rr_list * ldns_zone_rrs(const ldns_zone *z)
Get a list of a zone's content.
Definition zone.c:35
void ldns_zone_free(ldns_zone *zone)
Frees the allocated memory for the zone, and the rr_list structure in it.
Definition zone.c:369
ldns_status ldns_zone_new_frm_fp_l(ldns_zone **z, FILE *fp, const ldns_rdf *origin, uint32_t ttl, ldns_rr_class c, int *line_nr)
Create a new zone from a file, keep track of the line numbering.