]> git.ipfire.org Git - thirdparty/ldns.git/commitdiff
merge branch zone_sign_rewrite (r2504-2556) back into trunk
authorJelte Jansen <jelte@NLnetLabs.nl>
Mon, 28 Jan 2008 14:58:04 +0000 (14:58 +0000)
committerJelte Jansen <jelte@NLnetLabs.nl>
Mon, 28 Jan 2008 14:58:04 +0000 (14:58 +0000)
17 files changed:
Makefile.in
dname.c
dnssec.c
dnssec_zone.c [new file with mode: 0644]
examples/ldns-compare-zones.c
examples/ldns-signzone.c
keys.c
ldns/dnssec.h
ldns/dnssec_zone.h [new file with mode: 0644]
ldns/error.h
ldns/keys.h
ldns/ldns.h
ldns/rbtree.h [new file with mode: 0644]
rbtree.c [new file with mode: 0644]
rdata.c
str2host.c
zone.c

index 9b3a090f2820214d905f476623de28ac217acf61..7f989100787ba871d858b06b10f817b9a6ea0bb6 100644 (file)
@@ -37,7 +37,8 @@ INSTALL = $(srcdir)/install-sh
 LIBDNS_SOURCES =       rdata.c util.c rr.c packet.c wire2host.c \
                        host2str.c buffer.c str2host.c tsig.c resolver.c \
                        net.c host2wire.c dname.c dnssec.c keys.c \
-                       higher.c rr_functions.c parse.c update.c error.c zone.c
+                       higher.c rr_functions.c parse.c update.c error.c \
+                       zone.c dnssec_zone.c rbtree.c
 LIBDNS_HEADERS =       $(srcdir)/ldns/error.h          \
                        $(srcdir)/ldns/packet.h         \
                        $(srcdir)/ldns/common.h         \
@@ -58,8 +59,10 @@ LIBDNS_HEADERS       =       $(srcdir)/ldns/error.h          \
                        $(srcdir)/ldns/rr_functions.h   \
                        $(srcdir)/ldns/ldns.h           \
                        $(srcdir)/ldns/zone.h           \
-                       $(srcdir)/ldns/update.h                 \
-                       $(srcdir)/ldns/tsig.h
+                       $(srcdir)/ldns/dnssec_zone.h    \
+                       $(srcdir)/ldns/update.h         \
+                       $(srcdir)/ldns/tsig.h           \
+                       $(srcdir)/ldns/rbtree.h
 LIBDNS_OBJECTS =       $(LIBDNS_SOURCES:.c=.o) $(LIBOBJS)
 LIBDNS_LOBJECTS        =       $(LIBDNS_SOURCES:.c=.lo) $(LIBOBJS:.o=.lo)
 
diff --git a/dname.c b/dname.c
index 77b4f33a71b8ca64f32010f63362e15f839e1bbd..3b38910a41c1ab0d3d567b43b7a82ff65502f4f1 100644 (file)
--- a/dname.c
+++ b/dname.c
@@ -427,8 +427,12 @@ ldns_dname_label(const ldns_rdf *rdf, uint8_t labelpos)
        while ((len > 0) && src_pos < s) {
                if (labelcnt == labelpos) {
                        /* found our label */
-                       tmpnew = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, len + 1,
-                                       (ldns_rdf_data(rdf) + src_pos));
+                       tmpnew = LDNS_MALLOC(ldns_rdf);
+                       tmpnew->_type = LDNS_RDF_TYPE_DNAME;
+                       tmpnew->_data = LDNS_XMALLOC(uint8_t, len + 2);
+                       memset(tmpnew->_data, 0, len + 2);
+                       memcpy(tmpnew->_data, ldns_rdf_data(rdf) + src_pos, len + 1);
+                       tmpnew->_size = len + 1;
                        return tmpnew;
                }
                src_pos++;
index fa153374a25765489bc23540f58ba251b9483cbf..baab6be5fd9297caf9def50d34de084a7fdef8e7 100644 (file)
--- a/dnssec.c
+++ b/dnssec.c
@@ -46,7 +46,7 @@ ldns_dnssec_get_rrsig_for_name_and_type(const ldns_rdf *name,
                                               name) == 0 &&
                            ldns_rdf2native_int8(ldns_rr_rrsig_typecovered(candidate)) ==
                            type
-                          ) {
+                           ) {
                                return candidate;
                        }
                }
@@ -72,7 +72,7 @@ ldns_dnssec_get_dnskey_for_rrsig(const ldns_rr *rrsig, const ldns_rr_list *rrs)
                                               ldns_rr_rrsig_signame(rrsig)) == 0 &&
                            ldns_rdf2native_int16(ldns_rr_rrsig_keytag(rrsig)) ==
                            ldns_calc_keytag(candidate)
-                       ) {
+                           ) {
                                return candidate;
                        }
                }
@@ -203,10 +203,10 @@ ldns_dnssec_pkt_get_rrsigs_for_name_and_type(const ldns_pkt *pkt, ldns_rdf *name
        ldns_rdf *rdf_t;
        
        sigs = ldns_pkt_rr_list_by_name_and_type(pkt,
-                                                name,
-                                                LDNS_RR_TYPE_RRSIG,
-                                                LDNS_SECTION_ANY_NOQUESTION
-                                               );
+                                                                        name,
+                                                                        LDNS_RR_TYPE_RRSIG,
+                                                                        LDNS_SECTION_ANY_NOQUESTION
+                                                                        );
 
        t_netorder = htons(type); /* rdf are in network order! */
        rdf_t = ldns_rdf_new(LDNS_RDF_TYPE_TYPE, sizeof(ldns_rr_type), &t_netorder);
@@ -230,7 +230,7 @@ ldns_dnssec_pkt_get_rrsigs_for_type(const ldns_pkt *pkt, ldns_rr_type type)
        sigs = ldns_pkt_rr_list_by_type(pkt,
                                        LDNS_RR_TYPE_RRSIG,
                                        LDNS_SECTION_ANY_NOQUESTION
-                                      );
+                                                         );
 
        t_netorder = htons(type); /* rdf are in network order! */
        rdf_t = ldns_rdf_new(LDNS_RDF_TYPE_TYPE, sizeof(ldns_rr_type), &t_netorder);
@@ -325,7 +325,7 @@ ldns_dnssec_build_data_chain(ldns_resolver *res, uint16_t qflags, const ldns_rr_
        /* normally there will only be 1 signature 'set'
           but there can be more than 1 denial (wildcards)
           so check for NSEC
-        */
+       */
        if (type == LDNS_RR_TYPE_NSEC) {
                /* just throw in all signatures, the tree builder must sort
                   this out */
@@ -367,43 +367,43 @@ ldns_dnssec_build_data_chain(ldns_resolver *res, uint16_t qflags, const ldns_rr_
                        new_chain->parent_type = 0;
                        
                        keys = ldns_pkt_rr_list_by_name_and_type(pkt,
-                                       key_name,
-                                       LDNS_RR_TYPE_DNSKEY,
-                                       LDNS_SECTION_ANY_NOQUESTION
-                                       );
+                                                                                        key_name,
+                                                                                        LDNS_RR_TYPE_DNSKEY,
+                                                                                        LDNS_SECTION_ANY_NOQUESTION
+                                                                                        );
                        if (!keys) {
                                my_pkt = ldns_resolver_query(res, key_name, LDNS_RR_TYPE_DNSKEY, c, qflags);
                                keys = ldns_pkt_rr_list_by_name_and_type(my_pkt,
-                                               key_name,
-                                               LDNS_RR_TYPE_DNSKEY,
-                                               LDNS_SECTION_ANY_NOQUESTION
-                                               );
+                                                                                                key_name,
+                                                                                                LDNS_RR_TYPE_DNSKEY,
+                                                                                                LDNS_SECTION_ANY_NOQUESTION
+                                                                                                );
                                new_chain->parent = ldns_dnssec_build_data_chain(res, qflags, keys, my_pkt, NULL);
                                ldns_pkt_free(my_pkt);
                        } else {
                                new_chain->parent = ldns_dnssec_build_data_chain(res, qflags, keys, pkt, NULL);
                        }
-                        ldns_rr_list_deep_free(keys);
+                       ldns_rr_list_deep_free(keys);
                }
        } else {
                /* 'self-signed', parent is a DS */
                
-/* okay, either we have other keys signing the current one, or the current
- * one should have a DS record in the parent zone.
- * How do we find this out? Try both?
- *
- * request DNSKEYS for current zone, add all signatures to current level
- */
+               /* okay, either we have other keys signing the current one, or the current
               * one should have a DS record in the parent zone.
               * How do we find this out? Try both?
               *
               * request DNSKEYS for current zone, add all signatures to current level
               */
 
 
                new_chain->parent_type = 1;
 
                my_pkt = ldns_resolver_query(res, key_name, LDNS_RR_TYPE_DS, c, qflags);
                dss = ldns_pkt_rr_list_by_name_and_type(my_pkt,
-                                                       key_name,
-                                                       LDNS_RR_TYPE_DS,
-                                                       LDNS_SECTION_ANY_NOQUESTION
-                                                      );
+                                                                               key_name,
+                                                                               LDNS_RR_TYPE_DS,
+                                                                               LDNS_SECTION_ANY_NOQUESTION
+                                                                               );
                if (dss) {
                        new_chain->parent = ldns_dnssec_build_data_chain(res, qflags, dss, my_pkt, NULL);
                        ldns_rr_list_deep_free(dss);
@@ -413,9 +413,9 @@ ldns_dnssec_build_data_chain(ldns_resolver *res, uint16_t qflags, const ldns_rr_
 
                my_pkt = ldns_resolver_query(res, key_name, LDNS_RR_TYPE_DNSKEY, c, qflags);
                signatures2 = ldns_pkt_rr_list_by_name_and_type(my_pkt,
-                                                        key_name,
-                                                        LDNS_RR_TYPE_RRSIG,
-                                                        LDNS_SECTION_ANSWER);
+                                                                                          key_name,
+                                                                                          LDNS_RR_TYPE_RRSIG,
+                                                                                          LDNS_SECTION_ANSWER);
                if (signatures2) {
                        /* TODO: what if there were still sigs there? */
                        new_chain->signatures = signatures2;
@@ -460,12 +460,12 @@ ldns_dnssec_trust_tree_add_parent(ldns_dnssec_trust_tree *tree,
                                   const ldns_status parent_status)
 {
        if (tree && parent && tree->parent_count < LDNS_DNSSEC_TRUST_TREE_MAX_PARENTS) {
-/*
-printf("Add parent for: ");
-ldns_rr_print(stdout, tree->rr);
-printf("parent: ");
-ldns_rr_print(stdout, parent->rr);
-*/
+               /*
+                 printf("Add parent for: ");
+                 ldns_rr_print(stdout, tree->rr);
+                 printf("parent: ");
+                 ldns_rr_print(stdout, parent->rr);
+               */
                tree->parents[tree->parent_count] = (ldns_dnssec_trust_tree *) parent;
                tree->parent_status[tree->parent_count] = parent_status;
                tree->parent_signature[tree->parent_count] = (ldns_rr *) signature;
@@ -523,27 +523,27 @@ ldns_dnssec_trust_tree_print_sm(FILE *out, ldns_dnssec_trust_tree *tree, size_t
        
        if (tree) {
                if (tree->rr) {
-/*
-                       if (extended && tabs > 0) {
-                               print_tabs(out, tabs - 1);
-                               if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_DNSKEY) {
-                                       fprintf(out, "which is signed by:\n");
-                               } else if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_DS) {
-                                       fprintf(out, "which matches:\n");
-                               } else if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NSEC) {
-                                       fprintf(out, "whose existence is denied by:\n");
-                               }
-                       } else {
-*/
-/*
-                               if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NSEC) {
-                                       print_tabs(out, tabs, sibmap, treedepth);
-                                       fprintf(out, "Existence is denied by:\n");
-                               }
-*/
-/*
-                       }
-*/
+                       /*
+                         if (extended && tabs > 0) {
+                         print_tabs(out, tabs - 1);
+                         if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_DNSKEY) {
+                         fprintf(out, "which is signed by:\n");
+                         } else if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_DS) {
+                         fprintf(out, "which matches:\n");
+                         } else if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NSEC) {
+                         fprintf(out, "whose existence is denied by:\n");
+                         }
+                         } else {
+                       */
+                       /*
+                         if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NSEC) {
+                         print_tabs(out, tabs, sibmap, treedepth);
+                         fprintf(out, "Existence is denied by:\n");
+                         }
+                       */
+                       /*
+                         }
+                       */
 
                        print_tabs(out, tabs, sibmap, treedepth);
                        ldns_rdf_print(out, ldns_rr_owner(tree->rr));
@@ -553,7 +553,7 @@ ldns_dnssec_trust_tree_print_sm(FILE *out, ldns_dnssec_trust_tree *tree, size_t
                                fprintf(out, " (%s", descriptor->_name);
                        } else {
                                fprintf(out, " (TYPE%d", 
-                                               ldns_rr_get_type(tree->rr));
+                                          ldns_rr_get_type(tree->rr));
                        }
                        if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_DNSKEY) {
                                fprintf(out, " keytag: %u", ldns_calc_keytag(tree->rr));
@@ -571,11 +571,11 @@ ldns_dnssec_trust_tree_print_sm(FILE *out, ldns_dnssec_trust_tree *tree, size_t
                        
                        fprintf(out, ")\n");
                        for (i = 0; i < tree->parent_count; i++) {
-if (tree->parent_count > 1 && i < tree->parent_count - 1) {
-sibmap[tabs] = 1;
-} else {
-sibmap[tabs] = 0;
-}
+                               if (tree->parent_count > 1 && i < tree->parent_count - 1) {
+                                       sibmap[tabs] = 1;
+                               } else {
+                                       sibmap[tabs] = 0;
+                               }
                                /* only print errors */
                                if (ldns_rr_get_type(tree->parents[i]->rr) == LDNS_RR_TYPE_NSEC) {
                                        if (tree->parent_status[i] == LDNS_STATUS_OK) {
@@ -586,22 +586,22 @@ sibmap[tabs] = 0;
                                                fprintf(out, "Error in denial of existence: %s\n", ldns_get_errorstr_by_id(tree->parent_status[i]));
                                        }
                                } else
-                               if (tree->parent_status[i] != LDNS_STATUS_OK) {
-                                       print_tabs(out, tabs + 1, sibmap, treedepth);
-                                       fprintf(out, "%s:\n", ldns_get_errorstr_by_id(tree->parent_status[i]));
-                                       /*
-                                       print_tabs(out, tabs + 1, sibmap, treedepth);
-                                       */
-                                       ldns_rr_print(out, tree->parent_signature[i]);
-                                       printf("For RRset:\n");
-                                       ldns_rr_list_print(out, tree->rrset);
-                                       printf("With key:\n");
-                                       ldns_rr_print(out, tree->parents[i]->rr);
-                                       /*
-                                       print_tabs(out, tabs + 1, sibmap, treedepth);
-                                       fprintf(out, "from:\n");
-                                       */
-                               }
+                                       if (tree->parent_status[i] != LDNS_STATUS_OK) {
+                                               print_tabs(out, tabs + 1, sibmap, treedepth);
+                                               fprintf(out, "%s:\n", ldns_get_errorstr_by_id(tree->parent_status[i]));
+                                               /*
+                                                 print_tabs(out, tabs + 1, sibmap, treedepth);
+                                               */
+                                               ldns_rr_print(out, tree->parent_signature[i]);
+                                               printf("For RRset:\n");
+                                               ldns_rr_list_print(out, tree->rrset);
+                                               printf("With key:\n");
+                                               ldns_rr_print(out, tree->parents[i]->rr);
+                                               /*
+                                                 print_tabs(out, tabs + 1, sibmap, treedepth);
+                                                 fprintf(out, "from:\n");
+                                               */
+                                       }
                                ldns_dnssec_trust_tree_print_sm(out, tree->parents[i], tabs+1, extended, sibmap, treedepth);
                        }
                } else {
@@ -659,8 +659,8 @@ ldns_dnssec_derive_trust_tree_normal_rrset(ldns_dnssec_trust_tree *new_tree,
                                                while (tmp_rrset &&
                                                       ldns_rr_list_rr_count(cur_rrset) > 0 &&
                                                       ldns_dname_compare(
-                                                      ldns_rr_owner(ldns_rr_list_rr(tmp_rrset, 0)),
-                                                      ldns_rr_owner(cur_sig_rr)) != 0) {
+                                                                                        ldns_rr_owner(ldns_rr_list_rr(tmp_rrset, 0)),
+                                                                                        ldns_rr_owner(cur_sig_rr)) != 0) {
                                                        ldns_rr_list_deep_free(tmp_rrset);
                                                        tmp_rrset = ldns_rr_list_pop_rrset(cur_rrset);
                                                }
@@ -682,7 +682,7 @@ ldns_dnssec_derive_trust_tree_normal_rrset(ldns_dnssec_trust_tree *new_tree,
                        }
                }
        }
      done:
+ done:
        if (tmp_rrset && tmp_rrset != cur_rrset) {
                ldns_rr_list_deep_free(tmp_rrset);
        }
@@ -709,7 +709,7 @@ ldns_dnssec_derive_trust_tree_dnskey_rrset(ldns_dnssec_trust_tree *new_tree,
                if (cur_parent_rr != cur_rr &&
                    ldns_rr_get_type(cur_parent_rr) == LDNS_RR_TYPE_DNSKEY) {
                        if (ldns_calc_keytag(cur_parent_rr) == cur_keytag
-                          ) {
+                           ) {
                                /*cur_parent_tree = ldns_dnssec_derive_trust_tree(data_chain, cur_parent_rr);*/
                                cur_parent_tree = ldns_dnssec_trust_tree_new();
                                cur_parent_tree->rr = cur_parent_rr;
@@ -735,7 +735,7 @@ ldns_dnssec_derive_trust_tree_ds_rrset(ldns_dnssec_trust_tree *new_tree,
        if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_DNSKEY &&
            data_chain->parent &&
            data_chain->parent->rrset
-          ) {
+           ) {
                for (j = 0; j < ldns_rr_list_rr_count(data_chain->parent->rrset); j++) {
                        cur_parent_rr = ldns_rr_list_rr(data_chain->parent->rrset, j);
                        if (ldns_rr_get_type(cur_parent_rr) == LDNS_RR_TYPE_DS) {
@@ -806,69 +806,69 @@ ldns_dnssec_derive_trust_tree(ldns_dnssec_data_chain *data_chain, ldns_rr *rr)
        
                cur_sigs = data_chain->signatures;
 
-                       if (rr) {
-                               cur_rr = rr;
-                       }
+               if (rr) {
+                       cur_rr = rr;
+               }
 
-                       if (!cur_rr && ldns_rr_list_rr_count(cur_rrset) > 0) {
-                               cur_rr = ldns_rr_list_rr(cur_rrset, 0);
-                       }
+               if (!cur_rr && ldns_rr_list_rr_count(cur_rrset) > 0) {
+                       cur_rr = ldns_rr_list_rr(cur_rrset, 0);
+               }
 
-                       if (cur_rr) {
-                               new_tree->rr = cur_rr;
-                               new_tree->rrset = cur_rrset;
-                               /* there are three possibilities:
-                                  1 - 'normal' rrset, signed by a key
-                                  2 - dnskey signed by other dnskey
-                                  3 - dnskey proven by higher level DS
-                                  (data denied by nsec is a special case that can
-                                   occur in multiple places)
+               if (cur_rr) {
+                       new_tree->rr = cur_rr;
+                       new_tree->rrset = cur_rrset;
+                       /* there are three possibilities:
+                          1 - 'normal' rrset, signed by a key
+                          2 - dnskey signed by other dnskey
+                          3 - dnskey proven by higher level DS
+                          (data denied by nsec is a special case that can
+                          occur in multiple places)
                                   
-                               */
-                               if (cur_sigs) {
-                                       for (i = 0; i < ldns_rr_list_rr_count(cur_sigs); i++) {
-                                               /* find the appropriate key in the parent list */
-                                               cur_sig_rr = ldns_rr_list_rr(cur_sigs, i);
-                                               cur_keytag = ldns_rdf2native_int16(ldns_rr_rrsig_keytag(cur_sig_rr));
-
-                                               if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_NSEC) {
-                                                       if (ldns_dname_compare(ldns_rr_owner(cur_sig_rr), 
-                                                                              ldns_rr_owner(cur_rr)))
+                       */
+                       if (cur_sigs) {
+                               for (i = 0; i < ldns_rr_list_rr_count(cur_sigs); i++) {
+                                       /* find the appropriate key in the parent list */
+                                       cur_sig_rr = ldns_rr_list_rr(cur_sigs, i);
+                                       cur_keytag = ldns_rdf2native_int16(ldns_rr_rrsig_keytag(cur_sig_rr));
+
+                                       if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_NSEC) {
+                                               if (ldns_dname_compare(ldns_rr_owner(cur_sig_rr), 
+                                                                                  ldns_rr_owner(cur_rr)))
                                                        {
                                                                /* find first that does match */
 
                                                                for (j = 0;
                                                                     j < ldns_rr_list_rr_count(cur_rrset) && 
-                                                                    ldns_dname_compare(ldns_rr_owner(cur_sig_rr),ldns_rr_owner(cur_rr)) != 0;
+                                                                               ldns_dname_compare(ldns_rr_owner(cur_sig_rr),ldns_rr_owner(cur_rr)) != 0;
                                                                     j++) {
                                                                        cur_rr = ldns_rr_list_rr(cur_rrset, j);
                                                                        
                                                                }
                                                                if (ldns_dname_compare(ldns_rr_owner(cur_sig_rr), 
-                                                                                      ldns_rr_owner(cur_rr)))
-                                                               {
-                                                                       break;
-                                                               }
+                                                                                                  ldns_rr_owner(cur_rr)))
+                                                                       {
+                                                                               break;
+                                                                       }
                                                        }
                                                        
-                                               }
-                                               /* option 1 */
-                                               if (data_chain->parent) {
-                                                       ldns_dnssec_derive_trust_tree_normal_rrset(new_tree, data_chain, cur_sig_rr);
-                                               }
-
-                                               /* option 2 */
-                                               ldns_dnssec_derive_trust_tree_dnskey_rrset(new_tree, data_chain, cur_rr, cur_sig_rr);
                                        }
+                                       /* option 1 */
+                                       if (data_chain->parent) {
+                                               ldns_dnssec_derive_trust_tree_normal_rrset(new_tree, data_chain, cur_sig_rr);
+                                       }
+
+                                       /* option 2 */
+                                       ldns_dnssec_derive_trust_tree_dnskey_rrset(new_tree, data_chain, cur_rr, cur_sig_rr);
+                               }
                                        
-                                       ldns_dnssec_derive_trust_tree_ds_rrset(new_tree, data_chain, cur_rr);
-                               } else {
-                                       /* no signatures? maybe it's nsec data */
+                               ldns_dnssec_derive_trust_tree_ds_rrset(new_tree, data_chain, cur_rr);
+                       } else {
+                               /* no signatures? maybe it's nsec data */
                                        
-                                       /* just add every rr from parent as new parent */
-                                       ldns_dnssec_derive_trust_tree_no_sig(new_tree, data_chain);
-                               }
+                               /* just add every rr from parent as new parent */
+                               ldns_dnssec_derive_trust_tree_no_sig(new_tree, data_chain);
                        }
+               }
        }
 
        return new_tree;
@@ -889,35 +889,35 @@ ldns_dnssec_trust_tree_contains_keys(ldns_dnssec_trust_tree *tree, ldns_rr_list
        
        if (tree && trusted_keys && ldns_rr_list_rr_count(trusted_keys) > 0)
                { if (tree->rr) {
-                       for (i = 0; i < ldns_rr_list_rr_count(trusted_keys); i++) {
-                               /*
-                               printf("Trying key: ");
-                               ldns_rr_print(stdout, tree->rr);
-                               */
-                               equal = ldns_rr_compare_ds(tree->rr, ldns_rr_list_rr(trusted_keys, i));
-                               if (equal) {
-                                       result = LDNS_STATUS_OK;
-                                       return result;
+                               for (i = 0; i < ldns_rr_list_rr_count(trusted_keys); i++) {
+                                       /*
+                                         printf("Trying key: ");
+                                         ldns_rr_print(stdout, tree->rr);
+                                       */
+                                       equal = ldns_rr_compare_ds(tree->rr, ldns_rr_list_rr(trusted_keys, i));
+                                       if (equal) {
+                                               result = LDNS_STATUS_OK;
+                                               return result;
+                                       }
                                }
                        }
-               }
-               for (i = 0; i < tree->parent_count; i++) {
-                       parent_result = ldns_dnssec_trust_tree_contains_keys(tree->parents[i], trusted_keys);
-                       if (parent_result != LDNS_STATUS_CRYPTO_NO_DNSKEY) {
-                               if (tree->parent_status[i] != LDNS_STATUS_OK) {
-                                       result = tree->parent_status[i];
-                               } else {
-                                       if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NSEC &&
-                                           parent_result == LDNS_STATUS_OK
-                                          ) {
-                                               result = LDNS_STATUS_DNSSEC_EXISTENCE_DENIED;
+                       for (i = 0; i < tree->parent_count; i++) {
+                               parent_result = ldns_dnssec_trust_tree_contains_keys(tree->parents[i], trusted_keys);
+                               if (parent_result != LDNS_STATUS_CRYPTO_NO_DNSKEY) {
+                                       if (tree->parent_status[i] != LDNS_STATUS_OK) {
+                                               result = tree->parent_status[i];
                                        } else {
-                                               result = parent_result;
+                                               if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NSEC &&
+                                                   parent_result == LDNS_STATUS_OK
+                                                   ) {
+                                                       result = LDNS_STATUS_DNSSEC_EXISTENCE_DENIED;
+                                               } else {
+                                                       result = parent_result;
+                                               }
                                        }
                                }
                        }
-               }
-       } else {
+               } else {
                result = LDNS_STATUS_ERR;
        }
        
@@ -936,13 +936,13 @@ ldns_calc_keytag(const ldns_rr *key)
                return 0;
        }
 
-/*
-printf("calc keytag for key at %p:\n", key);
-ldns_rr_print(stdout, key);
-*/
+       /*
+         printf("calc keytag for key at %p:\n", key);
+         ldns_rr_print(stdout, key);
+       */
        if (ldns_rr_get_type(key) != LDNS_RR_TYPE_DNSKEY &&
            ldns_rr_get_type(key) != LDNS_RR_TYPE_KEY
-          ) {
+           ) {
                return 0;
        }
 
@@ -988,7 +988,7 @@ uint16_t ldns_calc_keytag_raw(uint8_t* key, size_t keysize)
 
 ldns_status
 ldns_verify(ldns_rr_list *rrset, ldns_rr_list *rrsig, const ldns_rr_list *keys, 
-               ldns_rr_list *good_keys)
+                 ldns_rr_list *good_keys)
 {
        uint16_t i;
        bool valid;
@@ -1014,8 +1014,8 @@ ldns_verify(ldns_rr_list *rrset, ldns_rr_list *rrsig, const ldns_rr_list *keys,
                for (i = 0; i < ldns_rr_list_rr_count(rrsig); i++) {
 
                        if (ldns_verify_rrsig_keylist(rrset,
-                                       ldns_rr_list_rr(rrsig, i),
-                                       keys, good_keys) == LDNS_STATUS_OK) {
+                                                                       ldns_rr_list_rr(rrsig, i),
+                                                                       keys, good_keys) == LDNS_STATUS_OK) {
                                verify_result = LDNS_STATUS_OK;
                        }
                }
@@ -1026,249 +1026,246 @@ ldns_verify(ldns_rr_list *rrset, ldns_rr_list *rrsig, const ldns_rr_list *keys,
 ldns_rr_list *
 ldns_fetch_valid_domain_keys(const ldns_resolver * res, const ldns_rdf * domain, const ldns_rr_list * keys, ldns_status *status)
 {
-  ldns_rr_list * trusted_keys = NULL;
-  ldns_rr_list * ds_keys = NULL;
+       ldns_rr_list * trusted_keys = NULL;
+       ldns_rr_list * ds_keys = NULL;
 
-  if (res && domain && keys) {
+       if (res && domain && keys) {
 
-    if ((trusted_keys = ldns_validate_domain_dnskey(res, domain, keys))) {
-      *status = LDNS_STATUS_OK;
-    } else {
+               if ((trusted_keys = ldns_validate_domain_dnskey(res, domain, keys))) {
+                       *status = LDNS_STATUS_OK;
+               } else {
       
-      /* No trusted keys in this domain, we'll have to find some in the parent domain */
-      *status = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY;
+                       /* No trusted keys in this domain, we'll have to find some in the parent domain */
+                       *status = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY;
       
-      if (ldns_rdf_size(domain) > 1) { /* Fail if we are at the root */
-        ldns_rr_list * parent_keys;
-        ldns_rdf * parent_domain = ldns_dname_left_chop(domain);
+                       if (ldns_rdf_size(domain) > 1) { /* Fail if we are at the root */
+                               ldns_rr_list * parent_keys;
+                               ldns_rdf * parent_domain = ldns_dname_left_chop(domain);
        
-        if ((parent_keys = ldns_fetch_valid_domain_keys(res, parent_domain, keys, status))) {
+                               if ((parent_keys = ldns_fetch_valid_domain_keys(res, parent_domain, keys, status))) {
          
-          /* Check DS records */
-          if ((ds_keys = ldns_validate_domain_ds(res, domain, parent_keys))) {
-            trusted_keys = ldns_fetch_valid_domain_keys(res, domain, ds_keys, status);
-            ldns_rr_list_deep_free(ds_keys);
-          } else {
-            /* No valid DS at the parent -- fail */
-            *status = LDNS_STATUS_CRYPTO_NO_TRUSTED_DS ;
-          }
-          ldns_rr_list_deep_free(parent_keys);
-        }
-        ldns_rdf_free(parent_domain);
-      }
-    }
-  }
-  return trusted_keys;
+                                       /* Check DS records */
+                                       if ((ds_keys = ldns_validate_domain_ds(res, domain, parent_keys))) {
+                                               trusted_keys = ldns_fetch_valid_domain_keys(res, domain, ds_keys, status);
+                                               ldns_rr_list_deep_free(ds_keys);
+                                       } else {
+                                               /* No valid DS at the parent -- fail */
+                                               *status = LDNS_STATUS_CRYPTO_NO_TRUSTED_DS ;
+                                       }
+                                       ldns_rr_list_deep_free(parent_keys);
+                               }
+                               ldns_rdf_free(parent_domain);
+                       }
+               }
+       }
+       return trusted_keys;
 }
 
 ldns_rr_list *
 ldns_validate_domain_dnskey (const ldns_resolver * res, const ldns_rdf * domain, const ldns_rr_list * keys)
 {
-  ldns_status status;
-  ldns_pkt * keypkt;
-  ldns_rr * cur_key;
-  uint16_t key_i; uint16_t key_j; uint16_t key_k;
-  uint16_t sig_i; ldns_rr * cur_sig;
+       ldns_status status;
+       ldns_pkt * keypkt;
+       ldns_rr * cur_key;
+       uint16_t key_i; uint16_t key_j; uint16_t key_k;
+       uint16_t sig_i; ldns_rr * cur_sig;
 
-  ldns_rr_list * domain_keys = NULL;
-  ldns_rr_list * domain_sigs = NULL;
-  ldns_rr_list * trusted_keys = NULL;
+       ldns_rr_list * domain_keys = NULL;
+       ldns_rr_list * domain_sigs = NULL;
+       ldns_rr_list * trusted_keys = NULL;
 
-  /* Fetch keys for the domain */
-  if ((keypkt = ldns_resolver_query(res, domain, LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, LDNS_RD))) {
+       /* Fetch keys for the domain */
+       if ((keypkt = ldns_resolver_query(res, domain, LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, LDNS_RD))) {
 
-    domain_keys = ldns_pkt_rr_list_by_type(keypkt, LDNS_RR_TYPE_DNSKEY, LDNS_SECTION_ANSWER);
-    domain_sigs = ldns_pkt_rr_list_by_type(keypkt, LDNS_RR_TYPE_RRSIG, LDNS_SECTION_ANSWER);
+               domain_keys = ldns_pkt_rr_list_by_type(keypkt, LDNS_RR_TYPE_DNSKEY, LDNS_SECTION_ANSWER);
+               domain_sigs = ldns_pkt_rr_list_by_type(keypkt, LDNS_RR_TYPE_RRSIG, LDNS_SECTION_ANSWER);
 
-    /* Try to validate the record using our keys */
-    for (key_i=0; key_i< ldns_rr_list_rr_count(domain_keys); key_i++) {
+               /* Try to validate the record using our keys */
+               for (key_i=0; key_i< ldns_rr_list_rr_count(domain_keys); key_i++) {
       
-      cur_key = ldns_rr_list_rr(domain_keys, key_i);
-      for (key_j=0; key_j<ldns_rr_list_rr_count(keys); key_j++) {
-        if (ldns_rr_compare_ds(ldns_rr_list_rr(keys, key_j), cur_key)) {
+                       cur_key = ldns_rr_list_rr(domain_keys, key_i);
+                       for (key_j=0; key_j<ldns_rr_list_rr_count(keys); key_j++) {
+                               if (ldns_rr_compare_ds(ldns_rr_list_rr(keys, key_j), cur_key)) {
           
-          /* Current key is trusted -- validate */
-          trusted_keys = ldns_rr_list_new();
+                                       /* Current key is trusted -- validate */
+                                       trusted_keys = ldns_rr_list_new();
           
-          for (sig_i=0; sig_i<ldns_rr_list_rr_count(domain_sigs); sig_i++) {
-            cur_sig = ldns_rr_list_rr(domain_sigs, sig_i);
-            /* Avoid non-matching sigs */
-            if (ldns_rdf2native_int16(ldns_rr_rrsig_keytag(cur_sig)) == ldns_calc_keytag(cur_key)) {
-              if ((status=ldns_verify_rrsig(domain_keys, cur_sig, cur_key)) == LDNS_STATUS_OK) {
+                                       for (sig_i=0; sig_i<ldns_rr_list_rr_count(domain_sigs); sig_i++) {
+                                               cur_sig = ldns_rr_list_rr(domain_sigs, sig_i);
+                                               /* Avoid non-matching sigs */
+                                               if (ldns_rdf2native_int16(ldns_rr_rrsig_keytag(cur_sig)) == ldns_calc_keytag(cur_key)) {
+                                                       if ((status=ldns_verify_rrsig(domain_keys, cur_sig, cur_key)) == LDNS_STATUS_OK) {
                 
-                /* Push the whole rrset -- we can't do much more */
-                for (key_k=0; key_k<ldns_rr_list_rr_count(domain_keys); key_k++) {
-                  ldns_rr_list_push_rr(trusted_keys, ldns_rr_clone(ldns_rr_list_rr(domain_keys, key_k)));
-                }
+                                                               /* Push the whole rrset -- we can't do much more */
+                                                               for (key_k=0; key_k<ldns_rr_list_rr_count(domain_keys); key_k++) {
+                                                                       ldns_rr_list_push_rr(trusted_keys, ldns_rr_clone(ldns_rr_list_rr(domain_keys, key_k)));
+                                                               }
                 
-                ldns_rr_list_deep_free(domain_keys);
-                ldns_rr_list_deep_free(domain_sigs);
-                ldns_pkt_free(keypkt);
-                return trusted_keys;
-              } /* else {
-                fprintf(stderr, "# Signature verification failed: %s\n", ldns_get_errorstr_by_id(status));
-              }
-            } else {
-              fprintf(stderr, "# Non-matching keytag for sig %u. Skipping.\n", sig_i);
-                */
-            }
-          }
+                                                               ldns_rr_list_deep_free(domain_keys);
+                                                               ldns_rr_list_deep_free(domain_sigs);
+                                                               ldns_pkt_free(keypkt);
+                                                               return trusted_keys;
+                                                       } /* else {
+                                                               fprintf(stderr, "# Signature verification failed: %s\n", ldns_get_errorstr_by_id(status));
+                                                               }
+                                                               } else {
+                                                               fprintf(stderr, "# Non-matching keytag for sig %u. Skipping.\n", sig_i);
+                                                         */
+                                               }
+                                       }
          
-          /* Only push our trusted key */
-          ldns_rr_list_push_rr(trusted_keys, ldns_rr_clone(cur_key));
-        }
-      }
-    }
-
-    ldns_rr_list_deep_free(domain_keys);
-    ldns_rr_list_deep_free(domain_sigs);
-    ldns_pkt_free(keypkt);
-
-  } else {
-    status = LDNS_STATUS_CRYPTO_NO_DNSKEY;
-  }
+                                       /* Only push our trusted key */
+                                       ldns_rr_list_push_rr(trusted_keys, ldns_rr_clone(cur_key));
+                               }
+                       }
+               }
+
+               ldns_rr_list_deep_free(domain_keys);
+               ldns_rr_list_deep_free(domain_sigs);
+               ldns_pkt_free(keypkt);
+
+       } else {
+               status = LDNS_STATUS_CRYPTO_NO_DNSKEY;
+       }
     
-  return trusted_keys;
+       return trusted_keys;
 }
 
 ldns_rr_list *
 ldns_validate_domain_ds (const ldns_resolver * res, const ldns_rdf * domain, const ldns_rr_list * keys)
 {
-  ldns_status status;
-  ldns_pkt * dspkt;
-  uint16_t key_i;
-  ldns_rr_list * rrset = NULL;
-  ldns_rr_list * sigs = NULL;
-  ldns_rr_list * trusted_keys = NULL;
-
-  /* Fetch DS for the domain */
-  if ((dspkt = ldns_resolver_query(res, domain, LDNS_RR_TYPE_DS, LDNS_RR_CLASS_IN, LDNS_RD))) {
-
-    rrset = ldns_pkt_rr_list_by_type(dspkt, LDNS_RR_TYPE_DS, LDNS_SECTION_ANSWER);
-    sigs = ldns_pkt_rr_list_by_type(dspkt, LDNS_RR_TYPE_RRSIG, LDNS_SECTION_ANSWER);
-
-    /* Validate sigs */
-    if ((status = ldns_verify(rrset, sigs, keys, NULL)) == LDNS_STATUS_OK) {
-      trusted_keys = ldns_rr_list_new();
-      for (key_i=0; key_i<ldns_rr_list_rr_count(rrset); key_i++) {
-       ldns_rr_list_push_rr(trusted_keys, ldns_rr_clone(ldns_rr_list_rr(rrset, key_i)));
-      }
-    }
+       ldns_status status;
+       ldns_pkt * dspkt;
+       uint16_t key_i;
+       ldns_rr_list * rrset = NULL;
+       ldns_rr_list * sigs = NULL;
+       ldns_rr_list * trusted_keys = NULL;
+
+       /* Fetch DS for the domain */
+       if ((dspkt = ldns_resolver_query(res, domain, LDNS_RR_TYPE_DS, LDNS_RR_CLASS_IN, LDNS_RD))) {
+
+               rrset = ldns_pkt_rr_list_by_type(dspkt, LDNS_RR_TYPE_DS, LDNS_SECTION_ANSWER);
+               sigs = ldns_pkt_rr_list_by_type(dspkt, LDNS_RR_TYPE_RRSIG, LDNS_SECTION_ANSWER);
+
+               /* Validate sigs */
+               if ((status = ldns_verify(rrset, sigs, keys, NULL)) == LDNS_STATUS_OK) {
+                       trusted_keys = ldns_rr_list_new();
+                       for (key_i=0; key_i<ldns_rr_list_rr_count(rrset); key_i++) {
+                               ldns_rr_list_push_rr(trusted_keys, ldns_rr_clone(ldns_rr_list_rr(rrset, key_i)));
+                       }
+               }
 
-    ldns_rr_list_deep_free(rrset);
-    ldns_rr_list_deep_free(sigs);
-    ldns_pkt_free(dspkt);
+               ldns_rr_list_deep_free(rrset);
+               ldns_rr_list_deep_free(sigs);
+               ldns_pkt_free(dspkt);
 
-  } else {
-    status = LDNS_STATUS_CRYPTO_NO_DS;
-  }
+       } else {
+               status = LDNS_STATUS_CRYPTO_NO_DS;
+       }
 
-  return trusted_keys;
+       return trusted_keys;
 }
 
-#ifdef HAVE_SSL
 ldns_status
 ldns_verify_trusted(ldns_resolver * res, ldns_rr_list * rrset, ldns_rr_list * rrsigs, ldns_rr_list * validating_keys)
 {
-  /* */
-  uint16_t sig_i; uint16_t key_i;
-  ldns_rr * cur_sig; ldns_rr * cur_key;
-  ldns_rr_list * trusted_keys = NULL;
-  ldns_status result = LDNS_STATUS_ERR;
-printf("[verify_trusted] set default result to %s\n", ldns_get_errorstr_by_id(result));
-
-  if (!res || !rrset || !rrsigs) {
-    return LDNS_STATUS_ERR;
-  }
+       /* */
+       uint16_t sig_i; uint16_t key_i;
+       ldns_rr * cur_sig; ldns_rr * cur_key;
+       ldns_rr_list * trusted_keys = NULL;
+       ldns_status result = LDNS_STATUS_ERR;
+       printf("[verify_trusted] set default result to %s\n", ldns_get_errorstr_by_id(result));
+
+       if (!res || !rrset || !rrsigs) {
+               return LDNS_STATUS_ERR;
+       }
 
-  if (ldns_rr_list_rr_count(rrset) < 1) {
-    return LDNS_STATUS_ERR;
-  }
+       if (ldns_rr_list_rr_count(rrset) < 1) {
+               return LDNS_STATUS_ERR;
+       }
 
-  if (ldns_rr_list_rr_count(rrsigs) < 1) {
-    return LDNS_STATUS_CRYPTO_NO_RRSIG;
-  }
+       if (ldns_rr_list_rr_count(rrsigs) < 1) {
+               return LDNS_STATUS_CRYPTO_NO_RRSIG;
+       }
   
-  /* Look at each sig */
-  for (sig_i=0; sig_i < ldns_rr_list_rr_count(rrsigs); sig_i++) {
-
-    cur_sig = ldns_rr_list_rr(rrsigs, sig_i);
-    /* Get a valid signer key and validate the sig */
-    if ((trusted_keys = ldns_fetch_valid_domain_keys(res, ldns_rr_rrsig_signame(cur_sig), ldns_resolver_dnssec_anchors(res), &result))) {
-
-      for (key_i = 0; key_i < ldns_rr_list_rr_count(trusted_keys); key_i++) {
-        cur_key = ldns_rr_list_rr(trusted_keys, key_i);
-printf("[verify_trusted] trying:\n[verify_trusted] ");
-
-        if ((result = ldns_verify_rrsig(rrset, cur_sig, cur_key)) == LDNS_STATUS_OK) {
-          if (validating_keys) {
-            ldns_rr_list_push_rr(validating_keys, ldns_rr_clone(cur_key));
-          }
-          ldns_rr_list_deep_free(trusted_keys);
-          printf("[verify_trusted] returning OK\n");
-          return LDNS_STATUS_OK;
-        }
-        else {
-               printf("RESULT: %s\nFOR:\n", ldns_get_errorstr_by_id(result));
-               ldns_rr_list_print(stdout, rrset);
-               ldns_rr_print(stdout, cur_sig);
-               ldns_rr_print(stdout, cur_key);
+       /* Look at each sig */
+       for (sig_i=0; sig_i < ldns_rr_list_rr_count(rrsigs); sig_i++) {
+
+               cur_sig = ldns_rr_list_rr(rrsigs, sig_i);
+               /* Get a valid signer key and validate the sig */
+               if ((trusted_keys = ldns_fetch_valid_domain_keys(res, ldns_rr_rrsig_signame(cur_sig), ldns_resolver_dnssec_anchors(res), &result))) {
+
+                       for (key_i = 0; key_i < ldns_rr_list_rr_count(trusted_keys); key_i++) {
+                               cur_key = ldns_rr_list_rr(trusted_keys, key_i);
+                               printf("[verify_trusted] trying:\n[verify_trusted] ");
+
+                               if ((result = ldns_verify_rrsig(rrset, cur_sig, cur_key)) == LDNS_STATUS_OK) {
+                                       if (validating_keys) {
+                                               ldns_rr_list_push_rr(validating_keys, ldns_rr_clone(cur_key));
+                                       }
+                                       ldns_rr_list_deep_free(trusted_keys);
+                                       printf("[verify_trusted] returning OK\n");
+                                       return LDNS_STATUS_OK;
+                               }
+                               else {
+                                       printf("RESULT: %s\nFOR:\n", ldns_get_errorstr_by_id(result));
+                                       ldns_rr_list_print(stdout, rrset);
+                                       ldns_rr_print(stdout, cur_sig);
+                                       ldns_rr_print(stdout, cur_key);
                
-        }
-printf("[verify_trusted] set result to %s\n", ldns_get_errorstr_by_id(result));
-      }
-    }
-    else {
-    printf("[verify_trusted] no valid domain keys\n");
-    }
-  }
-
-  ldns_rr_list_deep_free(trusted_keys);
-  printf("[verify_trusted] returning: %s\n", ldns_get_errorstr_by_id(result));
-  return result;
-}
-#endif
+                               }
+                               printf("[verify_trusted] set result to %s\n", ldns_get_errorstr_by_id(result));
+                       }
+               }
+               else {
+                       printf("[verify_trusted] no valid domain keys\n");
+               }
+       }
 
+       ldns_rr_list_deep_free(trusted_keys);
+       printf("[verify_trusted] returning: %s\n", ldns_get_errorstr_by_id(result));
+       return result;
+}
 
 ldns_status
 ldns_verify_rrsig_buffers(ldns_buffer *rawsig_buf, ldns_buffer *verify_buf, 
-       ldns_buffer *key_buf, uint8_t algo)
+                                        ldns_buffer *key_buf, uint8_t algo)
 {
        return ldns_verify_rrsig_buffers_raw((unsigned char*)ldns_buffer_begin(
-               rawsig_buf), ldns_buffer_position(rawsig_buf), verify_buf,
-               (unsigned char*)ldns_buffer_begin(key_buf), 
-               ldns_buffer_position(key_buf), algo);
+                                                                                                                        rawsig_buf), ldns_buffer_position(rawsig_buf), verify_buf,
+                                                                 (unsigned char*)ldns_buffer_begin(key_buf), 
+                                                                 ldns_buffer_position(key_buf), algo);
 }
 
 ldns_status
 ldns_verify_rrsig_buffers_raw(unsigned char* sig, size_t siglen,
-       ldns_buffer *verify_buf, unsigned char* key, size_t keylen, 
-       uint8_t algo)
+                                               ldns_buffer *verify_buf, unsigned char* key, size_t keylen, 
+                                               uint8_t algo)
 {
        /* check for right key */
        switch(algo) {
-               case LDNS_DSA:
-               case LDNS_DSA_NSEC3:
-                       return ldns_verify_rrsig_dsa_raw(sig, siglen, verify_buf, key, keylen);
-                       break;
-               case LDNS_RSASHA1:
-               case LDNS_RSASHA1_NSEC3:
-                       return ldns_verify_rrsig_rsasha1_raw(sig, siglen, verify_buf, key, keylen);
-                       break;
-               case LDNS_RSASHA256:
-               case LDNS_RSASHA256_NSEC3:
-                       return ldns_verify_rrsig_rsasha256_raw(sig, siglen, verify_buf, key, keylen);
-                       break;
-               case LDNS_RSASHA512:
-               case LDNS_RSASHA512_NSEC3:
-                       return ldns_verify_rrsig_rsasha512_raw(sig, siglen, verify_buf, key, keylen);
-                       break;
-               case LDNS_RSAMD5:
-                       return ldns_verify_rrsig_rsamd5_raw(sig, siglen, verify_buf, key, keylen);
-                       break;
-               default:
-                       /* do you know this alg?! */
-                       return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
+       case LDNS_DSA:
+       case LDNS_DSA_NSEC3:
+               return ldns_verify_rrsig_dsa_raw(sig, siglen, verify_buf, key, keylen);
+               break;
+       case LDNS_RSASHA1:
+       case LDNS_RSASHA1_NSEC3:
+               return ldns_verify_rrsig_rsasha1_raw(sig, siglen, verify_buf, key, keylen);
+               break;
+       case LDNS_RSASHA256:
+       case LDNS_RSASHA256_NSEC3:
+               return ldns_verify_rrsig_rsasha256_raw(sig, siglen, verify_buf, key, keylen);
+               break;
+       case LDNS_RSASHA512:
+       case LDNS_RSASHA512_NSEC3:
+               return ldns_verify_rrsig_rsasha512_raw(sig, siglen, verify_buf, key, keylen);
+               break;
+       case LDNS_RSAMD5:
+               return ldns_verify_rrsig_rsamd5_raw(sig, siglen, verify_buf, key, keylen);
+               break;
+       default:
+               /* do you know this alg?! */
+               return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
        }
 }
 
@@ -1284,7 +1281,7 @@ ldns_verify_rrsig_buffers_raw(unsigned char* sig, size_t siglen,
  */
 ldns_status
 ldns_verify_rrsig_keylist(ldns_rr_list *rrset, ldns_rr *rrsig, const ldns_rr_list *keys, 
-               ldns_rr_list *good_keys)
+                                        ldns_rr_list *good_keys)
 {
        ldns_buffer *rawsig_buf;
        ldns_buffer *verify_buf;
@@ -1320,7 +1317,7 @@ ldns_verify_rrsig_keylist(ldns_rr_list *rrset, ldns_rr *rrsig, const ldns_rr_lis
 
        /* check if the typecovered is equal to the type checked */
        if (ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rrsig)) !=
-                       ldns_rr_get_type(ldns_rr_list_rr(rrset_clone, 0))) {
+           ldns_rr_get_type(ldns_rr_list_rr(rrset_clone, 0))) {
                ldns_rr_list_deep_free(rrset_clone);
                ldns_rr_list_deep_free(validkeys);
                return LDNS_STATUS_CRYPTO_TYPE_COVERED_ERR;
@@ -1379,8 +1376,8 @@ ldns_verify_rrsig_keylist(ldns_rr_list *rrset, ldns_rr *rrsig, const ldns_rr_lis
        /* and update owner name if it was wildcard */
        for(i = 0; i < ldns_rr_list_rr_count(rrset_clone); i++) {
                if (label_count < 
-                       ldns_dname_label_count(
-                                       ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i)))) {
+                   ldns_dname_label_count(
+                                                         ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i)))) {
                        (void) ldns_str2rdf_dname(&wildcard_name, "*");
                        wildcard_chopped = ldns_rdf_clone(ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i)));
                        while (label_count < ldns_dname_label_count(wildcard_chopped)) {
@@ -1392,7 +1389,7 @@ ldns_verify_rrsig_keylist(ldns_rr_list *rrset, ldns_rr *rrsig, const ldns_rr_lis
                        ldns_rdf_deep_free(wildcard_chopped);
                        ldns_rdf_deep_free(ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i)));
                        ldns_rr_set_owner(ldns_rr_list_rr(rrset_clone, i), 
-                                       wildcard_name);
+                                                  wildcard_name);
                                        
                }
                ldns_rr_set_ttl(ldns_rr_list_rr(rrset_clone, i), orig_ttl);
@@ -1425,13 +1422,13 @@ ldns_verify_rrsig_keylist(ldns_rr_list *rrset, ldns_rr *rrsig, const ldns_rr_lis
                current_key = ldns_rr_list_rr(keys, i);
                /* before anything, check if the keytags match */
                if (ldns_calc_keytag(current_key) ==
-                       ldns_rdf2native_int16(ldns_rr_rrsig_keytag(rrsig))) {
+                   ldns_rdf2native_int16(ldns_rr_rrsig_keytag(rrsig))) {
                        key_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
                        
                        /* put the key-data in a buffer, that's the third rdf, with
                         * the base64 encoded key data */
                        if (ldns_rdf2buffer_wire(key_buf,
-                                       ldns_rr_rdf(current_key, 3)) != LDNS_STATUS_OK) {
+                                                               ldns_rr_rdf(current_key, 3)) != LDNS_STATUS_OK) {
                                ldns_buffer_free(rawsig_buf);
                                ldns_buffer_free(verify_buf);
                                /* returning is bad might screw up good keys later in the list
@@ -1443,9 +1440,9 @@ ldns_verify_rrsig_keylist(ldns_rr_list *rrset, ldns_rr *rrsig, const ldns_rr_lis
 
                        /* check for right key */
                        if (sig_algo == ldns_rdf2native_int8(ldns_rr_rdf(current_key, 
-                                                       2))) {
+                                                                                                   2))) {
                                result = ldns_verify_rrsig_buffers(rawsig_buf, 
-                                               verify_buf, key_buf, sig_algo);
+                                                                                       verify_buf, key_buf, sig_algo);
                        } else {
                                result = LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
                        }
