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 } else
76
77 return LDNS_STATUS_OK;
78}
79
80void
82 const ldns_dnssec_rrs *rrs)
83{
84 if (!rrs) {
85 if ((fmt->flags & LDNS_COMMENT_LAYOUT))
86 fprintf(out, "; <void>");
87 } else {
88 if (rrs->rr) {
89 ldns_rr_print_fmt(out, fmt, rrs->rr);
90 }
91 if (rrs->next) {
92 ldns_dnssec_rrs_print_fmt(out, fmt, rrs->next);
93 }
94 }
95}
96
97void
102
103
106{
107 ldns_dnssec_rrsets *new_rrsets;
108 new_rrsets = LDNS_MALLOC(ldns_dnssec_rrsets);
109 if(!new_rrsets) return NULL;
110 new_rrsets->rrs = NULL;
111 new_rrsets->type = 0;
112 new_rrsets->signatures = NULL;
113 new_rrsets->next = NULL;
114 return new_rrsets;
115}
116
117INLINE void
118ldns_dnssec_rrsets_free_internal(ldns_dnssec_rrsets *rrsets, int deep)
119{
120 if (rrsets) {
121 if (rrsets->rrs) {
122 ldns_dnssec_rrs_free_internal(rrsets->rrs, deep);
123 }
124 if (rrsets->next) {
125 ldns_dnssec_rrsets_free_internal(rrsets->next, deep);
126 }
127 if (rrsets->signatures) {
128 ldns_dnssec_rrs_free_internal(rrsets->signatures, deep);
129 }
130 LDNS_FREE(rrsets);
131 }
132}
133
134void
136{
137 ldns_dnssec_rrsets_free_internal(rrsets, 0);
138}
139
140void
142{
143 ldns_dnssec_rrsets_free_internal(rrsets, 1);
144}
145
148{
149 if (rrsets) {
150 return rrsets->type;
151 } else {
152 return 0;
153 }
154}
155
158 ldns_rr_type type)
159{
160 if (rrsets) {
161 rrsets->type = type;
162 return LDNS_STATUS_OK;
163 }
164 return LDNS_STATUS_ERR;
165}
166
167static ldns_dnssec_rrsets *
168ldns_dnssec_rrsets_new_frm_rr(ldns_rr *rr)
169{
170 ldns_dnssec_rrsets *new_rrsets;
171 ldns_rr_type rr_type;
172 bool rrsig;
173
174 new_rrsets = ldns_dnssec_rrsets_new();
175 rr_type = ldns_rr_get_type(rr);
176 if (rr_type == LDNS_RR_TYPE_RRSIG) {
177 rrsig = true;
179 } else {
180 rrsig = false;
181 }
182 if (!rrsig) {
183 new_rrsets->rrs = ldns_dnssec_rrs_new();
184 new_rrsets->rrs->rr = rr;
185 } else {
186 new_rrsets->signatures = ldns_dnssec_rrs_new();
187 new_rrsets->signatures->rr = rr;
188 }
189 new_rrsets->type = rr_type;
190 return new_rrsets;
191}
192
195{
196 ldns_dnssec_rrsets *new_rrsets;
197 ldns_rr_type rr_type;
198 bool rrsig = false;
200
201 if (!rrsets || !rr) {
202 return LDNS_STATUS_ERR;
203 }
204
205 rr_type = ldns_rr_get_type(rr);
206
207 if (rr_type == LDNS_RR_TYPE_RRSIG) {
208 rrsig = true;
210 }
211
212 if (!rrsets->rrs && rrsets->type == 0 && !rrsets->signatures) {
213 if (!rrsig) {
214 rrsets->rrs = ldns_dnssec_rrs_new();
215 rrsets->rrs->rr = rr;
216 rrsets->type = rr_type;
217 } else {
219 rrsets->signatures->rr = rr;
220 rrsets->type = rr_type;
221 }
222 return LDNS_STATUS_OK;
223 }
224
225 if (rr_type > ldns_dnssec_rrsets_type(rrsets)) {
226 if (rrsets->next) {
227 result = ldns_dnssec_rrsets_add_rr(rrsets->next, rr);
228 } else {
229 new_rrsets = ldns_dnssec_rrsets_new_frm_rr(rr);
230 rrsets->next = new_rrsets;
231 }
232 } else if (rr_type < ldns_dnssec_rrsets_type(rrsets)) {
233 /* move the current one into the new next,
234 replace field of current with data from new rr */
235 new_rrsets = ldns_dnssec_rrsets_new();
236 new_rrsets->rrs = rrsets->rrs;
237 new_rrsets->type = rrsets->type;
238 new_rrsets->signatures = rrsets->signatures;
239 new_rrsets->next = rrsets->next;
240 if (!rrsig) {
241 rrsets->rrs = ldns_dnssec_rrs_new();
242 rrsets->rrs->rr = rr;
243 rrsets->signatures = NULL;
244 } else {
245 rrsets->rrs = NULL;
247 rrsets->signatures->rr = rr;
248 }
249 rrsets->type = rr_type;
250 rrsets->next = new_rrsets;
251 } else {
252 /* equal, add to current rrsets */
253 if (rrsig) {
254 if (rrsets->signatures) {
255 result = ldns_dnssec_rrs_add_rr(rrsets->signatures, rr);
256 } else {
258 rrsets->signatures->rr = rr;
259 }
260 } else {
261 if (rrsets->rrs) {
262 result = ldns_dnssec_rrs_add_rr(rrsets->rrs, rr);
263 } else {
264 rrsets->rrs = ldns_dnssec_rrs_new();
265 rrsets->rrs->rr = rr;
266 }
267 }
268 }
269
270 return result;
271}
272
273static void
274ldns_dnssec_rrsets_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
275 const ldns_dnssec_rrsets *rrsets,
276 bool follow,
277 bool show_soa)
278{
279 if (!rrsets) {
280 if ((fmt->flags & LDNS_COMMENT_LAYOUT))
281 fprintf(out, "; <void>\n");
282 } else {
283 if (rrsets->rrs &&
284 (show_soa ||
286 )
287 ) {
288 ldns_dnssec_rrs_print_fmt(out, fmt, rrsets->rrs);
289 if (rrsets->signatures) {
291 rrsets->signatures);
292 }
293 }
294 if (follow && rrsets->next) {
295 ldns_dnssec_rrsets_print_soa_fmt(out, fmt,
296 rrsets->next, follow, show_soa);
297 }
298 }
299}
300
301
302void
304 const ldns_dnssec_rrsets *rrsets,
305 bool follow)
306{
307 ldns_dnssec_rrsets_print_soa_fmt(out, fmt, rrsets, follow, true);
308}
309
310void
311ldns_dnssec_rrsets_print(FILE *out, const ldns_dnssec_rrsets *rrsets, bool follow)
312{
314 rrsets, follow);
315}
316
319{
320 ldns_dnssec_name *new_name;
321
322 new_name = LDNS_CALLOC(ldns_dnssec_name, 1);
323 if (!new_name) {
324 return NULL;
325 }
326 /*
327 * not needed anymore because CALLOC initializes everything to zero.
328
329 new_name->name = NULL;
330 new_name->rrsets = NULL;
331 new_name->name_alloced = false;
332 new_name->nsec = NULL;
333 new_name->nsec_signatures = NULL;
334
335 new_name->is_glue = false;
336 new_name->hashed_name = NULL;
337
338 */
339 return new_name;
340}
341
344{
346
347 new_name->name = ldns_rr_owner(rr);
348 if(ldns_dnssec_name_add_rr(new_name, rr) != LDNS_STATUS_OK) {
349 ldns_dnssec_name_free(new_name);
350 return NULL;
351 }
352
353 return new_name;
354}
355
356INLINE void
357ldns_dnssec_name_free_internal(ldns_dnssec_name *name,
358 int deep)
359{
360 if (name) {
361 if (name->name_alloced) {
363 }
364 if (name->rrsets) {
365 ldns_dnssec_rrsets_free_internal(name->rrsets, deep);
366 }
367 if (name->nsec && deep) {
368 ldns_rr_free(name->nsec);
369 }
370 if (name->nsec_signatures) {
371 ldns_dnssec_rrs_free_internal(name->nsec_signatures, deep);
372 }
373 if (name->hashed_name) {
374 /* Hashed name is always allocated when signing,
375 * so always deep free
376 */
378 }
379 LDNS_FREE(name);
380 }
381}
382
383void
385{
386 ldns_dnssec_name_free_internal(name, 0);
387}
388
389void
391{
392 ldns_dnssec_name_free_internal(name, 1);
393}
394
395ldns_rdf *
397{
398 if (name) {
399 return name->name;
400 }
401 return NULL;
402}
403
404bool
406{
407 if (name) {
408 return name->is_glue;
409 }
410 return false;
411}
412
413void
415 ldns_rdf *dname)
416{
417 if (rrset && dname) {
418 rrset->name = dname;
419 }
420}
421
422
423void
425{
426 if (rrset && nsec) {
427 rrset->nsec = nsec;
428 }
429}
430
431int
432ldns_dnssec_name_cmp(const void *a, const void *b)
433{
436
437 if (na && nb) {
440 } else if (na) {
441 return 1;
442 } else if (nb) {
443 return -1;
444 } else {
445 return 0;
446 }
447}
448
451 ldns_rr *rr)
452{
454 ldns_rr_type rr_type;
455 ldns_rr_type typecovered = 0;
456
457 /* special handling for NSEC3 and NSECX covering RRSIGS */
458
459 if (!name || !rr) {
460 return LDNS_STATUS_ERR;
461 }
462
463 rr_type = ldns_rr_get_type(rr);
464
465 if (rr_type == LDNS_RR_TYPE_RRSIG) {
467 }
468
469 if (rr_type == LDNS_RR_TYPE_NSEC ||
470 rr_type == LDNS_RR_TYPE_NSEC3) {
471 /* XX check if is already set (and error?) */
472 name->nsec = rr;
473 } else if (typecovered == LDNS_RR_TYPE_NSEC ||
474 typecovered == LDNS_RR_TYPE_NSEC3) {
475 if (name->nsec_signatures) {
476 result = ldns_dnssec_rrs_add_rr(name->nsec_signatures, rr);
477 } else {
479 name->nsec_signatures->rr = rr;
480 }
481 } else {
482 /* it's a 'normal' RR, add it to the right rrset */
483 if (name->rrsets) {
484 result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
485 } else {
487 result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
488 }
489 }
490 return result;
491}
492
495 ldns_rr_type type) {
496 ldns_dnssec_rrsets *result;
497
498 result = name->rrsets;
499 while (result) {
500 if (result->type == type) {
501 return result;
502 } else {
503 result = result->next;
504 }
505 }
506 return NULL;
507}
508
511 const ldns_rdf *dname,
512 ldns_rr_type type)
513{
514 ldns_rbnode_t *node;
515
516 if (!zone || !dname || !zone->names) {
517 return NULL;
518 }
519
520 node = ldns_rbtree_search(zone->names, dname);
521 if (node) {
523 type);
524 } else {
525 return NULL;
526 }
527}
528
529static void
530ldns_dnssec_name_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
531 const ldns_dnssec_name *name,
532 bool show_soa)
533{
534 if (name) {
535 if(name->rrsets) {
536 ldns_dnssec_rrsets_print_soa_fmt(out, fmt,
537 name->rrsets, true, show_soa);
538 } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
539 fprintf(out, ";; Empty nonterminal: ");
540 ldns_rdf_print(out, name->name);
541 fprintf(out, "\n");
542 }
543 if(name->nsec) {
544 ldns_rr_print_fmt(out, fmt, name->nsec);
545 }
546 if (name->nsec_signatures) {
548 name->nsec_signatures);
549 }
550 } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
551 fprintf(out, "; <void>\n");
552 }
553}
554
555
556void
558 const ldns_dnssec_name *name)
559{
560 ldns_dnssec_name_print_soa_fmt(out, fmt, name, true);
561}
562
563void
568
569
572{
574 if(!zone) return NULL;
575 zone->soa = NULL;
576 zone->names = NULL;
577 zone->hashed_names = NULL;
578 zone->_nsec3params = NULL;
579
580 return zone;
581}
582
583static bool
584rr_is_rrsig_covering(ldns_rr* rr, ldns_rr_type t)
585{
588}
589
590/* When the zone is first read into an list and then inserted into an
591 * ldns_dnssec_zone (rbtree) the nodes of the rbtree are allocated close (next)
592 * to each other. Because ldns-verify-zone (the only program that uses this
593 * function) uses the rbtree mostly for sequential walking, this results
594 * in a speed increase (of 15% on linux) because we have less CPU-cache misses.
595 */
596#define FASTER_DNSSEC_ZONE_NEW_FRM_FP 1 /* Because of L2 cache efficiency */
597
598static ldns_status
599ldns_dnssec_zone_add_empty_nonterminals_nsec3(
600 ldns_dnssec_zone *zone, ldns_rbtree_t *nsec3s);
601
602static void
603ldns_todo_nsec3_ents_node_free(ldns_rbnode_t *node, void *arg) {
604 (void) arg;
606 LDNS_FREE(node);
607}
608
611 uint32_t default_ttl, ldns_rr_class ATTR_UNUSED(c), int* line_nr)
612{
613 ldns_rr* cur_rr;
614 size_t i;
615
616 ldns_rdf *my_origin = NULL;
617 ldns_rdf *my_prev = NULL;
618
620 /* NSEC3s may occur before the names they refer to. We must remember
621 them and add them to the name later on, after the name is read.
622 We track not yet matching NSEC3s*n the todo_nsec3s list */
623 ldns_rr_list* todo_nsec3s = ldns_rr_list_new();
624 /* when reading NSEC3s, there is a chance that we encounter nsecs
625 for empty nonterminals, whose nonterminals we cannot derive yet
626 because the needed information is to be read later.
627
628 nsec3_ents (where ent is e.n.t.; i.e. empty non terminal) will
629 hold the NSEC3s that still didn't have a matching name in the
630 zone tree, even after all names were read. They can only match
631 after the zone is equipped with all the empty non terminals. */
632 ldns_rbtree_t todo_nsec3_ents;
633 ldns_rbnode_t *new_node;
634 ldns_rr_list* todo_nsec3_rrsigs = ldns_rr_list_new();
635
636 ldns_status status;
637
638#ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
639 ldns_zone* zone = NULL;
640#else
641 ldns_rr *prev_rr = NULL;
642 uint32_t my_ttl = default_ttl;
643 /* RFC 1035 Section 5.1, says 'Omitted class and TTL values are default
644 * to the last explicitly stated values.'
645 */
646 bool ttl_from_TTL = false;
647 bool explicit_ttl = false;
648#endif
649
650 ldns_rbtree_init(&todo_nsec3_ents, ldns_dname_compare_v);
651
652#ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
653 status = ldns_zone_new_frm_fp_l(&zone, fp, origin, default_ttl, c, line_nr);
654 if (status != LDNS_STATUS_OK)
655 goto error;
656#endif
657 if (!newzone || !todo_nsec3s || !todo_nsec3_rrsigs ) {
658 status = LDNS_STATUS_MEM_ERR;
659 goto error;
660 }
661 if (origin) {
662 if (!(my_origin = ldns_rdf_clone(origin))) {
663 status = LDNS_STATUS_MEM_ERR;
664 goto error;
665 }
666 if (!(my_prev = ldns_rdf_clone(origin))) {
667 status = LDNS_STATUS_MEM_ERR;
668 goto error;
669 }
670 }
671
672#ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
673 if (ldns_zone_soa(zone)) {
674 status = ldns_dnssec_zone_add_rr(newzone, ldns_zone_soa(zone));
675 if (status != LDNS_STATUS_OK)
676 goto error;
677 }
678 for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
679 cur_rr = ldns_rr_list_rr(ldns_zone_rrs(zone), i);
680 status = LDNS_STATUS_OK;
681#else
682 while (!feof(fp)) {
683 /* If ttl came from $TTL line, then it should be the default.
684 * (RFC 2308 Section 4)
685 * Otherwise it "defaults to the last explicitly stated value"
686 * (RFC 1035 Section 5.1)
687 */
688 if (ttl_from_TTL)
689 my_ttl = default_ttl;
690 status = ldns_rr_new_frm_fp_l(&cur_rr, fp, &my_ttl, &my_origin,
691 &my_prev, line_nr, &explicit_ttl);
692#endif
693 switch (status) {
694 case LDNS_STATUS_OK:
695#ifndef FASTER_DNSSEC_ZONE_NEW_FRM_FP
696 if (explicit_ttl) {
697 if (!ttl_from_TTL) {
698 /* No $TTL, so ttl "defaults to the
699 * last explicitly stated value"
700 * (RFC 1035 Section 5.1)
701 */
702 my_ttl = ldns_rr_ttl(cur_rr);
703 }
704 /* When ttl is implicit, try to adhere to the rules as
705 * much as possible. (also for compatibility with bind)
706 * This was changed when fixing an issue with ZONEMD
707 * which hashes the TTL too.
708 */
709 } else if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SIG
710 || ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_RRSIG) {
711 if (ldns_rr_rd_count(cur_rr) >= 4
713
714 /* SIG without explicit ttl get ttl
715 * from the original_ttl field
716 * (RFC 2535 Section 7.2)
717 *
718 * Similarly for RRSIG, but stated less
719 * specifically in the spec.
720 * (RFC 4034 Section 3)
721 */
722 ldns_rr_set_ttl(cur_rr,
724 ldns_rr_rdf(rr, 3)));
725
726 } else if (prev_rr
727 && ldns_rr_get_type(prev_rr) == ldns_rr_get_type(cur_rr)
729 , ldns_rr_owner(cur_rr)) == 0)
730
731 /* "TTLs of all RRs in an RRSet must be the same"
732 * (RFC 2881 Section 5.2)
733 */
734 ldns_rr_set_ttl(cur_rr, ldns_rr_ttl(prev_rr));
735
736#endif
737 status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
738 switch(status) {
740 if (rr_is_rrsig_covering(cur_rr,
742 ldns_rr_list_push_rr(todo_nsec3_rrsigs,
743 cur_rr);
744 } else {
745 ldns_rr_list_push_rr(todo_nsec3s,
746 cur_rr);
747 }
748 status = LDNS_STATUS_OK;
749 break;
751 ldns_rr_free(cur_rr);
752#ifndef FASTER_DNSSEC_ZONE_NEW_FRM_FP
753 cur_rr = prev_rr;
754#else
755 cur_rr = NULL;
756#endif
757 status = LDNS_STATUS_OK;
758 break;
759 case LDNS_STATUS_OK:
760 break;
761 default:
762 goto error;
763 }
764#ifndef FASTER_DNSSEC_ZONE_NEW_FRM_FP
765 prev_rr = cur_rr;
766#endif
767 break;
768
769 case LDNS_STATUS_SYNTAX_TTL: /* the ttl was set*/
770#ifndef FASTER_DNSSEC_ZONE_NEW_FRM_FP
771 default_ttl = my_ttl;
772 ttl_from_TTL = true;
773#endif
774 status = LDNS_STATUS_OK;
775 break;
776
777
778 case LDNS_STATUS_SYNTAX_EMPTY: /* empty line was seen */
779 case LDNS_STATUS_SYNTAX_ORIGIN: /* the origin was set*/
780 status = LDNS_STATUS_OK;
781 break;
782
783 case LDNS_STATUS_SYNTAX_INCLUDE:/* $include not implemented */
785 break;
786
787 default:
788 goto error;
789 }
790 }
791
792 for (i = 0; status == LDNS_STATUS_OK &&
793 i < ldns_rr_list_rr_count(todo_nsec3s); i++) {
794 cur_rr = ldns_rr_list_rr(todo_nsec3s, i);
795 status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
797 if (!(new_node = LDNS_MALLOC(ldns_rbnode_t))) {
798 status = LDNS_STATUS_MEM_ERR;
799 break;
800 }
801 new_node->key = ldns_dname_label(ldns_rr_owner(cur_rr), 0);
802 new_node->data = cur_rr;
803 if (!ldns_rbtree_insert(&todo_nsec3_ents, new_node)) {
804 LDNS_FREE(new_node);
805 status = LDNS_STATUS_MEM_ERR;
806 break;
807 }
808 status = LDNS_STATUS_OK;
809 }
810 }
811 if (todo_nsec3_ents.count > 0)
812 (void) ldns_dnssec_zone_add_empty_nonterminals_nsec3(
813 newzone, &todo_nsec3_ents);
814 for (i = 0; status == LDNS_STATUS_OK &&
815 i < ldns_rr_list_rr_count(todo_nsec3_rrsigs); i++) {
816 cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i);
817 status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
818 }
819 if (z) {
820 *z = newzone;
821 newzone = NULL;
822 } else {
823 ldns_dnssec_zone_free(newzone);
824 newzone = NULL;
825 }
826
827error:
828#ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
829 if (zone) {
830 ldns_zone_free(zone);
831 }
832#endif
833 ldns_rr_list_free(todo_nsec3_rrsigs);
834 ldns_traverse_postorder(&todo_nsec3_ents,
835 ldns_todo_nsec3_ents_node_free, NULL);
836 ldns_rr_list_free(todo_nsec3s);
837
838 if (my_origin) {
839 ldns_rdf_deep_free(my_origin);
840 }
841 if (my_prev) {
842 ldns_rdf_deep_free(my_prev);
843 }
844 if (newzone) {
845 ldns_dnssec_zone_free(newzone);
846 }
847 return status;
848}
849
852 uint32_t ttl, ldns_rr_class ATTR_UNUSED(c))
853{
854 return ldns_dnssec_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL);
855}
856
857static void
858ldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg) {
859 (void) arg;
861 LDNS_FREE(node);
862}
863
864static void
865ldns_dnssec_name_node_deep_free(ldns_rbnode_t *node, void *arg) {
866 (void) arg;
868 LDNS_FREE(node);
869}
870
871static void
872ldns_hashed_names_node_free(ldns_rbnode_t *node, void *arg) {
873 (void) arg;
874 LDNS_FREE(node);
875}
876
877void
879{
880 if (zone) {
881 if (zone->hashed_names) {
883 ldns_hashed_names_node_free, NULL);
884 LDNS_FREE(zone->hashed_names);
885 }
886 if (zone->names) {
887 /* destroy all name structures within the tree */
889 ldns_dnssec_name_node_free,
890 NULL);
891 LDNS_FREE(zone->names);
892 }
893 LDNS_FREE(zone);
894 }
895}
896
897void
899{
900 if (zone) {
901 if (zone->hashed_names) {
903 ldns_hashed_names_node_free, NULL);
904 LDNS_FREE(zone->hashed_names);
905 }
906 if (zone->names) {
907 /* destroy all name structures within the tree */
909 ldns_dnssec_name_node_deep_free,
910 NULL);
911 LDNS_FREE(zone->names);
912 }
913 LDNS_FREE(zone);
914 }
915}
916
917/* use for dname comparison in tree */
918int
919ldns_dname_compare_v(const void *a, const void *b) {
920 return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b);
921}
922
923static void
924ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone,
925 ldns_dnssec_name* name, ldns_rr* nsec3rr);
926
927static void
928ldns_dnssec_zone_hashed_names_from_nsec3(
929 ldns_dnssec_zone* zone, ldns_rr* nsec3rr)
930{
931 ldns_rbnode_t* current_node;
932 ldns_dnssec_name* current_name;
933
934 assert(zone != NULL);
935 assert(nsec3rr != NULL);
936
937 if (zone->hashed_names) {
939 ldns_hashed_names_node_free, NULL);
940 LDNS_FREE(zone->hashed_names);
941 }
942 zone->_nsec3params = nsec3rr;
943
944 /* So this is a NSEC3 zone.
945 * Calculate hashes for all names already in the zone
946 */
948 if (zone->hashed_names == NULL) {
949 return;
950 }
951 for ( current_node = ldns_rbtree_first(zone->names)
952 ; current_node != LDNS_RBTREE_NULL
953 ; current_node = ldns_rbtree_next(current_node)
954 ) {
955 current_name = (ldns_dnssec_name *) current_node->data;
956 ldns_dnssec_name_make_hashed_name(zone, current_name, nsec3rr);
957
958 }
959}
960
961static void
962ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone,
963 ldns_dnssec_name* name, ldns_rr* nsec3rr)
964{
965 ldns_rbnode_t* new_node;
966
967 assert(name != NULL);
968 if (! zone->_nsec3params) {
969 if (! nsec3rr) {
970 return;
971 }
972 ldns_dnssec_zone_hashed_names_from_nsec3(zone, nsec3rr);
973
974 } else if (! nsec3rr) {
975 nsec3rr = zone->_nsec3params;
976 }
977 name->hashed_name = ldns_nsec3_hash_name_frm_nsec3(nsec3rr, name->name);
978
979 /* Also store in zone->hashed_names */
980 if ((new_node = LDNS_MALLOC(ldns_rbnode_t))) {
981
982 new_node->key = name->hashed_name;
983 new_node->data = name;
984
985 if (ldns_rbtree_insert(zone->hashed_names, new_node) == NULL) {
986
987 LDNS_FREE(new_node);
988 }
989 }
990}
991
992
993static ldns_rbnode_t *
994ldns_dnssec_zone_find_nsec3_original(ldns_dnssec_zone *zone, ldns_rr *rr) {
995 ldns_rdf *hashed_name;
996 ldns_rbnode_t *to_return;
997
998 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 && ! zone->_nsec3params){
999
1000 ldns_dnssec_zone_hashed_names_from_nsec3(zone, rr);
1001 }
1002 if (zone->hashed_names == NULL) {
1003 return NULL;
1004 }
1005 hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0);
1006 if (hashed_name == NULL) {
1007 return NULL;
1008 }
1009 to_return = ldns_rbtree_search(zone->hashed_names, hashed_name);
1010 ldns_rdf_deep_free(hashed_name);
1011 return to_return;
1012}
1013
1016{
1017 ldns_status result = LDNS_STATUS_OK;
1018 ldns_dnssec_name *cur_name;
1019 ldns_rbnode_t *cur_node;
1020 ldns_rr_type type_covered = 0;
1021
1022 if (!zone || !rr) {
1023 return LDNS_STATUS_ERR;
1024 }
1025
1026 if (!zone->names) {
1028 if(!zone->names) return LDNS_STATUS_MEM_ERR;
1029 }
1030
1031 /* we need the original of the hashed name if this is
1032 an NSEC3, or an RRSIG that covers an NSEC3 */
1034 type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
1035 }
1037 type_covered == LDNS_RR_TYPE_NSEC3) {
1038 cur_node = ldns_dnssec_zone_find_nsec3_original(zone, rr);
1039 if (!cur_node) {
1041 }
1042 } else {
1043 cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr));
1044 }
1045 if (!cur_node) {
1046 /* add */
1047 cur_name = ldns_dnssec_name_new_frm_rr(rr);
1048 if(!cur_name) return LDNS_STATUS_MEM_ERR;
1049 cur_node = LDNS_MALLOC(ldns_rbnode_t);
1050 if(!cur_node) {
1051 ldns_dnssec_name_free(cur_name);
1052 return LDNS_STATUS_MEM_ERR;
1053 }
1054 cur_node->key = ldns_rr_owner(rr);
1055 cur_node->data = cur_name;
1056 (void)ldns_rbtree_insert(zone->names, cur_node);
1057 ldns_dnssec_name_make_hashed_name(zone, cur_name, NULL);
1058 } else {
1059 cur_name = (ldns_dnssec_name *) cur_node->data;
1060 result = ldns_dnssec_name_add_rr(cur_name, rr);
1061 }
1063 zone->soa = cur_name;
1064 }
1065 return result;
1066}
1067
1068void
1070 const ldns_rbtree_t *tree,
1071 bool print_soa)
1072{
1073 ldns_rbnode_t *node;
1074 ldns_dnssec_name *name;
1075
1076 node = ldns_rbtree_first(tree);
1077 while (node != LDNS_RBTREE_NULL) {
1078 name = (ldns_dnssec_name *) node->data;
1079 ldns_dnssec_name_print_soa_fmt(out, fmt, name, print_soa);
1080 if ((fmt->flags & LDNS_COMMENT_LAYOUT))
1081 fprintf(out, ";\n");
1082 node = ldns_rbtree_next(node);
1083 }
1084}
1085
1086void
1087ldns_dnssec_zone_names_print(FILE *out, const ldns_rbtree_t *tree, bool print_soa)
1088{
1090 tree, print_soa);
1091}
1092
1093void
1095 const ldns_dnssec_zone *zone)
1096{
1097 if (zone) {
1098 if (zone->soa) {
1099 if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
1100 fprintf(out, ";; Zone: ");
1102 zone->soa));
1103 fprintf(out, "\n;\n");
1104 }
1107 zone->soa,
1109 false);
1110 if ((fmt->flags & LDNS_COMMENT_LAYOUT))
1111 fprintf(out, ";\n");
1112 }
1113
1114 if (zone->names) {
1116 zone->names, false);
1117 }
1118 }
1119}
1120
1121void
1126
1127static ldns_status
1128ldns_dnssec_zone_add_empty_nonterminals_nsec3(
1129 ldns_dnssec_zone *zone, ldns_rbtree_t *nsec3s)
1130{
1131 ldns_dnssec_name *new_name;
1132 ldns_rdf *cur_name;
1133 ldns_rdf *next_name;
1134 ldns_rbnode_t *cur_node, *next_node, *new_node;
1135
1136 /* for the detection */
1137 uint16_t i, cur_label_count, next_label_count;
1138 uint16_t soa_label_count = 0;
1139 ldns_rdf *l1, *l2;
1140 int lpos;
1141
1142 if (!zone) {
1143 return LDNS_STATUS_ERR;
1144 }
1145 if (zone->soa && zone->soa->name) {
1146 soa_label_count = ldns_dname_label_count(zone->soa->name);
1147 }
1148
1149 cur_node = ldns_rbtree_first(zone->names);
1150 while (cur_node != LDNS_RBTREE_NULL) {
1151 next_node = ldns_rbtree_next(cur_node);
1152
1153 /* skip glue */
1154 while (next_node != LDNS_RBTREE_NULL &&
1155 next_node->data &&
1156 ((ldns_dnssec_name *)next_node->data)->is_glue
1157 ) {
1158 next_node = ldns_rbtree_next(next_node);
1159 }
1160
1161 if (next_node == LDNS_RBTREE_NULL) {
1162 next_node = ldns_rbtree_first(zone->names);
1163 }
1164 if (! cur_node->data || ! next_node->data) {
1165 return LDNS_STATUS_ERR;
1166 }
1167 cur_name = ((ldns_dnssec_name *)cur_node->data)->name;
1168 next_name = ((ldns_dnssec_name *)next_node->data)->name;
1169 cur_label_count = ldns_dname_label_count(cur_name);
1170 next_label_count = ldns_dname_label_count(next_name);
1171
1172 /* Since the names are in canonical order, we can
1173 * recognize empty non-terminals by their labels;
1174 * every label after the first one on the next owner
1175 * name is a non-terminal if it either does not exist
1176 * in the current name or is different from the same
1177 * label in the current name (counting from the end)
1178 */
1179 for (i = 1; i < next_label_count - soa_label_count; i++) {
1180 lpos = (int)cur_label_count - (int)next_label_count + (int)i;
1181 if (lpos >= 0) {
1182 l1 = ldns_dname_clone_from(cur_name, (uint8_t)lpos);
1183 } else {
1184 l1 = NULL;
1185 }
1186 l2 = ldns_dname_clone_from(next_name, i);
1187
1188 if (!l1 || ldns_dname_compare(l1, l2) != 0) {
1189 /* We have an empty nonterminal, add it to the
1190 * tree
1191 */
1192 ldns_rbnode_t *node = NULL;
1193 ldns_rdf *ent_name;
1194
1195 if (!(ent_name = ldns_dname_clone_from(
1196 next_name, i))) {
1197
1200 return LDNS_STATUS_MEM_ERR;
1201 }
1202
1203 if (nsec3s && zone->_nsec3params) {
1204 ldns_rdf *ent_hashed_name;
1205
1206 if (!(ent_hashed_name =
1208 zone->_nsec3params,
1209 ent_name))) {
1212 ldns_rdf_deep_free(ent_name);
1213 return LDNS_STATUS_MEM_ERR;
1214 }
1215 node = ldns_rbtree_search(nsec3s,
1216 ent_hashed_name);
1217 ldns_rdf_deep_free(ent_hashed_name);
1218 if (!node) {
1221 ldns_rdf_deep_free(ent_name);
1222 continue;
1223 }
1224 }
1225 new_name = ldns_dnssec_name_new();
1226 if (!new_name) {
1229 ldns_rdf_deep_free(ent_name);
1230 return LDNS_STATUS_MEM_ERR;
1231 }
1232 new_name->name = ent_name;
1233 new_name->name_alloced = true;
1234 new_node = LDNS_MALLOC(ldns_rbnode_t);
1235 if (!new_node) {
1238 ldns_dnssec_name_free(new_name);
1239 return LDNS_STATUS_MEM_ERR;
1240 }
1241 new_node->key = new_name->name;
1242 new_node->data = new_name;
1243 (void)ldns_rbtree_insert(zone->names, new_node);
1244 ldns_dnssec_name_make_hashed_name(
1245 zone, new_name, NULL);
1246 if (node)
1247 (void) ldns_dnssec_zone_add_rr(zone,
1248 (ldns_rr *)node->data);
1249 }
1252 }
1253
1254 /* we might have inserted a new node after
1255 * the current one so we can't just use next()
1256 */
1257 if (next_node != ldns_rbtree_first(zone->names)) {
1258 cur_node = next_node;
1259 } else {
1260 cur_node = LDNS_RBTREE_NULL;
1261 }
1262 }
1263 return LDNS_STATUS_OK;
1264}
1265
1268{
1269 return ldns_dnssec_zone_add_empty_nonterminals_nsec3(zone, NULL);
1270}
1271
1272bool
1274{
1275 ldns_rr* nsec3;
1276 ldns_rbnode_t* node;
1277
1279 node = ldns_rbtree_first(zone->names);
1280 while (node != LDNS_RBTREE_NULL) {
1281 nsec3 = ((ldns_dnssec_name*)node->data)->nsec;
1282 if (nsec3 &&ldns_rr_get_type(nsec3)
1283 == LDNS_RR_TYPE_NSEC3 &&
1284 ldns_nsec3_optout(nsec3)) {
1285 return true;
1286 }
1287 node = ldns_rbtree_next(node);
1288 }
1289 }
1290 return false;
1291}
1292
1293/*
1294 * Stuff for calculating and verifying zone digests
1295 */
1305
1319
1320INLINE void
1321dnssec_zone_rr_iter_set_state_for_next_name(dnssec_zone_rr_iter *i)
1322{
1323 /* Make sure the i->name is "in zone" (i.e. below the apex) */
1324 if (i->apex_name) {
1325 ldns_rdf *name = (ldns_rdf *)i->node->key;
1326
1327 while (i->name && name != i->apex_name /* not apex */
1328
1329 && ( ldns_dname_label_count(name) != i->apex_labs
1330 || ldns_dname_compare(name, i->apex_name)) /* not apex */
1331
1332 && !ldns_dname_is_subdomain(name, i->apex_name) /* no sub */) {
1333
1334 /* next name */
1335 i->node = ldns_rbtree_next(i->node);
1336 if (i->node == LDNS_RBTREE_NULL)
1337 i->name = NULL;
1338 else {
1339 i->name = (ldns_dnssec_name *)i->node->data;
1340 name = (ldns_rdf *)i->node->key;
1341 }
1342 }
1343 }
1344 /* determine state */
1345 if (!i->name) {
1346 if (!i->nsec3_name)
1348 else {
1351 }
1352 } else if (!i->nsec3_name) {
1353 i->rrsets = i->name->rrsets;
1355
1357 , (ldns_rdf *)i->node->key) < 0) {
1360 } else {
1361 i->rrsets = i->name->rrsets;
1363 }
1364}
1365
1407static ldns_rr *
1408dnssec_zone_rr_iter_next(dnssec_zone_rr_iter *i)
1409{
1410 ldns_rr *nsec3;
1411
1412 for (;;) {
1413 if (i->rrs) {
1414 ldns_rr *rr = i->rrs->rr;
1415 i->rrs = i->rrs->next;
1416 return rr;
1417 }
1418 switch (i->state) {
1420 if (i->rrsets
1421 && i->rrsets->type < LDNS_RR_TYPE_RRSIG) {
1422
1423 i->rrs = i->rrsets->rrs;
1424 i->rrsets = i->rrsets->next;
1425 break;
1426 }
1427 i->rrsets4rrsigs = i->name->rrsets;
1428 if (i->name->nsec && ldns_rr_get_type(i->name->nsec)
1429 == LDNS_RR_TYPE_NSEC) {
1430
1432 break;
1433 }
1435 /* fallthrough */
1436
1438 if (i->rrsets4rrsigs) {
1439 i->rrs = i->rrsets4rrsigs->signatures;
1441 break;
1442 }
1444 /* fallthrough */
1445
1447 if (i->rrsets) {
1448 i->rrs = i->rrsets->rrs;
1449 i->rrsets = i->rrsets->next;
1450 break;
1451 }
1452 /* next name */
1453 i->node = ldns_rbtree_next(i->node);
1454 i->name = i->node == LDNS_RBTREE_NULL ? NULL
1455 : (ldns_dnssec_name *)i->node->data;
1456
1457 dnssec_zone_rr_iter_set_state_for_next_name(i);
1458 break;
1459
1461 if (i->rrsets4rrsigs
1463
1464 i->rrs = i->rrsets4rrsigs->signatures;
1466 break;
1467 }
1469 i->rrs = i->name->nsec_signatures;
1470 break;
1471
1473 if (i->rrsets4rrsigs) {
1474 i->rrs = i->rrsets4rrsigs->signatures;
1476 break;
1477 }
1479 return i->name->nsec;
1480
1482 nsec3 = i->nsec3_name->nsec;
1483
1484 /* next nsec3 */
1485 do {
1486 i->nsec3_node
1488 i->nsec3_name
1489 = i->nsec3_node == LDNS_RBTREE_NULL ? NULL
1491
1492 /* names for glue can be in the hashed_names
1493 * tree, but will not have a NSEC3
1494 */
1495 } while (i->nsec3_name && !i->nsec3_name->nsec);
1496
1497 dnssec_zone_rr_iter_set_state_for_next_name(i);
1498 return nsec3;
1499
1501 return NULL;
1502 }
1503 }
1504}
1505
1506static ldns_rr *
1507dnssec_zone_rr_iter_first(dnssec_zone_rr_iter *i, ldns_dnssec_zone *zone)
1508{
1509 if (!i || !zone)
1510 return NULL;
1511
1512 memset(i, 0, sizeof(*i));
1513 i->zone = zone;
1514 if (zone->soa && zone->soa->name) {
1515 i->apex_name = zone->soa->name;
1517 } else
1518 i->apex_name = NULL;
1519
1520
1521 i->node = ldns_rbtree_first(zone->names);
1522 i->name = i->node == LDNS_RBTREE_NULL ? NULL
1523 : (ldns_dnssec_name *)i->node->data;
1524
1525 if (zone->hashed_names) {
1527 i->nsec3_name = i->nsec3_node == LDNS_RBTREE_NULL ? NULL
1529 /* While there is no NSEC3 RR present at this hashed name,
1530 * skip to the next hashed name.
1531 */
1532 while (i->nsec3_name && !i->nsec3_name->nsec) {
1533 /* next nsec3 */
1535 i->nsec3_name = i->nsec3_node == LDNS_RBTREE_NULL ? NULL
1537 }
1538 }
1539 dnssec_zone_rr_iter_set_state_for_next_name(i);
1540 return dnssec_zone_rr_iter_next(i);
1541}
1542
1549
1557
1567
1568INLINE bool zone_digester_set(zone_digester *zd)
1569{ return zd && (zd->simple_sha384 || zd->simple_sha512); }
1570
1571INLINE void zone_digester_init(zone_digester *zd)
1572{ memset(zd, 0, sizeof(*zd)); }
1573
1574static ldns_status
1575zone_digester_add(zone_digester *zd, zonemd_scheme scheme, zonemd_hash hash)
1576{
1577 if (!zd)
1578 return LDNS_STATUS_NULL;
1579
1580 switch (scheme) {
1582 switch (hash) {
1583 case ZONEMD_HASH_SHA384:
1584 if (zd->double_sha384)
1586
1587 else if (zd->simple_sha384) {
1588 zd->simple_sha384 = 0;
1589 zd->double_sha384 = 1;
1591 }
1593 zd->simple_sha384 = 1;
1594 break;
1595
1596 case ZONEMD_HASH_SHA512:
1597 if (zd->double_sha512)
1599
1600 else if (zd->simple_sha512) {
1601 zd->simple_sha512 = 0;
1602 zd->double_sha512 = 1;
1604 }
1606 zd->simple_sha512 = 1;
1607 break;
1608 default:
1610 }
1611 break;
1612 default:
1614 }
1615 return LDNS_STATUS_OK;
1616}
1617
1618static ldns_status
1619zone_digester_update(zone_digester *zd, ldns_rr *rr)
1620{
1621 uint8_t data[65536];
1622 ldns_buffer buf;
1623 ldns_status st;
1624
1625 buf._data = data;
1626 buf._position = 0;
1627 buf._limit = sizeof(data);
1628 buf._capacity = sizeof(data);
1629 buf._fixed = 1;
1630 buf._status = LDNS_STATUS_OK;
1631
1633 return st;
1634
1635 if (zd->simple_sha384)
1636 ldns_sha384_update(&zd->sha384_CTX, data, buf._position);
1637
1638 if (zd->simple_sha512)
1639 ldns_sha512_update(&zd->sha512_CTX, data, buf._position);
1640
1641 return LDNS_STATUS_OK;
1642}
1643
1645new_zonemd(ldns_rr *soa, zonemd_hash hash)
1646{
1647 ldns_rr *rr = NULL;
1648 uint8_t *data = NULL;
1649 ldns_rdf *rdf;
1650 size_t md_len = hash == ZONEMD_HASH_SHA384
1653
1655 return NULL;
1656
1657 if (!(rdf = ldns_rdf_clone(ldns_rr_owner(soa))))
1658 goto error;
1659
1660 ldns_rr_set_owner(rr, rdf);
1662 ldns_rr_set_ttl(rr, ldns_rr_ttl(soa));
1663
1664 if (!(rdf = ldns_rdf_clone(ldns_rr_rdf(soa, 2))))
1665 goto error;
1666 ldns_rr_set_rdf(rr, rdf, 0);
1667
1669 goto error;
1670 ldns_rr_set_rdf(rr, rdf, 1);
1671
1672 if (!(rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, hash)))
1673 goto error;
1674 ldns_rr_set_rdf(rr, rdf, 2);
1675
1676 if (!(data = LDNS_XMALLOC(uint8_t, md_len)))
1677 goto error;
1678
1679 if (!(rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, md_len, data)))
1680 goto error;
1681 ldns_rr_set_rdf(rr, rdf, 3);
1682
1683 return rr;
1684error:
1685 if (data)
1686 LDNS_FREE(data);
1687 ldns_rr_free(rr);
1688 return NULL;
1689}
1690
1691static ldns_rr_list *
1692zone_digester_export(
1693 zone_digester *zd, ldns_rr *soa, ldns_status *ret_st)
1694{
1696 ldns_rr_list *rr_list = NULL;
1697 ldns_rr *sha384 = NULL;
1698 ldns_rr *sha512 = NULL;
1699
1700 if (!zd || !soa)
1701 st = LDNS_STATUS_NULL;
1702
1703 else if (ldns_rr_get_type(soa) != LDNS_RR_TYPE_SOA
1704 || ldns_rr_rd_count(soa) < 3)
1706
1707 else if (!(rr_list = ldns_rr_list_new()))
1709
1710 else if (zd->simple_sha384
1711 && !(sha384 = new_zonemd(soa, ZONEMD_HASH_SHA384)))
1713
1714 else if (zd->simple_sha512
1715 && !(sha512 = new_zonemd(soa, ZONEMD_HASH_SHA512)))
1717
1718 else if (zd->simple_sha384
1719 && !ldns_rr_list_push_rr(rr_list, sha384))
1721
1722 else if (zd->simple_sha512
1723 && !ldns_rr_list_push_rr(rr_list, sha512)) {
1724 if (zd->simple_sha384)
1725 sha384 = NULL; /* deleted by ldns_rr_list_deep_free */
1727
1728 } else {
1729 if (sha384)
1731 , &zd->sha384_CTX);
1732 if (sha512)
1734 , &zd->sha512_CTX);
1735 return rr_list;
1736 }
1737 if (ret_st)
1738 *ret_st = st;
1739 if (sha384)
1740 ldns_rr_free(sha384);
1741 if (sha512)
1742 ldns_rr_free(sha512);
1743 if (rr_list)
1744 ldns_rr_list_deep_free(rr_list);
1745 return NULL;
1746}
1747
1748static ldns_status
1749ldns_digest_zone(ldns_dnssec_zone *zone, zone_digester *zd)
1750{
1752 dnssec_zone_rr_iter rr_iter;
1753 ldns_rr *rr;
1754 ldns_rdf *apex_name; /* name of zone apex */
1755
1756 if (!zone || !zd || !zone->soa || !zone->soa->name)
1757 return LDNS_STATUS_NULL;
1758
1759 apex_name = zone->soa->name;
1760 for ( rr = dnssec_zone_rr_iter_first(&rr_iter, zone)
1761 ; rr && !st
1762 ; rr = dnssec_zone_rr_iter_next(&rr_iter)) {
1763 /* Skip apex ZONEMD RRs */
1765 && !ldns_dname_compare(ldns_rr_owner(rr), apex_name))
1766 continue;
1767 /* Skip RRSIGs for apex ZONEMD RRs */
1771 && !ldns_dname_compare(ldns_rr_owner(rr), apex_name))
1772 continue;
1773 st = zone_digester_update(zd, rr);
1774 }
1775 return st;
1776}
1777
1780{
1781 ldns_dnssec_rrsets *zonemd, *soa;
1782 zone_digester zd;
1783 ldns_dnssec_rrs *rrs;
1784 ldns_rr *soa_rr;
1785 ldns_status st;
1788 size_t valid_zonemds;
1789
1790 if (!zone)
1791 return LDNS_STATUS_NULL;
1792
1794 zone, zone->soa->name, LDNS_RR_TYPE_ZONEMD);
1795 if (!zonemd) {
1796 ldns_rbnode_t *nsec3_node;
1797
1798 /* we need proof of non-existence for ZONEMD at the apex */
1799 if (zone->soa->nsec) {
1801 zone->soa->nsec),
1803 return LDNS_STATUS_NO_ZONEMD;
1804
1805 } else if (!zone->soa->hashed_name || !zone->hashed_names)
1806 return LDNS_STATUS_NO_ZONEMD;
1807
1808 else if (LDNS_RBTREE_NULL ==
1809 (nsec3_node = ldns_rbtree_search( zone->hashed_names
1810 , zone->soa->hashed_name)))
1811 return LDNS_STATUS_NO_ZONEMD;
1812 else {
1813 ldns_dnssec_name *nsec3
1814 = (ldns_dnssec_name *)nsec3_node->data;
1816 nsec3->nsec),
1818 return LDNS_STATUS_NO_ZONEMD;
1819 }
1820 /* ZONEMD at apex does really not exist */
1821 return LDNS_STATUS_OK;
1822 }
1824 zone, zone->soa->name, LDNS_RR_TYPE_SOA);
1825 if (!soa || !soa->rrs || !soa->rrs->rr)
1827
1828 soa_rr = soa->rrs->rr;
1829 if (ldns_rr_get_type(soa_rr) != LDNS_RR_TYPE_SOA
1830 || ldns_rr_rd_count(soa_rr) < 3)
1832
1833 zone_digester_init(&zd);
1834 for (rrs = zonemd->rrs; rrs; rrs = rrs->next) {
1835 if (!rrs->rr
1837 || ldns_rr_rd_count(rrs->rr) < 4)
1838 continue;
1839
1840 /* serial should match SOA's serial */
1841 if (ldns_rdf2native_int32(ldns_rr_rdf(soa_rr, 2))
1843 continue;
1844
1845 /* Add (scheme, hash) to digester */
1846 zone_digester_add(&zd,
1849 }
1850 if (!zone_digester_set(&zd))
1852
1853 if ((st = ldns_digest_zone(zone, &zd)))
1854 return st;
1855
1856 if (zd.simple_sha384)
1858 if (zd.simple_sha512)
1860
1861 valid_zonemds = 0;
1862 for (rrs = zonemd->rrs; rrs; rrs = rrs->next) {
1863 if (!rrs->rr
1865 || ldns_rr_rd_count(rrs->rr) < 4)
1866 continue;
1867
1868 /* serial should match SOA's serial */
1869 if (ldns_rdf2native_int32(ldns_rr_rdf(soa_rr, 2))
1871 continue;
1872
1875 continue;
1876
1880 == ldns_rdf_size(ldns_rr_rdf(rrs->rr, 3))
1881 && memcmp( simple_sha384
1882 , ldns_rdf_data(ldns_rr_rdf(rrs->rr, 3))
1884
1885 valid_zonemds += 1;
1886
1890 == ldns_rdf_size(ldns_rr_rdf(rrs->rr, 3))
1891 && memcmp( simple_sha512
1892 , ldns_rdf_data(ldns_rr_rdf(rrs->rr, 3))
1894
1895 valid_zonemds += 1;
1896 }
1897 return valid_zonemds ? LDNS_STATUS_OK : LDNS_STATUS_NO_VALID_ZONEMD;
1898}
1899
1900#ifdef HAVE_SSL
1901static ldns_status
1902rr_list2dnssec_rrs(ldns_rr_list *rr_list, ldns_dnssec_rrs **rrs,
1903 ldns_rr_list *new_rrs)
1904{
1905 ldns_rr *rr = NULL;
1906
1907 if (!rr_list || !rrs)
1908 return LDNS_STATUS_NULL;
1909
1910 if (ldns_rr_list_rr_count(rr_list) == 0)
1911 return LDNS_STATUS_OK;
1912
1913 if (!*rrs) {
1914 if (!(*rrs = ldns_dnssec_rrs_new()))
1915 return LDNS_STATUS_MEM_ERR;
1916 (*rrs)->rr = ldns_rr_list_pop_rr(rr_list);
1917 if (new_rrs)
1918 ldns_rr_list_push_rr(new_rrs, (*rrs)->rr);
1919 }
1920 while ((rr = ldns_rr_list_pop_rr(rr_list))) {
1921 ldns_status st;
1922
1923 if ((st = ldns_dnssec_rrs_add_rr(*rrs, rr))) {
1924 ldns_rr_list_push_rr(rr_list, rr);
1925 return st;
1926 } else if (new_rrs)
1927 ldns_rr_list_push_rr(new_rrs, rr);
1928 }
1929 return LDNS_STATUS_OK;
1930}
1931
1932
1935 ldns_rr_list *new_rrs, ldns_key_list *key_list, int signflags);
1938 ldns_rr_list *new_rrs, ldns_key_list *key_list, int signflags)
1939{
1941 zone_digester zd;
1942 ldns_rr_list *zonemd_rr_list = NULL;
1943 ldns_rr_list *zonemd_rrsigs = NULL;
1944 ldns_dnssec_rrsets *soa_rrset;
1945 ldns_rr *soa_rr = NULL;
1946 ldns_dnssec_rrsets **rrset_ref;
1947 ldns_dnssec_rrsets *zonemd_rrset;
1948
1949 zone_digester_init(&zd);
1951 zone_digester_add(&zd, ZONEMD_SCHEME_SIMPLE
1953
1955 zone_digester_add(&zd, ZONEMD_SCHEME_SIMPLE
1957
1958 if ((st = ldns_digest_zone(zone, &zd)))
1959 return st;
1960
1961 soa_rrset = ldns_dnssec_zone_find_rrset(
1962 zone, zone->soa->name, LDNS_RR_TYPE_SOA);
1963 if (!soa_rrset || !soa_rrset->rrs || !soa_rrset->rrs->rr)
1965 soa_rr = soa_rrset->rrs->rr;
1966
1967 if (!(zonemd_rr_list = zone_digester_export(&zd, soa_rr, &st)))
1968 return st;
1969
1970 /* - replace or add ZONEMD rrset */
1971 rrset_ref = &zone->soa->rrsets; /* scan rrsets at apex */
1972 while (*rrset_ref && (*rrset_ref)->type < LDNS_RR_TYPE_ZONEMD)
1973 rrset_ref = &(*rrset_ref)->next;
1974 if (*rrset_ref && (*rrset_ref)->type == LDNS_RR_TYPE_ZONEMD) {
1975 /* reuse zonemd rrset */
1976 zonemd_rrset = *rrset_ref;
1977 ldns_dnssec_rrs_free(zonemd_rrset->rrs);
1978 zonemd_rrset->rrs = NULL;
1979 ldns_dnssec_rrs_free(zonemd_rrset->signatures);
1980 zonemd_rrset->signatures = NULL;
1981 } else {
1982 /* insert zonemd rrset */
1983 zonemd_rrset = ldns_dnssec_rrsets_new();
1984 if (!zonemd_rrset) {
1985 ldns_rr_list_deep_free(zonemd_rr_list);
1986 return LDNS_STATUS_MEM_ERR;
1987 }
1988 zonemd_rrset->type = LDNS_RR_TYPE_ZONEMD;
1989 zonemd_rrset->next = *rrset_ref;
1990 *rrset_ref = zonemd_rrset;
1991 }
1992 if ((zonemd_rrsigs = ldns_sign_public(zonemd_rr_list, key_list)))
1993 st = rr_list2dnssec_rrs( zonemd_rrsigs
1994 , &zonemd_rrset->signatures, new_rrs);
1995 if (!st)
1996 st = rr_list2dnssec_rrs( zonemd_rr_list
1997 , &zonemd_rrset->rrs, new_rrs);
1998 ldns_rr_list_deep_free(zonemd_rr_list);
1999 ldns_rr_list_deep_free(zonemd_rrsigs);
2000 return st;
2001}
2002
2003#endif /* HAVE_SSL */
2004
#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:1395
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:1370
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:1288
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:81
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:98
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_EQUAL_RR
Definition error.h:147
@ 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:149
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:3454
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:3466
#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:72
@ 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:1009
uint32_t ldns_rr_ttl(const ldns_rr *rr)
returns the ttl of an rr structure.
Definition rr.c:929
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:2855
void ldns_rr_list_deep_free(ldns_rr_list *rr_list)
frees an rr_list structure and all rrs contained therein.
Definition rr.c:1018
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:802
ldns_rr_list * ldns_rr_list_new(void)
creates a new rr_list structure.
Definition rr.c:998
ldns_rr * ldns_rr_list_pop_rr(ldns_rr_list *rr_list)
pops the last rr from an rrlist.
Definition rr.c:1175
enum ldns_enum_rr_type ldns_rr_type
Definition rr.h:260
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:1130
size_t ldns_rr_rd_count(const ldns_rr *rr)
returns the rd_count of an rr structure.
Definition rr.c:935
ldns_rdf * ldns_rr_rdf(const ldns_rr *rr, size_t nr)
returns the rdata field member counter.
Definition rr.c:907
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:955
ldns_rr_type ldns_rr_get_type(const ldns_rr *rr)
returns the type of the rr.
Definition rr.c:941
void ldns_rr_set_ttl(ldns_rr *rr, uint32_t ttl)
sets the ttl in the rr structure.
Definition rr.c:814
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:838
ldns_rr_class ldns_rr_get_class(const ldns_rr *rr)
returns the class of the rr.
Definition rr.c:947
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:988
void ldns_rr_set_class(ldns_rr *rr, ldns_rr_class rr_class)
sets the class in the rr.
Definition rr.c:832
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:794
ldns_rdf * ldns_rr_owner(const ldns_rr *rr)
returns the owner name of an rr structure.
Definition rr.c:917
int ldns_rr_compare(const ldns_rr *rr1, const ldns_rr *rr2)
compares two rrs.
Definition rr.c:1676
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:819
void ldns_sha384_init(ldns_sha384_CTX *)
Definition sha2.c:952
void ldns_sha512_init(ldns_sha512_CTX *)
Definition sha2.c:635
#define LDNS_SHA512_DIGEST_LENGTH
Definition sha2.h:69
void ldns_sha512_final(uint8_t[64], ldns_sha512_CTX *)
Definition sha2.c:912
#define LDNS_SHA384_DIGEST_LENGTH
Definition sha2.h:66
void ldns_sha384_update(ldns_sha384_CTX *, const uint8_t *, size_t)
Definition sha2.c:961
void ldns_sha384_final(uint8_t[48], ldns_sha384_CTX *)
Definition sha2.c:965
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:203
List or Set of Resource Records.
Definition rr.h:355
Resource Record.
Definition rr.h:327
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.