]> git.ipfire.org Git - thirdparty/ldns.git/commitdiff
Most of the dnssexy features for ldns-verify-zone.
authorWillem Toorop <willem@NLnetLabs.nl>
Tue, 6 Mar 2012 13:32:39 +0000 (13:32 +0000)
committerWillem Toorop <willem@NLnetLabs.nl>
Tue, 6 Mar 2012 13:32:39 +0000 (13:32 +0000)
Changelog
Makefile.in
examples/ldns-duration.c [new file with mode: 0644]
examples/ldns-duration.h [new file with mode: 0644]
examples/ldns-verify-zone.1
examples/ldns-verify-zone.c

index d57be50bb3e61c811f5e1a29d7d5858b2b96570c..5a2f0642e0ec4a0529e6ce341d23e5a582c9eb26 100644 (file)
--- a/Changelog
+++ b/Changelog
@@ -1,4 +1,10 @@
 1.6.13
+       * New -S option for ldns-verify-zone to chase signatures online.
+       * New -k option for ldns-verify-zone to validate using a trusted key.
+       * New inception and expiration margin options (-i and -e) to 
+         ldns-verify-zone.
+       * fix ldns-verify-zone to allow NSEC3 signatures to come before
+         the NSEC3 RR in all cases. Thanks Wolfgang Nagele.
        * Zero the correct flag (opt-out) when creating NSEC3PARAMS.
          Thanks Peter van Dijk.
        * Canonicalize RRSIG's Signer's name too when validating, because 
@@ -6,9 +12,9 @@
        * bugfix #433: Allocate rdf using ldns_rdf_new in ldns_dname_label
        * bugfix #432: Use LDNS_MALLOC & LDNS_FREE i.s.o. malloc & free
        * bugfix #431: Added error message for LDNS_STATUS_INVALID_B32_EXT
-       * bugfix #427: Eplicitely link ssl with the programs that use it.
+       * bugfix #427: Explicitely link ssl with the programs that use it.
        * Fix reading \DDD: Error on values that are outside range (>255).
-       * bugfix #429: fix doxyparse.plfails on NetBSD because specified
+       * bugfix #429: fix doxyparse.pl fails on NetBSD because specified
          path to perl.
 
 1.6.12
index 9d5689b024359d822262b324861f20b218a9eac2..c779e095da36efdfdd5300c87c9f58456e6a8170 100644 (file)
@@ -65,24 +65,26 @@ LDNS_LOBJS_EX       = ^linktest\.c$$
 LDNS_ALL_LOBJS = $(LDNS_LOBJS) $(LIBLOBJS)
 LIB            = libldns.la
 
-LDNS_HEADERS   = buffer.h dname.h dnssec.h dnssec_sign.h dnssec_verify.h dnssec_zone.h error.h higher.h host2str.h host2wire.h keys.h ldns.h packet.h parse.h rbtree.h rdata.h resolver.h rr.h rr_functions.h sha1.h sha2.h str2host.h tsig.h update.h wire2host.h zone.h 
+LDNS_HEADERS   = buffer.h dname.h dnssec.h dnssec_sign.h dnssec_verify.h dnssec_zone.h error.h higher.h host2str.h host2wire.h keys.h ldns.h packet.h parse.h rbtree.h rdata.h resolver.h rr_functions.h rr.h sha1.h sha2.h str2host.h tsig.h update.h wire2host.h zone.h 
 LDNS_HEADERS_EX        = ^config\.h|common\.h|util\.h|net\.h$$
 LDNS_HEADERS_GEN= common.h util.h net.h
 
-PYLDNS_I_FILES = $(pywrapdir)/file_py3.i $(pywrapdir)/ldns.i $(pywrapdir)/ldns_buffer.i $(pywrapdir)/ldns_dname.i $(pywrapdir)/ldns_dnssec.i $(pywrapdir)/ldns_key.i $(pywrapdir)/ldns_packet.i $(pywrapdir)/ldns_rdf.i $(pywrapdir)/ldns_resolver.i $(pywrapdir)/ldns_rr.i $(pywrapdir)/ldns_zone.i
+PYLDNS_I_FILES = $(pywrapdir)/file_py3.i $(pywrapdir)/ldns_buffer.i $(pywrapdir)/ldns_dname.i $(pywrapdir)/ldns_dnssec.i $(pywrapdir)/ldns.i $(pywrapdir)/ldns_key.i $(pywrapdir)/ldns_packet.i $(pywrapdir)/ldns_rdf.i $(pywrapdir)/ldns_resolver.i $(pywrapdir)/ldns_rr.i $(pywrapdir)/ldns_zone.i
 
 DRILL_LOBJS    = drill/chasetrace.lo drill/dnssec.lo drill/drill.lo drill/drill_util.lo drill/error.lo drill/root.lo drill/securetrace.lo drill/work.lo
 
-EXAMPLE_LOBJS  = examples/ldns-chaos.lo examples/ldns-compare-zones.lo examples/ldns-dpa.lo examples/ldns-gen-zone.lo examples/ldns-key2ds.lo examples/ldns-keyfetcher.lo examples/ldns-keygen.lo examples/ldns-mx.lo examples/ldns-notify.lo examples/ldns-nsec3-hash.lo examples/ldns-read-zone.lo examples/ldns-resolver.lo examples/ldns-revoke.lo examples/ldns-rrsig.lo examples/ldns-signzone.lo examples/ldns-test-edns.lo examples/ldns-testns.lo examples/ldns-testpkts.lo examples/ldns-update.lo examples/ldns-verify-zone.lo examples/ldns-version.lo examples/ldns-walk.lo examples/ldns-zcat.lo examples/ldns-zsplit.lo examples/ldnsd.lo
-EXAMPLE_PROGS  = examples/ldns-chaos examples/ldns-compare-zones examples/ldns-gen-zone examples/ldns-key2ds examples/ldns-keyfetcher examples/ldns-keygen examples/ldns-mx examples/ldns-notify examples/ldns-nsec3-hash examples/ldns-read-zone examples/ldns-resolver examples/ldns-revoke examples/ldns-rrsig examples/ldns-test-edns examples/ldns-update examples/ldns-version examples/ldns-walk examples/ldns-zcat examples/ldns-zsplit examples/ldnsd 
-EX_PROGS_BASENM        = ldns-chaos ldns-compare-zones ldns-dpa ldns-gen-zone ldns-key2ds ldns-keyfetcher ldns-keygen ldns-mx ldns-notify ldns-nsec3-hash ldns-read-zone ldns-resolver ldns-revoke ldns-rrsig ldns-signzone ldns-test-edns ldns-testns ldns-update ldns-verify-zone ldns-version ldns-walk ldns-zcat ldns-zsplit ldnsd 
-EXAMPLE_PROGS_EX= ^examples/ldns-testpkts\.c|examples/ldns-testns\.c|examples/ldns-dpa\.c|examples/ldns-signzone\.c|examples/ldns-verify-zone\.c$$
+EXAMPLE_LOBJS  = examples/ldns-chaos.lo examples/ldns-compare-zones.lo examples/ldnsd.lo examples/ldns-dpa.lo examples/ldns-duration.lo examples/ldns-gen-zone.lo examples/ldns-key2ds.lo examples/ldns-keyfetcher.lo examples/ldns-keygen.lo examples/ldns-mx.lo examples/ldns-notify.lo examples/ldns-nsec3-hash.lo examples/ldns-read-zone.lo examples/ldns-resolver.lo examples/ldns-revoke.lo examples/ldns-rrsig.lo examples/ldns-signzone.lo examples/ldns-test-edns.lo examples/ldns-testns.lo examples/ldns-testpkts.lo examples/ldns-update.lo examples/ldns-verify-zone.lo examples/ldns-version.lo examples/ldns-walk.lo examples/ldns-zcat.lo examples/ldns-zsplit.lo
+EXAMPLE_PROGS  = examples/ldns-chaos examples/ldns-compare-zones examples/ldnsd examples/ldns-gen-zone examples/ldns-key2ds examples/ldns-keyfetcher examples/ldns-keygen examples/ldns-mx examples/ldns-notify examples/ldns-nsec3-hash examples/ldns-read-zone examples/ldns-resolver examples/ldns-revoke examples/ldns-rrsig examples/ldns-test-edns examples/ldns-update examples/ldns-version examples/ldns-walk examples/ldns-zcat examples/ldns-zsplit 
+EX_PROGS_BASENM        = ldns-chaos ldns-compare-zones ldnsd ldns-dpa ldns-duration ldns-gen-zone ldns-key2ds ldns-keyfetcher ldns-keygen ldns-mx ldns-notify ldns-nsec3-hash ldns-read-zone ldns-resolver ldns-revoke ldns-rrsig ldns-signzone ldns-test-edns ldns-testns ldns-testpkts ldns-update ldns-verify-zone ldns-version ldns-walk ldns-zcat ldns-zsplit 
+EXAMPLE_PROGS_EX= ^examples/ldns-duration\.c|examples/ldns-testpkts\.c|examples/ldns-testns\.c|examples/ldns-dpa\.c|examples/ldns-signzone\.c|examples/ldns-verify-zone\.c$$
 TESTNS         = examples/ldns-testns
 TESTNS_LOBJS   = examples/ldns-testns.lo examples/ldns-testpkts.lo
 LDNS_DPA       = examples/ldns-dpa
 LDNS_DPA_LOBJS = examples/ldns-dpa.lo
-EX_SSL_PROGS   = examples/ldns-signzone examples/ldns-verify-zone
-EX_SSL_LOBJS   = examples/ldns-signzone.lo examples/ldns-verify-zone.lo
+LDNS_VFY        = examples/ldns-verify-zone
+LDNS_VFY_LOBJS  = examples/ldns-verify-zone.lo examples/ldns-duration.lo
+EX_SSL_PROGS   = examples/ldns-signzone
+EX_SSL_LOBJS   = examples/ldns-signzone.lo
 
 
 COMPILE                = $(CC) $(CPPFLAGS) $(CFLAGS)
@@ -108,13 +110,13 @@ $(LDNS_LOBJS) $(LIBLOBJS) $(DRILL_LOBJS) $(EXAMPLE_LOBJS):
        $(COMP_LIB) $(LIBSSL_CPPFLAGS) -c $(srcdir)/$(@:.lo=.c) -o $@
 
 setup-builddir:
-       if test ! -d compat ; then mkdir compat ; fi
-       if test ! -d drill ; then mkdir drill ; fi
-       if test ! -d examples ; then mkdir examples ; fi
-       if test ! -h config.h ; then ln -s ldns/config.h . ; fi
-       if test ! -h lib ; then ln -s .libs lib ; fi ;
-       if test ! -d include ; then $(INSTALL) -d include; fi
-       if test ! -h include/ldns ; then ln -s ../ldns include/ldns || echo "include/ldns exists"; fi
+       @if test ! -d compat ; then mkdir compat ; fi
+       @if test ! -d drill ; then mkdir drill ; fi
+       @if test ! -d examples ; then mkdir examples ; fi
+       @if test ! -h config.h ; then ln -s ldns/config.h . ; fi
+       @if test ! -h lib ; then ln -s .libs lib ; fi ;
+       @if test ! -d include ; then $(INSTALL) -d include; fi
+       @if test ! -h include/ldns ; then ln -s ../ldns include/ldns || echo "include/ldns exists"; fi
 
 putdown-builddir:
        rm -f include/ldns lib config.h
@@ -125,12 +127,12 @@ putdown-builddir:
 
 drill: no-drill-config-h drill/drill
 no-drill-config-h:
-       if test -e $(srcdir)/drill/config.h -o -e drill/config.h ; then \
-               echo "A config.h was detected in the drill subdirectory." ; \
-               echo "This does not work when building drill from here." ; \
-               echo "Either remove the config.h from the subdirectory" ; \
-               echo "or build drill there." ; \
-               exit -1 ; \
+       @if test -e $(srcdir)/drill/config.h -o -e drill/config.h ; \
+       then echo "A config.h was detected in the drill subdirectory." ; \
+            echo "This does not work when building drill from here." ; \
+            echo "Either remove the config.h from the subdirectory" ; \
+            echo "or build drill there." ; \
+            exit -1 ; \
        fi
 drill/drill: $(DRILL_LOBJS) $(LIB)
        $(LINK_EXE) $(DRILL_LOBJS) $(LIBS) $(LIBSSL_LIBS) -lldns -o drill/drill
@@ -150,14 +152,14 @@ uninstall-drill:
 clean-drill:
        $(LIBTOOL) --mode clean rm -f $(DRILL_LOBJS) drill/drill
 