@@ -1560,7 +1557,11 @@ ldns_verify_rrsig(ldns_rr_list *rrset, ldns_rr *rrsig, ldns_rr *key)
        ldns_rdf *wildcard_chopped;
        ldns_rdf *wildcard_chopped_tmp;
 
-
+       printf("START\n");
+       ldns_rr_list_print(stdout, rrset);
+       ldns_rr_print(stdout, rrsig);
+       ldns_rr_print(stdout, key);
+       printf("END\n");
        if (!rrset) {
                return LDNS_STATUS_NO_DATA;
        }
@@ -1579,8 +1580,6 @@ ldns_verify_rrsig(ldns_rr_list *rrset, ldns_rr *rrsig, ldns_rr *key)
        }
        if (now - inception < 0) {
                /* bad sig, inception date has not passed */
-
-print_dates(now, inception);
                return LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED;
        }
 
@@ -1605,41 +1604,41 @@ print_dates(now, inception);
        /* (the DSA API wants DER encoding for instance) */
 
        switch(sig_algo) {
-               case LDNS_RSAMD5:
-               case LDNS_RSASHA1:
-               case LDNS_RSASHA1_NSEC3:
-               case LDNS_RSASHA256:
-               case LDNS_RSASHA256_NSEC3:
-               case LDNS_RSASHA512:
-               case LDNS_RSASHA512_NSEC3:
-                       if (ldns_rdf2buffer_wire(rawsig_buf,
-                                               ldns_rr_rdf(rrsig, 8)) != LDNS_STATUS_OK) {
-                               ldns_buffer_free(rawsig_buf);
-                               ldns_buffer_free(verify_buf);
-                               return LDNS_STATUS_MEM_ERR;
-                       }
-                       break;
-               case LDNS_DSA:
-               case LDNS_DSA_NSEC3:
-                       if (ldns_convert_dsa_rrsig_rdata(rawsig_buf,
-                                               ldns_rr_rdf(rrsig, 8)) != LDNS_STATUS_OK) {
-                               ldns_buffer_free(rawsig_buf);
-                               ldns_buffer_free(verify_buf);
-                               return LDNS_STATUS_MEM_ERR;
-                       }
-                       break;
-                       break;
-               case LDNS_DH:
-               case LDNS_ECC:
-               case LDNS_INDIRECT:
+       case LDNS_RSAMD5:
+       case LDNS_RSASHA1:
+       case LDNS_RSASHA1_NSEC3:
+       case LDNS_RSASHA256:
+       case LDNS_RSASHA256_NSEC3:
+       case LDNS_RSASHA512:
+       case LDNS_RSASHA512_NSEC3:
+               if (ldns_rdf2buffer_wire(rawsig_buf,
+                                                       ldns_rr_rdf(rrsig, 8)) != LDNS_STATUS_OK) {
                        ldns_buffer_free(rawsig_buf);
                        ldns_buffer_free(verify_buf);
-                       return LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL;
-               default:
+                       return LDNS_STATUS_MEM_ERR;
+               }
+               break;
+       case LDNS_DSA:
+       case LDNS_DSA_NSEC3:
+               if (ldns_convert_dsa_rrsig_rdata(rawsig_buf,
+                                                                  ldns_rr_rdf(rrsig, 8)) != LDNS_STATUS_OK) {
                        ldns_buffer_free(rawsig_buf);
                        ldns_buffer_free(verify_buf);
-                       ldns_rr_list_deep_free(rrset_clone);
-                       return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
+                       return LDNS_STATUS_MEM_ERR;
+               }
+               break;
+               break;
+       case LDNS_DH:
+       case LDNS_ECC:
+       case LDNS_INDIRECT:
+               ldns_buffer_free(rawsig_buf);
+               ldns_buffer_free(verify_buf);
+               return LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL;
+       default:
+               ldns_buffer_free(rawsig_buf);
+               ldns_buffer_free(verify_buf);
+               ldns_rr_list_deep_free(rrset_clone);
+               return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
        }
        
        result = LDNS_STATUS_ERR;
@@ -1649,13 +1648,13 @@ print_dates(now, inception);
        label_count = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 2));
 
        orig_ttl = ldns_rdf2native_int32(
-                       ldns_rr_rdf(rrsig, 3));
+                                                          ldns_rr_rdf(rrsig, 3));
 
        /* reset the ttl in the rrset with the orig_ttl from the sig */
        for(i = 0; i < ldns_rr_list_rr_count(rrset_clone); i++) {
                if (label_count < 
-                       ldns_dname_label_count(
-                                       ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i)))) {
+                   ldns_dname_label_count(
+                                                         ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i)))) {
                        (void) ldns_str2rdf_dname(&wildcard_name, "*");
                        wildcard_chopped = ldns_rdf_clone(ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i)));
                        while (label_count < ldns_dname_label_count(wildcard_chopped)) {
@@ -1667,12 +1666,12 @@ print_dates(now, inception);
                        ldns_rdf_deep_free(wildcard_chopped);
                        ldns_rdf_deep_free(ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i)));
                        ldns_rr_set_owner(ldns_rr_list_rr(rrset_clone, i), 
-                                       wildcard_name);
+                                                  wildcard_name);
                                        
                }
                ldns_rr_set_ttl(
-                               ldns_rr_list_rr(rrset_clone, i),
-                               orig_ttl);
+                                        ldns_rr_list_rr(rrset_clone, i),
+                                        orig_ttl);
                /* convert to lowercase */
                ldns_rr2canonical(ldns_rr_list_rr(rrset_clone, i));
        }
@@ -1697,9 +1696,9 @@ print_dates(now, inception);
        }
 
        if (ldns_calc_keytag(key)
-               ==
-               ldns_rdf2native_int16(ldns_rr_rrsig_keytag(rrsig))
-          ) {
+           ==
+           ldns_rdf2native_int16(ldns_rr_rrsig_keytag(rrsig))
+           ) {
                key_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
                
                /* before anything, check if the keytags match */
@@ -1707,7 +1706,7 @@ print_dates(now, inception);
                /* put the key-data in a buffer, that's the third rdf, with
                 * the base64 encoded key data */
                if (ldns_rdf2buffer_wire(key_buf,
-                               ldns_rr_rdf(key, 3)) != LDNS_STATUS_OK) {
+                                                       ldns_rr_rdf(key, 3)) != LDNS_STATUS_OK) {
                        ldns_rr_list_deep_free(rrset_clone);
                        ldns_buffer_free(rawsig_buf);
                        ldns_buffer_free(verify_buf);
@@ -1723,7 +1722,7 @@ print_dates(now, inception);
                
                ldns_buffer_free(key_buf); 
        }