-examples: no-examples-config-h $(EXAMPLE_PROGS) $(TESTNS) $(LDNS_DPA) $(EX_SSL_PROGS)
+examples: no-examples-config-h $(EXAMPLE_PROGS) $(TESTNS) $(LDNS_DPA) $(LDNS_VFY) $(EX_SSL_PROGS)
 no-examples-config-h:
-       if test -e $(srcdir)/examples/config.h -o -e examples/config.h ; then \
-               echo "A config.h was detected in the examples subdirectory." ; \
-               echo "This does not work when building examples from here." ; \
-               echo "Either remove the config.h from the subdirectory" ; \
-               echo "or build examples there." ; \
-               exit -1 ; \
+       @if test -e $(srcdir)/examples/config.h -o -e examples/config.h ; \
+       then echo "A config.h was detected in the examples subdirectory." ; \
+            echo "This does not work when building examples from here." ; \
+            echo "Either remove the config.h from the subdirectory" ; \
+            echo "or build examples there." ; \
+            exit -1 ; \
        fi
 $(EXAMPLE_PROGS):
        $(LINK_EXE) $@.lo $(LIBS) -lldns -o $@
@@ -169,14 +171,18 @@ $(LDNS_DPA):
        $(LINK_EXE) $(LDNS_DPA_LOBJS) $(LIBS) $(LIBPCAP_LIBS) -lldns \
                 -o $(LDNS_DPA)
 
+$(LDNS_VFY):
+       $(LINK_EXE) $(LDNS_VFY_LOBJS) $(LIBS) $(LIBSSL_LIBS) -lldns \
+                -o $(LDNS_VFY)
+
 $(EX_SSL_PROGS):
        $(LINK_EXE) $@.lo $(LIBS) $(LIBSSL_LIBS) -lldns -o $@
 
-install-examples: $(EXAMPLE_PROGS) $(TESTNS) $(LDNS_DPA) $(EX_SSL_PROGS)
+install-examples: $(EXAMPLE_PROGS) $(TESTNS) $(LDNS_DPA) $(LDNS_VFY) $(EX_SSL_PROGS)
        $(INSTALL) -m 755 -d $(DESTDIR)$(bindir)
        $(INSTALL) -m 755 -d $(DESTDIR)$(mandir)
        $(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man1
-       for p in $(EXAMPLE_PROGS) $(TESTNS) $(LDNS_DPA) $(EX_SSL_PROGS) ; do \
+       for p in $(EXAMPLE_PROGS) $(TESTNS) $(LDNS_DPA) $(LDNS_VFY) $(EX_SSL_PROGS) ; do \
                $(LIBTOOL) --mode=install cp $$p $(DESTDIR)$(bindir) ; \
                $(INSTALL) -m 644 $(srcdir)/$$p.1 $(DESTDIR)$(mandir)/man1 ; \
        done
@@ -190,7 +196,7 @@ uninstall-examples:
 
 clean-examples:
        $(LIBTOOL) --mode clean rm -f $(EXAMPLE_PROGS) 
-       $(LIBTOOL) --mode clean rm -f $(TESTNS) $(LDNS_DPA) $(EX_SSL_PROGS)
+       $(LIBTOOL) --mode clean rm -f $(TESTNS) $(LDNS_DPA) $(LDNS_VFY) $(EX_SSL_PROGS)
        $(LIBTOOL) --mode clean rm -f $(EXAMPLE_LOBJS)
 
 linktest: $(srcdir)/linktest.c libldns.la
@@ -216,12 +222,14 @@ doxygen: manpages
        $(doxygen) $(srcdir)/libdns.doxygen
 
 doc: manpages $(doxygen)
-       $(INSTALL) -d doc
+       @$(INSTALL) -d doc
 
 manpages: $(srcdir)/doc/function_manpages 
-       $(INSTALL) -d doc
-       cat $(srcdir)/ldns/*.h | $(srcdir)/doc/doxyparse.pl -m $(srcdir)/doc/function_manpages 2>&1 | \
-       grep -v ^doxygen | grep -v ^cat  > doc/ldns_manpages
+       @$(INSTALL) -d doc
+       @cat $(srcdir)/ldns/*.h \
+       | $(srcdir)/doc/doxyparse.pl \
+               -m $(srcdir)/doc/function_manpages 2>&1 \
+       | grep -v ^doxygen | grep -v ^cat  > doc/ldns_manpages
 
 pyldns: _ldns.la
 
@@ -449,6 +457,9 @@ depend:
        done
        for p in $(EXAMPLE_PROGS) $(LDNS_DPA) $(EX_SSL_PROGS); do \
                echo "$$p: $$p.lo $$p.o \$$(LIB)" >> $(DEPEND_TMP) ; done
+       echo "$(LDNS_VFY): `for o in $(LDNS_VFY_LOBJS) ; do \
+                               echo -n "$$o $${o%lo}o " ; done` \$$(LIB)" \
+                               >> $(DEPEND_TMP)
        echo "$(TESTNS): `for o in $(TESTNS_LOBJS) ; do \
                                echo -n "$$o $${o%lo}o " ; done` \$$(LIB)" \
                                >> $(DEPEND_TMP)
@@ -577,7 +588,7 @@ parse.lo parse.o: $(srcdir)/parse.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/uti
  $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \
  ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h $(srcdir)/ldns/wire2host.h \
  $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h $(srcdir)/ldns/sha2.h
-rbtree.lo rbtree.o: $(srcdir)/rbtree.c ldns/config.h $(srcdir)/ldns/rbtree.h
+rbtree.lo rbtree.o: $(srcdir)/rbtree.c ldns/config.h $(srcdir)/ldns/rbtree.h ldns/util.h ldns/common.h
 rdata.lo rdata.o: $(srcdir)/rdata.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h ldns/common.h \
  $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h \
  $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h \
@@ -687,11 +698,18 @@ examples/ldns-chaos.lo examples/ldns-chaos.o: $(srcdir)/examples/ldns-chaos.c ld
 examples/ldns-compare-zones.lo examples/ldns-compare-zones.o: $(srcdir)/examples/ldns-compare-zones.c ldns/config.h $(srcdir)/ldns/ldns.h \
  ldns/util.h ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dname.h \
  $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/keys.h \
- $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \
- $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \
- $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \
+ $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \
+ $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/higher.h \
+ $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \
  $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \
  $(srcdir)/ldns/sha2.h
+examples/ldnsd.lo examples/ldnsd.o: $(srcdir)/examples/ldnsd.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h ldns/common.h \
+ $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h \
+ $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h \
+ $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h \
+ $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \
+ ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h $(srcdir)/ldns/wire2host.h \
+ $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h $(srcdir)/ldns/sha2.h
 examples/ldns-dpa.lo examples/ldns-dpa.o: $(srcdir)/examples/ldns-dpa.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h \
  ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h \
  $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h \
@@ -700,12 +718,13 @@ examples/ldns-dpa.lo examples/ldns-dpa.o: $(srcdir)/examples/ldns-dpa.c ldns/con
  $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \
  $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \
  $(srcdir)/ldns/sha2.h $(srcdir)/examples/ldns-dpa.h
+examples/ldns-duration.lo examples/ldns-duration.o: $(srcdir)/examples/ldns-duration.c $(srcdir)/examples/ldns-duration.h
 examples/ldns-gen-zone.lo examples/ldns-gen-zone.o: $(srcdir)/examples/ldns-gen-zone.c ldns/config.h $(srcdir)/ldns/ldns.h \
  ldns/util.h ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dname.h \
  $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/keys.h \
- $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \
- $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \
- $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \
+ $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \
+ $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/higher.h \
+ $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \
  $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \
  $(srcdir)/ldns/sha2.h
 examples/ldns-key2ds.lo examples/ldns-key2ds.o: $(srcdir)/examples/ldns-key2ds.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h \
@@ -719,9 +738,9 @@ examples/ldns-key2ds.lo examples/ldns-key2ds.o: $(srcdir)/examples/ldns-key2ds.c
 examples/ldns-keyfetcher.lo examples/ldns-keyfetcher.o: $(srcdir)/examples/ldns-keyfetcher.c ldns/config.h $(srcdir)/ldns/ldns.h \
  ldns/util.h ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dname.h \
  $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/keys.h \
- $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \
- $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \
- $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \
+ $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \
+ $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/higher.h \
+ $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \
  $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \
  $(srcdir)/ldns/sha2.h
 examples/ldns-keygen.lo examples/ldns-keygen.o: $(srcdir)/examples/ldns-keygen.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h \
@@ -751,25 +770,25 @@ examples/ldns-notify.lo examples/ldns-notify.o: $(srcdir)/examples/ldns-notify.c
 examples/ldns-nsec3-hash.lo examples/ldns-nsec3-hash.o: $(srcdir)/examples/ldns-nsec3-hash.c ldns/config.h $(srcdir)/ldns/ldns.h \
  ldns/util.h ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dname.h \
  $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/keys.h \
- $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \
- $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \
- $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \
+ $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \
+ $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/higher.h \
+ $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \
  $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \
  $(srcdir)/ldns/sha2.h
 examples/ldns-read-zone.lo examples/ldns-read-zone.o: $(srcdir)/examples/ldns-read-zone.c ldns/config.h $(srcdir)/ldns/ldns.h \
  ldns/util.h ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dname.h \
  $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/keys.h \
- $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \
- $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \
- $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \
+ $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \
+ $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/higher.h \
+ $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \
  $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \
  $(srcdir)/ldns/sha2.h
 examples/ldns-resolver.lo examples/ldns-resolver.o: $(srcdir)/examples/ldns-resolver.c ldns/config.h $(srcdir)/ldns/ldns.h \
  ldns/util.h ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dname.h \
  $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/keys.h \
- $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \
- $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \
- $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \
+ $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \
+ $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/higher.h \
+ $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \
  $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \
  $(srcdir)/ldns/sha2.h
 examples/ldns-revoke.lo examples/ldns-revoke.o: $(srcdir)/examples/ldns-revoke.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h \
@@ -791,17 +810,17 @@ examples/ldns-rrsig.lo examples/ldns-rrsig.o: $(srcdir)/examples/ldns-rrsig.c ld
 examples/ldns-signzone.lo examples/ldns-signzone.o: $(srcdir)/examples/ldns-signzone.c ldns/config.h $(srcdir)/ldns/ldns.h \
  ldns/util.h ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dname.h \
  $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/keys.h \
- $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \
- $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \
- $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \
+ $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \
+ $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/higher.h \
+ $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \
  $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \
  $(srcdir)/ldns/sha2.h
 examples/ldns-test-edns.lo examples/ldns-test-edns.o: $(srcdir)/examples/ldns-test-edns.c ldns/config.h $(srcdir)/ldns/ldns.h \
  ldns/util.h ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dname.h \
  $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/keys.h \
- $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \
- $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \
- $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \
+ $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \
+ $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/higher.h \
+ $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \
  $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \
  $(srcdir)/ldns/sha2.h
 examples/ldns-testns.lo examples/ldns-testns.o: $(srcdir)/examples/ldns-testns.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h \
@@ -815,9 +834,9 @@ examples/ldns-testns.lo examples/ldns-testns.o: $(srcdir)/examples/ldns-testns.c
 examples/ldns-testpkts.lo examples/ldns-testpkts.o: $(srcdir)/examples/ldns-testpkts.c ldns/config.h $(srcdir)/ldns/ldns.h \
  ldns/util.h ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dname.h \
  $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/keys.h \
- $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \
- $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \
- $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \
+ $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \
+ $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/higher.h \
+ $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \
  $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \
  $(srcdir)/ldns/sha2.h $(srcdir)/examples/ldns-testpkts.h
 examples/ldns-update.lo examples/ldns-update.o: $(srcdir)/examples/ldns-update.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h \
@@ -828,14 +847,14 @@ examples/ldns-update.lo examples/ldns-update.o: $(srcdir)/examples/ldns-update.c
  $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \
  $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \
  $(srcdir)/ldns/sha2.h
-examples/ldns-verify-zone.lo examples/ldns-verify-zone.o: $(srcdir)/examples/ldns-verify-zone.c ldns/config.h $(srcdir)/ldns/ldns.h \
ldns/util.h ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dname.h \
- $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/keys.h \
- $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \
- $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \
- $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \
$(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \
- $(srcdir)/ldns/sha2.h
+examples/ldns-verify-zone.lo examples/ldns-verify-zone.o: $(srcdir)/examples/ldns-verify-zone.c ldns/config.h \
$(srcdir)/examples/ldns-duration.h $(srcdir)/ldns/ldns.h ldns/util.h ldns/common.h \
+ $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h \
+ $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h \
+ $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h \
+ $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \
ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h $(srcdir)/ldns/wire2host.h \
+ $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h $(srcdir)/ldns/sha2.h
 examples/ldns-version.lo examples/ldns-version.o: $(srcdir)/examples/ldns-version.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h \
  ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h \
  $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h \
@@ -868,13 +887,6 @@ examples/ldns-zsplit.lo examples/ldns-zsplit.o: $(srcdir)/examples/ldns-zsplit.c
  $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \
  $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \
  $(srcdir)/ldns/sha2.h
-examples/ldnsd.lo examples/ldnsd.o: $(srcdir)/examples/ldnsd.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h ldns/common.h \
- $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h \
- $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h \
- $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h \
- $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \
- ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h $(srcdir)/ldns/wire2host.h \
- $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h $(srcdir)/ldns/sha2.h
 drill/chasetrace.lo drill/chasetrace.o: $(srcdir)/drill/chasetrace.c $(srcdir)/drill/drill.h ldns/config.h \
  $(srcdir)/drill/drill_util.h $(srcdir)/ldns/ldns.h ldns/util.h ldns/common.h $(srcdir)/ldns/buffer.h \
  $(srcdir)/ldns/error.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h \
@@ -941,6 +953,7 @@ drill/work.lo drill/work.o: $(srcdir)/drill/work.c $(srcdir)/drill/drill.h ldns/
  $(srcdir)/ldns/sha2.h
 examples/ldns-chaos: examples/ldns-chaos.lo examples/ldns-chaos.o $(LIB)
 examples/ldns-compare-zones: examples/ldns-compare-zones.lo examples/ldns-compare-zones.o $(LIB)
+examples/ldnsd: examples/ldnsd.lo examples/ldnsd.o $(LIB)
 examples/ldns-gen-zone: examples/ldns-gen-zone.lo examples/ldns-gen-zone.o $(LIB)
 examples/ldns-key2ds: examples/ldns-key2ds.lo examples/ldns-key2ds.o $(LIB)
 examples/ldns-keyfetcher: examples/ldns-keyfetcher.lo examples/ldns-keyfetcher.o $(LIB)
@@ -958,8 +971,7 @@ examples/ldns-version: examples/ldns-version.lo examples/ldns-version.o $(LIB)
 examples/ldns-walk: examples/ldns-walk.lo examples/ldns-walk.o $(LIB)
 examples/ldns-zcat: examples/ldns-zcat.lo examples/ldns-zcat.o $(LIB)
 examples/ldns-zsplit: examples/ldns-zsplit.lo examples/ldns-zsplit.o $(LIB)
-examples/ldnsd: examples/ldnsd.lo examples/ldnsd.o $(LIB)
 examples/ldns-dpa: examples/ldns-dpa.lo examples/ldns-dpa.o $(LIB)
 examples/ldns-signzone: examples/ldns-signzone.lo examples/ldns-signzone.o $(LIB)
-examples/ldns-verify-zone: examples/ldns-verify-zone.lo examples/ldns-verify-zone.o $(LIB)
+examples/ldns-verify-zone: examples/ldns-verify-zone.lo examples/ldns-verify-zone.o examples/ldns-duration.lo examples/ldns-duration.o  $(LIB)
 examples/ldns-testns: examples/ldns-testns.lo examples/ldns-testns.o examples/ldns-testpkts.lo examples/ldns-testpkts.o  $(LIB)
diff --git a/examples/ldns-duration.c b/examples/ldns-duration.c
new file mode 100644 (file)
index 0000000..b5086d8
--- /dev/null
@@ -0,0 +1,547 @@
+/*
+ * $Id: duration.c 4518 2011-02-24 15:39:09Z matthijs $
+ *
+ * Copyright (c) 2009 NLNet Labs. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ */
+
+/**
+ *
+ * This file is copied from the OpenDNSSEC source repository
+ * and only slightly adapted to make it fit.
+ */
+
+/**
+ *
+ * Durations.
+ */
+
+#include "ldns-duration.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+
+/**
+ * Create a new 'instant' duration.
+ *
+ */
+ldns_duration_type*
+ldns_duration_create(void)
+{
+    ldns_duration_type* duration;
+
+    duration = malloc(sizeof(ldns_duration_type));
+    if (!duration) {
+        return NULL;
+    }
+    duration->years = 0;
+    duration->months = 0;
+    duration->weeks = 0;
+    duration->days = 0;
+    duration->hours = 0;
+    duration->minutes = 0;
+    duration->seconds = 0;
+    return duration;
+}
+
+
+/**
+ * Compare durations.
+ *
+ */
+int
+ldns_duration_compare(ldns_duration_type* d1, ldns_duration_type* d2)
+{
+    if (!d1 && !d2) {
+        return 0;
+    }
+    if (!d1 || !d2) {
+        return d1?-1:1;
+    }
+
+    if (d1->years != d2->years) {
+        return d1->years - d2->years;
+    }
+    if (d1->months != d2->months) {
+        return d1->months - d2->months;
+    }
+    if (d1->weeks != d2->weeks) {
+        return d1->weeks - d2->weeks;
+    }
+    if (d1->days != d2->days) {
+        return d1->days - d2->days;
+    }
+    if (d1->hours != d2->hours) {
+        return d1->hours - d2->hours;
+    }
+    if (d1->minutes != d2->minutes) {
+        return d1->minutes - d2->minutes;
+    }
+    if (d1->seconds != d2->seconds) {
+        return d1->seconds - d2->seconds;
+    }
+
+    return 0;
+}
+
+
+/**
+ * Create a duration from string.
+ *
+ */
+ldns_duration_type*
+ldns_duration_create_from_string(const char* str)
+{
+    ldns_duration_type* duration = ldns_duration_create();
+    char* P, *X, *T, *W;
+    int not_weeks = 0;
+
+    if (!duration) {
+        return NULL;
+    }
+    if (!str) {
+        return duration;
+    }
+
+    P = strchr(str, 'P');
+    if (!P) {
+       ldns_duration_cleanup(duration);
+        return NULL;
+    }
+
+    T = strchr(str, 'T');
+    X = strchr(str, 'Y');
+    if (X) {
+        duration->years = atoi(str+1);
+        str = X;
+        not_weeks = 1;
+    }
+    X = strchr(str, 'M');
+    if (X && (!T || (size_t) (X-P) < (size_t) (T-P))) {
+        duration->months = atoi(str+1);
+        str = X;
+        not_weeks = 1;
+    }
+    X = strchr(str, 'D');
+    if (X) {
+        duration->days = atoi(str+1);
+        str = X;
+        not_weeks = 1;
+    }
+    if (T) {
+        str = T;
+        not_weeks = 1;
+    }
+    X = strchr(str, 'H');
+    if (X && T) {
+        duration->hours = atoi(str+1);
+        str = X;
+        not_weeks = 1;
+    }
+    X = strrchr(str, 'M');
+    if (X && T && (size_t) (X-P) > (size_t) (T-P)) {
+        duration->minutes = atoi(str+1);
+        str = X;
+        not_weeks = 1;
+    }
+    X = strchr(str, 'S');
+    if (X && T) {
+        duration->seconds = atoi(str+1);
+        str = X;
+        not_weeks = 1;
+    }
+
+    W = strchr(str, 'W');
+    if (W) {
+        if (not_weeks) {
+            ldns_duration_cleanup(duration);
+            return NULL;
+        } else {
+            duration->weeks = atoi(str+1);
+            str = W;
+        }
+    }
+    return duration;
+}
+
+
+/**
+ * Get the number of digits in a number.
+ *
+ */
+static size_t
+digits_in_number(time_t duration)
+{
+    uint32_t period = (uint32_t) duration;
+    size_t count = 0;
+
+    while (period > 0) {
+        count++;
+        period /= 10;
+    }
+    return count;
+}
+
+
+/**
+ * Convert a duration to a string.
+ *
+ */
+char*
+ldns_duration2string(ldns_duration_type* duration)
+{
+    char* str = NULL, *num = NULL;
+    size_t count = 2;
+    int T = 0;
+
+    if (!duration) {
+        return NULL;
+    }
+
+    if (duration->years > 0) {
+        count = count + 1 + digits_in_number(duration->years);
+    }
+    if (duration->months > 0) {
+        count = count + 1 + digits_in_number(duration->months);
+    }
+    if (duration->weeks > 0) {
+        count = count + 1 + digits_in_number(duration->weeks);
+    }
+    if (duration->days > 0) {
+        count = count + 1 + digits_in_number(duration->days);
+    }
+    if (duration->hours > 0) {
+        count = count + 1 + digits_in_number(duration->hours);
+        T = 1;
+    }
+    if (duration->minutes > 0) {
+        count = count + 1 + digits_in_number(duration->minutes);
+        T = 1;
+    }
+    if (duration->seconds > 0) {
+        count = count + 1 + digits_in_number(duration->seconds);
+        T = 1;
+    }
+    if (T) {
+        count++;
+    }
+
+    str = (char*) calloc(count, sizeof(char));
+    str[0] = 'P';
+    str[1] = '\0';
+
+    if (duration->years > 0) {
+        count = digits_in_number(duration->years);
+        num = (char*) calloc(count+2, sizeof(char));
+        snprintf(num, count+2, "%uY", (uint32_t) duration->years);
+        str = strncat(str, num, count+2);
+        free((void*) num);
+    }
+    if (duration->months > 0) {
+        count = digits_in_number(duration->months);
+        num = (char*) calloc(count+2, sizeof(char));
+        snprintf(num, count+2, "%uM", (uint32_t) duration->months);
+        str = strncat(str, num, count+2);
+        free((void*) num);
+    }
+    if (duration->weeks > 0) {
+        count = digits_in_number(duration->weeks);
+        num = (char*) calloc(count+2, sizeof(char));
+        snprintf(num, count+2, "%uW", (uint32_t) duration->weeks);
+        str = strncat(str, num, count+2);
+        free((void*) num);
+    }
+    if (duration->days > 0) {
+        count = digits_in_number(duration->days);
+        num = (char*) calloc(count+2, sizeof(char));
+        snprintf(num, count+2, "%uD", (uint32_t) duration->days);
+        str = strncat(str, num, count+2);
+        free((void*) num);
+    }
+    if (T) {
+        str = strncat(str, "T", 1);
+    }
+    if (duration->hours > 0) {
+        count = digits_in_number(duration->hours);
+        num = (char*) calloc(count+2, sizeof(char));
+        snprintf(num, count+2, "%uH", (uint32_t) duration->hours);
+        str = strncat(str, num, count+2);
+        free((void*) num);
+    }
+    if (duration->minutes > 0) {
+        count = digits_in_number(duration->minutes);
+        num = (char*) calloc(count+2, sizeof(char));
+        snprintf(num, count+2, "%uM", (uint32_t) duration->minutes);
+        str = strncat(str, num, count+2);
+        free((void*) num);
+    }
+    if (duration->seconds > 0) {
+        count = digits_in_number(duration->seconds);
+        num = (char*) calloc(count+2, sizeof(char));
+        snprintf(num, count+2, "%uS", (uint32_t) duration->seconds);
+        str = strncat(str, num, count+2);
+        free((void*) num);
+    }
+    return str;
+}
+
+
+/**
+ * Convert a duration to a time.
+ *
+ */
+time_t
+ldns_duration2time(ldns_duration_type* duration)
+{
+    time_t period = 0;
+    char* dstr = NULL;
+
+    if (duration) {
+        period += (duration->seconds);
+        period += (duration->minutes)*60;
+        period += (duration->hours)*3600;
+        period += (duration->days)*86400;
+        period += (duration->weeks)*86400*7;
+        period += (duration->months)*86400*31;
+        period += (duration->years)*86400*365;
+
+        /* [TODO] calculate correct number of days in this month/year */
+       /*
+        if (duration->months || duration->years) {
+        }
+       */
+    }
+    return period;
+}
+
+/**
+ * Return the shortest time.
+ *
+ */
+time_t
+time_minimum(time_t a, time_t b)
+{
+    return (a < b ? a : b);
+}
+
+/**
+ * Return the longest time.
+ *
+ */
+time_t
+time_maximum(time_t a, time_t b)
+{
+    return (a > b ? a : b);
+}
+
+
+/**
+ * Return a random time.
+ *
+ */
+time_t
+ods_rand(time_t mod)
+{
+#ifdef HAVE_ARC4RANDOM_UNIFORM
+    return (time_t) (arc4random_uniform((uint32_t) mod+1));
+#elif HAVE_ARC4RANDOM
+    return (time_t) (arc4random() % (unsigned) mod+1);
+#else
+    return (time_t) (random() % (unsigned) mod+1);
+#endif
+}
+
+
+/* Number of days per month (except for February in leap years). */
+static const int mdays[] = {
+    31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+
+static int
+is_leap_year(int year)
+{
+    return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
+}
+
+
+static int
+leap_days(int y1, int y2)
+{
+    --y1;
+    --y2;
+    return (y2/4 - y1/4) - (y2/100 - y1/100) + (y2/400 - y1/400);
+}
+
+
+/*
+ * Code taken from NSD 3.2.5, which is
+ * code adapted from Python 2.4.1 sources (Lib/calendar.py).
+ */
+static time_t
+mktime_from_utc(const struct tm *tm)
+{
+    int year = 1900 + tm->tm_year;
+    time_t days = 365 * (year - 1970) + leap_days(1970, year);
+    time_t hours;
+    time_t minutes;
+    time_t seconds;
+    int i;
+
+    for (i = 0; i < tm->tm_mon; ++i) {
+        days += mdays[i];
+    }
+    if (tm->tm_mon > 1 && is_leap_year(year)) {
+        ++days;
+    }
+    days += tm->tm_mday - 1;
+
+    hours = days * 24 + tm->tm_hour;
+    minutes = hours * 60 + tm->tm_min;
+    seconds = minutes * 60 + tm->tm_sec;
+
+    return seconds;
+}
+
+
+/**
+ * Convert time in string format into seconds.
+ *
+ */
+static time_t
+timeshift2time(const char *time)
+{
+        /* convert a string in format YYMMDDHHMMSS to time_t */
+        struct tm tm;
+        time_t timeshift = 0;
+
+        /* Try to scan the time... */
+        if (strptime(time, "%Y%m%d%H%M%S", &tm)) {
+                timeshift = mktime_from_utc(&tm);
+       }
+        return timeshift;
+}
+
+
+/**
+ * Return the time since Epoch, measured in seconds.
+ *
+ */
+time_t
+time_now(void)
+{
+#ifdef ENFORCER_TIMESHIFT
+    const char* env = getenv("ENFORCER_TIMESHIFT");
+    if (env) {
+        return timeshift2time(env);
+    } else
+#endif /* ENFORCER_TIMESHIFT */
+
+    return time(NULL);
+}
+
+
+/**
+ * copycode: This code is based on the EXAMPLE in the strftime manual.
+ *
+ */
+uint32_t
+time_datestamp(time_t tt, const char* format, char** str)
+{
+    time_t t;
+    struct tm *tmp;
+    uint32_t ut = 0;
+    char outstr[32];
+
+    if (tt) {
+        t = tt;
+    } else {
+        t = time_now();
+    }
+
+    tmp = localtime(&t);
+    if (tmp == NULL) {
+        return 0;
+    }
+
+    if (strftime(outstr, sizeof(outstr), format, tmp) == 0) {
+        return 0;
+    }
+
+    ut = (uint32_t) strtoul(outstr, NULL, 10);
+    if (str) {
+        *str = strdup(outstr);
+    }
+    return ut;
+}
+
+static void
+time_itoa_reverse(char* s)
+{
+    int i, j;
+    char c;
+
+    for (i = 0, j = strlen(s)-1; i<j; i++, j--) {
+        c = s[i];
+        s[i] = s[j];
+        s[j] = c;
+    }
+    return;
+}
+
+
+/**
+ * Convert time into string.
+ *
+ */
+void
+time_itoa(time_t n, char* s)
+{
+    int i = 0;
+
+    do {       /* generate digits in reverse order */
+        s[i++] = n % 10 + '0';   /* get next digit */
+    } while ((n /= 10) > 0);     /* delete it */
+    s[i] = '\0';
+    time_itoa_reverse(s);
+    return;
+}
+
+
+/**
+ * Clean up duration.
+ *
+ */
+void
+ldns_duration_cleanup(ldns_duration_type* duration)
+{
+    if (!duration) {
+        return;
+    }
+    free(duration);
+    return;
+}
diff --git a/examples/ldns-duration.h b/examples/ldns-duration.h
new file mode 100644 (file)
index 0000000..24becd5
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * $Id: duration.h 4341 2011-01-31 15:21:09Z matthijs $
+ *
+ * Copyright (c) 2009 NLNet Labs. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ */
+
+/**
+ *
+ * This file is copied from the OpenDNSSEC source repository
+ * and only slightly adapted to make it fit.
+ */
+
+/**
+ *
+ * Durations.
+ */
+
+#ifndef LDNS_DURATION_H
+#define LDNS_DURATION_H
+
+#include <stdint.h>
+#include <time.h>
+
+/**
+ * Duration.
+ *
+ */
+typedef struct ldns_duration_struct ldns_duration_type;
+struct ldns_duration_struct
+{
+    time_t years;
+    time_t months;
+    time_t weeks;
+    time_t days;
+    time_t hours;
+    time_t minutes;
+    time_t seconds;
+};
+
+/**
+ * Create a new 'instant' duration.
+ * \return ldns_duration_type* created duration
+ *
+ */
+ldns_duration_type* ldns_duration_create(void);
+
+/**
+ * Compare durations.
+ * \param[in] d1 one duration
+ * \param[in] d2 another duration
+ * \return int 0 if equal, -1 if d1 < d2, 1 if d2 < d1
+ *
+ */
+int ldns_duration_compare(ldns_duration_type* d1, ldns_duration_type* d2);
+
+/**
+ * Create a duration from string.
+ * \param[in] str string-format duration
+ * \return ldns_duration_type* created duration
+ *
+ */
+ldns_duration_type* ldns_duration_create_from_string(const char* str);
+
+/**
+ * Convert a duration to a string.
+ * \param[in] duration duration to be converted
+ * \return char* string-format duration
+ *
+ */
+char* ldns_duration2string(ldns_duration_type* duration);
+
+/**
+ * Convert a duration to a time.
+ * \param[in] duration duration to be converted
+ * \return time_t time-format duration
+ *
+ */
+time_t ldns_duration2time(ldns_duration_type* duration);
+
+/**
+ * Return a random time.
+ * \param[in] mod modulo
+ * \return time_t random time
+ *
+ */
+time_t ods_rand(time_t mod);
+
+/**
+ * Return the shortest time.
+ * \param[in] a one time
+ * \param[in] b another time
+ * \return time_t the shortest time
+ *
+ */
+time_t time_minimum(time_t a, time_t b);
+
+/**
+ * Return the longest time.
+ * \param[in] a one time
+ * \param[in] b another time
+ * \return time_t the shortest time
+ *
+ */
+time_t time_maximum(time_t a, time_t b);
+
+/**
+ * Convert time into string.
+ * \param[in] n time
+ * \param[in] s string
+ *
+ */
+void time_itoa(time_t n, char* s);
+
+/**
+ * Return time in datestamp.
+ * \param[in] tt time
+ * \param[in] format stamp format
+ * \param[out] str store string
+ * \return uint32_t integer based datestamp.
+ *
+ */
+uint32_t time_datestamp(time_t tt, const char* format, char** str);
+
+/**
+ * Return the time since Epoch, measured in seconds.
+ * If the timeshift is enabled, return the environment variable.
+ * \return time_t now (or timeshift).
+ *
+ */
+time_t time_now(void);
+
+/**
+ * Clean up duration.
+ * \param[in] duration duration to be cleaned up
+ *
+ */
+void ldns_duration_cleanup(ldns_duration_type* duration);
+
+#endif /* LDNS_DURATION_H */
index f4555a79ff4bcb1daf3c3f3783718c7a38b73839..cc93ce753c40524883bd55f5426d3b5bfb001d2a 100644 (file)
@@ -14,10 +14,27 @@ RRSIG resource records are checked against the DNSKEY set at the zone apex.
 Each name is checked for an NSEC(3), if appropriate.
 
 .SH OPTIONS
+.TP
+\fB-h\fR
+Show usage and exit
+
 .TP
 \fB-a\fR
 Apex only, check only the zone apex
 
+.TP
+\fB-e\fR \fIperiod\fR
+Signatures may not expire within this period.
+
+.TP
+\fB-i\fR \fIperiod\fR
+Signatures must have been valid at least this long.
+
+.TP
+\fB-k\fR \fIfile\fR
+A file that contains a trusted DNSKEY or DS rr.
+This option may be given more than once.
+
 .TP
 \fB-p\fR \fI[0-100]\fR
 Only check this percentage of the zone.
@@ -25,8 +42,9 @@ Which names to check is determined randomly.
 Defaults to 100.
 
 .TP
-\fB-h\fR
-Show usage and exit
+\fB-S\fR
+Chase signature(s) to a known key.
+The network may be accessed to validate the zone's DNSKEYs. (implies -k)
 
 .TP
 \fB-t\fR \fIYYYYMMDDhhmmss | [+|-]offset\fR
index 7b67c73bcf00610d69ca17b914b8d5ad08e67670..5bb5ac9eb681b85ad8abceecb72dddc63a8718a2 100644 (file)
@@ -11,6 +11,7 @@
 #include "config.h"
 #include <unistd.h>
 #include <stdlib.h>
+#include "ldns-duration.h"
 
 #include <ldns/ldns.h>
 
 #ifdef HAVE_SSL
 #include <openssl/err.h>
 
+#define LDNS_VERIFY_ZONE_ERROR 0x8000
+#define LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED_WITHIN_MARGIN \
+                               LDNS_VERIFY_ZONE_ERROR | 0
+#define LDNS_STATUS_CRYPTO_SIG_EXPIRED_WITHIN_MARGIN \
+                               LDNS_VERIFY_ZONE_ERROR | 1
+
 int verbosity = 3;
+time_t check_time = 0;
+time_t inception_offset = 0;
+time_t expiration_offset = 0;
+bool do_sigchase = false;
+bool no_nomatch_msg = false;
+bool zone_is_nsec3_optout = false;
+
+FILE* myout;
+FILE* myerr;
 
-static int
-zone_is_nsec3_optout(ldns_rbtree_t *zone_nodes)
+static const char*
+get_errorstr_by_id(int err)
 {
-       /* simply find the first NSEC3 RR and check its flags */
-       /* TODO: maybe create a general function that uses the active
-        * NSEC3PARAM RR? */
-       ldns_rbnode_t *cur_node;
-       ldns_dnssec_name *cur_name;
-       cur_node = ldns_rbtree_first(zone_nodes);
-       while (cur_node != LDNS_RBTREE_NULL) {
-               cur_name = (ldns_dnssec_name *) cur_node->data;
-               if (cur_name && cur_name->nsec &&
-                   ldns_rr_get_type(cur_name->nsec) == LDNS_RR_TYPE_NSEC3) {
-                       if (ldns_nsec3_optout(cur_name->nsec)) {
-                               return 1;
-                       } else {
-                               return 0;
-                       }
-               }
-               cur_node = ldns_rbtree_next(cur_node);
+       switch (err) {
+               case LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED_WITHIN_MARGIN:
+                       return "DNSSEC signature not incepted long enough";
+               case LDNS_STATUS_CRYPTO_SIG_EXPIRED_WITHIN_MARGIN:
+                       return "DNSSEC signature will expire to soon";
+               default:
+                       return ldns_get_errorstr_by_id(err);
        }
-       return 0;
 }
 
 static void
-print_type(ldns_rr_type type)
+print_type(FILE* stream, ldns_rr_type type)
 {
-       const ldns_rr_descriptor *descriptor;
+       const ldns_rr_descriptor *descriptor  = ldns_rr_descript(type);
 
-       descriptor = ldns_rr_descript(type);
        if (descriptor && descriptor->_name) {
-               fprintf(stdout, "%s", descriptor->_name);
+               fprintf(stream, "%s", descriptor->_name);
        } else {
-               fprintf(stdout, "TYPE%u",
-                          type);
+               fprintf(stream, "TYPE%u", type);
+       }
+}
+
+ldns_status
+read_key_file(const char *filename, ldns_rr_list *keys)
+{
+       ldns_status status = LDNS_STATUS_ERR;
+       ldns_rr *rr;
+       FILE *fp;
+       uint32_t my_ttl = 0;
+       ldns_rdf *my_origin = NULL;
+       ldns_rdf *my_prev = NULL;
+       int line_nr;
+
+       if (! (fp = fopen(filename, "r"))) {
+               fprintf( myerr
+                      , "Error opening %s: %s\n"
+                      , filename
+                      , strerror(errno)
+                      );
+               return LDNS_STATUS_ERR;
        }
+       while (!feof(fp)) {
+               status = ldns_rr_new_frm_fp_l( &rr
+                                            , fp
+                                            , &my_ttl
+                                            , &my_origin
+                                            , &my_prev
+                                            , &line_nr
+                                            );
+
+               if (status == LDNS_STATUS_OK) {
 
+                       if ( ldns_rr_get_type(rr) == LDNS_RR_TYPE_DS
+                       ||   ldns_rr_get_type(rr) == LDNS_RR_TYPE_DNSKEY )
+
+                               ldns_rr_list_push_rr(keys, rr);
+
+               } else if (status == LDNS_STATUS_SYNTAX_EMPTY
+                      ||  status == LDNS_STATUS_SYNTAX_TTL
+                      ||  status == LDNS_STATUS_SYNTAX_ORIGIN
+                      ||  status == LDNS_STATUS_SYNTAX_INCLUDE )
+
+                       status = LDNS_STATUS_OK;
+               else
+                       break;
+       }
+       return status;
 }
 
-static ldns_dnssec_zone *
-create_dnssec_zone(ldns_zone *orig_zone)
+static bool
+rr_is_rrsig_covering(ldns_rr* rr, ldns_rr_type t)
 {
+       return     ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG
+               && ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)) == t;
+}
+
+static ldns_status
+dnssec_zone_new_frm_fp_l( ldns_dnssec_zone** z
+                       , FILE* fp
+                       , ldns_rdf* origin
+                       , uint32_t ttl
+                       , ldns_rr_class ATTR_UNUSED(c)
+                       , int* line_nr
+                       )
+{
+       ldns_rr* cur_rr;
        size_t i;
-       ldns_dnssec_zone *dnssec_zone;
-       ldns_rr *cur_rr;
-       ldns_status status;
 
+       uint32_t  my_ttl = ttl;
+       ldns_rdf *my_origin = NULL;
+       ldns_rdf *my_prev = NULL;
+
+       ldns_dnssec_zone *newzone = ldns_dnssec_zone_new();
        /* when reading NSEC3s, there is a chance that we encounter nsecs
           for empty nonterminals, whose nonterminals we cannot derive yet
           because the needed information is to be read later. in that case
           we keep a list of those nsec3's and retry to add them later */
-       ldns_rr_list *failed_nsec3s = ldns_rr_list_new();
-       ldns_rr_list *failed_nsec3_rrsigs = ldns_rr_list_new();
+       ldns_rr_list* todo_nsec3s = ldns_rr_list_new();
+       ldns_rr_list* todo_nsec3_rrsigs = ldns_rr_list_new();
 
-       dnssec_zone = ldns_dnssec_zone_new();
-       if (ldns_dnssec_zone_add_rr(dnssec_zone, ldns_zone_soa(orig_zone))
-                       != LDNS_STATUS_OK) {
-               if (verbosity > 0) {
-                       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++) {
-               cur_rr = ldns_rr_list_rr(ldns_zone_rrs(orig_zone), i);
-               status = ldns_dnssec_zone_add_rr(dnssec_zone, cur_rr);
-               if (status != LDNS_STATUS_OK) {
-                       if (LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND
-                                       == status) {
-                               if (ldns_rr_get_type(cur_rr)
-                                           == LDNS_RR_TYPE_RRSIG
-                                           && ldns_rdf2rr_type(
-                                                 ldns_rr_rrsig_typecovered(
-                                                         cur_rr
-                                                  )
-                                               ) == LDNS_RR_TYPE_NSEC3) {
-                                       ldns_rr_list_push_rr(
-                                                       failed_nsec3_rrsigs, 
-                                                       cur_rr);
+       ldns_status status = LDNS_STATUS_MEM_ERR;
+
+       if ( ! newzone || ! todo_nsec3s || ! todo_nsec3_rrsigs ) goto error;
+
+       if (origin) {
+               if (! (my_origin = ldns_rdf_clone(origin))) goto error;
+               if (! (my_prev   = ldns_rdf_clone(origin))) goto error;
+       }
+
+       while (!feof(fp)) {
+               status = ldns_rr_new_frm_fp_l( &cur_rr
+                                            , fp
+                                            , &my_ttl
+                                            , &my_origin
+                                            , &my_prev
+                                            , line_nr
+                                            );
+               switch (status) {
+               case LDNS_STATUS_OK:
+
+                       status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
+                       if (status 
+                       ==  LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) {
+
+                               if (rr_is_rrsig_covering( cur_rr
+                                                       , LDNS_RR_TYPE_NSEC3)){
+                                       ldns_rr_list_push_rr( todo_nsec3_rrsigs
+                                                           , cur_rr
+                                                           );
                                } else {
-                                       ldns_rr_list_push_rr(failed_nsec3s, 
-                                                       cur_rr);
-                               }
-                       } else {
-                               if (verbosity > 0) {
-                                       fprintf(stderr, "Error adding RR to "
-                                                       "dnssec zone"
-                                                       ", skipping record:\n");
-                                       ldns_rr_print(stderr, cur_rr);
+                                       ldns_rr_list_push_rr( todo_nsec3s
+                                                           , cur_rr
+                                                           );
                                }
-                       }
+                       } else if (status != LDNS_STATUS_OK)
+                               goto error;
+
+                       if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_NSEC3)
+                               zone_is_nsec3_optout
+                                       =  zone_is_nsec3_optout
+                                          || ldns_nsec3_optout(cur_rr);
+
+                       break;
+
+
+               case LDNS_STATUS_SYNTAX_EMPTY:  /* empty line was seen */
+               case LDNS_STATUS_SYNTAX_TTL:    /* the ttl was set*/
+               case LDNS_STATUS_SYNTAX_ORIGIN: /* the origin was set*/
+                       break;
+
+               case LDNS_STATUS_SYNTAX_INCLUDE:/* $include not implemented */
+                       status =  LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL;
+                       break;
+
+               default:
+                       goto error;
                }
        }
 
-       if (ldns_rr_list_rr_count(failed_nsec3s) > 0) {
-               (void) ldns_dnssec_zone_add_empty_nonterminals(dnssec_zone);
-               for (i = 0; i < ldns_rr_list_rr_count(failed_nsec3s); i++) {
-                       cur_rr = ldns_rr_list_rr(failed_nsec3s, i);
-                       status = ldns_dnssec_zone_add_rr(dnssec_zone, cur_rr);
+       if (ldns_rr_list_rr_count(todo_nsec3s) > 0) {
+               (void) ldns_dnssec_zone_add_empty_nonterminals(newzone);
+               for (i = 0; i < ldns_rr_list_rr_count(todo_nsec3s); i++) {
+                       cur_rr = ldns_rr_list_rr(todo_nsec3s, i);
+                       status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
                }
-               for (i = 0; i < ldns_rr_list_rr_count(failed_nsec3_rrsigs); 
-                               i++) {
-                       cur_rr = ldns_rr_list_rr(failed_nsec3_rrsigs, i);
-                       status = ldns_dnssec_zone_add_rr(dnssec_zone, cur_rr);
+               for (i = 0; i < ldns_rr_list_rr_count(todo_nsec3_rrsigs); i++){
+                       cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i);
+                       status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
+               }
+       } else if (ldns_rr_list_rr_count(todo_nsec3_rrsigs) > 0) {
+               for (i = 0; i < ldns_rr_list_rr_count(todo_nsec3_rrsigs); i++){
+                       cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i);
+                       status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
                }
        }
 
-       ldns_rr_list_free(failed_nsec3_rrsigs);
-       ldns_rr_list_free(failed_nsec3s);
-       return dnssec_zone;
+       ldns_rr_list_free(todo_nsec3_rrsigs);
+       ldns_rr_list_free(todo_nsec3s);
+
+       if (z) {
+               *z = newzone;
+       } else {
+               ldns_dnssec_zone_free(newzone);
+       }
+
+       return LDNS_STATUS_OK;
+
+error:
+       if (my_origin) {
+               ldns_rdf_deep_free(my_origin);
+       }
+       if (my_prev) {
+               ldns_rdf_deep_free(my_prev);
+       }
+       if (newzone) {
+               ldns_dnssec_zone_free(newzone);
+       }
+       return status;
+}
+
+
+
+static void
+print_rr_error(FILE* stream, ldns_rr* rr, const char* msg)
+{
+       if (verbosity > 0) {
+               fprintf(stream, "Error: %s for ", msg);
+               ldns_rdf_print(stream, ldns_rr_owner(rr));
+               fprintf(stream, "\t");
+               print_type(stream, ldns_rr_get_type(rr));
+               fprintf(stream, "\n");
+       }
+}
+
+static void
+print_rr_status_error(FILE* stream, ldns_rr* rr, ldns_status status)
+{
+       if (status != LDNS_STATUS_OK) {
+               print_rr_error(stream, rr, get_errorstr_by_id(status));
+               if (verbosity > 0 && status == LDNS_STATUS_SSL_ERR) {
+                       ERR_load_crypto_strings();
+                       ERR_print_errors_fp(stream);
+               }
+       }
+}
+
+static void
+print_rrs_status_error( FILE* stream
+                     , ldns_rr_list* rrs
+                     , ldns_status status
+                     , ldns_dnssec_rrs* cur_sig
+                     )
+{
+       if (status != LDNS_STATUS_OK) {
+               if (ldns_rr_list_rr_count(rrs) > 0) {
+                       print_rr_status_error( stream
+                                            , ldns_rr_list_rr(rrs, 0)
+                                            , status
+                                            );
+               } else {
+                       fprintf( stream
+                              , "Error: %s for <unknown>\n"
+                              , get_errorstr_by_id(status)
+                              );
+               }
+               if (verbosity >= 4) {
+                       fprintf(stream, "RRSet:\n");
+                       ldns_rr_list_print(stream, rrs);
+                       fprintf(stream, "Signature:\n");
+                       ldns_rr_print(stream, cur_sig->rr);
+                       fprintf(stream, "\n");
+               }
+       }
+}
+
+static ldns_status
+rrsig_check_time_margins(ldns_rr* rrsig)
+{
+       int32_t inception, expiration;
+
+       inception  = ldns_rdf2native_int32(ldns_rr_rrsig_inception (rrsig));
+       expiration = ldns_rdf2native_int32(ldns_rr_rrsig_expiration(rrsig));
+
+       if (check_time - inception_offset  - inception  < 0) {
+               return LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED_WITHIN_MARGIN;
+       }
+       if (expiration - expiration_offset - check_time < 0) {
+               return LDNS_STATUS_CRYPTO_SIG_EXPIRED_WITHIN_MARGIN;
+       }
+       return LDNS_STATUS_OK;
+}
+
+static ldns_status
+verify_rrs( ldns_rr_list* rrset_rrs
+         , ldns_dnssec_rrs* cur_sig
+         , ldns_rr_list* keys
+         )
+{
+       ldns_rr_list* good_keys;
+       ldns_status status, result = LDNS_STATUS_OK;
+
+       while (cur_sig) {
+               good_keys = ldns_rr_list_new();
+               status = ldns_verify_rrsig_keylist_time( rrset_rrs
+                                                      , cur_sig->rr
+                                                      , keys
+                                                      , check_time
+                                                      , good_keys
+                                                      );
+               status = status ? status 
+                               : rrsig_check_time_margins(cur_sig->rr);
+               if ( status != LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY
+               || ! no_nomatch_msg ) {
+                       print_rrs_status_error( myerr
+                                             , rrset_rrs
+                                             , status
+                                             , cur_sig
+                                             );
+               }
+               result = result ? result : status;
+               ldns_rr_list_free(good_keys);
+               cur_sig = cur_sig->next;
+       }
+
+       return result;
 }
 
 static ldns_status
-verify_dnssec_rrset(
-               ldns_rdf *zone_name, 
-               ldns_rdf *name,
-               ldns_dnssec_rrsets *rrset,
-               ldns_rr_list *keys,
-               time_t check_time
-               ) 
+verify_dnssec_rrset( ldns_rdf *zone_name
+                  , ldns_rdf *name
+                  , ldns_dnssec_rrsets *rrset
+                  , ldns_rr_list *keys
+                  ) 
 {
        ldns_rr_list *rrset_rrs;
        ldns_dnssec_rrs *cur_rr, *cur_sig;
        ldns_status status;
-       ldns_rr_list *good_keys;
-       ldns_status result = LDNS_STATUS_OK;
 
        if (!rrset->rrs) return LDNS_STATUS_OK;
 
@@ -158,115 +368,39 @@ verify_dnssec_rrset(
        }
        cur_sig = rrset->signatures;
        if (cur_sig) {
-               while (cur_sig) {
-                       good_keys = ldns_rr_list_new();
-                       status = ldns_verify_rrsig_keylist_time(
-                                       rrset_rrs, cur_sig->rr, 
-                                       keys, check_time, good_keys);
-                       if (status != LDNS_STATUS_OK) {
-                               if (verbosity > 0) {
-                                       printf("Error: %s",
-                                               ldns_get_errorstr_by_id(
-                                                       status));
-                                       printf(" for ");
-                                       ldns_rdf_print(stdout,
-                                               ldns_rr_owner(rrset->rrs->rr));
-                                       printf("\t");
-                                       print_type(rrset->type);
-                                       printf("\n");
-                                       if (result == LDNS_STATUS_OK) {
-                                               result = status;
-                                       }
-                                       if (status == LDNS_STATUS_SSL_ERR) {
-                                               ERR_load_crypto_strings();
-                                               ERR_print_errors_fp(stdout);
-                                       }
-                                       if (verbosity >= 4) {
-                                               printf("RRSet:\n");
-                                               ldns_dnssec_rrs_print(stdout,
-                                                               rrset->rrs);
-                                               printf("Signature:\n");
-                                               ldns_rr_print(stdout,
-                                                               cur_sig->rr);
-                                               printf("\n");
-                                       }
-                               }
-                       }
-                       ldns_rr_list_free(good_keys);
+               status = verify_rrs(rrset_rrs, cur_sig, keys);
 
-                       cur_sig = cur_sig->next;
-               }
+       } else /* delegations may be unsigned (on opt out...) */
+              if (rrset->type != LDNS_RR_TYPE_NS 
+              ||  ldns_dname_compare(name, zone_name) == 0) {
+               
+               print_rr_error(myerr, rrset->rrs->rr, "no signatures");
+               status = LDNS_STATUS_CRYPTO_NO_RRSIG;
        } else {
-               /* delegations are unsigned */
-               if (rrset->type != LDNS_RR_TYPE_NS ||
-                       ldns_dname_compare(name, zone_name) == 0) {
-                       if (verbosity > 0) {
-                               printf("Error: no signatures for ");
-                               ldns_rdf_print(stdout, 
-                                               ldns_rr_owner(rrset->rrs->rr));
-                               printf("\t");
-                               print_type(rrset->type);
-                               printf("\n");
-                       }
-               }
+               status = LDNS_STATUS_OK;
        }
        ldns_rr_list_free(rrset_rrs);
-       return result;
+
+       return status;
 }
 
 static ldns_status
-verify_single_rr(
-               ldns_rr *rr, 
-               ldns_dnssec_rrs *signature_rrs, 
-               ldns_rr_list *keys)
+verify_single_rr( ldns_rr *rr
+               , ldns_dnssec_rrs *signature_rrs
+               , ldns_rr_list *keys
+               )
 {
        ldns_rr_list *rrset_rrs;
-       ldns_rr_list *good_keys;
-       ldns_dnssec_rrs *cur_sig;
        ldns_status status;
-       ldns_status result = LDNS_STATUS_OK;
 
        rrset_rrs = ldns_rr_list_new();
        ldns_rr_list_push_rr(rrset_rrs, rr);
 
-       cur_sig = signature_rrs;
-       while (cur_sig) {
-               good_keys = ldns_rr_list_new();
-               status = ldns_verify_rrsig_keylist(
-                               rrset_rrs, cur_sig->rr, keys, good_keys);
-               if (status != LDNS_STATUS_OK) {
-                       if (verbosity >= 1) {
-                               printf("Error: %s ", 
-                                       ldns_get_errorstr_by_id(status));
-                               if (result == LDNS_STATUS_OK) {
-                                       result = status;
-                               }
-                               printf("for ");
-                               ldns_rdf_print(stdout, ldns_rr_owner(rr));
-                               printf("\t");
-                               print_type(ldns_rr_get_type(rr));
-                               printf("\n");
-                               if (status == LDNS_STATUS_SSL_ERR) {
-                                       ERR_load_crypto_strings();
-                                       ERR_print_errors_fp(stdout);
-                               }
-                               if (verbosity >= 4) {
-                                       printf("RRSet:\n");
-                                       ldns_rr_list_print(stdout, rrset_rrs);
-                                       printf("Signature:\n");
-                                       ldns_rr_print(stdout, cur_sig->rr);
-                                       printf("\n");
-                               }
-                       }
-                       result = status;
-               }
-               ldns_rr_list_free(good_keys);
-               cur_sig = cur_sig->next;
-       }
+       status = verify_rrs(rrset_rrs, signature_rrs, keys);
 
        ldns_rr_list_free(rrset_rrs);
 
-       return result;
+       return status;
 }
 
 static ldns_status
@@ -295,22 +429,27 @@ verify_next_hashed_name(ldns_rbtree_t *zone_nodes, ldns_dnssec_name *name)
                        continue;
                }
                if (!next_name->hashed_name) {
-                       next_name->hashed_name = ldns_nsec3_hash_name_frm_nsec3(
-                                       name->nsec, next_name->name);
+                       next_name->hashed_name = ldns_nsec3_hash_name_frm_nsec3
+                                                ( name->nsec
+                                                , next_name->name
+                                                );
                }
                /* we keep track of what 'so far' is the next hashed name;
                 * it must of course be 'larger' than the current name
                 * if we find one that is larger, but smaller than what we
                 * previously thought was the next one, that one is the next
                 */
-               cmp = ldns_dname_compare(
-                               name->hashed_name, next_name->hashed_name);
+               cmp = ldns_dname_compare( name->hashed_name
+                                       , next_name->hashed_name
+                                       );
                if (cmp < 0) {
                        if (!cur_next_name) {
                                cur_next_name = next_name;
                        } else {
-                               cmp = ldns_dname_compare(next_name->hashed_name,
-                                               cur_next_name->hashed_name);
+                               cmp = ldns_dname_compare
+                                     ( next_name->hashed_name
+                                     , cur_next_name->hashed_name
+                                     );
                                if (cmp < 0) {
                                        cur_next_name = next_name;
                                }
@@ -321,8 +460,9 @@ verify_next_hashed_name(ldns_rbtree_t *zone_nodes, ldns_dnssec_name *name)
                if (!cur_first_name) {
                        cur_first_name = next_name;
                } else {
-                       cmp = ldns_dname_compare(next_name->hashed_name,
-                                       cur_first_name->hashed_name);
+                       cmp = ldns_dname_compare( next_name->hashed_name
+                                               , cur_first_name->hashed_name
+                                               );
                        if (cmp < 0) {
                                cur_first_name = next_name;
                        }
@@ -335,19 +475,24 @@ verify_next_hashed_name(ldns_rbtree_t *zone_nodes, ldns_dnssec_name *name)
 
        next_owner_str = ldns_rdf2str(ldns_nsec3_next_owner(name->nsec));
        next_owner_dname = ldns_dname_new_frm_str(next_owner_str);
-       cmp = ldns_dname_compare(next_owner_dname,
-                                cur_next_name->hashed_name);
+       cmp = ldns_dname_compare( next_owner_dname
+                               , cur_next_name->hashed_name
+                               );
        ldns_rdf_deep_free(next_owner_dname);
        LDNS_FREE(next_owner_str);
        if (cmp != 0) {
-               printf("Error: The NSEC3 record for ");
-               ldns_rdf_print(stdout, name->name);
-               printf(" points to the wrong next hashed owner name\n");
-               printf("(should point to ");
-               ldns_rdf_print(stdout, cur_next_name->name);
-               printf("(whose hashed name is ");
-               ldns_rdf_print(stdout, cur_next_name->hashed_name);
-               printf(")\n");
+               if (verbosity > 0) {
+                       fprintf(myerr, "Error: The NSEC3 record for ");
+                       ldns_rdf_print(stdout, name->name);
+                       fprintf( myerr
+                              , " points to the wrong next hashed owner"
+                                " name\n\tshould point to "
+                              );
+                       ldns_rdf_print(myerr, cur_next_name->name);
+                       fprintf(myerr, ", whose hashed name is ");
+                       ldns_rdf_print(myerr, cur_next_name->hashed_name);
+                       fprintf(myerr, "\n");
+               }
                return LDNS_STATUS_ERR;
        } else {
                return LDNS_STATUS_OK;
@@ -355,10 +500,10 @@ verify_next_hashed_name(ldns_rbtree_t *zone_nodes, ldns_dnssec_name *name)
 }
 
 static ldns_status
-verify_nsec(
-               ldns_rbtree_t *zone_nodes, 
-               ldns_rbnode_t *cur_node, 
-               ldns_rr_list *keys)
+verify_nsec( ldns_rbtree_t *zone_nodes
+          , ldns_rbnode_t *cur_node
+          , ldns_rr_list *keys
+          )
 {
        ldns_rbnode_t *next_node;
        ldns_dnssec_name *name, *next_name;
@@ -368,20 +513,21 @@ verify_nsec(
        name = (ldns_dnssec_name *) cur_node->data;
        if (name->nsec) {
                if (name->nsec_signatures) {
-                       status = verify_single_rr(name->nsec,
-                                       name->nsec_signatures, keys);
-                       if (result == LDNS_STATUS_OK) {
-                               result = status;
-                       }
+                       status = verify_single_rr( name->nsec
+                                                , name->nsec_signatures
+                                                , keys
+                                                );
+
+                       result = result ? result : status;
                } else {
-                       if (verbosity >= 1) {
-                               printf("Error: the NSEC(3) record of ");
-                               ldns_rdf_print(stdout, name->name);
-                               printf(" has no signatures\n");
-                       }
-                       if (result == LDNS_STATUS_OK) {
-                               result = LDNS_STATUS_ERR;
+                       if (verbosity >= 0) {
+                               fprintf( myerr
+                                      , "Error: the NSEC(3) record of "
+                                      );
+                               ldns_rdf_print(myerr, name->name);
+                               fprintf(myerr, " has no signatures\n");
                        }
+                       result = result ? result : LDNS_STATUS_ERR;
                }
                /* check whether the NSEC record points to the right name */
                switch (ldns_rr_get_type(name->nsec)) {
@@ -395,81 +541,82 @@ verify_nsec(
                                next_node = ldns_dnssec_name_node_next_nonglue(
                                                next_node);
                                next_name = (ldns_dnssec_name *)next_node->data;
-                               if (ldns_dname_compare(
-                                                       next_name->name,
-                                                       ldns_rr_rdf(
-                                                               name->nsec, 0)) 
-                                               != 0) {
-                                       printf("Error: the NSEC record for ");
-                                       ldns_rdf_print(stdout, name->name);
-                                       printf(" points to the wrong next "
-                                                       "owner name\n");
+                               if (ldns_dname_compare( next_name->name
+                                                     , ldns_rr_rdf( name->nsec
+                                                                  , 0
+                                                                  )
+                                                     ) != 0) {
+                                       fprintf( myerr
+                                              , "Error: the NSEC record for "
+                                              );
+                                       ldns_rdf_print(myerr, name->name);
+                                       fprintf( myerr
+                                              , " points to the wrong next"
+                                                " owner name\n"
+                                              );
                                        if (verbosity >= 4) {
-                                               printf("     : ");
-                                               ldns_rdf_print(stdout,
-                                                       ldns_rr_rdf(name->nsec, 
-                                                               0));
-                                               printf(" i.s.o. ");
-                                               ldns_rdf_print(stdout, 
-                                                       next_name->name);
-                                               printf(".\n");
-                                       }
-                                       if (result == LDNS_STATUS_OK) {
-                                               result = LDNS_STATUS_ERR;
+                                               fprintf(myerr, "\t: ");
+                                               ldns_rdf_print( myerr
+                                                             , ldns_rr_rdf(
+                                                               name->nsec, 0)
+                                                             );
+                                               fprintf(myerr, " i.s.o. ");
+                                               ldns_rdf_print( myerr
+                                                             , next_name->name
+                                                             );
+                                               fprintf(myerr, ".\n");
                                        }
+                                       result = result ? result 
+                                              : LDNS_STATUS_ERR;
                                }
                                break;
                        case LDNS_RR_TYPE_NSEC3:
                                /* find the hashed next name in the tree */
-                               /* this is expensive, do we need to add support
-                                * for this in the structs? (ie. pointer to next
-                                * hashed name?)
+                               /* this is expensive, do we need to add 
+                                * support for this in the structs?
+                                * (ie. pointer to next hashed name?)
                                 */
-                               status = verify_next_hashed_name(
-                                               zone_nodes, name);
-                               if (result == LDNS_STATUS_OK) {
-                                       result = status;
-                               }
+                               status = verify_next_hashed_name( zone_nodes
+                                                               , name
+                                                               );
+                               result = result ? result : status;
                                break;
                        default:
                                break;
                }
        } else {
-               /* todo; do this once and cache result? */
-               if (zone_is_nsec3_optout(zone_nodes) &&
-                               (   ldns_dnssec_name_is_glue(name)
-                                || (
-                                        ldns_dnssec_rrsets_contains_type(
-                                               name->rrsets, LDNS_RR_TYPE_NS)
-                                    && !ldns_dnssec_rrsets_contains_type(
-                                               name->rrsets, LDNS_RR_TYPE_DS)
-                                   )
-                               )) {
+               if (zone_is_nsec3_optout
+               && (ldns_dnssec_name_is_glue(name)
+                   || (    ldns_dnssec_rrsets_contains_type( name->rrsets
+                                                           , LDNS_RR_TYPE_NS
+                                                           )
+                       && !ldns_dnssec_rrsets_contains_type( name->rrsets
+                                                           , LDNS_RR_TYPE_DS
+                                                           )))) {
+                       /* TODO */
                        /* ok, no problem, but we need to remember to check
                         * whether the chain does not actually point to this
                         * name later */
                } else {
                        if (verbosity >= 1) {
-                               printf("Error: there is no NSEC(3) for ");
-                               ldns_rdf_print(stdout, name->name);
-                               printf("\n");
-                       }
-                       if (result == LDNS_STATUS_OK) {
-                               result = LDNS_STATUS_ERR;
+                               fprintf( myerr
+                                      , "Error: there is no NSEC(3) for ");
+                               ldns_rdf_print(myerr, name->name);
+                               fprintf(myerr, "\n");
                        }
+                       result = result ? result : LDNS_STATUS_ERR;
                }
        }
        return result;
 }
 
 static ldns_status
-verify_dnssec_name(ldns_rdf *zone_name,
-               ldns_dnssec_zone* ATTR_UNUSED(zone),
-                ldns_rbtree_t *zone_nodes,
-                ldns_rbnode_t *cur_node,
-               ldns_rr_list *keys,
-               time_t check_time
-               )
+verify_dnssec_name( ldns_rdf *zone_name
+                 , ldns_dnssec_zone* ATTR_UNUSED(zone)
+                 , ldns_rbtree_t *zone_nodes
+                 , ldns_rbnode_t *cur_node
+                 , ldns_rr_list *keys
+                 )
 {
        ldns_status result = LDNS_STATUS_OK;
        ldns_status status;
@@ -480,9 +627,9 @@ verify_dnssec_name(ldns_rdf *zone_name,
 
        name = (ldns_dnssec_name *) cur_node->data;
        if (verbosity >= 3) {
-               printf("Checking: ");
-               ldns_rdf_print(stdout, name->name);
-               printf("\n");
+               fprintf(myout, "Checking: ");
+               ldns_rdf_print(myout, name->name);
+               fprintf(myout, "\n");
        }
 
        if (ldns_dnssec_name_is_glue(name)) {
@@ -490,105 +637,251 @@ verify_dnssec_name(ldns_rdf *zone_name,
                cur_rrset = name->rrsets;
                while (cur_rrset) {
                        if (cur_rrset->signatures) {
-                               if (verbosity >= 1) {
-                                       printf("Error: ");
-                                       ldns_rdf_print(stdout, name->name);
-                                       printf("\t");
-                                       print_type(cur_rrset->type);
-                                       printf(" has signature(s), "
-                                                       "but is glue\n");
+                               if (verbosity >= 0) {
+                                       fprintf(myerr, "Error: ");
+                                       ldns_rdf_print(myerr, name->name);
+                                       fprintf(myerr, "\t");
+                                       print_type(myerr, cur_rrset->type);
+                                       fprintf( myerr
+                                              , " has signature(s),"
+                                                " but is glue\n"
+                                              );
                                }
                                result = LDNS_STATUS_ERR;
                        }
                        cur_rrset = cur_rrset->next;
                }
                if (name->nsec) {
-                       if (verbosity >= 1) {
-                               printf("Error: ");
-                               ldns_rdf_print(stdout, name->name);
-                               printf("\thas an NSEC(3), but is glue\n");
+                       if (verbosity >= 0) {
+                               fprintf(myerr, "Error: ");
+                               ldns_rdf_print(myerr, name->name);
+                               fprintf( myerr
+                                      , " has an NSEC(3),"
+                                        " but is glue\n"
+                                      );
                        }
                        result = LDNS_STATUS_ERR;
                }
        } else {
                /* not glue, do real verify */
 
-               on_delegation_point = ldns_dnssec_rrsets_contains_type(
-                               name->rrsets, LDNS_RR_TYPE_NS)
-                       && !ldns_dnssec_rrsets_contains_type(
-                               name->rrsets, LDNS_RR_TYPE_SOA);
-
+               on_delegation_point 
+                       =   ldns_dnssec_rrsets_contains_type( name->rrsets
+                                                           , LDNS_RR_TYPE_NS
+                                                           )
+                       && !ldns_dnssec_rrsets_contains_type( name->rrsets
+                                                           , LDNS_RR_TYPE_SOA
+                                                           );
                cur_rrset = name->rrsets;
                while(cur_rrset) {
 
                        /* Do not check occluded rrsets
                         * on the delegation point
                         */
-                       if (       ( on_delegation_point && (
-                                       cur_rrset->type == LDNS_RR_TYPE_NS
-                                    || cur_rrset->type == LDNS_RR_TYPE_DS))
-                               || (!on_delegation_point &&
-                                       cur_rrset->type != LDNS_RR_TYPE_RRSIG
-                                    && cur_rrset->type != LDNS_RR_TYPE_NSEC)) {
-
-                               status = verify_dnssec_rrset(
-                                               zone_name, name->name, 
-                                               cur_rrset, keys, check_time);
-                               if (status != LDNS_STATUS_OK 
-                                               && result == LDNS_STATUS_OK) {
-                                       result = status;
-                               }
+                       if ((   on_delegation_point 
+                            && (  cur_rrset->type == LDNS_RR_TYPE_NS
+                               || cur_rrset->type == LDNS_RR_TYPE_DS))
+                       ||  (  !on_delegation_point 
+                            &&    cur_rrset->type != LDNS_RR_TYPE_RRSIG
+                            &&    cur_rrset->type != LDNS_RR_TYPE_NSEC)) {
+
+                               status = verify_dnssec_rrset( zone_name
+                                                           , name->name
+                                                           , cur_rrset
+                                                           , keys
+                                                           );
+                               result = result ? result : status;
                        }
                        cur_rrset = cur_rrset->next;
                }
 
-               status = verify_nsec(zone_nodes, cur_node, keys);
-               if (result == LDNS_STATUS_OK) {
-                       result = status;
-               }
+               status = verify_nsec( zone_nodes
+                                   , cur_node
+                                   , keys
+                                   );
+               result = result ? result : status;
        }
        return result;
 }
 
+static void
+add_keys_with_matching_ds( ldns_dnssec_rrsets* from_keys
+                        , ldns_rr_list *dss
+                        , ldns_rr_list *to_keys
+                        )
+{
+       size_t i;
+       ldns_rr* ds_rr;
+       ldns_dnssec_rrs *cur_key;
+
+       for ( i = 0
+           ; i < ldns_rr_list_rr_count(dss)
+           ; i++ ) {
+
+               if (    ldns_rr_get_type(ds_rr = ldns_rr_list_rr(dss, i)) 
+                    == LDNS_RR_TYPE_DS) {
+
+                       for ( cur_key = from_keys->rrs
+                           ; cur_key
+                           ; cur_key = cur_key->next ) {
+
+                               if (ldns_rr_compare_ds(cur_key->rr, ds_rr)) {
+                                       ldns_rr_list_push_rr( to_keys
+                                                           , cur_key->rr
+                                                           );
+                                       break;
+                               }
+                       }
+               }
+       }
+}
+
+static ldns_status
+sigchase( ldns_resolver* res
+       , ldns_rdf *zone_name
+       , ldns_dnssec_rrsets *zonekeys
+       , ldns_rr_list *keys
+       )
+{
+       ldns_dnssec_rrs* cur_key;
+       ldns_status status;
+       bool free_resolver = false;
+       ldns_rdf* parent_name;
+       ldns_rr_list* parent_keys;
+       ldns_rr_list* ds_keys;
+
+       add_keys_with_matching_ds(zonekeys, keys, keys);
+
+       /* First try to authenticate the keys offline.
+        * When do_sigchase is given validation may continue lookup up
+        * keys online. Reporting the failure of the offline validation
+        * should then be suppressed.
+        */
+       no_nomatch_msg = do_sigchase;
+       status = verify_dnssec_rrset( zone_name
+                                   , zone_name
+                                   , zonekeys
+                                   , keys
+                                   );
+       no_nomatch_msg = false;
+
+       /* Continue online on validation failure when the -S option was given.
+        */
+       if ( do_sigchase 
+       &&   status == LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY
+       &&   ldns_dname_label_count(zone_name) > 0 ) {
+
+               if (! res) {
+                       if ((status = ldns_resolver_new_frm_file(&res, NULL))){
+                               ldns_resolver_free(res);
+                               fprintf( myerr
+                                      , "Could not create resolver: %s\n"
+                                      , ldns_get_errorstr_by_id(status)
+                                      );
+                               return status;
+                       }
+                       free_resolver = true;
+                       ldns_resolver_set_dnssec(res,1);
+                       ldns_resolver_set_dnssec_cd(res, 1);
+               }
+               if ((parent_name = ldns_dname_left_chop(zone_name))) {
+                       /*
+                        * Use the (authenticated) keys of the parent zone ...
+                        */
+                       parent_keys
+                               = ldns_fetch_valid_domain_keys( res
+                                                             , parent_name
+                                                             , keys
+                                                             , &status
+                                                             );
+                       ldns_rdf_deep_free(parent_name);
+
+                       /*
+                        * ... to validate the DS for the zone ...
+                        */
+                       ds_keys = ldns_validate_domain_ds( res
+                                                        , zone_name
+                                                        , parent_keys
+                                                        );
+                       ldns_rr_list_free(parent_keys);
+
+                       /*
+                        * ... to use it to add the KSK to the trusted keys ...
+                        */
+                       add_keys_with_matching_ds(zonekeys, ds_keys, keys);
+                       ldns_rr_list_free(ds_keys);
+
+                       /*
+                        * ... to validate all zonekeys ...
+                        */
+                       status = verify_dnssec_rrset( zone_name
+                                                   , zone_name
+                                                   , zonekeys
+                                                   , keys
+                                                   );
+               } else {
+                       status = LDNS_STATUS_MEM_ERR;
+               }
+               if (free_resolver) {
+                       ldns_resolver_deep_free(res);
+               }
+
+       }
+       /*
+        * ... so they can all be added to our list of trusted keys.
+        */
+       if (status == LDNS_STATUS_OK)
+               for ( cur_key = zonekeys->rrs
+                   ; cur_key
+                   ; cur_key = cur_key->next
+                   ) 
+                       ldns_rr_list_push_rr(keys, cur_key->rr);
+       return status;
+}
+
 static ldns_status
-verify_dnssec_zone(
-               ldns_dnssec_zone *dnssec_zone, 
-               ldns_rdf *zone_name, 
-               bool apexonly, 
-               int percentage,
-               time_t check_time
-               ) 
+verify_dnssec_zone( ldns_dnssec_zone *dnssec_zone
+                 , ldns_rdf *zone_name
+                 , ldns_rr_list *keys
+                 , bool apexonly
+                 , int percentage
+                 ) 
 {
-       ldns_rr_list *keys;
        ldns_rbnode_t *cur_node;
        ldns_dnssec_rrsets *cur_key_rrset;
        ldns_dnssec_rrs *cur_key;
        ldns_status status;
        ldns_status result = LDNS_STATUS_OK;
 
-       keys = ldns_rr_list_new();
-       cur_key_rrset = ldns_dnssec_zone_find_rrset(
-                               dnssec_zone, zone_name, LDNS_RR_TYPE_DNSKEY);
+       cur_key_rrset = ldns_dnssec_zone_find_rrset( dnssec_zone, zone_name
+                                                  , LDNS_RR_TYPE_DNSKEY
+                                                  );
        if (!cur_key_rrset || !cur_key_rrset->rrs) {
-               if (verbosity >= 1) {
-                       printf("No DNSKEY records at zone apex\n");
+               if (verbosity >= 0) {
+                       fprintf( myerr
+                              , "Error: No DNSKEY records at zone apex\n");
                }
                result = LDNS_STATUS_ERR;
        } else {
-               cur_key = cur_key_rrset->rrs;
-               while (cur_key) {
-                       if (verbosity >= 4) {
-                               printf("DNSKEY: ");
-                               ldns_rr_print(stdout, cur_key->rr);
-                       }
-                       ldns_rr_list_push_rr(keys, cur_key->rr);
-                       cur_key = cur_key->next;
-               }
+               /* are keys given with -k to use for validation? */
+               if (ldns_rr_list_rr_count(keys) > 0) {
+                       if ((result = sigchase( NULL
+                                             , zone_name
+                                             , cur_key_rrset
+                                             , keys
+                                             )))
+                               goto error;
+               } else
+                       for ( cur_key = cur_key_rrset->rrs
+                           ; cur_key
+                           ; cur_key = cur_key->next
+                           ) 
+                               ldns_rr_list_push_rr(keys, cur_key->rr);
 
                cur_node = ldns_rbtree_first(dnssec_zone->names);
                if (cur_node == LDNS_RBTREE_NULL) {
-                       if (verbosity >= 1) {
-                               printf("Empty zone?\n");
+                       if (verbosity >= 0) {
+                               fprintf(myerr, "Error: Empty zone?\n");
                        }
                        result = LDNS_STATUS_ERR;
                }
@@ -608,25 +901,21 @@ verify_dnssec_zone(
                while (cur_node != LDNS_RBTREE_NULL) {
                        /* should we check this one? saves calls to random. */
                        if (percentage == 100
-                                       || ((random() % 100) 
-                                               >= 100 - percentage)) {
-                               status = verify_dnssec_name(
-                                               zone_name,
-                                               dnssec_zone,
-                                               dnssec_zone->names,
-                                               cur_node,
-                                               keys,
-                                               check_time);
-                               if (status != LDNS_STATUS_OK
-                                               && result == LDNS_STATUS_OK) {
-                                       result = status;
-                               }
+                       || ((random() % 100) >= 100 - percentage)) {
+                               status = verify_dnssec_name( zone_name
+                                                          , dnssec_zone
+                                                          , dnssec_zone->names
+                                                          , cur_node
+                                                          , keys
+                                                          );
+                               result = result ? result : status;
                                if (apexonly)
                                        break;
                        }
                        cur_node = ldns_rbtree_next(cur_node);
                }
        }
+error:
        ldns_rr_list_free(keys);
        return result;
 }
@@ -636,68 +925,131 @@ main(int argc, char **argv)
 {
        char *filename;
        FILE *fp;
-       ldns_zone *z;
        int line_nr = 0;
        int c;
        ldns_status s;
-       ldns_dnssec_zone *dnssec_zone;
+       ldns_dnssec_zone *dnssec_zone = NULL;
        ldns_status result = LDNS_STATUS_ERR;
        bool apexonly = false;
        int percentage = 100;
        struct tm tm;
-       time_t check_time = ldns_time(NULL);
+       ldns_duration_type *duration;
+       ldns_rr_list *keys = ldns_rr_list_new();
 
-       while ((c = getopt(argc, argv, "ahvV:p:t:")) != -1) {
+       check_time = ldns_time(NULL);
+       myout = stdout;
+       // myerr = stderr;
+       myerr = stdout;
+
+       while ((c = getopt(argc, argv, "ae:hi:k:vV:p:St:")) != -1) {
                switch(c) {
                 case 'a':
                         apexonly = true;
                         break;
                case 'h':
-                       printf("Usage: %s [OPTIONS] <zonefile>\n", argv[0]);
-                       printf("\tReads the zonefile and checks for DNSSEC "
-                                       "errors.\n");
-                       printf("\nIt checks whether NSEC(3)s are present,");
-                       printf(" and verifies all signatures\n");
-                       printf("It also checks the NSEC(3) chain, but it will "
-                                       "error on opted-out delegations\n");
-                       printf("\nOPTIONS:\n");
-                       printf("\t-a\t\tapex only, check only the zone apex\n");
-                       printf("\t-p [0-100]\tonly checks this percentage of "
-                                       "the zone.\n\t\t\tDefaults to 100\n");
-                       printf("\t-h\t\tshow this text\n");
-                       printf("\t-t YYYYMMDDhhmmss | [+|-]offset\n\t\t\t"
-                                       "Set the validation time either by an "
-                                       "absolute time\n\t\t\tvalue or as an offset "
-                                       "in seconds from <now>.\n");
-                       printf("\t-v\t\tshows the version and exits\n");
-                       printf("\t-V [0-5]\tset verbosity level (default 3)\n");
-                       printf("\nif no file is given standard input is "
-                                       "read\n");
+                       printf( "Usage: %s [OPTIONS] <zonefile>\n", argv[0] );
+                       printf( "\tReads the zonefile and checks for DNSSEC "
+                               "errors.\n"
+                             );
+                       printf( "\nIt checks whether NSEC(3)s are present, "
+                               "and verifies all signatures\n"
+                             );
+                       printf( "It also checks the NSEC(3) chain, but it "
+                               "will error on opted-out delegations\n"
+                             );
+                       printf( "\nOPTIONS:\n");
+                       printf( "\t-h\t\tshow this text\n");
+                       printf( "\t-a\t\tapex only, "
+                               "check only the zone apex\n"
+                             );
+                       printf( "\t-e <period>\tsignatures may not expire "
+                               "within this period.\n"
+                             );
+                       printf( "\t-i <period>\tsignatures must have been "
+                               "valid at least this long.\n"
+                             );
+                       printf( "\t-k <file>\tspecify a file that contains a "
+                               "trusted DNSKEY or DS rr.\n\t\t\t"
+                               "This option may be given more than "
+                               "once.\n"
+                             );
+                       printf( "\t-p [0-100]\tonly checks this percentage of "
+                               "the zone.\n\t\t\tDefaults to 100\n"
+                             );
+                       printf( "\t-S\t\tchase signature(s) to a known key. "
+                               "The network may be\n\t\t\taccessed to "
+                               "validate the zone's DNSKEYs. (implies -k)\n"
+                             );
+                       printf( "\t-t YYYYMMDDhhmmss | [+|-]offset\n\t\t\t"
+                               "set the validation time either by an "
+                               "absolute time\n\t\t\tvalue or as an "
+                               "offset in seconds from <now>.\n\t\t\t"
+                               "For data that came from the network (while "
+                               "chasing),\n\t\t\tsystem time will be used "
+                               "for validating it regardless.\n"
+                             );
+                       printf( "\t-v\t\tshows the version and exits\n");
+                       printf( "\t-V [0-5]\tset verbosity level (default 3)\n"
+                             );
+                       printf( "\n<period>s are given "
+                               "in ISO 8601 duration format: "
+                               "P[n]Y[n]M[n]DT[n]H[n]M[n]S\n"
+                             );
+                       printf( "\nif no file is given "
+                               "standard input is read\n"
+                             );
                        exit(EXIT_SUCCESS);
                        break;
-               case 'v':
-                       printf("verify-zone version %s (ldns version %s)\n",
-                                 LDNS_VERSION, ldns_version());
-                       exit(EXIT_SUCCESS);
+               case 'e':
+               case 'i':
+                       duration = ldns_duration_create_from_string(optarg);
+                       if (!duration) {
+                               fprintf( myerr
+                                      , "<period> should be in ISO 8601 "
+                                        "duration format: "
+                                        "P[n]Y[n]M[n]DT[n]H[n]M[n]S\n"
+                                      );
+                                exit(EXIT_FAILURE);
+                       }
+                       if (c == 'e')
+                               expiration_offset 
+                                       = ldns_duration2time(duration);
+                       else
+                               inception_offset 
+                                       = ldns_duration2time(duration);
                        break;
-               case 'V':
-                       verbosity = atoi(optarg);
+               case 'k':
+                       s = read_key_file(optarg, keys);
+                       if (s != LDNS_STATUS_OK) {
+                               fprintf( myerr
+                                      , "Could not parse key file %s: %s\n"
+                                      , optarg
+                                      , get_errorstr_by_id(s)
+                                      );
+                                exit(EXIT_FAILURE);
+                       }
                        break;
                 case 'p':
                         percentage = atoi(optarg);
                         if (percentage < 0 || percentage > 100) {
-                               fprintf(stderr, "percentage needs to fall "
-                                               "between 0..100\n");
+                               fprintf( myerr
+                                      , "percentage needs to fall "
+                                        "between 0..100\n"
+                                      );
                                 exit(EXIT_FAILURE);
                         }
                         srandom(time(NULL) ^ getpid());
                         break;
+               case 'S':
+                       do_sigchase = true;
+                       /* may chase */
+                       break;
                case 't':
-                       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) == 6) {
+                       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 ) == 6) {
                                tm.tm_year -= 1900;
                                tm.tm_mon--;
                                check_time = mktime_from_utc(&tm);
@@ -705,8 +1057,23 @@ main(int argc, char **argv)
                        else  {
                                check_time += atoi(optarg);
                        }
+                       break;
+               case 'v':
+                       printf( "verify-zone version %s (ldns version %s)\n"
+                             , LDNS_VERSION
+                             , ldns_version()
+                             );
+                       exit(EXIT_SUCCESS);
+                       break;
+               case 'V':
+                       verbosity = atoi(optarg);
+                       break;
                }
        }
+       if (do_sigchase && ldns_rr_list_rr_count(keys) == 0) {
+               fprintf(myerr, "Unable to chase signature without keys.\n");
+               exit(EXIT_SUCCESS);
+       }
 
        argc -= optind;
        argv += optind;
@@ -718,66 +1085,87 @@ main(int argc, char **argv)
 
                fp = fopen(filename, "r");
                if (!fp) {
-                       fprintf(stderr,
-                                  "Unable to open %s: %s\n",
-                                  filename,
-                                  strerror(errno));
+                       fprintf( myerr
+                              , "Unable to open %s: %s\n"
+                              , filename
+                              , strerror(errno)
+                              );
                        exit(EXIT_FAILURE);
                }
        }
 
-       s = ldns_zone_new_frm_fp_l(&z, fp, NULL, 0, LDNS_RR_CLASS_IN, &line_nr);
+       s = dnssec_zone_new_frm_fp_l( &dnssec_zone
+                                   , fp
+                                   , NULL
+                                   , 0
+                                   , LDNS_RR_CLASS_IN
+                                   , &line_nr
+                                   );
        if (s == LDNS_STATUS_OK) {
-               if (!ldns_zone_soa(z)) {
-                       fprintf(stderr, "; Error: no SOA in the zone\n");
+               if (! dnssec_zone->soa) {
+                       fprintf(myerr, "; Error: no SOA in the zone\n");
                        exit(1);
                }
 
-               dnssec_zone = create_dnssec_zone(z);
                result = ldns_dnssec_zone_mark_glue(dnssec_zone);
                if (result != LDNS_STATUS_OK) {
                        if (verbosity >= 1) {
-                               printf("There were errors identifying the glue "
-                                               "in the zone\n");
+                               fprintf( myerr
+                                      , "There were errors identifying the "
+                                        "glue in the zone\n"
+                                      );
                        }
                }
 
                if (verbosity >= 5) {
-                       ldns_dnssec_zone_print(stdout, dnssec_zone);
+                       ldns_dnssec_zone_print(myout, dnssec_zone);
                }
 
-               result = verify_dnssec_zone(dnssec_zone, 
-                               ldns_rr_owner(ldns_zone_soa(z)),
-                               apexonly, percentage, check_time);
+               result = verify_dnssec_zone( dnssec_zone
+                                          , dnssec_zone->soa->name
+                                          , keys
+                                          , apexonly
+                                          , percentage
+                                          );
 
                if (result == LDNS_STATUS_OK) {
-                       if (verbosity >= 1) {
-                               printf("Zone is verified and complete\n");
+                       if (verbosity >= 3) {
+                               fprintf( myout
+                                      , "Zone is verified and complete\n"
+                                      );
                        }
                } else {
                        if (verbosity >= 1) {
-                               printf("There were errors in the zone\n");
+                               fprintf( myerr
+                                      , "There were errors in the zone\n"
+                                      );
                        }
                }
 
-               ldns_zone_free(z);
                ldns_dnssec_zone_deep_free(dnssec_zone);
        } else {
-               fprintf(stderr, "%s at %d\n",
-                               ldns_get_errorstr_by_id(s),
-                               line_nr);
+               fprintf( myerr
+                      , "%s at %d\n"
+                      , get_errorstr_by_id(s)
+                      , line_nr
+                      );
                 exit(EXIT_FAILURE);
        }
        fclose(fp);
 
        exit(result);
 }
+
 #else
+
 int
 main(int argc, char **argv)
 {
-       fprintf(stderr, "ldns-verify-zone needs OpenSSL support, "
-                       "which has not been compiled in\n");
+       fprintf( stderr
+              , "ldns-verify-zone needs OpenSSL support, "
+                "which has not been compiled in\n"
+              );
        return 1;
 }
 #endif /* HAVE_SSL */
+