-        else {
+       else {
                /* No keys with the corresponding keytag are found */
                if (result == LDNS_STATUS_ERR) {
                        result = LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY;
@@ -1733,15 +1732,15 @@ print_dates(now, inception);
        ldns_rr_list_deep_free(rrset_clone);
        ldns_buffer_free(rawsig_buf);
        ldns_buffer_free(verify_buf);
-/*
-       printf("RETURNING RESULT: %s\n", ldns_get_errorstr_by_id(result));
-       printf("for:\n");
-       ldns_rr_list_print(stdout, rrset);
-       printf("sig:\n");
-       ldns_rr_print(stdout, rrsig);
-       printf("key:\n");
-       ldns_rr_print(stdout, key);
-*/
+       /*
+         printf("RETURNING RESULT: %s\n", ldns_get_errorstr_by_id(result));
+         printf("for:\n");
+         ldns_rr_list_print(stdout, rrset);
+         printf("sig:\n");
+         ldns_rr_print(stdout, rrsig);
+         printf("key:\n");
+         ldns_rr_print(stdout, key);
+       */
        return result;
 }
 
@@ -1749,12 +1748,12 @@ ldns_status
 ldns_verify_rrsig_evp(ldns_buffer *sig, ldns_buffer *rrset, EVP_PKEY *key, const EVP_MD *digest_type)
 {
        return ldns_verify_rrsig_evp_raw((unsigned char*)ldns_buffer_begin(
-               sig), ldns_buffer_position(sig), rrset, key, digest_type);
+                                                                                                                 sig), ldns_buffer_position(sig), rrset, key, digest_type);
 }
 
 ldns_status
 ldns_verify_rrsig_evp_raw(unsigned char *sig, size_t siglen, 
-       ldns_buffer *rrset, EVP_PKEY *key, const EVP_MD *digest_type)
+                                        ldns_buffer *rrset, EVP_PKEY *key, const EVP_MD *digest_type)
 {
        EVP_MD_CTX ctx;
        int res;
@@ -1780,29 +1779,29 @@ ldns_status
 ldns_verify_rrsig_dsa(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key)
 {
        return ldns_verify_rrsig_dsa_raw((unsigned char*)ldns_buffer_begin(
-               sig), ldns_buffer_position(sig), rrset, (unsigned char*)
-               ldns_buffer_begin(key), ldns_buffer_position(key));
+                                                                                                                 sig), ldns_buffer_position(sig), rrset, (unsigned char*)
+                                                          ldns_buffer_begin(key), ldns_buffer_position(key));
 }
 
 ldns_status
 ldns_verify_rrsig_rsasha1(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key)
 {
        return ldns_verify_rrsig_rsasha1_raw((unsigned char*)ldns_buffer_begin(
-               sig), ldns_buffer_position(sig), rrset, (unsigned char*)
-               ldns_buffer_begin(key), ldns_buffer_position(key));
+                                                                                                                        sig), ldns_buffer_position(sig), rrset, (unsigned char*)
+                                                                 ldns_buffer_begin(key), ldns_buffer_position(key));
 }
 
 ldns_status
 ldns_verify_rrsig_rsamd5(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key)
 {
        return ldns_verify_rrsig_rsamd5_raw((unsigned char*)ldns_buffer_begin(
-               sig), ldns_buffer_position(sig), rrset, (unsigned char*)
-               ldns_buffer_begin(key), ldns_buffer_position(key));
+                                                                                                                       sig), ldns_buffer_position(sig), rrset, (unsigned char*)
+                                                                ldns_buffer_begin(key), ldns_buffer_position(key));
 }
 
 ldns_status
 ldns_verify_rrsig_dsa_raw(unsigned char* sig, size_t siglen,
-        ldns_buffer* rrset, unsigned char* key, size_t keylen)
+                                        ldns_buffer* rrset, unsigned char* key, size_t keylen)
 {
        EVP_PKEY *evp_key;
        ldns_status result;
@@ -1817,7 +1816,7 @@ ldns_verify_rrsig_dsa_raw(unsigned char* sig, size_t siglen,
 
 ldns_status
 ldns_verify_rrsig_rsasha1_raw(unsigned char* sig, size_t siglen,
-        ldns_buffer* rrset, unsigned char* key, size_t keylen)
+                                               ldns_buffer* rrset, unsigned char* key, size_t keylen)
 {
        EVP_PKEY *evp_key;
        ldns_status result;
@@ -1832,7 +1831,7 @@ ldns_verify_rrsig_rsasha1_raw(unsigned char* sig, size_t siglen,
 
 ldns_status
 ldns_verify_rrsig_rsasha256_raw(unsigned char* sig, size_t siglen,
-        ldns_buffer* rrset, unsigned char* key, size_t keylen)
+                                                 ldns_buffer* rrset, unsigned char* key, size_t keylen)
 {
 #ifdef SHA256_DIGEST_LENGTH
        EVP_PKEY *evp_key;
@@ -1851,7 +1850,7 @@ ldns_verify_rrsig_rsasha256_raw(unsigned char* sig, size_t siglen,
 
 ldns_status
 ldns_verify_rrsig_rsasha512_raw(unsigned char* sig, size_t siglen,
-        ldns_buffer* rrset, unsigned char* key, size_t keylen)
+                                                 ldns_buffer* rrset, unsigned char* key, size_t keylen)
 {
 #ifdef SHA512_DIGEST_LENGTH
        EVP_PKEY *evp_key;
@@ -1872,7 +1871,7 @@ ldns_verify_rrsig_rsasha512_raw(unsigned char* sig, size_t siglen,
 
 ldns_status
 ldns_verify_rrsig_rsamd5_raw(unsigned char* sig, size_t siglen,
-        ldns_buffer* rrset, unsigned char* key, size_t keylen)
+                                           ldns_buffer* rrset, unsigned char* key, size_t keylen)
 {
        EVP_PKEY *evp_key;
        ldns_status result;
@@ -1885,12 +1884,11 @@ ldns_verify_rrsig_rsamd5_raw(unsigned char* sig, size_t siglen,
        return result;
 }
 
-#ifdef HAVE_SSL
 DSA *
 ldns_key_buf2dsa(ldns_buffer *key)
 {
        return ldns_key_buf2dsa_raw((unsigned char*)ldns_buffer_begin(key),
-               ldns_buffer_position(key));
+                                                  ldns_buffer_position(key));
 }
 
 DSA *
@@ -1936,13 +1934,12 @@ ldns_key_buf2dsa_raw(unsigned char* key, size_t len)
 
        return dsa;
 }
-#endif
 
 RSA *
 ldns_key_buf2rsa(ldns_buffer *key)
 {
        return ldns_key_buf2rsa_raw((unsigned char*)ldns_buffer_begin(key),
-               ldns_buffer_position(key));
+                                                  ldns_buffer_position(key));
 }
 
 RSA *
@@ -2012,29 +2009,29 @@ ldns_key_rr2ds(const ldns_rr *key, ldns_hash h)
        }
        ldns_rr_set_type(ds, LDNS_RR_TYPE_DS);
        ldns_rr_set_owner(ds, ldns_rdf_clone(
-                               ldns_rr_owner(key)));
+                                                                 ldns_rr_owner(key)));
        ldns_rr_set_ttl(ds, ldns_rr_ttl(key));
        ldns_rr_set_class(ds, ldns_rr_get_class(key));
 
        switch(h) {
-               default:
-               case LDNS_SHA1:
-                       digest = LDNS_XMALLOC(uint8_t, SHA_DIGEST_LENGTH);
-                       if (!digest) {
-                               ldns_rr_free(ds);
-                               return NULL;
-                       }
+       default:
+       case LDNS_SHA1:
+               digest = LDNS_XMALLOC(uint8_t, SHA_DIGEST_LENGTH);
+               if (!digest) {
+                       ldns_rr_free(ds);
+                       return NULL;
+               }
                break;
-               case LDNS_SHA256:
-                       #ifdef SHA256_DIGEST_LENGTH
-                       digest = LDNS_XMALLOC(uint8_t, SHA256_DIGEST_LENGTH);
-                       if (!digest) {
-                               ldns_rr_free(ds);
-                               return NULL;
-                       }
-                       #else
+       case LDNS_SHA256:
+#ifdef SHA256_DIGEST_LENGTH
+               digest = LDNS_XMALLOC(uint8_t, SHA256_DIGEST_LENGTH);
+               if (!digest) {
+                       ldns_rr_free(ds);
                        return NULL;
-                       #endif
+               }
+#else
+               return NULL;
+#endif
                break;
        }
 
@@ -2060,8 +2057,8 @@ ldns_key_rr2ds(const ldns_rr *key, ldns_hash h)
 
        /* digest */
        /* owner name */
-        tmp = ldns_rdf_clone(ldns_rr_owner(key));
-        ldns_dname2canonical(tmp);
+       tmp = ldns_rdf_clone(ldns_rr_owner(key));
+       ldns_dname2canonical(tmp);
        if (ldns_rdf2buffer_wire(data_buf, tmp) != LDNS_STATUS_OK) {
                LDNS_FREE(digest);
                ldns_buffer_free(data_buf);
@@ -2079,23 +2076,23 @@ ldns_key_rr2ds(const ldns_rr *key, ldns_hash h)
                return NULL;
        }
        switch(h) {
-               case LDNS_SHA1:
+       case LDNS_SHA1:
                (void) SHA1((unsigned char *) ldns_buffer_begin(data_buf),
-                               ldns_buffer_position(data_buf),
-                               (unsigned char*) digest);
+                                 ldns_buffer_position(data_buf),
+                                 (unsigned char*) digest);
 
                tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX, SHA_DIGEST_LENGTH,
-                               digest);
+                                                          digest);
                ldns_rr_push_rdf(ds, tmp);
 
                break;
-               case LDNS_SHA256:
+       case LDNS_SHA256:
 #ifdef SHA256_DIGEST_LENGTH
                (void) SHA256((unsigned char *) ldns_buffer_begin(data_buf),
-                           ldns_buffer_position(data_buf),
-                           (unsigned char*) digest);
+                                   ldns_buffer_position(data_buf),
+                                   (unsigned char*) digest);
                tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX, SHA256_DIGEST_LENGTH,
-                               digest);
+                                                          digest);
                ldns_rr_push_rdf(ds, tmp);
 #endif
                break;
@@ -2150,7 +2147,7 @@ ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys)
                label_count--;
                for (i = 0; i < ldns_rr_list_rr_count(rrset_clone); i++) {
                        new_owner = ldns_dname_cat_clone(wildcard_label, 
-                                       ldns_dname_left_chop(ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i))));
+                                                                          ldns_dname_left_chop(ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i))));
                        ldns_rr_set_owner(ldns_rr_list_rr(rrset_clone, i), new_owner);
                }
        }
@@ -2165,17 +2162,30 @@ ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys)
        ldns_rr_list_sort(rrset_clone);
        
        for (key_count = 0; key_count < ldns_key_list_key_count(keys); key_count++) {
+               if (!ldns_key_use(ldns_key_list_key(keys, key_count))) {
+                       continue;
+               }
                sign_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
+               if (!sign_buf) {
+                       printf("[XX]ERROR NO SIGN BUG, OUT OF MEM?\n");
+                       ldns_rr_list_print(stdout, rrset_clone);
+                       while(true) {
+                               sleep(1);
+                               printf(".");
+                               fflush(stdout);
+                       }
+                       exit(123);
+               }
                b64rdf = NULL;
 
                current_key = ldns_key_list_key(keys, key_count);
                /* sign all RRs with keys that have ZSKbit, !SEPbit.
                   sign DNSKEY RRs with keys that have ZSKbit&SEPbit */
                if (
-                       ldns_key_flags(current_key) & LDNS_KEY_ZONE_KEY &&
-                       (!(ldns_key_flags(current_key) & LDNS_KEY_SEP_KEY) ||
+                   ldns_key_flags(current_key) & LDNS_KEY_ZONE_KEY &&
+                   (!(ldns_key_flags(current_key) & LDNS_KEY_SEP_KEY) ||
                        ldns_rr_get_type(ldns_rr_list_rr(rrset, 0)) == LDNS_RR_TYPE_DNSKEY)
-                  ) {
+                   ) {
                        current_sig = ldns_rr_new_frm_type(LDNS_RR_TYPE_RRSIG);
                        
                        /* set the type on the new signature */
@@ -2183,54 +2193,54 @@ ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys)
 
                        ldns_rr_set_ttl(current_sig, orig_ttl);
                        ldns_rr_set_owner(current_sig, 
-                                       ldns_rdf_clone(ldns_rr_owner(ldns_rr_list_rr(rrset_clone, 0))));
+                                                  ldns_rdf_clone(ldns_rr_owner(ldns_rr_list_rr(rrset_clone, 0))));
 
                        /* fill in what we know of the signature */
 
                        /* set the orig_ttl */
                        (void)ldns_rr_rrsig_set_origttl(current_sig, 
-                                       ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, orig_ttl));
+                                                                         ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, orig_ttl));
                        /* the signers name */
 
                        (void)ldns_rr_rrsig_set_signame(current_sig, 
-                                       ldns_rdf_clone(ldns_key_pubkey_owner(current_key)));
+                                                                         ldns_rdf_clone(ldns_key_pubkey_owner(current_key)));
                        /* label count - get it from the first rr in the rr_list */
                        (void)ldns_rr_rrsig_set_labels(current_sig, 
-                                       ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, label_count));
+                                                                        ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, label_count));
                        /* inception, expiration */
                        now = time(NULL);
                        if (ldns_key_inception(current_key) != 0) {
                                (void)ldns_rr_rrsig_set_inception(current_sig,
-                                               ldns_native2rdf_int32(LDNS_RDF_TYPE_TIME, 
-                                                       ldns_key_inception(current_key)));
+                                                                                   ldns_native2rdf_int32(LDNS_RDF_TYPE_TIME, 
+                                                                                                                        ldns_key_inception(current_key)));
                        } else {
                                (void)ldns_rr_rrsig_set_inception(current_sig,
-                                               ldns_native2rdf_int32(LDNS_RDF_TYPE_TIME, now));
+                                                                                   ldns_native2rdf_int32(LDNS_RDF_TYPE_TIME, now));
                        }
                        if (ldns_key_expiration(current_key) != 0) {
                                (void)ldns_rr_rrsig_set_expiration(current_sig,
-                                               ldns_native2rdf_int32(LDNS_RDF_TYPE_TIME, 
-                                                       ldns_key_expiration(current_key)));
+                                                                                       ldns_native2rdf_int32(LDNS_RDF_TYPE_TIME, 
+                                                                                                                         ldns_key_expiration(current_key)));
                        } else {
                                (void)ldns_rr_rrsig_set_expiration(current_sig,
-                                               ldns_native2rdf_int32(LDNS_RDF_TYPE_TIME, 
-                                                       now + LDNS_DEFAULT_EXP_TIME));
+                                                                                       ldns_native2rdf_int32(LDNS_RDF_TYPE_TIME, 
+                                                                                                                         now + LDNS_DEFAULT_EXP_TIME));
                        }
 
                        /* key-tag */
-/*printf("SETTING KEYTAG TO: %u\n", ldns_key_keytag(current_key));*/
+                       /*printf("SETTING KEYTAG TO: %u\n", ldns_key_keytag(current_key));*/
                        (void)ldns_rr_rrsig_set_keytag(current_sig,
-                                       ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, 
-                                               ldns_key_keytag(current_key)));
+                                                                        ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, 
+                                                                                                          ldns_key_keytag(current_key)));
 
                        /* algorithm - check the key and substitute that */
                        (void)ldns_rr_rrsig_set_algorithm(current_sig,
-                                       ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG, 
-                                               ldns_key_algorithm(current_key)));
+                                                                           ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG, 
+                                                                                                               ldns_key_algorithm(current_key)));
                        /* type-covered */
                        (void)ldns_rr_rrsig_set_typecovered(current_sig,
-                                       ldns_native2rdf_int16(LDNS_RDF_TYPE_TYPE,
-                                               ldns_rr_get_type(ldns_rr_list_rr(rrset_clone, 0))));
+                                                                                ldns_native2rdf_int16(LDNS_RDF_TYPE_TYPE,
+                                                                                                                  ldns_rr_get_type(ldns_rr_list_rr(rrset_clone, 0))));
                        /* right now, we have: a key, a semi-sig and an rrset. For
                         * which we can create the sig and base64 encode that and
                         * add that to the signature */
@@ -2314,7 +2324,7 @@ ldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key)
        }
        
        sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(to_sign),
-                       ldns_buffer_position(to_sign), NULL);
+                                 ldns_buffer_position(to_sign), NULL);
        if (!sha1_hash) {
                ldns_buffer_free(b64sig);
                return NULL;
@@ -2373,18 +2383,18 @@ ldns_sign_public_evp(ldns_buffer *to_sign, EVP_PKEY *key, const EVP_MD *digest_t
        r = EVP_SignInit(&ctx, md_type);
        if(r == 1)
                r = EVP_SignUpdate(&ctx, (unsigned char*)
-                       ldns_buffer_begin(to_sign), 
-                       ldns_buffer_position(to_sign));
+                                           ldns_buffer_begin(to_sign), 
+                                           ldns_buffer_position(to_sign));
        if(r == 1)
                r = EVP_SignFinal(&ctx, (unsigned char*)
-                       ldns_buffer_begin(b64sig), &siglen, key);
+                                          ldns_buffer_begin(b64sig), &siglen, key);
        if(r != 1) {
                ldns_buffer_free(b64sig);
                return NULL;
        }
 
        sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen,
-                       ldns_buffer_begin(b64sig));
+                                                                ldns_buffer_begin(b64sig));
        ldns_buffer_free(b64sig);
        EVP_MD_CTX_cleanup(&ctx);
        return sigdata_rdf;
@@ -2407,21 +2417,25 @@ ldns_sign_public_rsasha1(ldns_buffer *to_sign, RSA *key)
        }
 
        sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(to_sign),
-                       ldns_buffer_position(to_sign), NULL);
+                                 ldns_buffer_position(to_sign), NULL);
        if (!sha1_hash) {
                ldns_buffer_free(b64sig);
                return NULL;
        }
 
        result = RSA_sign(NID_sha1, sha1_hash, SHA_DIGEST_LENGTH,
-                       (unsigned char*)ldns_buffer_begin(b64sig),
-                       &siglen, key);
+                                  (unsigned char*)ldns_buffer_begin(b64sig),
+                                  &siglen, key);
+       if (result != 1) {
+               return NULL;
+       }
+
        if (result != 1) {
                return NULL;
        }
 
        sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen, 
-                       ldns_buffer_begin(b64sig));
+                                                                ldns_buffer_begin(b64sig));
        ldns_buffer_free(b64sig); /* can't free this buffer ?? */
        return sigdata_rdf;
 }
@@ -2440,43 +2454,32 @@ ldns_sign_public_rsamd5(ldns_buffer *to_sign, RSA *key)
        }
        
        md5_hash = MD5((unsigned char*)ldns_buffer_begin(to_sign),
-                       ldns_buffer_position(to_sign), NULL);
+                               ldns_buffer_position(to_sign), NULL);
        if (!md5_hash) {
                ldns_buffer_free(b64sig);
                return NULL;
        }
 
        RSA_sign(NID_md5, md5_hash, MD5_DIGEST_LENGTH,
-                       (unsigned char*)ldns_buffer_begin(b64sig),
-                       &siglen, key);
+                   (unsigned char*)ldns_buffer_begin(b64sig),
+                   &siglen, key);
 
        sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen, 
-                       ldns_buffer_begin(b64sig));
+                                                                ldns_buffer_begin(b64sig));
        ldns_buffer_free(b64sig);
        return sigdata_rdf;
 }
 
-ldns_rr *
-ldns_create_nsec(ldns_rdf *cur_owner, ldns_rdf *next_owner, ldns_rr_list *rrs)
+ldns_rdf *
+ldns_dnssec_create_nsec_bitmap(ldns_rr_type rr_type_list[],
+                                                size_t size,
+                                                ldns_rr_type nsec_type)
 {
-       /* we do not do any check here - garbage in, garbage out */
-       
-       /* the the start and end names - get the type from the
-        * before rrlist */
-
-       /* we don't have an nsec encoder... :( */
-
-       /* inefficient, just give it a name, a next name, and a list of rrs */
-       /* we make 1 big uberbitmap first, then windows */
-       /* todo: make something more efficient :) */
-       uint16_t i;
-       ldns_rr *i_rr;
-
-       uint8_t *bitmap = LDNS_XMALLOC(uint8_t, 2);
+       size_t i;
+       uint8_t *bitmap;
        uint16_t bm_len = 0;
        uint16_t i_type;
-
-       ldns_rr *nsec = NULL;
+       ldns_rdf *bitmap_rdf;
 
        uint8_t *data = NULL;
        uint8_t cur_data[32];
@@ -2484,51 +2487,36 @@ ldns_create_nsec(ldns_rdf *cur_owner, ldns_rdf *next_owner, ldns_rr_list *rrs)
        uint8_t cur_window_max = 0;
        uint16_t cur_data_size = 0;
 
-       nsec = ldns_rr_new();
-       ldns_rr_set_type(nsec, LDNS_RR_TYPE_NSEC);
-       ldns_rr_set_owner(nsec, ldns_rdf_clone(cur_owner));
-       /* TODO: TTL jelte? */
-       ldns_rr_push_rdf(nsec, ldns_rdf_clone(next_owner));
-
-       bitmap[0] = 0;
-       for (i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
-               i_rr = ldns_rr_list_rr(rrs, i);
+       if (nsec_type != LDNS_RR_TYPE_NSEC &&
+           nsec_type != LDNS_RR_TYPE_NSEC3) {
+               return NULL;
+       }
 
-               if (ldns_rdf_compare(cur_owner,
-                                        ldns_rr_owner(i_rr)) == 0) {
-                       /* add type to bitmap */
-                       i_type = ldns_rr_get_type(i_rr);
-                       if ((i_type / 8) + 1 > bm_len) {
-                               bitmap = LDNS_XREALLOC(bitmap, uint8_t, (i_type / 8) + 2);
-                               /* set to 0 */
-                               for (; bm_len <= i_type / 8; bm_len++) {
-                                       bitmap[bm_len] = 0;
-                               }
-                       }
-                       ldns_set_bit(bitmap + (int) i_type / 8, (int) (7 - (i_type % 8)), true);
-               }
+       /* the types in the list should be orders, lowest first,
+          so the last one contains the highest type */
+       i_type = rr_type_list[size-1];
+       if (i_type < nsec_type) {
+               i_type = nsec_type;
        }
-       /* add NSEC and RRSIG anyway */
-       i_type = LDNS_RR_TYPE_RRSIG;
-       if (i_type / 8 > bm_len) {
-               bitmap = LDNS_XREALLOC(bitmap, uint8_t, (i_type / 8) + 2);
-               /* set to 0 */
-               for (; bm_len <= i_type / 8; bm_len++) {
-                       bitmap[bm_len] = 0;
-               }
+       bm_len = i_type / 8 + 2;
+       bitmap = LDNS_XMALLOC(uint8_t, bm_len);
+       for (i = 0; i < bm_len; i++) {
+               bitmap[i] = 0;
        }
-       ldns_set_bit(bitmap + (int) i_type / 8, (int) (7 - (i_type % 8)), true);
-       i_type = LDNS_RR_TYPE_NSEC;
 
-       if (i_type / 8 > bm_len) {
-               bitmap = LDNS_XREALLOC(bitmap, uint8_t, (i_type / 8) + 2);
-               /* set to 0 */
-               for (; bm_len <= i_type / 8; bm_len++) {
-                       bitmap[bm_len] = 0;
-               }
+       for (i = 0; i < size; i++) {
+               i_type = rr_type_list[i];
+               ldns_set_bit(bitmap + (int) i_type / 8, (int) (7 - (i_type % 8)), true);
        }
+       /* always add nsec (if this is not nsec3 and rrsig */
+       i_type = LDNS_RR_TYPE_RRSIG;
        ldns_set_bit(bitmap + (int) i_type / 8, (int) (7 - (i_type % 8)), true);
+       i_type = nsec_type;
+       if (i_type != LDNS_RR_TYPE_NSEC3) {
+               ldns_set_bit(bitmap + (int) i_type / 8, (int) (7 - (i_type % 8)), true);
+       }
 
+       /* fold it into windows TODO: can this be done directly? */
        memset(cur_data, 0, 32);
        for (i = 0; i < bm_len; i++) {
                if (i / 32 > cur_window) {
@@ -2553,22 +2541,215 @@ ldns_create_nsec(ldns_rdf *cur_owner, ldns_rdf *next_owner, ldns_rr_list *rrs)
        }
        if (cur_window_max > 0) {
                /* this window has stuff, add it */
-               data = LDNS_XREALLOC(data, uint8_t, cur_data_size + cur_window_max + 3);
+               data = LDNS_XREALLOC(data,
+                                                uint8_t,
+                                                cur_data_size + cur_window_max + 3);
                data[cur_data_size] = cur_window;
                data[cur_data_size + 1] = cur_window_max + 1;
                memcpy(data + cur_data_size + 2, cur_data, cur_window_max+1);
                cur_data_size += cur_window_max + 3;
        }
-
-       ldns_rr_push_rdf(nsec, ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC, cur_data_size, data));
+       
+       bitmap_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC,
+                                                               cur_data_size,
+                                                               data);
 
        LDNS_FREE(bitmap);
        LDNS_FREE(data);
-       return nsec;
+
+       return bitmap_rdf;
 }
 
-ldns_rdf *
-ldns_nsec3_hash_name(ldns_rdf *name, uint8_t algorithm, uint16_t iterations, uint8_t salt_length, uint8_t *salt)
+ldns_rr *
+ldns_dnssec_create_nsec(ldns_dnssec_name *from, ldns_dnssec_name *to, ldns_rr_type nsec_type)
+{
+       ldns_rr *nsec_rr;
+       ldns_rr_type types[1024];
+       size_t type_count = 0;
+       ldns_dnssec_rrsets *cur_rrsets;
+
+       if (!from || !to || (nsec_type != LDNS_RR_TYPE_NSEC &&
+                                        nsec_type != LDNS_RR_TYPE_NSEC3)) {
+               return NULL;
+       }
+
+       nsec_rr = ldns_rr_new();
+       ldns_rr_set_type(nsec_rr, nsec_type);
+       ldns_rr_set_owner(nsec_rr, ldns_rdf_clone(ldns_dnssec_name_name(from)));
+       ldns_rr_push_rdf(nsec_rr, ldns_rdf_clone(ldns_dnssec_name_name(to)));
+
+       cur_rrsets = from->rrsets;
+       while (cur_rrsets) {
+               types[type_count] = cur_rrsets->type;
+               type_count++;
+               cur_rrsets = cur_rrsets->next;
+       }
+
+       ldns_rr_push_rdf(nsec_rr, ldns_dnssec_create_nsec_bitmap(types,
+                                                                                                 type_count,
+                                                                                                 nsec_type));
+
+       return nsec_rr;
+}
+
+ldns_rr *
+ldns_dnssec_create_nsec3(ldns_dnssec_name *from,
+                                       ldns_dnssec_name *to,
+                                       ldns_rdf *zone_name,
+                                       uint8_t algorithm,
+                                       uint8_t flags,
+                                       uint16_t iterations,
+                                       uint8_t salt_length,
+                                       uint8_t *salt)
+{
+       ldns_rr *nsec_rr;
+       ldns_rr_type types[1024];
+       size_t type_count = 0;
+       ldns_dnssec_rrsets *cur_rrsets;
+       ldns_status status;
+
+       flags = flags;
+
+       if (!from || !to) {
+               return NULL;
+       }
+
+       nsec_rr = ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3);
+       ldns_rr_set_owner(nsec_rr, ldns_nsec3_hash_name(ldns_dnssec_name_name(from), algorithm, iterations, salt_length, salt));
+       /*      ldns_rr_push_rdf(nsec_rr, ldns_rdf_clone(ldns_dnssec_name_name(to)));*/
+       status = ldns_dname_cat(ldns_rr_owner(nsec_rr), zone_name);
+       ldns_nsec3_add_param_rdfs(nsec_rr, algorithm, flags, iterations, salt_length, salt);
+
+       /* XXX why the next? */
+       cur_rrsets = from->rrsets;
+       while (cur_rrsets) {
+               types[type_count] = cur_rrsets->type;
+               type_count++;
+               cur_rrsets = cur_rrsets->next;
+       }
+
+       ldns_rr_set_rdf(nsec_rr, NULL, 4);
+       ldns_rr_set_rdf(nsec_rr,
+                                ldns_dnssec_create_nsec_bitmap(types,
+                                                                                 type_count,
+                                                                                 LDNS_RR_TYPE_NSEC3), 5);
+
+       return nsec_rr;
+}
+
+ldns_rr *
+ldns_create_nsec(ldns_rdf *cur_owner, ldns_rdf *next_owner, ldns_rr_list *rrs)
+{
+       /* we do not do any check here - garbage in, garbage out */
+       
+       /* the the start and end names - get the type from the
+        * before rrlist */
+
+       /* we don't have an nsec encoder... :( */
+
+       /* inefficient, just give it a name, a next name, and a list of rrs */
+       /* we make 1 big uberbitmap first, then windows */
+       /* todo: make something more efficient :) */
+       uint16_t i;
+       ldns_rr *i_rr;
+
+       uint8_t *bitmap = LDNS_XMALLOC(uint8_t, 2);
+       uint16_t bm_len = 0;
+       uint16_t i_type;
+
+       ldns_rr *nsec = NULL;
+
+       uint8_t *data = NULL;
+       uint8_t cur_data[32];
+       uint8_t cur_window = 0;
+       uint8_t cur_window_max = 0;
+       uint16_t cur_data_size = 0;
+
+       nsec = ldns_rr_new();
+       ldns_rr_set_type(nsec, LDNS_RR_TYPE_NSEC);
+       ldns_rr_set_owner(nsec, ldns_rdf_clone(cur_owner));
+       /* TODO: TTL jelte? */
+       ldns_rr_push_rdf(nsec, ldns_rdf_clone(next_owner));
+
+       bitmap[0] = 0;
+       for (i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
+               i_rr = ldns_rr_list_rr(rrs, i);
+
+               if (ldns_rdf_compare(cur_owner,
+                                                ldns_rr_owner(i_rr)) == 0) {
+                       /* add type to bitmap */
+                       i_type = ldns_rr_get_type(i_rr);
+                       if ((i_type / 8) + 1 > bm_len) {
+                               bitmap = LDNS_XREALLOC(bitmap, uint8_t, (i_type / 8) + 2);
+                               /* set to 0 */
+                               for (; bm_len <= i_type / 8; bm_len++) {
+                                       bitmap[bm_len] = 0;
+                               }
+                       }
+                       ldns_set_bit(bitmap + (int) i_type / 8, (int) (7 - (i_type % 8)), true);
+               }
+       }
+       /* add NSEC and RRSIG anyway */
+       i_type = LDNS_RR_TYPE_RRSIG;
+       if (i_type / 8 > bm_len) {
+               bitmap = LDNS_XREALLOC(bitmap, uint8_t, (i_type / 8) + 2);
+               /* set to 0 */
+               for (; bm_len <= i_type / 8; bm_len++) {
+                       bitmap[bm_len] = 0;
+               }
+       }
+       ldns_set_bit(bitmap + (int) i_type / 8, (int) (7 - (i_type % 8)), true);
+       i_type = LDNS_RR_TYPE_NSEC;
+
+       if (i_type / 8 > bm_len) {
+               bitmap = LDNS_XREALLOC(bitmap, uint8_t, (i_type / 8) + 2);
+               /* set to 0 */
+               for (; bm_len <= i_type / 8; bm_len++) {
+                       bitmap[bm_len] = 0;
+               }
+       }
+       ldns_set_bit(bitmap + (int) i_type / 8, (int) (7 - (i_type % 8)), true);
+
+       memset(cur_data, 0, 32);
+       for (i = 0; i < bm_len; i++) {
+               if (i / 32 > cur_window) {
+                       /* check, copy, new */
+                       if (cur_window_max > 0) {
+                               /* this window has stuff, add it */
+                               data = LDNS_XREALLOC(data, uint8_t, cur_data_size + cur_window_max + 3);
+                               data[cur_data_size] = cur_window;
+                               data[cur_data_size + 1] = cur_window_max + 1;
+                               memcpy(data + cur_data_size + 2, cur_data, cur_window_max+1);
+                               cur_data_size += cur_window_max + 3;
+                       }
+                       cur_window++;
+                       cur_window_max = 0;
+                       memset(cur_data, 0, 32);
+               } else {
+                       cur_data[i%32] = bitmap[i];
+                       if (bitmap[i] > 0) {
+                               cur_window_max = i%32;
+                       }
+               }
+       }
+       if (cur_window_max > 0) {
+               /* this window has stuff, add it */
+               data = LDNS_XREALLOC(data, uint8_t, cur_data_size + cur_window_max + 3);
+               data[cur_data_size] = cur_window;
+               data[cur_data_size + 1] = cur_window_max + 1;
+               memcpy(data + cur_data_size + 2, cur_data, cur_window_max+1);
+               cur_data_size += cur_window_max + 3;
+       }
+
+       ldns_rr_push_rdf(nsec, ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC, cur_data_size, data));
+
+       LDNS_FREE(bitmap);
+       LDNS_FREE(data);
+       return nsec;
+}
+
+ldns_rdf *
+ldns_nsec3_hash_name(ldns_rdf *name, uint8_t algorithm, uint16_t iterations, uint8_t salt_length, uint8_t *salt)
 {
        char *orig_owner_str;
        size_t hashed_owner_str_len;
@@ -2588,7 +2769,7 @@ ldns_nsec3_hash_name(ldns_rdf *name, uint8_t algorithm, uint16_t iterations, uin
        
        hashed_owner_str_len = salt_length + ldns_rdf_size(name);
        hashed_owner_str = LDNS_XMALLOC(char, hashed_owner_str_len);
-        memcpy(hashed_owner_str, ldns_rdf_data(name), ldns_rdf_size(name));
+       memcpy(hashed_owner_str, ldns_rdf_data(name), ldns_rdf_size(name));
        memcpy(hashed_owner_str + ldns_rdf_size(name), salt, salt_length);
 
        for (cur_it = iterations + 1; cur_it > 0; cur_it--) {
@@ -2621,7 +2802,7 @@ ldns_nsec3_hash_name(ldns_rdf *name, uint8_t algorithm, uint16_t iterations, uin
                exit(4);
        }
        hashed_owner_str_len = hashed_owner_b32_len;
-        hashed_owner_b32[hashed_owner_b32_len] = '\0';
+       hashed_owner_b32[hashed_owner_b32_len] = '\0';
 
        status = ldns_str2rdf_dname(&hashed_owner, hashed_owner_b32);
        if (status != LDNS_STATUS_OK) {
@@ -2635,11 +2816,11 @@ ldns_nsec3_hash_name(ldns_rdf *name, uint8_t algorithm, uint16_t iterations, uin
 
 void
 ldns_nsec3_add_param_rdfs(ldns_rr *rr,
-                           uint8_t algorithm, 
-                           uint8_t flags,
-                           uint16_t iterations,
-                           uint8_t salt_length,
-                           uint8_t *salt)
+                                        uint8_t algorithm, 
+                                        uint8_t flags,
+                                        uint16_t iterations,
+                                        uint8_t salt_length,
+                                        uint8_t *salt)
 {
        ldns_rdf *salt_rdf = NULL;
        uint8_t *salt_data = NULL;
@@ -2652,9 +2833,9 @@ ldns_nsec3_add_param_rdfs(ldns_rr *rr,
        salt_data[0] = salt_length;
        memcpy(salt_data + 1, salt, salt_length);
        salt_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC3_SALT, salt_length + 1, salt_data);
-       ldns_rr_set_rdf(rr,  salt_rdf, 3);
 
        ldns_rr_set_rdf(rr, salt_rdf, 3);
+       LDNS_FREE(salt_data);
 }
 
 /* this will NOT return the NSEC3  completed, you will have to run the
@@ -2688,17 +2869,17 @@ ldns_create_nsec3(ldns_rdf *cur_owner,
 
        ldns_status status;
        
-        /*
-        printf("HASH FOR: ");
-        ldns_rdf_print(stdout, cur_owner);
-        */
+       /*
+         printf("HASH FOR: ");
+         ldns_rdf_print(stdout, cur_owner);
+       */
        
        /*
-       printf("\n");
-       for (i=0; i<hashed_owner_str_len; i++) {
-               printf("%02x ", (uint8_t) hashed_owner_str[i]);
-       }
-       printf("\n");
+         printf("\n");
+         for (i=0; i<hashed_owner_str_len; i++) {
+         printf("%02x ", (uint8_t) hashed_owner_str[i]);
+         }
+         printf("\n");
        */
        hashed_owner = ldns_nsec3_hash_name(cur_owner, algorithm, iterations, salt_length, salt);
        status = ldns_dname_cat(hashed_owner, cur_zone);
@@ -2791,14 +2972,14 @@ ldns_create_nsec3(ldns_rdf *cur_owner,
        LDNS_FREE(bitmap);
        LDNS_FREE(data);
 
-/*
-printf(";; Created NSEC3 for:\n");
-printf(";; ");
-ldns_rdf_print(stdout, cur_owner);
-printf("\n");
-printf(";; ");
-ldns_rr_print(stdout, nsec);
-*/
+       /*
+         printf(";; Created NSEC3 for:\n");
+         printf(";; ");
+         ldns_rdf_print(stdout, cur_owner);
+         printf("\n");
+         printf(";; ");
+         ldns_rr_print(stdout, nsec);
+       */
        return nsec;
 }
 
@@ -2807,7 +2988,7 @@ ldns_nsec3_algorithm(const ldns_rr *nsec3_rr)
 {
        if (nsec3_rr && ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3 &&
            ldns_rdf_size(ldns_rr_rdf(nsec3_rr, 0)) > 0
-          ) {
+           ) {
                /*return ldns_rdf_data(ldns_rr_rdf(nsec3_rr, 0))[0];*/
                return ldns_rdf2native_int8(ldns_rr_rdf(nsec3_rr, 0));
        }
@@ -2819,7 +3000,7 @@ ldns_nsec3_flags(const ldns_rr *nsec3_rr)
 {
        if (nsec3_rr && ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3 &&
            ldns_rdf_size(ldns_rr_rdf(nsec3_rr, 1)) > 0
-          ) {
+           ) {
                /*return ldns_rdf_data(ldns_rr_rdf(nsec3_rr, 0))[0];*/
                return ldns_rdf2native_int8(ldns_rr_rdf(nsec3_rr, 0));
        }
@@ -2837,7 +3018,7 @@ ldns_nsec3_iterations(const ldns_rr *nsec3_rr)
 {
        if (nsec3_rr && ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3 &&
            ldns_rdf_size(ldns_rr_rdf(nsec3_rr, 2)) > 0
-          ) {
+           ) {
                return ldns_rdf2native_int16(ldns_rr_rdf(nsec3_rr, 2));
        }
        return 0;
@@ -2905,18 +3086,18 @@ ldns_nsec3_hash_name_frm_nsec3(const ldns_rr *nsec, ldns_rdf *name)
 {
        uint8_t algorithm;
        uint16_t iterations;
-/*     uint8_t *data;*/
+       /*      uint8_t *data;*/
        uint8_t salt_length;
        uint8_t *salt = 0;
-/*uint8_t salt_i;*/
+       /*uint8_t salt_i;*/
        
        ldns_rdf *hashed_owner;
 
-/*
-printf("NSEC RDF: ");
-ldns_rdf_print(stdout, ldns_rr_rdf(nsec, 0));
-printf("\n\n");
-*/
+       /*
+         printf("NSEC RDF: ");
+         ldns_rdf_print(stdout, ldns_rr_rdf(nsec, 0));
+         printf("\n\n");
+       */
        algorithm = ldns_nsec3_algorithm(nsec);
        salt_length = ldns_nsec3_salt_length(nsec);
        salt = ldns_nsec3_salt_data(nsec);
@@ -2924,13 +3105,13 @@ printf("\n\n");
        
        hashed_owner = ldns_nsec3_hash_name(name, algorithm, iterations, salt_length, salt);
        
-/*
-printf(";; Iterations: %u, Salt: ", iterations);
-for (salt_i = 0; salt_i < salt_length; salt_i++) {
-       printf("%02x", salt[salt_i]);
-}
-printf("\n");
-*/
+       /*
+         printf(";; Iterations: %u, Salt: ", iterations);
+         for (salt_i = 0; salt_i < salt_length; salt_i++) {
+         printf("%02x", salt[salt_i]);
+         }
+         printf("\n");
+       */
        LDNS_FREE(salt);
        return hashed_owner;
 }
@@ -2993,19 +3174,19 @@ ldns_nsec_covers_name(const ldns_rr *nsec, const ldns_rdf *name)
                return false;
        }
        
-/*
-printf("nsec coverage:\n");
-ldns_rdf_print(stdout, nsec_owner);
-printf(" <= \n");
-ldns_rdf_print(stdout, name);
-printf(" <  \n");
-ldns_rdf_print(stdout, nsec_next);
-printf("\n\n");
-*/
+       /*
+         printf("nsec coverage:\n");
+         ldns_rdf_print(stdout, nsec_owner);
+         printf(" <= \n");
+         ldns_rdf_print(stdout, name);
+         printf(" <  \n");
+         ldns_rdf_print(stdout, nsec_next);
+         printf("\n\n");
+       */
        /* in the case of the last nsec */
        if(ldns_dname_compare(nsec_owner, nsec_next) > 0) {
                result = (ldns_dname_compare(nsec_owner, name) <= 0 ||
-                         ldns_dname_compare(name, nsec_next) < 0);
+                               ldns_dname_compare(name, nsec_next) < 0);
        } else {
                result = (ldns_dname_compare(nsec_owner, name) <= 0 &&
                          ldns_dname_compare(name, nsec_next) < 0);
@@ -3018,7 +3199,7 @@ printf("\n\n");
 /* sig may be null - if so look in the packet */
 ldns_status
 ldns_pkt_verify(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, 
-               ldns_rr_list *k, ldns_rr_list *s, ldns_rr_list *good_keys)
+                        ldns_rr_list *k, ldns_rr_list *s, ldns_rr_list *good_keys)
 {
        ldns_rr_list *rrset;
        ldns_rr_list *sigs;
@@ -3043,7 +3224,7 @@ ldns_pkt_verify(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o,
        } else {
                /* otherwise get them from the packet */
                sigs = ldns_pkt_rr_list_by_name_and_type(p, o, LDNS_RR_TYPE_RRSIG, 
-                               LDNS_SECTION_ANY_NOQUESTION);
+                                                                                LDNS_SECTION_ANY_NOQUESTION);
                if (!sigs) {
                        /* no sigs */
                        return LDNS_STATUS_ERR;
@@ -3071,6 +3252,569 @@ ldns_pkt_verify(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o,
        return ldns_verify(rrset, sigs, k, good_keys);
 }
 
+ldns_rr_list *
+ldns_zone_create_nsecs(const ldns_zone *zone, ldns_rr_list *orig_zone_rrs, ldns_rr_list *glue_rrs)
+{
+       ldns_rr_list *nsec_rrs = ldns_rr_list_new();
+       ldns_rdf *start_dname = NULL;
+       ldns_rdf *next_dname = NULL;
+       ldns_rdf *cur_dname = NULL;
+
+       ldns_rr *nsec = NULL;
+       ldns_rr *next_rr = NULL;
+       size_t i;
+
+       /* add nsecs */
+       for (i = 0; i < ldns_rr_list_rr_count(orig_zone_rrs); i++) {
+               if (!start_dname) {
+                       /*start_dname = ldns_rr_owner(ldns_zone_soa(zone));*/
+                       start_dname = ldns_rr_owner(ldns_rr_list_rr(orig_zone_rrs, i));
+                       cur_dname = start_dname;
+               } else {
+                       next_rr = ldns_rr_list_rr(orig_zone_rrs, i);
+                       next_dname = ldns_rr_owner(next_rr);
+                       if (ldns_rdf_compare(cur_dname, next_dname) != 0) {
+                               /* skip glue */
+                               if (ldns_rr_list_contains_rr(glue_rrs, next_rr)) {
+                                       cur_dname = next_dname;
+                               } else {
+                                       nsec = ldns_create_nsec(cur_dname, 
+                                                                           next_dname,
+                                                                           orig_zone_rrs);
+                                       ldns_rr_set_ttl(nsec, ldns_rdf2native_int32(ldns_rr_rdf(ldns_zone_soa(zone), 6)));
+                                       ldns_rr_list_push_rr(nsec_rrs, nsec);
+                                       /*start_dname = next_dname;*/
+                                       cur_dname = next_dname;
+                               }
+                       }
+               }
+       }
+       nsec = ldns_create_nsec(cur_dname, 
+                                           start_dname,
+                                           orig_zone_rrs);
+       ldns_rr_list_push_rr(nsec_rrs, nsec);
+       ldns_rr_set_ttl(nsec, ldns_rdf2native_int32(ldns_rr_rdf(ldns_zone_soa(zone), 6)));
+
+       return nsec_rrs;
+}
+
+
+/* return a clone of the given list without RRSIGS and NSEC(3)'s */
+/* if removed_rrs is not null, push clones of sigs and nsecs there */
+ldns_rr_list *
+ldns_rr_list_strip_dnssec(ldns_rr_list *rr_list, ldns_rr_list *removed_rrs)
+{
+       size_t i;
+       ldns_rr_list *new_list;
+       ldns_rr *cur_rr;
+       
+       if (!rr_list) {
+               return NULL;
+       }
+
+       new_list = ldns_rr_list_new();
+
+       for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
+               cur_rr = ldns_rr_list_rr(rr_list, i);
+               if (ldns_rr_get_type(cur_rr) != LDNS_RR_TYPE_RRSIG &&
+                   ldns_rr_get_type(cur_rr) != LDNS_RR_TYPE_NSEC &&
+                   ldns_rr_get_type(cur_rr) != LDNS_RR_TYPE_NSEC3) {
+                       ldns_rr_list_push_rr(new_list, ldns_rr_clone(cur_rr));
+               } else {
+                       if (removed_rrs) {
+                               ldns_rr_list_push_rr(removed_rrs, ldns_rr_clone(cur_rr));
+                       }
+               }
+       }
+
+       return new_list;
+}
+
+ldns_status
+ldns_dnssec_chain_nsec3_list(ldns_rr_list *nsec3_rrs)
+{
+       size_t i;
+       char *next_nsec_owner_str;
+       ldns_rdf *next_nsec_owner_label;
+       ldns_rdf *next_nsec_rdf;
+       ldns_status status = LDNS_STATUS_OK;
+
+       for (i = 0; i < ldns_rr_list_rr_count(nsec3_rrs); i++) {
+               if (i == ldns_rr_list_rr_count(nsec3_rrs) - 1) {
+                       next_nsec_owner_label = ldns_dname_label(ldns_rr_owner(ldns_rr_list_rr(nsec3_rrs, 0)), 0);
+                       next_nsec_owner_str = ldns_rdf2str(next_nsec_owner_label);
+                       if (next_nsec_owner_str[strlen(next_nsec_owner_str) - 1] == '.') {
+                               next_nsec_owner_str[strlen(next_nsec_owner_str) - 1] = '\0';
+                       }
+                       status = ldns_str2rdf_b32_ext(&next_nsec_rdf, next_nsec_owner_str);
+                       if (!ldns_rr_set_rdf(ldns_rr_list_rr(nsec3_rrs, i), next_nsec_rdf, 4)) {
+                               /* todo: error */
+                       }
+
+                       ldns_rdf_deep_free(next_nsec_owner_label);
+                       LDNS_FREE(next_nsec_owner_str);
+               } else {
+                       next_nsec_owner_label = ldns_dname_label(ldns_rr_owner(ldns_rr_list_rr(nsec3_rrs, i + 1)), 0);
+                       next_nsec_owner_str = ldns_rdf2str(next_nsec_owner_label);
+                       if (next_nsec_owner_str[strlen(next_nsec_owner_str) - 1] == '.') {
+                               next_nsec_owner_str[strlen(next_nsec_owner_str) - 1] = '\0';
+                       }
+                       status = ldns_str2rdf_b32_ext(&next_nsec_rdf, next_nsec_owner_str);
+                       ldns_rdf_deep_free(next_nsec_owner_label);
+                       LDNS_FREE(next_nsec_owner_str);
+                       if (!ldns_rr_set_rdf(ldns_rr_list_rr(nsec3_rrs, i), next_nsec_rdf, 4)) {
+                               /* todo: error */
+                       }
+               }
+       }
+       return status;
+}
+
+static int
+qsort_rr_compare_nsec3(const void *a, const void *b)
+{
+       const ldns_rr *rr1 = * (const ldns_rr **) a;
+       const ldns_rr *rr2 = * (const ldns_rr **) b;
+       if (rr1 == NULL && rr2 == NULL) {
+               return 0;
+       }
+       if (rr1 == NULL) {
+               return -1;
+       } 
+       if (rr2 == NULL) {
+               return 1;
+       }
+       return ldns_rdf_compare(ldns_rr_owner(rr1), ldns_rr_owner(rr2));
+}
+
+void ldns_rr_list_sort_nsec3(ldns_rr_list *unsorted) {
+       qsort(unsorted->_rrs,
+             ldns_rr_list_rr_count(unsorted),
+             sizeof(ldns_rr *),
+             qsort_rr_compare_nsec3);
+}
+
+ldns_status
+ldns_dnssec_zone_create_nsec3s(ldns_dnssec_zone *zone,
+                                                ldns_rr_list *new_rrs,
+                                                uint8_t algorithm,
+                                                uint8_t flags,
+                                                uint16_t iterations,
+                                                uint8_t salt_length,
+                                                uint8_t *salt)
+{
+       ldns_rbnode_t *first_name_node;
+       ldns_rbnode_t *current_name_node;
+       ldns_dnssec_name *first_name;
+       ldns_dnssec_name *current_name;
+       ldns_status result = LDNS_STATUS_OK;
+       ldns_rr *nsec_rr;
+       ldns_rr_list *nsec3_list;
+       
+       if (!zone || !new_rrs || !zone->names) {
+               return LDNS_STATUS_ERR;
+       }
+
+       nsec3_list = ldns_rr_list_new();
+
+       first_name_node = ldns_rbtree_first(zone->names);
+       first_name = (ldns_dnssec_name *) first_name_node->data;
+       
+       current_name_node = first_name_node;
+       current_name = first_name;
+
+       while (ldns_rbtree_next(current_name_node) != LDNS_RBTREE_NULL) {
+               nsec_rr = ldns_dnssec_create_nsec3(current_name,
+                                                                       (ldns_dnssec_name *) ldns_rbtree_next(current_name_node)->data,
+                                                                    zone->soa->name,
+                                                                       algorithm,
+                                                                       flags,
+                                                                       iterations,
+                                                                       salt_length,
+                                                                       salt);
+               ldns_dnssec_name_add_rr(current_name, nsec_rr);
+               ldns_rr_list_push_rr(new_rrs, nsec_rr);
+               ldns_rr_list_push_rr(nsec3_list, nsec_rr);
+               current_name_node = ldns_rbtree_next(current_name_node);
+               current_name = (ldns_dnssec_name *) current_name_node->data;
+       }
+       nsec_rr = ldns_dnssec_create_nsec3(current_name,
+                                                            first_name,
+                                                               zone->soa->name,
+                                                               algorithm,
+                                                               flags,
+                                                               iterations,
+                                                               salt_length,
+                                                               salt);
+       result = ldns_dnssec_name_add_rr(current_name, nsec_rr);
+       ldns_rr_list_push_rr(new_rrs, nsec_rr);
+       ldns_rr_list_push_rr(nsec3_list, nsec_rr);
+
+       ldns_rr_list_sort_nsec3(nsec3_list);
+       ldns_dnssec_chain_nsec3_list(nsec3_list);
+       if (result != LDNS_STATUS_OK) {
+               return result;
+       }
+       
+       ldns_rr_list_free(nsec3_list);
+       return result;
+}
+
+ldns_status
+ldns_dnssec_zone_create_nsecs(ldns_dnssec_zone *zone,
+                                               ldns_rr_list *new_rrs,
+                                               ldns_rr_type nsec_type)
+{
+       ldns_rbnode_t *first_name_node;
+       ldns_rbnode_t *current_name_node;
+       ldns_dnssec_name *first_name;
+       ldns_dnssec_name *current_name;
+       ldns_status result = LDNS_STATUS_OK;
+       ldns_rr *nsec_rr;
+
+       if (!zone || !new_rrs || !zone->names) {
+               return LDNS_STATUS_ERR;
+       }
+
+       first_name_node = ldns_rbtree_first(zone->names);
+       first_name = (ldns_dnssec_name *) first_name_node->data;
+       
+       current_name_node = first_name_node;
+       current_name = first_name;
+
+       switch (nsec_type) {
+       case LDNS_RR_TYPE_NSEC:
+               while (ldns_rbtree_next(current_name_node) != LDNS_RBTREE_NULL) {
+                       nsec_rr = ldns_dnssec_create_nsec(current_name,
+                                                                           (ldns_dnssec_name *) ldns_rbtree_next(current_name_node)->data,
+                                                                           nsec_type);
+                       ldns_dnssec_name_add_rr(current_name, nsec_rr);
+                       ldns_rr_list_push_rr(new_rrs, nsec_rr);
+                       current_name_node = ldns_rbtree_next(current_name_node);
+                       current_name = (ldns_dnssec_name *) current_name_node->data;
+               }
+               nsec_rr = ldns_dnssec_create_nsec(current_name,
+                                                                   first_name,
+                                                                   nsec_type);
+               result = ldns_dnssec_name_add_rr(current_name, nsec_rr);
+               if (result != LDNS_STATUS_OK) {
+                       return result;
+               }
+               ldns_rr_list_push_rr(new_rrs, nsec_rr);
+               break;
+       case LDNS_RR_TYPE_NSEC3:
+               break;
+       default:
+               return LDNS_STATUS_ERR;
+       }
+
+       return result;
+}
+
+int
+ldns_dnssec_default_add_to_signatures(ldns_rr *sig, void *n)
+{
+       sig = sig;
+       n = n;
+       return LDNS_SIGNATURE_LEAVE_ADD_NEW;
+}
+
+int
+ldns_dnssec_default_leave_signatures(ldns_rr *sig, void *n)
+{
+       sig = sig;
+       n = n;
+       return LDNS_SIGNATURE_LEAVE_NO_ADD;
+}
+
+int
+ldns_dnssec_default_delete_signatures(ldns_rr *sig, void *n)
+{
+       sig = sig;
+       n = n;
+       return LDNS_SIGNATURE_REMOVE_NO_ADD;
+}
+
+int
+ldns_dnssec_default_replace_signatures(ldns_rr *sig, void *n)
+{
+       sig = sig;
+       n = n;
+       return LDNS_SIGNATURE_REMOVE_ADD_NEW;
+}
+
+ldns_dnssec_rrs *
+ldns_dnssec_remove_signatures(ldns_dnssec_rrs *signatures,
+                                               ldns_key_list *key_list,
+                                               int (*func)(ldns_rr *, void *),
+                                               void *arg) {
+       ldns_dnssec_rrs *base_rrs = signatures;
+       ldns_dnssec_rrs *cur_rr = base_rrs;
+       ldns_dnssec_rrs *prev_rr = NULL;
+       ldns_dnssec_rrs *next_rr;
+
+       uint16_t keytag;
+       size_t i;
+       int v;
+
+       key_list = key_list;
+
+       if (!cur_rr) {
+               switch(func(NULL, arg)) {
+               case LDNS_SIGNATURE_LEAVE_ADD_NEW:
+               case LDNS_SIGNATURE_REMOVE_ADD_NEW:
+               break;
+               case LDNS_SIGNATURE_LEAVE_NO_ADD:
+               case LDNS_SIGNATURE_REMOVE_NO_ADD:
+               ldns_key_list_set_use(key_list, false);
+               break;
+               default:
+                       fprintf(stderr, "[XX] unknown return value from callback\n");
+                       break;
+               }
+               return NULL;
+       }
+       v = func(cur_rr->rr, arg);
+
+       while (cur_rr) {
+               next_rr = cur_rr->next;
+               
+               switch (func(cur_rr->rr, arg)) {
+               case  LDNS_SIGNATURE_LEAVE_ADD_NEW:
+                       prev_rr = cur_rr;
+                       break;
+               case LDNS_SIGNATURE_LEAVE_NO_ADD:
+                       keytag = ldns_rdf2native_int16(ldns_rr_rrsig_keytag(cur_rr->rr));
+                       for (i = 0; i < ldns_key_list_key_count(key_list); i++) {
+                               if (ldns_key_keytag(ldns_key_list_key(key_list, i)) ==
+                                   keytag) {
+                                       ldns_key_set_use(ldns_key_list_key(key_list, i),
+                                                                 false);
+                               }
+                       }
+                       prev_rr = cur_rr;
+                       break;
+               case LDNS_SIGNATURE_REMOVE_NO_ADD:
+                       keytag = ldns_rdf2native_int16(ldns_rr_rrsig_keytag(cur_rr->rr));
+                       for (i = 0; i < ldns_key_list_key_count(key_list); i++) {
+                               if (ldns_key_keytag(ldns_key_list_key(key_list, i)) ==
+                                   keytag) {
+                                       ldns_key_set_use(ldns_key_list_key(key_list, i),
+                                                                 false);
+                               }
+                       }
+                       if (prev_rr) {
+                               prev_rr->next = next_rr;
+                       } else {
+                               base_rrs = next_rr;
+                       }
+                       LDNS_FREE(cur_rr);
+                       break;
+               case LDNS_SIGNATURE_REMOVE_ADD_NEW:
+                       if (prev_rr) {
+                               prev_rr->next = next_rr;
+                       } else {
+                               base_rrs = next_rr;
+                       }
+                       LDNS_FREE(cur_rr);
+                       break;
+               default:
+                       fprintf(stderr, "[XX] unknown return value from callback\n");
+                       break;
+               }
+               cur_rr = next_rr;
+       }
+
+       return base_rrs;
+}
+
+ldns_status
+ldns_dnssec_zone_create_rrsigs(ldns_dnssec_zone *zone,
+                                                ldns_rr_list *new_rrs,
+                                                ldns_key_list *key_list,
+                                                int (*func)(ldns_rr *, void*),
+                                                void *arg) {
+       ldns_status result = LDNS_STATUS_OK;
+       zone = zone;
+       new_rrs = new_rrs;
+       key_list = key_list;
+       //bool sign_list = true;
+       ldns_rbnode_t *cur_node;
+       ldns_rr_list *rr_list;
+
+       ldns_dnssec_name *cur_name;
+       ldns_dnssec_rrsets *cur_rrset;
+       ldns_dnssec_rrs *cur_rr;
+
+       ldns_rr_list *siglist;
+       
+       size_t i;
+
+       /* TODO: callback to see is list should be signed */
+       /* TODO: remove 'old' signatures from signature list */
+       cur_node = ldns_rbtree_first(zone->names);
+       while (cur_node != LDNS_RBTREE_NULL) {
+               cur_name = (ldns_dnssec_name *) cur_node->data;
+
+               cur_rrset = cur_name->rrsets;
+               while (cur_rrset) {
+                       /* reset keys to use */
+                       ldns_key_list_set_use(key_list, true);
+
+                       /* walk through old sigs, remove the old, and mark which keys (not) to use) */
+                       cur_rrset->signatures = ldns_dnssec_remove_signatures(cur_rrset->signatures,
+                                                                                                           key_list,
+                                                                                                           func,
+                                                                                                           arg);
+
+                       /* TODO: set count to zero? */
+                       rr_list = ldns_rr_list_new();
+
+                       cur_rr = cur_rrset->rrs;
+                       while (cur_rr) {
+                               ldns_rr_list_push_rr(rr_list, cur_rr->rr);
+                               cur_rr = cur_rr->next;
+                       }
+
+                       siglist = ldns_sign_public(rr_list, key_list);
+                       for (i = 0; i < ldns_rr_list_rr_count(siglist); i++) {
+                               if (cur_rrset->signatures) {
+                                       ldns_dnssec_rrs_add_rr(cur_rrset->signatures,
+                                                                          ldns_rr_list_rr(siglist, i));
+                               } else {
+                                       cur_rrset->signatures = ldns_dnssec_rrs_new();
+                                       cur_rrset->signatures->rr = ldns_rr_list_rr(siglist, i);
+                                       ldns_rr_list_push_rr(new_rrs, ldns_rr_list_rr(siglist, i));
+                               }
+                       }
+                       ldns_rr_list_free(siglist);
+                       ldns_rr_list_free(rr_list);
+
+                       cur_rrset = cur_rrset->next;
+               }
+
+               /* sign the nsec */
+               cur_name->nsec_signatures = ldns_dnssec_remove_signatures(cur_name->nsec_signatures,
+                                                                                                          key_list,
+                                                                                                          func,
+                                                                                                          arg);
+
+               rr_list = ldns_rr_list_new();
+               ldns_rr_list_push_rr(rr_list, cur_name->nsec);
+               siglist = ldns_sign_public(rr_list, key_list);
+               
+               for (i = 0; i < ldns_rr_list_rr_count(siglist); i++) {
+                       if (cur_name->nsec_signatures) {
+                               ldns_dnssec_rrs_add_rr(cur_name->nsec_signatures,
+                                                                  ldns_rr_list_rr(siglist, i));
+                       } else {
+                               cur_name->nsec_signatures = ldns_dnssec_rrs_new();
+                               cur_name->nsec_signatures->rr = ldns_rr_list_rr(siglist, i);
+                               ldns_rr_list_push_rr(new_rrs, ldns_rr_list_rr(siglist, i));
+                       }
+               }
+               ldns_rr_list_free(siglist);
+               ldns_rr_list_free(rr_list);
+
+               cur_node = ldns_rbtree_next(cur_node);
+       }
+
+       return result;
+}
+
+ldns_status
+ldns_dnssec_zone_sign(ldns_dnssec_zone *zone,
+                                 ldns_rr_list *new_rrs,
+                                 ldns_key_list *key_list,
+                                 int (*func)(ldns_rr *, void *),
+                                 void *arg)
+{
+       ldns_status result = LDNS_STATUS_OK;
+
+       if (!zone || !new_rrs || !key_list) {
+               return LDNS_STATUS_ERR;
+       }
+
+       /* zone is already sorted */
+       
+       /* check whether we need to add nsecs */
+       if (zone->names && !((ldns_dnssec_name *)zone->names->root->data)->nsec) {
+               result = ldns_dnssec_zone_create_nsecs(zone, new_rrs, LDNS_RR_TYPE_NSEC);
+               if (result != LDNS_STATUS_OK) {
+                       return result;
+               }
+       }
+
+       printf("[XX] Create signatures!\n");
+       result = ldns_dnssec_zone_create_rrsigs(zone,
+                                                                       new_rrs,
+                                                                       key_list,
+                                                                       func,
+                                                                       arg);
+       printf("[XX] done\n");
+
+       return result;
+}
+
+ldns_status
+ldns_dnssec_zone_sign_nsec3(ldns_dnssec_zone *zone,
+                                          ldns_rr_list *new_rrs,
+                                          ldns_key_list *key_list,
+                                          int (*func)(ldns_rr *, void *),
+                                          void *arg,
+                                          uint8_t algorithm,
+                                          uint8_t flags,
+                                          uint16_t iterations,
+                                          uint8_t salt_length,
+                                          uint8_t *salt)
+{
+       ldns_rr *nsec3, *nsec3params;
+       ldns_status result = LDNS_STATUS_OK;
+
+       /* TODO if there are already nsec3s presents and their
+        * parameters are the same as these, we don't have to recreate
+        */
+       if (zone->names) {
+               /* add empty nonterminals */
+               ldns_dnssec_zone_add_empty_nonterminals(zone);
+
+               nsec3 = ((ldns_dnssec_name *)zone->names->root->data)->nsec;
+               if (nsec3 && ldns_rr_get_type(nsec3) == LDNS_RR_TYPE_NSEC3) {
+                       // no need to recreate
+               } else {
+                       if (!ldns_dnssec_zone_find_rrset(zone,
+                                                                          zone->soa->name,
+                                                                          LDNS_RR_TYPE_NSEC3PARAMS)) {
+                               /* create and add the nsec3params rr */
+                               nsec3params = ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3PARAMS);
+                               ldns_rr_set_owner(nsec3params, ldns_rdf_clone(zone->soa->name));
+                               ldns_nsec3_add_param_rdfs(nsec3params, algorithm, flags, iterations, salt_length, salt);
+                               ldns_dnssec_zone_add_rr(zone, nsec3params);
+                               ldns_rr_list_push_rr(new_rrs, nsec3params);
+                       }
+                       result = ldns_dnssec_zone_create_nsec3s(zone,
+                                                                                       new_rrs,
+                                                                                       algorithm,
+                                                                                       flags,
+                                                                                       iterations,
+                                                                                       salt_length,
+                                                                                       salt);
+                       if (result != LDNS_STATUS_OK) {
+                               return result;
+                       }
+               }
+
+               result = ldns_dnssec_zone_create_rrsigs(zone,
+                                                                               new_rrs,
+                                                                               key_list,
+                                                                               func,
+                                                                               arg);
+       }
+       
+       return result;
+}
+
+
 ldns_zone *
 ldns_zone_sign(const ldns_zone *zone, ldns_key_list *key_list)
 {
@@ -3086,22 +3830,27 @@ ldns_zone_sign(const ldns_zone *zone, ldns_key_list *key_list)
         */
        
        ldns_zone *signed_zone;
-       ldns_rr_list *cur_rrset;
+       /*
+         ldns_rr_list *cur_rrset;
+       */
        ldns_rr_list *cur_rrsigs;
+
        ldns_rr_list *orig_zone_rrs;
        ldns_rr_list *signed_zone_rrs;
        ldns_rr_list *pubkeys;
        ldns_rr_list *glue_rrs;
+       ldns_rr_list *rrsig_rrs = NULL;
        
+       /*
        ldns_rdf *start_dname = NULL;
        ldns_rdf *cur_dname = NULL;
        ldns_rr *next_rr = NULL;
        ldns_rdf *next_dname = NULL;
        ldns_rr *nsec;
+       */
        ldns_rr *ckey;
        uint16_t i;
-       ldns_rr_type cur_rrset_type;
-       
+
        signed_zone = ldns_zone_new();
 
        /* there should only be 1 SOA, so the soa record is 1 rrset */
@@ -3114,7 +3863,7 @@ ldns_zone_sign(const ldns_zone *zone, ldns_key_list *key_list)
        ldns_rr_list_push_rr(orig_zone_rrs, ldns_rr_clone(ldns_zone_soa(zone)));
        
        /* canon now, needed for correct nsec creation */
-        for (i = 0; i < ldns_rr_list_rr_count(orig_zone_rrs); i++) {
+       for (i = 0; i < ldns_rr_list_rr_count(orig_zone_rrs); i++) {
                ldns_rr2canonical(ldns_rr_list_rr(orig_zone_rrs, i));
        }
        glue_rrs = ldns_zone_glue_rr_list(zone);
@@ -3126,62 +3875,21 @@ ldns_zone_sign(const ldns_zone *zone, ldns_key_list *key_list)
                ldns_rr_list_push_rr(pubkeys, ckey);
        }
 
-       signed_zone_rrs = ldns_rr_list_new();
-       
-       ldns_rr_list_sort(orig_zone_rrs);
-       
-       /* add nsecs */
-       for (i = 0; i < ldns_rr_list_rr_count(orig_zone_rrs); i++) {
-               if (!start_dname) {
-                       /*start_dname = ldns_rr_owner(ldns_zone_soa(zone));*/
-                       start_dname = ldns_rr_owner(ldns_rr_list_rr(orig_zone_rrs, i));
-                       cur_dname = start_dname;
-               } else {
-                       next_rr = ldns_rr_list_rr(orig_zone_rrs, i);
-                       next_dname = ldns_rr_owner(next_rr);
-                       if (ldns_rdf_compare(cur_dname, next_dname) != 0) {
-                               /* skip glue */
-                               if (ldns_rr_list_contains_rr(glue_rrs, next_rr)) {
-                                       cur_dname = next_dname;
-                               } else {
-                                       nsec = ldns_create_nsec(cur_dname, 
-                                                               next_dname,
-                                                               orig_zone_rrs);
-                                       ldns_rr_set_ttl(nsec, ldns_rdf2native_int32(ldns_rr_rdf(ldns_zone_soa(zone), 6)));
-                                       ldns_rr_list_push_rr(signed_zone_rrs, nsec);
-                                       /*start_dname = next_dname;*/
-                                       cur_dname = next_dname;
-                               }
-                       }
-               }
-               ldns_rr_list_push_rr(signed_zone_rrs, ldns_rr_list_rr(orig_zone_rrs, i));
+       signed_zone_rrs = ldns_rr_list_strip_dnssec(orig_zone_rrs, NULL);
+
+       ldns_rr_list_deep_free(orig_zone_rrs);
+
+       if (!signed_zone_rrs) {
+               printf("error!\n");
+               exit(1);
        }
-       nsec = ldns_create_nsec(cur_dname, 
-                               start_dname,
-                               orig_zone_rrs);
-       ldns_rr_list_push_rr(signed_zone_rrs, nsec);
-       ldns_rr_list_free(orig_zone_rrs);
-       ldns_rr_set_ttl(nsec, ldns_rdf2native_int32(ldns_rr_rdf(ldns_zone_soa(zone), 6)));
 
-       /* Sign all rrsets in the zone */
-       cur_rrset = ldns_rr_list_pop_rrset(signed_zone_rrs);
-       while (cur_rrset) {
-               /* don't sign certain types */
-               cur_rrset_type = ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0));
-               cur_dname = ldns_rr_owner(ldns_rr_list_rr(cur_rrset, 0));
+       
+       ldns_rr_list_sort(signed_zone_rrs);
+       /*
+       nsec_rrs = ldns_zone_create_nsecs(zone, signed_zone_rrs, glue_rrs);
 
-               /* if we have KSKs, use them for DNSKEYS, otherwise
-                  make them selfsigned (?) */
-                /* don't sign sigs, delegations, and glue */
-               if (cur_rrset_type != LDNS_RR_TYPE_RRSIG &&
-                   ((ldns_dname_is_subdomain(cur_dname, ldns_rr_owner(ldns_zone_soa(signed_zone)))
-                      && cur_rrset_type != LDNS_RR_TYPE_NS
-                     ) ||
-                    ldns_rdf_compare(cur_dname, ldns_rr_owner(ldns_zone_soa(signed_zone))) == 0
-                   ) &&
-                   !(ldns_rr_list_contains_rr(glue_rrs, ldns_rr_list_rr(cur_rrset, 0)))
-                  ) {
-                       cur_rrsigs = ldns_sign_public(cur_rrset, key_list);
+       ldns_rr_list_cat(signed_zone_rrs, nsec_rrs);
                        if (!cur_rrsigs) {
                                ldns_zone_deep_free(signed_zone);
                                ldns_rr_list_deep_free(signed_zone_rrs);
@@ -3189,52 +3897,26 @@ ldns_zone_sign(const ldns_zone *zone, ldns_key_list *key_list)
                                ldns_rr_list_free(glue_rrs);
                                return NULL;
                        }
-                       /* TODO: make optional, replace exit call */
-                       /* if not optional it should be left out completely
-                          (for it is possible to generate bad signarures, by
-                          specifying a future inception date */
-                       
-                       ldns_zone_push_rr_list(signed_zone, cur_rrset);
-                       ldns_zone_push_rr_list(signed_zone, cur_rrsigs);
-                       ldns_rr_list_free(cur_rrsigs);
-               } else {
-                       /* push it unsigned (glue, sigs, delegations) */
-                       ldns_zone_push_rr_list(signed_zone, cur_rrset);
-               }
-               ldns_rr_list_free(cur_rrset);
-               cur_rrset = ldns_rr_list_pop_rrset(signed_zone_rrs);
-       }
+       ldns_rr_list_free(nsec_rrs);
+       */
+       /*
+       rrsig_rrs = ldns_zone_create_rrsigs(signed_zone, signed_zone_rrs, glue_rrs, key_list);
+       */
+
+       ldns_rr_list_cat(signed_zone_rrs, rrsig_rrs);
+       ldns_rr_list_free(rrsig_rrs);
+
+       ldns_rr_list_deep_free(ldns_zone_rrs(signed_zone));
+       ldns_zone_set_rrs(signed_zone, ldns_rr_list_clone(signed_zone_rrs));
+       
        ldns_rr_list_deep_free(signed_zone_rrs);
        ldns_rr_list_deep_free(pubkeys);
        ldns_rr_list_free(glue_rrs);
+
        return signed_zone;
        
 }
 
-static int
-qsort_rr_compare_nsec3(const void *a, const void *b)
-{
-       const ldns_rr *rr1 = * (const ldns_rr **) a;
-       const ldns_rr *rr2 = * (const ldns_rr **) b;
-       if (rr1 == NULL && rr2 == NULL) {
-               return 0;
-       }
-       if (rr1 == NULL) {
-               return -1;
-       } 
-       if (rr2 == NULL) {
-               return 1;
-       }
-       return ldns_rdf_compare(ldns_rr_owner(rr1), ldns_rr_owner(rr2));
-}
-
-void ldns_rr_list_sort_nsec3(ldns_rr_list *unsorted) {
-       qsort(unsorted->_rrs,
-             ldns_rr_list_rr_count(unsorted),
-             sizeof(ldns_rr *),
-             qsort_rr_compare_nsec3);
-}
-
 ldns_zone *
 ldns_zone_sign_nsec3(ldns_zone *zone, ldns_key_list *key_list, uint8_t algorithm, uint8_t flags, uint16_t iterations, uint8_t salt_length, uint8_t *salt)
 {
diff --git a/dnssec_zone.c b/dnssec_zone.c
new file mode 100644 (file)
index 0000000..3c23ac1
--- /dev/null
@@ -0,0 +1,684 @@
+/*
+ * special zone file structures and functions for better dnssec handling
+ */
+
+#include <ldns/config.h>
+
+#include <ldns/ldns.h>
+
+ldns_dnssec_rrs *
+ldns_dnssec_rrs_new()
+{
+       ldns_dnssec_rrs *new_rrs;
+       new_rrs = LDNS_MALLOC(ldns_dnssec_rrs);
+       new_rrs->rr = NULL;
+       new_rrs->next = NULL;
+       return new_rrs;
+}
+
+void
+ldns_dnssec_rrs_free(ldns_dnssec_rrs *rrs)
+{
+       if (rrs) {
+               if (rrs->next) {
+                       ldns_dnssec_rrs_free(rrs->next);
+               }
+               LDNS_FREE(rrs);
+       }
+}
+
+ldns_status
+ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr)
+{
+       int cmp;
+       ldns_dnssec_rrs *new_rrs;
+       if (!rrs || !rr) {
+               return LDNS_STATUS_ERR;
+       }
+
+       /* this could be done more efficiently; name and type should already
+          be equal */
+       cmp = ldns_rr_compare(rrs->rr,
+                                         rr);
+       /* should we error on equal? */
+       if (cmp <= 0) {
+               if (rrs->next) {
+                       ldns_dnssec_rrs_add_rr(rrs->next, rr);
+               } else {
+                       new_rrs = ldns_dnssec_rrs_new();
+                       new_rrs->rr = rr;
+                       rrs->next = new_rrs;
+               }
+       } else if (cmp > 0) {
+               /* put the current old rr in the new next, put the new
+                  rr in the current container */
+               new_rrs = ldns_dnssec_rrs_new();
+               new_rrs->rr = rrs->rr;
+               new_rrs->next = rrs->next;
+               rrs->rr = rr;
+               rrs->next = new_rrs;
+       }
+       return LDNS_STATUS_OK;
+}
+
+void
+ldns_dnssec_rrs_print(FILE *out, ldns_dnssec_rrs *rrs)
+{
+       if (!rrs) {
+               fprintf(out, "<void>");
+       } else {
+               if (rrs->rr) {
+                       ldns_rr_print(out, rrs->rr);
+               }
+               if (rrs->next) {
+                       ldns_dnssec_rrs_print(out, rrs->next);
+               }
+       }
+}
+
+ldns_dnssec_rrsets *
+ldns_dnssec_rrsets_new()
+{
+       ldns_dnssec_rrsets *new_rrsets;
+       new_rrsets = LDNS_MALLOC(ldns_dnssec_rrsets);
+       new_rrsets->rrs = NULL;
+       new_rrsets->type = 0;
+       new_rrsets->signatures = NULL;
+       new_rrsets->next = NULL;
+       return new_rrsets;
+}
+
+void
+ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets)
+{
+       if (rrsets) {
+               if (rrsets->rrs) {
+                       ldns_dnssec_rrs_free(rrsets->rrs);
+               }
+               if (rrsets->next) {
+                       ldns_dnssec_rrsets_free(rrsets->next);
+               }
+               if (rrsets->signatures) {
+                       ldns_dnssec_rrs_free(rrsets->signatures);
+               }
+               LDNS_FREE(rrsets);
+       }
+}
+
+ldns_rr_type
+ldns_dnssec_rrsets_type(ldns_dnssec_rrsets *rrsets)
+{
+       if (rrsets) {
+               return rrsets->type;
+       } else {
+               return 0;
+       }
+}
+
+ldns_status
+ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets,
+                                          ldns_rr_type type)
+{
+       if (rrsets) {
+               rrsets->type = type;
+               return LDNS_STATUS_OK;
+       }
+       return LDNS_STATUS_ERR;
+}
+
+
+ldns_status
+ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr)
+{
+       ldns_dnssec_rrsets *new_rrsets;
+       ldns_rr_type rr_type;
+       bool rrsig = false;
+       ldns_status result = LDNS_STATUS_OK;
+
+       if (!rrsets || !rr) {
+               return LDNS_STATUS_ERR;
+       }
+
+       rr_type = ldns_rr_get_type(rr);
+
+       if (rr_type == LDNS_RR_TYPE_RRSIG) {
+               rrsig = true;
+               rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
+       }
+
+       if (!rrsets->rrs && rrsets->type == 0) {
+               rrsets->rrs = ldns_dnssec_rrs_new();
+               rrsets->rrs->rr = rr;
+               rrsets->type = ldns_rr_get_type(rr);
+               return LDNS_STATUS_OK;
+       }
+
+       if (rr_type > ldns_dnssec_rrsets_type(rrsets)) {
+               if (rrsets->next) {
+                       result = ldns_dnssec_rrsets_add_rr(rrsets->next, rr);
+               } else {
+                       new_rrsets = ldns_dnssec_rrsets_new();
+                       new_rrsets->rrs = ldns_dnssec_rrs_new();
+                       new_rrsets->rrs->rr = rr;
+                       new_rrsets->type = ldns_rr_get_type(rr);
+                       rrsets->next = new_rrsets;
+               }
+       } else if (rr_type < ldns_dnssec_rrsets_type(rrsets)) {
+               /* move the current one into the new next, 
+                  replace field of current with data from new rr */
+               new_rrsets = ldns_dnssec_rrsets_new();
+               new_rrsets->rrs = rrsets->rrs;
+               new_rrsets->type = rrsets->type;
+               new_rrsets->signatures = rrsets->signatures;
+               new_rrsets->next = rrsets->next;
+               rrsets->rrs = ldns_dnssec_rrs_new();
+               rrsets->rrs->rr = rr;
+               rrsets->signatures = NULL;
+               rrsets->type = ldns_rr_get_type(rr);
+               rrsets->next = new_rrsets;
+       } else {
+               /* equal, add to current rrsets */
+               if (rrsig) {
+                       if (rrsets->signatures) {
+                               result = ldns_dnssec_rrs_add_rr(rrsets->signatures, rr);
+                       } else {
+                               rrsets->signatures = ldns_dnssec_rrs_new();
+                               rrsets->signatures->rr = rr;
+                       }
+               } else {
+                       result = ldns_dnssec_rrs_add_rr(rrsets->rrs, rr);
+               }
+       }
+
+       return result;
+}
+
+void
+ldns_dnssec_rrsets_print_soa(FILE *out,
+                                           ldns_dnssec_rrsets *rrsets,
+                                           bool follow,
+                                           bool show_soa)
+{
+       if (!rrsets) {
+               fprintf(out, "<void>\n");
+       } else {
+               if (rrsets->rrs &&
+                   (show_soa ||
+                       ldns_rr_get_type(rrsets->rrs->rr) != LDNS_RR_TYPE_SOA
+                   )
+                  ) {
+                       ldns_dnssec_rrs_print(out, rrsets->rrs);
+                       if (rrsets->signatures) {
+                               ldns_dnssec_rrs_print(out, rrsets->signatures);
+                       }
+               }
+               if (follow && rrsets->next) {
+                       ldns_dnssec_rrsets_print_soa(out, rrsets->next, follow, show_soa);
+               }
+       }
+}
+
+void
+ldns_dnssec_rrsets_print(FILE *out, ldns_dnssec_rrsets *rrsets, bool follow)
+{
+       ldns_dnssec_rrsets_print_soa(out, rrsets, follow, true);
+}
+
+ldns_dnssec_name *
+ldns_dnssec_name_new()
+{
+       ldns_dnssec_name *new_name;
+
+       new_name = LDNS_MALLOC(ldns_dnssec_name);
+       if (!new_name) {
+               return NULL;
+       }
+
+       new_name->rrsets = NULL;
+       new_name->name_alloced = false;
+       new_name->nsec = NULL;
+       new_name->nsec_signatures = NULL;
+
+       return new_name;
+}
+
+ldns_dnssec_name *
+ldns_dnssec_name_new_frm_rr(ldns_rr *rr)
+{
+       ldns_dnssec_name *new_name = ldns_dnssec_name_new();
+
+       new_name->name = ldns_rr_owner(rr);
+       ldns_dnssec_name_add_rr_to_current(new_name, rr);
+
+       return new_name;
+}
+
+void
+ldns_dnssec_name_free(ldns_dnssec_name *name)
+{
+       if (name) {
+               if (name->name_alloced) {
+                       ldns_rdf_deep_free(name->name);
+               }
+               if (name->rrsets) {
+                       ldns_dnssec_rrsets_free(name->rrsets);
+               }
+               if (name->nsec_signatures) {
+                       ldns_dnssec_rrs_free(name->nsec_signatures);
+               }
+               LDNS_FREE(name);
+       }
+}
+
+ldns_rdf *
+ldns_dnssec_name_name(ldns_dnssec_name *name)
+{
+       if (name) {
+               return name->name;
+       }
+       return NULL;
+}
+
+void
+ldns_dnssec_name_set_name(ldns_dnssec_name *rrset,
+                                        ldns_rdf *dname)
+{
+       if (rrset && dname) {
+               rrset->name = dname;
+       }
+}
+
+ldns_rr *
+ldns_dnssec_name_nsec(ldns_dnssec_name *rrset)
+{
+       if (rrset) {
+               return rrset->nsec;
+       }
+       return NULL;
+}
+
+void
+ldns_dnssec_name_set_nsec(ldns_dnssec_name *rrset, ldns_rr *nsec)
+{
+       if (rrset && nsec) {
+               rrset->nsec = nsec;
+       }
+}
+
+ldns_status
+ldns_dnssec_name_add_rr_to_current(ldns_dnssec_name *name,
+                                                       ldns_rr *rr)
+{
+       ldns_dnssec_rrsets *new_rrsets;
+       ldns_status result = LDNS_STATUS_OK;
+
+       if (!name || !rr) {
+               return LDNS_STATUS_ERR;
+       }
+
+       if (name->rrsets) {
+               result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
+       } else {
+               new_rrsets = ldns_dnssec_rrsets_new();
+               result = ldns_dnssec_rrsets_add_rr(new_rrsets, rr);
+               name->rrsets = new_rrsets;
+       }
+
+       return result;
+}
+
+int
+ldns_dnssec_name_cmp(const void *a, const void *b)
+{
+       ldns_dnssec_name *na = (ldns_dnssec_name *) a;
+       ldns_dnssec_name *nb = (ldns_dnssec_name *) b;
+
+       if (na && nb) {
+               return ldns_dname_compare(ldns_dnssec_name_name(na),
+                                                        ldns_dnssec_name_name(nb));
+       } else if (na) {
+               return 1;
+       } else if (nb) {
+               return -1;
+       } else {
+               return 0;
+       }
+}
+
+
+ldns_status
+ldns_dnssec_name_add_rr(ldns_dnssec_name *name,
+                                   ldns_rr *rr)
+{
+       ldns_status result = LDNS_STATUS_OK;
+       name = name;
+       rr = rr;
+       ldns_rdf *name_name;
+       bool hashed_name = false;
+
+       /* special handling for NSEC3 and NSECX covering RRSIGS */
+       ldns_rr_type rr_type = ldns_rr_get_type(rr);
+       ldns_rr_type typecovered = 0;
+
+       if (!name || !rr) {
+               return LDNS_STATUS_ERR;
+       }
+
+       rr_type = ldns_rr_get_type(rr);
+
+       if (rr_type == LDNS_RR_TYPE_RRSIG) {
+               typecovered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
+       }
+
+       if (rr_type == LDNS_RR_TYPE_NSEC3 ||
+           typecovered == LDNS_RR_TYPE_NSEC3) {
+               name_name = ldns_nsec3_hash_name_frm_nsec3(rr,
+                                                                                  ldns_dnssec_name_name(name));
+               hashed_name = true;
+       } else {
+               name_name = ldns_dnssec_name_name(name);
+       }
+
+       if (rr_type == LDNS_RR_TYPE_NSEC ||
+           rr_type == LDNS_RR_TYPE_NSEC3) {
+               /* XX check if is already set (and error?) */
+               name->nsec = rr;
+       } else if (typecovered == LDNS_RR_TYPE_NSEC ||
+                        typecovered == LDNS_RR_TYPE_NSEC3) {
+               if (name->nsec_signatures) {
+                       ldns_dnssec_rrs_add_rr(name->nsec_signatures, rr);
+               } else {
+                       name->nsec_signatures = ldns_dnssec_rrs_new();
+                       name->nsec_signatures->rr = rr;
+               }
+       } else {
+               result = ldns_dnssec_name_add_rr_to_current(name, rr);
+       }
+
+       if (hashed_name) {
+               ldns_rdf_deep_free(name_name);
+       }
+
+       return result;
+}
+
+ldns_dnssec_rrsets *
+ldns_dnssec_name_find_rrset(ldns_dnssec_name *name,
+                                          ldns_rr_type type) {
+       ldns_dnssec_rrsets *result;
+
+       result = name->rrsets;
+       while (result) {
+               if (result->type == type) {
+                       return result;
+               } else {
+                       result = result->next;
+               }
+       }
+       return NULL;
+}
+
+ldns_dnssec_rrsets *
+ldns_dnssec_zone_find_rrset(ldns_dnssec_zone *zone,
+                                          ldns_rdf *dname,
+                                          ldns_rr_type type)
+{
+       ldns_rbnode_t *node;
+
+       if (!zone || !dname) {
+               return NULL;
+       }
+
+       node = ldns_rbtree_search(zone->names, dname);
+       if (node) {
+               return ldns_dnssec_name_find_rrset((ldns_dnssec_name *)node->data,
+                                                                       type);
+       } else {
+               return NULL;
+       }
+}
+
+static inline void
+print_indent(FILE *out, int c)
+{
+       int i;
+       for (i=0; i<c; i++) {
+               fprintf(out, "    ");
+       }
+}
+
+void
+ldns_dnssec_name_print_soa(FILE *out, ldns_dnssec_name *name, bool show_soa)
+{
+       if (name) {
+               if(name->rrsets) {
+                       ldns_dnssec_rrsets_print_soa(out, name->rrsets, true, show_soa);
+               } else {
+                       fprintf(out, ";; Empty nonterminal: ");
+                       ldns_rdf_print(out, name->name);
+                       fprintf(out, "\n");
+               }
+               if(name->nsec) {
+                       ldns_rr_print(out, name->nsec);
+               }
+               if (name->nsec_signatures) {
+                       ldns_dnssec_rrs_print(out, name->nsec_signatures);
+               }
+       } else {
+               fprintf(out, "<void>\n");
+       }
+}
+
+void
+ldns_dnssec_name_print(FILE *out, ldns_dnssec_name *name)
+{
+       ldns_dnssec_name_print_soa(out, name, true);
+}
+
+ldns_dnssec_zone *
+ldns_dnssec_zone_new()
+{
+       ldns_dnssec_zone *zone = LDNS_MALLOC(ldns_dnssec_zone);
+       zone->soa = NULL;
+       zone->names = NULL;
+
+       return zone;
+}
+
+void
+ldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg) {
+       arg = arg;
+       ldns_dnssec_name_free((ldns_dnssec_name *)node->data);
+       free(node);
+}
+
+void
+ldns_dnssec_zone_free(ldns_dnssec_zone *zone)
+{
+       if (zone) {
+               if (zone->names) {
+                       /* destroy all name structures within the tree */
+                       traverse_postorder(zone->names,
+                                                   ldns_dnssec_name_node_free,
+                                                   NULL);
+                       free(zone->names);
+               }
+               LDNS_FREE(zone);
+       }
+}
+
+/* use for dname comparison in tree */
+int
+ldns_dname_compare_v(const void *a, const void *b) {
+       return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b);
+}
+
+ldns_status
+ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr)
+{
+       ldns_status result = LDNS_STATUS_OK;
+       ldns_dnssec_name *cur_name;
+       ldns_rbnode_t *cur_node;
+
+       if (!zone || !rr) {
+               return LDNS_STATUS_ERR;
+       }
+
+       if (!zone->names) {
+               zone->names = ldns_rbtree_create(ldns_dname_compare_v);
+       }
+       
+       cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr));
+
+       if (!cur_node) {
+               /* add */
+               cur_name = ldns_dnssec_name_new_frm_rr(rr);
+               cur_node = LDNS_MALLOC(ldns_rbnode_t);
+               cur_node->key = ldns_rr_owner(rr);
+               cur_node->data = cur_name;
+               ldns_rbtree_insert(zone->names, cur_node);
+       } else {
+               cur_name = (ldns_dnssec_name *) cur_node->data;
+               ldns_dnssec_name_add_rr(cur_name, rr);
+       }
+
+       if (result != LDNS_STATUS_OK) {
+               fprintf(stderr, "error adding rr: ");
+               ldns_rr_print(stderr, rr);
+       }
+
+       /*TODO ldns_dnssec_name_print_names(stdout, zone->names, 0);*/
+       if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
+               zone->soa = cur_name;
+       }
+
+       return result;
+}
+
+void
+ldns_dnssec_zone_names_print(FILE *out, ldns_rbtree_t *tree, bool print_soa)
+{
+       ldns_rbnode_t *node;
+       ldns_dnssec_name *name;
+
+       node = ldns_rbtree_first(tree);
+       while (node != LDNS_RBTREE_NULL) {
+               name = (ldns_dnssec_name *) node->data;
+               ldns_dnssec_name_print_soa(out, name, print_soa);
+               node = ldns_rbtree_next(node);
+       }
+}
+
+void
+ldns_dnssec_zone_print(FILE *out, ldns_dnssec_zone *zone)
+{
+       if (zone) {
+               if (zone->soa) {
+                       ldns_dnssec_rrsets_print(out,
+                                                               ldns_dnssec_name_find_rrset(zone->soa,
+                                                                                                          LDNS_RR_TYPE_SOA),
+                                                               false);
+               }
+
+               if (zone->names) {
+                       ldns_dnssec_zone_names_print(out, zone->names, false);
+               }
+       }
+}
+
+ldns_status
+ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
+{
+       ldns_dnssec_name *new_name;
+       ldns_dnssec_name *cur_name;
+       ldns_dnssec_name *next_name;
+       ldns_rbnode_t *cur_node, *next_node, *new_node;
+
+       /* for the detection */
+       uint16_t j, cur_label_count, next_label_count;
+       ldns_rdf *l1, *l2, *post, *post2;
+       bool found_difference = false;
+
+       if (!zone) {
+               return LDNS_STATUS_ERR;
+       }
+       cur_node = ldns_rbtree_first(zone->names);
+       while (cur_node != LDNS_RBTREE_NULL) {
+               next_node = ldns_rbtree_next(cur_node);
+               if (next_node == LDNS_RBTREE_NULL) {
+                       next_node = ldns_rbtree_first(zone->names);
+               }
+
+               cur_name = (ldns_dnssec_name *)cur_node->data;
+               next_name = (ldns_dnssec_name *)next_node->data;
+
+               found_difference = false;
+
+               cur_label_count = ldns_dname_label_count(cur_name->name);
+               next_label_count = ldns_dname_label_count(next_name->name);
+
+               post = ldns_dname_new_frm_str(".");
+               for (j = 1 + ldns_dname_label_count(zone->soa->name); 
+                       j < cur_label_count && 
+                               j <= next_label_count && 
+                               !found_difference;
+                       j++) {
+                       l1 = ldns_dname_label(cur_name->name, cur_label_count - j);
+                       l2 = ldns_dname_label(next_name->name, next_label_count - j);
+                       post2 = ldns_dname_cat_clone(l2, post);
+                       ldns_rdf_deep_free(post);
+                       post = post2;
+
+                       if (ldns_dname_compare(l1, l2) != 0 &&
+                           j < next_label_count) {
+                               found_difference = true;
+                               
+                               new_name = ldns_dnssec_name_new();
+                               new_name->name = ldns_rdf_clone(post);
+                               new_name->name_alloced = true;
+                               new_node = LDNS_MALLOC(ldns_rbnode_t);
+                               new_node->key = new_name->name;
+                               new_node->data = new_name;
+                               ldns_rbtree_insert(zone->names, new_node);
+                               //ldns_dnssec_zone_add_name(zone, new_name);
+                       }
+                       ldns_rdf_deep_free(l1);
+                       ldns_rdf_deep_free(l2);
+               }
+               /* and if next label is longer than cur + 1, these must be empty nons too */
+               /* skip current label (total now equal to cur_dname) */
+               if (!found_difference && j < cur_label_count && j <= next_label_count) {
+                       l2 = ldns_dname_label(next_name->name, next_label_count - j);
+                       post2 = ldns_dname_cat_clone(l2, post);
+                       ldns_rdf_deep_free(post);
+                       post = post2;
+                       j++;
+               }
+               while (j < next_label_count) {
+                       l2 = ldns_dname_label(next_name->name, next_label_count - j);
+                       post2 = ldns_dname_cat_clone(l2, post);
+                       ldns_rdf_deep_free(post);
+                       post = post2;
+                       /*
+                         printf("Found empty non-terminal: ");
+                         ldns_rdf_print(stdout, post);
+                         printf("\n");
+                       */
+                       ldns_rdf_deep_free(l2);
+                       j++;    
+                       new_name = ldns_dnssec_name_new();
+                       new_name->name = ldns_rdf_clone(post);
+                       new_name->name_alloced = true;
+                       new_node = LDNS_MALLOC(ldns_rbnode_t);
+                       new_node->key = new_name->name;
+                       new_node->data = new_name;
+                       ldns_rbtree_insert(zone->names, new_node);
+               }
+               ldns_rdf_deep_free(post);
+               /* TODO: other name->name (we need to free this one) */
+               
+
+               cur_node = ldns_rbtree_next(cur_node);
+       }
+       return LDNS_STATUS_OK;
+}
index 97da5f456c6d1b43404841b3fe3196f955a2f6d7..eb98baa38b0e2a02620c6a671fc4963e3a88427a 100644 (file)
@@ -96,15 +96,30 @@ main(int argc, char **argv)
        if (s != LDNS_STATUS_OK) {
                fclose(fp1);
                fprintf(stderr, "%s: %s at %d\n",
-                       fn1,
-                       ldns_get_errorstr_by_id(s),
-                       line_nr1);
+                          fn1,
+                          ldns_get_errorstr_by_id(s),
+                          line_nr1);
                exit(EXIT_FAILURE);
        }
        fclose(fp1);
 
-       /* Sort first zone */
-       ldns_zone_sort(z1);
+       fn1 = argv[0];
+       fp1 = fopen(fn1, "r");
+       if (!fp1) {
+               fprintf(stderr, "Unable to open %s: %s\n", fn1, strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+       /* Read first zone */
+       s = ldns_zone_new_frm_fp_l(&z1, fp1, NULL, 0, LDNS_RR_CLASS_IN, &line_nr1);
+
+       if (s != LDNS_STATUS_OK) {
+               fclose(fp1);
+               fprintf(stderr, "%s at %d\n", 
+                          ldns_get_errorstr_by_id(s),
+                          line_nr1);
+               exit(EXIT_FAILURE);
+       }
+       fclose(fp1);
 
        fn2 = argv[1];
        fp2 = fopen(fn2, "r");
@@ -119,15 +134,31 @@ main(int argc, char **argv)
                ldns_zone_deep_free(z1);
                fclose(fp2);
                fprintf(stderr, "%s: %s at %d\n",
-                       fn2,
-                       ldns_get_errorstr_by_id(s),
-                       line_nr2);
+                          fn2,
+                          ldns_get_errorstr_by_id(s),
+                          line_nr2);
                exit(EXIT_FAILURE);
        }
        fclose(fp2);
 
-       /* Sort second zone */
-       ldns_zone_sort(z2);
+       fn2 = argv[1];
+       fp2 = fopen(fn2, "r");
+       if (!fp2) {
+               fprintf(stderr, "Unable to open %s: %s\n", fn2, strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+       /* Read second zone */
+       s = ldns_zone_new_frm_fp_l(&z2, fp2, NULL, 0, LDNS_RR_CLASS_IN, &line_nr2);
+
+       if (s != LDNS_STATUS_OK) {
+               ldns_zone_deep_free(z1);
+               fclose(fp2);
+               fprintf(stderr, "%s at %d\n", 
+                          ldns_get_errorstr_by_id(s),
+                          line_nr2);
+               exit(EXIT_FAILURE);
+       }
+       fclose(fp2);
 
        rrl1 = ldns_zone_rrs(z1);
        rrc1 = ldns_rr_list_rr_count(rrl1);
index 44de81d7713fb2b540d1a1dacdca4363be5661e2..73fe2578875c401d4e2c7f2b5e13b36dd32de2a4 100644 (file)
@@ -100,7 +100,6 @@ strip_dnssec_records(ldns_zone *zone)
        
        new_list = ldns_rr_list_new();
        
-       new_list = ldns_rr_list_new();
        while ((cur_rr = ldns_rr_list_pop_rr(ldns_zone_rrs(zone)))) {
                if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_RRSIG ||
                    ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_NSEC
@@ -129,7 +128,7 @@ main(int argc, char *argv[])
        ldns_zone *orig_zone;
        ldns_rr_list *orig_rrs = NULL;
        ldns_rr *orig_soa = NULL;
-       ldns_zone *signed_zone;
+       ldns_dnssec_zone *signed_zone;
 
        const char *keyfile_name_base;
        char *keyfile_name;
@@ -139,6 +138,8 @@ main(int argc, char *argv[])
        ldns_key_list *keys;
        size_t key_i;
        ldns_status s;
+       size_t i;
+       ldns_rr_list *added_rrs;
 
        bool leave_old_dnssec_data = false;
 
@@ -154,7 +155,7 @@ main(int argc, char *argv[])
        bool use_nsec3 = false;
        
        uint8_t nsec3_algorithm = 1;
-       uint8_t nsec3_flags = 0;
+       /*uint8_t nsec3_flags = 0;*/
        size_t nsec3_iterations_cmd = 1;
        uint16_t nsec3_iterations = 1;
        uint8_t nsec3_salt_length = 0;
@@ -171,13 +172,14 @@ main(int argc, char *argv[])
        ldns_rr_class class = LDNS_RR_CLASS_IN; 
        
        char *prog = strdup(argv[0]);
+       ldns_status result;
        
        inception = 0;
        expiration = 0;
        
        keys = ldns_key_list_new();
 
-/*     OPENSSL_config(NULL);*/
+       /*      OPENSSL_config(NULL);*/
 
        while ((c = getopt(argc, argv, "a:e:f:i:k:lno:s:t:v:E:K:")) != -1) {
                switch (c) {
@@ -193,14 +195,14 @@ main(int argc, char *argv[])
 
                        if (strlen(optarg) == 8 &&
                            sscanf(optarg, "%4d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday)
-                          ) {
+                           ) {
                                tm.tm_year -= 1900;
                                tm.tm_mon--;
                                check_tm(tm);
                                expiration = (uint32_t) mktime_from_utc(&tm);
                        } else if (strlen(optarg) == 14 &&
-                           sscanf(optarg, "%4d%2d%2d%2d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec)
-                          ) {
+                                        sscanf(optarg, "%4d%2d%2d%2d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec)
+                                        ) {
                                tm.tm_year -= 1900;
                                tm.tm_mon--;
                                check_tm(tm);
@@ -218,14 +220,14 @@ main(int argc, char *argv[])
 
                        if (strlen(optarg) == 8 &&
                            sscanf(optarg, "%4d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday)
-                          ) {
+                           ) {
                                tm.tm_year -= 1900;
                                tm.tm_mon--;
                                check_tm(tm);
                                inception = (uint32_t) mktime_from_utc(&tm);
                        } else if (strlen(optarg) == 14 &&
-                           sscanf(optarg, "%4d%2d%2d%2d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec)
-                          ) {
+                                        sscanf(optarg, "%4d%2d%2d%2d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec)
+                                        ) {
                                tm.tm_year -= 1900;
                                tm.tm_mon--;
                                check_tm(tm);
@@ -309,22 +311,22 @@ main(int argc, char *argv[])
                                if (s == LDNS_STATUS_OK) {
                                        /* must be dnssec key */
                                        switch (ldns_key_algorithm(key)) {
-                                               case LDNS_SIGN_RSAMD5:
-                                               case LDNS_SIGN_RSASHA1:
-                                               case LDNS_SIGN_RSASHA1_NSEC3:
-                                               case LDNS_SIGN_RSASHA256:
-                                               case LDNS_SIGN_RSASHA256_NSEC3:
-                                               case LDNS_SIGN_RSASHA512:
-                                               case LDNS_SIGN_RSASHA512_NSEC3:
-                                               case LDNS_SIGN_DSA:
-                                               case LDNS_SIGN_DSA_NSEC3:
-                                                       ldns_key_list_push_key(keys, key);
-                                                       /*printf("Added key at %p:\n", key);*/
-                                                       /*ldns_key_print(stdout, key);*/
-                                                       break;
-                                               default:
-                                                       fprintf(stderr, "Warning, key not suitable for signing, ignoring key with algorithm %u\n", ldns_key_algorithm(key));
-                                                       break;
+                                       case LDNS_SIGN_RSAMD5:
+                                       case LDNS_SIGN_RSASHA1:
+                                       case LDNS_SIGN_RSASHA1_NSEC3:
+                                       case LDNS_SIGN_RSASHA256:
+                                       case LDNS_SIGN_RSASHA256_NSEC3:
+                                       case LDNS_SIGN_RSASHA512:
+                                       case LDNS_SIGN_RSASHA512_NSEC3:
+                                       case LDNS_SIGN_DSA:
+                                       case LDNS_SIGN_DSA_NSEC3:
+                                               ldns_key_list_push_key(keys, key);
+                                               /*printf("Added key at %p:\n", key);*/
+                                               /*ldns_key_print(stdout, key);*/
+                                               break;
+                                       default:
+                                               fprintf(stderr, "Warning, key not suitable for signing, ignoring key with algorithm %u\n", ldns_key_algorithm(key));
+                                               break;
                                        }
                                } else {
                                        printf("Error reading key '%s' from engine: %s\n", eng_key_id, ldns_get_errorstr_by_id(s));
@@ -347,28 +349,28 @@ main(int argc, char *argv[])
                        exit(EXIT_FAILURE);
                        break;
                case 's':
-                       if (strlen(optarg) % 2 != 0) {
-                                fprintf(stderr, "Salt value is not valid hex data, not a multiple of 2 characters\n");
-                                exit(EXIT_FAILURE);
-                       }
-                       nsec3_salt_length = (uint8_t) strlen(optarg) / 2;
+                       if (strlen(optarg) % 2 != 0) {
+                               fprintf(stderr, "Salt value is not valid hex data, not a multiple of 2 characters\n");
+                               exit(EXIT_FAILURE);
+                       }
+                       nsec3_salt_length = (uint8_t) strlen(optarg) / 2;
                        nsec3_salt = LDNS_XMALLOC(uint8_t, nsec3_salt_length);
-                        for (c = 0; c < (int) strlen(optarg); c += 2) {
-                                if (isxdigit(optarg[c]) && isxdigit(optarg[c+1])) {
-                                        nsec3_salt[c/2] = (uint8_t) ldns_hexdigit_to_int(optarg[c]) * 16 +
-                                                          ldns_hexdigit_to_int(optarg[c+1]);
-                                } else {
-                                        fprintf(stderr, "Salt value is not valid hex data.\n");
-                                        exit(EXIT_FAILURE);
-                                }
-                        }
+                       for (c = 0; c < (int) strlen(optarg); c += 2) {
+                               if (isxdigit(optarg[c]) && isxdigit(optarg[c+1])) {
+                                       nsec3_salt[c/2] = (uint8_t) ldns_hexdigit_to_int(optarg[c]) * 16 +
+                                               ldns_hexdigit_to_int(optarg[c+1]);
+                               } else {
+                                       fprintf(stderr, "Salt value is not valid hex data.\n");
+                                       exit(EXIT_FAILURE);
+                               }
+                       }
 
                        break;
                case 't':
                        nsec3_iterations_cmd = (size_t) atol(optarg);
                        if (nsec3_iterations_cmd > LDNS_NSEC3_MAX_ITERATIONS) {
-                         fprintf(stderr, "Iterations count can not exceed %u, quitting\n", LDNS_NSEC3_MAX_ITERATIONS);
-                         exit(EXIT_FAILURE);
+                               fprintf(stderr, "Iterations count can not exceed %u, quitting\n", LDNS_NSEC3_MAX_ITERATIONS);
+                               exit(EXIT_FAILURE);
                        }
                        nsec3_iterations = (uint16_t) nsec3_iterations_cmd;
                        break;
@@ -393,6 +395,7 @@ main(int argc, char *argv[])
        
        zonefile = fopen(zonefile_name, "r");
        
+       printf("[XX] Reading zone file\n");
        if (!zonefile) {
                fprintf(stderr, "Error: unable to read %s (%s)\n", zonefile_name, strerror(errno));
                exit(EXIT_FAILURE);
@@ -400,8 +403,8 @@ main(int argc, char *argv[])
                s = ldns_zone_new_frm_fp_l(&orig_zone, zonefile, origin, ttl, class, &line_nr);
                if (s != LDNS_STATUS_OK) {
                        fprintf(stderr, "Zone not read, error: %s at %s line %d\n", 
-                                       ldns_get_errorstr_by_id(s), 
-                                       zonefile_name, line_nr);
+                                  ldns_get_errorstr_by_id(s), 
+                                  zonefile_name, line_nr);
                        exit(EXIT_FAILURE);
                } else {
                        orig_soa = ldns_zone_soa(orig_zone);
@@ -427,11 +430,17 @@ main(int argc, char *argv[])
        while (argi < argc) {
                keyfile_name_base = argv[argi];
                keyfile_name = LDNS_XMALLOC(char, strlen(keyfile_name_base) + 9);
-               snprintf(keyfile_name, strlen(keyfile_name_base) + 9, "%s.private", keyfile_name_base);
+               snprintf(keyfile_name,
+                           strlen(keyfile_name_base) + 9,
+                           "%s.private",
+                           keyfile_name_base);
                keyfile = fopen(keyfile_name, "r");
                line_nr = 0;
                if (!keyfile) {
-                       fprintf(stderr, "Error: unable to read %s: %s\n", keyfile_name, strerror(errno));
+                       fprintf(stderr,
+                                  "Error: unable to read %s: %s\n",
+                                  keyfile_name,
+                                  strerror(errno));
                } else {
                        s = ldns_key_new_frm_fp_l(&key, keyfile, &line_nr);
                        fclose(keyfile);
@@ -450,21 +459,34 @@ main(int argc, char *argv[])
                                
                                /* find the public key in the zone, or in a
                                 * seperate file
-                                * we 'generate' one anyway, then match that to any present in the zone,
-                                *  if it matches, we drop our own. If not, we try to see if there
-                                * is a .key file present. If not, we use our own generated one, with
+                                * we 'generate' one anyway, 
+                                * then match that to any present in the zone,
+                                * if it matches, we drop our own. If not,
+                                * we try to see if there is a .key file present.
+                                * If not, we use our own generated one, with
                                 * some default values */
                                
                                pubkey_gen = ldns_key2rr(key);
+
                                if (verbosity >= 2) {
-                                       fprintf(stderr, "Looking for key with keytag %u or %u\n", (unsigned int) ldns_calc_keytag(pubkey_gen), (unsigned int)  ldns_calc_keytag(pubkey_gen) + 1);
+                                       fprintf(stderr,
+                                                  "Looking for key with keytag %u or %u\n",
+                                                  (unsigned int) ldns_calc_keytag(pubkey_gen),
+                                                  (unsigned int) ldns_calc_keytag(pubkey_gen)+1
+                                                  );
                                }
-                               for (key_i = 0; key_i < ldns_rr_list_rr_count(orig_rrs); key_i++) {
+                               for (key_i = 0;
+                                       key_i < ldns_rr_list_rr_count(orig_rrs);
+                                       key_i++) {
                                        pubkey = ldns_rr_list_rr(orig_rrs, key_i);
                                        if (ldns_rr_get_type(pubkey) == LDNS_RR_TYPE_DNSKEY &&
-                                           (ldns_calc_keytag(pubkey) == ldns_calc_keytag(pubkey_gen) ||
+                                           (ldns_calc_keytag(pubkey)
+                                               ==
+                                               ldns_calc_keytag(pubkey_gen) ||
                                             /* KSK has gen-keytag + 1 */
-                                            ldns_calc_keytag(pubkey) == ldns_calc_keytag(pubkey_gen) + 1) 
+                                            ldns_calc_keytag(pubkey)
+                                               ==
+                                               ldns_calc_keytag(pubkey_gen) + 1) 
                                            ) {
                                                /* found it, drop our own */
                                                if (verbosity >= 2) {
@@ -474,16 +496,25 @@ main(int argc, char *argv[])
                                        }
                                }
                                /* it was not in the zone, try to read a .key file */
-                               keyfile_name = LDNS_XMALLOC(char, strlen(keyfile_name_base) + 5);
-                               snprintf(keyfile_name, strlen(keyfile_name_base) + 5, "%s.key", keyfile_name_base);
+                               keyfile_name = LDNS_XMALLOC(char,
+                                                                          strlen(keyfile_name_base) + 5);
+                               snprintf(keyfile_name,
+                                           strlen(keyfile_name_base) + 5,
+                                           "%s.key",
+                                           keyfile_name_base);
                                if (verbosity >= 2) {
                                        fprintf(stderr, "Trying to read %s\n", keyfile_name);
                                }
                                keyfile = fopen(keyfile_name, "r");
                                line_nr = 0;
                                if (keyfile) {
-                                       if (ldns_rr_new_frm_fp_l(&pubkey, keyfile, &default_ttl, NULL, NULL, &line_nr) ==
-                                                       LDNS_STATUS_OK) {
+                                       if (ldns_rr_new_frm_fp_l(&pubkey,
+                                                                               keyfile,
+                                                                               &default_ttl,
+                                                                               NULL,
+                                                                               NULL,
+                                                                               &line_nr) ==
+                                           LDNS_STATUS_OK) {
                                                ldns_key_set_pubkey_owner(key, ldns_rdf_clone(ldns_rr_owner(pubkey)));
                                                ldns_key_set_flags(key, ldns_rdf2native_int16(ldns_rr_rdf(pubkey, 0)));
                                                ldns_key_set_keytag(key, ldns_calc_keytag(pubkey));
@@ -494,61 +525,35 @@ main(int argc, char *argv[])
                                        goto found;
                                }
                                
-                               /* okay, so reading .key didn't work either, just use our generated one */
+                               /* okay, so reading .key didn't work either,
+                                  just use our generated one */
                                if (verbosity >= 2) {
                                        fprintf(stderr, "Not in zone, no .key file, generating DNSKEY from .private\n");
                                }
                                ldns_zone_push_rr(orig_zone, pubkey_gen);
                                
                                
-                               found:
+                       found:
                                ldns_rr_free(pubkey_gen);
                                switch (ldns_key_algorithm(key)) {
-                                       case LDNS_SIGN_RSAMD5:
-                                       case LDNS_SIGN_RSASHA1:
-                                       case LDNS_SIGN_RSASHA1_NSEC3:
-                                       case LDNS_SIGN_RSASHA256:
-                                       case LDNS_SIGN_RSASHA256_NSEC3:
-                                       case LDNS_SIGN_RSASHA512:
-                                       case LDNS_SIGN_RSASHA512_NSEC3:
-                                       case LDNS_SIGN_DSA:
-                                       case LDNS_SIGN_DSA_NSEC3:
-                                               ldns_key_list_push_key(keys, key);
-                                               /*printf("Added key at %p:\n", key);*/
-                                               /*ldns_key_print(stdout, key);*/
-                                               break;
-                                       default:
-                                               fprintf(stderr, "Warning, key not suitable for signing, ignoring key from %s with algorithm %u\n", keyfile_name, ldns_key_algorithm(key));
-                                               break;
+                               case LDNS_SIGN_RSAMD5:
+                               case LDNS_SIGN_RSASHA1:
+                               case LDNS_SIGN_RSASHA1_NSEC3:
+                               case LDNS_SIGN_RSASHA256:
+                               case LDNS_SIGN_RSASHA256_NSEC3:
+                               case LDNS_SIGN_RSASHA512:
+                               case LDNS_SIGN_RSASHA512_NSEC3:
+                               case LDNS_SIGN_DSA:
+                               case LDNS_SIGN_DSA_NSEC3:
+                                       ldns_key_list_push_key(keys, key);
+                                       /*printf("Added key at %p:\n", key);*/
+                                       /*ldns_key_print(stdout, key);*/
+                                       break;
+                               default:
+                                       fprintf(stderr, "Warning, key not suitable for signing, ignoring key from %s with algorithm %u\n", keyfile_name, ldns_key_algorithm(key));
+                                       break;
                                }
                                LDNS_FREE(keyfile_name);
-#if 0
- else {
-                                       /* apparently the public key is not in the zone
-                                          so we try to read the .key file
-                                        */
-                                       keyfile_name = LDNS_XMALLOC(char, strlen(keyfile_name_base) + 5);
-                                       snprintf(keyfile_name, strlen(keyfile_name_base) + 5, "%s.key", keyfile_name_base);
-                                       fprintf(stderr, "trying to read %s\n", keyfile_name);
-                                       keyfile = fopen(keyfile_name, "r");
-                                       line_nr = 0;
-                                       if (!keyfile) {
-                                               fprintf(stderr, "Error: unable to read %s: %s\n", keyfile_name, strerror(errno));
-                                       } else {
-                                               if (ldns_rr_new_frm_fp_l(&pubkey, keyfile, &default_ttl, NULL, NULL, &line_nr) ==
-                                                               LDNS_STATUS_OK) {
-                                                       ldns_key_set_pubkey_owner(key, ldns_rdf_clone(ldns_rr_owner(pubkey)));
-                                                       ldns_key_set_flags(key, ldns_rdf2native_int16(ldns_rr_rdf(pubkey, 0)));
-                                                       ldns_key_set_keytag(key, ldns_calc_keytag(pubkey));
-                                               }
-                                               ldns_key_list_push_key(keys, key);
-                                               ldns_zone_push_rr(orig_zone, ldns_rr_clone(pubkey));
-                                               ldns_rr_free(pubkey);
-                                               fclose(keyfile);
-                                       }
-                                       LDNS_FREE(keyfile_name);
-                               }
-#endif
                        } else {
                                fprintf(stderr, "Error reading key from %s at line %d\n", argv[argi], line_nr);
                        }
@@ -563,11 +568,6 @@ main(int argc, char *argv[])
                exit(EXIT_FAILURE);
        }
 
-       /* remove old RRSIGS and NSECS */
-       if (!leave_old_dnssec_data) {
-               strip_dnssec_records(orig_zone);
-       }
-
        /* walk through the keys, and add pubkeys to the orig zone */
        for (key_i = 0; key_i < ldns_key_list_key_count(keys); key_i++) {
                key = ldns_key_list_key(keys, key_i);
@@ -576,22 +576,55 @@ main(int argc, char *argv[])
                        pubkey = ldns_key2rr(key);
                        ldns_key_set_flags(key, ldns_rdf2native_int16(ldns_rr_rdf(pubkey, 0)));
                        ldns_key_set_keytag(key, ldns_calc_keytag(pubkey));
-                       ldns_zone_push_rr(orig_zone, pubkey);
+                       /*ldns_zone_push_rr(orig_zone, pubkey);*/
                        printf("Derived DNSKEY RR:\n");
                        ldns_rr_print(stdout, pubkey);
                }
        }
-                       
+
+       printf("[XX] convert to dnssec zone\n");
+       signed_zone = ldns_dnssec_zone_new();
+       if (ldns_dnssec_zone_add_rr(signed_zone, ldns_zone_soa(orig_zone)) !=
+           LDNS_STATUS_OK) {
+               fprintf(stderr, "Error adding SOA to dnssec zone, skipping record\n");
+       }
+
+       for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(orig_zone)); i++) {
+               if (ldns_dnssec_zone_add_rr(signed_zone, 
+                                                          ldns_rr_list_rr(ldns_zone_rrs(orig_zone), 
+                                                                                   i)) !=
+                   LDNS_STATUS_OK) {
+                       fprintf(stderr, "Error adding RR to dnssec zone");
+                       fprintf(stderr, ", skipping record:\n");
+                       ldns_rr_print(stderr, 
+                                           ldns_rr_list_rr(ldns_zone_rrs(orig_zone), i));
+               }
+       }
+
+       /* list to store newly created rrs, so we can free them later */
+       added_rrs = ldns_rr_list_new();
+
        if (use_nsec3) {
-               signed_zone = ldns_zone_sign_nsec3(orig_zone,
-                                                  keys,
-                                                  nsec3_algorithm,
-                                                  nsec3_flags,
-                                                  nsec3_iterations,
-                                                  nsec3_salt_length,
-                                                  nsec3_salt);
+               result = ldns_dnssec_zone_sign_nsec3(signed_zone,
+                                                                         added_rrs,
+                                                                         keys,
+                                                                         ldns_dnssec_default_replace_signatures,
+                                                                         NULL,
+                                                                         nsec3_algorithm,
+                                                                         0,
+                                                                         nsec3_iterations,
+                                                                         nsec3_salt_length,
+                                                                         nsec3_salt);
        } else {
-               signed_zone = ldns_zone_sign(orig_zone, keys);
+               result = ldns_dnssec_zone_sign(signed_zone,
+                                                 added_rrs,
+                                                 keys,
+                                                 ldns_dnssec_default_replace_signatures,
+                                                 NULL);
+       }
+       if (result != LDNS_STATUS_OK) {
+               fprintf(stderr, "Error signing zone: %s\n",
+                          ldns_get_errorstr_by_id(result));
        }
        
        if (!outputfile_name) {
@@ -604,7 +637,7 @@ main(int argc, char *argv[])
                if (!outputfile) {
                        fprintf(stderr, "Unable to open %s for writing: %s\n", outputfile_name, strerror(errno));
                } else {
-                       ldns_zone_print(outputfile, signed_zone);
+                       ldns_dnssec_zone_print(outputfile, signed_zone);
                        fclose(outputfile);
                }
 /*
@@ -623,8 +656,10 @@ main(int argc, char *argv[])
                exit(EXIT_FAILURE);
        }
        
+       ldns_dnssec_zone_free(signed_zone);
        ldns_key_list_free(keys);
        ldns_zone_deep_free(orig_zone);
+       ldns_rr_list_deep_free(added_rrs);
        
        LDNS_FREE(outputfile_name);
        
diff --git a/keys.c b/keys.c
index 87bbd3a7d1fd01c729227ccc2f77dacfbb10ddb7..dd35bb833efb62a67e5b545443368c3253fc93f5 100644 (file)
--- a/keys.c
+++ b/keys.c
@@ -54,6 +54,7 @@ ldns_key_new()
                return NULL;
        } else {
                /* some defaults - not sure wether to do this */
+               ldns_key_set_use(newkey, true);
                ldns_key_set_flags(newkey, LDNS_KEY_ZONE_KEY);
                ldns_key_set_origttl(newkey, 0);
                ldns_key_set_keytag(newkey, 0);
@@ -63,7 +64,7 @@ ldns_key_new()
                ldns_key_set_hmac_key(newkey, NULL);
                return newkey;
        }
-return NULL;
+       return NULL;
 }
 
 ldns_status 
@@ -651,6 +652,23 @@ ldns_key_algorithm(const ldns_key *k)
        return k->_alg;
 }
 
+void
+ldns_key_set_use(ldns_key *k, bool v)
+{
+       if (k) {
+               k->_use = v;
+       }
+}
+
+bool
+ldns_key_use(const ldns_key *k)
+{
+       if (k) {
+               return k->_use;
+       }
+       return false;
+}
+
 EVP_PKEY *
 ldns_key_evp_key(const ldns_key *k)
 {
@@ -718,6 +736,16 @@ ldns_key_pubkey_owner(const ldns_key *k)
 }
 
 /* write */
+void
+ldns_key_list_set_use(ldns_key_list *keys, bool v)
+{
+       size_t i;
+
+       for (i = 0; i < ldns_key_list_key_count(keys); i++) {
+               ldns_key_set_use(ldns_key_list_key(keys, i), v);
+       }
+}
+
 void            
 ldns_key_list_set_key_count(ldns_key_list *key, size_t count)
 {
index 09ef3efa6127f7514f5c8a79c6e6d741b6f61881..53ad1ece74e3c176e51b4f695a0b97ae7ea81f2b 100644 (file)
@@ -31,6 +31,7 @@
 #include <ldns/keys.h>
 #include <ldns/zone.h>
 #include <ldns/resolver.h>
+#include <ldns/dnssec_zone.h>
 
 #define LDNS_MAX_KEYLEN                2048
 #define LDNS_DNSSEC_KEYPROTO   3
@@ -49,6 +50,12 @@ struct ldns_dnssec_data_chain_struct {
   ldns_dnssec_data_chain *parent;
 };
 
+/** return values for the old-signature callback */
+#define LDNS_SIGNATURE_LEAVE_ADD_NEW 0
+#define LDNS_SIGNATURE_LEAVE_NO_ADD 1
+#define LDNS_SIGNATURE_REMOVE_ADD_NEW 2
+#define LDNS_SIGNATURE_REMOVE_NO_ADD 3
+
 /**
  * Returns the first RRSIG rr that corresponds to the rrset with the given name and type
  * TODO: may be more, use all sigs...
@@ -607,16 +614,99 @@ ldns_rdf *ldns_nsec3_hash_name(ldns_rdf *name, uint8_t algorithm, uint16_t itera
  */
 ldns_status ldns_pkt_verify(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, ldns_rr_list *k, ldns_rr_list *s, ldns_rr_list *good_keys);
 
+/** 
+ * Default callback function to always leave present signatures, and
+ * add new ones
+ * \param[in] sig The signature to check for removal (unused)
+ * \param[in] n Optional argument (unused)
+ * \return LDNS_SIGNATURE_LEAVE_ADD_NEW
+ */
+int ldns_dnssec_default_add_to_signatures(ldns_rr *sig, void *n);
+/** 
+ * Default callback function to always leave present signatures, and
+ * add no new ones for the keys of these signatures
+ * \param[in] sig The signature to check for removal (unused)
+ * \param[in] n Optional argument (unused)
+ * \return LDNS_SIGNATURE_LEAVE_NO_ADD
+ */
+int ldns_dnssec_default_leave_signatures(ldns_rr *sig, void *n);
+/** 
+ * Default callback function to always remove present signatures, but
+ * add no new ones
+ * \param[in] sig The signature to check for removal (unused)
+ * \param[in] n Optional argument (unused)
+ * \return LDNS_SIGNATURE_REMOVE_NO_ADD
+ */
+int ldns_dnssec_default_delete_signatures(ldns_rr *sig, void *n);
+/** 
+ * Default callback function to always leave present signatures, and
+ * add new ones
+ * \param[in] sig The signature to check for removal (unused)
+ * \param[in] n Optional argument (unused)
+ * \return LDNS_SIGNATURE_REMOVE_ADD_NEW
+ */
+int ldns_dnssec_default_replace_signatures(ldns_rr *sig, void *n);
+
 /**
  * signs the given zone with the given new zone
- * returns a newly allocated signed zone
- * extra arguments will come later (expiration etc.)
+ * 
+ * \param[in] zone the zone to sign
+ * \param[in] key_list the list of keys to sign the zone with
+ * \param[in] new_rrs newly created resource records are added to this list, to free them later
+ * \param[in] func callback function that decides what to do with old signatures
+ * \param[in] arg optional argument for the callback function
+ * \return LDNS_STATUS_OK on success, an error code otherwise
+ */
+ldns_status ldns_dnssec_zone_sign(ldns_dnssec_zone *zone,
+                                                   ldns_rr_list *new_rrs,
+                                                   ldns_key_list *key_list,
+                                                   int (*func)(ldns_rr *, void *),
+                                                   void *arg);
+
+/**
+ * signs the given zone with the given new zone, with NSEC3
  *
  * \param[in] zone the zone to sign
  * \param[in] key_list the list of keys to sign the zone with
- * \return the signed zone
+ * \param[in] new_rrs newly created resource records are added to this list, to free them later
+ * \param[in] func callback function that decides what to do with old signatures
+ * \param[in] arg optional argument for the callback function
+ * \param[in] algorithm the NSEC3 hashing algorithm to use
+ * \param[in] flags NSEC3 flags
+ * \param[in] iterations the number of NSEC3 hash iterations to use
+ * \param[in] salt_length the length (in octets) of the NSEC3 salt
+ * \param[in] salt the NSEC3 salt data
+ * \return LDNS_STATUS_OK on success, an error code otherwise
+ */
+ldns_status ldns_dnssec_zone_sign_nsec3(ldns_dnssec_zone *zone,
+                                                               ldns_rr_list *new_rrs,
+                                                               ldns_key_list *key_list,
+                                                               int (*func)(ldns_rr *, void *),
+                                                               void *arg,
+                                                               uint8_t algorithm,
+                                                               uint8_t flags,
+                                                               uint16_t iterations,
+                                                               uint8_t salt_length,
+                                                               uint8_t *salt);
+
+/**
+ * Signs the zone, and returns a newly allocated signed zone
+ * \param[in] zone the zone to sign
+ * \param[in] key_list list of keys to sign with
+ * \return signed zone
  */
 ldns_zone *ldns_zone_sign(const ldns_zone *zone, ldns_key_list *key_list);
+/**
+ * Signs the zone with NSEC3, and returns a newly allocated signed zone
+ * \param[in] zone the zone to sign
+ * \param[in] key_list list of keys to sign with
+ * \param[in] algorithm the NSEC3 hashing algorithm to use
+ * \param[in] flags NSEC3 flags
+ * \param[in] iterations the number of NSEC3 hash iterations to use
+ * \param[in] salt_length the length (in octets) of the NSEC3 salt
+ * \param[in] salt the NSEC3 salt data
+ * \return signed zone
+ */
 ldns_zone *ldns_zone_sign_nsec3(ldns_zone *zone, ldns_key_list *key_list, uint8_t algorithm, uint8_t flags, uint16_t iterations, uint8_t salt_length, uint8_t *salt);
  
 /**
diff --git a/ldns/dnssec_zone.h b/ldns/dnssec_zone.h
new file mode 100644 (file)
index 0000000..4e20ea3
--- /dev/null
@@ -0,0 +1,329 @@
+/*
+ * special zone file structures and functions for better dnssec handling
+ *
+ * A zone contains a SOA dnssec_zone_rrset, and an AVL tree of 'normal'
+ * dnssec_zone_rrsets, indexed by name and type
+ */
+
+#ifndef LDNS_DNSSEC_ZONE_H
+#define LDNS_DNSSEC_ZONE_H
+#include <ldns/ldns.h>
+#include <ldns/rbtree.h>
+
+/**
+ * Singly linked list of rrs
+ */
+typedef struct ldns_struct_dnssec_rrs ldns_dnssec_rrs;
+struct ldns_struct_dnssec_rrs
+{
+       ldns_rr *rr;
+       ldns_dnssec_rrs *next;
+};
+
+/**
+ * Singly linked list of RRsets
+ */
+typedef struct ldns_struct_dnssec_rrsets ldns_dnssec_rrsets;
+struct ldns_struct_dnssec_rrsets
+{
+       ldns_dnssec_rrs *rrs;
+       ldns_rr_type type;
+       ldns_dnssec_rrs *signatures;
+       ldns_dnssec_rrsets *next;
+};
+
+/**
+ * Structure containing all resource records for a domain name
+ * Including the derived NSEC3, if present
+ */
+typedef struct ldns_struct_dnssec_name ldns_dnssec_name;
+struct ldns_struct_dnssec_name
+{
+       /**
+        * pointer to a dname containing the name.
+        * Usually points to the owner name of the first RR of the first RRset
+        */
+       ldns_rdf *name;
+       /** 
+        * Usually, the name is a pointer to the owner name of the first rr for
+        * this name, but sometimes there is no actual data to point to, 
+        * for instance in
+        * names representing empty nonterminals. If so, set alloced to true to
+        * indicate that this data must also be freed when the name is freed
+        */
+       bool name_alloced;
+       /**
+        * The rrsets for this name
+        */
+       ldns_dnssec_rrsets *rrsets;
+       /**
+        * NSEC pointing to the next name (or NSEC3 pointing to the next NSEC3)
+        */
+       ldns_rr *nsec;
+       /**
+        * signatures for the NSEC record
+        */
+       ldns_dnssec_rrs *nsec_signatures;
+};
+
+/**
+ * Structure containing a dnssec zone
+ */
+struct ldns_struct_dnssec_zone {
+       /** points to the name containing the SOA RR */
+       ldns_dnssec_name *soa;
+       /** tree of ldns_dnssec_names */
+       ldns_rbtree_t *names;
+};
+typedef struct ldns_struct_dnssec_zone ldns_dnssec_zone;
+
+/**
+ * Creates a new entry for 1 pointer to an rr and 1 pointer to the next rrs
+ * \return the allocated data
+ */
+ldns_dnssec_rrs *
+ldns_dnssec_rrs_new();
+
+/**
+ * Frees the list of rrs, but *not* its data
+ *
+ * \param[in] rrs the data structure to free
+ */
+void
+ldns_dnssec_rrs_free(ldns_dnssec_rrs *rrs);
+
+/**
+ * Adds an RR to the list of RRs. The list will remain ordered
+ *
+ * \param[in] rrs the list to add to
+ * \param[in] rr the RR to add
+ * \return LDNS_STATUS_OK on success
+ */
+ldns_status
+ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr);
+
+/**
+ * Prints the given rrs to the file descriptor
+ *
+ * \param[in] out the file descriptor to print to
+ * \param[in] rrs the list of RRs to print
+ */
+void
+ldns_dnssec_rrs_print(FILE *out, ldns_dnssec_rrs *rrs);
+
+/**
+ * Creates a new list (entry) of RRsets
+ * \return the newly allocated structure
+ */
+ldns_dnssec_rrsets *
+ldns_dnssec_rrsets_new();
+
+/**
+ * Frees the list of rrsets and their rrs, but *not* their data
+ *
+ * \param[in] rrsets the data structure to free
+ */
+void
+ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets);
+
+/**
+ * Returns the rr type of the rrset (that is head of the given list)
+ *
+ * \param[in] rrsets the rrset to get the type of
+ * \return the rr type
+ */
+ldns_rr_type
+ldns_dnssec_rrsets_type(ldns_dnssec_rrsets *rrsets);
+
+/**
+ * Sets the RR type of the rrset (that is head of the given list)
+ *
+ * \param[in] rrsets the rrset to set the type of
+ * \param[in] type the type to set
+ * \return LDNS_STATUS_OK on success
+ */
+ldns_status
+ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets,
+                                          ldns_rr_type type);
+
+/**
+ * Add an ldns_rr to the corresponding RRset in the given list of RRsets.
+ * If it is not present, add it as a new RRset with 1 record.
+ *
+ * \param[in] rrsets the list of rrsets to add the RR to
+ * \param[in] rr the rr to add to the list of rrsets
+ * \return LDNS_STATUS_OK on success
+ */
+ldns_status
+ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr);
+
+/**
+ * Print the given list of rrsets to the fiven file descriptor
+ * 
+ * \param[in] out the file descriptor to print to
+ * \param[in] rrsets the list of RRsets to print
+ * \param[in] follow if set to false, only print the first RRset
+ */ 
+void
+ldns_dnssec_rrsets_print(FILE *out, ldns_dnssec_rrsets *rrsets, bool follow);
+
+/**
+ * Create a new data structure for a dnssec name
+ * \return the allocated structure
+ */
+ldns_dnssec_name *
+ldns_dnssec_name_new();
+
+/**
+ * Create a new data structure for a dnssec name for the given RR
+ *
+ * \param[in] rr the RR to derive properties from, and to add to the name
+ */
+ldns_dnssec_name *
+ldns_dnssec_name_new_frm_rr(ldns_rr *rr);
+
+/**
+ * Frees the name structure and its rrs and rrsets.
+ * Individual ldns_rr records therein are not freed
+ *
+ * \param[in] name the structure to free
+ */
+void
+ldns_dnssec_name_free(ldns_dnssec_name *name);
+
+/**
+ * Returns the domain name of the given dnssec_name structure
+ *
+ * \param[in] name the dnssec name to get the domain name from
+ * \return the domain name
+ */
+ldns_rdf *
+ldns_dnssec_name_name(ldns_dnssec_name *name);
+
+
+/**
+ * Sets the domain name of the given dnssec_name structure
+ *
+ * \param[in] name the dnssec name to set the domain name of
+ * \param[in] dname the domain name to set it to. This data is *not* copied.
+ */
+void
+ldns_dnssec_name_set_name(ldns_dnssec_name *name,
+                                                 ldns_rdf *dname);
+
+/**
+ * Sets the NSEC(3) RR of the given dnssec_name structure
+ *
+ * \param[in] name the dnssec name to set the domain name of
+ * \param[in] nsec the nsec rr to set it to. This data is *not* copied.
+ */
+void
+ldns_dnssec_name_set_nsec(ldns_dnssec_name *name, ldns_rr *nsec);
+
+/**
+ * 
+ */
+ldns_status
+ldns_dnssec_name_add_rr_to_current(ldns_dnssec_name *name,
+                                                                ldns_rr *rr);
+/**
+ *
+ */
+ldns_status
+ldns_dnssec_name_add_rr(ldns_dnssec_name *name,
+                                               ldns_rr *rr);
+
+/**
+ * Find the RRset with the given type in within this name structure
+ *
+ * \param[in] name the name to find the RRset in
+ * \param[in] type the type of the RRset to find
+ * \return the RRset, or NULL if not present
+ */
+ldns_dnssec_rrsets *
+ldns_dnssec_name_find_rrset(ldns_dnssec_name *name,
+                                          ldns_rr_type type);
+
+/**
+ * Find the RRset with the given name and type in the zone
+ *
+ * \param[in] zone the zone structure to find the RRset in
+ * \param[in] dname the domain name of the RRset to find
+ * \param[in] type the type of the RRset to find
+ * \return the RRset, or NULL if not present
+ */
+ldns_dnssec_rrsets *
+ldns_dnssec_zone_find_rrset(ldns_dnssec_zone *zone,
+                                          ldns_rdf *dname,
+                                          ldns_rr_type type);
+
+/**
+ * Prints the RRs in the  dnssec name structure to the given
+ * file descriptor
+ *
+ * \param[in] out the file descriptor to print to
+ * \param[in] name the name structure to print the contents of
+ */
+void
+ldns_dnssec_name_print(FILE *out, ldns_dnssec_name *name);
+
+/**
+ * Creates a new dnssec_zone structure
+ * \return the allocated structure
+ */
+ldns_dnssec_zone *
+ldns_dnssec_zone_new();
+
+/**
+ * Frees the given zone structure, and its rbtree of dnssec_names
+ * Individual ldns_rr RRs within those names are *not* freed
+ *
+ * \param[in] zone the zone to free
+ */ 
+void
+ldns_dnssec_zone_free(ldns_dnssec_zone *zone);
+
+/**
+ * Adds the given RR to the zone.
+ * It find whether there is a dnssec_name with that name present.
+ * If so, add it to that, if not create a new one. 
+ * Special handling of NSEC and RRSIG provided
+ *
+ * \param[in] zone the zone to add the RR to
+ * \param[in] rr The RR to add
+ * \return LDNS_STATUS_OK on success, an error code otherwise
+ */
+ldns_status
+ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr);
+
+/**
+ * Prints the rbtree of ldns_dnssec_name structures to the file descriptor
+ *
+ * \param[in] out the file descriptor to print the names to
+ * \param[in] tree the tree of ldns_dnssec_name structures to print
+ * \param[in] print_soa if true, print SOA records, if false, skip them
+ */
+void
+ldns_dnssec_zone_names_print(FILE *out, ldns_rbtree_t *tree, bool print_soa);
+
+/**
+ * Prints the complete zone to the given file descriptor
+ *
+ * \param[in] out the file descriptor to print to
+ * \param[in] zone the dnssec_zone to print
+ */
+void
+ldns_dnssec_zone_print(FILE *out, ldns_dnssec_zone *zone);
+
+/**
+ * Adds explicit dnssec_name structures for the empty nonterminals
+ * in this zone. (this is needed for NSEC3 generation)
+ *
+ * \param[in] zone the zone to check for empty nonterminals
+ * return LDNS_STATUS_OK on success.
+ */
+ldns_status
+ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone);
+
+#endif
index 2b86286164757a209a300f19c9e14c547a5ea481..39ec8940690cdc6e560a2c5aafa2459fe4ccf482 100644 (file)
@@ -18,8 +18,7 @@
 
 #include <ldns/util.h>
 
-enum ldns_enum_status 
-{
+enum ldns_enum_status {
        LDNS_STATUS_OK, 
        LDNS_STATUS_EMPTY_LABEL,
        LDNS_STATUS_LABEL_OVERFLOW,
@@ -58,39 +57,41 @@ enum ldns_enum_status
        LDNS_STATUS_CRYPTO_BOGUS,
        LDNS_STATUS_CRYPTO_SIG_EXPIRED,
        LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED,
-        LDNS_STATUS_CRYPTO_TSIG_BOGUS,
-        LDNS_STATUS_CRYPTO_TSIG_ERR,
+       LDNS_STATUS_CRYPTO_TSIG_BOGUS,
+       LDNS_STATUS_CRYPTO_TSIG_ERR,
        LDNS_STATUS_CRYPTO_EXPIRATION_BEFORE_INCEPTION,
-        LDNS_STATUS_CRYPTO_TYPE_COVERED_ERR,
-        LDNS_STATUS_ENGINE_KEY_NOT_LOADED,
-        LDNS_STATUS_NSEC3_ERR,
-        LDNS_STATUS_RES_NO_NS,
-        LDNS_STATUS_RES_QUERY,
-        LDNS_STATUS_WIRE_INCOMPLETE_HEADER,
-        LDNS_STATUS_WIRE_INCOMPLETE_QUESTION,
-        LDNS_STATUS_WIRE_INCOMPLETE_ANSWER,
-        LDNS_STATUS_WIRE_INCOMPLETE_AUTHORITY,
-        LDNS_STATUS_WIRE_INCOMPLETE_ADDITIONAL,
-        LDNS_STATUS_NO_DATA,
-        LDNS_STATUS_CERT_BAD_ALGORITHM,
-        LDNS_STATUS_SYNTAX_TYPE_ERR,
-        LDNS_STATUS_SYNTAX_CLASS_ERR,
-        LDNS_STATUS_SYNTAX_TTL_ERR,
-        LDNS_STATUS_SYNTAX_RDATA_ERR,
-        LDNS_STATUS_SYNTAX_DNAME_ERR,
-        LDNS_STATUS_SYNTAX_VERSION_ERR,
-        LDNS_STATUS_SYNTAX_ALG_ERR,
-        LDNS_STATUS_SYNTAX_KEYWORD_ERR,
-        LDNS_STATUS_SYNTAX_TTL,
-        LDNS_STATUS_SYNTAX_ORIGIN,
-        LDNS_STATUS_SYNTAX_EMPTY,
-        LDNS_STATUS_SYNTAX_ITERATIONS_OVERFLOW,
-        LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR,
-        LDNS_STATUS_SOCKET_ERROR,
-        LDNS_STATUS_SYNTAX_ERR,
-        LDNS_STATUS_DNSSEC_EXISTENCE_DENIED,
-        LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED,
-        LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED
+       LDNS_STATUS_CRYPTO_TYPE_COVERED_ERR,
+       LDNS_STATUS_ENGINE_KEY_NOT_LOADED,
+       LDNS_STATUS_NSEC3_ERR,
+       LDNS_STATUS_RES_NO_NS,
+       LDNS_STATUS_RES_QUERY,
+       LDNS_STATUS_WIRE_INCOMPLETE_HEADER,
+       LDNS_STATUS_WIRE_INCOMPLETE_QUESTION,
+       LDNS_STATUS_WIRE_INCOMPLETE_ANSWER,
+       LDNS_STATUS_WIRE_INCOMPLETE_AUTHORITY,
+       LDNS_STATUS_WIRE_INCOMPLETE_ADDITIONAL,
+       LDNS_STATUS_NO_DATA,
+       LDNS_STATUS_CERT_BAD_ALGORITHM,
+       LDNS_STATUS_SYNTAX_TYPE_ERR,
+       LDNS_STATUS_SYNTAX_CLASS_ERR,
+       LDNS_STATUS_SYNTAX_TTL_ERR,
+       LDNS_STATUS_SYNTAX_RDATA_ERR,
+       LDNS_STATUS_SYNTAX_DNAME_ERR,
+       LDNS_STATUS_SYNTAX_VERSION_ERR,
+       LDNS_STATUS_SYNTAX_ALG_ERR,
+       LDNS_STATUS_SYNTAX_KEYWORD_ERR,
+       LDNS_STATUS_SYNTAX_TTL,
+       LDNS_STATUS_SYNTAX_ORIGIN,
+       LDNS_STATUS_SYNTAX_EMPTY,
+       LDNS_STATUS_SYNTAX_ITERATIONS_OVERFLOW,
+       LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR,
+       LDNS_STATUS_SOCKET_ERROR,
+       LDNS_STATUS_SYNTAX_ERR,
+       LDNS_STATUS_DNSSEC_EXISTENCE_DENIED,
+       LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED,
+       LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED,
+       LDNS_STATUS_DNSSEC_NAME_ADDED_RIGHT,
+       LDNS_STATUS_DNSSEC_NAME_ADDED_LEFT
 };
 typedef enum ldns_enum_status ldns_status;
 
index 6bf716502348771cb0febf7f446bf90c37614a10..98e83fb3c31fa9041d1eae713f6a103b334f8de6 100644 (file)
@@ -95,6 +95,8 @@ typedef enum ldns_enum_signing_algorithm ldns_signing_algorithm;
  */
 struct ldns_struct_key {
        ldns_signing_algorithm _alg;
+       /** Whether to use this key when signing */
+       bool _use;
        /** Storage pointers for the types of keys supported */
        /* TODO remove unions? */
        struct {
@@ -400,6 +402,18 @@ DSA *ldns_key_dsa_key(const ldns_key *k);
  * \return the algorithm
  */
 ldns_signing_algorithm ldns_key_algorithm(const ldns_key *k);
+/**
+ * set the use flag
+ * \param[in] k the key
+ * \param[in] v the boolean value to set the _use field to
+ */
+void ldns_key_set_use(ldns_key *k, bool v);
+/**
+ * return the use flag
+ * \param[in] k the key
+ * \return the boolean value of the _use field
+ */
+bool ldns_key_use(const ldns_key *k);
 /**
  * return the hmac key data
  * \param[in] k the key
@@ -442,6 +456,14 @@ uint16_t ldns_key_keytag(const ldns_key *k);
  * \return the owner
  */
 ldns_rdf *ldns_key_pubkey_owner(const ldns_key *k);
+/**
+ * Set the 'use' flag for all keys in the list
+ * \param[in] keys The key_list
+ * \param[in] v The value to set the use flags to
+ */
+void
+ldns_key_list_set_use(ldns_key_list *keys, bool v);
+
 /**
  * return the flag of the key
  * \param[in] k the key
index b1f7bd0adbad34673f15c16d13871ce433772809..0a746ff844eaf2c366d1cbbd5d524c985bc0e212 100644 (file)
@@ -113,6 +113,8 @@ Or you can just use the menu above to browse through the API docs.
 #include <ldns/keys.h>
 #include <ldns/parse.h>
 #include <ldns/zone.h>
+#include <ldns/dnssec_zone.h>
+#include <ldns/rbtree.h>
 
 #define LDNS_IP4ADDRLEN      (32/8)
 #define LDNS_IP6ADDRLEN      (128/8)
diff --git a/ldns/rbtree.h b/ldns/rbtree.h
new file mode 100644 (file)
index 0000000..7363847
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * rbtree.h -- generic red-black tree
+ *
+ * Copyright (c) 2001-2007, NLnet Labs. All rights reserved.
+ * 
+ * This software is open source.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/**
+ * \file
+ * Red black tree. Implementation taken from NSD 3.0.5, adjusted for use
+ * in unbound (memory allocation, logging and so on).
+ */
+
+#ifndef LDNS_RBTREE_H_
+#define        LDNS_RBTREE_H_
+
+/**
+ * This structure must be the first member of the data structure in
+ * the rbtree.  This allows easy casting between an rbnode_t and the
+ * user data (poor man's inheritance).
+ */
+typedef struct ldns_rbnode_t ldns_rbnode_t;
+/**
+ * The rbnode_t struct definition.
+ */
+struct ldns_rbnode_t {
+       /** parent in rbtree, RBTREE_NULL for root */
+       ldns_rbnode_t   *parent;
+       /** left node (smaller items) */
+       ldns_rbnode_t   *left;
+       /** right node (larger items) */
+       ldns_rbnode_t   *right;
+       /** pointer to sorting key */
+       const void *key;
+       /** pointer to data */
+       const void *data;
+       /** colour of this node */
+       uint8_t     color;
+};
+
+/** The nullpointer, points to empty node */
+#define        LDNS_RBTREE_NULL &ldns_rbtree_null_node
+/** the global empty node */
+extern ldns_rbnode_t   ldns_rbtree_null_node;
+
+/** An entire red black tree */
+typedef struct ldns_rbtree_t ldns_rbtree_t;
+/** definition for tree struct */
+struct ldns_rbtree_t {
+       /** The root of the red-black tree */
+       ldns_rbnode_t    *root;
+
+       /** The number of the nodes in the tree */
+       size_t       count;
+
+       /** 
+        * Key compare function. <0,0,>0 like strcmp. 
+        * Return 0 on two NULL ptrs. 
+        */
+       int (*cmp) (const void *, const void *);
+};
+
+/** 
+ * Create new tree (malloced) with given key compare function. 
+ * @param cmpf: compare function (like strcmp) takes pointers to two keys.
+ * @return: new tree, empty.
+ */
+ldns_rbtree_t *ldns_rbtree_create(int (*cmpf)(const void *, const void *));
+
+/**
+ * Free the complete tree (but not its keys)
+ * @param rbtree The tree to free
+ */
+void ldns_rbtree_free(ldns_rbtree_t *rbtree);
+
+/** 
+ * Init a new tree (malloced by caller) with given key compare function. 
+ * @param rbtree: uninitialised memory for new tree, returned empty.
+ * @param cmpf: compare function (like strcmp) takes pointers to two keys.
+ */
+void ldns_rbtree_init(ldns_rbtree_t *rbtree, int (*cmpf)(const void *, const void *));
+
+/** 
+ * Insert data into the tree. 
+ * @param rbtree: tree to insert to.
+ * @param data: element to insert. 
+ * @return: data ptr or NULL if key already present. 
+ */
+ldns_rbnode_t *ldns_rbtree_insert(ldns_rbtree_t *rbtree, ldns_rbnode_t *data);
+
+/**
+ * Insert data into the tree (reversed arguments, for use as callback)
+ * \param[in] data element to insert
+ * \param[out] rbtree tree to insert in to
+ * \return data ptr or NULL if key is already present
+ */
+void ldns_rbtree_insert_vref(ldns_rbnode_t *data, void *rbtree);
+
+/**
+ * Delete element from tree.
+ * @param rbtree: tree to delete from.
+ * @param key: key of item to delete.
+ * @return: node that is now unlinked from the tree. User to delete it. 
+ * returns 0 if node not present 
+ */
+ldns_rbnode_t *ldns_rbtree_delete(ldns_rbtree_t *rbtree, const void *key);
+
+/**
+ * Find key in tree. Returns NULL if not found.
+ * @param rbtree: tree to find in.
+ * @param key: key that must match.
+ * @return: node that fits or NULL.
+ */
+ldns_rbnode_t *ldns_rbtree_search(ldns_rbtree_t *rbtree, const void *key);
+
+/**
+ * Find, but match does not have to be exact.
+ * @param rbtree: tree to find in.
+ * @param key: key to find position of.
+ * @param result: set to the exact node if present, otherwise to element that
+ *   precedes the position of key in the tree. NULL if no smaller element.
+ * @return: true if exact match in result. Else result points to <= element,
+ * or NULL if key is smaller than the smallest key. 
+ */
+int ldns_rbtree_find_less_equal(ldns_rbtree_t *rbtree, const void *key, 
+       ldns_rbnode_t **result);
+
+/**
+ * Returns first (smallest) node in the tree
+ * @param rbtree: tree
+ * @return: smallest element or NULL if tree empty.
+ */
+ldns_rbnode_t *ldns_rbtree_first(ldns_rbtree_t *rbtree);
+
+/**
+ * Returns last (largest) node in the tree
+ * @param rbtree: tree
+ * @return: largest element or NULL if tree empty.
+ */
+ldns_rbnode_t *ldns_rbtree_last(ldns_rbtree_t *rbtree);
+
+/**
+ * Returns next larger node in the tree
+ * @param rbtree: tree
+ * @return: next larger element or NULL if no larger in tree.
+ */
+ldns_rbnode_t *ldns_rbtree_next(ldns_rbnode_t *rbtree);
+
+/**
+ * Returns previous smaller node in the tree
+ * @param rbtree: tree
+ * @return: previous smaller element or NULL if no previous in tree.
+ */
+ldns_rbnode_t *ldns_rbtree_previous(ldns_rbnode_t *rbtree);
+
+/**
+ * split off 'elements' number of elements from the start
+ * of the name tree and return a new tree containing those
+ * elements
+ */
+ldns_rbtree_t *ldns_dnssec_rbtree_split(ldns_rbtree_t *tree, 
+                                                               size_t elements);
+
+/**
+ * add all node from the second tree to the first (removing them from the
+ * second), and fix up nsec(3)s if present
+ */
+void ldns_dnssec_rbtree_join(ldns_rbtree_t *tree1,
+                                           ldns_rbtree_t *tree2);
+
+/**
+ * Call with node=variable of struct* with rbnode_t as first element.
+ * with type is the type of a pointer to that struct. 
+ */
+#define RBTREE_FOR(node, type, rbtree) \
+       for(node=(type)ldns_rbtree_first(rbtree); \
+               (ldns_rbnode_t*)node != LDNS_RBTREE_NULL; \
+               node = (type)ldns_rbtree_next((ldns_rbnode_t*)node))
+
+/**
+ * Call function for all elements in the redblack tree, such that
+ * leaf elements are called before parent elements. So that all
+ * elements can be safely free()d.
+ * Note that your function must not remove the nodes from the tree.
+ * Since that may trigger rebalances of the rbtree.
+ * @param tree: the tree
+ * @param func: function called with element and user arg.
+ *     The function must not alter the rbtree.
+ * @param arg: user argument.
+ */
+void traverse_postorder(ldns_rbtree_t* tree, void (*func)(ldns_rbnode_t*, void*),
+       void* arg);
+
+#endif /* UTIL_RBTREE_H_ */
diff --git a/rbtree.c b/rbtree.c
new file mode 100644 (file)
index 0000000..921e0b6
--- /dev/null
+++ b/rbtree.c
@@ -0,0 +1,655 @@
+/*
+ * rbtree.c -- generic red black tree
+ *
+ * Taken from Unbound, modified for ldns
+ *
+ * Copyright (c) 2001-2007, NLnet Labs. All rights reserved.
+ * 
+ * This software is open source.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/**
+ * \file
+ * Implementation of a redblack tree.
+ */
+
+#include <ldns/config.h>
+#include <ldns/rbtree.h>
+
+/** Node colour black */
+#define        BLACK   0
+/** Node colour red */
+#define        RED     1
+
+/** the NULL node, global alloc */
+ldns_rbnode_t  ldns_rbtree_null_node = {
+       LDNS_RBTREE_NULL,       /* Parent.  */
+       LDNS_RBTREE_NULL,       /* Left.  */
+       LDNS_RBTREE_NULL,       /* Right.  */
+       NULL,                   /* Key.  */
+       BLACK           /* Color.  */
+};
+
+/** rotate subtree left (to preserve redblack property) */
+static void ldns_rbtree_rotate_left(ldns_rbtree_t *rbtree, ldns_rbnode_t *node);
+/** rotate subtree right (to preserve redblack property) */
+static void ldns_rbtree_rotate_right(ldns_rbtree_t *rbtree, ldns_rbnode_t *node);
+/** Fixup node colours when insert happened */
+static void ldns_rbtree_insert_fixup(ldns_rbtree_t *rbtree, ldns_rbnode_t *node);
+/** Fixup node colours when delete happened */
+static void ldns_rbtree_delete_fixup(ldns_rbtree_t* rbtree, ldns_rbnode_t* child, ldns_rbnode_t* child_parent);
+
+/*
+ * Creates a new red black tree, intializes and returns a pointer to it.
+ *
+ * Return NULL on failure.
+ *
+ */
+ldns_rbtree_t *
+ldns_rbtree_create (int (*cmpf)(const void *, const void *))
+{
+       ldns_rbtree_t *rbtree;
+
+       /* Allocate memory for it */
+       rbtree = (ldns_rbtree_t *) malloc(sizeof(ldns_rbtree_t));
+       if (!rbtree) {
+               return NULL;
+       }
+
+       /* Initialize it */
+       ldns_rbtree_init(rbtree, cmpf);
+
+       return rbtree;
+}
+
+void 
+ldns_rbtree_init(ldns_rbtree_t *rbtree, int (*cmpf)(const void *, const void *))
+{
+       /* Initialize it */
+       rbtree->root = LDNS_RBTREE_NULL;
+       rbtree->count = 0;
+       rbtree->cmp = cmpf;
+}
+
+/*
+ * Rotates the node to the left.
+ *
+ */
+static void
+ldns_rbtree_rotate_left(ldns_rbtree_t *rbtree, ldns_rbnode_t *node)
+{
+       ldns_rbnode_t *right = node->right;
+       node->right = right->left;
+       if (right->left != LDNS_RBTREE_NULL)
+               right->left->parent = node;
+
+       right->parent = node->parent;
+
+       if (node->parent != LDNS_RBTREE_NULL) {
+               if (node == node->parent->left) {
+                       node->parent->left = right;
+               } else  {
+                       node->parent->right = right;
+               }
+       } else {
+               rbtree->root = right;
+       }
+       right->left = node;
+       node->parent = right;
+}
+
+/*
+ * Rotates the node to the right.
+ *
+ */
+static void
+ldns_rbtree_rotate_right(ldns_rbtree_t *rbtree, ldns_rbnode_t *node)
+{
+       ldns_rbnode_t *left = node->left;
+       node->left = left->right;
+       if (left->right != LDNS_RBTREE_NULL)
+               left->right->parent = node;
+
+       left->parent = node->parent;
+
+       if (node->parent != LDNS_RBTREE_NULL) {
+               if (node == node->parent->right) {
+                       node->parent->right = left;
+               } else  {
+                       node->parent->left = left;
+               }
+       } else {
+               rbtree->root = left;
+       }
+       left->right = node;
+       node->parent = left;
+}
+
+static void
+ldns_rbtree_insert_fixup(ldns_rbtree_t *rbtree, ldns_rbnode_t *node)
+{
+       ldns_rbnode_t   *uncle;
+
+       /* While not at the root and need fixing... */
+       while (node != rbtree->root && node->parent->color == RED) {
+               /* If our parent is left child of our grandparent... */
+               if (node->parent == node->parent->parent->left) {
+                       uncle = node->parent->parent->right;
+
+                       /* If our uncle is red... */
+                       if (uncle->color == RED) {
+                               /* Paint the parent and the uncle black... */
+                               node->parent->color = BLACK;
+                               uncle->color = BLACK;
+
+                               /* And the grandparent red... */
+                               node->parent->parent->color = RED;
+
+                               /* And continue fixing the grandparent */
+                               node = node->parent->parent;
+                       } else {                                /* Our uncle is black... */
+                               /* Are we the right child? */
+                               if (node == node->parent->right) {
+                                       node = node->parent;
+                                       ldns_rbtree_rotate_left(rbtree, node);
+                               }
+                               /* Now we're the left child, repaint and rotate... */
+                               node->parent->color = BLACK;
+                               node->parent->parent->color = RED;
+                               ldns_rbtree_rotate_right(rbtree, node->parent->parent);
+                       }
+               } else {
+                       uncle = node->parent->parent->left;
+
+                       /* If our uncle is red... */
+                       if (uncle->color == RED) {
+                               /* Paint the parent and the uncle black... */
+                               node->parent->color = BLACK;
+                               uncle->color = BLACK;
+
+                               /* And the grandparent red... */
+                               node->parent->parent->color = RED;
+
+                               /* And continue fixing the grandparent */
+                               node = node->parent->parent;
+                       } else {                                /* Our uncle is black... */
+                               /* Are we the right child? */
+                               if (node == node->parent->left) {
+                                       node = node->parent;
+                                       ldns_rbtree_rotate_right(rbtree, node);
+                               }
+                               /* Now we're the right child, repaint and rotate... */
+                               node->parent->color = BLACK;
+                               node->parent->parent->color = RED;
+                               ldns_rbtree_rotate_left(rbtree, node->parent->parent);
+                       }
+               }
+       }
+       rbtree->root->color = BLACK;
+}
+
+void
+ldns_rbtree_insert_vref(ldns_rbnode_t *data, void *rbtree)
+{
+       (void) ldns_rbtree_insert((ldns_rbtree_t *) rbtree,
+                                                data);
+}
+
+/*
+ * Inserts a node into a red black tree.
+ *
+ * Returns NULL on failure or the pointer to the newly added node
+ * otherwise.
+ */
+ldns_rbnode_t *
+ldns_rbtree_insert (ldns_rbtree_t *rbtree, ldns_rbnode_t *data)
+{
+       /* XXX Not necessary, but keeps compiler quiet... */
+       int r = 0;
+
+       /* We start at the root of the tree */
+       ldns_rbnode_t   *node = rbtree->root;
+       ldns_rbnode_t   *parent = LDNS_RBTREE_NULL;
+
+       /* Lets find the new parent... */
+       while (node != LDNS_RBTREE_NULL) {
+               /* Compare two keys, do we have a duplicate? */
+               if ((r = rbtree->cmp(data->key, node->key)) == 0) {
+                       return NULL;
+               }
+               parent = node;
+
+               if (r < 0) {
+                       node = node->left;
+               } else {
+                       node = node->right;
+               }
+       }
+
+       /* Initialize the new node */
+       data->parent = parent;
+       data->left = data->right = LDNS_RBTREE_NULL;
+       data->color = RED;
+       rbtree->count++;
+
+       /* Insert it into the tree... */
+       if (parent != LDNS_RBTREE_NULL) {
+               if (r < 0) {
+                       parent->left = data;
+               } else {
+                       parent->right = data;
+               }
+       } else {
+               rbtree->root = data;
+       }
+
+       /* Fix up the red-black properties... */
+       ldns_rbtree_insert_fixup(rbtree, data);
+
+       return data;
+}
+
+/*
+ * Searches the red black tree, returns the data if key is found or NULL otherwise.
+ *
+ */
+ldns_rbnode_t *
+ldns_rbtree_search (ldns_rbtree_t *rbtree, const void *key)
+{
+       ldns_rbnode_t *node;
+
+       if (ldns_rbtree_find_less_equal(rbtree, key, &node)) {
+               return node;
+       } else {
+               return NULL;
+       }
+}
+
+/** helpers for delete: swap node colours */
+static void swap_int8(uint8_t* x, uint8_t* y) 
+{ 
+       uint8_t t = *x; *x = *y; *y = t; 
+}
+
+/** helpers for delete: swap node pointers */
+static void swap_np(ldns_rbnode_t** x, ldns_rbnode_t** y) 
+{
+       ldns_rbnode_t* t = *x; *x = *y; *y = t; 
+}
+
+/** Update parent pointers of child trees of 'parent' */
+static void change_parent_ptr(ldns_rbtree_t* rbtree, ldns_rbnode_t* parent, ldns_rbnode_t* old, ldns_rbnode_t* new)
+{
+       if(parent == LDNS_RBTREE_NULL)
+       {
+               if(rbtree->root == old) rbtree->root = new;
+               return;
+       }
+       if(parent->left == old) parent->left = new;
+       if(parent->right == old) parent->right = new;
+}
+/** Update parent pointer of a node 'child' */
+static void change_child_ptr(ldns_rbnode_t* child, ldns_rbnode_t* old, ldns_rbnode_t* new)
+{
+       if(child == LDNS_RBTREE_NULL) return;
+       if(child->parent == old) child->parent = new;
+}
+
+ldns_rbnode_t* 
+ldns_rbtree_delete(ldns_rbtree_t *rbtree, const void *key)
+{
+       ldns_rbnode_t *to_delete;
+       ldns_rbnode_t *child;
+       if((to_delete = ldns_rbtree_search(rbtree, key)) == 0) return 0;
+       rbtree->count--;
+
+       /* make sure we have at most one non-leaf child */
+       if(to_delete->left != LDNS_RBTREE_NULL &&
+          to_delete->right != LDNS_RBTREE_NULL)
+       {
+               /* swap with smallest from right subtree (or largest from left) */
+               ldns_rbnode_t *smright = to_delete->right;
+               while(smright->left != LDNS_RBTREE_NULL)
+                       smright = smright->left;
+               /* swap the smright and to_delete elements in the tree,
+                * but the ldns_rbnode_t is first part of user data struct
+                * so cannot just swap the keys and data pointers. Instead
+                * readjust the pointers left,right,parent */
+
+               /* swap colors - colors are tied to the position in the tree */
+               swap_int8(&to_delete->color, &smright->color);
+
+               /* swap child pointers in parents of smright/to_delete */
+               change_parent_ptr(rbtree, to_delete->parent, to_delete, smright);
+               if(to_delete->right != smright)
+                       change_parent_ptr(rbtree, smright->parent, smright, to_delete);
+
+               /* swap parent pointers in children of smright/to_delete */
+               change_child_ptr(smright->left, smright, to_delete);
+               change_child_ptr(smright->left, smright, to_delete);
+               change_child_ptr(smright->right, smright, to_delete);
+               change_child_ptr(smright->right, smright, to_delete);
+               change_child_ptr(to_delete->left, to_delete, smright);
+               if(to_delete->right != smright)
+                       change_child_ptr(to_delete->right, to_delete, smright);
+               if(to_delete->right == smright)
+               {
+                       /* set up so after swap they work */
+                       to_delete->right = to_delete;
+                       smright->parent = smright;
+               }
+
+               /* swap pointers in to_delete/smright nodes */
+               swap_np(&to_delete->parent, &smright->parent);
+               swap_np(&to_delete->left, &smright->left);
+               swap_np(&to_delete->right, &smright->right);
+
+               /* now delete to_delete (which is at the location where the smright previously was) */
+       }
+
+       if(to_delete->left != LDNS_RBTREE_NULL) child = to_delete->left;
+       else child = to_delete->right;
+
+       /* unlink to_delete from the tree, replace to_delete with child */
+       change_parent_ptr(rbtree, to_delete->parent, to_delete, child);
+       change_child_ptr(child, to_delete, to_delete->parent);
+
+       if(to_delete->color == RED)
+       {
+               /* if node is red then the child (black) can be swapped in */
+       }
+       else if(child->color == RED)
+       {
+               /* change child to BLACK, removing a RED node is no problem */
+               if(child!=LDNS_RBTREE_NULL) child->color = BLACK;
+       }
+       else ldns_rbtree_delete_fixup(rbtree, child, to_delete->parent);
+
+       /* unlink completely */
+       to_delete->parent = LDNS_RBTREE_NULL;
+       to_delete->left = LDNS_RBTREE_NULL;
+       to_delete->right = LDNS_RBTREE_NULL;
+       to_delete->color = BLACK;
+       return to_delete;
+}
+
+static void ldns_rbtree_delete_fixup(ldns_rbtree_t* rbtree, ldns_rbnode_t* child, ldns_rbnode_t* child_parent)
+{
+       ldns_rbnode_t* sibling;
+       int go_up = 1;
+
+       /* determine sibling to the node that is one-black short */
+       if(child_parent->right == child) sibling = child_parent->left;
+       else sibling = child_parent->right;
+
+       while(go_up)
+       {
+               if(child_parent == LDNS_RBTREE_NULL)
+               {
+                       /* removed parent==black from root, every path, so ok */
+                       return;
+               }
+
+               if(sibling->color == RED)
+               {       /* rotate to get a black sibling */
+                       child_parent->color = RED;
+                       sibling->color = BLACK;
+                       if(child_parent->right == child)
+                               ldns_rbtree_rotate_right(rbtree, child_parent);
+                       else    ldns_rbtree_rotate_left(rbtree, child_parent);
+                       /* new sibling after rotation */
+                       if(child_parent->right == child) sibling = child_parent->left;
+                       else sibling = child_parent->right;
+               }
+
+               if(child_parent->color == BLACK 
+                       && sibling->color == BLACK
+                       && sibling->left->color == BLACK
+                       && sibling->right->color == BLACK)
+               {       /* fixup local with recolor of sibling */
+                       if(sibling != LDNS_RBTREE_NULL)
+                               sibling->color = RED;
+
+                       child = child_parent;
+                       child_parent = child_parent->parent;
+                       /* prepare to go up, new sibling */
+                       if(child_parent->right == child) sibling = child_parent->left;
+                       else sibling = child_parent->right;
+               }
+               else go_up = 0;
+       }
+
+       if(child_parent->color == RED
+               && sibling->color == BLACK
+               && sibling->left->color == BLACK
+               && sibling->right->color == BLACK) 
+       {
+               /* move red to sibling to rebalance */
+               if(sibling != LDNS_RBTREE_NULL)
+                       sibling->color = RED;
+               child_parent->color = BLACK;
+               return;
+       }
+
+       /* get a new sibling, by rotating at sibling. See which child
+          of sibling is red */
+       if(child_parent->right == child
+               && sibling->color == BLACK
+               && sibling->right->color == RED
+               && sibling->left->color == BLACK)
+       {
+               sibling->color = RED;
+               sibling->right->color = BLACK;
+               ldns_rbtree_rotate_left(rbtree, sibling);
+               /* new sibling after rotation */
+               if(child_parent->right == child) sibling = child_parent->left;
+               else sibling = child_parent->right;
+       }
+       else if(child_parent->left == child
+               && sibling->color == BLACK
+               && sibling->left->color == RED
+               && sibling->right->color == BLACK)
+       {
+               sibling->color = RED;
+               sibling->left->color = BLACK;
+               ldns_rbtree_rotate_right(rbtree, sibling);
+               /* new sibling after rotation */
+               if(child_parent->right == child) sibling = child_parent->left;
+               else sibling = child_parent->right;
+       }
+
+       /* now we have a black sibling with a red child. rotate and exchange colors. */
+       sibling->color = child_parent->color;
+       child_parent->color = BLACK;
+       if(child_parent->right == child)
+       {
+               sibling->left->color = BLACK;
+               ldns_rbtree_rotate_right(rbtree, child_parent);
+       }
+       else
+       {
+               sibling->right->color = BLACK;
+               ldns_rbtree_rotate_left(rbtree, child_parent);
+       }
+}
+
+int
+ldns_rbtree_find_less_equal(ldns_rbtree_t *rbtree, const void *key, ldns_rbnode_t **result)
+{
+       int r;
+       ldns_rbnode_t *node;
+
+       /* We start at root... */
+       node = rbtree->root;
+
+       *result = NULL;
+
+       /* While there are children... */
+       while (node != LDNS_RBTREE_NULL) {
+               r = rbtree->cmp(key, node->key);
+               if (r == 0) {
+                       /* Exact match */
+                       *result = node;
+                       return 1;
+               } 
+               if (r < 0) {
+                       node = node->left;
+               } else {
+                       /* Temporary match */
+                       *result = node;
+                       node = node->right;
+               }
+       }
+       return 0;
+}
+
+/*
+ * Finds the first element in the red black tree
+ *
+ */
+ldns_rbnode_t *
+ldns_rbtree_first (ldns_rbtree_t *rbtree)
+{
+       ldns_rbnode_t *node;
+
+       for (node = rbtree->root; node->left != LDNS_RBTREE_NULL; node = node->left);
+       return node;
+}
+
+ldns_rbnode_t *
+ldns_rbtree_last (ldns_rbtree_t *rbtree)
+{
+       ldns_rbnode_t *node;
+
+       for (node = rbtree->root; node->right != LDNS_RBTREE_NULL; node = node->right);
+       return node;
+}
+
+/*
+ * Returns the next node...
+ *
+ */
+ldns_rbnode_t *
+ldns_rbtree_next (ldns_rbnode_t *node)
+{
+       ldns_rbnode_t *parent;
+
+       if (node->right != LDNS_RBTREE_NULL) {
+               /* One right, then keep on going left... */
+               for (node = node->right;
+                       node->left != LDNS_RBTREE_NULL;
+                       node = node->left);
+       } else {
+               parent = node->parent;
+               while (parent != LDNS_RBTREE_NULL && node == parent->right) {
+                       node = parent;
+                       parent = parent->parent;
+               }
+               node = parent;
+       }
+       return node;
+}
+
+ldns_rbnode_t *
+ldns_rbtree_previous(ldns_rbnode_t *node)
+{
+       ldns_rbnode_t *parent;
+
+       if (node->left != LDNS_RBTREE_NULL) {
+               /* One left, then keep on going right... */
+               for (node = node->left;
+                       node->right != LDNS_RBTREE_NULL;
+                       node = node->right);
+       } else {
+               parent = node->parent;
+               while (parent != LDNS_RBTREE_NULL && node == parent->left) {
+                       node = parent;
+                       parent = parent->parent;
+               }
+               node = parent;
+       }
+       return node;
+}
+
+/**
+ * split off elements number of elements from the start
+ * of the name tree and return a new tree 
+ */
+ldns_rbtree_t *
+ldns_rbtree_split(ldns_rbtree_t *tree,
+                          size_t elements)
+{
+       ldns_rbtree_t *new_tree;
+       ldns_rbnode_t *cur_node;
+       ldns_rbnode_t *move_node;
+       size_t count = 0;
+
+       new_tree = ldns_rbtree_create(tree->cmp);
+
+       cur_node = ldns_rbtree_first(tree);
+       while (count < elements && cur_node != LDNS_RBTREE_NULL) {
+               move_node = ldns_rbtree_delete(tree, cur_node->key);
+               ldns_rbtree_insert(new_tree, move_node);
+               cur_node = ldns_rbtree_first(tree);
+               count++;
+       }
+
+       return new_tree;
+}
+
+/*
+ * add all node from the second tree to the first (removing them from the
+ * second), and fix up nsec(3)s if present
+ */
+void
+ldns_rbtree_join(ldns_rbtree_t *tree1, ldns_rbtree_t *tree2)
+{
+       traverse_postorder(tree2, ldns_rbtree_insert_vref, tree1);
+}
+
+/** recursive descent traverse */
+static void 
+traverse_post(void (*func)(ldns_rbnode_t*, void*), void* arg, ldns_rbnode_t* node)
+{
+       if(!node || node == LDNS_RBTREE_NULL)
+               return;
+       /* recurse */
+       traverse_post(func, arg, node->left);
+       traverse_post(func, arg, node->right);
+       /* call user func */
+       (*func)(node, arg);
+}
+
+void 
+traverse_postorder(ldns_rbtree_t* tree, void (*func)(ldns_rbnode_t*, void*), void* arg)
+{
+       traverse_post(func, arg, tree->root);
+}
diff --git a/rdata.c b/rdata.c
index d5c38809183f2231458cc252f7cee8ea2ca6e5ca..980c875f6f23623b47dd3c80fc63a18fbaf2c2a1 100644 (file)
--- a/rdata.c
+++ b/rdata.c
@@ -187,6 +187,7 @@ ldns_rdf_new_frm_data(ldns_rdf_type type, size_t size, const void *data)
        ldns_rdf_set_type(rdf, type);
        ldns_rdf_set_size(rdf, size);
        memcpy(rdf->_data, data, size);
+
        return rdf;
 }
 
index 714a288f7c1fc121724d853930dcdc8ce2a12ad9..5b1914334c6f36988571a3aed76043227f4c156d 100644 (file)
@@ -612,6 +612,8 @@ ldns_str2rdf_nsec(ldns_rdf **rd, const char *str)
        *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC, cur_data_size, data);
        if(data)
                LDNS_FREE(data);
+       if (token)
+               LDNS_FREE(token);
        if(bitmap)
                LDNS_FREE(bitmap);
        ldns_buffer_free(str_buf);
diff --git a/zone.c b/zone.c
index bc7e20350418efe8ca58cad16871da5fd42a3ae1..37e83be9325702edb56ff45702f290f7c1e6fac5 100644 (file)
--- a/zone.c
+++ b/zone.c
@@ -56,10 +56,101 @@ ldns_zone_push_rr(ldns_zone *z, ldns_rr *rr)
        return ldns_rr_list_push_rr( ldns_zone_rrs(z), rr);
 }
 
+/* return a clone of the given rr list, without the glue records
+ * rr list should be the complete zone
+ * if present, stripped records are added to the list *glue_records
+ */
+ldns_rr_list *
+ldns_zone_strip_glue_rrs(const ldns_rdf *zone_name, const ldns_rr_list *rrs, ldns_rr_list *glue_rrs)
+{
+       ldns_rr_list *new_list = ldns_rr_list_new();
+
+       /* when do we find glue? It means we find an IP address
+        * (AAAA/A) for a nameserver listed in the zone
+        *
+        * Alg used here:
+        * first find all the zonecuts (NS records)
+        * find all the AAAA or A records (can be done it the 
+        * above loop).
+        *
+        * Check if the aaaa/a list are subdomains under the
+        * NS domains. If yes -> glue, if no -> not glue
+        */
+
+       ldns_rr_list *zone_cuts;
+       ldns_rr_list *addr;
+       ldns_rr *r, *ns, *a;
+       ldns_rdf *dname_a, *dname_ns, *ns_owner;
+       uint16_t i,j;
+
+       zone_cuts = ldns_rr_list_new();
+       addr = ldns_rr_list_new();
+
+       for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
+               r = ldns_rr_list_rr(rrs, i);
+               if (ldns_rr_get_type(r) == LDNS_RR_TYPE_A ||
+                               ldns_rr_get_type(r) == LDNS_RR_TYPE_AAAA) {
+                       /* possibly glue */
+                       ldns_rr_list_push_rr(addr, r);
+                       continue;
+               }
+               if (ldns_rr_get_type(r) == LDNS_RR_TYPE_NS) {
+                       /* multiple zones will end up here -
+                        * for now; not a problem
+                        */
+                       /* don't add NS records for the current zone itself */
+                       if (ldns_rdf_compare(ldns_rr_owner(r), 
+                                               zone_name) != 0) {
+                               ldns_rr_list_push_rr(zone_cuts, r);
+                       }
+                       continue;
+               }
+       }
+
+       /* will sorting make it quicker ?? */
+       for(i = 0; i < ldns_rr_list_rr_count(zone_cuts); i++) {
+               ns = ldns_rr_list_rr(zone_cuts, i);
+               ns_owner = ldns_rr_owner(ns);
+               dname_ns = ldns_rr_ns_nsdname(ns);
+               for(j = 0; j < ldns_rr_list_rr_count(addr); j++) {
+                       a = ldns_rr_list_rr(addr, j);
+                       dname_a = ldns_rr_owner(a);
+                       
+                       if (ldns_dname_is_subdomain(dname_a, ns_owner) &&
+                           ldns_rdf_compare(dname_ns, dname_a) == 0) {
+                               /* GLUE! */
+                               if (glue_rrs) {
+                                       ldns_rr_list_push_rr(glue_rrs, a);
+                               }
+                               break;
+                       } else {
+                               ldns_rr_list_push_rr(new_list, a);
+                       }
+               }
+       }
+       
+       ldns_rr_list_free(addr);
+       ldns_rr_list_free(zone_cuts);
+
+       return new_list;
+}
+
 /* this will be an EXPENSIVE op with our zone structure */
 ldns_rr_list *
 ldns_zone_glue_rr_list(const ldns_zone *z)
 {
+#if 0
+       ldns_rr_list *rrs = ldns_zone_rrs(z);
+       ldns_rr_list *glue_rrs = ldns_rr_list_new();
+       ldns_rr_list *stripped_rrs = ldns_zone_strip_glue_rrs(ldns_rr_owner(ldns_zone_soa(z)), rrs, glue_rrs);
+       printf("stripped:\n");
+       ldns_rr_list_print(stdout, stripped_rrs);
+       printf("glue:\n");
+       ldns_rr_list_print(stdout, glue_rrs);
+       ldns_rr_list_free(stripped_rrs);
+       return glue_rrs;
+#endif
+
        /* when do we find glue? It means we find an IP address
         * (AAAA/A) for a nameserver listed in the zone
         *
@@ -134,6 +225,7 @@ ldns_zone_glue_rr_list(const ldns_zone *z)
        } else {
                return glue;
        }
+
 }
 
 ldns_zone *
@@ -197,6 +289,7 @@ ldns_zone_new_frm_fp_l(ldns_zone **z, FILE *fp, ldns_rdf *origin, uint32_t ttl,
                                        /* second SOA 
                                         * just skip, maybe we want to say
                                         * something??? */
+                                       ldns_rr_free(rr);
                                        continue;
                                }
                                soa_seen = true;